Beispiel #1
0
def doit(args) :
    cgobj = CompGlyph()
    glyphcount = 0
    for g in ET.parse(args.input).getroot().findall('glyph'):
        glyphcount += 1
        cgobj.CDelement = g
        cgobj.CDline = None
        cgobj.parsefromCDelement()
        if cgobj.CDline != None:
            args.output.write(cgobj.CDline+'\n')
        else:
            pass # error in glyph number glyphcount message
    return
Beispiel #2
0
def doit(args):
    cgobj = CompGlyph()
    glyphcount = 0
    for g in ET.parse(args.input).getroot().findall('glyph'):
        glyphcount += 1
        cgobj.CDelement = g
        cgobj.CDline = None
        cgobj.parsefromCDelement()
        if cgobj.CDline != None:
            args.output.write(cgobj.CDline + '\n')
        else:
            pass  # error in glyph number glyphcount message
    return
Beispiel #3
0
def doit(args):
    ofile = args.output
    lfile = args.log
    filelinecount = 0
    linecount = 0
    elementcount = 0
    cgobj = CompGlyph()
    f = ET.Element('font')
    for line in args.input.readlines():
        filelinecount += 1
        testline = line.strip()
        if len(testline
               ) > 0 and testline[0:1] != '#':  # not whitespace or comment
            linecount += 1
            cgobj.CDline = line
            cgobj.CDelement = None
            try:
                cgobj.parsefromCDline()
                if cgobj.CDelement != None:
                    f.append(cgobj.CDelement)
                    elementcount += 1
            except ValueError as e:
                lfile.write("Line " + str(filelinecount) + ": " + str(e) +
                            '\n')
    if linecount != elementcount:
        lfile.write("Lines read from input file: " + str(filelinecount) + '\n')
        lfile.write("Lines parsed (excluding blank and comment lines): " +
                    str(linecount) + '\n')
        lfile.write("Valid glyphs found: " + str(elementcount) + '\n')


#   instead of simple serialization with: ofile.write(ET.tostring(f))
#   create ETWriter object and specify indentation and attribute order to get normalized output
    indentFirst = "   "
    indentIncr = "   "
    attOrder = "PSName,UID,with,at,x,y"
    for k in args.params:
        if k == 'indentIncr': indentIncr = args.params['indentIncr']
        elif k == 'indentFirst': indentFirst = args.params['indentFirst']
        elif k == 'attOrder': attOrder = args.params['attOrder']
    x = attOrder.split(',')
    attributeOrder = dict(zip(x, range(len(x))))
    etwobj = ETWriter(f,
                      indentFirst=indentFirst,
                      indentIncr=indentIncr,
                      attributeOrder=attributeOrder)
    ofile.write(etwobj.serialize_xml())

    return
Beispiel #4
0
def doit(args) :
    ofile = args.output
    lfile = args.log
    filelinecount = 0
    linecount = 0
    elementcount = 0
    cgobj = CompGlyph()
    f = ET.Element('font')
    for line in args.input.readlines():
        filelinecount += 1
        testline = line.strip()
	if len(testline) > 0 and testline[0] != '#':  # not whitespace or comment
            linecount += 1
            cgobj.CDline=line
            cgobj.CDelement=None
            try:
                cgobj.parsefromCDline()
                if cgobj.CDelement != None:
                    f.append(cgobj.CDelement)
                    elementcount += 1
            except ValueError, e:
                lfile.write("Line "+str(filelinecount)+": "+str(e)+'\n')
Beispiel #5
0
def doit(args) :
    global glyphlist
    infont = args.ifont
    if args.report: infont.logger.loglevel = args.report

    removeRE = re.compile(args.remove) if args.remove else None
    preserveRE = re.compile(args.preserve) if args.preserve else None

    ### temp section (these may someday be passed as optional parameters)
    RemoveUsedAnchors = True
    ### end of temp section

    cgobj = CompGlyph()

    for linenum, rawCDline in enumerate(args.cdfile):
        CDline=rawCDline.strip()
        if len(CDline) == 0 or CDline[0] == "#": continue
        infont.logger.log("Processing line " + str(linenum+1) + ": " + CDline,"I")
        cgobj.CDline=CDline
        try:
            cgobj.parsefromCDline()
        except ValueError as mess:
            infont.logger.log("Parsing error: " + str(mess), "E")
            continue
        g = cgobj.CDelement

        # Collect target glyph information and construct list of component glyphs
        targetglyphname = g.get("PSName")
        targetglyphunicode = g.get("UID")
        glyphlist = []	# list of component glyphs
        lsb = rsb = 0
        adv = None
        for e in g:
            if e.tag == 'note': pass
            elif e.tag == 'property': pass	# ignore mark info
            elif e.tag == 'lsb': lsb = int(e.get('width'))
            elif e.tag == 'rsb': rsb = int(e.get('width'))
            elif e.tag == 'advance': adv = int(e.get('width'))
            elif e.tag == 'base':
                addtolist(e,None)
        infont.logger.log(str(glyphlist),"V")

        # find each component glyph and compute x,y position
        xbase = xadvance = lsb
        ybase = 0
        componentlist = []
        targetglyphanchors = {} # dictionary of {name: (xOffset,yOffset)}
        for currglyph, prevglyph, baseAP, diacAP, shiftx, shifty in glyphlist:
            # get current glyph and its anchor names from font
            if currglyph not in infont.deflayer:
                infont.logger.log(currglyph + " not found in font", "E")
                continue
            cg = infont.deflayer[currglyph]
            cganc = [x.element.get('name') for x in cg['anchor']]
            diacAPx = diacAPy = 0
            baseAPx = baseAPy = 0
            if prevglyph is None:   # this is new 'base'
                xbase = xadvance
                xOffset = xbase
                yOffset = 0
                # Find advance width of currglyph and add to xadvance
                if 'advance' in cg:
                    cgadvance = cg['advance']
                    if cgadvance is not None and cgadvance.element.get('width') is not None:
                        xadvance += int(float(cgadvance.element.get('width')))
            else:                 	# this is 'attach'
                if diacAP is not None: # find diacritic Attachment Point in currglyph
                    if diacAP not in cganc:
                        infont.logger.log("The AP '" + diacAP + "' does not exist on diacritic glyph " + currglyph, "E")
                    else:
                        i = cganc.index(diacAP)
                        diacAPx = int(float(cg['anchor'][i].element.get('x')))
                        diacAPy = int(float(cg['anchor'][i].element.get('y')))
                else:
                    infont.logger.log("No AP specified for diacritic " + currglyph, "E")
                if baseAP is not None: # find base character Attachment Point in targetglyph
                    if baseAP not in targetglyphanchors.keys():
                        infont.logger.log("The AP '" + baseAP + "' does not exist on base glyph when building " + targetglyphname, "E")
                    else:
                        baseAPx = targetglyphanchors[baseAP][0]
                        baseAPy = targetglyphanchors[baseAP][1]
                        if RemoveUsedAnchors:
                            infont.logger.log("Removing used anchor " + baseAP, "V")
                            del targetglyphanchors[baseAP]
                xOffset = baseAPx - diacAPx
                yOffset = baseAPy - diacAPy

            if shiftx is not None: xOffset += int(shiftx)
            if shifty is not None: yOffset += int(shifty)

            componentdic = {'base': currglyph}
            if xOffset != 0: componentdic['xOffset'] = str(xOffset)
            if yOffset != 0: componentdic['yOffset'] = str(yOffset)
            componentlist.append( componentdic )

            # Move anchor information to targetglyphanchors
            for a in cg['anchor']:
                dic = a.element.attrib
                thisanchorname = dic['name']
                if RemoveUsedAnchors and thisanchorname == diacAP:
                    infont.logger.log("Skipping used anchor " + diacAP, "V")
                    continue # skip this anchor
                # add anchor (adjusted for position in targetglyph)
                targetglyphanchors[thisanchorname] = ( int( dic['x'] ) + xOffset, int( dic['y'] ) + yOffset )
                infont.logger.log("Adding anchor " + thisanchorname + ": " + str(targetglyphanchors[thisanchorname]), "V")
            infont.logger.log(str(targetglyphanchors),"V")

        if adv is not None:
            xadvance = adv  ### if adv specified, then this advance value overrides calculated value
        else:
            xadvance += rsb ### adjust with rsb

        infont.logger.log("Glyph: " + targetglyphname + ", " + str(targetglyphunicode) + ", " + str(xadvance), "V")
        for c in componentlist:
            infont.logger.log(str(c), "V")

        # Flatten components unless -n set
        if not args.noflatten:
            newcomponentlist = []
            for compdic in componentlist:
                c = compdic['base']
                x = compdic.get('xOffset')
                y = compdic.get('yOffset')
                # look up component glyph
                g=infont.deflayer[c]
                # check if it has only components (that is, no contours) in outline
                if g['outline'] and g['outline'].components and not g['outline'].contours:
                    # for each component, get base, x1, y1 and create new entry with base, x+x1, y+y1
                    for subcomp in g['outline'].components:
                        componentdic = subcomp.element.attrib.copy()
                        x1 = componentdic.pop('xOffset', 0)
                        y1 = componentdic.pop('yOffset', 0)
                        xOffset = addtwo(x, x1)
                        yOffset = addtwo(y, y1)
                        if xOffset != 0: componentdic['xOffset'] = str(xOffset)
                        if yOffset != 0: componentdic['yOffset'] = str(yOffset)
                        newcomponentlist.append( componentdic )
                else:
                    newcomponentlist.append( compdic )
            if componentlist == newcomponentlist:
                infont.logger.log("No changes to flatten components", "V")
            else:
                componentlist = newcomponentlist
                infont.logger.log("Components flattened", "V")
                for c in componentlist:
                    infont.logger.log(str(c), "V")

        # Check if this new glyph exists in the font already; if so, decide whether to replace, or issue warning
        preservedAPs = set()
        if  targetglyphname in infont.deflayer.keys():
            infont.logger.log("Target glyph, " + targetglyphname + ", already exists in font.", "V")
            targetglyph = infont.deflayer[targetglyphname]
            if targetglyph['outline'] and targetglyph['outline'].contours and not args.force: # don't replace glyph with contours, unless -f set
                infont.logger.log("Not replacing existing glyph, " + targetglyphname + ", because it has contours.", "W")
                continue
            else:
                infont.logger.log("Replacing information in existing glyph, " + targetglyphname, "V")
                # delete information from existing glyph
                targetglyph.remove('outline')
                targetglyph.remove('advance')
                for i in xrange(len(targetglyph['anchor'])-1,-1,-1):
                    aname = targetglyph['anchor'][i].element.attrib['name']
                    if preserveRE is not None and preserveRE.match(aname):
                        preservedAPs.add(aname)
                        infont.logger.log("Preserving anchor " + aname, "V")
                    else:
                        targetglyph.remove('anchor',index=i)
        else:
            infont.logger.log("Adding new glyph, " + targetglyphname, "V")
            # create glyph, using targetglyphname, targetglyphunicode
            targetglyph = ufo.Uglif(layer=infont.deflayer, name=targetglyphname)
            # actually add the glyph to the font
            infont.deflayer.addGlyph(targetglyph)

        targetglyph.add('advance',{'width': str(xadvance)} )
        if targetglyphunicode: # remove any existing unicode value(s) before adding unicode value
            for i in xrange(len(targetglyph['unicode'])-1,-1,-1):
                targetglyph.remove('unicode',index=i)
            targetglyph.add('unicode',{'hex': targetglyphunicode} )
        targetglyph.add('outline')
        # to the outline element, add a component element for every entry in componentlist
        for compdic in componentlist:
            comp = ufo.Ucomponent(targetglyph['outline'],ET.Element('component',compdic))
            targetglyph['outline'].appendobject(comp,'component')
        # copy anchors to new glyph from targetglyphanchors which has format {'U': (500,1000), 'L': (500,0)}
        for a in sorted(targetglyphanchors):
            if removeRE is not None and removeRE.match(a):
                infont.logger.log("Skipping unwanted anchor " + a, "V")
                continue  # skip this anchor
            if a not in preservedAPs:
                targetglyph.add('anchor', {'name': a, 'x': str(targetglyphanchors[a][0]), 'y': str(targetglyphanchors[a][1])} )
        # mark glyphs as being generated by setting cell mark color to dark green (if -c indicated)
        if args.color:
            lib = targetglyph["lib"]
            if lib is None: targetglyph.add("lib")
            targetglyph["lib"].setval("public.markColor", "string", "0.04,0.57,0.04,1")

    # If analysis only, return without writing output font
    if args.analysis: return
    # Return changed font and let execute() write it out
    return infont
Beispiel #6
0
def doit(args) :
    global glyphlist
    infont = args.ifont
    if args.report: infont.logger.loglevel = args.report

    ### temp section (these may someday be passed as optional parameters)
    RemoveUsedAnchors = True
    FlattenComponents = True
    ### end of temp section

    cgobj = CompGlyph()

    for linenum, rawCDline in enumerate(args.cdfile):
        CDline=rawCDline.strip()
        if len(CDline) == 0 or CDline[0] == "#": continue
        infont.logger.log("Processing line " + str(linenum+1) + ": " + CDline,"I")
        cgobj.CDline=CDline
        try:
            cgobj.parsefromCDline()
        except ValueError as mess:
            infont.logger.log("Parsing error: " + str(mess), "E")
            continue
        g = cgobj.CDelement

        # Collect target glyph information and construct list of component glyphs
        targetglyphname = g.get("PSName")
        targetglyphunicode = g.get("UID")
        glyphlist = []	# list of component glyphs
        lsb = rsb = 0
        adv = None
        for e in g:
            if e.tag == 'note': pass
            elif e.tag == 'property': pass	# ignore mark info
            elif e.tag == 'lsb': lsb = int(e.get('width'))
            elif e.tag == 'rsb': rsb = int(e.get('width'))
            elif e.tag == 'advance': adv = int(e.get('width'))
            elif e.tag == 'base':
                addtolist(e,None)
        infont.logger.log(str(glyphlist),"V")

        # find each component glyph and compute x,y position
        xbase = xadvance = lsb
        ybase = 0
        componentlist = []
        targetglyphanchors = {} # dictionary of {name: (xOffset,yOffset)}
        for currglyph, prevglyph, baseAP, diacAP, shiftx, shifty in glyphlist:
            # get current glyph and its anchor names from font
            if currglyph not in infont.deflayer:
                infont.logger.log(currglyph + " not found in font", "E")
                continue
            cg = infont.deflayer[currglyph]
            cganc = [x.element.get('name') for x in cg['anchor']]
            diacAPx = diacAPy = 0
            baseAPx = baseAPy = 0
            if prevglyph is None:   # this is new 'base'
                xbase = xadvance
                xOffset = xbase
                yOffset = 0
            else:                 	# this is 'attach'
                if diacAP is not None: # find diacritic Attachment Point in currglyph
                    if diacAP not in cganc:
                        infont.logger.log("The AP '" + diacAP + "' does not exist on diacritic glyph " + currglyph, "E")
                    else:
                        i = cganc.index(diacAP)
                        diacAPx = int(float(cg['anchor'][i].element.get('x')))
                        diacAPy = int(float(cg['anchor'][i].element.get('y')))
                else:
                    infont.logger.log("No AP specified for diacritic " + currglyph, "E")
                if baseAP is not None: # find base character Attachment Point in targetglyph
                    if baseAP not in targetglyphanchors.keys():
                        infont.logger.log("The AP '" + baseAP + "' does not exist on base glyph when building " + targetglyphname, "E")
                    else:
                        baseAPx = targetglyphanchors[baseAP][0]
                        baseAPy = targetglyphanchors[baseAP][1]
                        if RemoveUsedAnchors:
                            infont.logger.log("Removing used anchor " + baseAP, "V")
                            del targetglyphanchors[baseAP]
                xOffset = baseAPx - diacAPx
                yOffset = baseAPy - diacAPy

            if shiftx is not None: xOffset += int(shiftx)
            if shifty is not None: yOffset += int(shifty)

            componentdic = {'base': currglyph}
            if xOffset != 0: componentdic['xOffset'] = str(xOffset)
            if yOffset != 0: componentdic['yOffset'] = str(yOffset)
            componentlist.append( componentdic )

            # Find advance width of currglyph and add to xadvance
            cgadvance = cg['advance'] if 'advance' in cg else None
            if cgadvance is not None and cgadvance.element.get('width') is not None :
                xadvance += int(float(cgadvance.element.get('width')))

            # Move anchor information to targetglyphanchors
            for a in cg['anchor']:
                dic = a.element.attrib
                thisanchorname = dic['name']
                if RemoveUsedAnchors and thisanchorname == diacAP:
                    infont.logger.log("Skiping used anchor " + diacAP, "V")
                    continue # skip this anchor
                # add anchor (adjusted for position in targetglyph)
                targetglyphanchors[thisanchorname] = ( int( dic['x'] ) + xOffset, int( dic['y'] ) + yOffset )
                infont.logger.log("Adding anchor " + thisanchorname + ": " + str(targetglyphanchors[thisanchorname]), "V")
            infont.logger.log(str(targetglyphanchors),"V")

        xbase = xadvance + rsb ### adjust with rsb
        if adv is not None: xbase = adv ### if adv specified, then this advance value overrides calculated value

        infont.logger.log("Glyph: " + targetglyphname + ", " + str(targetglyphunicode) + ", " + str(xbase), "V")
        for c in componentlist:
            infont.logger.log(str(c), "V")

        # Flatten components
        if FlattenComponents:
            newcomponentlist = []
            for compdic in componentlist:
                c = compdic['base']
                x = compdic.get('xOffset')
                y = compdic.get('yOffset')
                # look up component glyph
                g=infont.deflayer[c]
                # check if it has only components (that is, no contours) in outline
                if g['outline'] and g['outline'].components and not g['outline'].contours:
                    # for each component, get base, x1, y1 and create new entry with base, x+x1, y+y1
                    for subcomp in g['outline'].components:
                        b = subcomp.element.get('base')
                        x1 = subcomp.element.get('xOffset')
                        y1 = subcomp.element.get('yOffset')
                        xOffset = addtwo(x, x1)
                        yOffset = addtwo(y, y1)
                        componentdic = {'base': b}
                        if xOffset != 0: componentdic['xOffset'] = str(xOffset)
                        if yOffset != 0: componentdic['yOffset'] = str(yOffset)
                        newcomponentlist.append( componentdic )
                else:
                    newcomponentlist.append( compdic )
            if componentlist == newcomponentlist:
                infont.logger.log("No changes to flatten components", "V")
            else:
                componentlist = newcomponentlist
                infont.logger.log("Components flattened", "V")
                for c in componentlist:
                    infont.logger.log(str(c), "V")

        # Check if this new glyph exists in the font already; if so, decide whether to replace, or issue warning
        if  targetglyphname in infont.deflayer.keys():
            infont.logger.log("Target glyph, " + targetglyphname + ", already exists in font.", "V")
            targetglyph = infont.deflayer[targetglyphname]
            if targetglyph['outline'] and targetglyph['outline'].contours and not args.force: # don't replace glyph with contours, unless -f set
                infont.logger.log("Not replacing existing glyph, " + targetglyphname + ", because it has contours.", "W")
                continue
            else:
                infont.logger.log("Replacing information in existing glyph, " + targetglyphname, "V")
                # delete information from existing glyph
                targetglyph.remove('outline')
                targetglyph.remove('advance')
                for i in xrange(len(targetglyph['anchor'])-1,-1,-1):
                    targetglyph.remove('anchor',index=i)
        else:
            infont.logger.log("Adding new glyph, " + targetglyphname, "V")
            # create glyph, using targetglyphname, targetglyphunicode
            targetglyph = ufo.Uglif(layer=infont.deflayer, name=targetglyphname)
            # actually add the glyph to the font
            infont.deflayer.addGlyph(targetglyph)

        targetglyph.add('advance',{'width': str(xbase)} )
        if targetglyphunicode: # remove any existing unicode value(s) before adding unicode value
            for i in xrange(len(targetglyph['unicode'])-1,-1,-1):
                targetglyph.remove('unicode',index=i)
            targetglyph.add('unicode',{'hex': targetglyphunicode} )
        targetglyph.add('outline')
        # to the outline element, add a component element for every entry in componentlist
        for compdic in componentlist:
            comp = ufo.Ucomponent(targetglyph['outline'],ET.Element('component',compdic))
            targetglyph['outline'].appendobject(comp,'component')
        # copy anchors to new glyph from targetglyphanchors which has format {'U': (500,1000), 'L': (500,0)}
        for a in targetglyphanchors:
            targetglyph.add('anchor', {'name': a, 'x': str(targetglyphanchors[a][0]), 'y': str(targetglyphanchors[a][1])} )

    # If analysis only, return without writing output font
    if args.analysis: return
    # Return changed font and let execute() write it out
    return infont