Skip to main content
aidanc96140468
Participant
July 5, 2019
Frage

Any way to check/change font in a portion of a TextItem?

  • July 5, 2019
  • 2 Antworten
  • 2112 Ansichten

Hello! I have been working with scripts that modify existing Text Items within PSDs. In some cases, there are Text Items that have more than one font in them. I would like to be able to isolate the portion of the string that is in a different font so that it can be changed. The desired result would be taking something like this:

"Here is some text"

to this:

"Here is some text"

So far I can isolate the font used for the first character in the string of the Text Item, and changing the font associated with the text item changes the font for every character. Is it possible to change only the font that is different, assuming that I know the postscript names of the fonts in question?

Thanks for any help!

Dieses Thema wurde für Antworten geschlossen.

2 Antworten

microbians
Known Participant
January 26, 2021
// USED AS


setFormatting(theHash, {
    from:3,
    to:9,
    fontName: "Helvetica",
    fontStyleName: "Light"
});

setFormatting(theHash, {
    from:11,
    to:13,
    impliedFontSize: 120,
});

// FUCNTIONS 

function setFormatting(activeLayer, style) {

    if (activeLayer.kind == LayerKind.TEXT) {

        defaultStyleList = getFormatting(activeLayer);
        app.activeDocument.activeLayer = activeLayer

        // NEW SET
        var idset               = stringIDToTypeID("set")
        var idtextStyleRange    = stringIDToTypeID("textStyleRange");
        var idtextStyle         = stringIDToTypeID("textStyle");
        var idfrom              = stringIDToTypeID("from");
        var idto                = stringIDToTypeID("to");
        var pnt                 = stringIDToTypeID("pointsUnit");

        var maxTextLength       = activeLayer.textItem.contents.length;

        // Look at every styled part of the current text
        for(var p=0; p<defaultStyleList.length; p++) {

            // TEXT RANGE
            style.from = style.from || 0;
            style.to   = style.to || maxTextLength;

            var defaultStyle = defaultStyleList[p];

            // if the old range is out the current pass it
            if (defaultStyle.from>style.to || defaultStyle.to<style.from) continue;

            // if the old range iintersect the current, it claps
            if (defaultStyle.to<style.to) style.to=defaultStyle.to;
            if (defaultStyle.from>style.from) style.from=defaultStyle.from;

            // MAIN ACTION LIST
            var action = new ActionDescriptor();

            // DEF TO THE LAYER ??
            var reference = new ActionReference();
            reference.putEnumerated( stringIDToTypeID("textLayer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum") );
            action.putReference( stringIDToTypeID("null"), reference );

            // TEXT ACTION
            var textAction = new ActionDescriptor();

            // ACTION LIST
            var textList = new ActionList();

            // TEXT RANGE
            var textStyleRange = new ActionDescriptor();
            textStyleRange.putInteger( idfrom, style.from );
            textStyleRange.putInteger( idto, style.to );

            // TEXT STYLE
            var textStyle = new ActionDescriptor();

            textStyle.putBoolean( stringIDToTypeID("styleSheetHasParent"), true );

            // FONT
            if (style.fontPostScriptName) {
                textStyle.putString( stringIDToTypeID("fontPostScriptName"), style.fontPostScriptName || defaultStyle.fontPostScriptName );
            } else {
                textStyle.putString( stringIDToTypeID("fontName"), style.fontName || defaultStyle.fontName );
                textStyle.putString( stringIDToTypeID("fontStyleName"), style.fontStyleName || defaultStyle.fontStyleName );
            }

            if (style.scaleFactor==undefined) {
                var layerDescription = executeActionGet(reference);
                var textDecripcion = layerDescription.getObjectValue(stringIDToTypeID('textKey'));
                var scaleFactor=1;
                if (textDecripcion.hasKey(stringIDToTypeID('transform'))) {
                    style.scaleFactor = textDecripcion.getObjectValue(stringIDToTypeID('transform')).getUnitDoubleValue(stringIDToTypeID("yy"));
                }
            }

            // FONT SIZE
            textStyle.putUnitDouble( stringIDToTypeID("size"), pnt, style.size || defaultStyle.size);
            textStyle.putUnitDouble( stringIDToTypeID("impliedFontSize"), pnt, style.impliedFontSize || defaultStyle.impliedFontSize );

            // TEXT SCALE
            style.horizontalScale!=undefined &&    textStyle.putDouble( stringIDToTypeID("horizontalScale"), style.horizontalScale || 100.000000 );
            style.verticalScale!=undefined &&      textStyle.putDouble( stringIDToTypeID("verticalScale"), style.verticalScale || 100.000000 );

            style.syntheticBold!=undefined &&      textStyle.putBoolean( stringIDToTypeID("syntheticBold"), style.syntheticBold || false );
            style.syntheticItalic!=undefined &&    textStyle.putBoolean( stringIDToTypeID("syntheticItalic"), style.syntheticItalic || false  );

            // FONT LEADING
            if (style.leading!=undefined) {
                if (style.leading!="") {
                    textStyle.putBoolean( stringIDToTypeID("autoLeading"), false ); // Force false to put own leading size
                    textStyle.putUnitDouble( stringIDToTypeID("leading"), pnt, style.leading );
                    textStyle.putUnitDouble( stringIDToTypeID("impliedLeading"), pnt, style.impliedLeading );
                } else {
                    textStyle.putBoolean( stringIDToTypeID("autoLeading"), true );
                }
            }

            // FONT TRACKING
            textStyle.putInteger( stringIDToTypeID("tracking"), style.tracking || defaultStyle.tracking || 0  );

            // BASELINE SHIFT
            style.baselineShift!=undefined &&          textStyle.putUnitDouble( stringIDToTypeID("baselineShift"), pnt, style.baselineShift || 0 );
            style.impliedBaselineShift!=undefined &&   textStyle.putUnitDouble( stringIDToTypeID("impliedBaselineShift"), pnt, style.impliedBaselineShift || 0 );

            // FONT CAPS
            if (style.fontCaps!=undefined) {
                var idfontCaps = stringIDToTypeID("fontCaps");
                var idTypeOfCaps = stringIDToTypeID( style.fontCaps || "normal"); // normal, allCaps, smallCaps
                textStyle.putEnumerated( idfontCaps, idfontCaps, idTypeOfCaps );
            }

            // BASELINE
            if (style.baseline!=undefined) {
                var idTypeOfBaseline = stringIDToTypeID( style.baseline || "normal"); // normal, superScript, subScript
                textStyle.putEnumerated( stringIDToTypeID("baseline"), stringIDToTypeID("baseline"), idTypeOfBaseline );
            }

            // STRIKE
            if (style.strikethrough!=undefined) {
                var idstrikethrough = stringIDToTypeID("strikethrough");
                if (style.strikethrough == true) {
                    var idTypeOfStrikethrough = stringIDToTypeID("strikethrough");
                } else {
                    var idTypeOfStrikethrough = stringIDToTypeID("strikethroughOff");
                }
                textStyle.putEnumerated( idstrikethrough, idstrikethrough, idTypeOfStrikethrough );
            }

            // UNDERLINE
            if (style.underline!=undefined) {
                var idunderline = stringIDToTypeID("underline");
                if (style.underline == true) {
                    var idTypeOfUnderline = stringIDToTypeID("underlineOnLeftInVertical");
                } else {
                    var idTypeOfUnderline = stringIDToTypeID("underlineOff");
                }
                textStyle.putEnumerated( idunderline, idunderline, idTypeOfUnderline );
            }

            // KERNING
            if (style.autoKern!=undefined) {
                var idautoKern = stringIDToTypeID("autoKern");
                var idTypeOfAutoKern = stringIDToTypeID( style.autoKern || "opticalKern"); //opticalKern, metricsKern, manual (0)
                textStyle.putEnumerated( idautoKern, idautoKern, idTypeOfAutoKern );
            }

            // ITALICS
            style.italics!=undefined && textStyle.putBoolean( stringIDToTypeID("italics"), style.italics || false );

            // COLOR
            var colorAction = new ActionDescriptor();
            colorAction.putDouble(stringIDToTypeID("red"), style.color && style.color.rgb.red || defaultStyle.color.rgb.red );
            colorAction.putDouble(stringIDToTypeID("grain"), style.color && style.color.rgb.green || defaultStyle.color.rgb.green);
            colorAction.putDouble(stringIDToTypeID("blue"), style.color && style.color.rgb.blue || defaultStyle.color.rgb.blue);
            textStyle.putObject(stringIDToTypeID("color"), stringIDToTypeID("RGBColor"), colorAction);

            // SET THE STYLE ACTION
            textStyleRange.putObject( idtextStyle, idtextStyle, textStyle );
            textList.putObject( idtextStyleRange, textStyleRange );
            textAction.putList( idtextStyleRange, textList );
            action.putObject( idto, stringIDToTypeID("textLayer"), textAction );

            // EXECUTE THE ACTION
            executeAction( idset, action, DialogModes.NO );
        }
    }
}

// get fonts and other parameters used in type layer
function getFormatting(textLayer) {

    if (textLayer.kind == LayerKind.TEXT) {

        var textContent = textLayer.textItem.contents;

        var pnt = stringIDToTypeID("pointsUnit");

        app.activeDocument.activeLayer = textLayer;
        var reference = new ActionReference();

        reference.putEnumerated( stringIDToTypeID("textLayer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum") );
        var layerDesc = executeActionGet(reference);
        var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));
        var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));

        var styleByRanges = [];

        for (var m = 0; m < rangeList.count; m++) {

            var style={};

            var textStyle = rangeList.getObjectValue(m).getObjectValue(stringIDToTypeID('textStyle'));

            style.from  = rangeList.getObjectValue(m).getInteger(stringIDToTypeID('from'));
            style.to    = rangeList.getObjectValue(m).getInteger(stringIDToTypeID('to'));

            var scaleFactor=1;
            if (textDesc.hasKey(stringIDToTypeID('transform'))) {
                scaleFactor = textDesc.getObjectValue(stringIDToTypeID('transform')).getUnitDoubleValue(stringIDToTypeID("yy"));
            }

            style.scaleFactor = scaleFactor;

            style.fontPostScriptName =  textStyle.getString( stringIDToTypeID("fontPostScriptName") );
            style.fontName =            textStyle.getString( stringIDToTypeID("fontName") );
            style.fontStyleName =       textStyle.getString( stringIDToTypeID("fontStyleName") );

            style.size =                new UnitValue(textStyle.getUnitDoubleValue( stringIDToTypeID("size") ), pnt ).value;
            style.impliedFontSize =     new UnitValue(textStyle.getUnitDoubleValue( stringIDToTypeID("impliedFontSize") ), pnt ).value;

            textStyle.hasKey(stringIDToTypeID('horizontalScale'))   && style.horizontalScale = textStyle.getDouble( stringIDToTypeID("horizontalScale") );
            textStyle.hasKey(stringIDToTypeID('verticalScale'))     && style.verticalScale =   textStyle.getDouble( stringIDToTypeID("verticalScale") );

            textStyle.hasKey(stringIDToTypeID('syntheticBold'))     && style.syntheticBold =   textStyle.getBoolean( stringIDToTypeID("syntheticBold") );
            textStyle.hasKey(stringIDToTypeID('syntheticItalic'))   && style.syntheticItalic = textStyle.getBoolean( stringIDToTypeID("syntheticItalic") );

            textStyle.hasKey(stringIDToTypeID('autoLeading'))       && style.autoLeading =     textStyle.getBoolean( stringIDToTypeID("autoLeading") ); // Force false to put own leading size
            textStyle.hasKey(stringIDToTypeID('leading'))           && style.leading =         new UnitValue(textStyle.getUnitDoubleValue( stringIDToTypeID("leading") ), pnt ).value;
            textStyle.hasKey(stringIDToTypeID('impliedLeading'))    && style.impliedLeading =  new UnitValue(textStyle.getUnitDoubleValue( stringIDToTypeID("impliedLeading") ), pnt ).value;


            textStyle.hasKey(stringIDToTypeID('tracking'))          && style.tracking =        textStyle.getInteger( stringIDToTypeID("tracking") );

            // BASELINE SHIFT
            textStyle.hasKey(stringIDToTypeID('baselineShift'))         && style.baselineShift =       new UnitValue( textStyle.getUnitDoubleValue( stringIDToTypeID("baselineShift") ), pnt ).value;
            textStyle.hasKey(stringIDToTypeID('impliedBaselineShift'))  && style.impliedBaselineShift= new UnitValue( textStyle.getUnitDoubleValue( stringIDToTypeID("impliedBaselineShift") ), pnt ).value;


            textStyle.hasKey(stringIDToTypeID('fontCaps'))              && style.fontCaps =        typeIDToStringID( textStyle.getEnumerationValue( stringIDToTypeID("fontCaps") ) );
            textStyle.hasKey(stringIDToTypeID('baseline'))              && style.baseline =        typeIDToStringID( textStyle.getEnumerationValue( stringIDToTypeID("baseline") ) );
            textStyle.hasKey(stringIDToTypeID('strikethrough'))         && style.strikethrough =   typeIDToStringID( textStyle.getEnumerationValue( stringIDToTypeID("strikethrough") ) );
            textStyle.hasKey(stringIDToTypeID('underline'))             && style.underline =       typeIDToStringID( textStyle.getEnumerationValue( stringIDToTypeID("underline") ) );
            textStyle.hasKey(stringIDToTypeID('autoKern'))              && style.autoKern =        typeIDToStringID( textStyle.getEnumerationValue( stringIDToTypeID("autoKern") ) );

            textStyle.hasKey(stringIDToTypeID('italics'))               && style.italics =         textStyle.getBoolean( stringIDToTypeID("italics") );

            style.color =           getColorFromDescriptor( textStyle.getObjectValue( stringIDToTypeID("color") ), typeIDToCharID( textStyle.getClass(stringIDToTypeID("color") ) ));

            style.text =            textContent.substring(style.from, style.to);

            styleByRanges.push(style);

        }

        return styleByRanges;
    }
}
Participant
August 6, 2021

@microbians This is a great script thanks!  how do I set the color option when calling it.

GreenColor = new SolidColor();
GreenColor.rgb.red = 60;
GreenColor.rgb.green = 186;
GreenColor.rgb.blue = 84;

setFormatting(theHash, {
    from:11,
    to:13,
    color: GreenColor
});

Errors out with 

Error 24: getColorFromDescriptor is not a function.

Line: 265 -> style.color = getColorFromDescriptor( textStyle.getObjectValue( stringIDToTypeID("color") ), typeIDToCharID( textStyle.getClass(stringIDToTypeID("color") ) ));

Legend
July 23, 2019

Yes but it requires ActionScript rather than just ExtendScript.

#target photoshop

layerUpdate();

function setFormatting(start, end, fontName, fontStyle, fontSize){

    var idsetd = app.charIDToTypeID('setd');

    var action = new ActionDescriptor();

    var idnull = app.charIDToTypeID('null');

    var reference = new ActionReference();

    var idTxLr = app.charIDToTypeID('TxLr');

    var idOrdn = app.charIDToTypeID('Ordn');

    var idTrgt = app.charIDToTypeID('Trgt');

    reference.putEnumerated(idTxLr, idOrdn, idTrgt);

    action.putReference(idnull, reference);

    var idT = app.charIDToTypeID('T   ');

    var textAction = new ActionDescriptor();

    var idTxtt = app.charIDToTypeID('Txtt');

    var actionList = new ActionList();

    var textRange = new ActionDescriptor();

    var idFrom = app.charIDToTypeID('From');

    textRange.putInteger(idFrom, start);

    textRange.putInteger(idT, end);

    var idTxtS = app.charIDToTypeID('TxtS');

    var formatting = new ActionDescriptor();

    var idFntN = app.charIDToTypeID('FntN');

    formatting.putString(idFntN, fontName);

    var idFntS = app.charIDToTypeID('FntS');

    formatting.putString(idFntS, fontStyle);

    var idSz = app.charIDToTypeID('Sz  ');

    var idPnt = app.charIDToTypeID('#Pnt');

    formatting.putUnitDouble(idSz, idPnt, fontSize);

    textRange.putObject(idTxtS, idTxtS, formatting);

    actionList.putObject(idTxtt, textRange);

    textAction.putList(idTxtt, actionList);

    action.putObject(idT, idTxLr, textAction);

    app.executeAction(idsetd, action, DialogModes.NO);

    }

function layerUpdate(){

    if(documents.length > 0){

        var originalDialogMode = app.displayDialogs;

        app.displayDialogs = DialogModes.ERROR;

        var originalRulerUnits = preferences.rulerUnits;

        var j = 0;

        try{

            var docRef = activeDocument;

            preferences.rulerUnits = Units.POINTS;

            var m = 0;

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

                var LayerRef = docRef.artLayers;

                if(LayerRef.kind == LayerKind.TEXT){

                    var TextRef = LayerRef.textItem;

                    TextRef.textComposer = TextComposer.ADOBESINGLELINE;

                    var layerText = TextRef.contents;

                    var newText = layerText.replace('A', 'B');

                    if(newText != layerText){

                        j = i;

                        TextRef.contents = newText;

                        if(TextRef.size == 96){

                            TextRef.size = 42;

                            TextRef.font = 'Calibri';

                            TextRef.useAutoLeading = false;

                            TextRef.leading = 42;

                            var l = TextRef.contents.split(/\r/);

                            docRef.activeLayer = LayerRef;

                            setFormatting(0, l[0].length, 'Calibri', 'Bold', 96);

                            preferences.rulerUnits = Units.PIXELS;

                            if(TextRef.kind == TextType.PARAGRAPHTEXT){

                                TextRef.height = 220;

                                TextRef.width = 460;

                                }

                            preferences.rulerUnits = Units.POINTS;

                            break;

                            }

                        }

            }

        catch(e){

            alert(e + '  ' + e.line);

            preferences.rulerUnits = originalRulerUnits;

            app.displayDialogs = originalDialogMode;

            return;

            }

        preferences.rulerUnits = originalRulerUnits;

        app.displayDialogs = originalDialogMode;

        }

    else{

        alert('You must have a document open to run this script.');

        return;

        }

    }

This is an edited production script I use, it should get you started.

aidanc96140468
Participant
July 25, 2019

Thank you so much! I'll dig in with that.

Legend
July 25, 2019

Once you can isolate the part of your text to format (I do a split on the return character) its just a matter of calling the setFormatting function and passing your settings.