-
Notifications
You must be signed in to change notification settings - Fork 104
/
Steal kerning from InDesign.py
233 lines (203 loc) · 7.4 KB
/
Steal kerning from InDesign.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# MenuTitle: Steal Kerning from InDesign
# -*- coding: utf-8 -*-
from __future__ import division, print_function, unicode_literals
__doc__ = """
Use the font in InD (set up a document with one text box on the first page, set the kerning method to Optical), then run this script.
"""
from Foundation import NSAppleScript
from timeit import default_timer as timer
from GlyphsApp import Glyphs
from mekkablue import reportTimeInNaturalLanguage
# start taking time:
start = timer()
thisFont = Glyphs.font # frontmost font
thisFontMaster = thisFont.selectedFontMaster # active master
thisFontMasterID = thisFontMaster.id # active master id
listOfSelectedLayers = thisFont.selectedLayers # active layers of selected glyphs
replacements = {
"bullet character": "•",
"copyright symbol": "©",
"double left quote": "“",
"double right quote": "”",
"ellipsis character": "…",
"Em dash": "—",
"En dash": "–",
"nonbreaking space": " ",
"section symbol": "§",
"single left quote": "‘",
"single right quote": "’",
"trademark symbol": "™",
}
# brings macro window to front and clears its log:
Glyphs.clearLog()
# Glyphs.showMacroWindow()
def glyphNameForLetter(letter):
glyphName = False
if len(letter) > 0:
letter = letter[0]
utf16value = "%.4X" % ord(letter)
glyphName = Glyphs.glyphInfoForUnicode(utf16value).name
return glyphName
def runAppleScript(scriptSource, args=[]):
s = NSAppleScript.alloc().initWithSource_(scriptSource)
result, error = s.executeAndReturnError_(None)
if error:
print("AppleScript Error:")
print(error)
print("Tried to run:")
for i, line in enumerate(scriptSource.splitlines()):
print("%03i" % (i + 1), line)
return False
if result:
return result.stringValue()
else:
return True
def cleanText(thisText, cleanDict):
"""cleanDict={"searchFor":"replaceWith"}"""
for searchFor in cleanDict.keys():
replaceWith = cleanDict[searchFor]
thisText = thisText.replace(searchFor, replaceWith)
return thisText
# Determine InDesign application name (for use in the AppleScripts):
Glyphs.registerDefault("com.mekkablue.stealKerningFromInDesign.indesignAppName", "Adobe InDesign")
getInDesign = """
try
set InDesign to application "%s"
on error
set InDesign to choose application with title "Please choose Adobe InDesign"
end try
InDesign as string
""" % Glyphs.defaults["com.mekkablue.stealKerningFromInDesign.indesignAppName"]
indesign = runAppleScript(getInDesign)
if indesign != Glyphs.defaults["com.mekkablue.stealKerningFromInDesign.indesignAppName"]:
Glyphs.defaults["com.mekkablue.stealKerningFromInDesign.indesignAppName"] = indesign
print("Accessing: %s" % indesign)
# Define AppleScripts to be run later:
getKernValuesFromInDesign = """
set kernvalues to ""
tell application "%s"
tell front document
tell parent story of first text frame
repeat with i from 1 to (count characters) - 1
try
set kernvalue to (kerning value of insertion point 2 of character i) as integer
set kernvalueline to character i & character (i + 1) & " " & kernvalue
set kernvalues to kernvalues & kernvalueline & "\n"
end try
end repeat
end tell
end tell
end tell
kernvalues
""" % indesign
getNameOfDocument = """
tell application "%s"
tell front document
name
end tell
end tell
""" % indesign
getTextOfFrame = """
tell application "%s"
tell front document
contents of first text frame
end tell
end tell
""" % indesign
getNameOfFont = """
tell application "%s"
tell front document
tell first text frame
tell character 1 of parent story
name of applied font
end tell
end tell
end tell
end tell
""" % indesign
# Execute AppleScripts and store results in variables:
# Extract document name and report:
try:
docName = runAppleScript(getNameOfDocument)
docName = str(docName).strip()
print(f"\nExtracting kerning from document: {docName}")
except Exception as e:
print("\nERROR while trying to extract the name of the first InDesign document.")
print(
"Possible causes:\n 1. No permissions in System Preferences > Security & Privacy > Privacy > Automation > Glyphs. Please review.\n 2. No document open in InDesign; will try to continue.\n 3. New document has not been saved yet."
)
print(e)
print()
# Extract text and report:
try:
frameText = runAppleScript(getTextOfFrame)
frameText = "%.60s..." % frameText.strip()
print(f"\nFound text: {frameText}")
except Exception as e:
print("\nERROR while trying to extract the text of the first text frame.")
print(
"Possible causes:\n 1. No permissions in System Preferences > Security & Privacy > Privacy > Automation > Glyphs. Please review.\n 2. No text frame in the frontmost document in InDesign; will try to continue."
)
print(e)
print()
# Extract font name and report:
try:
fontName = runAppleScript(getNameOfFont)
fontName = fontName.replace("\t", " ").replace("font ", "").strip()
print(f"\nFound font: {fontName}")
print("\nProcessing, please wait. Can take a minute...\n")
except Exception as e:
print("\nERROR while trying to extract the font in the first text frame.")
print(
"Possible causes:\n 1. No permissions in System Preferences > Security & Privacy > Privacy > Automation > Glyphs. Please review.\n 2. No text in the first text frame of the frontmost document in InDesign; will try to continue."
)
print(e)
print()
# Extract kern strings and report:
kernInfo = runAppleScript(getKernValuesFromInDesign)
print(f"Applying kerning to: {thisFont.familyName}, Master: {thisFontMaster.name}\n")
kernPairCount = 0
# Parse kern strings and set kerning in the font:
for thisLine in kernInfo.splitlines():
if len(thisLine) > 3:
# sometimes, InD returns a char description rather than a char 🤷🏻♀️, this is a hack that fixes it:
thisLine = cleanText(thisLine, replacements)
# check for left side:
leftSide = glyphNameForLetter(thisLine[0])
if not leftSide:
print(f"WARNING:\n Could not determine (left) glyph name: {thisLine[0]}.\n Skipping pair ‘{thisLine[0]}{thisLine[1]}’.\n")
else:
if not thisFont.glyphs[leftSide]:
print(f"WARNING:\n Expected (left) glyph /{leftSide} not found in {thisFont.familyName}.\n Skipping pair ‘{thisLine[0]}{thisLine[1]}’.\n")
else:
# check for right side:
rightSide = glyphNameForLetter(thisLine[1])
if not rightSide:
print(f"WARNING:\n Could not determine (right) glyph name: {thisLine[1]}.\n Skipping pair ‘{thisLine[0]}{thisLine[1]}’.\n")
else:
if not thisFont.glyphs[rightSide]:
print(f"WARNING:\n Expected (right) glyph /{rightSide} not found in {thisFont.familyName}.\n Skipping pair ‘{thisLine[0]}{thisLine[1]}’.\n")
else:
try:
kernValue = float(thisLine[3:])
if kernValue:
thisFont.setKerningForPair(thisFontMasterID, leftSide, rightSide, kernValue)
kernPairCount += 1
print(f" Kerning for {leftSide}:{rightSide} set to {kernValue}.")
else:
print(f" No kerning {leftSide}:{rightSide}. Ignored.")
except Exception as e:
print(f" ERROR: Could not set kerning for {leftSide}:{rightSide}.\n")
print(e)
print(f" Offending line:\n {thisLine}")
import traceback
print(traceback.format_exc())
# take time and report:
end = timer()
timereport = reportTimeInNaturalLanguage(end - start)
print(f"\nImported {kernPairCount} kern pairs.\nTime elapsed: {timereport}.")
# Floating notification:
Glyphs.showNotification(
f"{kernPairCount} pairs for {thisFont.familyName}",
f"Stolen from InDesign in {timereport}.",
)