How Priint Brought Comet from InDesign to Illustrator

Leo Quensel
Oct 23 · 7 min read

“Today’s guest post is by Leo Quensel, lead developer at the priint Group for the priint:comet plug-in for Illustrator. The priint Group is a long-time extender of InDesign, and has more recently brought their plug-in to Illustrator as a CEP panel. In this post, Leo shares details about their path to adding Illustrator support while leveraging existing code from their InDesign plug-in, all using classic CC extensibility APIs like C++ SDKs, CEP, and ExtendScript.”

— Erin Finnegan, Community Engineer, Creative Cloud

Starting fifteen years ago, the priint Group found that layout automation was still in a copy and paste mode with many manual processes that cost time and money. And so, the priint Group developed the priint:comet plug-in for InDesign to automate the processes between content systems and layout. Fifteen years later, it’s still the leading database publishing system for layout automation today.

Since the start of the priint Group, our developers have found solutions to automate the print touch points for omnichannel customer experiences. Our latest development is the priint:comet plug-in for Illustrator: it’s used for layout automation and loading data from nearly any data source right into Illustrator documents.

This story gives a rough overview of how the priint:comet plug-in for Illustrator came to be and some of the challenges I still face today as lead developer.

Some background

Two years ago, my boss Horst Huber asked me if it was feasible to port the functionality of our priint:comet plug-ins for InDesign over to Illustrator. The same question had bubbled up from time to time when talking to customers, so this was the deciding push for us to develop a prototype.

My initial concern was that the two host apps each follow a very different design approach. Our existing plug-ins and workflows were specially designed for InDesign. Horst swept away my concerns by saying simply; “If it was easy, everyone would do it”.

Where we are today

Fast forward to today to find that we have our first official release at hand; sporting an already impressive set of features including our core technology like placeholders, products, and layout rules.

Our first customers have started exploring the product and already provide valuable feedback and feature wish lists, essentially helping shape the future of our development.

As of right now, everything is in place to start production on projects with priint:comet for Illustrator. (In case you’re interested, there is a webinar online. Please note that it requires registration.)

How we got there

When we started to work on our plug-in for Illustrator, we first had to choose which technology and APIs to use. Illustrator offers Extendscript and C++ APIs, as well as native and CEP (Common Extensibility Platform) panels and dialogs for building user interfaces.

On the backend our choice was obvious: We already had an extensive set of base libraries and tools built around the InDesign C++ APIs, and could reuse them for our plug-in for Illustrator. These libraries provide functionality like data source connectivity, HTML parsing, XML handling, file system access etc..

We were able to reuse a lot of existing functionality not specific to InDesign, and only making minor changes. This saved us from rewriting at least a few tens of thousands of lines of code.

However, when it came to functionality specific to Illustrator, for example, inserting text into a text frame, or placing an image, we were not so lucky: Both host applications vastly differ in their APIs and data model approaches, so we had to start over when it came to implementing some of what we had already written for InDesign.

Luckily, we had a pretty good idea of what we wanted feature-wise, so most of the time we could use our plug-ins for InDesign as guidelines and figure out how to do a similar implementation in Illustrator.

An example

A common example is geometry modification and information querying. When working with layout automation, this functionality is used everywhere.

Let’s say you want to query the bounding box of a frame (InDesign) or a piece of art (Illustrator):

/*Find the bounding box of a frame in the InDesign C++ API:*/ Utils<Facade::IGeometryFacade>()-> GetItemBounds (frameRef, coordinates, boundsKind);
/*Find the bounding box of a frame in the Illustrator C++ API:*/
sAIArt->GetArtTransformBounds(frameArt, nil, kNoStrokeBounds, &oBBox);

Illustrator and InDesign use different coordinate systems. Since all our transformations relied on the InDesign system, we built conversion functionality right into any function working with Illustrator coordinates:

if (inDesignStylePageCoords) {
//negate the vertical values
oBBox.top *= -1.0;
oBBox.bottom *= -1.0;
}

Our product can be driven by our own custom scripting language called cScript, which syntax and logic-wise is much like good old C.

When the user wants to find out the bounding box of a piece of geometry, he calls the exact same function in InDesign and Illustrator: frame::bbox, using the same syntax and parameters, and now, the same coordinate system.

In this way, we we able to reuse implementations for custom scripts in our new plug-in for Illustrator.

UI implementation

Illustrator provides native platform panels and dialogs as well as the Adobe Common Extensibility Platform (CEP).

Since we did not want to write the entire UI logic twice (for Mac and Windows), we decided to give CEP a shot, which enables building user interfaces through HTML, and also allows the use of JavaScript to drive the user interface.

While InDesign can also be extended with CEP, our existing technology relies on the native InDesign user interface using ODFRC resource files. Therefore, we had to build up knowledge on how to work with CEP and how to get data and interaction triggers back and forth between Illustrator and CEP.

Since our panels are rather complex we also had to find out how to properly implement our functionality for an HTML based front-end.

In the end we ended up only using jQuery and LESS as helper frameworks and wrote everything else ourselves in order to have full control over how the UI looks, behaves and feels.

A closer look at Layout rules

Let’s inspect one of our prime features from the plug-ins for InDesign which we also brought to our plug-in for Illustrator: layout rules.

Layout rules are sets of rules and conditions which can be applied to images and text frames. These rules can then be executed in certain situations, for example, when loading data from a data source into text frames.

Let’s say you want to load some text into a text frame. You don’t know how long the text will be since that depends on the data you are loading from your data source, so you may end up with overset text:

With layout rules you can remedy the situation by setting up a rule to “Fit frame” which is triggered whenever text is loaded into that frame.

But you only want that to happen when the frame is not big enough, right? You don’t want it to shrink when the text is not overset. So, you place a layout condition around the rule: “If text overflow”. Now the rule only gets triggered when the loaded text actually causes the frame to overflow.

Illustrator layout rules CEP panel:

Text frames after loading text and applying the layout rules:

Rules and conditions can be nested arbitrarily, allowing complex decision trees and behaviors to adapt your Illustrator files to any content loaded from your data source.

There is a set of predefined rules and the possibility to create your own rules and conditions which are implemented in our cScript language.

Implementation

We had to face the choice of whether to take parts from an existing implementation of our plug-ins for InDesign or rewrite the implementation from scratch. At the same time, we had to figure out how to attach the layout rule data to art objects in Illustrator and send it to CEP to display for editing purposes.

Our existing implementation was purely string based using a custom syntax which we parsed ourselves. However, we would have to implement our syntax parser in JavaScript as well, due to the necessity of wrapping the data before sending it to CEP in order to display the layout rule tree in the UI.

In the end we decided to completely rewrite the layout rule mechanism to a comprehensive set of C++ classes and store it in a hierarchical fashion.

priint’s layout rule mechanism hierarchy

This hierarchy can at any point be easily serialized to a JSON string which can then be exchanged between CEP and Illustrator. The JSON string is also what is stored inside the Illustrator document to save and read the layout rules of a piece of artwork.

The hierarchy also makes creating additional and custom layout rules easier down the line.

Here’s an example of layout rule data sent to CEP for UI purposes:

This technology is now pending to replace our old technology in our plug-ins for InDesign.

We want to hear from you!

Do you have any ideas, suggestion or feedback for our plug-in for Illustrator? We would love to hear from you at info@priint.com

Eager to know more? Check out priint.com or follow us on social media; LinkedIn or Twitter.


For more stories like this, subscribe to our Creative Cloud Developer Newsletter.

Adobe Tech Blog

News, updates, and thoughts related to Adobe, developers, and technology.

Leo Quensel

Written by

Lead developer for priint:comet Illustrator plugins at priint.com

Adobe Tech Blog

News, updates, and thoughts related to Adobe, developers, and technology.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade