{"id":5659,"date":"2018-05-29T17:56:14","date_gmt":"2018-05-30T00:56:14","guid":{"rendered":"https:\/\/www.rorohiko.com\/wordpress\/?page_id=5659"},"modified":"2018-05-31T22:48:54","modified_gmt":"2018-06-01T05:48:54","slug":"aintrospector-documentation","status":"publish","type":"page","link":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/","title":{"rendered":"AIntrospector Documentation"},"content":{"rendered":"<h1>AIntrospector 1.0.11 &#8211; 30 May 2018<\/h1>\n<p>This project has multiple goals.<\/p>\n<h2>Short Term<\/h2>\n<p>The short term goal is to provide ExtendScript access to Illustrator data that is currently inaccessible to ExtendScript scripts.<\/p>\n<p>There is a discrepancy between what can be accessed using the C++ API and what can be accessed from ExtendScript.<\/p>\n<p>This plug-in attempts to bridge that gap.<\/p>\n<p>The plug-in currently provides an additional DOM (Document Object Model), unrelated to the ExtendScript DOM.<\/p>\n<p>The AIntrospector DOM is more low-level than the ExtendScript DOM.<\/p>\n<p>This alternative DOM can be used from ExtendScript alongside the ExtendScript DOM and offers access to areas that are inaccessible to the ExtendScript DOM.<\/p>\n<p>At this time, the AIntrospector DOM is still very sparse: it is populated with new attributes and new features on an &#8216;as-needed&#8217; basis for some real-life projects. For example, the AIntrospector DOM gives you access to information about &#8216;type on a path&#8217; that is not available in the ExtendScript DOM (nor in the C++ API).<\/p>\n<p>The current focal areas, where the DOM is being extended, are determined by the needs of current customers who have a solid commitment to licensing AIntrospector.<\/p>\n<h2>Low-level DOM: optimizing for asynchronous use<\/h2>\n<p>The low-level AIntrospector DOM can be accessed from CEP\/JavaScript as well as from ExtendScript.<\/p>\n<p>When accessing the DOM from CEP\/JavaScript, there is no &#8216;intermediate&#8217; use of ExtendScript: JavaScript calls are handled by the plug-in without any use of ExtendScript. This allows the creation of CEP panels that are totally free of any ExtendScript.<\/p>\n<h3>PARM\/MRAP errors<\/h3>\n<p>The hope\/assumption is that this can put an end to PARM\/MRAP errors which seem to be caused by some &#8216;disconnect&#8217; between the ExtendScript engine and Illustrator.<\/p>\n<p>When PARM\/MRAP happens, Illustrator remains fully responsive and alive to the user, and at the same time, ExtendScript scripts can still be run, but somehow, ExtendScript seems to lose its grip on Illustrator, and anything you try causes a PARM\/MRAP error, which can only be cured by restarting Illustrator.<\/p>\n<h3>Async DOM<\/h3>\n<p>One of the underlying principles is to support asynchronous access. The idea is that there are two realms: one &#8216;inside&#8217; Illustrator, and one &#8216;outside&#8217; Illustrator.<\/p>\n<p>The AIntrospector API bridges these two realms.<\/p>\n<p>When calling from &#8216;outside&#8217; to &#8216;inside&#8217; there is a substantial cost in time and performance, especially when calling from JavaScript\/CEP: we&#8217;re switching between two very different contexts.<\/p>\n<p>The AIntrospector DOM is being designed to reduce the number of such context switches as much as possible.<\/p>\n<p>The &#8216;outside&#8217; code can prepare a request object, which is a bit like a shopping list or &#8216;to do&#8217; list.<\/p>\n<p>The request object can express complex queries into the Illustrator data structures, and the idea is to shoehorn as much as possible into a single request.<\/p>\n<p>The request is then fired off, the context switches, and the &#8216;inside&#8217; resolves and execute the request, without needing to call back to the outside during processing.<\/p>\n<p>If you have choice between formulating three small requests, or instead an equivalent single complex requests, you would choose the latter because you will only &#8216;pay&#8217; for one context switch between &#8216;outside&#8217; and &#8216;inside&#8217;.<\/p>\n<h2>Long Term<\/h2>\n<p>Once the low-level DOM nears completion, the mid term goal is to attempt to build a second, higher level DOM on top of the low-level AIntrospector DOM. This new DOM would be as close to the ExtendScript DOM as possible, and I would try and make the asynchronicity as invisible as possible, so existing ExtendScript scripts might be able to run in a JavaScript\/CEP environment (as opposed to the ExtendScript engine) against the new DOM.<\/p>\n<h2>GPU features<\/h2>\n<p>Another aspect of the plug-in is to provide &#8216;GPU-like&#8217; features. Some tasks are too massive to be handled in ExtendScript or JavaScript, but are feasible in C++. The plug-in will gradually provide functions to handle such requests. I&#8217;ve added one already as a proof of concept: simplifyPath.<\/p>\n<h2>Focus on CEP\/JavaScript<\/h2>\n<p>Gradually, the focus will shift from ExtendScript to providing more features to CEP\/JavaScript.<\/p>\n<h1>API<\/h1>\n<p>The API provided by the AIntrospectorUI extension works both in ExtendScript and in JavaScript.<\/p>\n<p>From JavaScript, all calls into AIntrospector are asynchronous.<\/p>\n<p>From ExtendScript, calls can be either synchronous or asynchronous.<\/p>\n<h2>To run stuff from ExtendScript-only setups<\/h2>\n<p>Make sure to start the script with something like<\/p>\n<pre><code>#include \"&lt;some path&gt;\/standalone.jsx\" \n<\/code><\/pre>\n<p>or equivalent.<\/p>\n<p>This loads and initializes the ExtendScript infrastructure.<\/p>\n<h2>XUID<\/h2>\n<p>In order to reference objects in Illustrator (page items, colors, documents, artboards&#8230;) the plug-in uses XUID (eXtended UID).<\/p>\n<p>For many object types, XUID are just plain GUID.<\/p>\n<p>But some objects in Illustrator do not have the internal data structures to retain their GUID. There is no way for Illustrator to &#8216;remember&#8217; what the GUID for those objects would be.<\/p>\n<p>In order to handle such objects (e.g. Artboards), the plug-in uses the GUID of the &#8216;owner&#8217; of the object, suffixed with a short string. Part of this string will be a four-letter code:<\/p>\n<pre><code>ArBd -&gt; Artboard\nArSt -&gt; Art Style\nLiEf -&gt; Live Effect\nLayr -&gt; Layer\n<\/code><\/pre>\n<h3>Artboards<\/h3>\n<p>For example, if a document has GUID 706c0a02-32fd-4fae-b745-778ba6995328, then its artboards will have the following XUID:<\/p>\n<pre><code>706c0a02-32fd-4fae-b745-778ba6995328ArBd0\n706c0a02-32fd-4fae-b745-778ba6995328ArBd1\n706c0a02-32fd-4fae-b745-778ba6995328ArBd2\n... and so on\n<\/code><\/pre>\n<p>For artboards, the owner (document) GUID is suffixed with a type code (ArBd = Artboard) and an index 0..n-1 where n = number of artboards.<\/p>\n<p>By nature, artboards do not have &#8216;stable&#8217; XUID: if the order of the artboards in a document changes, the XUID associated with any of the artboards will change.<\/p>\n<h3>Layers<\/h3>\n<p>Any group in an Illustrator document will have its own GUID.<\/p>\n<p>Illustrator layers are always associated with a special group (a layer group), and becaused of that, they don&#8217;t have their own GUID.<\/p>\n<p>Instead they have an XUID which is derived from the GUID of the underlying layer group.<\/p>\n<p>So, if we have a layer &#8216;ABC&#8217;, and the associated layer group has a GUID of<\/p>\n<pre><code>1715b7bb-0b79-486f-9cbd-c56846e73400\n<\/code><\/pre>\n<p>then the layer will have XUID<\/p>\n<pre><code>1715b7bb-0b79-486f-9cbd-c56846e73400Layr\n<\/code><\/pre>\n<h3>Live Effects<\/h3>\n<p>Live effects are owned by the application, not by a document.<\/p>\n<p>The Illustrator application has a fixed GUID 21862fc3-f16b-42b6-acb3-00165cedd121, and the live effects have an XUID based on their name derived from that.<\/p>\n<pre><code>21862fc3-f16b-42b6-acb3-00165cedd121LiEfLive Effect Name\n<\/code><\/pre>\n<h3>Art Styles<\/h3>\n<p>Art styles are owned by a document.<\/p>\n<p>Art styles have an XUID based on their name derived from the document GUID.<\/p>\n<pre><code>1715b7bb-0b79-486f-9cbd-c56846e73400ArStArt Style Name\n<\/code><\/pre>\n<h2>Synchronous vs Asynchronous<\/h2>\n<p>Asynchronous use of the API is compatible with both JavaScript and ExtendScript.<\/p>\n<h3>Asynchronous API call:<\/h3>\n<pre><code>AIn.sendAIntrospectorQuery(query, function(result) {...});\n<\/code><\/pre>\n<h3>Synchronous API call (ExtendScript only):<\/h3>\n<pre><code>result = AIn.sendAIntrospectorQuery(query);\n<\/code><\/pre>\n<h3>Synchronous call with &#8216;implicit reference&#8217; (ExtendScript only):<\/h3>\n<p>In ExtendScript you can omit the reference attribute from a query object and instead use<\/p>\n<pre><code>result = AIn.sendPageItemIntrospectorQuery(pageItem, query);\n<\/code><\/pre>\n<p>This allows you to reference objects directly, rather than via the reference mechanism.<\/p>\n<h2>Symbolic constants<\/h2>\n<p>A lot of Illustrator calls in the C++ API take enumeration constants.<\/p>\n<p>These are numerical (integer) constants that each represent a particular state or condition.<\/p>\n<p>For example, in the C++ API, you&#8217;ll find<\/p>\n<pre><code>    \/** Type constants for drawing modes. *\/\n    enum AIDrawingMode\n    {\n        kAIDrawNormalMode = 0,\n        kAIDrawBehindMode,\n        kAIDrawInsideMode\n    };\n<\/code><\/pre>\n<p>To keep things readable in C++ code, developers will rather use &#8216;kAIDrawNormalMode&#8217; instead of a &#8216;0&#8217;. These two things are equivalent as far as the C++ compiler is concerned, but writing kAIDrawNormalMode makes it much easier to understand the code for the human reader of the C++ code.<\/p>\n<p>The AIntrospector plug-in uses a similar mechanism, and will allow symbolic strings for nearly all parameters for API calls that need such integer values.<\/p>\n<p>Any call to AIntrospector that has a JSON construct with a drawing mode parameter will accept either an integer value, as well as a string value.<\/p>\n<p>You can either use<\/p>\n<pre><code>    {\n    ...\n      drawingMode: 1\n    ...\n    }\n<\/code><\/pre>\n<p>or<\/p>\n<pre><code>    {\n    ...\n      drawingMode: \"kAIDrawBehindMode\"\n    ...\n    }\n<\/code><\/pre>\n<p>and both will work the same.<\/p>\n<p>It will also return these symbolic strings rather than the &#8216;naked&#8217; integer values, so the returned data from a &#8216;getinfo&#8217; becomes is easier to understand.<\/p>\n<p>Example:<\/p>\n<pre><code>    {\n      \"uid\": \"460cec74-8915-477b-8baa-bc527d0cc094\",\n      \"name\": \"my group\",\n      \"type\": \"art\",\n      \"artType\": \"kTextFrameArt\",\n      \"artBounds:top\": \"-293.2734375\",\n      \"filePath\": \"\",\n      \"pathObject\": \"3c336f5b-ccf4-4d20-9f6a-389a3af3d30f\",\n      \"typeOnPath\": {\n        \"typeOnPathEffect\": \"kTypeOnPathRainbow\",\n        \"typeOnPathFlipped\": \"1\"\n      }\n    }\n<\/code><\/pre>\n<p>artType is returned as &#8216;kTextFrameArt&#8217;, which is equivalent with the integer constant &#8217;12&#8217;. Seeing &#8216;kTextFrameArt&#8217; is a lot easier to understand than seeing &#8217;12&#8217;.<\/p>\n<h2>Reference<\/h2>\n<p>To refer to an object in Illustrator you can use a reference object.<\/p>\n<p>There are four types of references: symbolic, uid, indexed and relative<\/p>\n<p>A single reference object can refer to multiple Illustrator objects (e.g. referring to the current selection)<\/p>\n<h3>Symbolic<\/h3>\n<p>To refer to the current document:<\/p>\n<pre><code>    {\n        type: \"symbolic\",\n        symbolType: \"curDoc\"\n    }\n<\/code><\/pre>\n<p>To refer to the current selection (which might refer to multiple elements):<\/p>\n<pre><code>    {\n        type: \"symbolic\",\n        symbolType: \"selected\"\n    }\n<\/code><\/pre>\n<p>To refer to the application object (this should always return the pre-determined GUID AIn.C.APPLICATION_UID = &#8220;21862fc3-f16b-42b6-acb3-00165cedd121&#8221;):<\/p>\n<pre><code>    {\n        type: \"symbolic\",\n        symbolType: \"application\"\n    }\n<\/code><\/pre>\n<h3>uid<\/h3>\n<p>To refer to an object by its XUID:<\/p>\n<pre><code>{\n    type: \"uid\",\n    uid: \"706c0a02-32fd-4fae-b745-778ba6995328\"\n}\n<\/code><\/pre>\n<h3>indexed<\/h3>\n<p>This is a recursive definition: you need a nested reference object to use the index with.<\/p>\n<p>To refer to an object &#8216;below&#8217; another object by its index:<\/p>\n<pre><code>    {\n        type: \"indexed\",\n        index: anIdx,\n        reference: {\n            ... a reference object for the parent object ...\n        }\n    }\n<\/code><\/pre>\n<h3>relative<\/h3>\n<p>This is a recursive definition. you need a nested reference object as the base for the relation.<\/p>\n<p>The available relations are:<\/p>\n<pre><code>ancestor\nchild\ndescendant\nnext\nparent\nprevious\n<\/code><\/pre>\n<p>ancestor = recursive parent descendant = recursive child<\/p>\n<p>The ancestor and descendant references track down via parent or child relations.<\/p>\n<p>To refer to an object relative to another object:<\/p>\n<pre><code>    {\n        type: \"relative\",\n        relation: \"parent\",\n        reference: {\n            ... a reference object for the child object ...\n        }\n    }\n\n\n    {\n        type: \"relative\",\n        relation: \"child\",\n        reference: {\n            ... a reference object for the parent object ...\n        }\n    }\n\n\n    {\n        type: \"relative\",\n        relation: \"next\",\n        reference: {\n            ... a reference object for the sibling object ...\n        }\n    }\n\n\n    {\n        type: \"relative\",\n        relation: \"previous\",\n        reference: {\n            ... a reference object for the sibling object ...\n        }\n    }\n\n\n    {\n        type: \"relative\",\n        relation: \"ancestor\",\n        includeRoots: true\/false, \/\/ optional, default = false\n        reference: {\n            ... a reference object for the descendant object ..\n        },\n        filter: ... a filter ...,\n        visitFilter: ... a filter ...\n    }\n\n\n    {\n        type: \"relative\",\n        relation: \"descendant\",\n        includeRoots: true\/false, \/\/ optional, default = false\n        reference: {\n            ... a reference object for the ancestor object ...\n        },\n        filter: ... a filter ...,\n        visitFilter: ... a filter ...\n    }\n<\/code><\/pre>\n<h4>filter<\/h4>\n<p>The filter determines which elements are to be selected by the reference<\/p>\n<h4>visitFilter<\/h4>\n<p>The visitFilter determines how to recurse up or down: if an element does not match the visitFilter the recursion will not descend or ascend into it.<\/p>\n<h4>includeRoots<\/h4>\n<p>If includeRoots is true, then the referenced object(s) themselves are also tested for matching against the filter and can be included in the result.<\/p>\n<p>By default only objects &#8216;one step removed&#8217; &#8211; i.e. children or parents &#8211; of the referenced object(s) are tested.<\/p>\n<h4>filter objects<\/h4>\n<p>A basic filter object will compares attribute values:<\/p>\n<pre><code>    {\n        attr1: value1,\n        attr2: value2...\n    }\n<\/code><\/pre>\n<p>This will filter all elements that have attr1 == value1 and attr2 == value2.<\/p>\n<p>Example:<\/p>\n<pre><code>   {\n      isArtClipping: \"1\"\n   }\n<\/code><\/pre>\n<p>will filter all elements that have isArtClipping = 1.<\/p>\n<p>To change the filter comparison operation from &#8216;equals&#8217; to something else (&lt;, &lt;=, >, >=), you need to nest the filter into a &#8216;cmp&#8217; object.<\/p>\n<pre><code>   {\n        cmp: \"&lt;\",\n        filter : {\n          ... a basic filter object ...\n        }\n    }\n<\/code><\/pre>\n<p>This causes the comparison to compare &#8216;attr &lt; value&#8217; instead of &#8216;attr == value&#8217;.<\/p>\n<p>Example:<\/p>\n<pre><code>   {\n        cmp: \"&lt;=\",\n        filter : {\n          artType: \"kCompoundPathArt\"\n        }\n    }\n<\/code><\/pre>\n<p>will filter all art elements that have an art type &lt;= kCompoundPathArt. kCompoundPathArt is a symbolic representation of the integer value 3.<\/p>\n<p>Filters can be inverted or combined.<\/p>\n<p>To invert a filter:<\/p>\n<pre><code>   {\n        invert: true\n        filter : {\n        ... a filter object ...\n        }\n    }\n<\/code><\/pre>\n<p>To combine two or more filters with &#8216;and&#8217;:<\/p>\n<pre><code>   {\n        and: \n        [\n             {\n               ... filter object 1 ...\n             },\n             {\n               ... filter object 2 ...\n             }\n             ...\n        ]\n    }\n<\/code><\/pre>\n<p>To combine two or more filters with &#8216;or&#8217;:<\/p>\n<pre><code>   {\n        or: \n        [\n             {\n               ... filter object 1 ...\n             },\n             {\n               ... filter object 2 ...\n             }\n             ...\n        ]\n    }\n<\/code><\/pre>\n<h3>Complex references<\/h3>\n<p>It is allowed to have multiple nested reference objects.<\/p>\n<p>For example, this works:<\/p>\n<pre><code>    {\n        opcode: \"getinfo\", \n        attr: [ \"uid\", \"name\" ],\n        reference: {\n            type: \"relative\", \n            relation: \"child\",\n            reference: {\n                type: \"relative\", \n                relation: \"child\",\n                reference: {\n                    type: \"uid\", \n                    uid: AIn.C.APPLICATION_UID\n                }\n            }\n        }\n    }\n<\/code><\/pre>\n<p>It will retrieve all the children (e.g. layers, art styles) for all open documents: documents are children of the application, and layers and art styles are children of the documents.<\/p>\n<h2>Request<\/h2>\n<p>Requests allow us to &#8216;do&#8217; something (i.e. extract data, or make changes to the document).<\/p>\n<p>Asynchronous calls will always need to use a request that contains a reference object, so the plug-in can know what objects to target with the request.<\/p>\n<p>Synchronous call with &#8216;implicit reference&#8217; can omit the reference object from the request. They target the object that is provided in the synchronous call.<\/p>\n<p>Each request needs at least an opcode (OPeration CODE).<\/p>\n<p>The following opcodes are currently supported (work in progress):<\/p>\n<pre><code>disposeArt\ngetinfo\nnewArt\nreorderArt\nselect\nsetinfo\nsimplifyPath\n<\/code><\/pre>\n<h3>disposeArt<\/h3>\n<pre><code>    {\n        opcode: \"disposeArt\",\n        reference: {\n            .... a reference object ...\n        }\n    }\n<\/code><\/pre>\n<p>This will remove the referenced art from the document.<\/p>\n<h3>getinfo<\/h3>\n<p>This request retrieves information about one or more objects and returns it.<\/p>\n<pre><code>    {\n        opcode: \"getinfo\",\n        alwaysReturnArray: true\/false, \/\/ optional, defaults to false\n        attr: ... a single attr or an array of attr ...\n        reference: {\n            .... a reference object ...\n        }\n    }\n<\/code><\/pre>\n<p>When alwaysReturnArray is true, the returned value is always an array (which could be empty or have only a single element).<\/p>\n<p>If alwaysReturnArray is false the returned value is either a single item if there is only a single result, or an array if there are multiple results.<\/p>\n<p>There is some support for function-like calls. Instead of just an attribute name, they are specified by 2-element arrays <code>[ &lt;&lt;attr&gt;&gt;, &lt;&lt;param&gt;&gt; ]<\/code><\/p>\n<p>Supported function-like attr:<\/p>\n<pre><code>    attr = allArt, param = { artType: ..., whichAttr:..., matchAttr:...}\n           each of those either a symbolic string, \n           e.g. 'kArtSelected' or an integer\n    attr = artOrder, param = string with artUID to compare with\n    attr = artUserAttr, param = whichAttr (either a symbolic string, \n           e.g. 'kArtSelected' or an integer)\n    attr = pathSegments, param = { segNum: ..., segCount: .... }. \n           pathSegments can also be used as a normal attribute\n    attr = pathLength,  param = AIReal flatness\n    attr = validArt, param = bool searchAllLayerLists\n<\/code><\/pre>\n<p>To call these, you need to provide a two-element array: first element is the attr name, second element is a JSON-encoded parameter construct.<\/p>\n<p>attr can currently be one or more selected from (work in progress):<\/p>\n<pre><code>    artBounds\n    artBoundsOptions\n    artDrawingMode\n    artHasFill\n    artHasStroke\n    artIsGraph\n    artStrokeParams\n    artStyle\n    artStyleName\n    artStyleScaleFactor\n    artSubType\n    artTargettingAction\n    artTimeStampOptions\n    artTransferAttrsOptions\n    artType\n    artXMP\n    ascent\n    autoKernType\n    autoLeading\n    baseLineShift\n    characterRotation\n    childCount\n    contents\n    descent\n    dictionary\n    distanceToBaseLine\n    entryType\n    extractedText\n    filePath\n    font\n    fontBaselineOption\n    fontCapsOption\n    fontSize\n    frameIndex\n    glyphOrientation\n    hasNote\n    horizontalScale\n    isArtClipping\n    isArtStyledArt\n    isEnvelope\n    layerGroup\n    leading\n    lineOrientation\n    matrix\n    maxCapHeight\n    minCapHeight\n    name\n    next\n    note\n    onPathTextTRange\n    origins\n    paintOrder\n    parent\n    parsedStyle\n    partOfLinkedText\n    pathArea\n    pathClosed\n    pathGuide\n    pathHasLength\n    pathIsClip\n    pathObject\n    pathPolarity\n    pathSegmentCount\n    pathSegments (can also be used as a function)\n    placedType\n    pointTextAnchor\n    prepArt\n    previous\n    spaceGlyphWidth\n    storyIndex\n    styledArt\n    text\n    textAntialias\n    textFrameColumnCount\n    textFrameColumnGutter\n    textFrameMatrix\n    textFrameOpticalAlignment\n    textFrameRowCount\n    textFrameRowGutter\n    textFrameRowMajorOrder\n    textFrameSpacing\n    textFrameStoryDirection\n    textFrameType\n    textOrientation\n    tracking\n    type\n    typeOnPath\n    typeOnPathEffect\n    typeOnPathFlipped\n    uid\n    underlinePosition\n    underlineThickness\n    verticalScale\n<\/code><\/pre>\n<p>Not all attributes make sense for all object types. If the attribute is not defined, an empty string will be returned.<\/p>\n<p>If the reference resolves to multiple objects, an array of replies will be returned.<\/p>\n<p>The reply object will contain an entry for each requested attr.<\/p>\n<h4>Example:<\/h4>\n<pre><code>    {\n        opcode: \"getinfo\",\n        attr: \"uid\"\n        reference: {\n            type: \"symbolic\",\n            symbolType: \"root\"\n        }\n    }\n<\/code><\/pre>\n<p>will return a single object<\/p>\n<pre><code>    {\n        uid: \"706c0a02-32fd-4fae-b745-778ba6995328\"\n    }\n<\/code><\/pre>\n<p>single uid, the uid of the document.<\/p>\n<h4>Example:<\/h4>\n<pre><code>    {\n        opcode: \"getinfo\",\n        attr: \"name\"\n        reference: {\n            type: \"uid\",\n            uid: [\"706c0a02-32fd-4fae-b745-778ba6995328\", \n                  \"807c0a02-32fd-4fae-b745-778ba6995439\"]\n        }\n    }\n<\/code><\/pre>\n<p>will return an array of two objects, the names of these objects:<\/p>\n<pre><code>    [\n        {\n            name: \"name 1\"\n        },\n        {\n            name: \"name 2\"\n        }\n    ]\n<\/code><\/pre>\n<h4>Example:<\/h4>\n<pre><code>    {\n        opcode: \"getinfo\",\n        attr: [ \"name\", \"childCount\" ]\n        reference: {\n            type: \"uid\",\n            uid: [\"706c0a02-32fd-4fae-b745-778ba6995328\", \n                  \"807c0a02-32fd-4fae-b745-778ba6995439\"]\n        }\n    }\n<\/code><\/pre>\n<p>will return an array of two objects:<\/p>\n<pre><code>    [\n        {\n            name: \"name 1\",\n            childCount: 5\n        },\n        {\n            name: \"name 2\"\n            childCount: 0\n        }\n    ]\n<\/code><\/pre>\n<h4>Example:<\/h4>\n<pre><code>    {\n        opcode: \"getinfo\",\n        attr:  [ \"allArt\", { \"artType\" : \"kAnyArt\" } ],\n        reference: {\n            .... a reference to a document ...\n        }\n    }\n<\/code><\/pre>\n<p>will call allArt({ &#8220;artType&#8221; : &#8220;kAnyArt&#8221; }) and return all UIDS of all art in the referenced document.<\/p>\n<h3>newArt<\/h3>\n<pre><code>    {\n        opcode: \"newArt\",\n        params: {\n          artType: ... art type...,\n          paintOrder: ... paint order...,\n          prepArt: ... a reference to a preparatory art object ...\n        }\n    }\n<\/code><\/pre>\n<p>This will create a new, empty art object.<\/p>\n<p>It will execute the C++ AIArtSuite call:<\/p>\n<pre><code>    AIAPI AIErr(*NewArt)(ai::int16 type, ai::int16 paintOrder, \n        AIArtHandle prep, AIArtHandle *newArt)\n<\/code><\/pre>\n<h3>reorderArt<\/h3>\n<pre><code>    {\n        opcode: \"reorderArt\",\n        reference: {\n           ... an art object...\n        }\n        params: {\n          paintOrder: ... paint order...,\n          prepArt: ... a reference to a preparatory art object ...\n        }\n    }\n<\/code><\/pre>\n<p>This will reorder the targeted art relative to the prep art.<\/p>\n<p>It will execute the C++ AIArtSuite call:<\/p>\n<pre><code>    AIAPI AIErr (*ReorderArt) (AIArtHandle thisArt, ai::int16 paintOrder, \n      AIArtHandle prep)\n<\/code><\/pre>\n<h3>select<\/h3>\n<p>Will attempt to select the referenced items<\/p>\n<h3>setinfo<\/h3>\n<p>This request will change some attributes or related data on the referenced objects.<\/p>\n<h3>simplifyPath<\/h3>\n<p>Will attempt to simplify the path. Smoothing uses a sliding average of smoothAveragePointCount to average out points along the path as long as they are no more than smoothToleranceInPoints apart.<\/p>\n<p>If a point between two other points is less than toleranceInPoints away from the other two, it will be removed.<\/p>\n<p>If a compound path subsegment has less than minSegmentCount segments, it will be deleted<\/p>\n<pre><code>  {\n      opcode: \"simplifyPath\",\n      smoothToleranceInPoints: 10,\n      smoothAveragePointCount: 10,\n      toleranceInPoints: 0.4,\n      minSegmentCount: 4,\n      reference: ...\n  }\n<\/code><\/pre>\n<p>This seems to work well on bitmaps that have been converted to paths and zig-zag all over the place. I&#8217;ve been able to reduce a sample compound path from > 200,000 path segments down to a few 10,000 while retaining something visually very close to the original. It also helps in making a path more manageable for manual editing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>AIntrospector 1.0.11 &#8211; 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data that is currently inaccessible to ExtendScript scripts. There is a discrepancy between what can be &hellip; <a href=\"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":143,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5659","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>AIntrospector Documentation - Rorohiko Workflow Resources<\/title>\n<meta name=\"description\" content=\"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AIntrospector Documentation - Rorohiko Workflow Resources\" \/>\n<meta property=\"og:description\" content=\"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/\" \/>\n<meta property=\"og:site_name\" content=\"Rorohiko Workflow Resources\" \/>\n<meta property=\"article:modified_time\" content=\"2018-06-01T05:48:54+00:00\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/aintrospector-documentation\\\/\",\"url\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/aintrospector-documentation\\\/\",\"name\":\"AIntrospector Documentation - Rorohiko Workflow Resources\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#website\"},\"datePublished\":\"2018-05-30T00:56:14+00:00\",\"dateModified\":\"2018-06-01T05:48:54+00:00\",\"description\":\"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/aintrospector-documentation\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/aintrospector-documentation\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/aintrospector-documentation\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AIntrospector Documentation\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#website\",\"url\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/\",\"name\":\"Rorohiko Workflow Resources\",\"description\":\"Custom InDesign Development\",\"publisher\":{\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#organization\",\"name\":\"Rorohiko Ltd.\",\"url\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.rorohiko.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/roro-logo-3d-v2.png\",\"contentUrl\":\"https:\\\/\\\/www.rorohiko.com\\\/wordpress\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/roro-logo-3d-v2.png\",\"width\":207,\"height\":200,\"caption\":\"Rorohiko Ltd.\"},\"image\":{\"@id\":\"https:\\\/\\\/rorohiko.com\\\/wordpress\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/zwettemaan\",\"https:\\\/\\\/www.instagram.com\\\/kriscoppieters\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/kristiaan\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AIntrospector Documentation - Rorohiko Workflow Resources","description":"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/","og_locale":"en_US","og_type":"article","og_title":"AIntrospector Documentation - Rorohiko Workflow Resources","og_description":"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data","og_url":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/","og_site_name":"Rorohiko Workflow Resources","article_modified_time":"2018-06-01T05:48:54+00:00","twitter_misc":{"Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/","url":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/","name":"AIntrospector Documentation - Rorohiko Workflow Resources","isPartOf":{"@id":"https:\/\/rorohiko.com\/wordpress\/#website"},"datePublished":"2018-05-30T00:56:14+00:00","dateModified":"2018-06-01T05:48:54+00:00","description":"AIntrospector 1.0.11 - 30 May 2018 This project has multiple goals. Short Term The short term goal is to provide ExtendScript access to Illustrator data","breadcrumb":{"@id":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/rorohiko.com\/wordpress\/aintrospector-documentation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rorohiko.com\/wordpress\/"},{"@type":"ListItem","position":2,"name":"AIntrospector Documentation"}]},{"@type":"WebSite","@id":"https:\/\/rorohiko.com\/wordpress\/#website","url":"https:\/\/rorohiko.com\/wordpress\/","name":"Rorohiko Workflow Resources","description":"Custom InDesign Development","publisher":{"@id":"https:\/\/rorohiko.com\/wordpress\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rorohiko.com\/wordpress\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/rorohiko.com\/wordpress\/#organization","name":"Rorohiko Ltd.","url":"https:\/\/rorohiko.com\/wordpress\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rorohiko.com\/wordpress\/#\/schema\/logo\/image\/","url":"https:\/\/www.rorohiko.com\/wordpress\/wp-content\/uploads\/2018\/03\/roro-logo-3d-v2.png","contentUrl":"https:\/\/www.rorohiko.com\/wordpress\/wp-content\/uploads\/2018\/03\/roro-logo-3d-v2.png","width":207,"height":200,"caption":"Rorohiko Ltd."},"image":{"@id":"https:\/\/rorohiko.com\/wordpress\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/zwettemaan","https:\/\/www.instagram.com\/kriscoppieters\/","https:\/\/www.linkedin.com\/in\/kristiaan"]}]}},"_links":{"self":[{"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/pages\/5659","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/users\/143"}],"replies":[{"embeddable":true,"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/comments?post=5659"}],"version-history":[{"count":21,"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/pages\/5659\/revisions"}],"predecessor-version":[{"id":5688,"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/pages\/5659\/revisions\/5688"}],"wp:attachment":[{"href":"https:\/\/rorohiko.com\/wordpress\/wp-json\/wp\/v2\/media?parent=5659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}