Adobe Illustrator has a surprisingly robust and flexible scripting API. Objects of all types are cleanly delineated and the feature set goes pretty deep. The hardest part, I found, was getting used to the different record types used between colors and object frames vs. geometric bounds. Some consistency or clearer (read as: any) documentation in the Dictionary would help, I don't care which, but these aren't atypical issues for Adobe products.

Artboards (CS4)


I could be wrong, but artboards look to be a new feature in Illustrator. In some recent work I ran afoul of them, and I’m still trying to figure what is the point of this “feature”. The dimension information for them look to be {x || y, height, width, x || y}, but the Dictionary is not clear on which are exactly x and y. The following snippet really just shows how to access and change them quickly and cleanly.

Set all artboards to visible bounds of content within the document (CS4)




on FixArtboard(TheDocument)
tell application "Adobe Illustrator"
tell TheDocument
set visibleBounds to visible bounds
set theArtboards to artboards
set lastArtboard to count theArtboards
repeat with thisArtboard from 1 to lastArtboard
set theArtboard to item thisArtboard of theArtboards
set artboard rectangle of theArtboard to visibleBounds
end repeat
end tell
end tell
end FixArtboard


Set all artboards to a specific size (CS4)



This may seem obvious, but I find it sometimes helps to see things in context rather than a detached block of code.\


on FixArtboard(theDocument)
tell application "Adobe Illustrator"
tell theDocument
-- artboards > artboard 1 > artboard rectangle : {x||y, height, width, x||y} the docs aren't clear on what's what here
set theArtboards to artboards
set lastArtboard to count theArtboards
repeat with thisArtboard from 1 to lastArtboard
set theArtboard to item thisArtboard of theArtboards
set artboard rectangle of theArtboard to {600.0, 288.0, 432.0, 960.0}
end repeat
end tell
end tell
end FixArtboard


Convert CMYK Spot Color to plain CMYK Color (CS4)



The thing to note about this is that applying a color to a path item is as simple as applying a record, and while the color values are floats, the class has to be declared in the new record and is an enumerated value. In other words, colors are merely records and not custom objects in Illustrator.


on ConvertCMYKSpotColorToPlainCMYKInPathItem(thePathItem) -- (path item) as void
tell application "Adobe Illustrator"

set theFillColor to fill color of thePathItem
set theFillColorClass to class of theFillColor as string

if theFillColorClass = "spot color info" then

set theSpotColor to spot of theFillColor
set theColor to color of theSpotColor

set theColorClass to class of theColor as string

if theColorClass = "CMYK color info" then

set vBlack to black of theColor
set vCyan to cyan of theColor
set vMagenta to magenta of theColor
set vYellow to yellow of theColor

set fill color of thePathItem to {black:vBlack, cyan:vCyan, magenta:vMagenta, yellow:vYellow, class:CMYK color info}

end if
end if
end tell
end ConvertCMYKSpotColorToPlainCMYKInPathItem


Matching Colors (CS4)



This subroutine was written in response to an error found in a book where a bunch of art contained text that was a 4-color mix when all it should ever be is 100% black.

But finding a color and checking it's values isn't as obvious as one might think. In Illustrator, if you look at a color and see these values in the GUI's palette...
  • C:66.8%
  • M:57.8%
  • Y:66.4%
  • K:50.3%
...they are actually...
  • C:66.800004243851%
  • M:57.809996604919%
  • Y:66.409999132156%
  • K:50.38999915123%
...in the scripting API. When looking for a color it is crucial to get the exact values before starting the comparison.

To complicate matters further, I wasn't able to do a direct comparison of the values (color = value), I had to use a scorecard method by comparing a given value against a (very) narrow range as shown below.


on IsColorRichBlack(theFillColor) -- (fill color as record) as boolean
tell application "Adobe Illustrator"
set vCyan to cyan of theFillColor
set vMagenta to magenta of theFillColor
set vYellow to yellow of theFillColor
set vBlack to black of theFillColor

set theColorMatchScore to 0

if (vCyan ? 66.8) and (vCyan ? 66.9) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vMagenta ? 57.8) and (vMagenta ? 57.9) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vYellow ? 66.4) and (vYellow ? 66.5) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vBlack ? 50.3) and (vBlack ? 50.4) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if theColorMatchScore = 4 then
return true
end if
return false
end tell
end IsColorRichBlack


Is Stroke Color Black In Page Item (CS4)



This is a variation on IsColorRichBlack, but instead of looking at the fill for a specific black this looks into just the stroke for any variation of black. This was created to help resolve a problem with overprinting because most objects need overprinting off whereas black text (in labels) and strokes (in leader lines) need to have overprinting on.


on IsStrokeColorBlackInPageItem(thePageItem) -- (fill color as record) as boolean

tell application "Adobe Illustrator"

try
set theStrokeColor to stroke color of thePageItem
on error
return true -- don't touch anything, just in case
end try

set vCyan to cyan of theStrokeColor
set vMagenta to magenta of theStrokeColor
set vYellow to yellow of theStrokeColor
set vBlack to black of theStrokeColor

if (vBlack = 100.0) then
return true
end if

set theColorMatchScore to 0

if (vCyan ≥ 66.8) and (vCyan ≤ 66.9) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vMagenta ≥ 57.8) and (vMagenta ≤ 57.9) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vYellow ≥ 66.4) and (vYellow ≤ 66.5) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if (vBlack ≥ 50.3) and (vBlack ≤ 50.4) then
set theColorMatchScore to theColorMatchScore + 1
else
set theColorMatchScore to theColorMatchScore - 1
end if

if theColorMatchScore = 4 then
return true
end if

return false

end tell
end IsStrokeColorBlackInPageItem


Disable Overprints In PageItem (CS4)



This is used in conjunction with IsStrokeColorBlackInPageItem(PageItem) to handle overprinting issues. In almost every case, overprinting should be applied to black paths and text.


on DisableOverprintsInPageItem(PageItem)
tell application "Adobe Illustrator"
try
set fill overprint of PageItem to false

set strokeColorIsBlack to IsStrokeColorBlackInPageItem(PageItem) of me
if strokeColorIsBlack is false then
set stroke overprint of PageItem to false
end if

on error the error_message number the error_number
-- do something with the error because some objects can’t accept the command, typically nothing just to be sure nothing wonky happens in the layout.
end try
end tell
end DisableOverprintsInPageItem


Get all page items within a document (CS4)



I think most of the time, getting the page items at the document level is enough for most jobs, but sometimes every object needs to be touched for one reason or another. This takes a page item, gets all of the child page items, and even goes into found group items. I'm not sure why, but simply passing a document object to this won't work.


property pAtomicPageItems : {}

tell application "Adobe Illustrator"
open theEpsFile without dialogs

set TheDocument to document 1

set pageItemCount to (count page items in TheDocument)

if pageItemCount > 0 then
set firstPageItem to 1
set thisPageItem to firstPageItem
repeat with thisPageItem from 1 to pageItemCount
set thePageItem to page item thisPageItem of TheDocument
set end of pAtomicPageItems to thePageItem
my GetPageItemsInPageItem(thePageItem)
end repeat
end if

set groupItemCount to (count group items) in TheDocument

if groupItemCount > 0 then
set firstGroupItem to 1
set thisGroupItem to firstGroupItem
repeat with thisGroupItem from firstGroupItem to groupItemCount
try
set theGroupItem to item thisGroupItem of group items of TheDocument
my GetPageItemsInPageItem(theGroupItem)
end try
end repeat
end if

(* do something with the collected page items *)

end tell

on GetPageItemsInPageItem(ParentPageItem) -- (page item) as list
tell application "Adobe Illustrator"
try
set pageItemCount to (count page items in ParentPageItem)

if pageItemCount > 0 then
set firstPageItem to 1
set thisPageItem to firstPageItem
repeat with thisPageItem from 1 to pageItemCount
set thePageItem to page item thisPageItem of ParentPageItem
set end of pAtomicPageItems to thePageItem
my GetPageItemsInPageItem(thePageItem)
end repeat
end if

set groupItemCount to (count group items) in ParentPageItem

if groupItemCount > 0 then
set firstGroupItem to 1
set thisGroupItem to firstGroupItem
repeat with thisGroupItem from firstGroupItem to groupItemCount
set theGroupItem to item thisGroupItem of group items of ParentPageItem
my GetPageItemsInPageItem(theGroupItem)
end repeat
end if

end try

end tell
end GetPageItemsInPageItem


Parse Path Item (CS4)



This is a general purpose subroutine that shows examples of the various things that can be checked on path item in Illustrator. A lot of what is above started out here in one form or another.


on ParsePathItem(thePathItem) -- (page item) as void
tell application "Adobe Illustrator"

set theStrokeWidth to width of thePathItem

-- set the width to the minimum for all strokes regardless of color.
if theStrokeWidth > 0.0 and theStrokeWidth < 0.25 then
try
set width of thePathItem to 0.25
on error the error_message number the error_number
log "ERROR: set width of thePathItem to 0.25: " & error_number & ", " & error_message
end try
end if

set theStrokeColor to stroke color of thePathItem
set kCurrentStrokeColor to theStrokeColor

set theStrokeColorClass to class of theStrokeColor as string

if theStrokeColorClass contains "no color info" then
-- do nothing
else

if theStrokeColorClass contains "CMYK" then -- not finding this

(* Analyze the color to see what needs to happen next *)

set cVal to cyan of theStrokeColor
set mVal to magenta of theStrokeColor
set yVal to yellow of theStrokeColor
set kVal to black of theStrokeColor

set inkCoverage to cVal + mVal + yVal + kVal

if cVal = 0.0 and mVal = 0.0 and yVal = 0.0 and kVal = 100.0 then
-- do nothing

else if inkCoverage ≥ 350.0 then -- the color is 4-color black
my SetPathItemStrokeColorToK100(thePathItem)

else -- the color is not black, but it is 4-color and the stroke needs to be bigger.

if theStrokeWidth ≥ 0.25 and theStrokeWidth < 0.5 then
try
set width of thePathItem to 0.5
on error the error_message number the error_number
log "ERROR:set width of thePathItem to 0.5: " & error_number & ", " & error_message
end try
end if -- theStrokeWidth
end if -- color check
else if theStrokeColorClass contains "spot" then

(* If the name contains "Black", then change the color C0 M0 Y0 K100 *)

set theSpotColor to spot of theStrokeColor
set theSpotColorName to name of theSpotColor

if theSpotColorName contains "black" then
my SetPathItemStrokeColorToK100(thePathItem)
end if
end if

end if -- theStrokeColor is"no color info" then

end tell -- application
end ParsePathItem