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 , NSEventTypeLeftMouseDown , NSEventTypeLeftMouseDragged , NSEventTypeMouseMoved , NSEventTypeLeftMouseUp , NSEventTypePressure , NSEventTypeTabletPoint
7
7
from Foundation import NSNotFound , NSNumber , NSMutableDictionary
8
8
import math
9
9
import collections
@@ -78,6 +78,9 @@ def apply_values_for_anchors(font, master, layer, lsb_value, rsb_value, tsb_valu
78
78
else :
79
79
delete_anchor (font , master , layer , 'BSB' )
80
80
81
+ def round_to_grid (value , subdivision = 1.0 ):
82
+ return int (math .floor (value / subdivision + 0.5 )) * subdivision if subdivision else value
83
+
81
84
def make_gray_color ():
82
85
return NSColor .colorWithDeviceRed_green_blue_alpha_ (0.0 / 256.0 , 0.0 / 256.0 , 0.0 / 256.0 , 0.25 )
83
86
@@ -87,7 +90,7 @@ def make_magenta_color():
87
90
def make_cyan_color ():
88
91
return NSColor .colorWithDeviceRed_green_blue_alpha_ (0.0 / 256.0 , 159.0 / 256.0 , 227.0 / 256.0 , 1.0 )
89
92
90
- def draw_metrics_rect (font , master , layer , lsb_value , rsb_value , tsb_value , bsb_value ):
93
+ def draw_metrics_rect (font , master , layer , lsb_value , rsb_value , tsb_value , bsb_value , scale = 1.0 , dotted = False ):
91
94
vert_width = layer .vertWidth () if callable (layer .vertWidth ) else layer .vertWidth
92
95
if vert_width is None :
93
96
vert_width = master .ascender - master .descender
@@ -99,8 +102,10 @@ def draw_metrics_rect(font, master, layer, lsb_value, rsb_value, tsb_value, bsb_
99
102
y2 = descender + (bsb_value or 0.0 )
100
103
101
104
path = NSBezierPath .bezierPathWithRect_ (NSMakeRect (x1 , y2 , x2 - x1 , y1 - y2 ))
102
- path .setLineWidth_ (1.0 )
103
- path .stroke ()
105
+ path .setLineWidth_ (1.0 / scale )
106
+ if dotted :
107
+ path .setLineDash_count_phase_ ([path .lineWidth () * 3.0 , path .lineWidth () * 3.0 ], 2 , 0.0 )
108
+ path .stroke ()
104
109
105
110
def guess_anchor_direction_and_calc_distance_from_edge (location , master , layer ):
106
111
vert_width = layer .vertWidth () if callable (layer .vertWidth ) else layer .vertWidth
@@ -188,6 +193,9 @@ class CJKAnchorPlacementTool(SelectTool):
188
193
@objc .python_method
189
194
def start (self ):
190
195
self .needs_disable_update_anchors = False
196
+ self .grid_subdivision = 1.0
197
+ self .last_do_kerning = None
198
+ self .last_do_spacing = None
191
199
192
200
@objc .python_method
193
201
def settings (self ):
@@ -212,15 +220,18 @@ def mouseDoubleDown_(self, event):
212
220
font = layer .parent .parent
213
221
master = font .masters [layer .associatedMasterId or layer .layerId ]
214
222
anchor_name , distance_from_edge = guess_anchor_direction_and_calc_distance_from_edge (location , master , layer )
215
- if anchor_name == 'LSB' :
216
- self .LSBValue = distance_from_edge
217
- elif anchor_name == 'RSB' :
218
- self .RSBValue = distance_from_edge
219
- elif anchor_name == 'TSB' :
220
- self .TSBValue = distance_from_edge
221
- elif anchor_name == 'BSB' :
222
- self .BSBValue = distance_from_edge
223
-
223
+ if distance_from_edge > 0.0 :
224
+ if anchor_name == 'LSB' :
225
+ self .LSBValue = distance_from_edge
226
+ elif anchor_name == 'RSB' :
227
+ self .RSBValue = distance_from_edge
228
+ elif anchor_name == 'TSB' :
229
+ self .TSBValue = distance_from_edge
230
+ elif anchor_name == 'BSB' :
231
+ self .BSBValue = distance_from_edge
232
+ return
233
+ super (CJKAnchorPlacementTool , self ).mouseDoubleDown_ (event )
234
+
224
235
@LSBValue .setter
225
236
def LSBValue (self , value ):
226
237
if self ._LSBValue != value :
@@ -265,41 +276,70 @@ def update_anchors(self):
265
276
apply_values_for_anchors (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue )
266
277
267
278
@objc .python_method
268
- def sync_values (self , font , master , layer ):
279
+ def sync_values (self , font , master , layer , needs_round = False ):
269
280
if layer :
270
281
lsb_anchor = layer .anchors ['LSB' ] if layer .anchors else None
271
282
rsb_anchor = layer .anchors ['RSB' ] if layer .anchors else None
272
283
tsb_anchor = layer .anchors ['TSB' ] if layer .anchors else None
273
284
bsb_anchor = layer .anchors ['BSB' ] if layer .anchors else None
274
285
self .needs_disable_update_anchors = True
275
286
if lsb_anchor :
276
- self .LSBValue = lsb_anchor .position .x
287
+ self .LSBValue = round_to_grid ( lsb_anchor .position .x , self . grid_subdivision if needs_round else None )
277
288
else :
278
289
self .LSBValue = None
279
290
if rsb_anchor :
280
- self .RSBValue = layer .width - rsb_anchor .position .x
291
+ self .RSBValue = round_to_grid ( layer .width - rsb_anchor .position .x , self . grid_subdivision if needs_round else None )
281
292
else :
282
293
self .RSBValue = None
283
294
if tsb_anchor and master :
284
- self .TSBValue = master .ascender - tsb_anchor .position .y
295
+ self .TSBValue = round_to_grid ( master .ascender - tsb_anchor .position .y , self . grid_subdivision if needs_round else None )
285
296
else :
286
297
self .TSBValue = None
287
298
if bsb_anchor and master :
288
- self .BSBValue = - (master .descender - bsb_anchor .position .y )
299
+ self .BSBValue = round_to_grid ( - (master .descender - bsb_anchor .position .y ), self . grid_subdivision if needs_round else None )
289
300
else :
290
301
self .BSBValue = None
291
302
self .needs_disable_update_anchors = False
303
+ if needs_round :
304
+ self .update_anchors () # feedback if rounding is enabled
305
+
306
+ @objc .python_method
307
+ def update_grid_subdivision (self , event ):
308
+ if event :
309
+ flags = event .modifierFlags ()
310
+ if flags & NSShiftKeyMask :
311
+ self .grid_subdivision = 10.0
312
+ if flags & NSAlternateKeyMask :
313
+ self .grid_subdivision *= 0.5
314
+ else :
315
+ self .grid_subdivision = 1.0
316
+ else :
317
+ self .grid_subdivision = 1.0
292
318
293
319
@objc .python_method
294
320
def background (self , layer ):
295
321
font = layer .parent .parent
296
322
master = font .masters [layer .associatedMasterId or layer .layerId ]
297
-
323
+ event = NSApplication .sharedApplication ().currentEvent ()
324
+ valid_event_types = (NSEventTypeLeftMouseDragged , NSEventTypeMouseMoved , NSEventTypeLeftMouseUp , NSEventTypePressure , NSEventTypeTabletPoint )
298
325
arrange_anchors (font , master , layer )
299
- self .sync_values (font , master , layer )
326
+ self .update_grid_subdivision (event )
327
+ self .sync_values (font , master , layer , needs_round = event .type () in valid_event_types if event else False )
300
328
with currentGraphicsContext () as ctx :
301
- make_cyan_color ().setStroke ()
302
- draw_metrics_rect (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue )
329
+ dotted = False
330
+ has_unbalanced_palt = sum ((1 if value is None else 0 for value in (self .LSBValue , self .RSBValue ))) == 1
331
+ has_unbalanced_vpal = sum ((1 if value is None else 0 for value in (self .TSBValue , self .BSBValue ))) == 1
332
+ if sum ((1 if value is None else 0 for value in (self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue ))) == 4 :
333
+ has_unbalanced_palt , has_unbalanced_vpal = None , None
334
+ if has_unbalanced_palt is None and has_unbalanced_vpal is None :
335
+ dotted = True
336
+ make_cyan_color ().setStroke ()
337
+ elif has_unbalanced_palt or has_unbalanced_vpal :
338
+ make_magenta_color ().setStroke ()
339
+ else :
340
+ make_cyan_color ().setStroke ()
341
+ scale = self .editViewController ().graphicView ().scale ()
342
+ draw_metrics_rect (font , master , layer , self .LSBValue , self .RSBValue , self .TSBValue , self .BSBValue , scale = scale , dotted = dotted )
303
343
304
344
@objc .python_method
305
345
def __file__ (self ):
0 commit comments