def test_subdividePathWithPaths_colinear(self): divided, intersections = TFSTesselation().subdividePathWithPaths([ openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(2, 2), TFSPoint(6, 2)), ]) self.assertEqual(len(divided), 2) self.assertEqual(len(intersections), 0)
def test_rightAngleRight(self): self.assertPointClose(TFSPoint(0, 0).rightAngleRight(), TFSPoint(0, 0)) self.assertPointClose( TFSPoint(1, 0).rightAngleRight(), TFSPoint(0, -1)) self.assertPointClose( TFSPoint(3, 0).rightAngleRight(), TFSPoint(0, -3)) self.assertPointClose( TFSPoint(-3, 0).rightAngleRight(), TFSPoint(0, 3)) self.assertPointClose(TFSPoint(0, 5).rightAngleRight(), TFSPoint(5, 0))
def test_midpoint(self): self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(0, 0)), TFSPoint(0, 0)) self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(3, 4)), TFSPoint(1.5, 2)) self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(-3, -4)), TFSPoint(-1.5, -2))
def test_hash(self): testset = set() self.assertEqual(len(testset), 0) testset.add(TFSPoint(0, 0)) self.assertEqual(len(testset), 1) testset.add(TFSPoint(0, 0)) self.assertEqual(len(testset), 1) testset.add(TFSPoint(0, 1)) self.assertEqual(len(testset), 2) testset.add(TFSPoint(0, 1.0)) self.assertEqual(len(testset), 2)
def test_flatePathLeft_deflateSquare(self): ''' XXXX (counter-clockwise) X X X X XXXX ''' paths = TFSSilhouette._flatePathLeft( polygonWithPoints(TFSPoint(0, 0), TFSPoint(0, 3), TFSPoint(3, 3), TFSPoint(3, 0)).reverse(), 1) self.assertIsNotNone(paths) self.assertEqual(len(paths), 1) path = paths[0] self.assertEqual(len(path), 4)
def test_rotate(self): self.assertPointClose( TFSPoint(3, 0).rotate(math.pi * 0.0), TFSPoint(3, 0)) self.assertPointClose( TFSPoint(3, 0).rotate(math.pi * 0.5), TFSPoint(0, 3)) self.assertPointClose( TFSPoint(3, 0).rotate(math.pi * 1.0), TFSPoint(-3, 0)) self.assertPointClose( TFSPoint(3, 0).rotate(math.pi * 1.5), TFSPoint(0, -3))
def alignToptoAscenderFunction(paths): font = CurrentFont() mm = minmaxPaths(paths) paths = [ path.applyPlus(TFSPoint(0, font.info.ascender - mm.maxY)) for path in paths ] return paths
def centerBelowAscenderFunction(paths): font = CurrentFont() mm = minmaxPaths(paths) paths = [ path.applyPlus( TFSPoint(0, (font.info.ascender - (mm.maxY - mm.minY)) * 0.5)) for path in paths ] return paths
def test_subdividePathWithPaths_selfIntersect0(self): ''' XXXXX X X XXXXX ''' divided, intersections = TFSTesselation().subdividePathWithPaths([ openPathWithPoints( TFSPoint(0, 2), TFSPoint(4, 2), TFSPoint(4, 4), TFSPoint(0, 4), TFSPoint(0, 2), ), ]) # debugPaths('divided', divided) self.assertEqual(len(divided), 1) self.assertEqual(len(intersections), 0)
def renderSvgScene(self, filenamePrefix, pathTuples, hGuidelines=None): from tfs.common.TFSSvg import TFSSvg, TFSSvgPath filename = '%s.svg' % ( filenamePrefix, ) dstFile = os.path.abspath(os.path.join(self.svg_folder, filename)) CANVAS_BACKGROUND_COLOR = 0xffffffff CANVAS_BORDER_COLOR = 0x07fbfbfbf fiSvg = TFSSvg().withBackground(CANVAS_BACKGROUND_COLOR).withBorder(CANVAS_BORDER_COLOR) # if pathTuples: for color, contours in pathTuples: self.subrenderGlyphContours(fiSvg, contours, color) if hGuidelines: for hGuideline in hGuidelines: p0 = TFSPoint(hGuideline, self.fifont.info.descender) p1 = TFSPoint(hGuideline, self.fifont.info.ascender) GUIDELINE_COLOR = 0x7fdfdfdf fiSvg.addItem(TFSSvgPath(openPathWithPoints(p0, p1)).addStroke(GUIDELINE_COLOR, 1)) vGuidelines = ( 0, self.fifont.info.ascender, self.fifont.info.descender, ) if vGuidelines: minmax = None for color, contours in pathTuples: minmax = minmaxMerge(minmax, minmaxPaths(contours)) for vGuideline in vGuidelines: p0 = TFSPoint(0, vGuideline) p1 = TFSPoint(minmax.maxX, vGuideline) GUIDELINE_COLOR = 0x7fdfdfdf fiSvg.addItem(TFSSvgPath(openPathWithPoints(p0, p1)).addStroke(GUIDELINE_COLOR, 1)) SVG_HEIGHT = 400 SVG_MAX_WIDTH = 800 fiSvg.renderToFile(dstFile, margin=10, height=SVG_HEIGHT, maxWidth=SVG_MAX_WIDTH) return filename
def test_inflatePaths_inflateDeflateSquare(self): ''' XXXX (clockwise) X X X X XXXX ''' paths = TFSSilhouette.inflatePaths((polygonWithPoints( TFSPoint(0, 0), TFSPoint(0, 3), TFSPoint(3, 3), TFSPoint(3, 0)), ), 1) self.assertIsNotNone(paths) self.assertEqual(len(paths), 1) path = paths[0] self.assertEqual(len(path), 8) # debugPath('inflateDeflateSquare.1', path) paths = TFSSilhouette.deflatePaths(paths, 1) self.assertIsNotNone(paths) self.assertEqual(len(paths), 1) path = paths[0] # debugPath('inflateDeflateSquare.2', path) self.assertEqual(len(path), 4)
def test_cullEmptyAngles(self): paths = TFSTesselation().cullEmptyAngles([ polygonWithPoints(TFSPoint(0, 0), TFSPoint(0, 2), TFSPoint(2, 2), TFSPoint(2, 4), TFSPoint(2, 2), TFSPoint(4, 2)), ]) self.assertEqual(len(paths), 1) path = paths[0] self.assertEqual(len(path), 4)
class TFSPointTest(TFSTest): def setUp(self): pass def test_invert(self): self.assertPointEquals(TFSPoint(1, 0).invert(), TFSPoint(-1, 0)) self.assertPointEquals(TFSPoint(3, 2).invert(), TFSPoint(-3, -2)) def test_length(self): self.assertClose(TFSPoint(3, 4).length(), 5) self.assertClose(TFSPoint(0, 0).length(), 0) def test_distanceTo(self): self.assertClose(TFSPoint(0, 0).distanceTo(TFSPoint(0, 0)), 0) self.assertClose(TFSPoint(0, 0).distanceTo(TFSPoint(3, 4)), 5) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(0, 0)), 5) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(3, 4)), 0) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(6, 8)), 5) def test_midpoint(self): self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(0, 0)), TFSPoint(0, 0)) self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(3, 4)), TFSPoint(1.5, 2)) self.assertPointClose( TFSPoint(0, 0).midpoint(TFSPoint(-3, -4)), TFSPoint(-1.5, -2)) def test_normalize(self): try: self.assertPointClose(TFSPoint(0, 0).normalize(), TFSPoint(0, 0)) self.fail('Missing ZeroDivisionError') except ZeroDivisionError, e: pass self.assertPointClose(TFSPoint(2, 0).normalize(), TFSPoint(1, 0)) self.assertPointClose( TFSPoint(-3, -4).normalize(), TFSPoint(-3 / 5.0, -4 / 5.0))
def getTableSvg(self, glyphs, maxValue): glyphs.sort(lambda glyph0, glyph1:cmp(glyph0.codePoint, glyph1.codePoint)) glyphs = glyphs[:1000] from tfs.common.TFSSvg import TFSSvg, TFSSvgPath, blendArgbColors CANVAS_BACKGROUND_COLOR = 0xffffffff CANVAS_BORDER_COLOR = 0x07fbfbfbf fiSvg = TFSSvg().withBackground(CANVAS_BACKGROUND_COLOR).withBorder(CANVAS_BORDER_COLOR) glyphCount = len(glyphs) margin = 10 hSpacing = vSpacing = 10 cellWidth = cellHeight = 10 glyphsPerRow = 13 width = 2 * margin + (glyphsPerRow * cellWidth) + ((glyphsPerRow - 1) * hSpacing) rowCount = int(math.ceil(glyphCount / glyphsPerRow)) height = 2 * margin + (rowCount * cellHeight) + ((rowCount - 1) * vSpacing) for index, glyph in enumerate(glyphs): x = index % glyphsPerRow y = int(math.floor(index / glyphsPerRow)) corner = TFSPoint(margin + x * (cellWidth + hSpacing), margin + y * (cellHeight + vSpacing)) path = polygonWithPoints(corner, corner.right(cellWidth), corner.right(cellWidth).up(cellHeight), corner.up(cellHeight)) path = path.applyScaleXY(1.0, -1.0) minGlyphColor = 0xffafafff maxGlyphColor = 0xff0f0f5f phase = glyph.count / float(maxValue) glyphColor = blendArgbColors(minGlyphColor, maxGlyphColor, phase) fiSvg.addItem(TFSSvgPath(path).addFill(glyphColor)) return fiSvg.renderRaw(None, width, height)
def test_inflatePaths_inflateOverlappingSquares(self): ''' (clockwise) XXXX X X XXXX X X X X XXXX X X XXXX ''' paths = TFSSilhouette.inflatePaths(( polygonWithPoints(TFSPoint(0, 0), TFSPoint(0, 3), TFSPoint(3, 3), TFSPoint(3, 0)), polygonWithPoints(TFSPoint(4, 2), TFSPoint(4, 5), TFSPoint(7, 5), TFSPoint(7, 2)), ), 1) self.assertIsNotNone(paths) self.assertEqual(len(paths), 1) path = paths[0] self.assertEqual(len(path), 14)
def alignBottomToBaselineFunction(paths): font = CurrentFont() mm = minmaxPaths(paths) paths = [path.applyPlus(TFSPoint(0, -mm.minY)) for path in paths] return paths
def test_invert(self): self.assertPointEquals(TFSPoint(1, 0).invert(), TFSPoint(-1, 0)) self.assertPointEquals(TFSPoint(3, 2).invert(), TFSPoint(-3, -2))
def test_subdividePathWithPaths(self): divided, intersections = TFSTesselation().subdividePathWithPaths([openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(6, 0), TFSPoint(6, 4)), ]) self.assertEqual(len(divided), 2) self.assertEqual(len(intersections), 0) divided, intersections = TFSTesselation().subdividePathWithPaths([openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(2, 0), TFSPoint(2, 4)), ]) # debugPaths('divided', divided) self.assertEqual(len(divided), 4) self.assertEqual(len(intersections), 1) divided, intersections = TFSTesselation().subdividePathWithPaths([openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(2, 0), TFSPoint(2, 4)), openPathWithPoints(TFSPoint(3, 0), TFSPoint(3, 4)), ]) # debugPaths('divided', divided) self.assertEqual(len(divided), 7) self.assertEqual(len(intersections), 2) divided, intersections = TFSTesselation().subdividePathWithPaths([openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(0, 1), TFSPoint(4, 1)), openPathWithPoints(TFSPoint(2, 0), TFSPoint(2, 4)), openPathWithPoints(TFSPoint(3, 0), TFSPoint(3, 4)), ]) # debugPaths('divided', divided) self.assertEqual(len(divided), 12) self.assertEqual(len(intersections), 4) ''' Endpoint intersection ''' divided, intersections = TFSTesselation().subdividePathWithPaths([openPathWithPoints(TFSPoint(0, 2), TFSPoint(4, 2)), openPathWithPoints(TFSPoint(4, 2), TFSPoint(4, 4)), ]) self.assertEqual(len(divided), 2) self.assertEqual(len(intersections), 0)
def appendDiacriticalContours(self, alignment, baseContours, diacriticalContours, baseCodePoint, diacriticalCodePoint): baseMinmax = minmaxPaths(baseContours) diacriticalMinmax = minmaxPaths(diacriticalContours) def minmaxHCenter(minmax): return (minmax.minX) + ((minmax.maxX - minmax.minX) * 0.5) def minmaxVCenter(minmax): return (minmax.minY) + ((minmax.maxY - minmax.minY) * 0.5) def minmaxTop(minmax): return minmax.maxY def minmaxBottom(minmax): return minmax.minY def getOffsetX(codePoint, joinCentersMap, defaultValue): if codePoint in joinCentersMap: offset = joinCentersMap[codePoint] return offset.x else: return defaultValue def getOffsetY(codePoint, joinCentersMap, defaultValue): if codePoint in joinCentersMap: offset = joinCentersMap[codePoint] if offset.y is None: return defaultValue return offset.y else: return defaultValue if alignment == TFSCompoundsList.DIACRITICAL_ALIGN_TOP_ROTATE_FLOAT: diacriticalContours = [contour.applyScale(-1.0) for contour in diacriticalContours] diacriticalMinmax = minmaxPaths(diacriticalContours) alignment = TFSCompoundsList.DIACRITICAL_ALIGN_TOP elif alignment == TFSCompoundsList.DIACRITICAL_ALIGN_TAIL_H_FLIP: diacriticalContours = [contour.applyScaleXY(-1.0, 1.0) for contour in diacriticalContours] diacriticalMinmax = minmaxPaths(diacriticalContours) alignment = TFSCompoundsList.DIACRITICAL_ALIGN_TAIL if alignment == TFSCompoundsList.DIACRITICAL_ALIGN_TOP: offsetX = (getOffsetX(baseCodePoint, self.topJoinCentersMap, minmaxHCenter(baseMinmax)) - getOffsetX(diacriticalCodePoint, self.topJoinCentersMap, minmaxHCenter(diacriticalMinmax))) offsetY = (self.default_diacritical_distance + getOffsetY(baseCodePoint, self.topJoinCentersMap, minmaxTop(baseMinmax)) - getOffsetY(diacriticalCodePoint, self.topJoinCentersMap, minmaxBottom(diacriticalMinmax))) elif alignment == TFSCompoundsList.DIACRITICAL_ALIGN_TAIL: offsetX = (getOffsetX(baseCodePoint, self.tailJoinCentersMap, minmaxHCenter(baseMinmax)) - getOffsetX(diacriticalCodePoint, self.tailJoinCentersMap, minmaxHCenter(diacriticalMinmax))) offsetY = (getOffsetY(baseCodePoint, self.tailJoinCentersMap, minmaxBottom(baseMinmax)) - getOffsetY(diacriticalCodePoint, self.tailJoinCentersMap, minmaxTop(diacriticalMinmax))) elif alignment == TFSCompoundsList.DIACRITICAL_ALIGN_TAIL_FLOAT: offsetX = (getOffsetX(baseCodePoint, self.tailJoinCentersMap, minmaxHCenter(baseMinmax)) - getOffsetX(diacriticalCodePoint, self.tailJoinCentersMap, minmaxHCenter(diacriticalMinmax))) offsetY = (getOffsetY(baseCodePoint, self.tailJoinCentersMap, minmaxBottom(baseMinmax)) - getOffsetY(diacriticalCodePoint, self.tailJoinCentersMap, minmaxTop(diacriticalMinmax))) - self.default_diacritical_distance elif alignment == TFSCompoundsList.DIACRITICAL_ALIGN_MIDDLE: offsetX = (getOffsetX(baseCodePoint, self.middleJoinCentersMap, minmaxHCenter(baseMinmax)) - getOffsetX(diacriticalCodePoint, self.middleJoinCentersMap, minmaxHCenter(diacriticalMinmax))) offsetY = (getOffsetY(baseCodePoint, self.middleJoinCentersMap, minmaxVCenter(baseMinmax)) - getOffsetY(diacriticalCodePoint, self.middleJoinCentersMap, minmaxVCenter(diacriticalMinmax))) else: raise Exception('Unknown diacritical aligment: ' + alignment) offsetX = round(offsetX) offsetY = round(offsetY) diacriticalContours = [contour.applyPlus(TFSPoint(offsetX, offsetY)) for contour in diacriticalContours] return baseContours + diacriticalContours
def test_normalize(self): try: self.assertPointClose(TFSPoint(0, 0).normalize(), TFSPoint(0, 0)) self.fail('Missing ZeroDivisionError') except ZeroDivisionError, e: pass
def test_dotProduct(self): self.assertEquals(TFSPoint(3, 4).dotProduct(TFSPoint(5, 7)), 43) self.assertEquals(TFSPoint(3, 4).dotProduct(TFSPoint(0, 0)), 0)
def test_distanceTo(self): self.assertClose(TFSPoint(0, 0).distanceTo(TFSPoint(0, 0)), 0) self.assertClose(TFSPoint(0, 0).distanceTo(TFSPoint(3, 4)), 5) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(0, 0)), 5) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(3, 4)), 0) self.assertClose(TFSPoint(3, 4).distanceTo(TFSPoint(6, 8)), 5)
def test_length(self): self.assertClose(TFSPoint(3, 4).length(), 5) self.assertClose(TFSPoint(0, 0).length(), 0)
def convertPoint(x, y): return TFSPoint(float(x), float(y))
def test_flateSegmentLeft(self): ''' A curve with center c. X c X X x XXX ''' segment = TFSSilhouette._flateSegmentLeft( TFSSegment(TFSPoint(0, 3), TFSPoint(0, 2), TFSPoint(2, 0), TFSPoint(3, 0)), 0.5) self.assertIsNotNone(segment) self.assertEqual(len(segment), 4) segment = TFSSilhouette._flateSegmentLeft( TFSSegment(TFSPoint(0, 3), TFSPoint(0, 2), TFSPoint(2, 0), TFSPoint(3, 0)), 2.5) self.assertIsNotNone(segment) self.assertEqual(len(segment), 4) segment = TFSSilhouette._flateSegmentLeft( TFSSegment(TFSPoint(0, 3), TFSPoint(0, 2), TFSPoint(2, 0), TFSPoint(3, 0)), 3) self.assertIsNone(segment) segment = TFSSilhouette._flateSegmentLeft( TFSSegment(TFSPoint(0, 3), TFSPoint(0, 2), TFSPoint(2, 0), TFSPoint(3, 0)), 3.5) self.assertIsNone(segment)
def alignLeftFunction(paths): mm = minmaxPaths(paths) paths = [path.applyPlus(TFSPoint(-mm.minX, 0)) for path in paths] return paths