summaryrefslogtreecommitdiff
path: root/scripts/lib/fontbuild/mitreGlyph.py
diff options
context:
space:
mode:
authorChristian Robertson <robertsonc@google.com>2014-05-19 16:09:20 -0700
committerChristian Robertson <robertsonc@google.com>2014-05-19 16:09:20 -0700
commit7051939fa74b5f8f453be605f5dc3b4c23e1d1d9 (patch)
tree65cb31b34a64b2b07f9f6fd1bcb58d9a4945a92d /scripts/lib/fontbuild/mitreGlyph.py
Importing Roboto 2.0
Diffstat (limited to 'scripts/lib/fontbuild/mitreGlyph.py')
-rwxr-xr-xscripts/lib/fontbuild/mitreGlyph.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/scripts/lib/fontbuild/mitreGlyph.py b/scripts/lib/fontbuild/mitreGlyph.py
new file mode 100755
index 0000000..ab68e4e
--- /dev/null
+++ b/scripts/lib/fontbuild/mitreGlyph.py
@@ -0,0 +1,121 @@
+"""Mitre Glyph:
+
+mitreSize : Length of the segment created by the mitre. The default is 4.
+maxAngle : Maximum angle in radians at which nodes will be mitred. The default is .9 (about 50 degrees).
+ Works for both inside and outside angles
+
+"""
+
+from FL import *
+import math
+
+def getContours(g):
+ nLength = len(g.nodes)
+ contours = []
+ cid = -1
+ for i in range(nLength):
+ n = g.nodes[i]
+ if n.type == nMOVE:
+ cid += 1
+ contours.append([])
+ contours[cid].append(n)
+ return contours
+
+def getTangents(contours):
+ tmap = []
+ for c in contours:
+ clen = len(c)
+ for i in range(clen):
+ n = c[i]
+ p = Point(n.x, n.y)
+ nn = c[(i + 1) % clen]
+ pn = c[(clen + i - 1) % clen]
+ if nn.type == nCURVE:
+ np = Point(nn[1].x,nn[1].y)
+ else:
+ np = Point(nn.x,nn.y)
+ if n.type == nCURVE:
+ pp = Point(n[2].x,n[2].y)
+ else:
+ pp = Point(pn.x,pn.y)
+ nVect = Point(-p.x + np.x, -p.y + np.y)
+ pVect = Point(-p.x + pp.x, -p.y + pp.y)
+ tmap.append((pVect,nVect))
+ return tmap
+
+def normalizeVector(p):
+ m = getMagnitude(p);
+ if m != 0:
+ return p*(1/m)
+ else:
+ return Point(0,0)
+
+def getMagnitude(p):
+ return math.sqrt(p.x*p.x + p.y*p.y)
+
+def getDistance(v1,v2):
+ return getMagnitude(Point(v1.x - v2.x, v1.y - v2.y))
+
+def getAngle(v1,v2):
+ angle = math.atan2(v1.y,v1.x) - math.atan2(v2.y,v2.x)
+ return (angle + (2*math.pi)) % (2*math.pi)
+
+def angleDiff(a,b):
+ return math.pi - abs((abs(a - b) % (math.pi*2)) - math.pi)
+
+def getAngle2(v1,v2):
+ return abs(angleDiff(math.atan2(v1.y, v1.x), math.atan2(v2.y, v2.x)))
+
+def getMitreOffset(n,v1,v2,mitreSize=4,maxAngle=.9):
+
+ # dont mitre if segment is too short
+ if abs(getMagnitude(v1)) < mitreSize * 2 or abs(getMagnitude(v2)) < mitreSize * 2:
+ return
+ angle = getAngle2(v2,v1)
+ v1 = normalizeVector(v1)
+ v2 = normalizeVector(v2)
+ if v1.x == v2.x and v1.y == v2.y:
+ return
+
+
+ # only mitre corners sharper than maxAngle
+ if angle > maxAngle:
+ return
+
+ radius = mitreSize / abs(getDistance(v1,v2))
+ offset1 = Point(round(v1.x * radius), round(v1.y * radius))
+ offset2 = Point(round(v2.x * radius), round(v2.y * radius))
+ return offset1, offset2
+
+def mitreGlyph(g,mitreSize,maxAngle):
+ if g == None:
+ return
+
+ contours = getContours(g)
+ tangents = getTangents(contours)
+ nodes = []
+ needsMitring = False
+ nid = -1
+ for c in contours:
+ for n in c:
+ nid += 1
+ v1, v2 = tangents[nid]
+ off = getMitreOffset(n,v1,v2,mitreSize,maxAngle)
+ n1 = Node(n)
+ if off != None:
+ offset1, offset2 = off
+ n2 = Node(nLINE, Point(n.x + offset2.x, n.y + offset2.y))
+ n1[0].x += offset1.x
+ n1[0].y += offset1.y
+ nodes.append(n1)
+ nodes.append(n2)
+ needsMitring = True
+ else:
+ nodes.append(n1)
+ if needsMitring:
+ g.Clear()
+ g.Insert(nodes)
+
+fl.SetUndo()
+mitreGlyph(fl.glyph,8.,.9)
+fl.UpdateGlyph() \ No newline at end of file