In the Illustrator Preferences or current document settings (Document Setup → Units) you set the ruler units. Document units do not affect global preferences, but changing global units will change document settings. In the DOM, the activeDocument.rulerUnits
property returns the current units from the list: RulerUnits.Pixels
, RulerUnits.Millimeters
, and so on. But more interesting is RulerUnits.Unknown
— the document exists, but the units in it don’t exist?
The CC 2020 release showed that this is easily possible for Adobe developers. They added feet, yards, and meters to Illustrator, but forgot about the API, and for a long time. Even in the latest betas of CC 2022, scripts in documents with new units get RulerUnits.Unknown
. This prevents you from converting units from one to the other because the sizes of objects and artboards in the scripts are stored in pixels.
Luckily, Illustrator still needs somewhere to store information about document units, and it writes it in XMP metadata: activeDocument.XMPString
. In the Adobe’s book “XMP Specification” , where it mentions a property of type Dimensions that contains three fields:
- stDim:w —width,
- stDim:h — height,
- stDim:unit — ruler units.
An example of a piece of metadata with the field we need:
<xmpTPg:NPages>1</xmpTPg:NPages>
<xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>
<xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
<xmpTPg:MaxPageSize rdf:parseType="Resource">
<stDim:w>1366.000000</stDim:w>
<stDim:h>768.000000</stDim:h>
<stDim:unit>Pixels</stDim:unit>
</xmpTPg:MaxPageSize>
Let’s face the pain right away — the problem is that the metadata is written only when the file is saved. This means that when changing units in a document, the user must save the file before running the script. There are no such problems with older units, because the scripts get them on the fly.
Our algorithm will look like this:
- check that the rulers are undefined,
- get data from
activeDocument.XMPString
, - find the field stDim:unit,
- retrieve the name of the units, e.g. by searching for matches of the
exec()
string.
var doc = activeDocument;
if (doc.rulerUnits == RulerUnits.Unknown) {
var xmp = doc.XMPString;
var units = '';
if (/stDim:unit/i.test(xmp)) {
units = /<stDim:unit>(.*?)<\/stDim:unit>/g.exec(xmp)[1];
}
alert('Current units: ' + units);
}
The example applies to new units only, and you can see the full code for the ruler check and conversion function in the ArtboardsFinder script.
Upd: CC 2023 v27.1.1 was released in December 2022 and added new unit keys for RulerUnits. But for previous versions, checking the contents of XMP with RulerUnits.Unknown is still relevant.