Copy link to clipboard
Copied
Hi, as part of a larger script I'm tryng to capture a list of missing document fonts for InDesign2022.
I have what I think should work, something like this:
var doc = app.activeDocument;
var missingfonts = [];
for (var i=0; i < doc.fonts.length; i++) {
var doc_fontname = doc.fonts.item(i).name;
// var doc_fontname = doc.fonts[i].name; // <- alt def. of above line
var fontStatus = app.fonts.itemByName(doc_fontname).status.toString();
if (fontStatus == "NOT_AVAILABLE") {
missingfonts.push(doc_fontname);
}
}
$.writeln(missingfonts);
However: either way I define doc_fontname above, its value includes a repeat of the variant name after the fontname, eg: "Minion Pro ItalicItalic"; for every font except the font that is actually missing (which shows correctly, "Bodoni 72 Italic". Because of this, the names being wrong, all items show up as NOT_AVAILABLE.
I've seen this font.name issue in two other discussions, but not resolved, here and here.
Regardless, I'm really just looking for a way to get names of missing document fonts, so am open to other methods. Thank you!
Copy link to clipboard
Copied
Hi @Matt276783077obu ,
to see the value of status of a font you could ask directly when you are looping all fonts of a document. For example:
if( doc.fonts[i].status == FontStatus.NOT_AVAILABLE )
{
// do something
};
See: https://www.indesignjs.de/extendscriptAPI/indesign-latest/#FontStatus.html
Regards,
Uwe Laubender
( Adobe Community Expert )
Copy link to clipboard
Copied
Hi @Matt276783077obu, I did a quick poke around and I can confirm the exact same weirdness with font style names doubling. And, in general, I found working with the Font objects quite slippery, probably because of the name doubling bug causing invalid object references.
Anyway, have a look at this little script and see if it helps. I honestly don't know if it will. In my test document one of my "missing" fonts was actually marked as "SUBSTITUTED" (even though the app.font of the same name was "INSTALLED", not missing!) so I've included that status here.
- Mark
var doc = app.activeDocument;
var missingfonts = [];
for (var i = 0; i < doc.fonts.length; i++) {
if (
doc.fonts[i].status === FontStatus.NOT_AVAILABLE
|| doc.fonts[i].status === FontStatus.SUBSTITUTED
) {
missingfonts.push(getSensibleFontName(app.fonts.itemByName(doc.fonts.item(i).name)));
}
}
// this part just to test that the names work
for (var i = 0; i < missingfonts.length; i++) {
var font = app.fonts.itemByName(missingfonts[i]);
$.write('"' + font.name + '"');
$.writeln(' (' + String(font.status) + ')');
}
function getSensibleFontName(font) {
var sensibleName = font.fontFamily,
name = font.name,
delimiter = '\t',
styleName = name.split(delimiter)[1],
hasBadDoubleStyleName = styleName.slice(0, styleName.length / 2) == styleName.slice(styleName.length / 2);
if (hasBadDoubleStyleName)
sensibleName += delimiter + styleName.slice(0, styleName.length / 2);
else
sensibleName += delimiter + styleName;
return sensibleName;
};
Copy link to clipboard
Copied
Hi Mark,
a font listed under app could be indeed flagged as INSTALLED with status.
And at the same time it could be SUBSTITUTED when seen from the perspective a document has on fonts.
How can you be sure it's the same font? By its name alone? Unlikely.
Further: fonts in a Document fonts folder could trump the one from the system.
Also fonts from the Fonts directory of the InDesign application folder.
Hm. And what about substitutions that Adobe Fonts is able to do?
Automatically, if InDesign's preferences for this are enabled.
Thinking about all this: The wrong type of a font in a Document fonts folder could block the one with the same name that is installed elsewhere in the system. Could this lead to a situation where Adobe Fonts kicks in and substitutes the font for that document? And how about the situation where you open a document where the font already was substituted on a different machine? Will the value of status change if both fonts, the original one and the substituted one are available at the same time?
Regards,
Uwe Laubender
( Adobe Community Expert )
Copy link to clipboard
Copied
Hi Uwe, yes you show some definite complexities. And these issues are on top of the OPs original problem with getting wrong font names and (I think) the effects of those wrong names invalidating object references.
- Mark
Copy link to clipboard
Copied
Uwe and Mark those are excellent points about SUBTITUTED cases complicating things, I was already checking font.status against app instead of doc because a System font was incorrectly showing NOT_AVAILABLE at the doc level.
I noticed that attempting to read doc.font.location generates an Exception, for a missing font. Does it seem reasonable to test against location instead and get my missing font list that way?
Copy link to clipboard
Copied
Is this a Mac problem? I've never seen it in Windows (10). Or is it related to Adobe fonts? I always have Adobe Fonts disabled.
Anyway, two comments. Dealing with fonts in a script you really must get an array of fonts, not a collection. The scripts above make five calls at each iteration in the for-loop, which is very inefficient. Get the fonts once using everyItem().getElements(), and that'll be (almost) the only call to the fonts object you'll make. The script will run many times faster.
Nice trick with getSensibleFontName(), Mark. Just for interest's sake (hope you don't mind), it can be done in a single line:
function getSensibleFontName (name /*string*/) {
return name.replace (/\t(.+)\1/,'\t$1');
}
Peter
Copy link to clipboard
Copied
Hi Peter,
Is it a Mac problem? Maybe. I've asked another poster with the same problem which OS they are using. When I find out I'll lodge a bug report if none exists.
You're right about gettings all the fonts in one go at the start, but as mentioned in this post using everyItem().getElements() works as expected and doesn't invoke the bug so we weren't doing it. The following works for me with no fiddling:
var doc = app.activeDocument,
documentFonts = doc.fonts.everyItem().getElements(),
missingfonts = [];
for (var i = 0; i < documentFonts.length; i++) {
if (
documentFonts[i].status === FontStatus.NOT_AVAILABLE
|| documentFonts[i].status === FontStatus.SUBSTITUTED
) {
missingfonts.push(documentFonts[i].name);
}
}
(Thanks for prompting me, though—I should have posted this for the OP but was caught up in the bug weirdness.)
As for the regex... yes please always share your better ways. I'm not expert with regex and can use all the help I can get. Each time hopefully I get a little bit better. Thank you!
- Mark