Using Colors in Acrobat JavaScript

Crash course in manipulating color in PDF files

One of the nice things about Acrobat’s JavaScript implementation is that
you can use JavaScript to change the fillColor, strokeColor, and textColor
properties of the Field object at runtime. In plain English, that means you
can alter the color of text-field backgrounds and borders (and the text
itself) programmatically so that, for example, the text in a text field
could change color in response to a mouse-over event. Or, the text on a
certain part of the page could be in black up to a certain cutoff date,
then appear red after that date. Or, you could give the user a popup list
of color preferences (see code example further below).

Without further ado, let’s go through a crash course in Acrobat JavaScript
color conventions, so that you’ll know how to manipulate colors when you
need to do so.

Colors Are Arrays

Rule No. 1 is: in Acrobat, colors are arrays. By convention, the first item
in the array is the color space (designated by a string): ‘T’ for
transparent, ‘G’ for grayscale, ‘RGB’ for red-green-blue, or ‘CMYK’ for
cyan-magenta-yellow-black. Subsequent positions in the array designate
color-channel values (which can range from zero to one). For ‘T’, there are
no subsequent positions. For ‘G’, there is one channel value (indicating
the amount of white, incidentally; not black). For ‘RGB’ there are three
extra array slots, and for ‘CMYK’ there are (obviously) four channel values.

Creating a new color on the fly is as easy as:


var myDarkRed = ['RGB',0.5,0,0]; // dark red

var darkRed = new Array('RGB',0.5,0,0); // equivalent

In either case, you’ve created an array that meets the definition of a
color. To access the green channel of the darkRed color, you’d inspect or
set darkRed[2]. The blue channel would be darkRed[3]. To check whether
you’re dealing with an ‘RGB’ color, you’d inspect darkRed[0].

Convenience Colors

For convenience, Adobe’s engineers have predefined some colors that you can
use wherever a quick color choice is needed. The colors are defined in the
AForm.js file as follows:


color.transparent = new Array('T');
color.black = new Array('G', 0);
color.white = new Array('G', 1);
color.dkGray = new Array('G', 0.25);
color.gray = new Array('G', 0.5);
color.ltGray = new Array('G', 0.75);
color.red = new Array('RGB', 1, 0, 0);
color.green = new Array('RGB', 0, 1, 0);
color.blue = new Array('RGB', 0, 0, 1);
color.cyan = new Array('CMYK', 1, 0, 0, 0);
color.magenta = new Array('CMYK', 0, 1, 0, 0);
color.yellow = new Array('CMYK', 0, 0, 1, 0);


To specify a dark gray (75% gray) background color for a text field named
‘CustomerName’, you’d do:


this.getField('CustomerName').fillColor = color.dkGray;

Notice that white is defined as the array [‘G’,1]. It could just as easily
be defined as [‘RGB’,1,1,1]. But it’s not! If you write a custom function
that ‘averages’ colors (by numerically averaging the RGB channel values),
you’ll get in trouble when you try to average, say, color.red with
color.white. You’ll also get in trouble if you try to interpolate between
color.red and color.yellow. The colors (as defined above) are in different
color spaces. In Adobe’s world, color.white and color.yellow are not RGB
colors.

The lesson here is, always check the color-space value (the zeroth item of
the color array) first, to see which color space you’re operating in,
BEFORE trying to manipulate channel values. Otherwise, you’re asking for a
runtime error.

Color Comparison

If you have version 4.05 of Acrobat or Reader, you’ll find that the
AForm.js file (in your Plug-Ins:AcroForm:JavaScripts folder) contains
convenience methods for doing color comparisons and converting between
color spaces. You can use color.equal(c1,c2) to compare two colors, c1 and
c2, for equality:


var y1 = ['RGB',1,1,0]; // yellow in RGB

var y2 = ['CMYK',0,0,1,0]; // yellow in CMYK

var bool = color.equal(y1,y2); // bool is true!

The color comparison is done in a ‘smart’ way, by first converting both
colors to the same color space. Then the arrays are checked position by
position. The actual code for this is shown in AForm.js.

Color-Space Conversion

Also available in Acrobat 4.05 is a convenience method for converting
between color spaces. Say you have an RGB color that you’d like to know the
CMYK equivalent of.


var myRed = ['RGB',0.8,0,0];

var myRed2 = color.convert(myRed,'CMYK'); //

After the second line executes, myRed2 will equal [‘CMYK’,0.8,1,0.8,0]. You
can also set a text field’s background color to the new color to see how it
compares to the original. (As you probably know, colors don’t always stay
the same when converted from one space to another.)

A Popup Menu for Colors

Here’s a code example for advanced JavaScript users that shows how to set
the fill color for a text-field named ‘swatch’ on the fly, on the basis of
a user selection from a popup menu. To try it out, create a new text field
(using Acrobat’s Form tool) and name it ‘swatch’, then create a push button
(with whatever name you want) and attach the following code to the
mouse-DOWN event of the button:


var colors = new Array();

for (var i in color)
colors.push(i); // get a list of colors

while (colors[0] != 'transparent')
colors.shift(); // bump the non-colors

colors.unshift('Choose a Color:'); // label

var choice = app.popUpMenu(colors); // show menu

if (choice != null) // did user select something?
this.getField('swatch').fillColor = eval('color.' + choice);

Let’s walk through this code one statement (one semicolon) at a time.
First, we start by creating an empty array named ‘colors’. In the second
statement, we use JavaScript’s ‘for-in’ loop construct to enumerate all the
properties of Adobe’s color object (in AForm.js), pushing them into our
array. The first two members of the array, however, will be ‘equal’ and
‘convert’ (the convenience methods described above), which we don’t want.
Therefore we ‘shift’ those out of the array. In the zeroth position of the
array, we want the label ‘Choose a Color:’ for our popup menu, so we
unshift that string into place. Then we use the undocumented popUpMenu()
method of the App object to create a popup menu for the user to select a
color from.

Finally, we check to be sure the user actually CHOSE something (i.e., the
‘choice’ was non-null), then set the ‘swatch’ fill color to whatever the
user chose. If the user chose ‘blue’, we construct the string ‘color.blue’
and evaluate it. Remember Rule No. 1. Colors are not Strings. Colors are
Arrays. If we had left the eval() operation off the color choice, in the
last line of code, we would have been trying to set the fill color to a
String, which is a no-no.

One more caveat: Don’t try to use ‘color.transparent’ for a textColor or a
fgColor. (The latter property has been deprecated. It is replaced by
textColor.) Only background (fill) colors can be set to transparent.

You May Also Like

About the Author: Kas Thomas

Leave a Reply