Example #1
0
	def testWrite(self):
		infoObject = self.makeInfoObject()
		writer = UFOWriter(self.dstDir, formatVersion=1)
		writer.writeInfo(infoObject)
		writtenData = self.readPlist()
		for attr, originalValue in list(fontInfoVersion1.items()):
			newValue = writtenData[attr]
			self.assertEqual(newValue, originalValue)
Example #2
0
 def testWrite(self):
     infoObject = self.makeInfoObject()
     writer = UFOWriter(self.dstDir, formatVersion=1)
     writer.writeInfo(infoObject)
     writtenData = self.readPlist()
     for attr, originalValue in list(fontInfoVersion1.items()):
         newValue = writtenData[attr]
         self.assertEqual(newValue, originalValue)
Example #3
0
 def testFontStyleConversion(self):
     fontStyle1To2 = {
         64: "regular",
         1: "italic",
         32: "bold",
         33: "bold italic"
     }
     for old, new in list(fontStyle1To2.items()):
         infoObject = self.makeInfoObject()
         infoObject.styleMapStyleName = new
         writer = UFOWriter(self.dstDir, formatVersion=1)
         writer.writeInfo(infoObject)
         writtenData = self.readPlist()
         self.assertEqual(writtenData["fontStyle"], old)
Example #4
0
	def testFontStyleConversion(self):
		fontStyle1To2 = {
			64 : "regular",
			1  : "italic",
			32 : "bold",
			33 : "bold italic"
		}
		for old, new in list(fontStyle1To2.items()):
			infoObject = self.makeInfoObject()
			infoObject.styleMapStyleName = new
			writer = UFOWriter(self.dstDir, formatVersion=1)
			writer.writeInfo(infoObject)
			writtenData = self.readPlist()
			self.assertEqual(writtenData["fontStyle"], old)
Example #5
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()):
         infoObject = self.makeInfoObject()
         infoObject.openTypeOS2WidthClass = new
         writer = UFOWriter(self.dstDir, formatVersion=1)
         writer.writeInfo(infoObject)
         writtenData = self.readPlist()
         self.assertEqual(writtenData["widthName"], old)
Example #6
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()):
			infoObject = self.makeInfoObject()
			infoObject.openTypeOS2WidthClass = new
			writer = UFOWriter(self.dstDir, formatVersion=1)
			writer.writeInfo(infoObject)
			writtenData = self.readPlist()
			self.assertEqual(writtenData["widthName"], old)
Example #7
0
	def save(self):
		print "Saving font..."
		""" A real hack here. 
		If the font format was less than 3, we need to save it with the original
		format. I care specifically about RoboFont, which can still read only
		format 2. However, dfont.save() will save the processed layer only if
		the format is 3. If I ask to save(formatVersion=3) when the dfont format
		is 2, then the save function will  first mark all the glyphs in all the layers
		as being 'dirty' and needing to be saved. and also causes the defcon
		font.py:save to delete the original font and write everything anew.
		
		In order to avoid this, I reach into the defcon code and save only the processed glyphs layer.
		
		"""
		from ufoLib import UFOWriter
		writer = UFOWriter(self.dFont.path, formatVersion=2)
		layers = self.dFont.layers
		layer = layers[kProcessedGlyphsLayerName]
		writer._formatVersion = 3
		writer.layerContents[kProcessedGlyphsLayerName] = kProcessedGlyphsLayer
		glyphSet = writer.getGlyphSet(layerName=kProcessedGlyphsLayerName, defaultLayer=False)
		writer.writeLayerContents(layers.layerOrder)
		writer._formatVersion = 2
		layer.save(glyphSet)
		layer.dirty = False

		if self.fontType == kUFOFontType:
			self.ufoFontHashData.hashMapChanged = True
			self.ufoFontHashData.close() # Write the hash data.
		elif self.fontType == kType1FontType:
			cmd = "tx -t1 \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
		elif self.fontType == kCFFFontType:
			cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
		elif self.fontType == kOpenTypeCFFFontType:
			tempCFFPath = self.tempUFOPath + ".cff"
			cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, tempCFFPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
			cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (tempCFFPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
			if os.path.exists(tempCFFPath):
				os.remove(tempCFFPath)
		else:
			print "Font type is unknown: cannot save changes"

		if (self.tempUFOPath != None) and os.path.exists(self.tempUFOPath):
			shutil.rmtree(self.tempUFOPath) 
Example #8
0
    def save(self, path):
        if path is None:
            path = self.path

        if os.path.abspath(self.path) != os.path.abspath(path):
            # If user has specified a path other than the source font path,
            # then copy the entire UFO font, and operate on the copy.
            log.info("Copying from source UFO font to output UFO font before "
                     "processing...")
            if os.path.exists(path):
                shutil.rmtree(path)
            shutil.copytree(self.path, path)

        writer = UFOWriter(path, self._reader.formatVersion, validate=False)

        if self.hashMapChanged:
            self.writeHashMap(writer)
        self.hashMapChanged = False

        layer = PROCESSED_LAYER_NAME
        if self.writeToDefaultLayer:
            layer = None

        # Write glyphs.
        glyphset = writer.getGlyphSet(layer, defaultLayer=layer is None)
        for name, glyph in self.newGlyphMap.items():
            filename = self.glyphMap[name]
            if not self.writeToDefaultLayer and \
                    name in self.processedLayerGlyphMap:
                filename = self.processedLayerGlyphMap[name]
            glyphset.contents[name] = filename
            glyphset.writeGlyph(name, glyph, glyph.drawPoints)
        glyphset.writeContents()

        # Write layer contents.
        layers = {DEFAULT_LAYER_NAME: DEFAULT_GLYPHS_DIRNAME}
        if self.processedLayerGlyphMap:
            layers[PROCESSED_LAYER_NAME] = PROCESSED_GLYPHS_DIRNAME
        writer.layerContents.update(layers)
        writer.writeLayerContents([DEFAULT_LAYER_NAME, PROCESSED_LAYER_NAME])
Example #9
0
 def testWrite(self):
     writer = UFOWriter(self.dstDir, formatVersion=2)
     writer.setKerningGroupConversionRenameMaps(self.downConversionMapping)
     writer.writeKerning(self.kerning)
     writer.writeGroups(self.groups)
     # test groups
     path = os.path.join(self.dstDir, "groups.plist")
     writtenGroups = readPlist(path)
     self.assertEqual(writtenGroups, self.expectedWrittenGroups)
     # test kerning
     path = os.path.join(self.dstDir, "kerning.plist")
     writtenKerning = readPlist(path)
     self.assertEqual(writtenKerning, self.expectedWrittenKerning)
     self.tearDownUFO()
Example #10
0
	def save(self):
		print "Saving font..."
		""" A real hack here. 
		If the font format was less than 3, we need to save it with the original
		format. I care specifically about RoboFont, which can still read only
		format 2. However, dfont.save() will save the processed layer only if
		the format is 3. If I ask to save(formatVersion=3) when the dfont format
		is 2, then the save function will  first mark all the glyphs in all the layers
		as being 'dirty' and needing to be saved. and also causes the defcon
		font.py:save to delete the original font and write everything anew.
		
		In order to avoid this, I reach into the defcon code and save only the processed glyphs layer.
		
		"""
		from ufoLib import UFOWriter
		writer = UFOWriter(self.dFont.path, formatVersion=2)
		if self.saveToDefaultLayer:
			self.dFont.save()
		else:
			layers = self.dFont.layers
			layer = layers[kProcessedGlyphsLayerName]
			writer._formatVersion = 3
			writer.layerContents[kProcessedGlyphsLayerName] = kProcessedGlyphsLayer
			glyphSet = writer.getGlyphSet(layerName=kProcessedGlyphsLayerName, defaultLayer=False)
			writer.writeLayerContents(layers.layerOrder)
			writer._formatVersion = 2
			layer.save(glyphSet)
			layer.dirty = False

		if self.fontType == kUFOFontType:
			self.ufoFontHashData.close() # Write the hash data, if it has changed.
		elif self.fontType == kType1FontType:
			cmd = "tx -t1 \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
		elif self.fontType == kCFFFontType:
			cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
		elif self.fontType == kOpenTypeCFFFontType:
			tempCFFPath = self.tempUFOPath + ".cff"
			cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.tempUFOPath, tempCFFPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
			cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (tempCFFPath, self.fontPath)
			p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout
			log = p.read()
			if os.path.exists(tempCFFPath):
				os.remove(tempCFFPath)
		else:
			print "Font type is unknown: cannot save changes"

		if (self.tempUFOPath != None) and os.path.exists(self.tempUFOPath):
			shutil.rmtree(self.tempUFOPath) 
Example #11
0
	def testWrite(self):
		writer = UFOWriter(self.dstDir, formatVersion=2)
		writer.setKerningGroupConversionRenameMaps(self.downConversionMapping)
		writer.writeKerning(self.kerning)
		writer.writeGroups(self.groups)
		# test groups
		path = os.path.join(self.dstDir, "groups.plist")
		writtenGroups = readPlist(path)
		self.assertEqual(writtenGroups, self.expectedWrittenGroups)
		# test kerning
		path = os.path.join(self.dstDir, "kerning.plist")
		writtenKerning = readPlist(path)
		self.assertEqual(writtenKerning, self.expectedWrittenKerning)
		self.tearDownUFO()
Example #12
0
def test_pathlike(testufo):

    class PathLike(object):

        def __init__(self, s):
            self._path = s

        def __fspath__(self):
            return tostr(self._path, sys.getfilesystemencoding())

    path = PathLike(testufo)

    with UFOReader(path) as reader:
        assert reader._path == path.__fspath__()

    with UFOWriter(path) as writer:
        assert writer._path == path.__fspath__()
Example #13
0
def write_ufo_font(path, hand):
    glyphs = generate_glyphs(hand)

    import shutil
    root = "%s.ufo" % path
    shutil.rmtree(root)

    writer = UFOWriter(root, fileCreator="net.team2xh.tenchi")
    writer.writeGroups({character: [character] for character in hand.glyphs})
    writer.writeInfo(font_info(hand))
    write_ufo_glyphs(glyphs, root)

    #writer._readLayerContents()

    return root
Example #14
0
    def save(self):
        print("Saving font...")
        """ A real hack here.
        If the font format was less than 3, we need to save it with the
        original format. I care specifically about RoboFont, which can still
        read only format 2. However, dfont.save() will save the processed
        layer only if the format is 3. If I ask to save(formatVersion=3)
        when the dfont format is 2, then the save function will first mark all
        the glyphs in all the layers as being 'dirty' and needing to be saved.
        and also causes the defcon font.py:save to delete the original font
        and write everything anew.

        In order to avoid this, I reach into the defcon code and save only
        the processed glyphs layer. I also set glyph_set.ufoFormatVersion so
        that the glif files will be set to format 1.
        """
        from ufoLib import UFOWriter
        writer = UFOWriter(self.defcon_font.path, formatVersion=2)
        if self.save_to_default_layer:
            self.defcon_font.save()
        else:
            layers = self.defcon_font.layers
            layer = layers[PROCD_GLYPHS_LAYER_NAME]
            writer._formatVersion = 3
            writer.layerContents[PROCD_GLYPHS_LAYER_NAME] = \
                PROCD_GLYPHS_LAYER
            glyph_set = writer.getGlyphSet(layerName=PROCD_GLYPHS_LAYER_NAME,
                                           defaultLayer=False)
            writer.writeLayerContents(layers.layerOrder)
            glyph_set.ufoFormatVersion = 2
            layer.save(glyph_set)
            layer.dirty = False

        if self.font_type == UFO_FONT_TYPE:
            # Write the hash data, if it has changed.
            self.ufo_font_hash_data.close()
        elif self.font_type == TYPE1_FONT_TYPE:
            cmd = "tx -t1 \"%s\" \"%s\"" % (self.temp_ufo_path, self.font_path)
            subprocess.Popen(cmd,
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        elif self.font_type == CFF_FONT_TYPE:
            cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.temp_ufo_path,
                                                     self.font_path)
            subprocess.call(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
        elif self.font_type == OPENTYPE_CFF_FONT_TYPE:
            temp_cff_path = self.temp_ufo_path + ".cff"
            cmd = "tx -cff +b -std \"%s\" \"%s\"" % (self.temp_ufo_path,
                                                     temp_cff_path)
            subprocess.call(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
            cmd = "sfntedit -a \"CFF \"=\"%s\" \"%s\"" % (temp_cff_path,
                                                          self.font_path)
            subprocess.call(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
            if os.path.exists(temp_cff_path):
                os.remove(temp_cff_path)
        else:
            print("Font type is unknown: cannot save changes")

        if (self.temp_ufo_path is not None) \
                and os.path.exists(self.temp_ufo_path):
            shutil.rmtree(self.temp_ufo_path)
Example #15
0
    def save(self, destDir=None, doProgress=False, formatVersion=2):
        """Save the Font in UFO format."""
        # XXX note that when doing "save as" by specifying the destDir argument
        # _all_ glyphs get loaded into memory. This could be optimized by either
        # copying those .glif files that have not been edited or (not sure how
        # well that would work) by simply clearing out self._objects after the
        # save.
        from ufoLib import UFOWriter
        from robofab.tools.fontlabFeatureSplitter import splitFeaturesForFontLab
        # if no destination is given, or if
        # the given destination is the current
        # path, this is not a save as operation
        if destDir is None or destDir == self._path:
            saveAs = False
            destDir = self._path
        else:
            saveAs = True
        # start a progress bar
        nonGlyphCount = 5
        bar = None
        if doProgress:
            from robofab.interface.all.dialogs import ProgressBar
            bar = ProgressBar("Exporting UFO",
                              nonGlyphCount + len(self._object.keys()))
        # write
        writer = UFOWriter(destDir, formatVersion=formatVersion)
        try:
            # make a shallow copy of the lib. stuff may be added to it.
            fontLib = dict(self.lib)
            # info
            if bar:
                bar.label("Saving info...")
            writer.writeInfo(self.info)
            if bar:
                bar.tick()
            # kerning
            if self.kerning.changed or saveAs:
                if bar:
                    bar.label("Saving kerning...")
                writer.writeKerning(self.kerning.asDict())
                if bar:
                    bar.tick()
            # groups
            if bar:
                bar.label("Saving groups...")
            writer.writeGroups(self.groups)
            if bar:
                bar.tick()
            # features
            if bar:
                bar.label("Saving features...")
            features = self.features.text
            if features is None:
                features = ""
            if formatVersion == 2:
                writer.writeFeatures(features)
            elif formatVersion == 1:
                classes, features = splitFeaturesForFontLab(features)
                if classes:
                    fontLib["org.robofab.opentype.classes"] = classes.strip(
                    ) + "\n"
                if features:
                    featureDict = {}
                    for featureName, featureText in features:
                        featureDict[featureName] = featureText.strip() + "\n"
                    fontLib["org.robofab.opentype.features"] = featureDict
                    fontLib["org.robofab.opentype.featureorder"] = [
                        featureName for featureName, featureText in features
                    ]
            if bar:
                bar.tick()
            # lib
            if formatVersion == 1:
                fontLib[postScriptHintDataLibKey] = self.psHints.asDict()
            if bar:
                bar.label("Saving lib...")
            writer.writeLib(fontLib)
            if bar:
                bar.tick()
            # glyphs
            glyphNameToFileNameFunc = self.getGlyphNameToFileNameFunc()

            glyphSet = writer.getGlyphSet(glyphNameToFileNameFunc)
            if len(self._scheduledForDeletion) != 0:
                if bar:
                    bar.label("Removing deleted glyphs...")
                for glyphName in self._scheduledForDeletion:
                    if glyphSet.has_key(glyphName):
                        glyphSet.deleteGlyph(glyphName)
                if bar:
                    bar.tick()
            if bar:
                bar.label("Saving glyphs...")
            count = nonGlyphCount
            if saveAs:
                glyphNames = self.keys()
            else:
                glyphNames = self._object.keys()
            for glyphName in glyphNames:
                glyph = self[glyphName]
                glyph.psHints._saveToLib(glyph.lib)
                glyph._saveToGlyphSet(glyphSet,
                                      glyphName=glyphName,
                                      force=saveAs)
                if bar and not count % 10:
                    bar.tick(count)
                count = count + 1
            glyphSet.writeContents()
            self._glyphSet = glyphSet
        # only blindly stop if the user says to
        except KeyboardInterrupt:
            bar.close()
            bar = None
        # kill the progress bar
        if bar:
            bar.close()
        # reset internal stuff
        self._path = destDir
        self._scheduledForDeletion = []
        self.setChanged(False)
Example #16
0
def main(args=None):
    from io import open

    options = parse_args(args)
    config = getConfig(options.config)
    svg_file = options.infile

    # Parse SVG to read the width, height attributes defined in it
    svgObj = parseSvg(svg_file)
    width = float(svgObj.attrib['width'].replace("px", " "))
    height = float(svgObj.attrib['height'].replace("px", " "))
    name = os.path.splitext(os.path.basename(svg_file))[0]
    ufo_font_path = config['font']['ufo']
    # Get the font metadata from UFO
    reader = UFOReader(ufo_font_path)
    writer = UFOWriter(ufo_font_path)

    infoObject = InfoObject()
    reader.readInfo(infoObject)
    fontName = config['font']['name']

    # Get the configuration for this svg
    try:
        svg_config = config['svgs'][name]
    except KeyError:
        print("\033[93mSkip: Configuration not found for svg : %r\033[0m" %
              name)
        return
    if 'unicode' in svg_config:
        unicodeVal = unicode_hex_list(svg_config['unicode'])
    else:
        unicodeVal = None
    glyphWidth = width + int(svg_config['left']) + int(svg_config['right'])
    if glyphWidth < 0:
        raise UFOLibError("Glyph %s has negative width." % name)

    contentsPlistPath = ufo_font_path + '/glyphs/contents.plist'
    try:
        with open(contentsPlistPath, "rb") as f:
            contentsPlist = readPlist(f)
    except:
        raise UFOLibError("The file %s could not be read." % contentsPlistPath)

    glyph_name = svg_config['glyph_name']
    # Replace all capital letters with a following '_' to avoid file name clash in Windows
    glyph_file_name = re.sub(r'([A-Z]){1}', lambda pat: pat.group(1) + '_',
                             glyph_name) + '.glif'
    if glyph_name in contentsPlist:
        existing_glyph = True
    else:
        existing_glyph = False

    # Calculate the transformation to do
    transform = transform_list(config['font']['transform'])
    base = 0
    if 'base' in svg_config:
        base = int(svg_config['base'])
    transform[4] += int(svg_config['left'])  # X offset = left bearing
    transform[5] += height + base  # Y offset

    glif = svg2glif(svg_file,
                    name=svg_config['glyph_name'],
                    width=glyphWidth,
                    height=getattr(infoObject, 'unitsPerEm'),
                    unicodes=unicodeVal,
                    transform=transform,
                    version=config['font']['version'])

    if options.outfile is None:
        output_file = ufo_font_path + '/glyphs/' + glyph_file_name
    else:
        output_file = options.outfile
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write(glif)

    print(
        "\033[94m[%s]\033[0m \033[92mConvert\033[0m %s -> %s \033[92m✔️\033[0m"
        % (fontName, name, output_file))

    # If this is a new glyph, add it to the UFO/glyphs/contents.plist
    if not existing_glyph:
        contentsPlist[glyph_name] = glyph_file_name
        writePlistAtomically(contentsPlist, contentsPlistPath)
        print(
            "\033[94m[%s]\033[0m \033[92mAdd\033[0m %s -> %s \033[92m✔️\033[0m"
            % (fontName, glyph_name, glyph_file_name))
        lib_obj = reader.readLib()
        lib_obj['public.glyphOrder'].append(glyph_name)
        writer.writeLib(lib_obj)
Example #17
0
 def test_write(self, testufoz):
     with UFOWriter(testufoz, structure="zip") as writer:
         writer.writeLib({"hello world": 123})
     with UFOReader(testufoz) as reader:
         assert reader.readLib() == {"hello world": 123}
Example #18
0
def test_path_attribute_deprecated(testufo):
    with UFOWriter(testufo) as writer:
        with pytest.warns(DeprecationWarning, match="The 'path' attribute"):
            writer.path
Example #19
0
    existingFont = fontforge.open(existingFontPath)
    existingGlyphNames = set(existingFont.__iter__())

    justInSource = sourceGlyphNames - existingGlyphNames
    # print 'glyphs in both:', sourceGlyphNames & existingGlyphNames
    # print 'glyphs only in source:', justInSource

    filtered = [name for name in justInSource if isValid(name)]
    overlapping = [name for name in (sourceGlyphNames & existingGlyphNames) if isValid(name)]
    print 'from the latin and valid:', sorted(filtered)
    print '------------------'
    print 'overlapping and valid', sorted(overlapping)


    writer = UFOWriter('sources/jomhuria-latin.ufo', formatVersion=2)
    newGlypsSet = writer.getGlyphSet()


    for glyphName in filtered + overlapping:
        # note how incestuous Glyph and GlyphSet interact.
        glyph = Glyph(glyphName, sourceGlyphSet)
        # this reads just the attributes
        sourceGlyphSet.readGlyph(glyphName, glyph)
        newGlypsSet.writeGlyph(
                      glyphName
                    , glyphObject=glyph
                    , drawPointsFunc=glyph.drawPoints
                )

    # after writing glyphs write the contents.plist
Example #20
0
	def save(self, destDir=None, doProgress=False, formatVersion=2):
		"""Save the Font in UFO format."""
		# XXX note that when doing "save as" by specifying the destDir argument
		# _all_ glyphs get loaded into memory. This could be optimized by either
		# copying those .glif files that have not been edited or (not sure how
		# well that would work) by simply clearing out self._objects after the
		# save.
		from ufoLib import UFOWriter
		from robofab.tools.fontlabFeatureSplitter import splitFeaturesForFontLab
		# if no destination is given, or if
		# the given destination is the current
		# path, this is not a save as operation
		if destDir is None or destDir == self._path:
			saveAs = False
			destDir = self._path
		else:
			saveAs = True
		# start a progress bar
		nonGlyphCount = 5
		bar = None
		if doProgress:
			from robofab.interface.all.dialogs import ProgressBar
			bar = ProgressBar("Exporting UFO", nonGlyphCount + len(self._object.keys()))
		# write
		writer = UFOWriter(destDir, formatVersion=formatVersion)
		try:
			# make a shallow copy of the lib. stuff may be added to it.
			fontLib = dict(self.lib)
			# info
			if bar:
				bar.label("Saving info...")
			writer.writeInfo(self.info)
			if bar:
				bar.tick()
			# kerning
			if self.kerning.changed or saveAs:
				if bar:
					bar.label("Saving kerning...")
				writer.writeKerning(self.kerning.asDict())
				if bar:
					bar.tick()
			# groups
			if bar:
				bar.label("Saving groups...")
			writer.writeGroups(self.groups)
			if bar:
				bar.tick()
			# features
			if bar:
				bar.label("Saving features...")
			features = self.features.text
			if features is None:
				features = ""
			if formatVersion == 2:
				writer.writeFeatures(features)
			elif formatVersion == 1:
				classes, features = splitFeaturesForFontLab(features)
				if classes:
					fontLib["org.robofab.opentype.classes"] = classes.strip() + "\n"
				if features:
					featureDict = {}
					for featureName, featureText in features:
						featureDict[featureName] = featureText.strip() + "\n"
					fontLib["org.robofab.opentype.features"] = featureDict
					fontLib["org.robofab.opentype.featureorder"] = [featureName for featureName, featureText in features]
			if bar:
				bar.tick()
			# lib
			if formatVersion == 1:
				fontLib[postScriptHintDataLibKey] = self.psHints.asDict()
			if bar:
				bar.label("Saving lib...")
			writer.writeLib(fontLib)
			if bar:
				bar.tick()
			# glyphs
			glyphNameToFileNameFunc = self.getGlyphNameToFileNameFunc()

			glyphSet = writer.getGlyphSet(glyphNameToFileNameFunc)
			if len(self._scheduledForDeletion) != 0:
				if bar:
					bar.label("Removing deleted glyphs...")
				for glyphName in self._scheduledForDeletion:
					if glyphSet.has_key(glyphName):
						glyphSet.deleteGlyph(glyphName)
				if bar:
					bar.tick()
			if bar:
				bar.label("Saving glyphs...")
			count = nonGlyphCount
			if saveAs:
				glyphNames = self.keys()
			else:
				glyphNames = self._object.keys()
			for glyphName in glyphNames:
				glyph = self[glyphName]
				glyph.psHints._saveToLib(glyph.lib)
				glyph._saveToGlyphSet(glyphSet, glyphName=glyphName, force=saveAs)
				if bar and not count % 10:
					bar.tick(count)
				count = count + 1
			glyphSet.writeContents()
			self._glyphSet = glyphSet
		# only blindly stop if the user says to
		except KeyboardInterrupt:
			bar.close()
			bar = None
		# kill the progress bar
		if bar:
			bar.close()
		# reset internal stuff
		self._path = destDir
		self._scheduledForDeletion = []
		self.setChanged(False)
Example #21
0
 def test_init_writer(self):
     m = fs.memoryfs.MemoryFS()
     with UFOWriter(m) as writer:
         assert m.exists("metainfo.plist")
         assert writer._path == "<memfs>"