// Make an InDesign character map for a font
// Original script by Eric Menninga, Adobe Systems Inc.
// Modified and expanded by Chuck Weger, Elara Systems, LLC
// Modified by Thomas Kunz (TK)
// Version 1.1, May 2009
// Version 1.2, October 2013 - fixed a problem wherein the file failed to import into InDesign CC due to it having a Mac-based line-ending. Also fixed a runtime error if the user cancels the dialog.
// Version 1.2.1 May 2025 - Units of measurement changed to millimetres; document dimensions changed to A4 (210 mm × 297 mm)
// General flow:
// 1. Show a dialog prompting the user for font, starting and ending glyphs
// 2. Build a temporary file with InDesign Tagged Text codes for every glyph between starting and ending values
// 3. Make an InDesign document and import the tagged text file into a text frame
// ----------------------------------------------------------------------------------------------------------
// "main" program
var result = showUI();
if (result) {
var taggedTextFile = createGlyphFile(result["fontName"], result["fontStyle"], parseInt(result["beginGlyph"]), parseInt(result["endGlyph"]));
if (taggedTextFile != null) {
createInDesignDocFromTaggedText(taggedTextFile);
taggedTextFile.remove();
}
}
// ----------------------------------------------------------------------------------------------------------
// Create an InDesign tagged text file with "cSpecialGlyph" codes
function createGlyphFile(fontName, fontStyle, beginGlyph, endGlyph) {
var tempFile = new File(Folder.temp + "/glyphmap.txt"); // this file lives in the user's temporary folder
if (tempFile) {
if (getPlatform() == "MAC") {
tempFile.lineFeed = "Unix"; // added 10-18-13 by Chuck Weger. Otherwise the file import fails in CC
}
tempFile.remove(); // clear out any old one
tempFile.open("w");
tempFile.writeln ("<ASCII-" + getPlatform() + ">");
tempFile.writeln ("<Version:5><FeatureSet:InDesign-Roman><ColorTable:=<Black:COLOR:CMYK:Process:0,0,0,1>>");
tempFile.writeln ("<DefineParaStyle:FontTableStyle=<Nextstyle:FontTableStyle><cTypeface:" + fontStyle
+ "><cLigatures:0><cFont:" + fontName + "><cOTFContAlt:0>>");
tempFile.write("<ParaStyle:FontTableStyle>");
for (i = beginGlyph; i <= endGlyph; ++i) {
num = String(i);
tempFile.write("<cSpecialGlyph:");
tempFile.write(num);
tempFile.write("><0xFFFD> <cSpecialGlyph:>");
}
tempFile.close();
return(tempFile);
}
else {
return(null); // we couldn't create the temp file for some reason
}
}
// ----------------------------------------------------------------------------------------------------------
// Make an InDesign document, make a text frame, and import the file we created earlier
function createInDesignDocFromTaggedText(myFile) {
myDoc = app.documents.add(true);
myDoc.viewPreferences.properties = {horizontalMeasurementUnits:MeasurementUnits.MILLIMETERS,
verticalMeasurementUnits:MeasurementUnits.MILLIMETERS}; // modified by TK
myDoc.documentPreferences.properties = {pagesPerDocument:1,
pageWidth: "210 mm", // modified by TK
pageHeight: "297 mm", // modified by TK
facingPages:false,
pageOrientation:PageOrientation.portrait};
myFrame = myDoc. textFrames.add(myDoc.layers[0], undefined, undefined,
{geometricBounds:[9.8, 10, 287.1, 200], // modified by TK
textFramePreferences:{firstBaselineOffset:FirstBaseline.ascentOffset},
});
myFrame.insertionPoints[-1].place(myFile);
}
// ----------------------------------------------------------------------------------------------------------
// Everything below here has to do with showing the dialog box
function showUI() {
var fontList = getFontList();
var myDialog = app.dialogs.add({name:"Font Table",canCancel:true});
with(myDialog) {
with(dialogColumns.add()) {
with (dialogRows.add()) {
staticTexts.add({staticLabel:"Font:"});
var fontMenu = dropdowns.add ({stringList:fontList, selectedIndex:0});
}
with (dialogRows.add()) {
staticTexts.add({staticLabel:"Beginning Glyph ID:"});
var beginId = integerEditboxes.add({editContents:"1", minWidth:80, minimumValue:0, maximumValue:65535});
}
with (dialogRows.add()) {
staticTexts.add({staticLabel:"Ending Glyph ID:"});
var endId = integerEditboxes.add({editContents:"10", minWidth:80, minimumValue:0, maximumValue:65535});
}
}
}
//Display the dialog box:
var myResult = myDialog.show();
if(myResult == true){
var fontSplit = fontList[fontMenu.selectedIndex].split(" - ");
var reply = {fontName: fontSplit[0], fontStyle: fontSplit[1], beginGlyph: beginId.editValue, endGlyph: endId.editValue};
}
else {
var reply = null;
myDialog.destroy();
}
return (reply);
}
// ----------------------------------------------------------------------------------------------------------
// Build a list of fonts active in InDesign
function getFontList() {
var fontList = new Array();
var myFonts = CollectionToArray(app.fonts);
for (var i = 0; i < myFonts.length; i++) {
var thisFont = myFonts[i];
if (thisFont.status == FontStatus.INSTALLED) {
var s = thisFont.fontFamily + " - " + thisFont.fontStyleName;
fontList.push(s);
}
}
return(fontList);
}
// ----------------------------------------------------------------------------------------------------------
// Iterating over a collection is very slow in ExtendScript.
// This technique, which turns a collection into an array, is courtesty
// of Peter Truskier and Jim Birkenseer of Premedia Systems
function CollectionToArray(theCollection) {
return theCollection.everyItem().getElements().slice(0);
}
// ----------------------------------------------------------------------------------------------------------
// Figure out whether we're on a Mac, PC, or Atari
function getPlatform() {
// returns "MAC" or "WIN" depending upon the barometric pressure
var os = $.os;
if (os.indexOf("Mac", 0) >= 0) {
var platform = "MAC";
}
else {
var platform = "WIN";
}
return(platform);
}