Skip to main content
Participating Frequently
February 8, 2018
Answered

Duplicate/Move Layer, Outline Text, then Remove Strokes & Change Fill to Black

  • February 8, 2018
  • 1 reply
  • 1853 views

The ultimate goal of this script is to create a sort of plain black text version of a copy layer (with text that sometimes has various effects/appearances applied).

I've got a multi-part script I'm trying to write that will do a few things in order. I've got a few bits cobbled together from other scripts, but it's not entirely working and there's some bits of functionality I don't know how to fit in there. It's actually a bit of a mess and I'm sure there must be a more efficient way to go about it. Could anybody take a look and either point me in the right direction or (if someone had the time) create a more efficient version of this.

What I need the script to do:

1. Lock all Layers

2. Duplicate Layer "SOURCE"

3. Rename duped layer to "SOURCE APPROVAL" & hide all other layers

4. Move "SOURCE APPROVAL" layer to below "SOURCE" layer in layers palette

5. Outline all text on "SOURCE APPROVAL" layer

6. Select everything, remove all strokes, and change the Fill color of all objects (whether regular items or compound paths or grouped) to black (only on "SOURCE APPROVAL" layer)

What I've got so far is a giant mess that does some things, but not others. I haven't been able to get the layers to move to a specific point in the layers palette and I can't seem to affect compound paths to change their color or remove their strokes.

var docRef = app.activeDocument; 

var myLayers = docRef.layers;

var layer = app.activeDocument.activeLayer;

var flatBlack= new CMYKColor()

flatBlack.black=100;

for (a=0; a<myLayers.length; a++){

     myLayer = myLayers;

     myLayer.locked = true;

}

#target illustrator 

var ln = 'SOURCE'; 

var ol = docRef.layers.getByName(ln); 

var nl = docRef.layers.add(); 

nl.name = ln+' APPROVAL'; 

     

    for (var a = ol.pageItems.length-1; a >= 0; a--) { 

     

        ol.pageItems.duplicate(nl, ElementPlacement.PLACEATBEGINNING); 

     

        }

       

app.executeMenuCommand("selectall");

app.executeMenuCommand("ungroup");

app.executeMenuCommand("outline");

   

// Iterate through all path items

    for (var i = 0; i < nl.pathItems.length; i++) {

      with (nl.pathItems) {

        if (filled == true) {

          // If black exceeds maxBlack clip it to flat black (100%K)

          fillColor = flatBlack;

        }

        if (stroked == true) {

          stroked = false;

        }

      }

    }

This topic has been closed for replies.
Correct answer OMOTI


Sure thing, Not quite sure how to attach things on here, but here's a link: https://www.dropbox.com/s/qebzffy85rg40h4/TextStylesTest.ai?dl=0

The test file is meant to simulate many of the likely scenarios we might come across working on our files. To give some background, alot of times we pull art forward and make minor changes, but because so many different people have been in and out of the files over the years, files can get weird sometimes. Some of the designers we've had just do things differently or got sloppy files from an agency and didn't clean up the files afterwards. So we're constantly having to keep a lookout for booby traps (even in how the text is constructed). For proofreading purposes, we're wanting to submit a black and white document to proofreaders and other departments to verify the accuracy of the info and to avoid them getting distracted by any other visual elements, thus the need for this script to quickly output a "plain text" proofreading document.

Also, I recreated the file at home on CS6, whereas we use CC2017 at work. Not sure if anything in AI scripting changed between the two.


Thanks for the test file.

Like this?

#target illustrator

(function () {

   

    var docRef = app.activeDocument,

        myLayers = docRef.layers,

        layer = app.activeDocument.activeLayer,

        flatBlack = new CMYKColor(),

        ln = 'SOURCE',

        nln = ln + ' APPROVAL',

        ol = docRef.layers.getByName(ln),

        nl = docRef.layers.add(),

        pathItem,

        i,

        max;

   

    function isContainedInApprovalLayer(target) {

        if (target.parent.typename === "Document") {

            if (target.name === nln) {

                return true;

            }

            return false;

        }

        return isContainedInApprovalLayer(target.parent);

    }

   

    nl.name = nln;

    flatBlack.black = 100;

   

    nl.move(ol, ElementPlacement.PLACEAFTER);

   

    for (i = ol.pageItems.length - 1; i >= 0; i -= 1) {

        ol.pageItems.duplicate(nl, ElementPlacement.INSIDE);

    }

   

    for (i = 0, max = myLayers.length; i < max; i += 1) {

        myLayers.locked = true;

    }

   

    nl.locked = false;

   

    for (i = 0, max = myLayers.length; i < max; i += 1) {

        myLayers.visible = false;

    }

   

    nl.visible = true;

   

    docRef.selection = null;

   

    for (i = 0, max = nl.symbolItems.length; i < max; i += 1) {

        nl.symbolItems.selected = true;

    }

   

    // expand symbol item.

    app.executeMenuCommand('Expand3');

   

    app.executeMenuCommand('selectall');

    app.executeMenuCommand('outline');

   

    docRef.selection = null;

   

    for (i = 0, max = nl.groupItems.length; i < max; i += 1) {

        nl.groupItems.selected = true;

    }

   

    // Register action to "Clear Appearance" only in advance.

    // ("Clear Appearance" in the menu of Appearance panel)

    app.doScript("myAction", "myActionSet");

   

    for (i = 0, max = docRef.pathItems.length; i < max; i += 1) {

        pathItem = docRef.pathItems;

       

        if (isContainedInApprovalLayer(pathItem) && pathItem.locked === false && pathItem.hidden === false) {

            if (pathItem.filled === true) {

                pathItem.fillColor = flatBlack;

            }

            if (pathItem.stroked === true) {

                pathItem.stroked = false;

            }

        }

    }

   

    nl.locked = true;

   

}());

1 reply

OMOTI
Inspiring
February 9, 2018

Hello, paddirn.

Please try this and read the explanation in the code.

// #target illustrator

(function () {

   

    var docRef = app.activeDocument,

        myLayers = docRef.layers,

        layer = app.activeDocument.activeLayer,

        flatBlack = new CMYKColor(),

        ln = 'SOURCE',

        ol = docRef.layers.getByName(ln),

        nl = docRef.layers.add(),

        myPathItem,

        i;

   

    function dismantleCompoundPathItem() {

        app.executeMenuCommand("selectall");

        app.executeMenuCommand("noCompoundPath");

    }

   

    function ungroup() {

        app.executeMenuCommand("selectall");

        app.executeMenuCommand("releaseMask");

        app.executeMenuCommand("ungroup");

    }

   

    nl.name = ln + ' APPROVAL';

    flatBlack.black = 100;

   

    // (When the layer and the relativeObject are locked, the layer can't move.)

    // >> 4. Move "SOURCE APPROVAL" layer to below "SOURCE" layer in layers palette

    nl.move(ol, ElementPlacement.PLACEAFTER);

   

    for (i = ol.pageItems.length - 1; i >= 0; i -= 1) {

        // (change "ElementPlacement.PLACEATBEGINNING" to "ElementPlacement.INSIDE".)

        ol.pageItems.duplicate(nl, ElementPlacement.INSIDE);

    }

   

    for (i = 0; i < myLayers.length; i += 1) {

        myLayers.locked = true;

    }

   

    // unlock to edit objects in "nl" layer.

    nl.locked = false;

   

    // >> 3. ... hide all other layers

    for (i = 0; i < myLayers.length; i += 1) {

        myLayers.visible = false;

    }

   

    nl.visible = true;

   

    app.executeMenuCommand("selectall");

    app.executeMenuCommand("outline");

   

    // dismantle compoundpathitems

    if (0 < nl.compoundPathItems.length) {

        dismantleCompoundPathItem();

    }

   

    // clear clipping path and ungroup

    while (0 < nl.groupItems.length) {

        ungroup();

    }

   

    for (i = 0; i < nl.pathItems.length; i += 1) {

        myPathItem = nl.pathItems;

        if (myPathItem.filled === true) {

            myPathItem.fillColor = flatBlack;

        }

        if (myPathItem.stroked === true) {

            myPathItem.stroked = false;

        }

    }

   

    // >> 1. Lock all Layers

    nl.locked = true;

   

}());

paddirnAuthor
Participating Frequently
February 9, 2018

Thanks for taking a look at it, that code looks alot better than the junk I was try to cludge together. I ran the script and it does do a good portion, but it's still getting stuck on a part of the problem I've been having with it. I probably didn't explain it well enough. I'm trying to get it to outline/fill with Black a variety of type styles/appearances that may be setup in our files.

So the test file I'm running it on looks like this:

After I ran your script, it ends up looking like this:

So all the copy is outlined and some paths change to black/lose strokes, which is what I needed, but the outlined text itself doesn't change color and some of the strokes on the text doesn't actually lose it's stroke. It also didn't touch the invisible objects, which is a good thing.

I tried adjusting the last portion of it that adds the fill and removes the strokes, but that didn't seem to do it either:

    while (0 < nl.groupItems.length) {

        ungroup();

    }

   

    for (i = 0; i < nl.pathItems.length; i += 1) {

        myPathItem = nl.pathItems;

        myCompoundPathItem = nl.compoundPathItems;

        if (myPathItem.filled === true) {

            myPathItem.fillColor = flatBlack;

        }

        if (myPathItem.stroked === true) {

            myPathItem.stroked = false;

        }

        if (myCompoundPathItem.filled === true) {

            myCompoundPathItem.fillColor = flatBlack;

        }

        if (myCompoundPathItem.stroked === true) {

            myCompoundPathItem.stroked = false;

        }

   }

OMOTI
OMOTICorrect answer
Inspiring
February 10, 2018


Sure thing, Not quite sure how to attach things on here, but here's a link: https://www.dropbox.com/s/qebzffy85rg40h4/TextStylesTest.ai?dl=0

The test file is meant to simulate many of the likely scenarios we might come across working on our files. To give some background, alot of times we pull art forward and make minor changes, but because so many different people have been in and out of the files over the years, files can get weird sometimes. Some of the designers we've had just do things differently or got sloppy files from an agency and didn't clean up the files afterwards. So we're constantly having to keep a lookout for booby traps (even in how the text is constructed). For proofreading purposes, we're wanting to submit a black and white document to proofreaders and other departments to verify the accuracy of the info and to avoid them getting distracted by any other visual elements, thus the need for this script to quickly output a "plain text" proofreading document.

Also, I recreated the file at home on CS6, whereas we use CC2017 at work. Not sure if anything in AI scripting changed between the two.


Thanks for the test file.

Like this?

#target illustrator

(function () {

   

    var docRef = app.activeDocument,

        myLayers = docRef.layers,

        layer = app.activeDocument.activeLayer,

        flatBlack = new CMYKColor(),

        ln = 'SOURCE',

        nln = ln + ' APPROVAL',

        ol = docRef.layers.getByName(ln),

        nl = docRef.layers.add(),

        pathItem,

        i,

        max;

   

    function isContainedInApprovalLayer(target) {

        if (target.parent.typename === "Document") {

            if (target.name === nln) {

                return true;

            }

            return false;

        }

        return isContainedInApprovalLayer(target.parent);

    }

   

    nl.name = nln;

    flatBlack.black = 100;

   

    nl.move(ol, ElementPlacement.PLACEAFTER);

   

    for (i = ol.pageItems.length - 1; i >= 0; i -= 1) {

        ol.pageItems.duplicate(nl, ElementPlacement.INSIDE);

    }

   

    for (i = 0, max = myLayers.length; i < max; i += 1) {

        myLayers.locked = true;

    }

   

    nl.locked = false;

   

    for (i = 0, max = myLayers.length; i < max; i += 1) {

        myLayers.visible = false;

    }

   

    nl.visible = true;

   

    docRef.selection = null;

   

    for (i = 0, max = nl.symbolItems.length; i < max; i += 1) {

        nl.symbolItems.selected = true;

    }

   

    // expand symbol item.

    app.executeMenuCommand('Expand3');

   

    app.executeMenuCommand('selectall');

    app.executeMenuCommand('outline');

   

    docRef.selection = null;

   

    for (i = 0, max = nl.groupItems.length; i < max; i += 1) {

        nl.groupItems.selected = true;

    }

   

    // Register action to "Clear Appearance" only in advance.

    // ("Clear Appearance" in the menu of Appearance panel)

    app.doScript("myAction", "myActionSet");

   

    for (i = 0, max = docRef.pathItems.length; i < max; i += 1) {

        pathItem = docRef.pathItems;

       

        if (isContainedInApprovalLayer(pathItem) && pathItem.locked === false && pathItem.hidden === false) {

            if (pathItem.filled === true) {

                pathItem.fillColor = flatBlack;

            }

            if (pathItem.stroked === true) {

                pathItem.stroked = false;

            }

        }

    }

   

    nl.locked = true;

   

}());