Initial public commit
This commit is contained in:
commit
3b1fffade1
6648 changed files with 363948 additions and 0 deletions
102
misc/pylib/fontbuild/convertCurves.py
Normal file
102
misc/pylib/fontbuild/convertCurves.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#! /usr/bin/env python
|
||||
#
|
||||
# Copyright 2015 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""
|
||||
Converts a cubic bezier curve to a quadratic spline with
|
||||
exactly two off curve points.
|
||||
|
||||
"""
|
||||
|
||||
import numpy
|
||||
from numpy import array,cross,dot
|
||||
from fontTools.misc import bezierTools
|
||||
from robofab.objects.objectsRF import RSegment
|
||||
|
||||
def replaceSegments(contour, segments):
|
||||
while len(contour):
|
||||
contour.removeSegment(0)
|
||||
for s in segments:
|
||||
contour.appendSegment(s.type, [(p.x, p.y) for p in s.points], s.smooth)
|
||||
|
||||
def calcIntersect(a,b,c,d):
|
||||
numpy.seterr(all='raise')
|
||||
e = b-a
|
||||
f = d-c
|
||||
p = array([-e[1], e[0]])
|
||||
try:
|
||||
h = dot((a-c),p) / dot(f,p)
|
||||
except:
|
||||
print a,b,c,d
|
||||
raise
|
||||
return c + dot(f,h)
|
||||
|
||||
def simpleConvertToQuadratic(p0,p1,p2,p3):
|
||||
p = [array(i.x,i.y) for i in [p0,p1,p2,p3]]
|
||||
off = calcIntersect(p[0],p[1],p[2],p[3])
|
||||
|
||||
# OFFCURVE_VECTOR_CORRECTION = -.015
|
||||
OFFCURVE_VECTOR_CORRECTION = 0
|
||||
|
||||
def convertToQuadratic(p0,p1,p2,p3):
|
||||
# TODO: test for accuracy and subdivide further if needed
|
||||
p = [(i.x,i.y) for i in [p0,p1,p2,p3]]
|
||||
# if p[0][0] == p[1][0] and p[0][0] == p[2][0] and p[0][0] == p[2][0] and p[0][0] == p[3][0]:
|
||||
# return (p[0],p[1],p[2],p[3])
|
||||
# if p[0][1] == p[1][1] and p[0][1] == p[2][1] and p[0][1] == p[2][1] and p[0][1] == p[3][1]:
|
||||
# return (p[0],p[1],p[2],p[3])
|
||||
seg1,seg2 = bezierTools.splitCubicAtT(p[0], p[1], p[2], p[3], .5)
|
||||
pts1 = [array([i[0], i[1]]) for i in seg1]
|
||||
pts2 = [array([i[0], i[1]]) for i in seg2]
|
||||
on1 = seg1[0]
|
||||
on2 = seg2[3]
|
||||
try:
|
||||
off1 = calcIntersect(pts1[0], pts1[1], pts1[2], pts1[3])
|
||||
off2 = calcIntersect(pts2[0], pts2[1], pts2[2], pts2[3])
|
||||
except:
|
||||
return (p[0],p[1],p[2],p[3])
|
||||
off1 = (on1 - off1) * OFFCURVE_VECTOR_CORRECTION + off1
|
||||
off2 = (on2 - off2) * OFFCURVE_VECTOR_CORRECTION + off2
|
||||
return (on1,off1,off2,on2)
|
||||
|
||||
def cubicSegmentToQuadratic(c,sid):
|
||||
|
||||
segment = c[sid]
|
||||
if (segment.type != "curve"):
|
||||
print "Segment type not curve"
|
||||
return
|
||||
|
||||
#pSegment,junk = getPrevAnchor(c,sid)
|
||||
pSegment = c[sid-1] #assumes that a curve type will always be proceeded by another point on the same contour
|
||||
points = convertToQuadratic(pSegment.points[-1],segment.points[0],
|
||||
segment.points[1],segment.points[2])
|
||||
return RSegment(
|
||||
'qcurve', [[int(i) for i in p] for p in points[1:]], segment.smooth)
|
||||
|
||||
def glyphCurvesToQuadratic(g):
|
||||
|
||||
for c in g:
|
||||
segments = []
|
||||
for i in range(len(c)):
|
||||
s = c[i]
|
||||
if s.type == "curve":
|
||||
try:
|
||||
segments.append(cubicSegmentToQuadratic(c, i))
|
||||
except Exception:
|
||||
print g.name, i
|
||||
raise
|
||||
else:
|
||||
segments.append(s)
|
||||
replaceSegments(c, segments)
|
||||
Reference in a new issue