1# Copyright 2015 Google Inc. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15 16import re 17from anchors import alignComponentsToAnchors 18from string import find 19 20def parseComposite(composite): 21 c = composite.split("=") 22 d = c[1].split("/") 23 glyphName = d[0] 24 if len(d) == 1: 25 offset = [0,0] 26 else: 27 offset = [int(i) for i in d[1].split(",")] 28 accentString = c[0] 29 accents = accentString.split("+") 30 baseName = accents.pop(0) 31 accentNames = [i.split(":") for i in accents ] 32 return (glyphName, baseName, accentNames, offset) 33 34 35def copyMarkAnchors(f, g, srcname, width): 36 unicode_range = set( 37 range(0x0030, 0x02B0) + range(0x1E00, 0x1EFF) + 38 [0x430, 0x435, 0x440, 0x441, 0x445, 0x455, 0x456, 0x471]) 39 40 for anchor in f[srcname].anchors: 41 if "top_dd" == anchor.name: 42 g.appendAnchor(anchor.name, (anchor.x + width, anchor.y)) 43 if "bottom_dd" == anchor.name: 44 g.appendAnchor(anchor.name, (anchor.x + width, anchor.y)) 45 if "top0315" == anchor.name: 46 g.appendAnchor(anchor.name, (anchor.x + width, anchor.y)) 47 48 if ("top" == anchor.name and 49 (g.unicode in unicode_range or 50 g.name.endswith((".ccmp", ".smcp", ".NAV"))) and 51 not any(a.name == "parent_top" for a in g.anchors)): 52 g.appendAnchor("parent_top", anchor.position) 53 54 if ("bottom" == anchor.name and 55 (g.unicode in unicode_range or g.name.endswith(".smcp")) and 56 not any(a.name == "bottom" for a in g.anchors)): 57 g.appendAnchor("bottom", anchor.position) 58 59 if any(a.name == "top" for a in g.anchors): 60 return 61 62 anchor_parent_top = next( 63 (a for a in g.anchors if a.name == "parent_top"), None) 64 if anchor_parent_top is not None: 65 g.appendAnchor("top", anchor_parent_top.position) 66 67 68def generateGlyph(f,gname,glyphList={}): 69 glyphName, baseName, accentNames, offset = parseComposite(gname) 70 71 if baseName.find("_") != -1: 72 g = f.newGlyph(glyphName) 73 for componentName in baseName.split("_"): 74 g.appendComponent(componentName, (g.width, 0)) 75 g.width += f[componentName].width 76 setUnicodeValue(g, glyphList) 77 78 else: 79 if not f.has_key(glyphName): 80 try: 81 f.compileGlyph(glyphName, baseName, accentNames) 82 except KeyError as e: 83 print ("KeyError raised for composition rule '%s', likely %s " 84 "anchor not found in glyph '%s'" % (gname, e, baseName)) 85 return 86 g = f[glyphName] 87 setUnicodeValue(g, glyphList) 88 copyMarkAnchors(f, g, baseName, offset[1] + offset[0]) 89 if len(accentNames) > 0: 90 alignComponentsToAnchors(f, glyphName, baseName, accentNames) 91 if offset[0] != 0 or offset[1] != 0: 92 g.width += offset[1] + offset[0] 93 g.move((offset[0], 0), anchors=False) 94 else: 95 print ("Existing glyph '%s' found in font, ignoring composition " 96 "rule '%s'" % (glyphName, gname)) 97 98 99def setUnicodeValue(glyph, glyphList): 100 """Try to ensure glyph has a unicode value -- used by FDK to make OTFs.""" 101 102 if glyph.name in glyphList: 103 glyph.unicode = int(glyphList[glyph.name], 16) 104 else: 105 uvNameMatch = re.match("uni([\dA-F]{4})$", glyph.name) 106 if uvNameMatch: 107 glyph.unicode = int(uvNameMatch.group(1), 16) 108