1from __future__ import ( 2 print_function, division, absolute_import, unicode_literals) 3 4from ufo2ft.filters import BaseFilter 5from cu2qu.ufo import DEFAULT_MAX_ERR, CURVE_TYPE_LIB_KEY 6from cu2qu.pens import Cu2QuPointPen 7 8import logging 9 10 11logger = logging.getLogger(__name__) 12 13 14class CubicToQuadraticFilter(BaseFilter): 15 16 _kwargs = { 17 'conversionError': None, 18 'reverseDirection': True, 19 'rememberCurveType': False, 20 } 21 22 def set_context(self, font, glyphSet): 23 ctx = super(CubicToQuadraticFilter, self).set_context(font, glyphSet) 24 25 relativeError = self.options.conversionError or DEFAULT_MAX_ERR 26 ctx.absoluteError = relativeError * font.info.unitsPerEm 27 28 ctx.stats = {} 29 30 return ctx 31 32 def __call__(self, font, glyphSet=None): 33 if self.options.rememberCurveType: 34 curve_type = font.lib.get(CURVE_TYPE_LIB_KEY, "cubic") 35 if curve_type == "quadratic": 36 logger.info("Curves already converted to quadratic") 37 return set() 38 elif curve_type == "cubic": 39 pass # keep converting 40 else: 41 raise NotImplementedError(curve_type) 42 43 modified = super(CubicToQuadraticFilter, self).__call__(font, glyphSet) 44 if modified: 45 stats = self.context.stats 46 logger.info('New spline lengths: %s' % (', '.join( 47 '%s: %d' % (l, stats[l]) for l in sorted(stats.keys())))) 48 49 if self.options.rememberCurveType: 50 curve_type = font.lib.get(CURVE_TYPE_LIB_KEY, "cubic") 51 if curve_type != "quadratic": 52 font.lib[CURVE_TYPE_LIB_KEY] = "quadratic" 53 54 return modified 55 56 def filter(self, glyph): 57 if not len(glyph): 58 return False 59 60 pen = Cu2QuPointPen( 61 glyph.getPointPen(), 62 self.context.absoluteError, 63 reverse_direction=self.options.reverseDirection, 64 stats=self.context.stats) 65 contours = list(glyph) 66 glyph.clearContours() 67 for contour in contours: 68 contour.drawPoints(pen) 69 return True 70