Acrobat User Community

Creating and using layers (OCGs) with Acrobat JavaScript

By Thom ParkerJuly 7, 2006

Skill Level: Intermediate to Advanced

Acrobat 7 and Later

In Acrobat, the term “Layers” refers to Optional Content Groups (OCGs). OCGs are a mechanism for selectively controlling the visibility of page content. In Acrobat 7 (Professional and Standard) it is possible to both create and control these content layers through Acrobat JavaScript, giving the document developer a totally new ability to use dynamic content purely through scripting tools already available in Acrobat Professional. This is not another kind of form field or annotation, but true page content. OCGs are used to create multilayer pages (like a stack of transparencies), for everything from multi-language documents, layered views for architectural plans, to animated displays.

Understanding OCGs

To the user, an OCG appears as a physical layer of content on a PDF page. Figure 1 shows the Layers Panel (Menu: View>Navigation Tabs>Layers). Each entry in this panel represents an OCG in the document. Clicking the mouse on one of the Show/Hide buttons toggles the visibility of the page content associated with that layer. In this figure 3 OCGs are displayed. The first one (MyLayer) is hidden and the other two are visible as indicated by their Show/Hide buttons.

Figure 1 – OCG Layers Panel and Menu Options
See larger image

It’s easy to get the impression that the drawn page content and the OCG layer are the same thing, or that the page contents associated with the OCG are on some kind of physical layer, but this is not true. OCGs are not visible objects on the document or even real layers. They are a logical construction inside the PDF file that has either a true or false state. Any drawn object can be attached to an OCG. If the state of the OCG is true the object is drawn, and if the state is false the object is not drawn, so the Show/Hide buttons in the Layers panel really control the state of the OCG. This is very different from the concept of layers in other programs like Adobe Photoshop®. However, OCG layers are added when some file formats are converted to PDF. Adobe InDesign®, Microsoft PowerPoint®, and Autodesk AutoCAD® files can all be converted to a layered PDF when appropriately set up. Unfortunately, there isn’t yet a tool in Acrobat that can arbitrarily attach OCGs to drawn objects on the page. OCGs are only available through third party tools, file conversions, and a couple operations built into Acrobat Professional. It’s these Acrobat operations we’ll be using in this article since they give us a way to create OCGs without relying on external tools. They are the Watermark and Backgrounds and Headers and Footers menu items. However, layers created in other ways can be manipulated with the same techniques discussed here.

OCGs in JavaScript

OCGs were first added to the PDF specification in Acrobat 6. At the same time some basic JavaScript control over the OCGs was also added; i.e., the ability to list the existing OCGs and change OCG state. It was in Acrobat 7 that OCGs became really useful from JavaScript. The two most important features added were the ability to create an OCG layer with the Watermark functions, and the ability to rename an OCG.

Creating

Let’s get right into creating an OCG. For the following example you’ll need Acrobat Professional 7.0. First open up a PDF document. We’ll use this document as a scratch pad for trying out the OCG operations so make sure it’s a document you don’t mind altering, and has only a few pages. Next, bring up the JavaScript Console. If you’re unfamiliar with the JavaScript Console, read this tutorial.

Now we’re ready to begin. Enter and run the following line of code in the JavaScript Console.

this.addWatermarkFromText("Draft Copy");

This single line script will add the words “Draft Copy” to the center of all the document pages. This function has a large number of options for placing the text, controlling color, font, text size, and other parameters. There is also a related function, doc.addWatermarkFromFile(), that uses a PDF file to create the watermark. These functions also create an OCG layer to which the watermark is attached. Adding a Watermark, Background, Header, or Footer to the document from the Acrobat menus will also create an OCG.

Locating the OCG Objects

Now activate the Layers Panel in Acrobat (Menu item: View>Navigation Tabs>Layers). The first thing to notice is that the panel is empty. No OCGs are listed. The layer we just created with the watermark function is hidden from the user, but it isn’t hidden from JavaScript. Run the following code in the Console.

this.getOCGs(); 

The doc.getOCGs() function returns an array of OCG Objects. The result of this operation (Figure 2) shows the document contains only a single OCG named Watermark, which is from the previous doc.addWatermarkFromText() operation. The watermark functions always give the newly created OCG the name Watermark. If you use the watermark function a second time, a new watermark is added to the document, but a new OCG is not created. Instead, both watermarks are part of the same OCG.


Figure 2 – Using JavaScript to find OCGs

See larger image

The following function is used to find an OCG with a specific name. It will be referenced in some of the following examples so please run it in the JavaScript Console now, and/or when you use that example.

function FindOCG(cName) { 
    var aOCGs = this.getOCGs(); 
    for(var i=0; aOCGs && i<aOCGs.length;i++) { 
        if(aOCGs[i].name == cName) return aOCGs[i]; 
    } 
    return null; 
}

The OCG Object

The OCG Object provides a limited set of functions and properties for manipulating the layer.

OCG Object Members: (R/W – Read/Write)

Properties:

R/W

Description

initState -

R/W

Sets and gets the OCG state when the PDF is opened

locked -

R/W

Block changes to the OCG from the User Interface, can only be changed from JavaScript

name -

R/W

Identifying Name of the OCG

state -

R/W

On/Off (Visible/Hidden) value of the OCG

Functions:

Description

getIntent() -

Gets the viewing intent of the OCG, two values:
View (default) – Interactive use, OCG can be turned on and off
Design – Always visible, no changes to OCG allowed

setIntent() -

Sets the viewing intent of the OCG

setAction() -

Sets a JavaScript action to be evaluated each time the state of the layer changes

The state property is used at runtime to toggle the visibility of the OCG. All the other properties make changes to the PDF. They are more useful at document design time for automating the creation of an OCG. If used at runtime, the document would have to be saved for the changes to stick. This is a big problem when the PDF is viewed in Reader.

As an example of Design Time usage we’ll make a multi-layer PDF. The basic sequence is to alternately create an OCG with one of the watermark functions and then rename it using the name property. The following code adds three OCGs to a document. Each text watermark is offset by a quarter inch from the next. Copy and paste this code into the Console, then run it.

This code uses the FindOCG() function defined earlier in this article. Make sure to run the FindOCG() code first, so that the following code will work.

// First rename any previous layers named Watermark 
var ocg = null; 
while( (ocg = FindOCG("Watermark")) != null) ocg.name = "PreviousWatermark"; 

// Add three OCG layers to current PDF 
this.addWatermarkFromText({cText:"One",aColor:color.red,nVertValue:18}); 
FindOCG("Watermark").name = "LayerOne"; 
this.addWatermarkFromText({cText:"Two",aColor:color.blue,nVertValue:36}); 
FindOCG("Watermark").name = "LayerTwo"; 
this.addWatermarkFromText({cText:"Three",aColor:color.green,nVertValue:54}); 
FindOCG("Watermark").name = "LayerThree";

The words “One”, “Two”, and “Three” should now appear slightly above the middle of the page in the colors red, blue, and green.

Displaying the OCG on the Layers Tab

To allow the user to manipulate these OCGs, or to allow us to make changes in the OCGs that can’t be done from JavaScript, the OCGs must be visible in the Layers Panel (Figure 1). Inside the PDF, the OCGs that appear on this panel are referred to as the Order Array. From Acrobat JavaScript the doc.setOCGOrder() function is used to place OCGs into the Order Array. The following code makes all the OCGs in the PDF visible on the Layers Panel.

this.setOCGOrder(this.getOCGs());

All the OCGs should now be displayed on the Layers Panel.

What’s Missing:

Not all OCG properties can be set with JavaScript, and there are a couple important ones that currently can only be set from the OCG Properties Dialog. To display this dialog (Figure 3), right click on the OCG in the Layers Panel and select “Properties”.


Figure 3 – Optimizing the OCG Properties for working with JavaScript
See larger image

Both the Visibility and Print parameters are defaulted to Always. This doesn’t block JavaScript from changing the state of an OCG, but Acrobat re-evaluates the state of an OCG every time the layered content is redrawn. This happens when the document page is scrolled, zoomed, printed, or when any changes to the window are made. If the visibility is set to Always or Never, then these states will override the JavaScript setting. Change them to the settings shown in Figure 3 for all three layers.

Animating the Watermarks with a Timer

Now that we have 3 properly setup OCGs lets do a simple animation (see the example document below). To control this animation we’ll use an Acrobat Timer created with the app.setInterval() function. The interval function will use a counter to alternately turn the layers on and off. Start by placing the FindOCG() script, shown previously, in a Document Level script. We’ll use this function for locating the OCGs by name. Then place a button on the document and add the following code to the Mouse Down action.

OCGAnimation
Example document
Download [PDF, 18KB]

This code uses the FindOCG() function defined earlier in this article. Make sure to run the FindOCG() code first, so that the following code will work.

// When the PDF is first opened the "inc" variable does not exist 
// so we use it to signal initialization. This could be moved to 
// a document script. 
if(this.inc == null){ 
    // Initialize layer states FindOCG("LayerOne").state = false; 
    FindOCG("LayerTwo").state = false; 
    FindOCG("LayerThree").state = false; 

    // Initialize Counter Variable 
    this.inc = -1; 
} 

// Array of layer Names, could be moved to a document script 
var aLayers = ["LayerOne","LayerTwo","LayerThree"]; 

// Timer Interval function, Could be moved to a document script 
function ToggleOCGs() { 
    if(inc >= 0){ 
        // Toggle the state of the previous OCG 
        var ocg = FindOCG(aLayers[this.inc]); 
        ocg.state = !ocg.state; 
    } 

// Increment the counter, reset if necessary 
this.inc++; 
if(this.inc > 2) this.inc = 0; 

// Toggle the state of the next OCG 
var ocg = FindOCG(aLayers[this.inc]); 
ocg.state = !ocg.state; } 

//*** Main Button Code *** 
// Toggle Animation timer on and off based on the existence 
// of the iTimer variable 
if(this.iTimer){ 
    // Timer exists so turn it off 
    try{
        app.clearInterval(this.iTimer);
    }finally{
        this.iTimer = null;
    } 
    event.target.buttonSetCaption("Start Animation"); 
}else{ 
    // Timer does not exist so start it up 
    this.iTimer = app.setInterval("ToggleOCGs();",500); 
    event.target.buttonSetCaption("STOP Animation"); 
}

The first part of this script initializes all the OCGs to hidden. The second part defines an array of OCG names (to be used in the toggle function) and the function that will be used to toggle the OCG layers on and off. All of this code is initialization and can be moved to a document script. The last piece of code, the main button code, turns the timer on and off based on its current state, and sets the button’s label to reflect this.

The ToggleOCGs() function is called each time the timing interval is reached, 500 milliseconds. Its basic operation is to toggle the state of the current OCG, indicated by the counter value, then increment the counter and toggle the state of the next OCG. If everything is set up properly this has the effect of hiding the currently visible layer and making the next layer visible. The one exception to this sequence is the first time the function is called. In that case, all the OCGs are turned off, so we have to skip the lines of code that toggle the state of the previous OCG.

Other Uses

Any parameter in Acrobat or a PDF document accessible with JavaScript can be used to control the visibility of an OCG layer: the viewer’s language, the zoom factor, the document’s URL, the page number, a value in a form field, a button’s mouse down event, etc. This allows us a great deal of latitude in building PDF documents with content controllable through JavaScript.

Summary:

In Acrobat 7, Optional Content Groups (OCGs) can be created and manipulated with JavaScript. Functions provided in the Document Object and the OCG Object allows for the creation of multiple layer documents, where each layer controls the visibility of content on the PDF page. These OCG layers can be controlled at runtime to create document effects like animations and multi-language documents.