Skip to content
This repository has been archived by the owner on Jan 28, 2019. It is now read-only.

add the default xml declaration in writeGlyphToString #157

Merged
merged 4 commits into from
Jul 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 50 additions & 44 deletions Lib/ufoLib/glifLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,14 @@
from io import BytesIO, open
from warnings import warn
from collections import OrderedDict
from fontTools.misc.py23 import tobytes, unicode
from fontTools.misc.py23 import basestring, unicode
from ufoLib.plistlib import PlistWriter, readPlist, writePlist
from ufoLib.plistFromETree import readPlistFromTree
from ufoLib.pointPen import AbstractPointPen, PointToSegmentPen
from ufoLib.filenames import userNameToFileName
from ufoLib.validators import isDictEnough, genericTypeValidator, colorValidator,\
guidelinesValidator, anchorsValidator, identifierValidator, imageValidator, glyphLibValidator

try:
basestring
except NameError:
basestring = str

try:
unicode
except NameError:
unicode = str

from lxml import etree


Expand Down Expand Up @@ -388,7 +378,7 @@ def writeGlyph(self, glyphName, glyphObject=None, drawPointsFunc=None, formatVer
if validate is None:
validate = self._validateWrite
self._purgeCachedGLIF(glyphName)
data = writeGlyphToString(glyphName, glyphObject, drawPointsFunc, formatVersion=formatVersion, validate=validate)
data = _writeGlyphToBytes(glyphName, glyphObject, drawPointsFunc, formatVersion=formatVersion, validate=validate)
fileName = self.contents.get(glyphName)
if fileName is None:
if self._existingFileNames is None:
Expand All @@ -407,7 +397,7 @@ def writeGlyph(self, glyphName, glyphObject=None, drawPointsFunc=None, formatVer
if data == oldData:
return
with open(path, "wb") as f:
f.write(tobytes(data, encoding="utf-8"))
f.write(data)

def deleteGlyph(self, glyphName):
"""Permanently delete the glyph from the glyph set on disk. Will
Expand Down Expand Up @@ -560,34 +550,10 @@ def readGlyphFromString(aString, glyphObject=None, pointPen=None, formatVersions
_readGlyphFromTree(tree, glyphObject, pointPen, formatVersions=formatVersions, validate=validate)


def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, formatVersion=2, validate=True):
"""
Return .glif data for a glyph as a UTF-8 encoded string.
The 'glyphObject' argument can be any kind of object (even None);
the writeGlyphToString() method will attempt to get the following
attributes from it:
"width" the advance width of the glyph
"height" the advance height of the glyph
"unicodes" a list of unicode values for this glyph
"note" a string
"lib" a dictionary containing custom data
"image" a dictionary containing image data
"guidelines" a list of guideline data dictionaries
"anchors" a list of anchor data dictionaries

All attributes are optional: if 'glyphObject' doesn't
have the attribute, it will simply be skipped.

To write outline data to the .glif file, writeGlyphToString() needs
a function (any callable object actually) that will take one
argument: an object that conforms to the PointPen protocol.
The function will be called by writeGlyphToString(); it has to call the
proper PointPen methods to transfer the outline to the .glif file.

The GLIF format version can be specified with the formatVersion argument.

``validate`` will validate the written data. It is set to ``True`` by default.
"""
def _writeGlyphToBytes(
glyphName, glyphObject=None, drawPointsFunc=None, writer=None,
formatVersion=2, validate=True):
"""Return .glif data for a glyph as a UTF-8 encoded bytes string."""
# start
if validate and not isinstance(glyphName, basestring):
raise GlifLibError("The glyph name is not properly formatted.")
Expand Down Expand Up @@ -627,9 +593,49 @@ def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, formatV
if getattr(glyphObject, "lib", None):
_writeLib(glyphObject, root, validate)
# return the text
tree = etree.ElementTree(root)
text = etree.tostring(root, encoding=unicode, pretty_print=True)
return text
data = etree.tostring(
root, encoding="utf-8", xml_declaration=True, pretty_print=True
)
return data


def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, formatVersion=2, validate=True):
"""
Return .glif data for a glyph as a Unicode string (`unicode` in py2, `str`
in py3). The XML declaration's encoding is always set to "UTF-8".
The 'glyphObject' argument can be any kind of object (even None);
the writeGlyphToString() method will attempt to get the following
attributes from it:
"width" the advance width of the glyph
"height" the advance height of the glyph
"unicodes" a list of unicode values for this glyph
"note" a string
"lib" a dictionary containing custom data
"image" a dictionary containing image data
"guidelines" a list of guideline data dictionaries
"anchors" a list of anchor data dictionaries

All attributes are optional: if 'glyphObject' doesn't
have the attribute, it will simply be skipped.

To write outline data to the .glif file, writeGlyphToString() needs
a function (any callable object actually) that will take one
argument: an object that conforms to the PointPen protocol.
The function will be called by writeGlyphToString(); it has to call the
proper PointPen methods to transfer the outline to the .glif file.

The GLIF format version can be specified with the formatVersion argument.

``validate`` will validate the written data. It is set to ``True`` by default.
"""
data = _writeGlyphToBytes(
glyphName,
glyphObject=glyphObject,
drawPointsFunc=drawPointsFunc,
formatVersion=formatVersion,
validate=validate,
)
return data.decode("utf-8")


def _writeAdvance(glyphObject, element, validate):
Expand Down
5 changes: 3 additions & 2 deletions Lib/ufoLib/test/test_GLIF1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import unittest
from ufoLib.glifLib import GlifLibError, readGlyphFromString, writeGlyphToString
from ufoLib.test.testSupport import Glyph, stripText
from itertools import islice

try:
basestring
Expand All @@ -25,8 +26,8 @@ def pyToGLIF(self, py):
glyph = Glyph()
exec(py, {"glyph" : glyph, "pointPen" : glyph})
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=1, validate=True)
glif = "\n".join(glif.splitlines())
return glif
# discard the first line containing the xml declaration
return "\n".join(islice(glif.splitlines(), 1, None))

def glifToPy(self, glif):
glif = stripText(glif)
Expand Down
5 changes: 3 additions & 2 deletions Lib/ufoLib/test/test_GLIF2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import unittest
from ufoLib.glifLib import GlifLibError, readGlyphFromString, writeGlyphToString
from ufoLib.test.testSupport import Glyph, stripText
from itertools import islice

try:
basestring
Expand All @@ -25,8 +26,8 @@ def pyToGLIF(self, py):
glyph = Glyph()
exec(py, {"glyph" : glyph, "pointPen" : glyph})
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=2, validate=True)
glif = "\n".join(glif.splitlines())
return glif
# discard the first line containing the xml declaration
return "\n".join(islice(glif.splitlines(), 1, None))

def glifToPy(self, glif):
glif = stripText(glif)
Expand Down