Skip to main content
wckdtall
Inspiring
September 9, 2014
Answered

How do I find the font for a specific character in a textItem?

  • September 9, 2014
  • 4 replies
  • 2440 views

I'm writing a script that builds a font list for an open document. While I could have lookup the fonts for the file as a whole, my goal is to iterate over specific layerSets to build a font list from. The issue I'm facing, is that referencing:

app.fonts[text.textItem.font].name

Only pulls the font name of the first character of the textItem. I need to get the names of all the fonts in the textItem, and while I can successfully loop through each of the letters, they do not have the character attributes associated with them.

I tried this: app.fonts[text.textItem.contents.font].name

As well as many iterations of a similar idea, and I cannot get it to pull the font name, as it's not an attribute of each character. I apologize if this is a remedial question, but I'm a bit of a novice with javascript in Adobe programs.

For an example of what I'm trying to acheive, I was easily able to do this in illustrator, by using the following statement:

fontName = text.characters.characterAttributes.textFont.name;

When placed in a loop, this goes through each font in the text Layer.

This topic has been closed for replies.
Correct answer c.pfaffenbichler

Found some code I had assembled previously:

// get keys for type layer’s style;

// based on code by michael l hale;

// 2014, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

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

var ref = new ActionReference();

ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var layerDesc = executeActionGet(ref);

var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));

var paragraphStyle = textDesc.getList(stringIDToTypeID('paragraphStyleRange'));

var kernRange = textDesc.getList(stringIDToTypeID('kerningRange'));

var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));

var theFonts = new Array;

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

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

var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'));

// check if font is already in array;

var theCheck = true;

for (var n = 0; n < theFonts.length; n++) {

if (theFonts == aFont) {theCheck = false}

};

if (theCheck  == true) {theFonts.push(aFont)}

};

alert (theFonts.join("\n"));

}

};

4 replies

wckdtall
wckdtallAuthor
Inspiring
September 30, 2014

I can't quite figure out the try for this, I've wrapped this in a few ifs as well, which as my knowledge of PS scripting, and Javascript isn't vast at this point, may seem like terrible ideas, but that's how I learn!

        try{styleDesc.getObjectValue(stringIDToTypeID('fontPostScriptName')) != undefined}
        catch(e){
            var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'));
        }

Below are additional statements I tried, but I'm sure they don't follow the correct syntax:

try{styleDesc.getByName('fontPostScriptName')}

try{fontPostScriptName in styleDesc}

try{styleDesc.getString(stringIDToTypeID('fontPostScriptName')))

try{styleDesc.hasOwnProperty('fontPostScriptName'}

As well as a few others, but nothing work, a few returned false for each fi

I was also encountering the following error:

I can send the file with the error in it if needed, but I'm a bit stumped at this point. Even searching for error #8500, wasn't doing me any good.

c.pfaffenbichler
Community Expert
Community Expert
September 30, 2014

try {var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'))}

catch (e) {var aFont = /* insert your default font here */}

wckdtall
wckdtallAuthor
Inspiring
October 1, 2014

Then I don’t understand what the issue is, could you post the code?


It got rid of my formatting, so it's a little harder to read, but fairly straightforward. Basically the parent for loop finds layers within the layerSet 'quoteLayer'. This is successfully grabbing contents for each text item, and pushing them to an array. Where I'm looking for more info, is how to tell the actionReference to get quoteLayer as it's target, instead of the active Layer. Is it as simple as changing one of the values within ref.putEnumerated to charIDToTypeID(quoteLayer)?

for(n=0; n<quoteLayer.length; n++){
    if(quoteLayer.kind == LayerKind.TEXT) {
        quoteLineContents = quoteLayer.textItem.contents;
        arrayPush('quoteUsed',quoteLineContents)
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
        var layerDesc = executeActionGet(ref);
        var textDesc = layerDesc.getObjectValue((stringIDToTypeID('textKey'));
        var paragraphStyle = textDesc.getList(stringIDToTypeID('paragraphStyleRange'));
        var kernRange = textDesc.getList(stringIDToTypeID('kerningRange'));
        var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));
        for (var m = 0; m < rangeList.count; m++) {
            var styleDesc = rangeList.getObjectValue(m).getObjectValue(stringIDToTypeID('textStyle'));
            try {fontName = styleDesc.getString(stringIDToTypeID('fontPostScriptName'))}
            catch (e) {fontName = "Error: Reformat text objects and try again"}  
            arrayPush ('fontsUsed',fontName);
        }
    }
wckdtall
wckdtallAuthor
Inspiring
September 14, 2014

Great script! Tested it and it works like a charm! It did not however work at first. I tried editing it, but it turned out it was a fluke and that for some reason the text layer just simply didn't save the "fontPostScriptName", and the script kept breaking here: var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'));

But after changing the font back to itself, it worked just fine. Strangely enough the font is just myriad pro.

c.pfaffenbichler
Community Expert
Community Expert
September 14, 2014

Uh-oh … hadn’t thought of that and in my test it did not occur.

It’s been a while since I tried handling fonts in Photoshop Scripts but I think I saw something similar with leading – the default value does not return anything and therefore cause an error unless it has been changed at least once.

You may want to wrap that line in a try-clause and if it errors return the default case.

c.pfaffenbichler
Community Expert
c.pfaffenbichlerCommunity ExpertCorrect answer
Community Expert
September 9, 2014

Found some code I had assembled previously:

// get keys for type layer’s style;

// based on code by michael l hale;

// 2014, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

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

var ref = new ActionReference();

ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var layerDesc = executeActionGet(ref);

var textDesc = layerDesc.getObjectValue(stringIDToTypeID('textKey'));

var paragraphStyle = textDesc.getList(stringIDToTypeID('paragraphStyleRange'));

var kernRange = textDesc.getList(stringIDToTypeID('kerningRange'));

var rangeList = textDesc.getList(stringIDToTypeID('textStyleRange'));

var theFonts = new Array;

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

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

var aFont = styleDesc.getString(stringIDToTypeID('fontPostScriptName'));

// check if font is already in array;

var theCheck = true;

for (var n = 0; n < theFonts.length; n++) {

if (theFonts == aFont) {theCheck = false}

};

if (theCheck  == true) {theFonts.push(aFont)}

};

alert (theFonts.join("\n"));

}

};

wckdtall
wckdtallAuthor
Inspiring
September 9, 2014

Thanks for this! I'll check it out. Good to know that there is full functionality like this, wish it wasn't hidden within a subset of code. Thanks also for the tip about the scripting listener! I've got to start reading web pages from top to bottom, rather than just searching the text for what I need.

c.pfaffenbichler
Community Expert
Community Expert
September 9, 2014

In Photoshop you need to use Action Manager code for this (like one can record with ScriptingListener.plugin).