class GlyphnameDialog( object):

	def __init__( self ):
		x = 10
		y = 10
		height = 20
		button_width = 30
		glyphname_width = 180
		gap = 6
		self.w = Window( ( x + button_width + gap + glyphname_width + gap + button_width + x, y + height + y ), "insert glyph" )
		self.w.center()
		self.w.glyphname = EditText( ( x, y, glyphname_width, height ), '')
		x += glyphname_width + gap
		self.w.alignleft = Button( ( x, y, button_width, height ), LEFT, callback = self.buttonCallback )
		x += button_width + gap
		self.w.alignright = Button( ( x, y, button_width, height ), RIGHT, callback = self.buttonCallback )
		self.w.setDefaultButton( self.w.alignleft )
		self.w.alignright.bind( "\x1b", [] )
		self.w.open()

	def buttonCallback( self, sender ):
		alignment = sender.getTitle()
		glyphname = self.w.glyphname.get()
		if not glyphname:
			self.w.close()
			return
		if len( glyphname ) == 1:
			uni = ord(glyphname)
			g = font.glyphForUnicode_("%.4X" % uni)
			if g:
				glyphname = g.name
		other_glyph = font.glyphs[ glyphname ]
		if not other_glyph:
			for glyph in font.glyphs:
				if glyph.name.startswith( glyphname ):
					other_glyph = glyph
					print 'Using', glyph.name
					break
			else:
				print 'No matching glyph found.'
				self.w.close()
				return
		
		selected_glyphs = set( [ layer.parent for layer in font.selectedLayers ] )
		
		for glyph in selected_glyphs:
			glyph.beginUndo()
			for layer in glyph.layers:
				# find other layer
				for other_layer in other_glyph.layers:
					if other_layer.name == layer.name:
						insert_paths( layer, other_layer, alignment )
						break
				else:
					if active_layerId == layer.layerId:
						insert_paths( layer, other_glyph.layers[layer.associatedMasterId], alignment )
			glyph.endUndo()
		self.w.close()
Пример #2
0
class GlyphnameDialog(object):
    def __init__(self):
        x = 10
        y = 10
        height = 20
        button_width = 30
        glyphname_width = 180
        gap = 6
        self.w = Window(
            (x + button_width + gap + glyphname_width + gap + button_width + x,
             y + height + y), "insert glyph")
        self.w.center()
        self.w.glyphname = EditText((x, y, glyphname_width, height), '')
        x += glyphname_width + gap
        self.w.alignleft = Button((x, y, button_width, height),
                                  LEFT,
                                  callback=self.buttonCallback)
        x += button_width + gap
        self.w.alignright = Button((x, y, button_width, height),
                                   RIGHT,
                                   callback=self.buttonCallback)
        self.w.setDefaultButton(self.w.alignleft)
        self.w.alignright.bind("\x1b", [])
        self.w.open()

    def buttonCallback(self, sender):
        title = sender.getTitle()
        glyphname = self.w.glyphname.get()
        if not glyphname:
            self.w.close()
            return
        if len(glyphname) == 1:
            uni = ord(glyphname)
            g = font.glyphForUnicode_("%.4X" % uni)
            if g:
                glyphname = g.name
        other_glyph = font.glyphs[glyphname]
        if not other_glyph:
            for glyph in font.glyphs:
                if glyph.name.startswith(glyphname):
                    other_glyph = glyph
                    break
            else:
                self.w.close()
                return

        for layer in font.selectedLayers:
            glyph = layer.parent
            glyph.beginUndo()
            # deselect all
            for path in layer.paths:
                for node in path.nodes:
                    layer.removeObjectFromSelection_(node)
            # find other layer
            for other_layer in other_glyph.layers:
                if other_layer.name == layer.name:
                    # insert paths
                    for path in other_layer.copyDecomposedLayer().paths:
                        if title == RIGHT:
                            shift = layer.width - other_layer.width
                            for node in path.nodes:
                                node.x = node.x + shift
                        layer.paths.append(path)
                        # select path
                        layer.paths[-1].selected = True
                    break
            glyph.endUndo()
        self.w.close()
class makeDisplay(object):
    def __init__(self):
        self.verboten = {
            'right': ['napostrophe', 'Omegadasiavaria'],
            'left': ['ldot', 'Ldot', 'ldot.sc', 'sigmafinal'],
            'both': ['*.tf', '*.tosf', '.notdef', 'NULL', 'CR']
        }
        self.category = None
        self.messages = []
        self.interpolated_fonts = dict()
        self.use_real = True
        self.use_selection = False
        self.ignore_red = False
        self.current_glyph = None
        self.leftside_kerning_groups = None
        self.rightside_kerning_groups = None
        self.all_kern_categories = self.get_all_kern_categories()
        self.categories_leftside = self.get_categorised_glyphs('left')
        self.categories_rightside = self.get_categorised_glyphs('right')

        item_height = 24.0
        w_width = 300.0
        w_height = item_height * (7 + len(self.all_kern_categories))
        margin = 10
        next_y = margin
        col_1_width = w_width - (margin * 2)
        item_height = 24

        radio_height = item_height * len(self.all_kern_categories)

        self.w = Window((w_width, w_height), "Make Kerning Strings")

        self.w.text_1 = TextBox((margin, next_y, w_width, item_height), "Kern with:", sizeStyle='regular')
        next_y += item_height
        self.w.radioCategories = RadioGroup((margin, next_y, col_1_width, radio_height), self.all_kern_categories, sizeStyle='regular')
        self.w.radioCategories.set(0)
        next_y += radio_height + margin

        self.w.use_real = CheckBox((margin, next_y, col_1_width, item_height), "Use real words", value=True, sizeStyle='regular')
        next_y += item_height

        self.w.use_selected = CheckBox((margin, next_y, col_1_width, item_height), "Use the selected glyphs verbatum", value=False, sizeStyle='regular')
        next_y += item_height

        self.w.ignore_red = CheckBox((margin, next_y, col_1_width, item_height), "Ignore red marked glyphs", value=False, sizeStyle='regular')
        next_y += item_height + margin

        self.w.gobutton = Button((margin + (col_1_width / 4), next_y, col_1_width / 2, item_height), 'Make Strings', callback=self.makeitso)

        self.w.setDefaultButton(self.w.gobutton)
        self.w.center()
        self.w.open()
        # self.makeitso(None)

    def sbuttonCallback(self, sender):
        self.s.close()

    @staticmethod
    def has_smallcaps():
        for g in Glyphs.font.glyphs:
            if g.subCategory == 'Smallcaps':
                return True

        return False

    def get_all_kern_categories(self):
        kcats = [
            'Uppercase',
            'Lowercase',
        ]
        if self.has_smallcaps:
            kcats.append('Smallcaps')
        kcats += [
            'Quotes',
            'Number',
            'Punctuation',
            'Other',
        ]
        return kcats

    def get_canonincal_kerning_glyph(self, layer, pair_side):
        g = layer.parent

        if self.use_selection:
            return g

        if pair_side == 'left':
            g = Glyphs.font.glyphs[layer.parent.rightKerningGroup] or layer.parent
        if pair_side == 'right':
            g = Glyphs.font.glyphs[layer.parent.leftKerningGroup] or layer.parent

        if g is None:
            g = layer.parent

        return g

    @staticmethod
    def make_list_unique(this_list):
        unique_list = []
        for x in this_list:
            if x in unique_list or x is None:
                continue
            unique_list.append(x)

        return unique_list

    def get_categorised_glyphs(self, side):
        # cats = defaultdict(lambda: defaultdict(list))
        cats = dict((k, defaultdict(list)) for k in self.all_kern_categories)
        for g in [x for x in Glyphs.font.glyphs if self.is_elligable(x)]:
            l = cats.get(g.category, cats.get(g.subCategory, cats['Other']))
            l[g.script].append(self.get_canonincal_kerning_glyph(g.layers[0], side))

        for cat in cats.keys():
            for script in cats[cat].keys():
                cats[cat][script] = self.make_list_unique(cats[cat][script])

        return cats

    def get_string(self, left_g, right_g):
        string = None

        if self.category == 'Quotes':
            cat = left_g.subCategory if left_g.subCategory != 'Other' else left_g.category
            pattern = _kerningStrings.patterns.get(left_g.script, _kerningStrings.patterns.get('latin')).get(cat + '-Quotes', '')
            strings = [pattern.format(right=right_g.name, left=left_g.name, qL=quote_pair[0], qR=quote_pair[1]).replace(' /', '/') for quote_pair in _kerningStrings.quotations]
            string = '  '.join(strings)

        if not string and self.use_real:
            base_name_left, _, suffix_left = left_g.name.partition('.')
            base_name_right, _, suffix_right = right_g.name.partition('.')

            potentials = [
                base_name_left + base_name_right,
                base_name_left + '/' + base_name_right,
                '/' + base_name_left + ' ' + base_name_right,
                '/' + base_name_left + '/' + base_name_right,
            ]
            for s in potentials:
                string = _kerningStrings.strings.get(s)
                if string:
                    break
                print(s)

        if not string:
            pattern = self.get_pattern(left_g, right_g)
            string = pattern.format(right=right_g.name, left=left_g.name).replace(' /', '/')

        if not string:
            string = '/' + left_g.name + '/' + right_g.name

        return string

    def get_category_for_glyph(self, glyph):
        if glyph.category in self.all_kern_categories:
            return glyph.category

        if glyph.subCategory in self.all_kern_categories:
            return glyph.subCategory

        if glyph.subCategory == 'Currancy':
            return 'Number'

        return 'Other'

    def get_pattern(self, main_glyph, other_glyph):
        scripts_patterns = _kerningStrings.patterns.get(main_glyph.script, {})
        # print(self.get_category_for_glyph(main_glyph))
        # print(self.get_category_for_glyph(main_glyph) + '-' + self.get_category_for_glyph(other_glyph), self.all_kern_categories)
        pattern = scripts_patterns.get(self.get_category_for_glyph(main_glyph) + '-' + self.get_category_for_glyph(other_glyph), '')

        if self.category == 'Number':
            suffix = ''.join(main_glyph.name.partition('.')[1:])
        else:
            suffix = ''

        try:
            pattern = pattern.format(
                suffix=suffix,
                left='{left}',
                right='{right}',
            )
        except KeyError:
            pass

        return pattern

    def is_elligable(self, glyph, side='both'):
        if self.ignore_red and glyph.color == 0:
            return False

        if not glyph.export:
            return False

        for vgn in self.verboten[side]:
            if re.match(vgn.replace('.', '\\.').replace('*', '.*'), glyph.name):
                return False
        return True

    def makeitso(self, sender):
        try:
            self.w.close()
        except AttributeError:
            pass
        self.category = self.all_kern_categories[self.w.radioCategories.get()]

        self.use_real = self.w.use_real.get()
        self.use_selection = self.w.use_selected.get()
        self.ignore_red = self.w.ignore_red.get()
        all_strings = []

        if self.category == 'Quotes':
            left_of_string_glyphs = self.make_list_unique([self.get_canonincal_kerning_glyph(sl, 'right') for sl in Glyphs.font.selectedLayers if self.is_elligable(sl.parent, 'right')])
            right_of_string_glyphs = self.make_list_unique([self.get_canonincal_kerning_glyph(sl, 'left') for sl in Glyphs.font.selectedLayers if self.is_elligable(sl.parent, 'left')])
            pairs = zip_longest(left_of_string_glyphs, right_of_string_glyphs)
            for p in pairs:
                gl, gr = p
                if gl is None:
                    gl = gr if gr in left_of_string_glyphs else left_of_string_glyphs[0]
                if gr is None:
                    gr = gl if gl in left_of_string_glyphs else right_of_string_glyphs[0]

                kerning_string = self.get_string(gl, gr)
                if kerning_string not in all_strings:
                    all_strings.append(kerning_string)

        else:
            # Holds kerning key glyphs that have been seen already, to avoid duplicates
            processed_main_glyphs_left = OrderedDict()
            processed_main_glyphs_right = OrderedDict()
            # print([(k, self.categories_rightside[k].keys()) for k in self.categories_rightside.keys()])
            for sl in Glyphs.font.selectedLayers:
                # Process the selected glyph on the left side
                main_g_left = self.get_canonincal_kerning_glyph(sl, 'left')
                pair_strings_left = []
                if self.is_elligable(main_g_left, 'left'):
                    if main_g_left.name not in processed_main_glyphs_left.keys():
                        processed_main_glyphs_left[main_g_left.name] = [sl.parent.name]
                        try:
                            if sl.parent.script:
                                other_glyphs_rightside = self.categories_rightside[self.category].get(sl.parent.script, self.categories_rightside[self.category].get(None))
                            else:
                                other_glyphs_rightside = self.categories_rightside[self.category].get(None, self.categories_rightside[self.category].get('latin'))
                        except KeyError:
                            other_glyphs_rightside = []
                        # print(self.category, self.categories_rightside.keys())
                        print(sl.parent.script, self.category, self.categories_rightside[self.category].keys())

                        for g in other_glyphs_rightside:
                            if not self.is_elligable(g, 'right'):
                                continue
                            other_g = self.get_canonincal_kerning_glyph(g.layers[sl.associatedMasterId], 'right')
                            kerning_string_left = self.get_string(main_g_left, other_g)
                            if kerning_string_left not in pair_strings_left:
                                pair_strings_left.append(kerning_string_left)
                    else:
                        processed_main_glyphs_left[main_g_left.name].append(sl.parent.name)

                    if pair_strings_left:
                        pair_strings_left.insert(0, main_g_left.name)

                # Process the selected glyph on the right side
                main_g_right = self.get_canonincal_kerning_glyph(sl, 'right')
                pair_strings_right = []
                if self.is_elligable(main_g_right, 'right'):
                    if main_g_right.name not in processed_main_glyphs_right.keys():
                        processed_main_glyphs_right[main_g_right.name] = [sl.parent.name]

                        if self.category == 'Quotes':
                            other_glyphs_leftside = [main_g_right]
                            main_g_right = self.get_canonincal_kerning_glyph(sl, 'left')
                        else:
                            if sl.parent.script:
                                other_glyphs_leftside = self.categories_leftside[self.category].get(sl.parent.script, self.categories_leftside[self.category].get(None, []))
                            else:
                                other_glyphs_leftside = self.categories_leftside[self.category].get(None, self.categories_leftside[self.category].get('latin', []))

                        for g in other_glyphs_leftside:
                            if not self.is_elligable(g, 'left'):
                                continue
                            other_g = self.get_canonincal_kerning_glyph(g.layers[sl.associatedMasterId], 'left')
                            kerning_string_right = self.get_string(other_g, main_g_right)
                            if kerning_string_right not in pair_strings_right:
                                pair_strings_right.append(kerning_string_right)
                    else:
                        processed_main_glyphs_right[main_g_right.name].append(sl.parent.name)

                    if pair_strings_right:
                        pair_strings_right.insert(0, main_g_right.name)

                left_string = '  '.join(self.make_list_unique(pair_strings_left))
                right_string = '  '.join(self.make_list_unique(pair_strings_right))
                if all([left_string, right_string]):
                    pair_strings = '\n'.join([left_string, right_string])
                else:
                    pair_strings = left_string or right_string

                # print(':', pair_strings, ':')

                if pair_strings:
                    all_strings.append(pair_strings)

        Glyphs.font.newTab('\n\n'.join(all_strings))
        Glyphs.font.currentTab.previewInstances = 'live'
        Glyphs.font.currentTab.scale = 0.065
        Glyphs.font.currentTab.textCursor = 3
        Glyphs.font.tool = 'TextTool'
Пример #4
0
class replaceNamedComponent:
    def __init__(self):
        item_height = 24.0
        margin = 10
        w_width = 350.0
        w_height = (item_height * 5) + margin
        next_y = margin
        col_1_width = w_width - (margin * 2)
        item_height = 24

        self.get_prefs('SlantComponentPositions.pref')

        self.w = Window((w_width, w_height), "Slant Angle")

        self.w.slant_angle_text = TextBox(
            (margin, next_y + 2, col_1_width, item_height),
            "Slant Angle:",
            sizeStyle='regular')
        next_y += item_height
        self.w.slant_angle = EditText(
            (margin, next_y, col_1_width, item_height),
            self.prefs.get('slant_angle', ''))
        next_y += item_height + margin

        self.w.slant_all_layers = CheckBox(
            (margin, next_y, col_1_width, item_height),
            "Slant All Layers",
            value=int(self.prefs.get('slant_all_layers')),
            sizeStyle='regular')
        next_y += item_height + margin

        self.w.makeitso = Button(
            (w_width / 4.0, next_y, col_1_width / 2.0, item_height),
            'Slant Components',
            callback=self.makeitso)
        self.w.setDefaultButton(self.w.makeitso)

        self.w.open()
        self.w.center()

    def get_prefs(self, filename):
        self.pref_folder = os.path.expanduser(
            '~/Library/Application Support/Glyphs/Prefs')
        self.pref_filepath = os.path.join(self.pref_folder, filename)
        self.prefs = {}
        if os.path.exists(self.pref_filepath):
            with open(self.pref_filepath) as f:
                preflines = f.readlines()
            self.prefs = dict(
                line.split('\t') for line in preflines
                if line[0] != '#' and line.strip())

    def set_prefs(self, **kwargs):
        try:
            if not os.path.exists(self.pref_folder):
                os.makedirs(self.pref_folder)

            pref_string = '\n'.join(
                ['\t'.join(str(b) for b in a) for a in kwargs.items()])
            with open(self.pref_filepath, 'w') as f:
                f.write(pref_string)
        except AttributeError:
            print('The Preference filename has not been set.')

    def get_reference_point(self, selection, layer=None):
        return self.get_center_of_selection(selection)
        # return NSPoint(self.get_obj_center(layer).x, Glyphs.font.selectedFontMaster.xHeight / 2)

    def get_obj_center(self, obj):
        return NSPoint(obj.bounds.origin.x + (obj.bounds.size.width / 2),
                       obj.bounds.origin.y + (obj.bounds.size.height / 2))

    def get_center_of_selection(self, selection):
        all_points = []
        for obj in selection:
            try:
                all_points.append(self.get_obj_center(obj))
            except AttributeError:
                all_points.append(obj.position)

        all_xs = [x.x for x in all_points]
        all_ys = [x.x for x in all_points]

        x_average = sum(all_xs) / len(all_xs)
        y_average = sum(all_ys) / len(all_ys)

        return NSPoint(int(x_average), int(y_average))

    def makeitso(self, sender):
        self.w.close()
        slant_all_layers = self.w.slant_all_layers.get()
        # print(slant_all_layers, type(slant_all_layers))
        try:
            slant_angle = float(self.w.slant_angle.get())
        except TypeError:
            Glyphs.showNotification('Slant Component Positions',
                                    'The slant angle was not a number!')
            return

        self.set_prefs(slant_angle=slant_angle,
                       slant_all_layers=slant_all_layers)

        if not Glyphs.font.selectedLayers:
            return

        for sl in Glyphs.font.selectedLayers:
            if slant_all_layers:
                layers = [l for l in sl.parent.layers]
            else:
                layers = [sl]

            for l in layers:
                comps = [c for c in l.components if c.selected
                         ] or [c for c in l.components]
                if not comps:
                    Glyphs.showNotification(
                        'Slant Component Positions',
                        'You haven\'t selected any Components!')
                    return

                reference_point = self.get_reference_point(comps, l)
                for c in comps:
                    x_shift = math.tan(math.radians(slant_angle)) * (
                        self.get_obj_center(c).y - reference_point.y)
                    c.position = NSPoint(c.position.x + x_shift, c.position.y)
Пример #5
0
class GlyphnameDialog( object):

	def __init__( self ):
		hori_margin = 10
		verti_margin = hori_margin
		button_width = 30
		glyphname_width = 180
		line_height = 20
		gap = 9
		dialog_height = line_height + gap + line_height + gap + line_height
		dialog_width = button_width + gap + glyphname_width + gap + button_width
		self.w = Window( ( hori_margin + dialog_width + hori_margin, verti_margin + dialog_height + verti_margin ), "insert glyph" )
		self.w.center()
		x = hori_margin
		y = verti_margin
		# glyph name
		self.w.glyphname = EditText( ( x, y, glyphname_width, line_height ), '')
		self.w.glyphname.getNSTextField().setToolTip_( u'Enter the name of the glyph to be inserted. It is sufficient to enter the beginning of the glyph name, e.g. “deg” for “degree”.' )
		# buttons
		x += glyphname_width + gap
		self.w.alignleft = Button( ( x, y, button_width, line_height ), LEFT, callback = self.buttonCallback )
		self.w.alignleft.getNSButton().setToolTip_( 'Insert the other glyph left-aligned, i.e. at its original same position. Keyboard shortcut: Enter' )
		x += button_width + gap
		self.w.alignright = Button( ( x, y, button_width, line_height ), RIGHT, callback = self.buttonCallback )
		self.w.alignright.getNSButton().setToolTip_( 'Insert the other glyph right-aligned with respect to the advance widths. Keyboard shortcut: Esc' )
		self.w.setDefaultButton( self.w.alignleft )
		self.w.alignright.bind( "\x1b", [] )
		# insert as component
		as_component_is_checked = True
		if Glyphs.defaults["com.FMX.InsertGlyphToBackground.AsCompoment"]  is not None:
			as_component_is_checked = Glyphs.defaults["com.FMX.InsertGlyphToBackground.AsCompoment"]
		y += line_height + gap
		x = hori_margin
		self.w.as_component = CheckBox( ( x, y, dialog_width, line_height ), 'Insert as component', callback=None, value=as_component_is_checked )
		self.w.as_component.getNSButton().setToolTip_( 'If checked, the other glyph is inserted to the background as a component. Otherwise, it is inserted as paths (even if the other glyph is made of components).' )
		# clear current contents
		y += line_height + gap
		clear_contents_is_checked = True
		if Glyphs.defaults["com.FMX.InsertGlyphToBackground.ClearContents"]  is not None:
			clear_contents_is_checked = Glyphs.defaults["com.FMX.InsertGlyphToBackground.ClearContents"]
		self.w.clear_contents = CheckBox( ( x, y, dialog_width, line_height ), 'Clear current contents', callback=None, value=clear_contents_is_checked )
		self.w.clear_contents.getNSButton().setToolTip_( 'Check this to clear the background before inserting the other glyph. Uncheck to keep the current contents of the background.' )
		self.w.open()

	def buttonCallback( self, sender ):
		alignment = sender.getTitle()
		glyphname = self.w.glyphname.get()
		as_component_is_checked = self.w.as_component.get()
		clear_contents_is_checked = self.w.clear_contents.get()
		if not glyphname:
			self.w.close()
			return
		if len( glyphname ) == 1:
			uni = ord(glyphname)
			g = font.glyphForUnicode_("%.4X" % uni)
			if g:
				glyphname = g.name
		other_glyph = font.glyphs[ glyphname ]
		if not other_glyph:
			for glyph in font.glyphs:
				if glyph.name.startswith( glyphname ):
					other_glyph = glyph
					break
			else:
				self.w.close()
				return
		
		selected_glyphs = set( [ layer.parent for layer in font.selectedLayers ] )
		
		for glyph in selected_glyphs:
			glyph.beginUndo()
			for layer in glyph.layers:
				# find other layer
				for other_layer in other_glyph.layers:
					if other_layer.name == layer.name:
						insert_paths( layer, other_layer, alignment, as_component_is_checked, clear_contents_is_checked )
						break
				else:
					if layer.isBraceLayer:
						# the corresponding brace layer was not found in other_glyph.
						# let’s interpolate it on-the-fly:
						other_glyph_copy = other_glyph.copy()
						other_glyph_copy.parent = font
						# ^ Glyphs needs the font’s master coordinates for the re-interpolation
						interpolatedLayer = GSLayer()
						interpolatedLayer.name = layer.name
						# ^ necessary for the re-interpolation
						other_glyph_copy.layers.append( interpolatedLayer )
						interpolatedLayer.reinterpolate()
						insert_paths( layer, interpolatedLayer, alignment, as_component = False, clear_contents = clear_contents_is_checked )
					elif active_layerId == layer.layerId:
						insert_paths( layer, other_glyph.layers[layer.associatedMasterId], alignment, as_component_is_checked, clear_contents_is_checked )
			glyph.endUndo()
		Glyphs.defaults["com.FMX.InsertGlyphToBackground.AsCompoment"] = as_component_is_checked
		Glyphs.defaults["com.FMX.InsertGlyphToBackground.ClearContents"] = clear_contents_is_checked
		self.w.close()
class copyKerning(object):
    # TODO: Add class to different class name copying.
    # TODO: Allow left or right or both selection.
    # TODO: Allow open font selection.
    # TODO: Allow from/to layer selection.

    def __init__(self):
        item_height = 24.0
        margin = 10
        next_y = margin
        w_width = 400.0
        w_height = item_height * 7 + margin
        col_1_width = w_width - (margin * 2)

        self.this_font = Glyphs.font
        try:
            self.other_font = [f for f in Glyphs.fonts
                               if f != self.this_font][0]
        except IndexError:
            Glyphs.showNotification('Copy kerning for Class from Other Font:',
                                    'There is only 1 file open!')
            raise

        self.other_fonts_classes = self.get_other_fonts_classes()
        self.w = Window((w_width, w_height),
                        "Copy kerning for Class from Other Font")

        self.w.text_1 = TextBox(
            (margin, next_y, w_width, item_height),
            "Copy the kerning for this class to this font:",
            sizeStyle='small')
        next_y += item_height
        self.w.class_to_copy = PopUpButton(
            (margin, next_y, w_width - (margin * 2), item_height),
            self.other_fonts_classes,
            sizeStyle='regular')
        next_y += item_height + item_height

        self.w.copy_for_all = RadioGroup(
            (margin, next_y, w_width, item_height * 2), [
                ' Copy only for the current Master',
                ' Copy for All masters',
            ])
        self.w.copy_for_all.set(0)
        next_y += (item_height * 2) + margin

        self.w.gobutton = Button(
            (margin + (col_1_width / 4), next_y, col_1_width / 2, item_height),
            'Copy',
            callback=self.makeitso)

        self.w.setDefaultButton(self.w.gobutton)
        self.w.center()
        self.w.open()

    def get_other_fonts_classes(self):
        all_kern_groups = set()
        for g in self.other_font.glyphs:
            if g.leftKerningGroup is not None:
                all_kern_groups.add(g.leftKerningGroup)

            if g.rightKerningGroup is not None:
                all_kern_groups.add(g.rightKerningGroup)

        return sorted(all_kern_groups)

    def get_other_master(self, this_master):
        try:
            other_master = [
                m for m in self.other_font.masters
                if m.name == this_master.name
            ][0]
            return other_master
        except IndexError:
            pass

        return self.other_font.selectedFontMaster

    @staticmethod
    def glyph_for_id(font, some_name):
        try:
            return font.glyphForId_(some_name).name
        except AttributeError:
            return some_name

    def get_this_glyphname(self, some_name):
        try:
            return Glyphs.font.glyphForId_(some_name).name
        except AttributeError:
            return some_name

    def copy_left_kerning(self, this_master, class_name):
        mmk_class_name = '@MMK_L_{}'.format(class_name)
        for right, val in self.other_font.kerning[self.get_other_master(
                this_master).id][mmk_class_name].items():
            if right.startswith('@MMK'):
                right_name = right
            else:
                right_name = self.other_font.glyphForId_(right).name

            self.this_font.setKerningForPair(this_master.id, mmk_class_name,
                                             right_name, val)

    def copy_right_kerning(self, this_master, class_name):
        # TODO: This. Like, it's not done.
        print(
            'No left-side kerning was copied because the function hasn\'t been written yet.'
        )
        pass

    def makeitso(self, sender):
        self.w.close()
        class_name = self.w.class_to_copy.getItem()
        print(bool(self.w.copy_for_all.get()))
        chosen_masters = self.this_font.masters if self.w.copy_for_all.get(
        ) else [self.this_font.selectedFontMaster]
        for m in chosen_masters:
            self.copy_left_kerning(m, class_name)
            self.copy_right_kerning(m, class_name)
class GlyphnameDialog(object):
    def __init__(self):
        x = 10
        y = 10
        height = 20
        button_width = 30
        glyphname_width = 180
        gap = 6
        self.w = Window(
            (x + button_width + gap + glyphname_width + gap + button_width + x,
             y + height + y), "insert glyph")
        self.w.center()
        self.w.glyphname = EditText((x, y, glyphname_width, height), '')
        x += glyphname_width + gap
        self.w.alignleft = Button((x, y, button_width, height),
                                  LEFT,
                                  callback=self.buttonCallback)
        x += button_width + gap
        self.w.alignright = Button((x, y, button_width, height),
                                   RIGHT,
                                   callback=self.buttonCallback)
        self.w.setDefaultButton(self.w.alignleft)
        self.w.alignright.bind("\x1b", [])
        self.w.open()

    def buttonCallback(self, sender):
        alignment = sender.getTitle()
        glyphname = self.w.glyphname.get()
        if not glyphname:
            self.w.close()
            return
        if len(glyphname) == 1:
            uni = ord(glyphname)
            g = font.glyphForUnicode_("%.4X" % uni)
            if g:
                glyphname = g.name
        other_glyph = font.glyphs[glyphname]
        if not other_glyph:
            for glyph in font.glyphs:
                if glyph.name.startswith(glyphname):
                    other_glyph = glyph
                    print 'Using', glyph.name
                    break
            else:
                print 'No matching glyph found.'
                self.w.close()
                return

        selected_glyphs = set([layer.parent for layer in font.selectedLayers])

        for glyph in selected_glyphs:
            glyph.beginUndo()
            for layer in glyph.layers:
                # find other layer
                for other_layer in other_glyph.layers:
                    if other_layer.name == layer.name:
                        insert_paths(layer, other_layer, alignment)
                        break
                else:
                    if active_layerId == layer.layerId:
                        insert_paths(
                            layer,
                            other_glyph.layers[layer.associatedMasterId],
                            alignment)
            glyph.endUndo()
        self.w.close()
class GlyphnameDialog( object):

	def __init__( self ):
		x = 10
		y = 10
		height = 20
		button_width = 30
		glyphname_width = 180
		gap = 6
		self.w = Window( ( x + button_width + gap + glyphname_width + gap + button_width + x, y + height + y ), "insert glyph" )
		self.w.center()
		self.w.glyphname = EditText( ( x, y, glyphname_width, height ), '')
		x += glyphname_width + gap
		self.w.alignleft = Button( ( x, y, button_width, height ), LEFT, callback = self.buttonCallback )
		x += button_width + gap
		self.w.alignright = Button( ( x, y, button_width, height ), RIGHT, callback = self.buttonCallback )
		self.w.setDefaultButton( self.w.alignleft )
		self.w.alignright.bind( "\x1b", [] )
		self.w.open()

	def buttonCallback( self, sender ):
		title = sender.getTitle()
		glyphname = self.w.glyphname.get()
		if not glyphname:
			self.w.close()
			return
		if len( glyphname ) == 1:
			uni = ord(glyphname)
			g = font.glyphForUnicode_("%.4X" % uni)
			if g:
				glyphname = g.name
		other_glyph = font.glyphs[ glyphname ]
		if not other_glyph:
			for glyph in font.glyphs:
				if glyph.name.startswith( glyphname ):
					other_glyph = glyph
					print 'Using', glyph.name
					break
			else:
				print 'No matching glyph found.'
				self.w.close()
				return
		
		for layer in font.selectedLayers:
			glyph = layer.parent
			glyph.beginUndo()
			# deselect all
			for path in layer.paths:
				for node in path.nodes:
					layer.removeObjectFromSelection_( node )
			# find other layer
			for other_layer in other_glyph.layers:
				if other_layer.name == layer.name:
					# insert paths
					for path in other_layer.copyDecomposedLayer().paths:
						if title == RIGHT:
							shift = layer.width - other_layer.width
							for node in path.nodes:
								node.x = node.x + shift
						layer.paths.append( path )
						# select path
						layer.paths[-1].selected = True
					break
			glyph.endUndo()
		self.w.close()
Пример #9
0
class renameKerning(object):
    def __init__(self):
        item_height = 24.0
        w_width = 300.0
        w_height = item_height * 8
        margin = 10
        next_y = margin
        col_1_width = w_width - (margin * 2)
        item_height = 24

        self.messages = []
        self.interpolated_fonts = dict()
        self.current_glyph = None

        self.all_kern_groups = self.get_all_kern_groups()
        self.w = Window((w_width, w_height), "Rename Kern Groups")

        self.w.text_1 = TextBox((margin, next_y, w_width, item_height),
                                "Rename:",
                                sizeStyle='small')
        next_y += item_height
        self.w.nameFind = PopUpButton(
            (margin, next_y, w_width - (margin * 2), item_height),
            self.all_kern_groups,
            sizeStyle='regular')
        next_y += item_height + item_height

        self.w.text_2 = TextBox((margin, next_y, w_width, item_height),
                                "To:",
                                sizeStyle='small')
        next_y += item_height
        self.w.nameReplace = EditText(
            (margin, next_y, w_width - (margin * 2), item_height),
            "",
            sizeStyle='regular')
        next_y += item_height + margin

        self.w.gobutton = Button(
            (margin + (col_1_width / 4), next_y, col_1_width / 2, item_height),
            'Rename',
            callback=self.makeitso)

        self.w.setDefaultButton(self.w.gobutton)
        self.w.center()
        self.w.open()

    def sbuttonCallback(self, sender):
        self.s.close()

    def get_all_kern_groups(self):
        all_kern_groups = set()
        for g in Glyphs.font.glyphs:
            if g.leftKerningGroup is not None:
                all_kern_groups.add('{} - LEFT'.format(g.leftKerningGroup))
                if '{} - RIGHT'.format(g.leftKerningGroup) in all_kern_groups:
                    all_kern_groups.add('{} - BOTH'.format(g.leftKerningGroup))

            if g.rightKerningGroup is not None:
                all_kern_groups.add('{} - RIGHT'.format(g.rightKerningGroup))
                if '{} - LEFT'.format(g.rightKerningGroup) in all_kern_groups:
                    all_kern_groups.add('{} - BOTH'.format(
                        g.rightKerningGroup))

        return sorted(all_kern_groups)

    def makeitso(self, sender):
        self.w.close()
        nameReplace = self.w.nameReplace.get()
        nameFind = self.w.nameFind.getItem()
        group_name, _, side = nameFind.partition(' - ')

        for g in Glyphs.font.glyphs:
            if side in ['LEFT', 'BOTH']:
                if g.leftKerningGroup == group_name:
                    g.leftKerningGroup = nameReplace

            if side in ['RIGHT', 'BOTH']:
                if g.rightKerningGroup == group_name:
                    g.rightKerningGroup = nameReplace

        if '{} - {}'.format(nameReplace, side) in self.all_kern_groups:
            Glyphs.showNotification(
                'Kern Group Renaming Success!',
                'Note: the kern group named "{}" already exists so it will keep its existing kerning values.'
                .format(nameReplace))
            return

        for m_id in Glyphs.font.kerning:
            for left_group in Glyphs.font.kerning[m_id]:
                if side in ['RIGHT', 'BOTH']:
                    group_prefix = self.is_group(left_group, group_name)
                    if group_prefix:
                        for right_group, val in Glyphs.font.kerning[m_id][
                                left_group].items():
                            Glyphs.font.setKerningForPair(
                                m_id, group_prefix + nameReplace,
                                self.glyph_for_id(right_group), val)
                            Glyphs.font.removeKerningForPair(
                                m_id, left_group,
                                self.glyph_for_id(right_group))
                        left_group = group_prefix + nameReplace

                if side in ['LEFT', 'BOTH']:
                    for right_group, val in Glyphs.font.kerning[m_id][
                            left_group].items():
                        group_prefix = self.is_group(right_group, group_name)
                        if group_prefix:
                            # print(m_id, left_group, right_group, self.glyph_for_id(left_group), group_prefix + nameReplace, val)
                            # with open('/Users/benjones/Desktop/test.txt', 'a') as f:
                            #     f.write('{}\n'.format([m_id, left_group, right_group, self.glyph_for_id(left_group), group_prefix + nameReplace, val]))
                            Glyphs.font.setKerningForPair(
                                m_id, self.glyph_for_id(left_group),
                                group_prefix + nameReplace, val)
                            Glyphs.font.removeKerningForPair(
                                m_id, self.glyph_for_id(left_group),
                                right_group)

    @staticmethod
    def is_group(group, group_name):
        found_group = re.match('^(@MMK_._){}$'.format(group_name), group)
        if found_group is None:
            return False

        return found_group.group(1)

    @staticmethod
    def glyph_for_id(some_name):
        try:
            return Glyphs.font.glyphForId_(some_name).name
        except AttributeError:
            return some_name
Пример #10
0
class makeDisplay(object):
    def __init__(self):
        self.all_layer_combos = self.get_all_layer_combos()
        self.instance_values = self.get_instance_values()
        item_height = 24.0
        w_width = 300.0
        w_height = item_height * 10
        margin = 10
        next_y = margin
        col_1_width = w_width - (margin * 2)
        col_2_width = (w_width / 2) - (margin * 1.5)
        item_height = 24

        radio_height = 20 * 2
        self.get_prefs('addBraceLayers.pref')

        self.w = Window((w_width, w_height), "Add Layers")

        self.w.text_1 = TextBox((margin, next_y, col_1_width, item_height),
                                "Layer Combinations:",
                                sizeStyle='regular')
        next_y += item_height
        self.w.parent_layers = PopUpButton(
            (margin, next_y, col_1_width, item_height),
            self.all_layer_combos,
            sizeStyle='regular')
        self.set_all_layer_combos()
        next_y += item_height + margin

        self.w.brace_or_bracket = RadioGroup(
            (margin, next_y, col_1_width, radio_height),
            ['Bracket Layer [X]', 'Brace Layer {X}'],
            sizeStyle='regular')
        self.w.brace_or_bracket.set(int(self.prefs.get('brace_or_bracket', 0)))
        next_y += radio_height + margin

        self.w.text_2 = TextBox((margin, next_y, col_1_width, item_height),
                                "Layer Value:",
                                sizeStyle='regular')
        next_y += item_height
        self.w.layer_value = EditText(
            (margin, next_y, col_2_width, item_height),
            '',
            sizeStyle='small',
            placeholder='e.g. 700')
        self.w.instance_value_popup = PopUpButton(
            (margin + margin + col_2_width, next_y, col_2_width, item_height),
            self.instance_values,
            sizeStyle='regular',
            callback=self.changeinstance_value)
        next_y += item_height + margin
        if self.prefs.get('layer_value') is not None:
            self.w.layer_value.set(self.prefs.get('layer_value'))

        self.w.gobutton = Button(
            (margin + (col_1_width / 4), next_y, col_1_width / 2, item_height),
            'Add Layers',
            callback=self.makeitso)

        self.w.setDefaultButton(self.w.gobutton)
        self.w.center()
        self.w.open()
        # self.makeitso(None)

    def get_prefs(self, filename):
        self.pref_folder = os.path.expanduser(
            '~/Library/Application Support/Glyphs/Prefs')
        self.pref_filepath = os.path.join(self.pref_folder, filename)
        self.prefs = {}
        if os.path.exists(self.pref_filepath):
            with open(self.pref_filepath) as f:
                preflines = f.readlines()
            self.prefs = dict(
                line.split('\t') for line in preflines
                if line[0] != '#' and line.strip())

    def set_prefs(self, **kwargs):
        try:
            if not os.path.exists(self.pref_folder):
                os.makedirs(self.pref_folder)

            pref_string = '\n'.join(
                ['\t'.join(str(b) for b in a) for a in kwargs.items()])
            with open(self.pref_filepath, 'w') as f:
                f.write(pref_string)
        except AttributeError:
            print('The Preference filename has not been set.')

    def get_all_layer_combos(self):
        master_combos = OrderedDict()
        for mi, m in enumerate(Glyphs.font.masters):
            try:
                next_m = Glyphs.font.masters[mi + 1]
                if not next_m:
                    break
                combo_tup = (m, next_m)
                master_combos['{}-{}'.format(
                    *[x.name for x in combo_tup])] = combo_tup
            except IndexError:
                break

        return master_combos

    def set_all_layer_combos(self):
        selection_index = Glyphs.font.masterIndex
        if selection_index >= len(self.all_layer_combos):
            selection_index = len(self.all_layer_combos) - 1
        self.w.parent_layers.set(selection_index)

    def get_instance_values(self):
        return [''] + [
            ', '.join([str(x) for x in list(i.axes)])
            for i in Glyphs.font.instances
        ]

    def changeinstance_value(self, sender):
        self.w.layer_value.set(sender.getItem())

    def makeitso(self, sender):
        try:
            self.w.close()
        except AttributeError:
            pass

        parent_layers = self.w.parent_layers.getItem()
        brace_or_bracket = self.w.brace_or_bracket.get()
        layer_value = float(self.w.layer_value.get().strip())
        if int(layer_value) - layer_value == 0:
            layer_value = int(layer_value)

        self.set_prefs(
            parent_layers=parent_layers,
            brace_or_bracket=brace_or_bracket,
            layer_value=layer_value,
        )

        layer_name_template = '{master_name} {{{layer_value}}}' if brace_or_bracket else '{master_name} [{layer_value}]'

        master_names = parent_layers.split('-')
        masters = [m for m in Glyphs.font.masters if m.name in master_names]

        for sl in Glyphs.font.selectedLayers:
            g = sl.parent

            for m in masters:
                newL = copy.copy(g.layers[m.id])
                newL.layerId = None
                newL.associatedMasterId = m.id
                newL.name = layer_name_template.format(
                    master_name=m.name,
                    layer_value=layer_value,
                )
                g.layers.append(newL)