예제 #1
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)
예제 #2
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)
예제 #3
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)