3
3
import objc
4
4
from GlyphsApp import *
5
5
from GlyphsApp .plugins import *
6
- from AppKit import NSGraphicsContext , NSColor , NSMakeRect , NSInsetRect , NSMakePoint , NSAlternateKeyMask , NSBeep , NSNumberFormatter , NSValueTransformer
6
+ from AppKit import NSApplication , NSGraphicsContext , NSColor , NSMakeRect , NSInsetRect , NSMakePoint , NSAlternateKeyMask , NSBeep , NSNumberFormatter , NSValueTransformer , NSLeftMouseDown , NSLeftMouseUp , NSMouseMoved , NSLeftMouseDragged
7
+
7
8
from Foundation import NSNotFound , NSNumber , NSMutableDictionary
8
9
import math
9
10
import collections
10
11
import contextlib
11
12
13
+ VALID_EVENT_TYPES = (NSLeftMouseDown , NSLeftMouseUp , NSMouseMoved , NSLeftMouseDragged )
14
+
12
15
@contextlib .contextmanager
13
16
def currentGraphicsContext (context = None ):
14
17
context = context or NSGraphicsContext .currentContext ()
@@ -78,6 +81,9 @@ def apply_values_for_anchors(font, master, layer, lsb_value, rsb_value, tsb_valu
78
81
else :
79
82
delete_anchor (font , master , layer , 'BSB' )
80
83
84
+ def round_to_grid (value , subdivision = 1.0 ):
85
+ return int (math .floor (value / subdivision + 0.5 )) * subdivision if subdivision else value
86
+
81
87
def make_gray_color ():
82
88
return NSColor .colorWithDeviceRed_green_blue_alpha_ (0.0 / 256.0 , 0.0 / 256.0 , 0.0 / 256.0 , 0.25 )
83
89
@@ -87,7 +93,7 @@ def make_magenta_color():
87
93
def make_cyan_color ():
88
94
return NSColor .colorWithDeviceRed_green_blue_alpha_ (0.0 / 256.0 , 159.0 / 256.0 , 227.0 / 256.0 , 1.0 )
89
95
90
- def draw_metrics_rect (font , master , layer , lsb_value , rsb_value , tsb_value , bsb_value ):
96
+ def draw_metrics_rect (font , master , layer , lsb_value , rsb_value , tsb_value , bsb_value , scale = 1.0 , dotted = False ):
91
97
vert_width = layer .vertWidth () if callable (layer .vertWidth ) else layer .vertWidth
92
98
if vert_width is None :
93
99
vert_width = master .ascender - master .descender
@@ -99,8 +105,10 @@ def draw_metrics_rect(font, master, layer, lsb_value, rsb_value, tsb_value, bsb_
99
105
y2 = descender + (bsb_value or 0.0 )
100
106
101
107
path = NSBezierPath .bezierPathWithRect_ (NSMakeRect (x1 , y2 , x2 - x1 , y1 - y2 ))
102
- path .setLineWidth_ (1.0 )
103
- path .stroke ()
108
+ path .setLineWidth_ (1.0 / scale )
109
+ if dotted :
110
+ path .setLineDash_count_phase_ ([path .lineWidth () * 3.0 , path .lineWidth () * 3.0 ], 2 , 0.0 )
111
+ path .stroke ()
104
112
105
113
def guess_anchor_direction_and_calc_distance_from_edge (location , master , layer ):
106
114
vert_width = layer .vertWidth () if callable (layer .vertWidth ) else layer .vertWidth
@@ -189,6 +197,9 @@ class CJKAnchorPlacementTool(SelectTool):
189
197
@objc .python_method
190
198
def start (self ):
191
199
self .needs_disable_update_anchors = False
200
+ self .grid_subdivision = 1.0
201
+ self .last_do_kerning = None
202
+ self .last_do_spacing = None
192
203
193
204
@objc .python_method
194
205
def settings (self ):
@@ -217,14 +228,17 @@ def mouseDoubleDown_(self, event):
217
228
font = layer .parent .parent
218
229
master = font .masters [layer .associatedMasterId or layer .layerId ]
219
230
anchor_name , distance_from_edge = guess_anchor_direction_and_calc_distance_from_edge (location , master , layer )
220
- if anchor_name == 'LSB' :
221
- self .LSBValue = distance_from_edge
222
- elif anchor_name == 'RSB' :
223
- self .RSBValue = distance_from_edge
224
- elif anchor_name == 'TSB' :
225
- self .TSBValue = distance_from_edge
226
- elif anchor_name == 'BSB' :
227
- self .BSBValue = distance_from_edge
231
+ if distance_from_edge > 0.0 :
232
+ if anchor_name == 'LSB' :
233
+ self .LSBValue = distance_from_edge
234
+ elif anchor_name == 'RSB' :
235
+ self .RSBValue = distance_from_edge
236
+ elif anchor_name == 'TSB' :
237
+ self .TSBValue = distance_from_edge
238
+ elif anchor_name == 'BSB' :
239
+ self .BSBValue = distance_from_edge
240
+ return
241
+ objc .super (CJKAnchorPlacementTool , self ).mouseDoubleDown_ (event )
228
242
229
243
@LSBValue .setter
230
244
def LSBValue (self , value ):
@@ -270,41 +284,69 @@ def update_anchors(self):
270
284
apply_values_for_anchors (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue )
271
285
272
286
@objc .python_method
273
- def sync_values (self , font , master , layer ):
287
+ def sync_values (self , font , master , layer , needs_round = False ):
274
288
if layer :
275
289
lsb_anchor = layer .anchors ['LSB' ] if layer .anchors else None
276
290
rsb_anchor = layer .anchors ['RSB' ] if layer .anchors else None
277
291
tsb_anchor = layer .anchors ['TSB' ] if layer .anchors else None
278
292
bsb_anchor = layer .anchors ['BSB' ] if layer .anchors else None
279
293
self .needs_disable_update_anchors = True
280
294
if lsb_anchor :
281
- self .LSBValue = lsb_anchor .position .x
295
+ self .LSBValue = round_to_grid ( lsb_anchor .position .x , self . grid_subdivision if needs_round else None )
282
296
else :
283
297
self .LSBValue = None
284
298
if rsb_anchor :
285
- self .RSBValue = layer .width - rsb_anchor .position .x
299
+ self .RSBValue = round_to_grid ( layer .width - rsb_anchor .position .x , self . grid_subdivision if needs_round else None )
286
300
else :
287
301
self .RSBValue = None
288
302
if tsb_anchor and master :
289
- self .TSBValue = master .ascender - tsb_anchor .position .y
303
+ self .TSBValue = round_to_grid ( master .ascender - tsb_anchor .position .y , self . grid_subdivision if needs_round else None )
290
304
else :
291
305
self .TSBValue = None
292
306
if bsb_anchor and master :
293
- self .BSBValue = - (master .descender - bsb_anchor .position .y )
307
+ self .BSBValue = round_to_grid ( - (master .descender - bsb_anchor .position .y ), self . grid_subdivision if needs_round else None )
294
308
else :
295
309
self .BSBValue = None
296
310
self .needs_disable_update_anchors = False
311
+ if needs_round :
312
+ self .update_anchors () # feedback if rounding is enabled
313
+
314
+ @objc .python_method
315
+ def update_grid_subdivision (self , event ):
316
+ if event :
317
+ flags = event .modifierFlags ()
318
+ if flags & NSShiftKeyMask :
319
+ self .grid_subdivision = 10.0
320
+ if flags & NSAlternateKeyMask :
321
+ self .grid_subdivision *= 0.5
322
+ else :
323
+ self .grid_subdivision = 1.0
324
+ else :
325
+ self .grid_subdivision = 1.0
297
326
298
327
@objc .python_method
299
328
def background (self , layer ):
300
329
font = layer .parent .parent
301
330
master = font .masters [layer .associatedMasterId or layer .layerId ]
302
-
331
+ event = NSApplication . sharedApplication (). currentEvent ()
303
332
arrange_anchors (font , master , layer )
304
- self .sync_values (font , master , layer )
333
+ self .update_grid_subdivision (event )
334
+ self .sync_values (font , master , layer , needs_round = event .type () in VALID_EVENT_TYPES if event else False )
305
335
with currentGraphicsContext () as ctx :
306
- make_cyan_color ().setStroke ()
307
- draw_metrics_rect (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue )
336
+ dotted = False
337
+ has_unbalanced_palt = sum ((1 if value is None else 0 for value in (self .LSBValue , self .RSBValue ))) == 1
338
+ has_unbalanced_vpal = sum ((1 if value is None else 0 for value in (self .TSBValue , self .BSBValue ))) == 1
339
+ if sum ((1 if value is None else 0 for value in (self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue ))) == 4 :
340
+ has_unbalanced_palt , has_unbalanced_vpal = None , None
341
+ if has_unbalanced_palt is None and has_unbalanced_vpal is None :
342
+ dotted = True
343
+ make_cyan_color ().setStroke ()
344
+ elif has_unbalanced_palt or has_unbalanced_vpal :
345
+ make_magenta_color ().setStroke ()
346
+ else :
347
+ make_cyan_color ().setStroke ()
348
+ scale = self .editViewController ().graphicView ().scale ()
349
+ draw_metrics_rect (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue , scale = scale , dotted = dotted )
308
350
309
351
@objc .python_method
310
352
def __file__ (self ):
0 commit comments