Skip to main content
Inspiring
August 13, 2013
Answered

Error 21 (Changing color on text)

  • August 13, 2013
  • 1 reply
  • 5198 views

http://forums.adobe.com/message/5580527#5580527

Carlos wrote a script in response to the above thread. It changes CMYK black, and grayscale black to a swatch called "spot black". It's awesome, but it's only aimed at paths. I've made some adjustments to prevent it from effecting white and unpainted objects. I'm going to need it to work on text and gradients. Right now I am working on text.

I've tried to use the same logic that works on the paths on text, but I'm missing something. Help help.

This is the latest working version, it does not effect text or gradients.

// script.name = cmykBlackNgrayscaleToSpotBlack.jsx;

// script.description = changes art color from standard CMYK Black and Grayscale tones to an EXISTING Spot swatch named "spot black";

// script.requirements = an opened document;

// script.parent = CarlosCanto // 08/08/13;

// script.elegant = false;

// reference http://forums.adobe.com/thread/1267562?tstart=0

// Note: color values get rounded to the nearest integer, to avoid values like black = 99.99999999999999

//            Hidden and/or Locked Objects will be ignored, as well as objects in Hidden and/or Locked Layers

#target Illustrator

var idoc = app.activeDocument;

var pi = idoc.pathItems;

var sw = idoc.swatches["spot black"];

var fcounter = 0;

var scounter = 0;

for (j=0; j<pi.length; j++) {

    var ipath = pi;

    if (ipath.layer.visible==true && ipath.layer.locked==false && ipath.hidden==false && ipath.locked==false) {

        var fillColor = ipath.fillColor;

        if (fillColor.typename == "CMYKColor") {

            if (isColorBlack (fillColor)) {

                var fillk = Math.round(fillColor.black);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        else if (fillColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (fillColor)) {

                var fillk = Math.round(fillColor.gray);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        var strokeColor = ipath.strokeColor;

        if (strokeColor.typename == "CMYKColor") {

            if (isColorBlack (strokeColor)) {

                var strokek = Math.round(strokeColor.black);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

        else if (strokeColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (strokeColor)) {

                var strokek = Math.round(strokeColor.gray);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

    }

}

alert(fcounter + ' Fill(s) & ' + scounter + ' stroke(s) processed');

function cmykBlackToSpot (path, fill, stroke, k) {

    if (fill) {

        path.fillColor = sw.color;

        path.fillColor.tint = k;

    }

    if (stroke) {

        path.strokeColor = sw.color;

        path.strokeColor.tint = k;

    }

}

function isColorBlack (cmykColor) {

    var c = Math.round(cmykColor.cyan);

    var m = Math.round(cmykColor.magenta);

    var y = Math.round(cmykColor.yellow);

    var k = Math.round(cmykColor.black);

    if (c==0 && m==0 && y==0 && k != 0)

        return true

    else

        return false

}

function grayNotWhiteOrClear (GrayColor) {

    var pct = Math.round(GrayColor.gray);

    if (pct != 0)

        return true

    else

        return false

}

This is the version I'm working on now where I'm trying to include the text.

// script.name = cmykBlackNgrayscaleToSpotBlack.jsx;

// script.description = changes art color from standard CMYK Black and Grayscale tones to an EXISTING Spot swatch named "spot black";

// script.requirements = an opened document;

// script.parent = CarlosCanto // 08/08/13;

// script.elegant = false;

// reference http://forums.adobe.com/thread/1267562?tstart=0

// Note: color values get rounded to the nearest integer, to avoid values like black = 99.99999999999999

//            Hidden and/or Locked Objects will be ignored, as well as objects in Hidden and/or Locked Layers

#target Illustrator

var idoc = app.activeDocument;

var pi = idoc.pathItems;

var sw = idoc.swatches["spot black"];

var ch = idoc.textFrames[0].characters[0];

var fcounter = 0;

var scounter = 0;

for (j=0; j<pi.length; j++) {

    var ipath = pi;

    if (ipath.layer.visible==true && ipath.layer.locked==false && ipath.hidden==false && ipath.locked==false) {

        var fillColor = ipath.fillColor;

        if (fillColor.typename == "CMYKColor") {

            if (isColorBlack (fillColor)) {

                var fillk = Math.round(fillColor.black);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        else if (fillColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (fillColor)) {

                var fillk = Math.round(fillColor.gray);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        var strokeColor = ipath.strokeColor;

        if (strokeColor.typename == "CMYKColor") {

            if (isColorBlack (strokeColor)) {

                var strokek = Math.round(strokeColor.black);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

        else if (strokeColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (strokeColor)) {

                var strokek = Math.round(strokeColor.gray);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

    }

}

for (t=0; t<ch.length; t++) {

    var txt = ch;

    if (txt.layer.visible==true && txt.layer.locked==false && txt.hidden==false && txt.locked==false) {

        var fillColor = txt.fillColor;

        if (fillColor.typename == "CMYKColor") {

            if (isColorBlack (fillColor)) {

                var fillk = Math.round(fillColor.black);

                cmykBlackToSpot (txt, true, false, fillk);

                fcounter++;

            }

        }

        else if (fillColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (fillColor)) {

                var fillk = Math.round(fillColor.gray);

                cmykBlackToSpot (txt, true, false, fillk);

                fcounter++;

            }

        }

        var strokeColor = txt.strokeColor;

        if (strokeColor.typename == "CMYKColor") {

            if (isColorBlack (strokeColor)) {

                var strokek = Math.round(strokeColor.black);

                cmykBlackToSpot (txt, false, true, strokek);

                scounter++;

            }

        }

        else if (strokeColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (strokeColor)) {

                var strokek = Math.round(strokeColor.gray);

                cmykBlackToSpot (txt, false, true, strokek);

                scounter++;

            }

        }

    }

}

alert(fcounter + ' Fill(s) & ' + scounter + ' stroke(s) processed');

function cmykBlackToSpot (path, fill, stroke, k) {

    if (fill) {

        path.fillColor = sw.color;

        path.fillColor.tint = k;

    }

    if (stroke) {

        path.strokeColor = sw.color;

        path.strokeColor.tint = k;

    }

}

function isColorBlack (cmykColor) {

    var c = Math.round(cmykColor.cyan);

    var m = Math.round(cmykColor.magenta);

    var y = Math.round(cmykColor.yellow);

    var k = Math.round(cmykColor.black);

    if (c==0 && m==0 && y==0 && k != 0)

        return true

    else

        return false

}

function grayNotWhiteOrClear (GrayColor) {

    var pct = Math.round(GrayColor.gray);

    if (pct != 0)

        return true

    else

        return false

}

Here is a test file

https://docs.google.com/file/d/0BzEoJSYDhH_WdENjc092SF9GN0U/edit?usp=sharing

Thanks for playing.

This topic has been closed for replies.
Correct answer elDudereno

it just dawned on me, even though the "layer" property is not listed in the text frame properties, a text frame is still a subset of the "super class" pageItem...so

for page items we have

if (ipath.layer.visible==true && ipath.layer.locked==false && ipath.hidden==false && ipath.locked==false) {

for text, do the same

if (iTxtFrm.layer.visible==true && iTxtFrm.layer.locked==false && iTxtFrm.hidden==false && iTxtFrm.locked==false) {

and forget about meeting the parents


Carlos, you are right about that. I had a logic knot that was preventing it from working on text in groups AND directly on layers at the same time. I ended up using a version that didn't use your fix, even though it was viable.

Here is my final script. Works like a charm. Thanks for all the help.

// script.name = BlackToSpotBlack.jsx;

// script.description = changes art color from standard CMYK Black and Grayscale tones to a Spot swatch named "spot black";

// script.requirements = an opened document;

// script.parent = CarlosCanto // 08/08/13;

// script.elegant = false;

// reference http://forums.adobe.com/thread/1267562?tstart=0 && http://forums.adobe.com/message/5610447#5610447

// Note: color values get rounded to the nearest integer, to avoid values like black = 99.99999999999999

//              Hidden and/or Locked Objects will be ignored, as well as objects in Hidden and/or Locked Layers

#target Illustrator

var idoc = app.activeDocument;

var pi = idoc.pathItems;

var tf = idoc.textFrames;

createSpotBlack();

var sw = idoc.swatches["spot black"];

var fcounter = 0;

var scounter = 0;

var gcounter = 0;

//apply spot to paths and gradient stops

for (j=0; j<pi.length; j++) {

    var ipath = pi;

    if (ipath.layer.visible==true && ipath.layer.locked==false && ipath.hidden==false && ipath.locked==false) {

        var fillColor = ipath.fillColor;

        if (fillColor.typename == "CMYKColor") {

            if (isColorBlack (fillColor)) {

                var fillk = Math.round(fillColor.black);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        else if (fillColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (fillColor)) {

                var fillk = Math.round(fillColor.gray);

                cmykBlackToSpot (ipath, true, false, fillk);

                fcounter++;

            }

        }

        else if (fillColor.typename == "GradientColor") {

            var stops = ipath.fillColor.gradient.gradientStops;

            for (s=0; s<stops.length; s++) {

                var iStop = stops;

                var stopColor = iStop.color;

                if (stopColor.typename == "CMYKColor") {

                    if (isColorBlack (stopColor)) {

                        var stopk = Math.round(stopColor.black);

                        iStop.color = sw.color;

                        iStop.color.tint = stopk;

                        gcounter++;

                    }

                }

                if (stopColor.typename == "GrayColor") {

                    if (grayNotWhiteOrClear (stopColor)) {

                        var stopk = Math.round(stopColor.gray);

                        iStop.color = sw.color;

                        iStop.color.tint = stopk;

                        gcounter++;

                    }

                }

            }

        }

        var strokeColor = ipath.strokeColor;

        if (strokeColor.typename == "CMYKColor") {

            if (isColorBlack (strokeColor)) {

                var strokek = Math.round(strokeColor.black);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

        else if (strokeColor.typename == "GrayColor") {

            if (grayNotWhiteOrClear (strokeColor)) {

                var strokek = Math.round(strokeColor.gray);

                cmykBlackToSpot (ipath, false, true, strokek);

                scounter++;

            }

        }

        else if (strokeColor.typename == "GradientColor") {

            var stops = ipath.strokeColor.gradient.gradientStops;

            for (s=0; s<stops.length; s++) {

                var iStop = stops;

                var stopColor = iStop.color;

                if (stopColor.typename == "CMYKColor") {

                    if (isColorBlack (stopColor)) {

                        var stopk = Math.round(stopColor.black);

                        iStop.color = sw.color;

                        iStop.color.tint = stopk;

                        gcounter++;

                    }

                }

                if (stopColor.typename == "GrayColor") {

                    if (grayNotWhiteOrClear (stopColor)) {

                        var stopk = Math.round(stopColor.gray);

                        iStop.color = sw.color;

                        iStop.color.tint = stopk;

                        gcounter++;

                    }

                }

            }

        }

    }

}

// choose text and change

for (t=0; t<tf.length; t++) {

    var iTxtFrm = tf;

    if (iTxtFrm.locked==false && iTxtFrm.hidden==false) {

        if (meetTheParents(iTxtFrm) == "isLayerFree"){

            if (isLayerFree(iTxtFrm.parent)){

                changeText(iTxtFrm)

            } else {

                if (isGroupFree(iTxtFrm)){

                changeText(iTxtFrm)

                }

            }

        }

    }

}

alert(fcounter + ' Fill(s), ' + scounter + ' stroke(s) & ' + gcounter + ' Gradient Stop(s) processed.');

function meetTheParents(textFrame){

    if (textFrame.parent.typename = "Layer"){

        return "isLayerFree";

    } else if (textFrame.parent.typename = "GroupItem"){

        return "isGroupFree";

    }

}

function isGroupFree(groupItem){

    if (groupItem.parent.hidden==false && groupItem.parent.editable==true){

        if (groupItem.parent.typename == "Layer"){

            var greatgpa = groupItem.parent;

            isLayerFree(greatgpa);

        }else if (groupItem.parent.typename = "GroupItem"){

            var gpa = groupItem.parent;

            if (isGroupFree(gpa));

            return true

            } else {

            return false

        }

    }

}

function isLayerFree(layer){

    if (layer.locked == false && layer.visible == true){

        var gpa = layer.parent;

        isLayerFree(gpa);

        return true

        } else {

        return false

    }

}

// actually changes text

function changeText(textFrame){

    var chars = textFrame.characters;

    for (c=0; c<chars.length; c++) {

        var ltr = chars;

        if (ltr.characterAttributes.fillColor.typename == "CMYKColor"){

            if (isColorBlack (ltr.characterAttributes.fillColor)) {

                var fillk = Math.round(ltr.characterAttributes.fillColor.black);

                cmykBlackToSpot (ltr, true, false, fillk);

                fcounter++;

            }

        }

        if (ltr.characterAttributes.fillColor.typename == "GrayColor"){

            if (grayNotWhiteOrClear (ltr.characterAttributes.fillColor)) {

                var fillk = Math.round(ltr.characterAttributes.fillColor.gray);

                cmykBlackToSpot (ltr, true, false, fillk);

                fcounter++;

            }

        }

        if (ltr.characterAttributes.strokeColor.typename == "CMYKColor"){

            if (isColorBlack (ltr.characterAttributes.strokeColor)) {

                var strokek = Math.round(ltr.characterAttributes.strokeColor.black);

                cmykBlackToSpot (ltr, false, true, strokek);

                scounter++;

            }

        }

        if (ltr.characterAttributes.strokeColor.typename == "GrayColor"){

            if (grayNotWhiteOrClear (ltr.characterAttributes.strokeColor)) {

                var strokek = Math.round(ltr.characterAttributes.strokeColor.gray);

                cmykBlackToSpot (ltr, false, true, strokek);

                scounter++;

            }

        }

    }

};

function cmykBlackToSpot (path, fill, stroke, k) {

    if (fill) {

        path.fillColor = sw.color;

        path.fillColor.tint = k;

    }

    if (stroke) {

        path.strokeColor = sw.color;

        path.strokeColor.tint = k;

    }

}

function isColorBlack (cmykColor) {

    var c = Math.round(cmykColor.cyan);

    var m = Math.round(cmykColor.magenta);

    var y = Math.round(cmykColor.yellow);

    var k = Math.round(cmykColor.black);

    if (c==0 && m==0 && y==0 && k != 0)

        return true

    else

        return false

}

function grayNotWhiteOrClear (GrayColor) {

    var pct = Math.round(GrayColor.gray);

    if (pct != 0)

        return true

    else

        return false

}

function createSpotBlack(){

    if (!doesColorExist("spot black")){

        // Create CMYKColor

        var cmykColor = new CMYKColor();

        cmykColor.cyan = 9;

        cmykColor.magenta = 9;

        cmykColor.yellow = 9;

        cmykColor.black = 96;

        // Create Spot

        var spot = idoc.spots.add();

        spot.color = cmykColor;

        spot.colorType = ColorModel.SPOT;

        spot.name = "spot black";

    }

}

function doesColorExist(){

    var clrs = idoc.swatches;

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

        if (clrs.name=="spot black"){

            return true;

        }

    }

    return false;

}

1 reply

Inspiring
August 13, 2013

I doubt you are going to be able to utilize the same syntax for your differing items… Anyhows…

var pi = idoc.pathItems; // Carlos sets variable to a collection…

var ch = idoc.textFrames[0].characters[0]; // Here your variable is to a single character… I doubt this can be tested for locked or hidden…

var ch = idoc.textFrames; // Will give you something to loop thru but you will need to dig deeper still as every character can be different…

Personally I would go for stories when looking thru text…

Inspiring
August 13, 2013

So...

var ch = idoc.stories[0].textRanges[0].CharacterAttributes;

I'm looking in "Adobe IllustratorCS5 Scripting Reference: JavaScript" on page 226 (textRange) and I'm not seeing locked, hidden, or layers as textRange properties. So I'm guessing I can't test for them for stories either.

My scripting powers mostly consist of looking at an example, deciphering it, and applying what I need to make it work in my instance. Where could I go to find an example of a script that changes the fill and stroke of cmyk and grayscale text that isn't locked or hidden?

I'm pretty ignorant at all of this, so please bear with me.

P.S. If I didn't care if locked or hidden text was changed could I use idoc.textFrames[0].characters[0];  ?

CarlosCanto
Community Expert
Community Expert
August 14, 2013

if you don't care checking for Locked or Hidden, then you can skip that, only you'll get an error if a text frame is locked or hidden.

in short you need to loop through all text frames and within each, you have to loop through all characters, once you are at the character level, you can get its characterAttributes property and finally check for fillColor/strokeColor

if you do want to check for lock/hidden then you do that at the textFrame level

...note that textFrames don't have "layer" property...so, it complicates things, to determine if the layer it belongs to is locked or hidden, you have to check its parent...problem is, it can have parent, grand parent, great grand parent...