def test_bug232(self):
     # https://github.com/googlefonts/glyphsLib/issues/232
     u, g = get_glyph("uni07F0"), get_glyph("longlowtonecomb-nko")
     self.assertEqual((u.category, g.category), ("Mark", "Mark"))
     self.assertEqual((u.subCategory, g.subCategory), ("Nonspacing", "Nonspacing"))
     self.assertEqual((u.production_name, g.production_name), ("uni07F0", "uni07F0"))
     self.assertEqual((u.unicode, g.unicode), ("07F0", "07F0"))
Exemple #2
0
def generatePy(checkValues, fontAxes, firstGlyph, substitution, bracketDefault,
               origGlyphName):
    '''
    Verify that the glyph only has one substitution
    Glyphs App does not appear to support more though this script could serve as a workaround for that. Might add in the future
    '''
    for value in checkValues:
        glyphString = ""
        firstRegion = True
        axis = fontAxes["axis" + str(value.values()[0])]['tag']

        if value.keys()[0] != None and bracketDefault == False:
            if firstRegion == False:
                glyphString = glyphString + ", "
            glyphString = glyphString + (
                "\"%s\" : (%s, %s)" % (axis, str(value.keys()[0]), str(1.0)))
            firstRegion = False
        elif value.keys()[0] != None and bracketDefault == True:
            if firstRegion == False:
                glyphString = glyphString + ", "
            glyphString = glyphString + (
                "\"%s\" : (%s, %s)" % (axis, str(-1.0), str(value.keys()[0])))
            firstRegion = False

        glyphSub = "{\"%s\" : \"%s\"}" % (get_glyph(origGlyphName)[1],
                                          get_glyph(origGlyphName)[1] + suffix)
        print "([{%s}], %s)" % (glyphString, glyphSub)

        if firstGlyph == True:
            glyphString = "\t([{%s}], %s)," % (glyphString, glyphSub)
        else:
            glyphString = " \n\t([{%s}], %s)," % (glyphString, glyphSub)
        substitution = substitution + glyphString
        firstGlyph = False
    return substitution
def generatePy(checkValues, fontAxes, firstGlyph, substitution, bracketDefault, origGlyphName):
    '''
    Verify that the glyph only has one substitution
    Glyphs App does not appear to support more though this script could serve as a workaround for that. Might add in the future
    '''
    for value in checkValues:
        glyphString = ""
        firstRegion = True
        axis = fontAxes["axis" + str(value.values()[0])]['tag']

        if value.keys()[0] != None and bracketDefault == False:
            if firstRegion == False:
                glyphString = glyphString + ", "
            glyphString = glyphString + ("\"%s\" : (%s, %s)" % (axis, str(value.keys()[0]), str(1.0)))
            firstRegion = False
        elif value.keys()[0] != None and bracketDefault == True:
            if firstRegion == False:
                glyphString = glyphString + ", "
            glyphString = glyphString + ("\"%s\" : (%s, %s)" % (axis, str(-1.0), str(value.keys()[0])))
            firstRegion = False

        glyphSub = "{\"%s\" : \"%s\"}" % (get_glyph(origGlyphName)[1], get_glyph(origGlyphName)[1] + suffix)
        print "([{%s}], %s)" % (glyphString, glyphSub)

        if firstGlyph == True:
            glyphString = "\t([{%s}], %s)," % (glyphString, glyphSub)
        else:
            glyphString = " \n\t([{%s}], %s)," % (glyphString, glyphSub)
        substitution = substitution + glyphString
        firstGlyph = False
    return substitution
 def test_category(self):
     cat = lambda n: (get_glyph(n).category, get_glyph(n).subCategory)
     self.assertEqual(cat(".notdef"), ("Separator", None))
     self.assertEqual(cat("uni000D"), ("Separator", None))
     self.assertEqual(cat("boxHeavyUp"), ("Symbol", "Geometry"))
     self.assertEqual(cat("eacute"), ("Letter", "Lowercase"))
     self.assertEqual(cat("Abreveacute"), ("Letter", "Uppercase"))
     self.assertEqual(cat("C-fraktur"), ("Letter", "Uppercase"))
     self.assertEqual(cat("fi"), ("Letter", "Ligature"))
     self.assertEqual(cat("fi.alt"), ("Letter", "Ligature"))
     self.assertEqual(cat("hib-ko"), ("Letter", "Syllable"))
     self.assertEqual(cat("one.foo"), ("Number", "Decimal Digit"))
     self.assertEqual(cat("one_two.foo"), ("Number", "Ligature"))
     self.assertEqual(cat("o_f_f_i"), ("Letter", "Ligature"))
     self.assertEqual(cat("o_f_f_i.foo"), ("Letter", "Ligature"))
     self.assertEqual(cat("ain_alefMaksura-ar.fina"),
                      ("Letter", "Ligature"))
 def test_unicode(self):
     uni = lambda n: get_glyph(n).unicode
     self.assertIsNone(uni(".notdef"))
     self.assertEqual(uni("eacute"), "é")
     self.assertEqual(uni("Abreveacute"), "Ắ")
     self.assertEqual(uni("C-fraktur"), "ℭ")
     self.assertEqual(uni("Dboldscript-math"), "𝓓")
     self.assertEqual(uni("fi"), "fi")
     self.assertIsNone(uni("s_t"))  # no 'unicode' in GlyphsData
     self.assertEqual(uni("Gcommaaccent"), "Ģ")
     self.assertEqual(uni("o_f_f_i.foo"), "offi")
 def test_production_name(self):
     prod = lambda n: get_glyph(n).production_name
     self.assertEqual(prod(".notdef"), ".notdef")
     self.assertEqual(prod("eacute"), "eacute")
     self.assertEqual(prod("Abreveacute"), "uni1EAE")
     self.assertEqual(prod("C-fraktur"), "uni212D")
     self.assertEqual(prod("Dboldscript-math"), "u1D4D3")
     self.assertEqual(prod("fi"), "fi")
     self.assertEqual(prod("s_t"), "s_t")
     self.assertEqual(prod("Gcommaaccent"), "uni0122")
     self.assertEqual(prod("o_f_f_i.foo"), "o_f_f_i.foo")
 def test_production_name(self):
     # Our behavior differs from Glyphs, Glyphs 2.5.2 responses are in comments.
     prod = lambda n: get_glyph(n).production_name
     self.assertEqual(prod(".notdef"), ".notdef")
     self.assertEqual(prod("eacute"), "eacute")
     self.assertEqual(prod("Abreveacute"), "uni1EAE")
     self.assertEqual(prod("C-fraktur"), "uni212D")
     self.assertEqual(prod("Dboldscript-math"), "u1D4D3")
     self.assertEqual(prod("fi"), "fi")
     self.assertEqual(prod("s_t"), "s_t")
     self.assertEqual(prod("Gcommaaccent"), "uni0122")
     self.assertEqual(prod("o_f_f_i.foo"), "o_f_f_i.foo")
     self.assertEqual(prod("ain_alefMaksura-ar.fina"), "uniFD13")
     self.assertEqual(prod("brevecomb"), "uni0306")
     self.assertEqual(prod("brevecomb.case"), "uni0306.case")
     self.assertEqual(prod("brevecomb_acutecomb"), "uni03060301")
     self.assertEqual(prod("brevecomb_acutecomb.case"), "uni03060301.case")
     self.assertEqual(prod("brevecomb_a_a_a"), "uni0306006100610061")
     self.assertEqual(prod("brevecomb_a_a_a.case"),
                      "uni0306006100610061.case")
     self.assertEqual(prod("brevecomb_aaa.case"), "brevecomb_aaa.case")
     self.assertEqual(prod("brevecomb_Dboldscript-math"),
                      "uni0306_u1D4D3")  # brevecomb_Dboldscript-math
     self.assertEqual(
         prod("brevecomb_Dboldscript-math.f.r"),
         "uni0306_u1D4D3.f.r")  # brevecomb_Dboldscript-math.f.r
     self.assertEqual(prod("Dboldscript-math_Dboldscript-math"),
                      "u1D4D3_u1D4D3")
     self.assertEqual(prod("Dboldscript-math_Dboldscript-math.f"),
                      "u1D4D3_u1D4D3.f")
     self.assertEqual(prod("Dboldscript-math_a"), "u1D4D3_a")
     self.assertEqual(prod("a_Dboldscript-math"),
                      "a_u1D4D3")  # a_Dboldscript-math
     self.assertEqual(prod("Dboldscript-math_a_aa"),
                      "u1D4D3_a_uniA733")  # Dboldscript-math_a_aa
     self.assertEqual(prod("Dboldscript-math_a_aaa"),
                      "Dboldscript-math_a_aaa")
     self.assertEqual(prod("brevecomb_Dboldscript-math"),
                      "uni0306_u1D4D3")  # brevecomb_Dboldscript-math
     self.assertEqual(prod("Dboldscript-math_brevecomb"),
                      "u1D4D3_uni0306")  # Dboldscript-math_brevecomb
     self.assertEqual(prod("idotaccent"), "i.loclTRK")
     self.assertEqual(prod("a_idotaccent"), "a_i.loclTRK")
     self.assertEqual(prod("a_idotaccent_a"),
                      "a_idotaccent_a")  # a_i.loclTRK_a
     self.assertEqual(prod("a_a_acutecomb"), "a_a_acutecomb")
     self.assertEqual(prod("a_a_dieresiscomb"), "uni006100610308")
     self.assertEqual(prod("brevecomb_acutecomb"), "uni03060301")
     self.assertEqual(prod("vaphalaa-malayalam"), "uni0D030D35.1")
Exemple #8
0
 def __init__(self, path: str):
     self.font = self._load(path)
     self.math_tables = {}
     masters = sorted(self.font.masters, key=lambda m: m.weightValue)
     self._masters_num = len(masters)
     self._master_id_indices = {m.id: i for i, m in enumerate(masters)}
     self.interpolations: dict[str, tuple] = {
         i.name: [
             (self._master_id_indices[id], value)
             for id, value in i.instanceInterpolations.items()
         ]
         for i in self.font.instances if i.active
     }
     self.production_names: dict[str, str] = {
         g.name: glyphdata.get_glyph(g.name).production_name
         for g in self.font.glyphs
     }
     self._decompose_smart_comp()
Exemple #9
0
def test_data(glyphs, data):
    """Runs checks on the generated GlyphData

    Makes sure that the implementation of glyphsLib.glyphdata.get_glyph(),
    if it were to work on the generated GlyphData, will produce the exact
    same results as the original data files.
    """
    for _, glyph in sorted(glyphs.items()):
        name = glyph["name"]
        prod = glyph.get("production", name)
        unicode = glyph.get("unicode")
        unicode = unichr(int(unicode, 16)) if unicode else None
        category = glyph.get("category")
        subCategory = glyph.get("subCategory")
        g = get_glyph(name, data=data)
        assert name == g.name, (name, g.name)
        assert prod == g.production_name, (name, prod, g.production_name)
        assert unicode == g.unicode, (name, unicode, g.unicode)
        assert category == g.category, (name, category, g.category)
        assert subCategory == g.subCategory, (name, subCategory, g.subCategory)
Exemple #10
0
def to_ufo_glyph(self, ufo_glyph, layer, glyph_data):
    """Add .glyphs metadata, paths, components, and anchors to a glyph."""
    from glyphsLib import glyphdata  # Expensive import

    uval = glyph_data.unicode
    if uval is not None:
        ufo_glyph.unicode = int(uval, 16)
    note = glyph_data.note
    if note is not None:
        ufo_glyph.note = note
    last_change = glyph_data.lastChange
    if last_change is not None:
        ufo_glyph.lib[GLYPHLIB_PREFIX +
                      'lastChange'] = to_ufo_time(last_change)
    color_index = glyph_data.color
    if color_index is not None:
        ufo_glyph.lib[GLYPHLIB_PREFIX + 'ColorIndex'] = color_index
        color_tuple = None
        if isinstance(color_index, list):
            if not all(i in range(0, 256) for i in color_index):
                logger.warn('Invalid color tuple {} for glyph {}. '
                            'Values must be in range 0-255'.format(
                                color_index, glyph_data.name))
            else:
                color_tuple = ','.join(
                    '{0:.4f}'.format(i /
                                     255) if i in range(1, 255) else str(i //
                                                                         255)
                    for i in color_index)
        elif isinstance(color_index, int) and color_index in range(
                len(GLYPHS_COLORS)):
            color_tuple = GLYPHS_COLORS[color_index]
        else:
            logger.warn('Invalid color index {} for {}'.format(
                color_index, glyph_data.name))
        if color_tuple is not None:
            ufo_glyph.lib[PUBLIC_PREFIX + 'markColor'] = color_tuple
    export = glyph_data.export
    if not export:
        ufo_glyph.lib[GLYPHLIB_PREFIX + 'Export'] = export
    glyphinfo = glyphdata.get_glyph(ufo_glyph.name)
    production_name = glyph_data.production or glyphinfo.production_name
    if production_name != ufo_glyph.name:
        postscriptNamesKey = PUBLIC_PREFIX + 'postscriptNames'
        if postscriptNamesKey not in ufo_glyph.font.lib:
            ufo_glyph.font.lib[postscriptNamesKey] = dict()
        ufo_glyph.font.lib[postscriptNamesKey][
            ufo_glyph.name] = production_name

    for key in ['leftMetricsKey', 'rightMetricsKey', 'widthMetricsKey']:
        glyph_metrics_key = getattr(layer, key)
        if glyph_metrics_key is None:
            glyph_metrics_key = getattr(glyph_data, key)
        if glyph_metrics_key:
            ufo_glyph.lib[GLYPHLIB_PREFIX + key] = glyph_metrics_key

    # if glyph contains custom 'category' and 'subCategory' overrides, store
    # them in the UFO glyph's lib
    category = glyph_data.category
    if category is None:
        category = glyphinfo.category
    else:
        ufo_glyph.lib[GLYPHLIB_PREFIX + 'category'] = category
    subCategory = glyph_data.subCategory
    if subCategory is None:
        subCategory = glyphinfo.subCategory
    else:
        ufo_glyph.lib[GLYPHLIB_PREFIX + 'subCategory'] = subCategory

    # load width before background, which is loaded with lib data
    width = layer.width
    if width is None:
        pass
    elif category == 'Mark' and subCategory == 'Nonspacing' and width > 0:
        # zero the width of Nonspacing Marks like Glyphs.app does on export
        # TODO: check for customParameter DisableAllAutomaticBehaviour
        ufo_glyph.lib[GLYPHLIB_PREFIX + 'originalWidth'] = width
        ufo_glyph.width = 0
    else:
        ufo_glyph.width = width
    self.to_ufo_glyph_libdata(ufo_glyph, layer)

    pen = ufo_glyph.getPointPen()
    self.to_ufo_draw_paths(pen, layer.paths)
    self.to_ufo_draw_components(pen, layer.components)
    self.to_ufo_glyph_anchors(ufo_glyph, layer.anchors)
Exemple #11
0
            #     print axis, value.keys()[0], fontAxes["axis" + str(value.values()[0])]['nMax'], glyphSub
            # elif value.keys()[0] != None and bracketDefault == True:
            #     print axis, fontAxes["axis" + str(value.values()[0])]['nMin'], value.keys()[0], glyphSub
            if value.keys()[0] != None and bracketDefault == False:
                if firstRegion == False:
                    glyphString = glyphString + ", "
                glyphString = glyphString + "{\"" + axis + "\" : (" + str(
                    value.keys()[0]) + ", " + str(1.0) + ")}"
                firstRegion = False
            elif value.keys()[0] != None and bracketDefault == True:
                if firstRegion == False:
                    glyphString = glyphString + ", "
                glyphString = glyphString + "{\"" + axis + "\" : (" + str(
                    -1.0) + ", " + str(value.keys()[0]) + ")}"
                firstRegion = False
    glyphSub = "{\"" + get_glyph(
        needsDup[i])[1] + "\"" + " : " + "\"" + get_glyph(
            needsDup[i])[1] + suffix + "\"}"
    print "([" + glyphString + "], " + glyphSub + ")"
    if firstGlyph == True:
        glyphString = "\t([" + glyphString + "], " + glyphSub + "),"
    else:
        glyphString = " \n\t([" + glyphString + "], " + glyphSub + "),"
    substitution = substitution + glyphString
    firstGlyph = False

    # Move this to function?

    # Delete bracket layers now that they have been made master layers
    for layerId in delLayer:
        del font.glyphs[dupGlyph.name].layers[layerId]
        origGlyph = re.sub(suffix, "", dupGlyph.name)
Exemple #12
0
 def uni(n):
     return get_glyph(n).unicode
Exemple #13
0
# This script should be run from the command line for fixing glyph names that do not get properly converted when building with fontmake
# It is recommended to run this on a copy of your .glyphs file

import sys
import re
from glyphsLib.glyphdata import get_glyph
from glyphsLib import GSFont

filename = sys.argv[-1]
font = GSFont(filename)
changeName = {}

for glyph in font.glyphs:
	if re.match(".*-.*", get_glyph(glyph.name)[1]) != None:
		before = glyph.name
		glyph.name = re.sub("-", "_", glyph.name)
		after = glyph.name
		changeName.update({before:after})


for glyph in font.glyphs:
	for layer in glyph.layers:
		for component in layer.components:
			if component.name in changeName:
				component.name = changeName[component.name]


font.save(filename)

print "The glyphs: \n %s were renamed as \n %s" % (changeName.keys(), changeName.values())
Exemple #14
0
def to_ufo_glyph(self, ufo_glyph, layer, glyph):
    """Add .glyphs metadata, paths, components, and anchors to a glyph."""
    from glyphsLib import glyphdata  # Expensive import

    ufo_glyph.unicodes = [int(uval, 16) for uval in glyph.unicodes]
    note = glyph.note
    if note is not None:
        ufo_glyph.note = note
    last_change = glyph.lastChange
    if last_change is not None:
        ufo_glyph.lib[GLYPHLIB_PREFIX + "lastChange"] = to_ufo_time(last_change)

    color_index = glyph.color
    if color_index is not None:
        # .3f is enough precision to round-trip uint8 to float losslessly.
        # https://github.com/unified-font-object/ufo-spec/issues/61
        # #issuecomment-389759127
        if (
            isinstance(color_index, list)
            and len(color_index) == 4
            and all(0 <= v < 256 for v in color_index)
        ):
            ufo_glyph.markColor = ",".join(
                "{:.3f}".format(v / 255) for v in color_index
            )
        elif isinstance(color_index, int) and color_index in range(len(GLYPHS_COLORS)):
            ufo_glyph.markColor = GLYPHS_COLORS[color_index]
        else:
            logger.warning(
                "Glyph {}, layer {}: Invalid color index/tuple {}".format(
                    glyph.name, layer.name, color_index
                )
            )

    export = glyph.export
    if not export:
        ufo_glyph.lib[GLYPHLIB_PREFIX + "Export"] = export
    # FIXME: (jany) next line should be an API of GSGlyph?
    glyphinfo = glyphdata.get_glyph(ufo_glyph.name)
    production_name = glyph.production or glyphinfo.production_name
    if production_name != ufo_glyph.name:
        postscriptNamesKey = PUBLIC_PREFIX + "postscriptNames"
        if postscriptNamesKey not in ufo_glyph.font.lib:
            ufo_glyph.font.lib[postscriptNamesKey] = dict()
        ufo_glyph.font.lib[postscriptNamesKey][ufo_glyph.name] = production_name

    for key in ["leftMetricsKey", "rightMetricsKey", "widthMetricsKey"]:
        value = getattr(layer, key, None)
        if value:
            ufo_glyph.lib[GLYPHLIB_PREFIX + "layer." + key] = value
        value = getattr(glyph, key, None)
        if value:
            ufo_glyph.lib[GLYPHLIB_PREFIX + "glyph." + key] = value

    if glyph.script is not None:
        ufo_glyph.lib[SCRIPT_LIB_KEY] = glyph.script

    # if glyph contains custom 'category' and 'subCategory' overrides, store
    # them in the UFO glyph's lib
    category = glyph.category
    if category is None:
        category = glyphinfo.category
    else:
        ufo_glyph.lib[GLYPHLIB_PREFIX + "category"] = category
    subCategory = glyph.subCategory
    if subCategory is None:
        subCategory = glyphinfo.subCategory
    else:
        ufo_glyph.lib[GLYPHLIB_PREFIX + "subCategory"] = subCategory

    # load width before background, which is loaded with lib data
    width = layer.width
    if width is None:
        pass
    elif category == "Mark" and subCategory == "Nonspacing" and width > 0:
        # zero the width of Nonspacing Marks like Glyphs.app does on export
        # TODO: (jany) check for customParameter DisableAllAutomaticBehaviour
        # FIXME: (jany) also don't do that when rt UFO -> glyphs -> UFO
        ufo_glyph.lib[ORIGINAL_WIDTH_KEY] = width
        ufo_glyph.width = 0
    else:
        ufo_glyph.width = width

    self.to_ufo_background_image(ufo_glyph, layer)
    self.to_ufo_guidelines(ufo_glyph, layer)
    self.to_ufo_glyph_background(ufo_glyph, layer)
    self.to_ufo_annotations(ufo_glyph, layer)
    self.to_ufo_hints(ufo_glyph, layer)
    self.to_ufo_glyph_user_data(ufo_glyph.font, glyph)
    self.to_ufo_layer_user_data(ufo_glyph, layer)
    self.to_ufo_smart_component_axes(ufo_glyph, glyph)

    self.to_ufo_paths(ufo_glyph, layer)
    self.to_ufo_components(ufo_glyph, layer)
    self.to_ufo_glyph_anchors(ufo_glyph, layer.anchors)
Exemple #15
0
def _build_gdef(ufo):
    """Build a table GDEF statement for ligature carets."""
    from glyphsLib import glyphdata  # Expensive import

    bases, ligatures, marks, carets = set(), set(), set(), {}
    category_key = GLYPHLIB_PREFIX + 'category'
    subCategory_key = GLYPHLIB_PREFIX + 'subCategory'
    for glyph in ufo:
        has_attaching_anchor = False
        for anchor in glyph.anchors:
            name = anchor.name
            if name and not name.startswith('_'):
                has_attaching_anchor = True
            if name and name.startswith('caret_') and 'x' in anchor:
                carets.setdefault(glyph.name, []).append(round(anchor['x']))
        lib = glyph.lib
        glyphinfo = glyphdata.get_glyph(glyph.name)
        # first check glyph.lib for category/subCategory overrides; else use
        # global values from GlyphData
        category = lib.get(category_key)
        if category is None:
            category = glyphinfo.category
        subCategory = lib.get(subCategory_key)
        if subCategory is None:
            subCategory = glyphinfo.subCategory

        # Glyphs.app assigns glyph classes like this:
        #
        # * Base: any glyph that has an attaching anchor
        #   (such as "top"; "_top" does not count) and is neither
        #   classified as Ligature nor Mark using the definitions below;
        #
        # * Ligature: if subCategory is "Ligature" and the glyph has
        #   at least one attaching anchor;
        #
        # * Mark: if category is "Mark" and subCategory is either
        #   "Nonspacing" or "Spacing Combining";
        #
        # * Compound: never assigned by Glyphs.app.
        #
        # https://github.com/googlei18n/glyphsLib/issues/85
        # https://github.com/googlei18n/glyphsLib/pull/100#issuecomment-275430289
        if subCategory == 'Ligature' and has_attaching_anchor:
            ligatures.add(glyph.name)
        elif category == 'Mark' and (subCategory == 'Nonspacing' or
                                     subCategory == 'Spacing Combining'):
            marks.add(glyph.name)
        elif has_attaching_anchor:
            bases.add(glyph.name)
    if not any((bases, ligatures, marks, carets)):
        return None
    lines = ['table GDEF {', '  # automatic']
    glyphOrder = ufo.lib[PUBLIC_PREFIX + 'glyphOrder']
    glyphIndex = lambda glyph: glyphOrder.index(glyph)
    fmt = lambda g: ('[%s]' % ' '.join(sorted(g, key=glyphIndex))) if g else ''
    lines.extend([
        '  GlyphClassDef',
        '    %s, # Base' % fmt(bases),
        '    %s, # Liga' % fmt(ligatures),
        '    %s, # Mark' % fmt(marks),
        '    ;'])
    for glyph, caretPos in sorted(carets.items()):
        lines.append('  LigatureCaretByPos %s %s;' %
                     (glyph, ' '.join(unicode(p) for p in sorted(caretPos))))
    lines.append('} GDEF;')
    return '\n'.join(lines)
Exemple #16
0
            print "ERROR: More than 1 substitution detected for glyph \'%s\'" % needsDup[i]
            doNotSave = True
        else:
            axis = fontAxes["axis" + str(value.values()[0])]['tag']

            if value.keys()[0] != None and bracketDefault == False:
                if firstRegion == False:
                    glyphString = glyphString + ", "
                glyphString = glyphString + ("\"%s\" : (%s, %s)" % (axis, str(value.keys()[0]), str(1.0)))
                firstRegion = False
            elif value.keys()[0] != None and bracketDefault == True:
                if firstRegion == False:
                    glyphString = glyphString + ", "
                glyphString = glyphString + ("\"%s\" : (%s, %s)" % (axis, str(-1.0), str(value.keys()[0])))
                firstRegion = False
    glyphSub = "{\"%s\" : \"%s\"}" % (get_glyph(needsDup[i])[1], get_glyph(needsDup[i])[1] + suffix)
    print "([{%s}], %s)" % (glyphString, glyphSub)
    if firstGlyph == True:
        glyphString = "\t([{%s}], %s)," % (glyphString, glyphSub)
    else:
        glyphString = " \n\t([{%s}], %s)," % (glyphString, glyphSub)
    substitution = substitution + glyphString
    firstGlyph = False

# Move this to function?

    # Delete bracket layers now that they have been made master layers
    for layerId in delLayer:
        del font.glyphs[dupGlyph.name].layers[layerId]
        origGlyph = re.sub(suffix, "", dupGlyph.name)
        del font.glyphs[origGlyph].layers[layerId]
Exemple #17
0
 def cat(n):
     return get_glyph(n).category, get_glyph(n).subCategory
Exemple #18
0
def _build_gdef(ufo):
    """Build a GDEF table statement (GlyphClassDef and LigatureCaretByPos).

    Building GlyphClassDef requires anchor propagation or user care to work as
    expected, as Glyphs.app also looks at anchors for classification:

    * Base: any glyph that has an attaching anchor (such as "top"; "_top" does
      not count) and is neither classified as Ligature nor Mark using the
      definitions below;
    * Ligature: if subCategory is "Ligature" and the glyph has at least one
      attaching anchor;
    * Mark: if category is "Mark" and subCategory is either "Nonspacing" or
      "Spacing Combining";
    * Compound: never assigned by Glyphs.app.

    See:

    * https://github.com/googlei18n/glyphsLib/issues/85
    * https://github.com/googlei18n/glyphsLib/pull/100#issuecomment-275430289
    """
    from glyphsLib import glyphdata

    bases, ligatures, marks, carets = set(), set(), set(), {}
    category_key = GLYPHLIB_PREFIX + "category"
    subCategory_key = GLYPHLIB_PREFIX + "subCategory"

    for glyph in ufo:
        has_attaching_anchor = False
        for anchor in glyph.anchors:
            name = anchor.name
            if name and not name.startswith("_"):
                has_attaching_anchor = True
            if name and name.startswith("caret_") and "x" in anchor:
                carets.setdefault(glyph.name, []).append(round(anchor["x"]))

        # First check glyph.lib for category/subCategory overrides. Otherwise,
        # use global values from GlyphData.
        glyphinfo = glyphdata.get_glyph(glyph.name)
        category = glyph.lib.get(category_key) or glyphinfo.category
        subCategory = glyph.lib.get(subCategory_key) or glyphinfo.subCategory

        if subCategory == "Ligature" and has_attaching_anchor:
            ligatures.add(glyph.name)
        elif category == "Mark" and (subCategory == "Nonspacing"
                                     or subCategory == "Spacing Combining"):
            marks.add(glyph.name)
        elif has_attaching_anchor:
            bases.add(glyph.name)

    if not any((bases, ligatures, marks, carets)):
        return None

    def fmt(g):
        return ("[%s]" %
                " ".join(sorted(g, key=ufo.glyphOrder.index))) if g else ""

    lines = [
        "table GDEF {",
        "  # automatic",
        "  GlyphClassDef",
        "    %s, # Base" % fmt(bases),
        "    %s, # Liga" % fmt(ligatures),
        "    %s, # Mark" % fmt(marks),
        "    ;",
    ]
    for glyph, caretPos in sorted(carets.items()):
        lines.append("  LigatureCaretByPos %s %s;" %
                     (glyph, " ".join(unicode(p) for p in sorted(caretPos))))
    lines.append("} GDEF;")

    return "\n".join(lines)
Exemple #19
0
 def prod(n):
     return get_glyph(n).production_name