Пример #1
0
 def run_ufolib_import_validation(self):
     """
     ufoLib UFOReader.getLayerNames method validates the layercontents.plist file
     :return: (list) list of test failure Result objects
     """
     res = Result(self.testpath)
     ss = StdStreamer(self.ufopath)
     if (
         file_exists(self.testpath) is False
     ):  # should only meet this condition if not a mandatory file (runner.py checks)
         res.test_failed = False
         ss.stream_result(res)
         return self.test_fail_list
     try:
         # read layercontents.plist with ufoLib - the ufoLib library performs type validations on values on read
         ufolib_reader = UFOReader(self.ufopath, validate=True)
         ufolib_reader.getLayerNames()
         res.test_failed = False
         ss.stream_result(res)
     except Exception as e:
         if (
             self.testpath in self.mandatory_filepaths_list
         ):  # if part of mandatory file spec for UFO version, fail early
             res.test_failed = True
             res.exit_failure = True  # fail early b/c it is mandatory part of spec
         else:
             res.test_failed = (
                 True
             )  # fail the test, but wait to report until all other tests complete
         res.test_long_stdstream_string = (
             self.testpath + " failed ufoLib import test with error: " + str(e)
         )
         self.test_fail_list.append(res)
         ss.stream_result(res)
     return self.test_fail_list
Пример #2
0
 def reloadLayers(self, layerData):
     """
     Reload the layers. This should not be called externally.
     """
     reader = UFOReader(self.font.path, validate=self.font.ufoLibReadValidate)
     # handle the layers
     currentLayerOrder = self.layerOrder
     for layerName, l in layerData.get("layers", {}).items():
         # new layer
         if layerName not in currentLayerOrder:
             glyphSet = reader.getGlyphSet(layerName, validateRead=self.ufoLibReadValidate, validateWrite=self.font.ufoLibWriteValidate)
             self.newLayer(layerName, glyphSet)
         # get the layer
         layer = self[layerName]
         # reload the layer info
         if l.get("info"):
             layer.color = None
             layer.lib.clear()
             layer._glyphSet.readLayerInfo(layer)
             self._stampLayerInfoDataState(layer)
         # reload the glyphs
         glyphNames = l.get("glyphNames", [])
         if glyphNames:
             layer.reloadGlyphs(glyphNames)
     # handle the order
     if layerData.get("order", False):
         newLayerOrder = reader.getLayerNames()
         for layerName in self.layerOrder:
             if layerName not in newLayerOrder:
                 newLayerOrder.append(layerName)
         self.layerOrder = newLayerOrder
     # handle the default layer
     if layerData.get("default", False):
         newDefaultLayerName = reader.getDefaultLayerName()
         self.defaultLayer = self[newDefaultLayerName]
Пример #3
0
    def run_ufolib_import_validation(self):
        """
        ufoLib UFOReader.readMetaInfo method validates the UFO version number.  This method adds validation for
        expected reverse URL name scheme in
        :return: (list) list of test failure Result objects
        """

        res = Result(self.testpath)
        ss = StdStreamer(self.ufopath)
        if (
            file_exists(self.testpath) is False
        ):  # fail test, exit early if file is missing
            res.test_failed = True
            res.exit_failure = True
            res.test_long_stdstream_string = (
                "metainfo.plist is not available on the path " + self.testpath
            )
            ss.stream_result(res)
        try:
            ufolib_reader = UFOReader(self.ufopath, validate=True)
            ufolib_reader.readMetaInfo()
            res.test_failed = False
            ss.stream_result(res)
        except Exception as e:
            res.test_failed = True
            res.exit_failure = True
            res.test_long_stdstream_string = (
                self.testpath + " failed ufoLib import test with error: " + str(e)
            )
            self.test_fail_list.append(res)
            ss.stream_result(res)
        return self.test_fail_list
Пример #4
0
def test_pointCollector():
    ufoPath = getFontPath("MutatorSansBoldWideMutated.ufo")
    reader = UFOReader(ufoPath)
    glyphSet = reader.getGlyphSet()
    pen = PointCollector(glyphSet)
    glyphSet["B"].draw(pen)
    assert len(pen.points) == 38
    assert len(pen.tags) == 38
    assert pen.contours == [3, 37]
    assert pen.tags[:12] == [1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1]

    pen = PointCollector(glyphSet, decompose=False)
    glyphSet["Aacute"].draw(pen)
    assert len(pen.points) == 0
    assert pen.contours == []
    assert pen.components == [("A", (1, 0, 0, 1, 0, 0)), ("acute", (1, 0, 0, 1, 484, 20))]

    pen = PointCollector(glyphSet, decompose=True)
    glyphSet["Aacute"].draw(pen)
    assert len(pen.points) == 20
    assert pen.contours == [3, 7, 11, 15, 19]
    assert pen.components == []

    pen = PointCollector(glyphSet)
    glyphSet["O"].draw(pen)
    assert len(pen.points) == 28
    assert pen.contours == [13, 27]
Пример #5
0
    def read(cls, reader: UFOReader, lazy: bool = True) -> LayerSet:
        """Instantiates a LayerSet object from a :class:`fontTools.ufoLib.UFOReader`.

        Args:
            path: The path to the UFO to load.
            lazy: If True, load glyphs, data files and images as they are accessed. If
                False, load everything up front.
        """
        layers: dict[str, Layer] = {}
        defaultLayer = None

        defaultLayerName = reader.getDefaultLayerName()

        for layerName in reader.getLayerNames():
            isDefault = layerName == defaultLayerName
            if isDefault or not lazy:
                layer = cls._loadLayer(reader, layerName, lazy, isDefault)
                if isDefault:
                    defaultLayer = layer
                layers[layerName] = layer
            else:
                layers[layerName] = _LAYER_NOT_LOADED

        assert defaultLayer is not None

        self = cls(layers=layers, defaultLayer=defaultLayer)
        if lazy:
            self._reader = reader

        return self
Пример #6
0
 def save(self, writer, saveAs=False, progressBar=None):
     """
     Save data. This method should not be called externally.
     Subclasses may override this method to implement custom saving behavior.
     """
     if saveAs:
         font = self.font
         if font is not None and font.path is not None and os.path.exists(font.path):
             reader = UFOReader(font.path, validate=False)
             readerDataDirectoryListing = reader.getDataDirectoryListing()
             for fileName, data in self._data.items():
                 path = "%s/%s" % ("data", fileName)
                 if data["data"] is not None or fileName not in readerDataDirectoryListing:
                     continue
                 writer.copyFromReader(reader, path, path)
     for fileName in self._scheduledForDeletion:
         # instead of trying to maintain a list of in UFO
         # vs. in memory, simply skip and move on when
         # something can't be deleted because it isn't
         # in the UFO.
         writer.removePath("%s/%s" % ("data", fileName), force=True)
     self._scheduledForDeletion.clear()
     for fileName, data in self._data.items():
         if not data["dirty"]:
             continue
         writer.writeBytesToPath("%s/%s" % ("data", fileName), data["data"])
         data["dirty"] = False
         data["onDisk"] = True
         data["onDiskModTime"] = writer.getFileModificationTime("%s/%s" % ("data", fileName))
     self.dirty = False
Пример #7
0
 def run_ufolib_import_validation(self):
     """
     ufoLib UFOReader.readLib method validates the lib.plist file
     :return: (list) list of test failure Result objects
     """
     res = Result(self.testpath)
     ss = StdStreamer(self.ufopath)
     if file_exists(self.testpath) is False:
         res.test_failed = (
             False
         )  # not a mandatory file in UFO spec, test passes if missing
         ss.stream_result(res)
         return self.test_fail_list
     try:
         # read lib.plist with ufoLib - the ufoLib library performs type validations on values on read
         ufolib_reader = UFOReader(self.ufopath, validate=True)
         ufolib_reader.readLib()
         res.test_failed = False
         ss.stream_result(res)
     except Exception as e:
         res.test_failed = True
         res.test_long_stdstream_string = (
             self.testpath + " failed ufoLib import test with error: " + str(e)
         )
         ss.stream_result(res)
         self.test_fail_list.append(res)
     return self.test_fail_list
Пример #8
0
def test_ufoCharacterMapping_glyphNames():
    ufoPath = getFontPath("MutatorSansBoldWideMutated.ufo")
    reader = UFOReader(ufoPath)
    cmap, revCmap, anchors = fetchCharacterMappingAndAnchors(
        reader.getGlyphSet(), ufoPath, ["A"])
    assert cmap[0x0041] == "A"
    assert revCmap["A"] == [0x0041]
    assert anchors == {"A": [("top", 645, 815)]}
Пример #9
0
def test_getUpdateInfo(tmpdir):
    ufoSource = getFontPath("MutatorSansBoldWideMutated.ufo")
    ufoPath = shutil.copytree(ufoSource, tmpdir / "test.ufo")
    reader = UFOReader(ufoPath, validate=False)
    glyphSet = reader.getGlyphSet()
    cmap, unicodes, anchors = fetchCharacterMappingAndAnchors(glyphSet, ufoPath)

    state = UFOState(reader, glyphSet, getUnicodesAndAnchors=lambda: (unicodes, anchors))

    feaPath = pathlib.Path(reader.fs.getsyspath("/features.fea"))
    feaPath.touch()

    state = state.newState()
    (needsFeaturesUpdate, needsGlyphUpdate, needsInfoUpdate, needsCmapUpdate,
     needsLibUpdate) = state.getUpdateInfo()
    assert needsFeaturesUpdate
    assert not needsGlyphUpdate
    assert not needsInfoUpdate
    assert not needsCmapUpdate

    infoPath = pathlib.Path(reader.fs.getsyspath("/fontinfo.plist"))
    infoPath.touch()

    state = state.newState()
    (needsFeaturesUpdate, needsGlyphUpdate, needsInfoUpdate, needsCmapUpdate,
     needsLibUpdate) = state.getUpdateInfo()
    assert not needsFeaturesUpdate
    assert not needsGlyphUpdate
    assert needsInfoUpdate
    assert not needsCmapUpdate

    glyph = Glyph("A", None)
    ppen = RecordingPointPen()
    glyphSet.readGlyph("A", glyph, ppen)
    glyph.anchors[0]["x"] = 123
    glyphSet.writeGlyph("A", glyph, ppen.replay)

    state = state.newState()
    (needsFeaturesUpdate, needsGlyphUpdate, needsInfoUpdate, needsCmapUpdate,
     needsLibUpdate) = state.getUpdateInfo()
    assert needsFeaturesUpdate
    assert needsGlyphUpdate
    assert not needsInfoUpdate
    assert not needsCmapUpdate

    glyph = Glyph("A", None)
    ppen = RecordingPointPen()
    glyphSet.readGlyph("A", glyph, ppen)
    glyph.unicodes = [123]
    glyphSet.writeGlyph("A", glyph, ppen.replay)

    state = state.newState()
    (needsFeaturesUpdate, needsGlyphUpdate, needsInfoUpdate, needsCmapUpdate,
     needsLibUpdate) = state.getUpdateInfo()
    assert not needsFeaturesUpdate
    assert needsGlyphUpdate
    assert not needsInfoUpdate
    assert needsCmapUpdate
Пример #10
0
 def __getitem__(self, fileName):
     if self._data[fileName]["data"] is None:
         path = self.font.path
         reader = UFOReader(path, validate=False)
         path = "%s/%s" % ("data", fileName)
         data = reader.readBytesFromPath(path)
         onDiskModTime = reader.getFileModificationTime(path)
         self._data[fileName] = _dataDict(data=data, onDisk=True, onDiskModTime=onDiskModTime)
     return self._data[fileName]["data"]
Пример #11
0
	def testUFO2(self):
		self.makeUFO(formatVersion=2)
		reader = UFOReader(self.ufoPath, validate=True)
		kerning = reader.readKerning()
		self.assertEqual(self.expectedKerning, kerning)
		groups = reader.readGroups()
		self.assertEqual(self.expectedGroups, groups)
		info = TestInfoObject()
		reader.readInfo(info)
Пример #12
0
def extractIncludedFeatureFiles(ufoPath, reader=None):
    if isinstance(ufoPath, str):
        ufoPath = pathlib.Path(ufoPath)
    if reader is None:
        reader = UFOReader(ufoPath, validate=False)
    mainFeatures = reader.readFeatures()
    if not mainFeatures:
        return ()
    return sorted(set(_extractIncludedFeatureFiles(mainFeatures, [ufoPath.parent])))
Пример #13
0
def test_pointCollectorQuad():
    ufoPath = getFontPath("QuadTest-Regular.ufo")
    reader = UFOReader(ufoPath)
    glyphSet = reader.getGlyphSet()
    pen = PointCollector(glyphSet)
    glyphSet["a"].draw(pen)
    assert len(pen.points) == 4
    assert len(pen.tags) == 4
    assert pen.contours == [3]
    assert pen.tags == [0, 0, 0, 0]
Пример #14
0
 def __getitem__(self, fileName):
     d = self._data[fileName]
     if d["data"] is None:
         path = self.font.path
         reader = UFOReader(path, validate=False)
         data = reader.readImage(fileName, validate=self.ufoLibReadValidate)
         d["data"] = data
         d["digest"] = _makeDigest(data)
         d["onDisk"] = True
         d["onDiskModTime"] = reader.getFileModificationTime("%s/%s" % ("images", fileName))
     return d["data"]
Пример #15
0
 def open(cls, path, lazy=True, validate=True):
     reader = UFOReader(path, validate=validate)
     self = cls.read(reader, lazy=lazy)
     self._path = path
     self._fileStructure = reader.fileStructure
     if lazy:
         # keep the reader around so we can close it when done
         self._reader = reader
     else:
         reader.close()
     return self
Пример #16
0
 def testRead(self):
     originalData = dict(fontInfoVersion1)
     self._writeInfoToPlist(originalData)
     infoObject = TestInfoObject()
     reader = UFOReader(self.dstDir, validate=True)
     reader.readInfo(infoObject)
     for attr in dir(infoObject):
         if attr not in fontInfoVersion2:
             continue
         originalValue = fontInfoVersion2[attr]
         readValue = getattr(infoObject, attr)
         self.assertEqual(originalValue, readValue)
Пример #17
0
	def testRead(self):
		originalData = dict(fontInfoVersion1)
		self._writeInfoToPlist(originalData)
		infoObject = TestInfoObject()
		reader = UFOReader(self.dstDir, validate=True)
		reader.readInfo(infoObject)
		for attr in dir(infoObject):
			if attr not in fontInfoVersion2:
				continue
			originalValue = fontInfoVersion2[attr]
			readValue = getattr(infoObject, attr)
			self.assertEqual(originalValue, readValue)
Пример #18
0
 def _fontSaveWasCompleted(self):
     """
     When saving a UFOZ, the underlying ZipFS object is closed.
     The objects then stored in layer._glyphSet contain references
     to a closed, and therefore unusable, filesystem. To remedy this,
     after the save is completed this method will be called and new
     GlyphSet objects will be created and assigned to the layers.
     """
     reader = UFOReader(self.font.path, validate=self.font.ufoLibReadValidate)
     if reader.fileStructure is UFOFileStructure.ZIP:
         for layerName in self.layerOrder:
             layer = self[layerName]
             layer._glyphSet = reader.getGlyphSet(layerName=layerName, validateRead=self.ufoLibReadValidate)
Пример #19
0
def test_readMetaInfo_errors(ufo_path):
    (ufo_path / "metainfo.plist").unlink()
    with pytest.raises(UFOLibError, match="'metainfo.plist' is missing"):
        UFOReader(ufo_path)

    (ufo_path / "metainfo.plist").write_bytes(plistlib.dumps({}))
    with pytest.raises(UFOLibError, match="Missing required formatVersion"):
        UFOReader(ufo_path)

    (ufo_path / "metainfo.plist").write_bytes(plistlib.dumps([]))
    with pytest.raises(UFOLibError,
                       match="metainfo.plist is not properly formatted"):
        UFOReader(ufo_path)
Пример #20
0
 def save(self,
          writer,
          removeUnreferencedImages=False,
          saveAs=False,
          progressBar=None):
     """
     Save images. This method should not be called externally.
     Subclasses may override this method to implement custom saving behavior.
     """
     if removeUnreferencedImages:
         self.disableNotifications()
         for fileName in self.unreferencedFileNames:
             del self[fileName]
         self.enableNotifications()
     if saveAs:
         font = self.font
         if font is not None and font.path is not None and os.path.exists(
                 font.path):
             reader = UFOReader(font.path, validate=False)
             readerImageNames = reader.getImageDirectoryListing(
                 validate=self.ufoLibReadValidate)
             for fileName, data in self._data.items():
                 if data["data"] is not None or fileName not in readerImageNames:
                     continue
                 writer.copyImageFromReader(
                     reader,
                     fileName,
                     fileName,
                     validate=self.ufoLibWriteValidate)
     for fileName in self._scheduledForDeletion:
         try:
             writer.removeImage(fileName, validate=self.ufoLibWriteValidate)
         except UFOLibError:
             # this will be raised if the file doesn't exist.
             # instead of trying to maintain a list of in UFO
             # vs. in memory, simply fail and move on when
             # something can't be deleted because it isn't
             # in the UFO.
             pass
     self._scheduledForDeletion.clear()
     for fileName, data in self._data.items():
         if not data["dirty"]:
             continue
         writer.writeImage(fileName,
                           data["data"],
                           validate=self.ufoLibWriteValidate)
         data["dirty"] = False
         data["onDisk"] = True
         data["onDiskModTime"] = writer.getFileModificationTime(
             "%s/%s" % ("images", fileName))
     self.dirty = False
Пример #21
0
 def testFontStyleConversion(self):
     fontStyle1To2 = {
         64: "regular",
         1: "italic",
         32: "bold",
         33: "bold italic"
     }
     for old, new in list(fontStyle1To2.items()):
         info = dict(fontInfoVersion1)
         info["fontStyle"] = old
         self._writeInfoToPlist(info)
         reader = UFOReader(self.dstDir, validate=True)
         infoObject = TestInfoObject()
         reader.readInfo(infoObject)
         self.assertEqual(new, infoObject.styleMapStyleName)
Пример #22
0
	def testFontStyleConversion(self):
		fontStyle1To2 = {
			64 : "regular",
			1  : "italic",
			32 : "bold",
			33 : "bold italic"
		}
		for old, new in list(fontStyle1To2.items()):
			info = dict(fontInfoVersion1)
			info["fontStyle"] = old
			self._writeInfoToPlist(info)
			reader = UFOReader(self.dstDir, validate=True)
			infoObject = TestInfoObject()
			reader.readInfo(infoObject)
			self.assertEqual(new, infoObject.styleMapStyleName)
Пример #23
0
 def test_testForExternalChanges_modify_on_disk_and_scan(self):
     path = makeTestFontCopy()
     font = Font(path)
     reader = UFOReader(path)
     # d = font.data["com.typesupply.defcon.test.file"]
     font.data["com.typesupply.defcon.test.file"]
     filePath = os.path.join(path, "data",
                             "com.typesupply.defcon.test.file")
     f = open(filePath, "wb")
     f.write(b"blah")
     f.close()
     reader = UFOReader(path)
     self.assertEqual(font.data.testForExternalChanges(reader),
                      (["com.typesupply.defcon.test.file"], [], []))
     tearDownTestFontCopy()
Пример #24
0
 def _fontSaveWasCompleted(self):
     """
     When saving a UFOZ, the underlying ZipFS object is closed.
     The objects then stored in layer._glyphSet contain references
     to a closed, and therefore unusable, filesystem. To remedy this,
     after the save is completed this method will be called and new
     GlyphSet objects will be created and assigned to the layers.
     """
     reader = UFOReader(self.font.path,
                        validate=self.font.ufoLibReadValidate)
     if reader.fileStructure is UFOFileStructure.ZIP:
         for layerName in self.layerOrder:
             layer = self[layerName]
             layer._glyphSet = reader.getGlyphSet(
                 layerName=layerName, validateRead=self.ufoLibReadValidate)
Пример #25
0
def test_ufoCharacterMapping():
    ufoPath = getFontPath("MutatorSansBoldWideMutated.ufo")
    reader = UFOReader(ufoPath)
    cmap, revCmap, anchors = fetchCharacterMappingAndAnchors(
        reader.getGlyphSet(), ufoPath)
    assert cmap[0x0041] == "A"
    assert revCmap["A"] == [0x0041]
    # MutatorSansBoldWideMutated.ufo/glyphs/A_.glif contains a commented-out <unicode>
    # tag, that must not be parsed, as well as a commented-out <anchor>.
    assert 0x1234 not in cmap
    assert anchors == {
        "A": [("top", 645, 815)],
        "E": [("top", 582.5, 815)],
        "macroncmb": [("_top", 0, 815)]
    }
Пример #26
0
 def test_testForExternalChanges_change_layer_order(self):
     path = getTestFontPath("TestExternalEditing.ufo")
     path = makeTestFontCopy(path)
     shutil.copytree(os.path.join(path, "glyphs"),
                     os.path.join(path, "glyphs.test"))
     with open(os.path.join(path, "layercontents.plist"), "rb") as f:
         contents = load(f)
     contents.append(("test", "glyphs.test"))
     with open(os.path.join(path, "layercontents.plist"), "wb") as f:
         dump(contents, f)
     font = Font(path)
     with open(os.path.join(path, "layercontents.plist"), "rb") as f:
         contents = load(f)
     contents.reverse()
     with open(os.path.join(path, "layercontents.plist"), "wb") as f:
         dump(contents, f)
     reader = UFOReader(path)
     self.assertEqual(
         font.layers.testForExternalChanges(reader), {
             "deleted": [],
             "added": [],
             "modified": {},
             "defaultLayer": False,
             "order": True
         })
     tearDownTestFontCopy(font.path)
Пример #27
0
 def test_testForExternalChanges_change_layer_order(self):
     for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"):
         path = getTestFontPath(ufo)
         path = makeTestFontCopy(path)
         fileSystem = openTestFontAsFileSystem(path)
         fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test")
         with fileSystem.open(u"layercontents.plist", "rb") as f:
             contents = load(f)
         contents.append(("test", "glyphs.test"))
         with fileSystem.open(u"layercontents.plist", "wb") as f:
             dump(contents, f)
         closeTestFontAsFileSystem(fileSystem, path)
         with Font(path) as font:
             fileSystem = openTestFontAsFileSystem(path)
             with fileSystem.open(u"layercontents.plist", "rb") as f:
                 contents = load(f)
             contents.reverse()
             with fileSystem.open(u"layercontents.plist", "wb") as f:
                 dump(contents, f)
             closeTestFontAsFileSystem(fileSystem, path)
             with UFOReader(path) as reader:
                 self.assertEqual(font.layers.testForExternalChanges(reader),
                                  {"deleted": [], "added": [], "modified": {},
                                   "defaultLayer": False, "order": True})
         tearDownTestFontCopy(font.path)
Пример #28
0
    def _fontSaveWasCompleted(self):
        """
        On saving a UFO, the underlying fs object is closed.
        The objects then stored in layer._glyphSet contain references
        to a closed, and therefore unusable, filesystem. To remedy this,
        after the save is completed this method will be called and new
        GlyphSet objects will be created and assigned to the layers.
        """
        font = self.font
        font.close()
        font._reader = reader = UFOReader(font.path,
                                          validate=font.ufoLibReadValidate)
        defaultLayerName = self._defaultLayerName
        for layerName in self.layerOrder:
            layer = self[layerName]
            if reader.formatVersionTuple < (3, 0):
                # ufo2 or less has not layers
                # map only to the default layer to the ufo2 glyphSet
                # set all all other layers internal _glyphSet object to None
                if defaultLayerName == layerName:
                    glyphSet = reader.getGlyphSet(
                        validateRead=self.ufoLibReadValidate)
                else:
                    glyphSet = None
            else:
                # we do have layers and the must be available after a save action
                glyphSet = reader.getGlyphSet(
                    layerName=layerName, validateRead=self.ufoLibReadValidate)

            layer._glyphSet = glyphSet
Пример #29
0
    def test_testForExternalChanges_change_default_layer(self):
        for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"):
            path = getTestFontPath(ufo)
            path = makeTestFontCopy(path)

            fileSystem = openTestFontAsFileSystem(path)
            fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test")
            contents = [("foo", "glyphs"), ("test", "glyphs.test")]
            with fileSystem.open(u"layercontents.plist", "wb") as f:
                dump(contents, f)
            closeTestFontAsFileSystem(fileSystem, path)
            font = Font(path)
            fileSystem = openTestFontAsFileSystem(path)
            contents = [("foo", "glyphs.test"), ("test", "glyphs")]
            with fileSystem.open(u"layercontents.plist", "wb") as f:
                dump(contents, f)
            closeTestFontAsFileSystem(fileSystem, path)
            reader = UFOReader(path)
            self.assertEqual(
                font.layers.testForExternalChanges(reader), {
                    "deleted": [],
                    "added": [],
                    "modified": {},
                    "defaultLayer": True,
                    "order": False
                })
            tearDownTestFontCopy(font.path)
Пример #30
0
    def open(cls, path: PathLike, lazy: bool = True, validate: bool = True,) -> "Font":
        """Instantiates a new Font object from a path to a UFO.

        Args:
            path: The path to the UFO to load.
            lazy: If True, load glyphs, data files and images as they are accessed. If
                False, load everything up front.
            validate: If True, enable UFO data model validation during loading. If
                False, load whatever is deserializable.
        """
        reader = UFOReader(path, validate=validate)
        self = cls.read(reader, lazy=lazy)
        self._path = path
        if not lazy:
            reader.close()
        return self
Пример #31
0
 def reloadLayers(self, layerData):
     """
     Reload the layers. This should not be called externally.
     """
     with UFOReader(self.font.path, validate=self.font.ufoLibReadValidate) as reader:
         # handle the layers
         currentLayerOrder = self.layerOrder
         for layerName, l in layerData.get("layers", {}).items():
             # new layer
             if layerName not in currentLayerOrder:
                 glyphSet = reader.getGlyphSet(layerName, validateRead=self.ufoLibReadValidate, validateWrite=self.font.ufoLibWriteValidate)
                 self.newLayer(layerName, glyphSet)
             # get the layer
             layer = self[layerName]
             # reload the layer info
             if l.get("info"):
                 layer.color = None
                 layer.lib.clear()
                 layer._glyphSet.readLayerInfo(layer)
                 self._stampLayerInfoDataState(layer)
             # reload the glyphs
             glyphNames = l.get("glyphNames", [])
             if glyphNames:
                 layer.reloadGlyphs(glyphNames)
         # handle the order
         if layerData.get("order", False):
             newLayerOrder = reader.getLayerNames()
             for layerName in self.layerOrder:
                 if layerName not in newLayerOrder:
                     newLayerOrder.append(layerName)
             self.layerOrder = newLayerOrder
         # handle the default layer
         if layerData.get("default", False):
             newDefaultLayerName = reader.getDefaultLayerName()
             self.defaultLayer = self[newDefaultLayerName]
Пример #32
0
 def test_testForExternalChanges_remove_a_layer(self):
     for ufo in (u"TestExternalEditing.ufo", u"TestExternalEditing.ufoz"):
         path = getTestFontPath(ufo)
         path = makeTestFontCopy(path)
         fileSystem = openTestFontAsFileSystem(path)
         fs.copy.copy_dir(fileSystem, "glyphs", fileSystem, "glyphs.test")
         with fileSystem.open(u"layercontents.plist", "rb") as f:
             contents = load(f)
         contents.append(("test", "glyphs.test"))
         with fileSystem.open(u"layercontents.plist", "wb") as f:
             dump(contents, f)
         closeTestFontAsFileSystem(fileSystem, path)
         font = Font(path)
         fileSystem = openTestFontAsFileSystem(path)
         fileSystem.removetree(u"glyphs.test")
         with fileSystem.open(u"layercontents.plist", "rb") as f:
             contents = load(f)
         del contents[-1]
         with fileSystem.open(u"layercontents.plist", "wb") as f:
             dump(contents, f)
         closeTestFontAsFileSystem(fileSystem, path)
         reader = UFOReader(path)
         self.assertEqual(
             font.layers.testForExternalChanges(reader)["deleted"],
             ["test"])
         tearDownTestFontCopy(font.path)
Пример #33
0
def test_formatVersionTuple(ufo_path):
    reader = UFOReader(ufo_path)

    assert reader.formatVersionTuple == (3, 0)
    assert reader.formatVersionTuple.major == 3
    assert reader.formatVersionTuple.minor == 0
    assert str(reader.formatVersionTuple) == "3.0"
def _font_is_ufo(path):
    from fontTools.ufoLib import UFOReader
    from fontTools.ufoLib.errors import UFOLibError
    try:
        UFOReader(path, validate=False)
        return True
    except (UFOLibError, KeyError, TypeError):
        return False
Пример #35
0
 def testCases(path):
     reader = UFOReader(path)
     expectedFileStructure = fileStructure
     if fileStructure is None:
         expectedFileStructure = UFOFileStructure.PACKAGE
     else:
         expectedFileStructure = UFOFileStructure(fileStructure)
     self.assertEqual(reader.fileStructure, expectedFileStructure)
Пример #36
0
	def testWidthNameConversion(self):
		widthName1To2 = {
			"Ultra-condensed" : 1,
			"Extra-condensed" : 2,
			"Condensed"		  : 3,
			"Semi-condensed"  : 4,
			"Medium (normal)" : 5,
			"Semi-expanded"	  : 6,
			"Expanded"		  : 7,
			"Extra-expanded"  : 8,
			"Ultra-expanded"  : 9
		}
		for old, new in list(widthName1To2.items()):
			info = dict(fontInfoVersion1)
			info["widthName"] = old
			self._writeInfoToPlist(info)
			reader = UFOReader(self.dstDir, validate=True)
			infoObject = TestInfoObject()
			reader.readInfo(infoObject)
			self.assertEqual(new, infoObject.openTypeOS2WidthClass)
Пример #37
0
 def save(self, writer, removeUnreferencedImages=False, saveAs=False, progressBar=None):
     """
     Save images. This method should not be called externally.
     Subclasses may override this method to implement custom saving behavior.
     """
     if removeUnreferencedImages:
         self.disableNotifications()
         for fileName in self.unreferencedFileNames:
             del self[fileName]
         self.enableNotifications()
     if saveAs:
         font = self.font
         if font is not None and font.path is not None and os.path.exists(font.path):
             reader = UFOReader(font.path, validate=False)
             readerImageNames = reader.getImageDirectoryListing(validate=self.ufoLibReadValidate)
             for fileName, data in self._data.items():
                 if data["data"] is not None or fileName not in readerImageNames:
                     continue
                 writer.copyImageFromReader(reader, fileName, fileName, validate=self.ufoLibWriteValidate)
     for fileName in self._scheduledForDeletion:
         try:
             writer.removeImage(fileName, validate=self.ufoLibWriteValidate)
         except UFOLibError:
             # this will be raised if the file doesn't exist.
             # instead of trying to maintain a list of in UFO
             # vs. in memory, simply fail and move on when
             # something can't be deleted because it isn't
             # in the UFO.
             pass
     self._scheduledForDeletion.clear()
     for fileName, data in self._data.items():
         if not data["dirty"]:
             continue
         writer.writeImage(fileName, data["data"], validate=self.ufoLibWriteValidate)
         data["dirty"] = False
         data["onDisk"] = True
         data["onDiskModTime"] = writer.getFileModificationTime("%s/%s" % ("images", fileName))
     self.dirty = False