def test_even_odd_fill(self): pen = FreeTypePen(None) star(pen) t = Scale(0.05, 0.05) width, height = t.transformPoint((1000, 1000)) t = t.translate(0, 200) buf1, size1 = pen.buffer(width=width, height=height, transform=t, evenOdd=True) buf2, size2 = load_pgm(os.path.join(DATA_DIR, "test_even_odd_fill.pgm")) self.assertEqual(len(buf1), len(buf2)) self.assertEqual(size1, size2) self.assertGreater(psnr(buf1, buf2), PSNR_THRESHOLD)
def main(argv): if len(argv) != 2: sys.stderr.write( "Please enter paths to two font files for center of mass comparisons" + os.linesep) sys.exit(1) test_glyphs = ('uni002B', 'uni002E') font1 = TTFont(argv[0]) font2 = TTFont(argv[1]) test_fonts = (font1, font2) for glyph_name in test_glyphs: print("\nGLYPH: " + glyph_name) x = 0 for font in test_fonts: x += 1 print("Font " + str(x)) this_glyphset = font.getGlyphSet() glyph_obj = this_glyphset[glyph_name] stats_pen = StatisticsPen(glyphset=this_glyphset) upem = font['head'].unitsPerEm transformer = TransformPen(stats_pen, Scale(1. / upem)) glyph_obj.draw(transformer) for item in ['area', 'meanX', 'meanY']: print("%s: %g" % (item, getattr(stats_pen, item))) print(" ") print(" ")
def test_skew(self): pen = FreeTypePen(None) box(pen) t = Scale(0.05, 0.05).skew(math.pi / 4.0).translate(1234, 5678) width, height = None, None buf1, size1 = pen.buffer(width=width, height=height, transform=t) buf2, size2 = load_pgm(os.path.join(DATA_DIR, "test_skew.pgm")) self.assertEqual(len(buf1), len(buf2)) self.assertEqual(size1, size2) self.assertGreater(psnr(buf1, buf2), PSNR_THRESHOLD)
def test(glyphset, upem, glyphs): print('upem', upem) for glyph_name in glyphs: print() print("glyph:", glyph_name) glyph = glyphset[glyph_name] stats = GlyphStatistics(glyph, transform=Scale(1. / upem), glyphset=glyphset) for item in dir(stats): if item[0] == '_': continue print("%s: %g" % (item, getattr(stats, item)))
def test_contain(self): pen = FreeTypePen(None) star(pen) t = Scale(0.05, 0.05) width, height = 0, 0 buf1, size1 = pen.buffer(width=width, height=height, transform=t, contain=True) buf2, size2 = load_pgm(os.path.join(DATA_DIR, "test_non_zero_fill.pgm")) self.assertEqual(len(buf1), len(buf2)) self.assertEqual(size1, size2) self.assertGreater(psnr(buf1, buf2), PSNR_THRESHOLD)
def _test(glyphset, upem, glyphs): from fontTools.pens.transformPen import TransformPen from fontTools.misc.transform import Scale print('upem', upem) for glyph_name in glyphs: print() print("glyph:", glyph_name) glyph = glyphset[glyph_name] pen = StatisticsPen(glyphset=glyphset) transformer = TransformPen(pen, Scale(1. / upem)) glyph.draw(transformer) for item in [ 'area', 'momentX', 'momentY', 'momentXX', 'momentYY', 'momentXY', 'meanX', 'meanY', 'varianceX', 'varianceY', 'stddevX', 'stddevY', 'covariance', 'correlation', 'slant' ]: print("%s: %g" % (item, getattr(pen, item)))
def changeUPM(self, targetUPM): # Calculate scaling factor between old and new UPM upmOld = self.font["head"].unitsPerEm upmNew = int(targetUPM) isCubic = self.font.has_key("CFF ") if upmOld == upmNew: return elif upmNew < 16 or upmNew > 16384: print("WARNING: Invalid UPM value. --UPM is now ignored.", file=sys.stderr) return elif isCubic: print( "WARNING: CFF-based font detected. Unfortunately it is currently not supported.", file=sys.stderr) return elif upmNew > 5000: print( "WARNING: UPM > 5000 will cause problems in Adobe InDesign and Illustrator.", file=sys.stderr) else: pass scaleFactor = upmNew / upmOld # Get float because __future__.division has been imported # Conversion: re-scale all glyphs scaledGlyphs = {} glyphOrder = self.font.getGlyphOrder() glyphSet = self.font.getGlyphSet() for glyphName in glyphSet.keys(): glyph = glyphSet[glyphName] if isCubic: # TODO: `CFF ` # basePen = OTGlyphPen(glyphSet) pass else: # `glyf` basePen = TTGlyphPen(glyphSet) scalePen = TransformPen(basePen, Scale(scaleFactor, scaleFactor)) # Deal with quad composites (all cubics are not affected) if not isCubic and glyph._glyph.isComposite( ): # Scale each component's xy offset glyph.draw(basePen) for i in range(len(basePen.components)): componentName, oldTrans = basePen.components[i] newTrans = (oldTrans[0], oldTrans[1], oldTrans[2], oldTrans[3], oldTrans[4] * scaleFactor, oldTrans[5] * scaleFactor) basePen.components[i] = (componentName, newTrans) else: # Scale all cubics or base quads so that their composites will not be scaled multiple times glyph.draw(scalePen) # Glyph-specific hinting will be removed upon TTGlyphPen.glyph() call. scaledGlyphs[glyphName] = basePen.glyph() # Apply `glyf` table with scaled glyphs glyf = newTable("glyf") glyf.glyphOrder = glyphOrder glyf.glyphs = scaledGlyphs self.font["glyf"] = glyf # Update tables to apply the new UPM self.__applyNewUPM(upmOld, upmNew) # Recalculate `head`, `glyf`, `maxp` upon compile self.font.recalcBBoxes = True return
def test_Scale(self): assert Scale(1) == Transform(1, 0, 0, 1, 0, 0) assert Scale(2) == Transform(2, 0, 0, 2, 0, 0) assert Scale(1, 2) == Transform(1, 0, 0, 2, 0, 0)
def _parametrize(self): # convert from endopoint to center parametrization: # https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter # If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a # "lineto") joining the endpoints. # http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters rx = fabs(self.rx) ry = fabs(self.ry) if not (rx and ry): return False # If the current point and target point for the arc are identical, it should # be treated as a zero length path. This ensures continuity in animations. if self.target_point == self.current_point: return False mid_point_distance = (self.current_point - self.target_point) * 0.5 point_transform = Identity.rotate(-self.angle) transformed_mid_point = _map_point(point_transform, mid_point_distance) square_rx = rx * rx square_ry = ry * ry square_x = transformed_mid_point.real * transformed_mid_point.real square_y = transformed_mid_point.imag * transformed_mid_point.imag # Check if the radii are big enough to draw the arc, scale radii if not. # http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii radii_scale = square_x / square_rx + square_y / square_ry if radii_scale > 1: rx *= sqrt(radii_scale) ry *= sqrt(radii_scale) self.rx, self.ry = rx, ry point_transform = Scale(1 / rx, 1 / ry).rotate(-self.angle) point1 = _map_point(point_transform, self.current_point) point2 = _map_point(point_transform, self.target_point) delta = point2 - point1 d = delta.real * delta.real + delta.imag * delta.imag scale_factor_squared = max(1 / d - 0.25, 0.0) scale_factor = sqrt(scale_factor_squared) if self.sweep == self.large: scale_factor = -scale_factor delta *= scale_factor center_point = (point1 + point2) * 0.5 center_point += complex(-delta.imag, delta.real) point1 -= center_point point2 -= center_point theta1 = atan2(point1.imag, point1.real) theta2 = atan2(point2.imag, point2.real) theta_arc = theta2 - theta1 if theta_arc < 0 and self.sweep: theta_arc += TWO_PI elif theta_arc > 0 and not self.sweep: theta_arc -= TWO_PI self.theta1 = theta1 self.theta2 = theta1 + theta_arc self.theta_arc = theta_arc self.center_point = center_point return True