Using AIMaskSuite to create clipping mask in Adobe Illustrator CC 2019

Adobe Illustrator CC 2019 Plugin Development Notes by Musten Jiruwala
Adobe Illustrator CC 2019 Plugin Development Notes by Musten Jiruwala

Four weeks into writing an Adobe Illustrator CC 2019 plugin for the first time, the structure of the Adobe Illustrator CC 2019 SDK started to become clearer, albeit without much help from its documentation. I also searched the web and various forums on Adobe Illustrator CC 2019 SDK for usage of AIMaskSuite and found nothing. Hence, I thought of sharing this experience which may be of assistance to other AI plugin developers.

My team at TechMust has been writing Adobe InDesign plugins for nearly two decades. Developing an Adobe InDesign PlugIn means dealing with hundreds of “boss” classes and thousands of “interfaces”. Four weeks into AICC2019 SDK and we realised that none of those skills will be of any use in developing an Adobe Illustrator plugin. A pity.

The plugin that we are developing for AICC2019 is a simple plugin. It simply reads an XML file and places images defined in the XML file into an Illustrator document based on the parameters given in the XML file. Yes. That simple. To parse the XML, we used xerces XML framework (https://xerces.apache.org/xerces-c/)

Creating an AI document with a specific dimension was not difficult.

AINewDocumentPreset tSettings;

// get the preset
sAIDocumentList->GetPresetSettings(const_cast<ai::UnicodeString&>(strPreset), &tSettings);

// change the dimensionstSettings.docHeight = GetHeight()*(PPI / MMPI);
tSettings.docWidth = GetWidth()*(PPI / MMPI);
tSettings.docUnits = kMillimetersUnits;

// set the title
tSettings.docTitle = ai::UnicodeString(strTitle);
ai::UnicodeString oPreset(strPreset);

// create the document
tResult = sAIDocumentList->New(oPreset, &tSettings, kDialogOff, &oDocument);

aisdk::check_ai_error(tResult);

That’s it! I am sure there might be some simpler ways to do it. For now, this is simple enough for me 😉

The placement of file onto the document was also simple enough.

However, unlike in Adobe InDesign where the image is clipped in its parent page item, here it was the other way around. Read on!

First, create a clipping group. Yes, a group.

AIArtHandle oClippingGroup;
AIArtHandle oClippingRegion;

// create a clipping group.
sAIArt->NewArt(kGroupArt, kPlaceAboveAll, nullptr, &oClippingGroup);
tResult = sAIGroup->SetGroupClipped (oClippingGroup, true);

aisdk::check_ai_error(tResult);

Then, create a clipping region. You can create a clipping region in any shape. For simplicity sake, create a rectangular clipping region.

// Create a clipping art as kPathArt within the clipping group created above
sAIArt->NewArt(kPathArt, kPlaceInsideOnBottom, oClippingGroup, &oClippingRegion);

// Create a rectangle path for clipping
tResult = sAIPath->SetPathSegmentCount (oClippingRegion, 4);
AIPathSegment arrClipping [4];

arrClipping[0].p.h = oImageRect.left;
arrClipping[0].p.v = oImageRect.top;
arrClipping[0].in = arrClipping[0].out = arrClipping[0].p;
arrClipping[0].corner = true;

arrClipping[1].p.h = oImageRect.right;
arrClipping[1].p.v = oImageRect.top;
arrClipping[1].in = arrClipping[1].out = arrClipping[1].p;
arrClipping[1].corner = true;

arrClipping[2].p.h = oImageRect.right;
arrClipping[2].p.v = oImageRect.bottom;
arrClipping[2].in = arrClipping[2].out = arrClipping[2].p;
arrClipping[2].corner = true;

arrClipping[3].p.h = oImageRect.left;
arrClipping[3].p.v = oImageRect.bottom;
arrClipping[3].in = arrClipping[3].out = arrClipping[3].p;
arrClipping[3].corner = true;

// set the path in oClippingRegion
tResult = sAIPath->SetPathSegments(oClippingRegion, 0, 4, arrClipping);
aisdk::check_ai_error(tResult);

tResult = sAIPath->SetPathClosed (oClippingRegion, true);
aisdk::check_ai_error(tResult);

This will create a rectangular region. It will not yet be considered as a clipping region. To achieve that :

// Create Mask using clipping
AIMaskRef oClipRef;
// Create a mask reference for the oClippingRegion created above

tResult = sAIMask->CreateMask (oClippingRegion);
aisdk::check_ai_error(tResult);
tResult = sAIMask->GetMask (oClippingRegion, &oClipRef);
aisdk::check_ai_error(tResult);

// set the mask to denote that whatever is inside of the oClippingRegion should be visible and outside should be hidden.
tResult = sAIMask->SetClipping (oClipRef, true);
aisdk::check_ai_error(tResult);

// I am not sure as to whether this is needed or not. I have to do some more tests to find this out.
sAIMask->AddRef (oClipRef);

// Now, don’t forget to inform the AIArtSuite that this is the clipping region to be used in the clipping group!
tResult = sAIArt->SetArtUserAttr (oClippingRegion, kArtIsClipMask, kArtIsClipMask);
aisdk::check_ai_error(tResult);

The sequence is important. If the sequence is not followed, desired result cannot be achieved.

Create the group and set it to clipping. If the group is created but not set to clipping before sAIMask->CreateMask, it will not work. My reasoning is, clipping mask can be created only within a clipping group.

After these steps are done, create and place the image within this clipping group and – voila – it will respect the clipping. Don’t forget that image should be placed in the clipping group!

sAIArt->NewArt(kPlacedArt, 
      kPlaceInsideOnBottom, 
      oClippingGroup, 
      &oArtHandle);

Moving and transforming the placed image is another experience in Adobe Illustrator SDK. More on that later.

Author : Musten Jiruwala, CEO, TechMust Software Pvt Ltd. Bangalore.

Leave a Reply

Your email address will not be published. Required fields are marked *