コード例 #1
0
def test_warn_diff_between_designspace_and_ufos(caplog):
    ufo = defcon.Font()
    ufo.info.familyName = 'UFO Family Name'
    ufo.info.styleName = 'UFO Style Name'
    # ufo.info.styleMapFamilyName = 'UFO Stylemap Family Name'
    # ufo.info.styleMapStyleName = 'bold'

    doc = DesignSpaceDocument()
    source = doc.newSourceDescriptor()
    source.font = ufo
    source.familyName = 'DS Family Name'
    source.styleName = 'DS Style Name'
    doc.addSource(source)

    font = to_glyphs(doc, minimize_ufo_diffs=True)
    assert any(record.levelname == 'WARNING' for record in caplog.records)
    assert 'The familyName is different between the UFO and the designspace source' in caplog.text
    assert 'The styleName is different between the UFO and the designspace source' in caplog.text

    doc = to_designspace(font)
    source = doc.sources[0]

    # The UFO info will prevail
    assert ufo.info.familyName == 'UFO Family Name'
    assert ufo.info.styleName == 'UFO Style Name'
    assert source.font.info.familyName == 'UFO Family Name'
    assert source.font.info.styleName == 'UFO Style Name'
コード例 #2
0
ファイル: build.py プロジェクト: urduclassics/rana-kufi
def buildVF(font, opts):
    for instance in font.instances:
        print(f" MASTER  {instance.name}")
        build(instance, opts)
        if instance.name == "Regular":
            regular = instance

    ds = DesignSpaceDocument()

    for axisDef in font.customParameters["Axes"]:
        axis = ds.newAxisDescriptor()
        axis.tag = axisDef["Tag"]
        axis.name = axisDef["Name"]
        axis.maximum = max(i.axes[axis.tag] for i in font.instances)
        axis.minimum = min(i.axes[axis.tag] for i in font.instances)
        axis.default = regular.axes[axis.tag]
        ds.addAxis(axis)

    for instance in font.instances:
        source = ds.newSourceDescriptor()
        source.font = instance.font
        source.familyName = instance.familyName
        source.styleName = instance.name
        source.name = instance.fullName
        source.location = {a.name: instance.axes[a.tag] for a in ds.axes}
        ds.addSource(source)

    print(f" MERGE   {font.familyName}")
    otf, _, _ = merge(ds)
    return otf
コード例 #3
0
def test_designspace_source_locations(tmpdir):
    """Check that opening UFOs from their source descriptor works with both
    the filename and the path attributes.
    """
    designspace_path = os.path.join(str(tmpdir), 'test.designspace')
    light_ufo_path = os.path.join(str(tmpdir), 'light.ufo')
    bold_ufo_path = os.path.join(str(tmpdir), 'bold.ufo')

    designspace = DesignSpaceDocument()
    light_source = designspace.newSourceDescriptor()
    light_source.filename = 'light.ufo'
    designspace.addSource(light_source)
    bold_source = designspace.newSourceDescriptor()
    bold_source.path = bold_ufo_path
    designspace.addSource(bold_source)
    designspace.write(designspace_path)

    light = defcon.Font()
    light.info.ascender = 30
    light.save(light_ufo_path)

    bold = defcon.Font()
    bold.info.ascender = 40
    bold.save(bold_ufo_path)

    designspace = DesignSpaceDocument()
    designspace.read(designspace_path)

    font = to_glyphs(designspace)

    assert len(font.masters) == 2
    assert font.masters[0].ascender == 30
    assert font.masters[1].ascender == 40
コード例 #4
0
def test_warn_diff_between_designspace_and_ufos(caplog, ufo_module):
    ufo = ufo_module.Font()
    ufo.info.familyName = "UFO Family Name"
    ufo.info.styleName = "UFO Style Name"
    # ufo.info.styleMapFamilyName = 'UFO Stylemap Family Name'
    # ufo.info.styleMapStyleName = 'bold'

    doc = DesignSpaceDocument()
    source = doc.newSourceDescriptor()
    source.font = ufo
    source.familyName = "DS Family Name"
    source.styleName = "DS Style Name"
    doc.addSource(source)

    font = to_glyphs(doc, minimize_ufo_diffs=True)
    assert any(record.levelname == "WARNING" for record in caplog.records)
    assert (
        "The familyName is different between the UFO and the designspace source"
        in caplog.text)
    assert (
        "The styleName is different between the UFO and the designspace source"
        in caplog.text)

    doc = to_designspace(font, ufo_module=ufo_module)
    source = doc.sources[0]

    # The UFO info will prevail
    assert ufo.info.familyName == "UFO Family Name"
    assert ufo.info.styleName == "UFO Style Name"
    assert source.font.info.familyName == "UFO Family Name"
    assert source.font.info.styleName == "UFO Style Name"
コード例 #5
0
def test_unicodes(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testUnicodes.designspace")
    testDocPath2 = os.path.join(tmpdir, "testUnicodes_roundtrip.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyInfo = True
    s1.location = dict(weight=0)
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.location = dict(weight=1000)
    doc.addSource(s2)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500)
    glyphData = dict(name="arrow", mute=True, unicodes=[100, 200, 300])
    i1.glyphs['arrow'] = glyphData
    doc.addInstance(i1)
    # now we have sources and instances, but no axes yet.
    doc.axes = []  # clear the axes
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    doc.addAxis(a1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)
    new.write(testDocPath2)
    # compare the file contents
    f1 = open(testDocPath, 'r', encoding='utf-8')
    t1 = f1.read()
    f1.close()
    f2 = open(testDocPath2, 'r', encoding='utf-8')
    t2 = f2.read()
    f2.close()
    assert t1 == t2
    # check the unicode values read from the document
    assert new.instances[0].glyphs['arrow']['unicodes'] == [100, 200, 300]
コード例 #6
0
def test_unicodes(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testUnicodes.designspace")
    testDocPath2 = os.path.join(tmpdir, "testUnicodes_roundtrip.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyInfo = True
    s1.location = dict(weight=0)
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.location = dict(weight=1000)
    doc.addSource(s2)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500)
    glyphData = dict(name="arrow", mute=True, unicodes=[100, 200, 300])
    i1.glyphs['arrow'] = glyphData
    doc.addInstance(i1)
    # now we have sources and instances, but no axes yet.
    doc.axes = []   # clear the axes
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    doc.addAxis(a1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)
    new.write(testDocPath2)
    # compare the file contents
    with open(testDocPath, 'r', encoding='utf-8') as f1:
        t1 = f1.read()
    with open(testDocPath2, 'r', encoding='utf-8') as f2:
        t2 = f2.read()
    assert t1 == t2
    # check the unicode values read from the document
    assert new.instances[0].glyphs['arrow']['unicodes'] == [100,200,300]
コード例 #7
0
def test_load_masters_layerName_without_required_font():
    ds = DesignSpaceDocument()
    s = SourceDescriptor()
    s.font = None
    s.layerName = "Medium"
    ds.addSource(s)

    with pytest.raises(
            AttributeError,
            match="specified a layer name but lacks the required TTFont object",
    ):
        load_masters(ds)
コード例 #8
0
ファイル: varLib_test.py プロジェクト: behdad/fonttools
def test_load_masters_layerName_without_required_font():
    ds = DesignSpaceDocument()
    s = SourceDescriptor()
    s.font = None
    s.layerName = "Medium"
    ds.addSource(s)

    with pytest.raises(
        AttributeError,
        match="specified a layer name but lacks the required TTFont object",
    ):
        load_masters(ds)
コード例 #9
0
def test_adjustAxisDefaultToNeutral(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir,
                               "testAdjustAxisDefaultToNeutral.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(weight=55, width=1000)
    doc.addSource(s1)
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0  # the wrong value
    a1.name = "weight"
    a1.tag = "wght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = -10
    a2.maximum = 10
    a2.default = 0  # the wrong value
    a2.name = "width"
    a2.tag = "wdth"
    doc.addAxis(a2)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)
    new.check()
    loc = new.default.location
    for axisObj in new.axes:
        n = axisObj.name
        assert axisObj.default == loc.get(n)
コード例 #10
0
def test_designspace_source_locations(tmpdir, ufo_module):
    """Check that opening UFOs from their source descriptor works with both
    the filename and the path attributes.
    """
    designspace_path = os.path.join(str(tmpdir), "test.designspace")
    light_ufo_path = os.path.join(str(tmpdir), "light.ufo")
    bold_ufo_path = os.path.join(str(tmpdir), "bold.ufo")

    designspace = DesignSpaceDocument()
    wght = AxisDescriptor()
    wght.minimum = 100
    wght.maximum = 700
    wght.default = 100
    wght.name = "Weight"
    wght.tag = "wght"
    designspace.addAxis(wght)
    light_source = designspace.newSourceDescriptor()
    light_source.filename = "light.ufo"
    light_source.location = {"Weight": 100}
    designspace.addSource(light_source)
    bold_source = designspace.newSourceDescriptor()
    bold_source.path = bold_ufo_path
    bold_source.location = {"Weight": 700}
    designspace.addSource(bold_source)
    designspace.write(designspace_path)

    light = ufo_module.Font()
    light.info.ascender = 30
    light.save(light_ufo_path)

    bold = ufo_module.Font()
    bold.info.ascender = 40
    bold.save(bold_ufo_path)

    designspace = DesignSpaceDocument()
    designspace.read(designspace_path)

    font = to_glyphs(designspace, ufo_module=ufo_module)

    assert len(font.masters) == 2
    assert font.masters[0].ascender == 30
    assert font.masters[1].ascender == 40
コード例 #11
0
def test_updatePaths(tmpdir):
    doc = DesignSpaceDocument()
    doc.path = str(tmpdir / "foo" / "bar" / "MyDesignspace.designspace")

    s1 = SourceDescriptor()
    doc.addSource(s1)

    doc.updatePaths()

    # expect no changes
    assert s1.path is None
    assert s1.filename is None

    name1 = "../masters/Source1.ufo"
    path1 = posix(str(tmpdir / "foo" / "masters" / "Source1.ufo"))

    s1.path = path1
    s1.filename = None

    doc.updatePaths()

    assert s1.path == path1
    assert s1.filename == name1  # empty filename updated

    name2 = "../masters/Source2.ufo"
    s1.filename = name2

    doc.updatePaths()

    # conflicting filename discarded, path always gets precedence
    assert s1.path == path1
    assert s1.filename == "../masters/Source1.ufo"

    s1.path = None
    s1.filename = name2

    doc.updatePaths()

    # expect no changes
    assert s1.path is None
    assert s1.filename == name2
コード例 #12
0
def test_updatePaths(tmpdir):
    doc = DesignSpaceDocument()
    doc.path = str(tmpdir / "foo" / "bar" / "MyDesignspace.designspace")

    s1 = SourceDescriptor()
    doc.addSource(s1)

    doc.updatePaths()

    # expect no changes
    assert s1.path is None
    assert s1.filename is None

    name1 = "../masters/Source1.ufo"
    path1 = posix(str(tmpdir / "foo" / "masters" / "Source1.ufo"))

    s1.path = path1
    s1.filename = None

    doc.updatePaths()

    assert s1.path == path1
    assert s1.filename == name1  # empty filename updated

    name2 = "../masters/Source2.ufo"
    s1.filename = name2

    doc.updatePaths()

    # conflicting filename discarded, path always gets precedence
    assert s1.path == path1
    assert s1.filename == "../masters/Source1.ufo"

    s1.path = None
    s1.filename = name2

    doc.updatePaths()

    # expect no changes
    assert s1.path is None
    assert s1.filename == name2
コード例 #13
0
ファイル: build.py プロジェクト: alif-type/rana-kufi
def buildVF(opts):
    font = GSFont(opts.glyphs)
    glyphOrder = buildAltGlyphs(font)
    prepare(font)

    for instance in font.instances:
        print(f" MASTER  {instance.name}")
        build(instance, opts, glyphOrder)
        if instance.name == "Regular":
            regular = instance

    ds = DesignSpaceDocument()

    for i, axisDef in enumerate(font.axes):
        axis = ds.newAxisDescriptor()
        axis.tag = axisDef.axisTag
        axis.name = axisDef.name
        axis.maximum = max(x.axes[i] for x in font.instances)
        axis.minimum = min(x.axes[i] for x in font.instances)
        axis.default = regular.axes[i]
        ds.addAxis(axis)

    for instance in font.instances:
        source = ds.newSourceDescriptor()
        source.font = instance.font
        source.familyName = instance.familyName
        source.styleName = instance.name
        source.name = instance.fullName
        source.location = {
            a.name: instance.axes[i]
            for i, a in enumerate(ds.axes)
        }
        ds.addSource(source)

    print(f" MERGE   {font.familyName}")
    otf, _, _ = merge(ds)
    subroutinize(otf)
    if not opts.debug:
        otf["post"].formatType = 3.0
    return otf
コード例 #14
0
def test_ufo_filename_is_kept_the_same(tmpdir, ufo_module):
    """Check that the filenames of existing UFOs are correctly written to
    the designspace document when doing UFOs -> Glyphs -> designspace.
    This only works when the option "minimize_ufo_diffs" is given, because
    keeping track of this information adds stuff to the Glyphs file.
    """
    light_ufo_path = os.path.join(str(tmpdir), "light.ufo")
    bold_ufo_path = os.path.join(str(tmpdir), "subdir/bold.ufo")

    light = ufo_module.Font()
    light.info.ascender = 30
    light.save(light_ufo_path)

    bold = ufo_module.Font()
    bold.info.ascender = 40
    bold.save(bold_ufo_path)

    # First check: when going from UFOs -> Glyphs -> designspace
    font = to_glyphs([light, bold], minimize_ufo_diffs=True)

    designspace = to_designspace(font, ufo_module=ufo_module)
    assert designspace.sources[0].path == light_ufo_path
    assert designspace.sources[1].path == bold_ufo_path

    # Second check: going from designspace -> Glyphs -> designspace
    designspace_path = os.path.join(str(tmpdir), "test.designspace")
    designspace = DesignSpaceDocument()
    light_source = designspace.newSourceDescriptor()
    light_source.filename = "light.ufo"
    designspace.addSource(light_source)
    bold_source = designspace.newSourceDescriptor()
    bold_source.path = bold_ufo_path
    designspace.addSource(bold_source)
    designspace.write(designspace_path)

    font = to_glyphs([light, bold], minimize_ufo_diffs=True)

    assert designspace.sources[0].filename == "light.ufo"
    assert designspace.sources[1].filename == "subdir/bold.ufo"
コード例 #15
0
def buildDesignSpace(sources, instances, axes):
    doc = DesignSpaceDocument()
    # build source descriptors from source list
    for source in sources:
        s = SourceDescriptor()
        s.path = source["path"]
        s.name = source["name"]
        s.copyInfo = source["copyInfo"]
        s.location = source["location"]
        s.familyName = source["familyName"]
        s.styleName = source["styleName"]
        doc.addSource(s)
    # build instance descriptors from instance list
    for instance in instances:
        i = InstanceDescriptor()
        i.location = instance["location"]
        i.familyName = instance["familyName"]
        i.styleName = instance["styleName"]
        i.path = instance["path"]
        i.postScriptFontName = instance["postScriptFontName"]
        i.styleMapFamilyName = instance["styleMapFamilyName"]
        i.styleMapStyleName = instance["styleMapStyleName"]
        doc.addInstance(i)
    # build axis descriptors from axis list
    for axis in axes:
        a = AxisDescriptor()
        a.minimum = axis["minimum"]
        a.maximum = axis["maximum"]
        a.default = axis["default"]
        a.name = axis["name"]
        a.tag = axis["tag"]
        for languageCode, labelName in axis["labelNames"].items():
            a.labelNames[languageCode] = labelName
        a.map = axis["map"]
        doc.addAxis(a)
    return doc
コード例 #16
0
def test_pathNameResolve(tmpdir):
    tmpdir = str(tmpdir)
    # test how descriptor.path and descriptor.filename are resolved
    testDocPath1 = os.path.join(tmpdir, "testPathName_case1.designspace")
    testDocPath2 = os.path.join(tmpdir, "testPathName_case2.designspace")
    testDocPath3 = os.path.join(tmpdir, "testPathName_case3.designspace")
    testDocPath4 = os.path.join(tmpdir, "testPathName_case4.designspace")
    testDocPath5 = os.path.join(tmpdir, "testPathName_case5.designspace")
    testDocPath6 = os.path.join(tmpdir, "testPathName_case6.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")

    a1 = AxisDescriptor()
    a1.tag = "TAGA"
    a1.name = "axisName_a"
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0

    # Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = None
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath1)
    verify = DesignSpaceDocument()
    verify.read(testDocPath1)
    assert verify.sources[0].filename == None
    assert verify.sources[0].path == None

    # Case 2: filename is empty, path points somewhere: calculate a new filename.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath2)
    verify = DesignSpaceDocument()
    verify.read(testDocPath2)
    assert verify.sources[0].filename == "masters/masterTest1.ufo"
    assert verify.sources[0].path == posix(masterPath1)

    # Case 3: the filename is set, the path is None.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = None
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath3)
    verify = DesignSpaceDocument()
    verify.read(testDocPath3)
    assert verify.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
    # make the absolute path for filename so we can see if it matches the path
    p = os.path.abspath(os.path.join(os.path.dirname(testDocPath3), verify.sources[0].filename))
    assert verify.sources[0].path == posix(p)

    # Case 4: the filename points to one file, the path points to another. The path takes precedence.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath4)
    verify = DesignSpaceDocument()
    verify.read(testDocPath4)
    assert verify.sources[0].filename == "masters/masterTest1.ufo"

    # Case 5: the filename is None, path has a value, update the filename
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath5) # so that the document has a path
    doc.updateFilenameFromPath()
    assert doc.sources[0].filename == "masters/masterTest1.ufo"

    # Case 6: the filename has a value, path has a value, update the filenames with force
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.write(testDocPath5) # so that the document has a path
    doc.addSource(s)
    assert doc.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
    doc.updateFilenameFromPath(force=True)
    assert doc.sources[0].filename == "masters/masterTest1.ufo"
コード例 #17
0
def test_check(invalid_designspace, tmpdir):
    tmpdir = str(tmpdir)
    # check if the checks are checking
    testDocPath = os.path.join(tmpdir, invalid_designspace)
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")

    # no default selected
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.path = masterPath1
    s1.name = "master.ufo1"
    s1.location = dict(snap=0, pop=10)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.path = masterPath2
    s2.name = "master.ufo2"
    s2.location = dict(snap=1000, pop=20)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    doc.checkAxes()
    doc.getAxisOrder() == ['snap', 'pop']
    assert doc.default == None
    doc.checkDefault()
    assert doc.default.name == 'master.ufo1'

    # default selected
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.path = masterPath1
    s1.name = "master.ufo1"
    s1.location = dict(snap=0, pop=10)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.path = masterPath2
    s2.name = "master.ufo2"
    s2.copyInfo = True
    s2.location = dict(snap=1000, pop=20)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    doc.checkAxes()
    assert doc.getAxisOrder() == ['snap', 'pop']
    assert doc.default == None
    doc.checkDefault()
    assert doc.default.name == 'master.ufo2'

    # generate a doc without axes, save and read again
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.path = masterPath1
    s1.name = "master.ufo1"
    s1.location = dict(snap=0, pop=10)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.path = masterPath2
    s2.name = "master.ufo2"
    s2.location = dict(snap=1000, pop=20)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    doc.checkAxes()
    doc.write(testDocPath)
    __removeAxesFromDesignSpace(testDocPath)

    new = DesignSpaceDocument()
    new.read(testDocPath)
    assert len(new.axes) == 2
    new.checkAxes()
    assert len(new.axes) == 2
    assert print([a.name for a in new.axes]) == ['snap', 'pop']
    new.write(testDocPath)
コード例 #18
0
def test_pathNameResolve(tmpdir):
    tmpdir = str(tmpdir)
    # test how descriptor.path and descriptor.filename are resolved
    testDocPath1 = os.path.join(tmpdir, "testPathName_case1.designspace")
    testDocPath2 = os.path.join(tmpdir, "testPathName_case2.designspace")
    testDocPath3 = os.path.join(tmpdir, "testPathName_case3.designspace")
    testDocPath4 = os.path.join(tmpdir, "testPathName_case4.designspace")
    testDocPath5 = os.path.join(tmpdir, "testPathName_case5.designspace")
    testDocPath6 = os.path.join(tmpdir, "testPathName_case6.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")

    a1 = AxisDescriptor()
    a1.tag = "TAGA"
    a1.name = "axisName_a"
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0

    # Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = None
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath1)
    verify = DesignSpaceDocument()
    verify.read(testDocPath1)
    assert verify.sources[0].filename == None
    assert verify.sources[0].path == None

    # Case 2: filename is empty, path points somewhere: calculate a new filename.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath2)
    verify = DesignSpaceDocument()
    verify.read(testDocPath2)
    assert verify.sources[0].filename == "masters/masterTest1.ufo"
    assert verify.sources[0].path == posix(masterPath1)

    # Case 3: the filename is set, the path is None.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = None
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath3)
    verify = DesignSpaceDocument()
    verify.read(testDocPath3)
    assert verify.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
    # make the absolute path for filename so we can see if it matches the path
    p = os.path.abspath(os.path.join(os.path.dirname(testDocPath3), verify.sources[0].filename))
    assert verify.sources[0].path == posix(p)

    # Case 4: the filename points to one file, the path points to another. The path takes precedence.
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath4)
    verify = DesignSpaceDocument()
    verify.read(testDocPath4)
    assert verify.sources[0].filename == "masters/masterTest1.ufo"

    # Case 5: the filename is None, path has a value, update the filename
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = None
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.addSource(s)
    doc.write(testDocPath5) # so that the document has a path
    doc.updateFilenameFromPath()
    assert doc.sources[0].filename == "masters/masterTest1.ufo"

    # Case 6: the filename has a value, path has a value, update the filenames with force
    doc = DesignSpaceDocument()
    doc.addAxis(a1)
    s = SourceDescriptor()
    s.filename = "../somewhere/over/the/rainbow.ufo"
    s.path = masterPath1
    s.copyInfo = True
    s.location = dict(weight=0)
    s.familyName = "MasterFamilyName"
    s.styleName = "MasterStyleNameOne"
    doc.write(testDocPath5) # so that the document has a path
    doc.addSource(s)
    assert doc.sources[0].filename == "../somewhere/over/the/rainbow.ufo"
    doc.updateFilenameFromPath(force=True)
    assert doc.sources[0].filename == "masters/masterTest1.ufo"
コード例 #19
0
def test_fill_document(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "test.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()

    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    # note: just to test the element language, not an actual label name recommendations.
    a1.labelNames[u'fa-IR'] = u"قطر"
    a1.labelNames[u'en'] = u"Wéíght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = 0
    a2.maximum = 1000
    a2.default = 15
    a2.name = "width"
    a2.tag = "wdth"
    a2.map = [(0.0, 10.0), (15.0, 20.0), (401.0, 66.0), (1000.0, 990.0)]
    a2.hidden = True
    a2.labelNames[u'fr'] = u"Chasse"
    doc.addAxis(a2)

    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    assert s1.font is None
    s1.name = "master.ufo1"
    s1.copyLib = True
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(weight=0)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    s1.mutedGlyphNames.append("A")
    s1.mutedGlyphNames.append("Z")
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.copyLib = False
    s2.copyInfo = False
    s2.copyFeatures = False
    s2.muteKerning = True
    s2.location = dict(weight=1000)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    # add master 3 from a different layer
    s3 = SourceDescriptor()
    s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s3.name = "master.ufo2"
    s3.copyLib = False
    s3.copyInfo = False
    s3.copyFeatures = False
    s3.muteKerning = False
    s3.layerName = "supports"
    s3.location = dict(weight=1000)
    s3.familyName = "MasterFamilyName"
    s3.styleName = "Supports"
    doc.addSource(s3)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "InstanceFamilyName"
    i1.styleName = "InstanceStyleName"
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500, spooky=666)  # this adds a dimension that is not defined.
    i1.postScriptFontName = "InstancePostscriptName"
    i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i1.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125])
    i1.glyphs['arrow'] = glyphData
    i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>')
    i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever"
    doc.addInstance(i1)
    # add instance 2
    i2 = InstanceDescriptor()
    i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath))
    i2.familyName = "InstanceFamilyName"
    i2.styleName = "InstanceStyleName"
    i2.name = "instance.ufo2"
    # anisotropic location
    i2.location = dict(weight=500, width=(400,300))
    i2.postScriptFontName = "InstancePostscriptName"
    i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i2.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphMasters = [dict(font="master.ufo1", glyphName="BB", location=dict(width=20,weight=20)), dict(font="master.ufo2", glyphName="CC", location=dict(width=900,weight=900))]
    glyphData = dict(name="arrow", unicodes=[101, 201, 301])
    glyphData['masters'] = glyphMasters
    glyphData['note'] = "A note about this glyph"
    glyphData['instanceLocation'] = dict(width=100, weight=120)
    i2.glyphs['arrow'] = glyphData
    i2.glyphs['arrow2'] = dict(mute=False)
    doc.addInstance(i2)

    doc.filename = "suggestedFileName.designspace"
    doc.lib['com.coolDesignspaceApp.previewSize'] = 30

    # write some rules
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='axisName_a', minimum=0, maximum=1),
        dict(name='axisName_b', minimum=2, maximum=3)
    ])
    r1.subs.append(("a", "a.alt"))
    doc.addRule(r1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    assert_equals_test_file(testDocPath, 'data/test.designspace')
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)

    assert new.default.location == {'width': 20.0, 'weight': 0.0}
    assert new.filename == 'test.designspace'
    assert new.lib == doc.lib
    assert new.instances[0].lib == doc.instances[0].lib

    # test roundtrip for the axis attributes and data
    axes = {}
    for axis in doc.axes:
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for axis in new.axes:
        if axis.tag[0] == "_":
            continue
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for v in axes.values():
        a, b = v
        assert a == b
コード例 #20
0
def test_localisedNames(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testLocalisedNames.designspace")
    testDocPath2 = os.path.join(tmpdir, "testLocalisedNames_roundtrip.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyInfo = True
    s1.location = dict(weight=0)
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.location = dict(weight=1000)
    doc.addSource(s2)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "Montserrat"
    i1.styleName = "SemiBold"
    i1.styleMapFamilyName = "Montserrat SemiBold"
    i1.styleMapStyleName = "Regular"
    i1.setFamilyName("Montserrat", "fr")
    i1.setFamilyName(u"モンセラート", "ja")
    i1.setStyleName("Demigras", "fr")
    i1.setStyleName(u"半ば", "ja")
    i1.setStyleMapStyleName(u"Standard", "de")
    i1.setStyleMapFamilyName("Montserrat Halbfett", "de")
    i1.setStyleMapFamilyName(u"モンセラート SemiBold", "ja")
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500, spooky=666)  # this adds a dimension that is not defined.
    i1.postScriptFontName = "InstancePostscriptName"
    glyphData = dict(name="arrow", mute=True, unicodes=[0x123])
    i1.glyphs['arrow'] = glyphData
    doc.addInstance(i1)
    # now we have sources and instances, but no axes yet.
    doc.axes = []   # clear the axes
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    # note: just to test the element language, not an actual label name recommendations.
    a1.labelNames[u'fa-IR'] = u"قطر"
    a1.labelNames[u'en'] = u"Wéíght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = 0
    a2.maximum = 1000
    a2.default = 0
    a2.name = "width"
    a2.tag = "wdth"
    a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    a2.labelNames[u'fr'] = u"Poids"
    doc.addAxis(a2)
    # add an axis that is not part of any location to see if that works
    a3 = AxisDescriptor()
    a3.minimum = 333
    a3.maximum = 666
    a3.default = 444
    a3.name = "spooky"
    a3.tag = "spok"
    a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    #doc.addAxis(a3)    # uncomment this line to test the effects of default axes values
    # write some rules
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='weight', minimum=200, maximum=500),
        dict(name='width', minimum=0, maximum=150)
    ])
    r1.subs.append(("a", "a.alt"))
    doc.addRule(r1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)
    new.write(testDocPath2)
    with open(testDocPath, 'r', encoding='utf-8') as f1:
        t1 = f1.read()
    with open(testDocPath2, 'r', encoding='utf-8') as f2:
        t2 = f2.read()
    assert t1 == t2
コード例 #21
0
def test_handleNoAxes(tmpdir):
    tmpdir = str(tmpdir)
    # test what happens if the designspacedocument has no axes element.
    testDocPath = os.path.join(tmpdir, "testNoAxes_source.designspace")
    testDocPath2 = os.path.join(tmpdir, "testNoAxes_recontructed.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")

    # Case 1: No axes element in the document, but there are sources and instances
    doc = DesignSpaceDocument()

    for name, value in [('One', 1),('Two', 2),('Three', 3)]:
        a = AxisDescriptor()
        a.minimum = 0
        a.maximum = 1000
        a.default = 0
        a.name = "axisName%s" % (name)
        a.tag = "ax_%d" % (value)
        doc.addAxis(a)

    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyLib = True
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(axisNameOne=-1000, axisNameTwo=0, axisNameThree=1000)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    doc.addSource(s1)

    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo1"
    s2.copyLib = False
    s2.copyInfo = False
    s2.copyFeatures = False
    s2.location = dict(axisNameOne=1000, axisNameTwo=1000, axisNameThree=0)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)

    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "InstanceFamilyName"
    i1.styleName = "InstanceStyleName"
    i1.name = "instance.ufo1"
    i1.location = dict(axisNameOne=(-1000,500), axisNameTwo=100)
    i1.postScriptFontName = "InstancePostscriptName"
    i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i1.styleMapStyleName = "InstanceStyleMapStyleName"
    doc.addInstance(i1)

    doc.write(testDocPath)
    verify = DesignSpaceDocument()
    verify.read(testDocPath)
    verify.write(testDocPath2)
コード例 #22
0
def test_handleNoAxes(tmpdir):
    tmpdir = str(tmpdir)
    # test what happens if the designspacedocument has no axes element.
    testDocPath = os.path.join(tmpdir, "testNoAxes_source.designspace")
    testDocPath2 = os.path.join(tmpdir, "testNoAxes_recontructed.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")

    # Case 1: No axes element in the document, but there are sources and instances
    doc = DesignSpaceDocument()

    for name, value in [('One', 1),('Two', 2),('Three', 3)]:
        a = AxisDescriptor()
        a.minimum = 0
        a.maximum = 1000
        a.default = 0
        a.name = "axisName%s" % (name)
        a.tag = "ax_%d" % (value)
        doc.addAxis(a)

    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyLib = True
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(axisNameOne=-1000, axisNameTwo=0, axisNameThree=1000)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    doc.addSource(s1)

    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo1"
    s2.copyLib = False
    s2.copyInfo = False
    s2.copyFeatures = False
    s2.location = dict(axisNameOne=1000, axisNameTwo=1000, axisNameThree=0)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)

    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "InstanceFamilyName"
    i1.styleName = "InstanceStyleName"
    i1.name = "instance.ufo1"
    i1.location = dict(axisNameOne=(-1000,500), axisNameTwo=100)
    i1.postScriptFontName = "InstancePostscriptName"
    i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i1.styleMapStyleName = "InstanceStyleMapStyleName"
    doc.addInstance(i1)

    doc.write(testDocPath)
    verify = DesignSpaceDocument()
    verify.read(testDocPath)
    verify.write(testDocPath2)
コード例 #23
0
#---------
# masters
#---------

s0 = SourceDescriptor()
s0.path = "PaperOn.ufo"
s0.name = "master.PaperFont.PaperOn.0"
s0.familyName = familyName
s0.styleName = "Light"
s0.location = dict(weight=0, width=0)
s0.copyLib = True
s0.copyInfo = True
s0.copyGroups = True
s0.copyFeatures = True
doc.addSource(s0)

s1 = SourceDescriptor()
s1.path = "PaperOff.ufo"
s0.name = "master.PaperFont.PaperOff.0"
s1.familyName = familyName
s1.styleName = "Bold"
s1.location = dict(weight=1000, width=0)
doc.addSource(s1)

#--------
# saving
#--------

path = os.path.join(root, "PaperFont.designspace")
doc.write(path)
コード例 #24
0
def test_fill_document(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "test.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()

    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    # note: just to test the element language, not an actual label name recommendations.
    a1.labelNames[u'fa-IR'] = u"قطر"
    a1.labelNames[u'en'] = u"Wéíght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = 0
    a2.maximum = 1000
    a2.default = 20
    a2.name = "width"
    a2.tag = "wdth"
    a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    a2.hidden = True
    a2.labelNames[u'fr'] = u"Chasse"
    doc.addAxis(a2)

    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    assert s1.font is None
    s1.name = "master.ufo1"
    s1.copyLib = True
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(weight=0)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    s1.mutedGlyphNames.append("A")
    s1.mutedGlyphNames.append("Z")
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.copyLib = False
    s2.copyInfo = False
    s2.copyFeatures = False
    s2.muteKerning = True
    s2.location = dict(weight=1000)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    # add master 3 from a different layer
    s3 = SourceDescriptor()
    s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s3.name = "master.ufo2"
    s3.copyLib = False
    s3.copyInfo = False
    s3.copyFeatures = False
    s3.muteKerning = False
    s3.layerName = "supports"
    s3.location = dict(weight=1000)
    s3.familyName = "MasterFamilyName"
    s3.styleName = "Supports"
    doc.addSource(s3)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "InstanceFamilyName"
    i1.styleName = "InstanceStyleName"
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500, spooky=666)  # this adds a dimension that is not defined.
    i1.postScriptFontName = "InstancePostscriptName"
    i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i1.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125])
    i1.glyphs['arrow'] = glyphData
    i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>')
    i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever"
    doc.addInstance(i1)
    # add instance 2
    i2 = InstanceDescriptor()
    i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath))
    i2.familyName = "InstanceFamilyName"
    i2.styleName = "InstanceStyleName"
    i2.name = "instance.ufo2"
    # anisotropic location
    i2.location = dict(weight=500, width=(400,300))
    i2.postScriptFontName = "InstancePostscriptName"
    i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i2.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphMasters = [dict(font="master.ufo1", glyphName="BB", location=dict(width=20,weight=20)), dict(font="master.ufo2", glyphName="CC", location=dict(width=900,weight=900))]
    glyphData = dict(name="arrow", unicodes=[101, 201, 301])
    glyphData['masters'] = glyphMasters
    glyphData['note'] = "A note about this glyph"
    glyphData['instanceLocation'] = dict(width=100, weight=120)
    i2.glyphs['arrow'] = glyphData
    i2.glyphs['arrow2'] = dict(mute=False)
    doc.addInstance(i2)

    doc.filename = "suggestedFileName.designspace"
    doc.lib['com.coolDesignspaceApp.previewSize'] = 30

    # write some rules
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='axisName_a', minimum=0, maximum=1),
        dict(name='axisName_b', minimum=2, maximum=3)
    ])
    r1.subs.append(("a", "a.alt"))
    doc.addRule(r1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    assert_equals_test_file(testDocPath, 'data/test.designspace')
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)

    assert new.default.location == {'width': 20.0, 'weight': 0.0}
    assert new.filename == 'test.designspace'
    assert new.lib == doc.lib
    assert new.instances[0].lib == doc.instances[0].lib

    # test roundtrip for the axis attributes and data
    axes = {}
    for axis in doc.axes:
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for axis in new.axes:
        if axis.tag[0] == "_":
            continue
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for v in axes.values():
        a, b = v
        assert a == b
コード例 #25
0
ファイル: RotateMaster.py プロジェクト: bghryct/Tilt-Typeface
def buildDesignSpace(masterFont=None,
                     destPath=None,
                     glyphNames=[],
                     compositionType="rotate",
                     outlineAmount=None,
                     zOffset=None,
                     shadowLengthFactor=1,
                     doForceSmooth=False,
                     doMakeSubSources=False,
                     familyName=None,
                     alwaysConnect=False,
                     cap="RoundSimple",
                     connection="Round",
                     layerName=None,
                     styleName=None):

    # Open the master UFO
    if type(masterFont) == str:
        masterFont = OpenFont(masterFont, showInterface=False)

    # Get the master file name, if it's saved
    basePath = None
    masterFileName = "Font"
    if masterFont.path:
        basePath, masterFileName = os.path.split(masterFont.path)

    # Try to make a dest path, if there isn't one
    if destPath == None:
        if basePath:
            destPath = os.path.join(basePath, "Rotated")

    # Make new folders for the destPath
    if not os.path.exists(destPath):
        os.makedirs(destPath)

    # Use all glyphs, if no names are called for
    if glyphNames == []:
        glyphNames = list(masterFont.keys())
        glyphNames.sort()

    # Default names
    if not familyName:
        familyName = masterFont.info.familyName
    if not styleName:
        styleName = "Regular"
    """ Collect glyph data """
    # Organize the point data out of the glyph lib
    # and check to see which glyphs need to be present in a SubSource
    glyphPointData = {}
    needSubHROT = [
    ]  # Glyphs that need to be included in a SubSource when HROT is default
    needSubVROT = []
    for gName in glyphNames:
        if gName in masterFont:
            g = masterFont[gName]
            if layerName:
                # Copy point data to the layer
                if ZPOSITIONLIBKEY in g.lib.keys():
                    libdata = copy.deepcopy(g.lib[ZPOSITIONLIBKEY])
                else:
                    libdata = {}
                g = g.getLayer(layerName)
                g.lib[ZPOSITIONLIBKEY] = libdata
            pointData = readGlyphPointData(g)
            glyphPointData[gName] = pointData
            # Test for self-overlapping contours
            if doMakeSubSources == True:
                overlapResult = checkCurveOverlap(g)
                if "x" in overlapResult:
                    needSubHROT.append(gName)
                elif "y" in overlapResult:
                    needSubVROT.append(gName)
    """ Organize Source combinations """

    # Collect source info, based on the layout type
    # Organize file names, designspace locations, glyph lists, etc.
    sourceCombinations = []
    for locHROT, tagHROT in [(-45, "HROTn"), (0, "HROTd"), (45, "HROTx")]:
        for locVROT, tagVROT in [(-45, "VROTn"), (0, "VROTd"), (45, "VROTx")]:
            if "shadow" in compositionType:
                for locSLEN, tagSLEN in [(0, "SLENn"), (100, "SLENx")]:
                    for locSANG, tagSANG in [(-45, "SANGn"), (45, "SANGx")]:
                        # Rotate and Shadow
                        fileName = "Source-%s_%s_%s_%s.ufo" % (
                            tagHROT, tagVROT, tagSLEN, tagSANG)
                        loc = dict(HROT=locHROT,
                                   VROT=locVROT,
                                   SLEN=locSLEN,
                                   SANG=locSANG)
                        sourceInfo = dict(glyphNames=glyphNames,
                                          loc=loc,
                                          fileName=fileName,
                                          nudgeLoc=[0, 0])
                        sourceCombinations.append(sourceInfo)
            elif "depth" in compositionType:
                for locDPTH, tagDPTH in [(0, "DPTHn"), (100, "DPTHx")]:
                    # Rotate and depth
                    fileName = "Source-%s_%s_%s.ufo" % (tagHROT, tagVROT,
                                                        tagDPTH)
                    loc = dict(HROT=locHROT, VROT=locVROT, DPTH=locDPTH)
                    sourceInfo = dict(glyphNames=glyphNames,
                                      loc=loc,
                                      fileName=fileName,
                                      nudgeLoc=[0, 0])
                    sourceCombinations.append(sourceInfo)
            else:
                # Rotate only
                fileName = "Source-%s_%s.ufo" % (tagHROT, tagVROT)
                loc = dict(HROT=locHROT, VROT=locVROT)
                sourceInfo = dict(glyphNames=glyphNames,
                                  loc=loc,
                                  fileName=fileName,
                                  nudgeLoc=[0, 0])
                sourceCombinations.append(sourceInfo)

    # Process the sourceCombinations and make SubSources if necessary
    #print("needSubHROT", needSubHROT)
    #print("needSubVROT", needSubVROT)
    # @@@ Temporarily force all glyphs to be in all submasters
    needSubHROT = glyphNames
    needSubVROT = glyphNames
    if doMakeSubSources:
        doSubHROT = len(needSubHROT)
        doSubVROT = len(needSubVROT)
    else:
        doSubHROT = False
        doSubVROT = False
    # Loop through once to add new HROT SubSources
    newSourceCombos = []
    for sourceInfo in sourceCombinations:
        if sourceInfo["loc"]["HROT"] == 0:
            if doSubHROT:
                subSourceInfo = copy.deepcopy(sourceInfo)
                subSourceInfo["nudgeLoc"][
                    0] = 0  # Don't nudge, move the location instead
                subSourceInfo["loc"]["HROT"] += SLIGHTLYOFFAXIS
                subSourceInfo["glyphNames"] = needSubHROT
                subSourceInfo[
                    "fileName"] = "Sub" + subSourceInfo["fileName"].replace(
                        "HROTd", "HROTdd")
                newSourceCombos.append(subSourceInfo)
                # Nudge the default source
                sourceInfo["nudgeLoc"][0] -= SLIGHTLYOFFAXIS
    sourceCombinations += newSourceCombos
    # Looping back through to add VROT SubSources and to catch all of the new HROT SubSources
    newSourceCombos = []
    for sourceInfo in sourceCombinations:
        if sourceInfo["loc"]["VROT"] == 0:
            if doSubVROT:
                subSourceInfo = copy.deepcopy(sourceInfo)
                subSourceInfo["nudgeLoc"][
                    1] = 0  # Don't nudge, move the location instead
                subSourceInfo["loc"]["VROT"] -= SLIGHTLYOFFAXIS
                # Append the glyph list if this was the HROT=SLIGHTLYOFFAXIS
                if not subSourceInfo["loc"]["HROT"] == SLIGHTLYOFFAXIS:
                    subSourceInfo["glyphNames"] = []
                subSourceInfo["glyphNames"] += needSubVROT
                subSourceInfo["fileName"] = subSourceInfo["fileName"].replace(
                    "VROTd", "VROTdd")
                if not "Sub" in subSourceInfo["fileName"]:
                    subSourceInfo[
                        "fileName"] = "Sub" + subSourceInfo["fileName"]
                newSourceCombos.append(subSourceInfo)
                # Nudge the default source
                sourceInfo["nudgeLoc"][1] += SLIGHTLYOFFAXIS
    sourceCombinations += newSourceCombos
    """ Make the source UFOs """

    for sourceInfo in sourceCombinations:
        sourceUfoPath = os.path.join(destPath, sourceInfo["fileName"])
        if not os.path.exists(sourceUfoPath):
            sourceFont = NewFont(showInterface=False)
            sourceFont.save(sourceUfoPath)
            sourceFont.info.familyName = familyName
            sourceFont.info.styleName = styleName
            sourceFont.save()
            sourceFont.close()
    """ Process Glyphs into Source UFOs """

    # Process each UFO source, one at a time
    for sourceInfo in sourceCombinations:

        # Combine the nudgeLoc and loc, use this value when rotating
        rotateLoc = copy.deepcopy(sourceInfo["loc"])
        rotateLoc["HROT"] += sourceInfo["nudgeLoc"][0]
        rotateLoc["VROT"] += sourceInfo["nudgeLoc"][1]

        sourceUfoPath = os.path.join(destPath, sourceInfo["fileName"])
        sourceFont = OpenFont(sourceUfoPath, showInterface=False)

        for gName in sourceInfo["glyphNames"]:
            if gName in glyphPointData:
                pointData = copy.deepcopy(glyphPointData[gName])
            else:
                pointData = {}

            # Get the glyph started
            g = masterFont[gName]
            if layerName:
                g = g.getLayer(layerName)
            # Remove the glyph if it already existed and make a new one
            if gName in sourceFont:
                for layer in sourceFont.layers:
                    if gName in layer:
                        layer.removeGlyph(gName)
            sourceFont.newGlyph(gName)
            gDest = sourceFont[gName]
            gDest.appendGlyph(g)
            gDest.width = g.width
            gDest.unicode = g.unicode

            # Add anchors to the pointData so that they shift correctly
            # Use anchor + str(idx) as the ident
            for aIdx, anc in enumerate(gDest.anchors):
                ident = "anchor%s" % aIdx
                pos = list(anc.position)
                pointData[ident] = dict(x=pos[0], y=pos[1], z=0)

            # Decompose components in glyphs that were not bulit with Glyph Builder
            #   If the glyph has components, and if it's not marked with the "Glyph Builder Gray",
            #   it will need to be decomposed at this stage (but leave overlaps of course)
            #   Otherwise, glyphs that are gray will have their components reapplied after rotating with Glyph Builder.
            isComponent = False
            if not g.markColor == COMPOSITEGRAY:
                if len(gDest.components):
                    for c in gDest.components:
                        baseName = c.baseGlyph
                        masterBaseGlyph = masterFont[baseName]
                        # Decomposing from the master font because the base glyph might not be in the source font yet
                        for mc in masterBaseGlyph.contours:
                            gDest.appendContour(mc, offset=c.offset)
                        gDest.removeComponent(c)
                        # ...and copy over point data, taking into account the component offset
                        if baseName in glyphPointData:
                            basePointData = copy.deepcopy(
                                glyphPointData[baseName])
                            for ident in basePointData:
                                pointData[ident] = dict(
                                    x=basePointData[ident]["x"] + c.offset[0],
                                    y=basePointData[ident]["y"] + c.offset[1],
                                    z=basePointData[ident]["z"])
                        isComponent = True

            # Flatten the depth
            if "DPTH" in sourceInfo["loc"].keys():
                for ident in pointData:
                    pointData[ident]["z"] *= (sourceInfo["loc"]["DPTH"] * 0.01
                                              )  # Scale by the depth value

            # Shift the "z" value by an offset
            if not zOffset == None:
                for ident in pointData:
                    if not "anchor" in ident:  # ...but don't shift the anchors, the components are already shifted
                        pointData[ident]["z"] += zOffset

            # Extend the shadow
            if "SANG" in sourceInfo["loc"].keys():
                if sourceInfo["loc"]["SANG"] == -45:
                    shadowDirection = "left"
                else:
                    shadowDirection = "right"
                finalShadowLengthFactor = (sourceInfo["loc"]["SLEN"] *
                                           0.01) * shadowLengthFactor
                pointData = flattenShadow(gDest, pointData, shadowDirection,
                                          finalShadowLengthFactor)

            # Rotate the glyph
            # Merge the location and the nudgeLoc, if there is one
            marginChange, pointData = rotateGlyphPointData(
                gDest, rotateLoc, pointData)

            # Move the contour points into the correct position
            for c in gDest.contours:
                for pt in c.points:
                    ident = getIdent(pt)
                    if ident in pointData:
                        pt.x = pointData[ident]["x"]
                        pt.y = pointData[ident]["y"]

            # Move the anchors into the correct position
            for aIdx, anc in enumerate(gDest.anchors):
                ident = "anchor%s" % aIdx
                if ident in pointData:
                    anc.position = (int(round(pointData[ident]["x"])),
                                    int(round(pointData[ident]["y"])))

            # Shift the glyph to take in the sidebearings
            gDest.moveBy((-marginChange[0], 0))
            gDest.width -= marginChange[0] * 2

            if doForceSmooth and not isComponent:
                # If a bPoint was a smooth curve point in the original glyph,
                # force the related bPoint in the rotated glyph to be smooth
                for cIdx, c in enumerate(gDest.contours):
                    for bptIdx, thisBPt in enumerate(c.bPoints):
                        sourceBPt = g.contours[cIdx].bPoints[bptIdx]
                        if sourceBPt.type == "curve":
                            forceSmooth(thisBPt)

            # Round the point coordinates before outlining
            gDest.round()
            gDest.changed()

            # Outline the glyph
            if outlineAmount:
                outlineGlyph(sourceFont,
                             gDest,
                             outlineAmount,
                             alwaysConnect=alwaysConnect,
                             cap=cap,
                             connection=connection)

                # Round the point coordinates again, now that it's outlined
                gDest.round()
                gDest.changed()

            # Update
            #gDest.changed()

        # Resort the font
        sourceFont.glyphOrder = masterFont.glyphOrder

        # Copy the kerning
        sourceFont.groups.update(copy.deepcopy(masterFont.groups))
        sourceFont.kerning.update(copy.deepcopy(masterFont.kerning))

        # Copy the features
        sourceFont.features.text = masterFont.features.text

        # Done, save
        sourceFont.changed()
        sourceFont.save()
    """ New DesignSpaceDocument """

    designSpace = DesignSpaceDocument()
    designSpaceDocFilename = os.path.splitext(
        masterFileName)[0] + ".designspace"
    designSpaceDocPath = os.path.join(destPath, designSpaceDocFilename)
    """ Axis Descriptors """

    for tag in sourceCombinations[0]["loc"].keys():
        a = AxisDescriptor()
        a.minimum = AXISINFO[tag]["minimum"]
        a.maximum = AXISINFO[tag]["maximum"]
        a.default = AXISINFO[tag]["default"]
        a.name = AXISINFO[tag]["name"]
        a.tag = tag
        a.labelNames[u'en'] = AXISINFO[tag]["name"]
        designSpace.addAxis(a)
    """ Source Descriptors """

    for sourceInfo in sourceCombinations:
        sourceUfoPath = os.path.join(destPath, sourceInfo["fileName"])
        # Make a source description
        s = SourceDescriptor()
        s.path = sourceUfoPath
        s.name = os.path.splitext(sourceInfo["fileName"])[0]
        #s.font = defcon.Font(s.name)
        s.copyLib = True
        s.copyInfo = True
        s.copyInfoures = True
        s.familyName = masterFont.info.familyName
        s.styleName = s.name
        # Convert the loc from tags to names
        loc = {}
        for tag, value in sourceInfo["loc"].items():
            axisName = AXISINFO[tag]["name"]
            loc[axisName] = value
        s.location = loc
        designSpace.addSource(s)

    designSpace.write(designSpaceDocPath)
コード例 #26
0
ファイル: split.py プロジェクト: googlefonts/fonttools
def _extractSubSpace(
    doc: DesignSpaceDocument,
    userRegion: Region,
    *,
    keepVFs: bool,
    makeNames: bool,
    expandLocations: bool,
    makeInstanceFilename: MakeInstanceFilenameCallable,
) -> DesignSpaceDocument:
    subDoc = DesignSpaceDocument()
    # Don't include STAT info
    # FIXME: (Jany) let's think about it. Not include = OK because the point of
    # the splitting is to build VFs and we'll use the STAT data of the full
    # document to generate the STAT of the VFs, so "no need" to have STAT data
    # in sub-docs. Counterpoint: what if someone wants to split this DS for
    # other purposes?  Maybe for that it would be useful to also subset the STAT
    # data?
    # subDoc.elidedFallbackName = doc.elidedFallbackName

    def maybeExpandDesignLocation(object):
        if expandLocations:
            return object.getFullDesignLocation(doc)
        else:
            return object.designLocation

    for axis in doc.axes:
        range = userRegion[axis.name]
        if isinstance(range, Range) and hasattr(axis, "minimum"):
            # Mypy doesn't support narrowing union types via hasattr()
            # TODO(Python 3.10): use TypeGuard
            # https://mypy.readthedocs.io/en/stable/type_narrowing.html
            axis = cast(AxisDescriptor, axis)
            subDoc.addAxis(
                AxisDescriptor(
                    # Same info
                    tag=axis.tag,
                    name=axis.name,
                    labelNames=axis.labelNames,
                    hidden=axis.hidden,
                    # Subset range
                    minimum=max(range.minimum, axis.minimum),
                    default=range.default or axis.default,
                    maximum=min(range.maximum, axis.maximum),
                    map=[
                        (user, design)
                        for user, design in axis.map
                        if range.minimum <= user <= range.maximum
                    ],
                    # Don't include STAT info
                    axisOrdering=None,
                    axisLabels=None,
                )
            )

    # Don't include STAT info
    # subDoc.locationLabels = doc.locationLabels

    # Rules: subset them based on conditions
    designRegion = userRegionToDesignRegion(doc, userRegion)
    subDoc.rules = _subsetRulesBasedOnConditions(doc.rules, designRegion)
    subDoc.rulesProcessingLast = doc.rulesProcessingLast

    # Sources: keep only the ones that fall within the kept axis ranges
    for source in doc.sources:
        if not locationInRegion(doc.map_backward(source.designLocation), userRegion):
            continue

        subDoc.addSource(
            SourceDescriptor(
                filename=source.filename,
                path=source.path,
                font=source.font,
                name=source.name,
                designLocation=_filterLocation(
                    userRegion, maybeExpandDesignLocation(source)
                ),
                layerName=source.layerName,
                familyName=source.familyName,
                styleName=source.styleName,
                muteKerning=source.muteKerning,
                muteInfo=source.muteInfo,
                mutedGlyphNames=source.mutedGlyphNames,
            )
        )

    # Copy family name translations from the old default source to the new default
    vfDefault = subDoc.findDefault()
    oldDefault = doc.findDefault()
    if vfDefault is not None and oldDefault is not None:
        vfDefault.localisedFamilyName = oldDefault.localisedFamilyName

    # Variable fonts: keep only the ones that fall within the kept axis ranges
    if keepVFs:
        # Note: call getVariableFont() to make the implicit VFs explicit
        for vf in doc.getVariableFonts():
            vfUserRegion = getVFUserRegion(doc, vf)
            if regionInRegion(vfUserRegion, userRegion):
                subDoc.addVariableFont(
                    VariableFontDescriptor(
                        name=vf.name,
                        filename=vf.filename,
                        axisSubsets=[
                            axisSubset
                            for axisSubset in vf.axisSubsets
                            if isinstance(userRegion[axisSubset.name], Range)
                        ],
                        lib=vf.lib,
                    )
                )

    # Instances: same as Sources + compute missing names
    for instance in doc.instances:
        if not locationInRegion(instance.getFullUserLocation(doc), userRegion):
            continue

        if makeNames:
            statNames = getStatNames(doc, instance.getFullUserLocation(doc))
            familyName = instance.familyName or statNames.familyNames.get("en")
            styleName = instance.styleName or statNames.styleNames.get("en")
            subDoc.addInstance(
                InstanceDescriptor(
                    filename=instance.filename
                    or makeInstanceFilename(doc, instance, statNames),
                    path=instance.path,
                    font=instance.font,
                    name=instance.name or f"{familyName} {styleName}",
                    userLocation={} if expandLocations else instance.userLocation,
                    designLocation=_filterLocation(
                        userRegion, maybeExpandDesignLocation(instance)
                    ),
                    familyName=familyName,
                    styleName=styleName,
                    postScriptFontName=instance.postScriptFontName
                    or statNames.postScriptFontName,
                    styleMapFamilyName=instance.styleMapFamilyName
                    or statNames.styleMapFamilyNames.get("en"),
                    styleMapStyleName=instance.styleMapStyleName
                    or statNames.styleMapStyleName,
                    localisedFamilyName=instance.localisedFamilyName
                    or statNames.familyNames,
                    localisedStyleName=instance.localisedStyleName
                    or statNames.styleNames,
                    localisedStyleMapFamilyName=instance.localisedStyleMapFamilyName
                    or statNames.styleMapFamilyNames,
                    localisedStyleMapStyleName=instance.localisedStyleMapStyleName
                    or {},
                    lib=instance.lib,
                )
            )
        else:
            subDoc.addInstance(
                InstanceDescriptor(
                    filename=instance.filename,
                    path=instance.path,
                    font=instance.font,
                    name=instance.name,
                    userLocation={} if expandLocations else instance.userLocation,
                    designLocation=_filterLocation(
                        userRegion, maybeExpandDesignLocation(instance)
                    ),
                    familyName=instance.familyName,
                    styleName=instance.styleName,
                    postScriptFontName=instance.postScriptFontName,
                    styleMapFamilyName=instance.styleMapFamilyName,
                    styleMapStyleName=instance.styleMapStyleName,
                    localisedFamilyName=instance.localisedFamilyName,
                    localisedStyleName=instance.localisedStyleName,
                    localisedStyleMapFamilyName=instance.localisedStyleMapFamilyName,
                    localisedStyleMapStyleName=instance.localisedStyleMapStyleName,
                    lib=instance.lib,
                )
            )

    subDoc.lib = doc.lib

    return subDoc
コード例 #27
0
def test_fill_document(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "test.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyLib = True
    s1.copyInfo = True
    s1.copyFeatures = True
    s1.location = dict(weight=0)
    s1.familyName = "MasterFamilyName"
    s1.styleName = "MasterStyleNameOne"
    s1.mutedGlyphNames.append("A")
    s1.mutedGlyphNames.append("Z")
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.copyLib = False
    s2.copyInfo = False
    s2.copyFeatures = False
    s2.muteKerning = True
    s2.location = dict(weight=1000)
    s2.familyName = "MasterFamilyName"
    s2.styleName = "MasterStyleNameTwo"
    doc.addSource(s2)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "InstanceFamilyName"
    i1.styleName = "InstanceStyleName"
    i1.name = "instance.ufo1"
    i1.location = dict(
        weight=500, spooky=666)  # this adds a dimension that is not defined.
    i1.postScriptFontName = "InstancePostscriptName"
    i1.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i1.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125])
    i1.glyphs['arrow'] = glyphData
    doc.addInstance(i1)
    # add instance 2
    i2 = InstanceDescriptor()
    i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath))
    i2.familyName = "InstanceFamilyName"
    i2.styleName = "InstanceStyleName"
    i2.name = "instance.ufo2"
    # anisotropic location
    i2.location = dict(weight=500, width=(400, 300))
    i2.postScriptFontName = "InstancePostscriptName"
    i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
    i2.styleMapStyleName = "InstanceStyleMapStyleName"
    glyphMasters = [
        dict(font="master.ufo1",
             glyphName="BB",
             location=dict(width=20, weight=20)),
        dict(font="master.ufo2",
             glyphName="CC",
             location=dict(width=900, weight=900))
    ]
    glyphData = dict(name="arrow", unicodes=[101, 201, 301])
    glyphData['masters'] = glyphMasters
    glyphData['note'] = "A note about this glyph"
    glyphData['instanceLocation'] = dict(width=100, weight=120)
    i2.glyphs['arrow'] = glyphData
    i2.glyphs['arrow2'] = dict(mute=False)
    doc.addInstance(i2)

    # now we have sources and instances, but no axes yet.
    doc.check()

    # Here, since the axes are not defined in the document, but instead are
    # infered from the locations of the instances, we cannot guarantee the
    # order in which they will be created by the `check()` method.
    assert set(doc.getAxisOrder()) == set(['spooky', 'weight', 'width'])
    doc.axes = []  # clear the axes

    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    # note: just to test the element language, not an actual label name recommendations.
    a1.labelNames[u'fa-IR'] = u"قطر"
    a1.labelNames[u'en'] = u"Wéíght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = 0
    a2.maximum = 1000
    a2.default = 20
    a2.name = "width"
    a2.tag = "wdth"
    a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    a2.hidden = True
    a2.labelNames[u'fr'] = u"Poids"
    doc.addAxis(a2)
    # add an axis that is not part of any location to see if that works
    a3 = AxisDescriptor()
    a3.minimum = 333
    a3.maximum = 666
    a3.default = 444
    a3.name = "spooky"
    a3.tag = "spok"
    a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    #doc.addAxis(a3)    # uncomment this line to test the effects of default axes values
    # write some rules
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1))
    r1.conditions.append(dict(name='bbbb', minimum=2, maximum=3))
    r1.subs.append(("a", "a.alt"))
    doc.addRule(r1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)

    new.check()
    assert new.default.location == {'width': 20.0, 'weight': 0.0}

    # >>> for a, b in zip(doc.instances, new.instances):
    # ...     a.compare(b)
    # >>> for a, b in zip(doc.sources, new.sources):
    # ...     a.compare(b)
    # >>> for a, b in zip(doc.axes, new.axes):
    # ...     a.compare(b)
    # >>> [n.mutedGlyphNames for n in new.sources]
    # [['A', 'Z'], []]
    # >>> doc.getFonts()
    # []

    # test roundtrip for the axis attributes and data
    axes = {}
    for axis in doc.axes:
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for axis in new.axes:
        if axis.tag[0] == "_":
            continue
        if axis.tag not in axes:
            axes[axis.tag] = []
        axes[axis.tag].append(axis.serialize())
    for v in axes.values():
        a, b = v
        assert a == b
コード例 #28
0
#---------
# masters
#---------

s0 = SourceDescriptor()
s0.path = "MutatorSansLightCondensed.ufo"
s0.name = "master.MutatorSansTest.LightCondensed.0"
s0.familyName = familyName
s0.styleName = "LightCondensed"
s0.location = dict(weight=0, width=0)
s0.copyLib = True
s0.copyInfo = True
s0.copyGroups = True
s0.copyFeatures = True
doc.addSource(s0)

s1 = SourceDescriptor()
s1.path = "MutatorSansBoldCondensed.ufo"
s1.name = "master.MutatorSansTest.BoldCondensed.1"
s1.familyName = familyName
s1.styleName = "BoldCondensed"
s1.location = dict(weight=1000, width=0)
doc.addSource(s1)

s2 = SourceDescriptor()
s2.path = "MutatorSansLightWide.ufo"
s2.name = "master.MutatorSansTest.LightWide.2"
s2.familyName = familyName
s2.styleName = "LightWide"
s2.location = dict(weight=0, width=1000)
コード例 #29
0
    else:
        blackUfo = newUfo
        font = OpenFont(newUfo)
        tweakSpacing(font, adjustments['max']['offset'],
                     adjustments['max']['percentage'])
        font.save()

        if adjustments['max']['scaleFactor'] != 1:
            factor = adjustments['max']['scaleFactor']
            print('Scaling %s by %s' % (font.path, factor))
            scaleFont(font.path, font.path, factor)

        source.location = {'Weight': wght['max'], 'Optical size': opsz['min']}
        source.styleName = "BlackMin"

    doc.addSource(source)

# removeAreas(font)
doc.write(path)
doc.write(minPath)

minDoc = DesignSpaceDocument()
minDoc.read(minPath)

# resetting instances
minDoc.instances = []

# Calculate location
weightMin = wght.get('regular') - (wght.get('regular') -
                                   wght.get('min')) * weightCropIndex
weightMax = wght.get('regular') + (wght.get('max') -
コード例 #30
0
def test_localisedNames(tmpdir):
    tmpdir = str(tmpdir)
    testDocPath = os.path.join(tmpdir, "testLocalisedNames.designspace")
    testDocPath2 = os.path.join(tmpdir, "testLocalisedNames_roundtrip.designspace")
    masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
    masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
    instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
    instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
    doc = DesignSpaceDocument()
    # add master 1
    s1 = SourceDescriptor()
    s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
    s1.name = "master.ufo1"
    s1.copyInfo = True
    s1.location = dict(weight=0)
    doc.addSource(s1)
    # add master 2
    s2 = SourceDescriptor()
    s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath))
    s2.name = "master.ufo2"
    s2.location = dict(weight=1000)
    doc.addSource(s2)
    # add instance 1
    i1 = InstanceDescriptor()
    i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath))
    i1.familyName = "Montserrat"
    i1.styleName = "SemiBold"
    i1.styleMapFamilyName = "Montserrat SemiBold"
    i1.styleMapStyleName = "Regular"
    i1.setFamilyName("Montserrat", "fr")
    i1.setFamilyName(u"モンセラート", "ja")
    i1.setStyleName("Demigras", "fr")
    i1.setStyleName(u"半ば", "ja")
    i1.setStyleMapStyleName(u"Standard", "de")
    i1.setStyleMapFamilyName("Montserrat Halbfett", "de")
    i1.setStyleMapFamilyName(u"モンセラート SemiBold", "ja")
    i1.name = "instance.ufo1"
    i1.location = dict(weight=500, spooky=666)  # this adds a dimension that is not defined.
    i1.postScriptFontName = "InstancePostscriptName"
    glyphData = dict(name="arrow", mute=True, unicodes=[0x123])
    i1.glyphs['arrow'] = glyphData
    doc.addInstance(i1)
    # now we have sources and instances, but no axes yet.
    doc.axes = []   # clear the axes
    # write some axes
    a1 = AxisDescriptor()
    a1.minimum = 0
    a1.maximum = 1000
    a1.default = 0
    a1.name = "weight"
    a1.tag = "wght"
    # note: just to test the element language, not an actual label name recommendations.
    a1.labelNames[u'fa-IR'] = u"قطر"
    a1.labelNames[u'en'] = u"Wéíght"
    doc.addAxis(a1)
    a2 = AxisDescriptor()
    a2.minimum = 0
    a2.maximum = 1000
    a2.default = 0
    a2.name = "width"
    a2.tag = "wdth"
    a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    a2.labelNames[u'fr'] = u"Poids"
    doc.addAxis(a2)
    # add an axis that is not part of any location to see if that works
    a3 = AxisDescriptor()
    a3.minimum = 333
    a3.maximum = 666
    a3.default = 444
    a3.name = "spooky"
    a3.tag = "spok"
    a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
    #doc.addAxis(a3)    # uncomment this line to test the effects of default axes values
    # write some rules
    r1 = RuleDescriptor()
    r1.name = "named.rule.1"
    r1.conditionSets.append([
        dict(name='weight', minimum=200, maximum=500),
        dict(name='width', minimum=0, maximum=150)
    ])
    r1.subs.append(("a", "a.alt"))
    doc.addRule(r1)
    # write the document
    doc.write(testDocPath)
    assert os.path.exists(testDocPath)
    # import it again
    new = DesignSpaceDocument()
    new.read(testDocPath)
    new.write(testDocPath2)
    with open(testDocPath, 'r', encoding='utf-8') as f1:
        t1 = f1.read()
    with open(testDocPath2, 'r', encoding='utf-8') as f2:
        t2 = f2.read()
    assert t1 == t2