├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | scripting-for-illustrator-tutorial 2 | ================================== 3 | 4 | Scripting for Illustrator, a tutorial for Processing coders. 5 | 6 | ###Intro 7 | 8 | I'm going to show you how to create a new document, work with existing documents, make shapes, text, and placed images. I will also show you how to manipulate preexisting objects in a layout. The tutorial assumes you are familiar with basic concepts of object oriented language and the basics of Processing. Naturally, it helps to know the Javascript language, and the basics of Adobe Illustrator. If you are new to the Javascript language (even if you know Java from Processing), here is a nice JS tutorial: http://www.codecademy.com/en/tracks/javascript 9 | 10 | ###Install 11 | 12 | Beginning with Illustrator CC, the scripting is not bundled so please download and install it now. It can be found in the Adobe Creative Cloud system menu in the Apps tab. Otherwise, you can find the link here: https://creative.adobe.com/products/estk 13 | 14 | You will see a new folder called /Applications/Adobe ExtendScript Toolkit CC ... so now you can run the app called "ExtendScript Toolkit". Please do so now. 15 | 16 | You will see a cute little scripting app pop up, but it won't be aimed at Illustrator by default. Tell it to control Illustrator by selecting "Adobe Illustrator CC ####" (which ever version you prefer) from the top-left menu. 17 | 18 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/00.png) 19 | 20 | If Illustrator is not yet running, you will get this popup: 21 | 22 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/01.png) 23 | 24 | Choose "YES" and it will launch Illustrator for you. 25 | 26 | The chain link to the left of the dropdown menu is now linked-up and colored green. If illustrator closes, you will see the link icon looking "broken". 27 | 28 | ###HelloWorld 29 | 30 | It's deceptively simple. Type `"Hello World"` into the editor (INCLUDING THE QUOTES), then hit the green play button. Illustrator will flash for a moment, then return you back to ExtendScript. 31 | 32 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/02.png) 33 | 34 | Notice the console shows `hello world`. This is because the entire script is treated as an expression, so what ever is evaluated by the end of the interpretation will show up in the console. In fact, you can use it as a basic calculator. Type `1+3` and the console will show `4`. 35 | 36 | Now let's get more explicit. There is an actual function for printing to console, akin to `println()` in Processing. It's a static method of the `$` object. Like the JQuery javascript library, we have a frequently-used global object called `$` whose methods have to do with the ExtendScript system at large. For example, run this script: 37 | 38 | ```js 39 | $.writeln("hi there!"); 40 | $.writeln("here is another line."); 41 | ``` 42 | and you will see: 43 | 44 | ``` 45 | hi there! 46 | here is another line. 47 | Result: undefined 48 | ``` 49 | 50 | At the end, you see Result: undefined since the last function call was to `$.writeln()` and that has a void return type, and nothing is sent back. 51 | 52 | At this time, you may notice the editor's font is a sans-serif. You will most likely prefer a fixed-width font like Monaco or Courier New. I include instructions in tips and tricks for that at the far end of this tutorial. 53 | 54 | ###Documentation 55 | 56 | Let's explore the $ object in the documentation. Open up this PDF: 57 | 58 | */Applications/Adobe ExtendScript Toolkit CC/SDK/JavaScript Tools Guide CC.pdf* 59 | 60 | . . . and jump to page 216. There, you will see a list of properties and functions of this object, including `writeln()`. Amongst the functions, there are some that catch my eye: 61 | 62 | `$.colorPicker()` - asks the user to select a color from a standard color chooser, then returns an integer that, when represented in hexadecimal, is a standard HTML color triplet. Also works in Processing. 63 | 64 | `$.sleep()` - tells the system to wait a little bit between operations so you can perhaps see each shape being drawn at a slower pace. 65 | 66 | Okay, so let's stop printing test messages to the console and begin to control the Illustrator app. 67 | 68 | ###Install Illustrator API Documentation 69 | 70 | I'm not sure why, but Adobe does not bundle the Illustrator API documentation with ExtendScript or with Illustrator. Here is where to get it: http://www.adobe.com/devnet/illustrator/scripting.html ... Download the PDFs called "Illustrator Scripting Reference - JavaScript.pdf" and "Illustrator Scripting Guide.pdf". The guide is an overview of the entire system and how it works, although the language may possibly be developer-centric for an ITPer. The reference is a list of all the objects, describing their properties and methods. A great place to start is page 14. Here is the drawing you see. Don't worry if it's overwhelming information. The API is vast and you don't need to memorize this stuff. Just know that it's there for reference as you work. 71 | 72 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/03.png) 73 | 74 | An object model describes which types of things contain other types of things. In this case, the Application object is the top-most, root of the tree. The diagram shows that the Application directly contains TextFont, Document, and those 4 objects on the far right. In the next part of this tutorial, I will show you how to work with the documents. Please think of this as akin to the Processing tutorial on the `background()` and `size()` functions. 75 | 76 | ###Getting the open Document 77 | 78 | Continuing our discussion of the object model diagram, the Document object, in turn, looks like it directly contains most every kind of thing you would want to create or access, including shapes and art boards. Awesome, so let's work our way down into the cave! Please open the reference PDF (the file you downloaded, called "Illustrator Scripting Reference - JavaScript.pdf") and turn to page 3, the table of contents. Notice it's just a list of object names. Click on "Application" and it will jump to page 8, where it describes the Application object. The description says the following: 79 | 80 | "The Adobe® Illustrator® application object, referenced using the pre-defined global app object, which contains all other Illustrator objects." 81 | 82 | That tells me that there is an app object already available to my script, for free, and it's a global instance of the Application object. Let's test that by printing it to the console. 83 | 84 | ```js 85 | $.writeln(app); 86 | ``` 87 | 88 | You will see this printed to the console: 89 | [Application Adobe Illustrator] 90 | 91 | and that means that something exists there. If there was nothing, the execution would have stopped and colored the line red, telling you the symbol is undefined. But, because it didn't, we can traverse further down! The documentation for the Application object shows that there is a property called activeDocument. Let's print that too: 92 | 93 | ```js 94 | $.writeln(app.activeDocument); 95 | ``` 96 | 97 | You'll see the system gets confused unless you have a document open in illustrator. If the execution stopped and gave you a red line, try creating a new Illustrator document and leaving it open before running the script again, and it will not error that time. 98 | 99 | ###Create a New Document 100 | 101 | If you wish to simply work with the document you already have open, your shortcut is app.activeDocument. However, if you wish to create a new document, here's how we go about it. In the reference, we see the Application has a property called documents, which is an instance of Documents . Click the blue link to Documents and it will jump to page 45, documentation on the collection of Document objects. This object is basically an array of documents. If you have nothing open, the length property will be 0. To create a new document using a pop-up dialog to ask the user what sort of document they need, you can go like this: 102 | 103 | ```js 104 | app.documents.addDocument('',new DocumentPreset(),true); 105 | ``` 106 | 107 | Notice that this time, the console ended with `Result: [Document Untitled]` , meaning that this function returns a document instance. You could catch that in a variable and work with it from that point on: 108 | 109 | ```js 110 | var doc = app.documents.addDocument('',new DocumentPreset(),true); 111 | ``` 112 | 113 | Let's say you want to automate the creation of documents, for example, pulling from a paper-size database, or using a generative pattern of paper-sizes. You would be calling `Documents.add()` like this: 114 | 115 | ```js 116 | var doc = app.documents.add(); 117 | ``` 118 | 119 | Very simple, but there are parameters you could be adding to control the size, number of artboards, and to some extent, the grid layout of those art boards. 120 | 121 | ```js 122 | //create a new document of size 100x100 points 123 | var doc = app.documents.add( null , 100,100); 124 | 125 | //create a new document of default size, with 4 art boards. 126 | var doc = app.documents.add(null,null,null,4); 127 | 128 | // makes a 10x10 grid of artboards, each sized 10x10, with margin spacing of 10. 129 | var doc = app.documents.add(null,10,10,100,DocumentArtboardLayout.Column,10,10); 130 | ``` 131 | 132 | ###Shape and Color 133 | 134 | To draw a shape, you need to add a new path to the paths object. This is similar to the structure of app.documents but this time, it's Document.pathItems. 135 | 136 | This script: 137 | 138 | ```js 139 | var doc = app.documents.add(null,100,100); 140 | doc.pathItems.rectangle(0,0,50,20); 141 | ``` 142 | 143 | will give you this result: 144 | 145 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/04.png) 146 | 147 | 148 | Notice that unlike Processing, whose `0,0` origin point is at the top-left, the Illustrator document's `0,0` origin point is at the bottom-left. To get it inside the document, we would need to use a negative Y value. We can account for this by drawing the shape using the height of the document for the Y value. Notice in this example that the rectangle's X and Y order are swapped: 149 | 150 | ```js 151 | var width = 100; 152 | var height = 100; 153 | var doc = app.documents.add(null,width,height); 154 | doc.pathItems.rectangle(height,0,50,20); 155 | ``` 156 | 157 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/05.png) 158 | 159 | 160 | There are a few other handy shape functions you can call. Always check the documentation (reference, page 135) to see the order of parameters. Here is a demo that calls a few more of those shape functions: 161 | 162 | ```js 163 | var width = 100; 164 | var height = 100; 165 | var doc = app.documents.add(null,width,height); 166 | var p = doc.pathItems; 167 | p.rectangle(height,0,50,20); 168 | p.ellipse(20,30,20,10); 169 | p.polygon(10,50,20,6); 170 | p.roundedRectangle(height,60,30,30,5,5); 171 | p.star(70,30,10,20,8); 172 | ``` 173 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/06.png) 174 | 175 | Now that we've gotten the shape primitives out of the way, I'd like to show you how to build a path from vertices. In Processing, this is akin to `beginShape()`, `vertex()`, and `endShape()`. In Illustrator, you tell the pathItems collection to create a new path, and that path will live in that collection. You take that shape as a variable and do things to it, including setting the vertices, closing/opening it (whether the last and first points connect), and the stroke/fill information. 176 | 177 | ```js 178 | var width = 100; 179 | var height = 100; 180 | var doc = app.documents.add(null,width,height); 181 | var p = doc.pathItems; 182 | var shape = p.add(); 183 | shape.setEntirePath([ 184 | [78.5,26], 185 | [59.8,77.3], 186 | [18.3,77.3], 187 | [16.3,74.7], 188 | [17.5,71.5], 189 | [33.2,71.5], 190 | [39.5,77.5], 191 | [54.7,77.5], 192 | [31.7,35.8], 193 | [42,50.8], 194 | [48,51.8], 195 | [45,59.5], 196 | [49.2,68.8], 197 | [59,64], 198 | ]); 199 | shape.closed = true; 200 | shape.filled = false; 201 | shape.strokeCap = StrokeCap.ROUNDENDCAP; 202 | shape.strokeJoin = StrokeJoin.ROUNDENDJOIN; 203 | shape.strokeWidth = 10; 204 | ``` 205 | 206 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/07.png) 207 | 208 | Unlike Processing, the stroke and fill colors are not global properties of the sketch. Instead, they are individual properties of the object. Here is an example of how to take a pathItem object, and color it. 209 | 210 | ```js 211 | var doc = app.documents.add(null,100,100); 212 | var p = doc.pathItems; 213 | 214 | var star1 = p.star(40,50,50,60,3); 215 | star1.blendingMode = BlendModes.LIGHTEN; 216 | star1.fillColor = makeColor(255,0,0); 217 | star1.strokeColor = makeColor(0,255,0); 218 | star1.strokeWidth = 10; 219 | 220 | var star2 = p.star(60,50,50,60,3); 221 | star2.blendingMode = BlendModes.LIGHTEN; 222 | star2.fillColor = makeColor(0,0,255); 223 | star2.strokeColor = makeColor(255,0,255); 224 | 225 | /* 226 | necessary since RGBColor class has no constructor. 227 | */ 228 | function makeColor(r,g,b){ 229 | var c = new RGBColor(); 230 | c.red = r; 231 | c.green = g; 232 | c.blue = b; 233 | return c; 234 | } 235 | ``` 236 | 237 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/08.png) 238 | 239 | You can see I wrote a wrapper function to make the code look a bit more like Processing. I'm sure someone could sit down and write a wrapper class that sits on top of the Illustrator ExtendScript and supports a well-documented subset of the Processing API. However, doing so would not open you up to the things that are unique about Illustrator's system. For example, they have more color models than those which come bundled with Processing (not that you couldn't just implement those yourself). Here is an example of subtractive color... you know, the kind of color-mixing you learned from crayons and paint. 240 | 241 | ```js 242 | var width = 100; 243 | var height = 100; 244 | var doc = app.documents.add(null,width,height); 245 | var p = doc.pathItems; 246 | 247 | for(var y=0;y Preferences...* and in that popup, select *Fonts and Colors* on the right. In the Font dropdown menu, choose Monaco or Courier or which ever fixed-width font you prefer. It also helps me to choose 12 for the font size. 513 | 514 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/19.png) 515 | 516 | Hit OK when you are done, and the changes will be visible in the editor. 517 | 518 | ###Coding in the layout 519 | 520 | Because why not. JS has an `eval()` function and some of you know what that implies. 521 | 522 | ![](http://cdn.jtn.im/2014-11-13-ai-scripting-tut/20.png) 523 | 524 | The above is proof that you can code in the illustrator layout, itself. To run the code, access the text object then call eval on the string contents. 525 | 526 | --------------------------------------- 527 | 528 | 529 | Ok, that concludes this tutorial. Let me know if there are topics you're interested in knowing about. 530 | 531 | 532 | 533 | 534 | 535 | 536 | --------------------------------------------------------------------------------