From f771c371490313c407b88118cc54899a994100e1 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:52:02 +0100 Subject: [PATCH 01/10] Docs: fix code-example blocks in pens. --- Lib/fontTools/pens/freetypePen.py | 31 ++-- Lib/fontTools/pens/pointInsidePen.py | 3 +- Lib/fontTools/pens/recordingPen.py | 250 ++++++++++++++------------- Lib/fontTools/pens/svgPathPen.py | 21 ++- Lib/fontTools/pens/transformPen.py | 37 ++-- 5 files changed, 177 insertions(+), 165 deletions(-) diff --git a/Lib/fontTools/pens/freetypePen.py b/Lib/fontTools/pens/freetypePen.py index 870776bc7..a366b6d05 100644 --- a/Lib/fontTools/pens/freetypePen.py +++ b/Lib/fontTools/pens/freetypePen.py @@ -191,12 +191,11 @@ class FreeTypePen(BasePen): :Example: .. code-block:: - >> pen = FreeTypePen(None) - >> glyph.draw(pen) - >> buf, size = pen.buffer(width=500, height=1000) - >> type(buf), len(buf), size + >>> pen = FreeTypePen(None) + >>> glyph.draw(pen) + >>> buf, size = pen.buffer(width=500, height=1000) + >>> type(buf), len(buf), size (, 500000, (500, 1000)) - """ transform = transform or Transform() if not hasattr(transform, "transformPoint"): @@ -282,10 +281,10 @@ class FreeTypePen(BasePen): :Example: .. code-block:: - >> pen = FreeTypePen(None) - >> glyph.draw(pen) - >> arr = pen.array(width=500, height=1000) - >> type(a), a.shape + >>> pen = FreeTypePen(None) + >>> glyph.draw(pen) + >>> arr = pen.array(width=500, height=1000) + >>> type(a), a.shape (, (1000, 500)) """ import numpy as np @@ -331,9 +330,9 @@ class FreeTypePen(BasePen): :Example: .. code-block:: - >> pen = FreeTypePen(None) - >> glyph.draw(pen) - >> pen.show(width=500, height=1000) + >>> pen = FreeTypePen(None) + >>> glyph.draw(pen) + >>> pen.show(width=500, height=1000) """ from matplotlib import pyplot as plt @@ -383,10 +382,10 @@ class FreeTypePen(BasePen): :Example: .. code-block:: - >> pen = FreeTypePen(None) - >> glyph.draw(pen) - >> img = pen.image(width=500, height=1000) - >> type(img), img.size + >>> pen = FreeTypePen(None) + >>> glyph.draw(pen) + >>> img = pen.image(width=500, height=1000) + >>> type(img), img.size (, (500, 1000)) """ from PIL import Image diff --git a/Lib/fontTools/pens/pointInsidePen.py b/Lib/fontTools/pens/pointInsidePen.py index e1fbbbcb1..0c022d31b 100644 --- a/Lib/fontTools/pens/pointInsidePen.py +++ b/Lib/fontTools/pens/pointInsidePen.py @@ -15,7 +15,8 @@ class PointInsidePen(BasePen): Instances of this class can be recycled, as long as the setTestPoint() method is used to set the new point to test. - Typical usage: + :Example: + .. code-block:: pen = PointInsidePen(glyphSet, (100, 200)) outline.draw(pen) diff --git a/Lib/fontTools/pens/recordingPen.py b/Lib/fontTools/pens/recordingPen.py index ba165e195..585f44638 100644 --- a/Lib/fontTools/pens/recordingPen.py +++ b/Lib/fontTools/pens/recordingPen.py @@ -33,17 +33,18 @@ class RecordingPen(AbstractPen): pen.replay(otherPen). :Example: + .. code-block:: from fontTools.ttLib import TTFont from fontTools.pens.recordingPen import RecordingPen - + glyph_name = 'dollar' font_path = 'MyFont.otf' - + font = TTFont(font_path) glyphset = font.getGlyphSet() glyph = glyphset[glyph_name] - + pen = RecordingPen() glyph.draw(pen) print(pen.value) @@ -91,47 +92,48 @@ class DecomposingRecordingPen(DecomposingPen, RecordingPen): by thir name; other arguments are forwarded to the DecomposingPen's constructor:: - >>> class SimpleGlyph(object): - ... def draw(self, pen): - ... pen.moveTo((0, 0)) - ... pen.curveTo((1, 1), (2, 2), (3, 3)) - ... pen.closePath() - >>> class CompositeGlyph(object): - ... def draw(self, pen): - ... pen.addComponent('a', (1, 0, 0, 1, -1, 1)) - >>> class MissingComponent(object): - ... def draw(self, pen): - ... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0)) - >>> class FlippedComponent(object): - ... def draw(self, pen): - ... pen.addComponent('a', (-1, 0, 0, 1, 0, 0)) - >>> glyphSet = { - ... 'a': SimpleGlyph(), - ... 'b': CompositeGlyph(), - ... 'c': MissingComponent(), - ... 'd': FlippedComponent(), - ... } - >>> for name, glyph in sorted(glyphSet.items()): - ... pen = DecomposingRecordingPen(glyphSet) - ... try: - ... glyph.draw(pen) - ... except pen.MissingComponentError: - ... pass - ... print("{}: {}".format(name, pen.value)) - a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())] - b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())] - c: [] - d: [('moveTo', ((0, 0),)), ('curveTo', ((-1, 1), (-2, 2), (-3, 3))), ('closePath', ())] - >>> for name, glyph in sorted(glyphSet.items()): - ... pen = DecomposingRecordingPen( - ... glyphSet, skipMissingComponents=True, reverseFlipped=True, - ... ) - ... glyph.draw(pen) - ... print("{}: {}".format(name, pen.value)) - a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())] - b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())] - c: [] - d: [('moveTo', ((0, 0),)), ('lineTo', ((-3, 3),)), ('curveTo', ((-2, 2), (-1, 1), (0, 0))), ('closePath', ())] + >>> class SimpleGlyph(object): + ... def draw(self, pen): + ... pen.moveTo((0, 0)) + ... pen.curveTo((1, 1), (2, 2), (3, 3)) + ... pen.closePath() + >>> class CompositeGlyph(object): + ... def draw(self, pen): + ... pen.addComponent('a', (1, 0, 0, 1, -1, 1)) + >>> class MissingComponent(object): + ... def draw(self, pen): + ... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0)) + >>> class FlippedComponent(object): + ... def draw(self, pen): + ... pen.addComponent('a', (-1, 0, 0, 1, 0, 0)) + >>> glyphSet = { + ... 'a': SimpleGlyph(), + ... 'b': CompositeGlyph(), + ... 'c': MissingComponent(), + ... 'd': FlippedComponent(), + ... } + >>> for name, glyph in sorted(glyphSet.items()): + ... pen = DecomposingRecordingPen(glyphSet) + ... try: + ... glyph.draw(pen) + ... except pen.MissingComponentError: + ... pass + ... print("{}: {}".format(name, pen.value)) + a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())] + b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())] + c: [] + d: [('moveTo', ((0, 0),)), ('curveTo', ((-1, 1), (-2, 2), (-3, 3))), ('closePath', ())] + + >>> for name, glyph in sorted(glyphSet.items()): + ... pen = DecomposingRecordingPen( + ... glyphSet, skipMissingComponents=True, reverseFlipped=True, + ... ) + ... glyph.draw(pen) + ... print("{}: {}".format(name, pen.value)) + a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())] + b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())] + c: [] + d: [('moveTo', ((0, 0),)), ('lineTo', ((-3, 3),)), ('curveTo', ((-2, 2), (-1, 1), (0, 0))), ('closePath', ())] """ # raises MissingComponentError(KeyError) if base glyph is not found in glyphSet @@ -145,20 +147,21 @@ class RecordingPointPen(AbstractPointPen): pointPen.replay(otherPointPen). :Example: + .. code-block:: from defcon import Font from fontTools.pens.recordingPen import RecordingPointPen - + glyph_name = 'a' font_path = 'MyFont.ufo' - + font = Font(font_path) glyph = font[glyph_name] - + pen = RecordingPointPen() glyph.drawPoints(pen) print(pen.value) - + new_glyph = font.newGlyph('b') pen.replay(new_glyph.getPointPen()) """ @@ -211,81 +214,82 @@ class DecomposingRecordingPointPen(DecomposingPointPen, RecordingPointPen): keyed by thir name; other arguments are forwarded to the DecomposingPointPen's constructor:: - >>> from pprint import pprint - >>> class SimpleGlyph(object): - ... def drawPoints(self, pen): - ... pen.beginPath() - ... pen.addPoint((0, 0), "line") - ... pen.addPoint((1, 1)) - ... pen.addPoint((2, 2)) - ... pen.addPoint((3, 3), "curve") - ... pen.endPath() - >>> class CompositeGlyph(object): - ... def drawPoints(self, pen): - ... pen.addComponent('a', (1, 0, 0, 1, -1, 1)) - >>> class MissingComponent(object): - ... def drawPoints(self, pen): - ... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0)) - >>> class FlippedComponent(object): - ... def drawPoints(self, pen): - ... pen.addComponent('a', (-1, 0, 0, 1, 0, 0)) - >>> glyphSet = { - ... 'a': SimpleGlyph(), - ... 'b': CompositeGlyph(), - ... 'c': MissingComponent(), - ... 'd': FlippedComponent(), - ... } - >>> for name, glyph in sorted(glyphSet.items()): - ... pen = DecomposingRecordingPointPen(glyphSet) - ... try: - ... glyph.drawPoints(pen) - ... except pen.MissingComponentError: - ... pass - ... pprint({name: pen.value}) - {'a': [('beginPath', (), {}), - ('addPoint', ((0, 0), 'line', False, None), {}), - ('addPoint', ((1, 1), None, False, None), {}), - ('addPoint', ((2, 2), None, False, None), {}), - ('addPoint', ((3, 3), 'curve', False, None), {}), - ('endPath', (), {})]} - {'b': [('beginPath', (), {}), - ('addPoint', ((-1, 1), 'line', False, None), {}), - ('addPoint', ((0, 2), None, False, None), {}), - ('addPoint', ((1, 3), None, False, None), {}), - ('addPoint', ((2, 4), 'curve', False, None), {}), - ('endPath', (), {})]} - {'c': []} - {'d': [('beginPath', (), {}), - ('addPoint', ((0, 0), 'line', False, None), {}), - ('addPoint', ((-1, 1), None, False, None), {}), - ('addPoint', ((-2, 2), None, False, None), {}), - ('addPoint', ((-3, 3), 'curve', False, None), {}), - ('endPath', (), {})]} - >>> for name, glyph in sorted(glyphSet.items()): - ... pen = DecomposingRecordingPointPen( - ... glyphSet, skipMissingComponents=True, reverseFlipped=True, - ... ) - ... glyph.drawPoints(pen) - ... pprint({name: pen.value}) - {'a': [('beginPath', (), {}), - ('addPoint', ((0, 0), 'line', False, None), {}), - ('addPoint', ((1, 1), None, False, None), {}), - ('addPoint', ((2, 2), None, False, None), {}), - ('addPoint', ((3, 3), 'curve', False, None), {}), - ('endPath', (), {})]} - {'b': [('beginPath', (), {}), - ('addPoint', ((-1, 1), 'line', False, None), {}), - ('addPoint', ((0, 2), None, False, None), {}), - ('addPoint', ((1, 3), None, False, None), {}), - ('addPoint', ((2, 4), 'curve', False, None), {}), - ('endPath', (), {})]} - {'c': []} - {'d': [('beginPath', (), {}), - ('addPoint', ((0, 0), 'curve', False, None), {}), - ('addPoint', ((-3, 3), 'line', False, None), {}), - ('addPoint', ((-2, 2), None, False, None), {}), - ('addPoint', ((-1, 1), None, False, None), {}), - ('endPath', (), {})]} + >>> from pprint import pprint + >>> class SimpleGlyph(object): + ... def drawPoints(self, pen): + ... pen.beginPath() + ... pen.addPoint((0, 0), "line") + ... pen.addPoint((1, 1)) + ... pen.addPoint((2, 2)) + ... pen.addPoint((3, 3), "curve") + ... pen.endPath() + >>> class CompositeGlyph(object): + ... def drawPoints(self, pen): + ... pen.addComponent('a', (1, 0, 0, 1, -1, 1)) + >>> class MissingComponent(object): + ... def drawPoints(self, pen): + ... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0)) + >>> class FlippedComponent(object): + ... def drawPoints(self, pen): + ... pen.addComponent('a', (-1, 0, 0, 1, 0, 0)) + >>> glyphSet = { + ... 'a': SimpleGlyph(), + ... 'b': CompositeGlyph(), + ... 'c': MissingComponent(), + ... 'd': FlippedComponent(), + ... } + >>> for name, glyph in sorted(glyphSet.items()): + ... pen = DecomposingRecordingPointPen(glyphSet) + ... try: + ... glyph.drawPoints(pen) + ... except pen.MissingComponentError: + ... pass + ... pprint({name: pen.value}) + {'a': [('beginPath', (), {}), + ('addPoint', ((0, 0), 'line', False, None), {}), + ('addPoint', ((1, 1), None, False, None), {}), + ('addPoint', ((2, 2), None, False, None), {}), + ('addPoint', ((3, 3), 'curve', False, None), {}), + ('endPath', (), {})]} + {'b': [('beginPath', (), {}), + ('addPoint', ((-1, 1), 'line', False, None), {}), + ('addPoint', ((0, 2), None, False, None), {}), + ('addPoint', ((1, 3), None, False, None), {}), + ('addPoint', ((2, 4), 'curve', False, None), {}), + ('endPath', (), {})]} + {'c': []} + {'d': [('beginPath', (), {}), + ('addPoint', ((0, 0), 'line', False, None), {}), + ('addPoint', ((-1, 1), None, False, None), {}), + ('addPoint', ((-2, 2), None, False, None), {}), + ('addPoint', ((-3, 3), 'curve', False, None), {}), + ('endPath', (), {})]} + + >>> for name, glyph in sorted(glyphSet.items()): + ... pen = DecomposingRecordingPointPen( + ... glyphSet, skipMissingComponents=True, reverseFlipped=True, + ... ) + ... glyph.drawPoints(pen) + ... pprint({name: pen.value}) + {'a': [('beginPath', (), {}), + ('addPoint', ((0, 0), 'line', False, None), {}), + ('addPoint', ((1, 1), None, False, None), {}), + ('addPoint', ((2, 2), None, False, None), {}), + ('addPoint', ((3, 3), 'curve', False, None), {}), + ('endPath', (), {})]} + {'b': [('beginPath', (), {}), + ('addPoint', ((-1, 1), 'line', False, None), {}), + ('addPoint', ((0, 2), None, False, None), {}), + ('addPoint', ((1, 3), None, False, None), {}), + ('addPoint', ((2, 4), 'curve', False, None), {}), + ('endPath', (), {})]} + {'c': []} + {'d': [('beginPath', (), {}), + ('addPoint', ((0, 0), 'curve', False, None), {}), + ('addPoint', ((-3, 3), 'line', False, None), {}), + ('addPoint', ((-2, 2), None, False, None), {}), + ('addPoint', ((-1, 1), None, False, None), {}), + ('endPath', (), {})]} """ # raises MissingComponentError(KeyError) if base glyph is not found in glyphSet diff --git a/Lib/fontTools/pens/svgPathPen.py b/Lib/fontTools/pens/svgPathPen.py index 29d41a802..29d128da3 100644 --- a/Lib/fontTools/pens/svgPathPen.py +++ b/Lib/fontTools/pens/svgPathPen.py @@ -9,27 +9,30 @@ def pointToString(pt, ntos=str): class SVGPathPen(BasePen): """Pen to draw SVG path d commands. - Example:: - >>> pen = SVGPathPen(None) - >>> pen.moveTo((0, 0)) - >>> pen.lineTo((1, 1)) - >>> pen.curveTo((2, 2), (3, 3), (4, 4)) - >>> pen.closePath() - >>> pen.getCommands() - 'M0 0 1 1C2 2 3 3 4 4Z' - Args: glyphSet: a dictionary of drawable glyph objects keyed by name used to resolve component references in composite glyphs. ntos: a callable that takes a number and returns a string, to customize how numbers are formatted (default: str). + :Example: + .. code-block:: + + >>> pen = SVGPathPen(None) + >>> pen.moveTo((0, 0)) + >>> pen.lineTo((1, 1)) + >>> pen.curveTo((2, 2), (3, 3), (4, 4)) + >>> pen.closePath() + >>> pen.getCommands() + 'M0 0 1 1C2 2 3 3 4 4Z' + Note: Fonts have a coordinate system where Y grows up, whereas in SVG, Y grows down. As such, rendering path data from this pen in SVG typically results in upside-down glyphs. You can fix this by wrapping the data from this pen in an SVG group element with transform, or wrap this pen in a transform pen. For example: + .. code-block:: python spen = svgPathPen.SVGPathPen(glyphset) pen= TransformPen(spen , (1, 0, 0, -1, 0, 0)) diff --git a/Lib/fontTools/pens/transformPen.py b/Lib/fontTools/pens/transformPen.py index ff98dbddb..6916fa542 100644 --- a/Lib/fontTools/pens/transformPen.py +++ b/Lib/fontTools/pens/transformPen.py @@ -58,22 +58,27 @@ class TransformPointPen(FilterPointPen): """PointPen that transforms all coordinates using a Affine transformation, and passes them to another PointPen. - >>> from fontTools.pens.recordingPen import RecordingPointPen - >>> rec = RecordingPointPen() - >>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5)) - >>> v = iter(rec.value) - >>> pen.beginPath(identifier="contour-0") - >>> next(v) - ('beginPath', (), {'identifier': 'contour-0'}) - >>> pen.addPoint((100, 100), "line") - >>> next(v) - ('addPoint', ((190, 205), 'line', False, None), {}) - >>> pen.endPath() - >>> next(v) - ('endPath', (), {}) - >>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0") - >>> next(v) - ('addComponent', ('a', ), {'identifier': 'component-0'}) + For example:: + + >>> from fontTools.pens.recordingPen import RecordingPointPen + >>> rec = RecordingPointPen() + >>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5)) + >>> v = iter(rec.value) + >>> pen.beginPath(identifier="contour-0") + >>> next(v) + ('beginPath', (), {'identifier': 'contour-0'}) + + >>> pen.addPoint((100, 100), "line") + >>> next(v) + ('addPoint', ((190, 205), 'line', False, None), {}) + + >>> pen.endPath() + >>> next(v) + ('endPath', (), {}) + + >>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0") + >>> next(v) + ('addComponent', ('a', ), {'identifier': 'component-0'}) """ def __init__(self, outPointPen, transformation): From e7c78970ce3a718fff10cb06c69d20e95511d7c9 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:52:20 +0100 Subject: [PATCH 02/10] Docs: fix code-example blocks in ufoLib. --- Lib/fontTools/ufoLib/__init__.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Lib/fontTools/ufoLib/__init__.py b/Lib/fontTools/ufoLib/__init__.py index a014c9317..aa57beede 100755 --- a/Lib/fontTools/ufoLib/__init__.py +++ b/Lib/fontTools/ufoLib/__init__.py @@ -7,25 +7,29 @@ of the specification. Sets that list the font info attribute names for the fontinfo.plist formats are available for external use. These are: - fontInfoAttributesVersion1 - fontInfoAttributesVersion2 - fontInfoAttributesVersion3 + +- fontInfoAttributesVersion1 +- fontInfoAttributesVersion2 +- fontInfoAttributesVersion3 A set listing the fontinfo.plist attributes that were deprecated in version 2 is available for external use: - deprecatedFontInfoAttributesVersion2 + +- deprecatedFontInfoAttributesVersion2 Functions that do basic validation on values for fontinfo.plist are available for external use. These are - validateFontInfoVersion2ValueForAttribute - validateFontInfoVersion3ValueForAttribute + +- validateFontInfoVersion2ValueForAttribute +- validateFontInfoVersion3ValueForAttribute Value conversion functions are available for converting fontinfo.plist values between the possible format versions. - convertFontInfoValueForAttributeFromVersion1ToVersion2 - convertFontInfoValueForAttributeFromVersion2ToVersion1 - convertFontInfoValueForAttributeFromVersion2ToVersion3 - convertFontInfoValueForAttributeFromVersion3ToVersion2 + +- convertFontInfoValueForAttributeFromVersion1ToVersion2 +- convertFontInfoValueForAttributeFromVersion2ToVersion1 +- convertFontInfoValueForAttributeFromVersion2ToVersion3 +- convertFontInfoValueForAttributeFromVersion3ToVersion2 """ import os From 4b9cb1030e7aa7a1d2c98468acb48d1db66060c0 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:52:59 +0100 Subject: [PATCH 03/10] Docs: fix code-example blocks in svgLib. --- Lib/fontTools/svgLib/path/__init__.py | 4 ++++ Lib/fontTools/svgLib/path/parser.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Lib/fontTools/svgLib/path/__init__.py b/Lib/fontTools/svgLib/path/__init__.py index 742bc64ce..043b4dbe1 100644 --- a/Lib/fontTools/svgLib/path/__init__.py +++ b/Lib/fontTools/svgLib/path/__init__.py @@ -14,6 +14,8 @@ class SVGPath(object): For example, reading from an SVG file and drawing to a Defcon Glyph: + .. code-block:: + import defcon glyph = defcon.Glyph() pen = glyph.getPen() @@ -23,6 +25,8 @@ class SVGPath(object): Or reading from a string containing SVG data, using the alternative 'fromstring' (a class method): + .. code-block:: + data = ' Date: Tue, 3 Sep 2024 17:53:56 +0100 Subject: [PATCH 04/10] Docs: fix code-example blocks in varLib. --- Lib/fontTools/varLib/__init__.py | 4 ++++ Lib/fontTools/varLib/cff.py | 2 +- Lib/fontTools/varLib/mutator.py | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py index 6d0e00ee1..2c390c11a 100644 --- a/Lib/fontTools/varLib/__init__.py +++ b/Lib/fontTools/varLib/__init__.py @@ -10,10 +10,14 @@ ttf-interpolatable files for the masters and build a variable-font from them. Such ttf-interpolatable and designspace files can be generated from a Glyphs source, eg., using noto-source as an example: + .. code-block:: sh + $ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs Then you can make a variable-font this way: + .. code-block:: sh + $ fonttools varLib master_ufo/NotoSansArabic.designspace API *will* change in near future. diff --git a/Lib/fontTools/varLib/cff.py b/Lib/fontTools/varLib/cff.py index 59ac5c6f7..155429ab5 100644 --- a/Lib/fontTools/varLib/cff.py +++ b/Lib/fontTools/varLib/cff.py @@ -96,7 +96,7 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map): * step through each key in FontDict.Private. * For each key, step through each relevant source font Private dict, and - build a list of values to blend. + build a list of values to blend. The 'relevant' source fonts are selected by first getting the right submodel using ``vsindex_dict[vsindex]``. The indices of the diff --git a/Lib/fontTools/varLib/mutator.py b/Lib/fontTools/varLib/mutator.py index 6c327f945..80e46bb24 100644 --- a/Lib/fontTools/varLib/mutator.py +++ b/Lib/fontTools/varLib/mutator.py @@ -1,7 +1,9 @@ """ Instantiate a variation font. Run, eg: -$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85 +.. code-block:: sh + + $ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85 """ from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed @@ -162,7 +164,9 @@ def instantiateVariableFont(varfont, location, inplace=False, overlap=True): defining the desired location along the variable font's axes. The location values must be specified as user-space coordinates, e.g.: - {'wght': 400, 'wdth': 100} + .. code-block:: + + {'wght': 400, 'wdth': 100} By default, a new TTFont object is returned. If ``inplace`` is True, the input varfont is modified and reduced to a static font. From 1fc9bc2dcacd817e7784fc5aa8a84c83fae23526 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:54:29 +0100 Subject: [PATCH 05/10] Docs: fix code-example blocks in varLib/instancer. --- Lib/fontTools/varLib/instancer/__init__.py | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/__init__.py b/Lib/fontTools/varLib/instancer/__init__.py index 82676d419..fba79dbaa 100644 --- a/Lib/fontTools/varLib/instancer/__init__.py +++ b/Lib/fontTools/varLib/instancer/__init__.py @@ -5,7 +5,9 @@ create full instances (i.e. static fonts) from variable fonts, as well as "parti variable fonts that only contain a subset of the original variation space. For example, if you wish to pin the width axis to a given location while also -restricting the weight axis to 400..700 range, you can do:: +restricting the weight axis to 400..700 range, you can do: + +.. code-block:: sh $ fonttools varLib.instancer ./NotoSans-VF.ttf wdth=85 wght=400:700 @@ -19,30 +21,30 @@ the VF axes were given an explicit coordinate. E.g. here's how to pin the wght axis at a given location in a wght+wdth variable font, keeping only the deltas associated with the wdth axis:: -| >>> from fontTools import ttLib -| >>> from fontTools.varLib import instancer -| >>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf") -| >>> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes -| ['wght', 'wdth'] -| >>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300}) -| >>> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght' -| ['wdth'] + >>> from fontTools import ttLib + >>> from fontTools.varLib import instancer + >>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf") + >>> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes + ['wght', 'wdth'] + >>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300}) + >>> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght' + ['wdth'] If the input location specifies all the axes, the resulting instance is no longer 'variable' (same as using fontools varLib.mutator): -| >>> instance = instancer.instantiateVariableFont( -| ... varfont, {"wght": 700, "wdth": 67.5} -| ... ) -| >>> "fvar" not in instance -| True + >>> instance = instancer.instantiateVariableFont( + ... varfont, {"wght": 700, "wdth": 67.5} + ... ) + >>> "fvar" not in instance + True If one just want to drop an axis at the default location, without knowing in advance what the default value for that axis is, one can pass a `None` value: -| >>> instance = instancer.instantiateVariableFont(varfont, {"wght": None}) -| >>> len(varfont["fvar"].axes) -| 1 + >>> instance = instancer.instantiateVariableFont(varfont, {"wght": None}) + >>> len(varfont["fvar"].axes) + 1 From the console script, this is equivalent to passing `wght=drop` as input. @@ -57,24 +59,24 @@ course be combined: L1 dropping one or more axes while leaving the default tables unmodified; - | >>> font = instancer.instantiateVariableFont(varfont, {"wght": None}) + >>> font = instancer.instantiateVariableFont(varfont, {"wght": None}) L2 dropping one or more axes while pinning them at non-default locations; - | >>> font = instancer.instantiateVariableFont(varfont, {"wght": 700}) + >>> font = instancer.instantiateVariableFont(varfont, {"wght": 700}) L3 restricting the range of variation of one or more axes, by setting either a new minimum or maximum, potentially -- though not necessarily -- dropping entire regions of variations that fall completely outside this new range. - | >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)}) + >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)}) L4 moving the default location of an axis, by specifying (min,defalt,max) values: - | >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)}) + >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)}) Currently only TrueType-flavored variable fonts (i.e. containing 'glyf' table) are supported, but support for CFF2 variable fonts will be added soon. From df49533892cd82602bfc9a806fc1048e640c2f46 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:54:45 +0100 Subject: [PATCH 06/10] Docs: fix code-example blocks in voltLib. --- Lib/fontTools/voltLib/voltToFea.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/fontTools/voltLib/voltToFea.py b/Lib/fontTools/voltLib/voltToFea.py index 2265d5029..c77d5ad11 100644 --- a/Lib/fontTools/voltLib/voltToFea.py +++ b/Lib/fontTools/voltLib/voltToFea.py @@ -7,12 +7,16 @@ Usage To convert a VTP project file: +.. code-block:: sh + $ fonttools voltLib.voltToFea input.vtp output.fea It is also possible convert font files with `TSIV` table (as saved from Volt), in this case the glyph names used in the Volt project will be mapped to the actual glyph names in the font files when written to the feature file: +.. code-block:: sh + $ fonttools voltLib.voltToFea input.ttf output.fea The ``--quiet`` option can be used to suppress warnings. From 21d04842f8f9f51ea24c05f1fc3626f3b111fd2d Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Tue, 3 Sep 2024 17:55:02 +0100 Subject: [PATCH 07/10] Docs: fix code-example blocks in ttLib. --- Lib/fontTools/ttLib/sfnt.py | 5 +++-- Lib/fontTools/ttLib/ttFont.py | 26 +++++++++++++------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Lib/fontTools/ttLib/sfnt.py b/Lib/fontTools/ttLib/sfnt.py index b1569423c..6cc867a4d 100644 --- a/Lib/fontTools/ttLib/sfnt.py +++ b/Lib/fontTools/ttLib/sfnt.py @@ -1,8 +1,9 @@ """ttLib/sfnt.py -- low-level module to deal with the sfnt file format. Defines two public classes: - SFNTReader - SFNTWriter + +- SFNTReader +- SFNTWriter (Normally you don't have to use these classes explicitly; they are used automatically by ttLib.TTFont.) diff --git a/Lib/fontTools/ttLib/ttFont.py b/Lib/fontTools/ttLib/ttFont.py index f4a539678..ad8756a05 100644 --- a/Lib/fontTools/ttLib/ttFont.py +++ b/Lib/fontTools/ttLib/ttFont.py @@ -28,34 +28,34 @@ class TTFont(object): Example usage:: - >> from fontTools import ttLib - >> tt = ttLib.TTFont("afont.ttf") # Load an existing font file - >> tt['maxp'].numGlyphs + >>> from fontTools import ttLib + >>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file + >>> tt['maxp'].numGlyphs 242 - >> tt['OS/2'].achVendID + >>> tt['OS/2'].achVendID 'B&H\000' - >> tt['head'].unitsPerEm + >>> tt['head'].unitsPerEm 2048 For details of the objects returned when accessing each table, see :ref:`tables`. To add a table to the font, use the :py:func:`newTable` function:: - >> os2 = newTable("OS/2") - >> os2.version = 4 - >> # set other attributes - >> font["OS/2"] = os2 + >>> os2 = newTable("OS/2") + >>> os2.version = 4 + >>> # set other attributes + >>> font["OS/2"] = os2 TrueType fonts can also be serialized to and from XML format (see also the :ref:`ttx` binary):: - >> tt.saveXML("afont.ttx") + >>> tt.saveXML("afont.ttx") Dumping 'LTSH' table... Dumping 'OS/2' table... [...] - >> tt2 = ttLib.TTFont() # Create a new font object - >> tt2.importXML("afont.ttx") - >> tt2['maxp'].numGlyphs + >>> tt2 = ttLib.TTFont() # Create a new font object + >>> tt2.importXML("afont.ttx") + >>> tt2['maxp'].numGlyphs 242 The TTFont object may be used as a context manager; this will cause the file From 6914070e00c92d7f3d52b57f23ced21dea065095 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Wed, 4 Sep 2024 17:36:48 +0100 Subject: [PATCH 08/10] Docs, minor: remove trailing whitespace. --- Lib/fontTools/pens/recordingPen.py | 14 +++++++------- Lib/fontTools/pens/transformPen.py | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/fontTools/pens/recordingPen.py b/Lib/fontTools/pens/recordingPen.py index 585f44638..b8a817ccf 100644 --- a/Lib/fontTools/pens/recordingPen.py +++ b/Lib/fontTools/pens/recordingPen.py @@ -37,14 +37,14 @@ class RecordingPen(AbstractPen): from fontTools.ttLib import TTFont from fontTools.pens.recordingPen import RecordingPen - + glyph_name = 'dollar' font_path = 'MyFont.otf' - + font = TTFont(font_path) glyphset = font.getGlyphSet() glyph = glyphset[glyph_name] - + pen = RecordingPen() glyph.draw(pen) print(pen.value) @@ -151,17 +151,17 @@ class RecordingPointPen(AbstractPointPen): from defcon import Font from fontTools.pens.recordingPen import RecordingPointPen - + glyph_name = 'a' font_path = 'MyFont.ufo' - + font = Font(font_path) glyph = font[glyph_name] - + pen = RecordingPointPen() glyph.drawPoints(pen) print(pen.value) - + new_glyph = font.newGlyph('b') pen.replay(new_glyph.getPointPen()) """ diff --git a/Lib/fontTools/pens/transformPen.py b/Lib/fontTools/pens/transformPen.py index 6916fa542..3db6efdf2 100644 --- a/Lib/fontTools/pens/transformPen.py +++ b/Lib/fontTools/pens/transformPen.py @@ -67,15 +67,15 @@ class TransformPointPen(FilterPointPen): >>> pen.beginPath(identifier="contour-0") >>> next(v) ('beginPath', (), {'identifier': 'contour-0'}) - + >>> pen.addPoint((100, 100), "line") >>> next(v) ('addPoint', ((190, 205), 'line', False, None), {}) - + >>> pen.endPath() >>> next(v) ('endPath', (), {}) - + >>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0") >>> next(v) ('addComponent', ('a', ), {'identifier': 'component-0'}) From 7d93689aca5356c54c6a73d98feadbcd5a3a47cb Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Wed, 11 Sep 2024 15:45:46 +0100 Subject: [PATCH 09/10] Docs: workaround doctest-vs-Sphinx syntax highlighting. --- Lib/fontTools/pens/freetypePen.py | 61 +++++++++-------- Lib/fontTools/ttLib/ttFont.py | 78 ++++++++++++---------- Lib/fontTools/varLib/instancer/__init__.py | 50 +++++++++----- 3 files changed, 108 insertions(+), 81 deletions(-) diff --git a/Lib/fontTools/pens/freetypePen.py b/Lib/fontTools/pens/freetypePen.py index a366b6d05..1e3129cea 100644 --- a/Lib/fontTools/pens/freetypePen.py +++ b/Lib/fontTools/pens/freetypePen.py @@ -46,7 +46,7 @@ class FreeTypePen(BasePen): glyphSet: a dictionary of drawable glyph objects keyed by name used to resolve component references in composite glyphs. - :Examples: + Examples: If `numpy` and `matplotlib` is available, the following code will show the glyph image of `fi` in a new window:: @@ -178,7 +178,7 @@ class FreeTypePen(BasePen): object of the resulted bitmap and ``size`` is a 2-tuple of its dimension. - :Notes: + Notes: The image size should always be given explicitly if you need to get a proper glyph image. When ``width`` and ``height`` are omitted, it forcifully fits to the bounding box and the side bearings get @@ -188,13 +188,14 @@ class FreeTypePen(BasePen): maintained but RSB won’t. The difference between the two becomes more obvious when rotate or skew transformation is applied. - :Example: - .. code-block:: + Example: + .. code-block:: pycon - >>> pen = FreeTypePen(None) - >>> glyph.draw(pen) - >>> buf, size = pen.buffer(width=500, height=1000) - >>> type(buf), len(buf), size + >>> + >> pen = FreeTypePen(None) + >> glyph.draw(pen) + >> buf, size = pen.buffer(width=500, height=1000) + >> type(buf), len(buf), size (, 500000, (500, 1000)) """ transform = transform or Transform() @@ -268,7 +269,7 @@ class FreeTypePen(BasePen): A ``numpy.ndarray`` object with a shape of ``(height, width)``. Each element takes a value in the range of ``[0.0, 1.0]``. - :Notes: + Notes: The image size should always be given explicitly if you need to get a proper glyph image. When ``width`` and ``height`` are omitted, it forcifully fits to the bounding box and the side bearings get @@ -278,15 +279,17 @@ class FreeTypePen(BasePen): maintained but RSB won’t. The difference between the two becomes more obvious when rotate or skew transformation is applied. - :Example: - .. code-block:: + Example: + .. code-block:: pycon - >>> pen = FreeTypePen(None) - >>> glyph.draw(pen) - >>> arr = pen.array(width=500, height=1000) - >>> type(a), a.shape + >>> + >> pen = FreeTypePen(None) + >> glyph.draw(pen) + >> arr = pen.array(width=500, height=1000) + >> type(a), a.shape (, (1000, 500)) """ + import numpy as np buf, size = self.buffer( @@ -317,7 +320,7 @@ class FreeTypePen(BasePen): rendering glyphs with negative sidebearings without clipping. evenOdd: Pass ``True`` for even-odd fill instead of non-zero. - :Notes: + Notes: The image size should always be given explicitly if you need to get a proper glyph image. When ``width`` and ``height`` are omitted, it forcifully fits to the bounding box and the side bearings get @@ -327,12 +330,13 @@ class FreeTypePen(BasePen): maintained but RSB won’t. The difference between the two becomes more obvious when rotate or skew transformation is applied. - :Example: - .. code-block:: + Example: + .. code-block:: pycon - >>> pen = FreeTypePen(None) - >>> glyph.draw(pen) - >>> pen.show(width=500, height=1000) + >>> + >> pen = FreeTypePen(None) + >> glyph.draw(pen) + >> pen.show(width=500, height=1000) """ from matplotlib import pyplot as plt @@ -369,7 +373,7 @@ class FreeTypePen(BasePen): A ``PIL.image`` object. The image is filled in black with alpha channel obtained from the rendered bitmap. - :Notes: + Notes: The image size should always be given explicitly if you need to get a proper glyph image. When ``width`` and ``height`` are omitted, it forcifully fits to the bounding box and the side bearings get @@ -379,13 +383,14 @@ class FreeTypePen(BasePen): maintained but RSB won’t. The difference between the two becomes more obvious when rotate or skew transformation is applied. - :Example: - .. code-block:: + Example: + .. code-block:: pycon - >>> pen = FreeTypePen(None) - >>> glyph.draw(pen) - >>> img = pen.image(width=500, height=1000) - >>> type(img), img.size + >>> + >> pen = FreeTypePen(None) + >> glyph.draw(pen) + >> img = pen.image(width=500, height=1000) + >> type(img), img.size (, (500, 1000)) """ from PIL import Image diff --git a/Lib/fontTools/ttLib/ttFont.py b/Lib/fontTools/ttLib/ttFont.py index ad8756a05..0942bd80d 100644 --- a/Lib/fontTools/ttLib/ttFont.py +++ b/Lib/fontTools/ttLib/ttFont.py @@ -26,37 +26,43 @@ class TTFont(object): accessing tables. Tables will be only decompiled when necessary, ie. when they're actually accessed. This means that simple operations can be extremely fast. - Example usage:: - - >>> from fontTools import ttLib - >>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file - >>> tt['maxp'].numGlyphs - 242 - >>> tt['OS/2'].achVendID - 'B&H\000' - >>> tt['head'].unitsPerEm - 2048 + Example usage: + .. code-block:: pycon + + >>> + >> from fontTools import ttLib + >> tt = ttLib.TTFont("afont.ttf") # Load an existing font file + >> tt['maxp'].numGlyphs + 242 + >> tt['OS/2'].achVendID + 'B&H\000' + >> tt['head'].unitsPerEm + 2048 For details of the objects returned when accessing each table, see :ref:`tables`. - To add a table to the font, use the :py:func:`newTable` function:: - - >>> os2 = newTable("OS/2") - >>> os2.version = 4 - >>> # set other attributes - >>> font["OS/2"] = os2 + To add a table to the font, use the :py:func:`newTable` function: + .. code-block:: pycon + + >>> + >> os2 = newTable("OS/2") + >> os2.version = 4 + >> # set other attributes + >> font["OS/2"] = os2 TrueType fonts can also be serialized to and from XML format (see also the - :ref:`ttx` binary):: - - >>> tt.saveXML("afont.ttx") - Dumping 'LTSH' table... - Dumping 'OS/2' table... - [...] - - >>> tt2 = ttLib.TTFont() # Create a new font object - >>> tt2.importXML("afont.ttx") - >>> tt2['maxp'].numGlyphs - 242 + :ref:`ttx` binary): + .. code-block:: pycon + + >> + >> tt.saveXML("afont.ttx") + Dumping 'LTSH' table... + Dumping 'OS/2' table... + [...] + + >> tt2 = ttLib.TTFont() # Create a new font object + >> tt2.importXML("afont.ttx") + >> tt2['maxp'].numGlyphs + 242 The TTFont object may be used as a context manager; this will cause the file reader to be closed after the context ``with`` block is exited:: @@ -981,14 +987,16 @@ def tagToIdentifier(tag): letters get an underscore after the letter. Trailing spaces are trimmed. Illegal characters are escaped as two hex bytes. If the result starts with a number (as the result of a hex escape), an - extra underscore is prepended. Examples:: - - >>> tagToIdentifier('glyf') - '_g_l_y_f' - >>> tagToIdentifier('cvt ') - '_c_v_t' - >>> tagToIdentifier('OS/2') - 'O_S_2f_2' + extra underscore is prepended. Examples: + .. code-block:: pycon + + >>> + >> tagToIdentifier('glyf') + '_g_l_y_f' + >> tagToIdentifier('cvt ') + '_c_v_t' + >> tagToIdentifier('OS/2') + 'O_S_2f_2' """ import re diff --git a/Lib/fontTools/varLib/instancer/__init__.py b/Lib/fontTools/varLib/instancer/__init__.py index fba79dbaa..8a58dbd92 100644 --- a/Lib/fontTools/varLib/instancer/__init__.py +++ b/Lib/fontTools/varLib/instancer/__init__.py @@ -19,31 +19,37 @@ and returns a new TTFont representing either a partial VF, or full instance if a the VF axes were given an explicit coordinate. E.g. here's how to pin the wght axis at a given location in a wght+wdth variable -font, keeping only the deltas associated with the wdth axis:: +font, keeping only the deltas associated with the wdth axis: +.. code-block:: pycon - >>> from fontTools import ttLib - >>> from fontTools.varLib import instancer - >>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf") - >>> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes + >>> + >> from fontTools import ttLib + >> from fontTools.varLib import instancer + >> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf") + >> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes ['wght', 'wdth'] - >>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300}) - >>> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght' + >> partial = instancer.instantiateVariableFont(varfont, {"wght": 300}) + >> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght' ['wdth'] If the input location specifies all the axes, the resulting instance is no longer 'variable' (same as using fontools varLib.mutator): +.. code-block:: pycon - >>> instance = instancer.instantiateVariableFont( + >>> + >> instance = instancer.instantiateVariableFont( ... varfont, {"wght": 700, "wdth": 67.5} ... ) - >>> "fvar" not in instance + >> "fvar" not in instance True If one just want to drop an axis at the default location, without knowing in advance what the default value for that axis is, one can pass a `None` value: +.. code-block:: pycon - >>> instance = instancer.instantiateVariableFont(varfont, {"wght": None}) - >>> len(varfont["fvar"].axes) + >>> + >> instance = instancer.instantiateVariableFont(varfont, {"wght": None}) + >> len(varfont["fvar"].axes) 1 From the console script, this is equivalent to passing `wght=drop` as input. @@ -58,25 +64,33 @@ course be combined: L1 dropping one or more axes while leaving the default tables unmodified; + .. code-block:: pycon - >>> font = instancer.instantiateVariableFont(varfont, {"wght": None}) + >>> + >> font = instancer.instantiateVariableFont(varfont, {"wght": None}) L2 dropping one or more axes while pinning them at non-default locations; - - >>> font = instancer.instantiateVariableFont(varfont, {"wght": 700}) + .. code-block:: pycon + + >>> + >> font = instancer.instantiateVariableFont(varfont, {"wght": 700}) L3 restricting the range of variation of one or more axes, by setting either a new minimum or maximum, potentially -- though not necessarily -- dropping entire regions of variations that fall completely outside this new range. - - >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)}) + .. code-block:: pycon + + >>> + >> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)}) L4 moving the default location of an axis, by specifying (min,defalt,max) values: - - >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)}) + .. code-block:: pycon + + >>> + >> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)}) Currently only TrueType-flavored variable fonts (i.e. containing 'glyf' table) are supported, but support for CFF2 variable fonts will be added soon. From d05cdcf21f036dc2cb4ff252b81c2b752c01ee58 Mon Sep 17 00:00:00 2001 From: Nathan Williis Date: Wed, 11 Sep 2024 15:48:09 +0100 Subject: [PATCH 10/10] Docs: black --- Lib/fontTools/pens/freetypePen.py | 4 ++-- Lib/fontTools/ttLib/ttFont.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Lib/fontTools/pens/freetypePen.py b/Lib/fontTools/pens/freetypePen.py index 1e3129cea..065da932a 100644 --- a/Lib/fontTools/pens/freetypePen.py +++ b/Lib/fontTools/pens/freetypePen.py @@ -289,7 +289,7 @@ class FreeTypePen(BasePen): >> type(a), a.shape (, (1000, 500)) """ - + import numpy as np buf, size = self.buffer( @@ -333,7 +333,7 @@ class FreeTypePen(BasePen): Example: .. code-block:: pycon - >>> + >>> >> pen = FreeTypePen(None) >> glyph.draw(pen) >> pen.show(width=500, height=1000) diff --git a/Lib/fontTools/ttLib/ttFont.py b/Lib/fontTools/ttLib/ttFont.py index 0942bd80d..d7bd92bc2 100644 --- a/Lib/fontTools/ttLib/ttFont.py +++ b/Lib/fontTools/ttLib/ttFont.py @@ -28,7 +28,7 @@ class TTFont(object): Example usage: .. code-block:: pycon - + >>> >> from fontTools import ttLib >> tt = ttLib.TTFont("afont.ttf") # Load an existing font file @@ -42,7 +42,7 @@ class TTFont(object): For details of the objects returned when accessing each table, see :ref:`tables`. To add a table to the font, use the :py:func:`newTable` function: .. code-block:: pycon - + >>> >> os2 = newTable("OS/2") >> os2.version = 4 @@ -52,13 +52,13 @@ class TTFont(object): TrueType fonts can also be serialized to and from XML format (see also the :ref:`ttx` binary): .. code-block:: pycon - + >> >> tt.saveXML("afont.ttx") Dumping 'LTSH' table... Dumping 'OS/2' table... [...] - + >> tt2 = ttLib.TTFont() # Create a new font object >> tt2.importXML("afont.ttx") >> tt2['maxp'].numGlyphs @@ -989,7 +989,7 @@ def tagToIdentifier(tag): result starts with a number (as the result of a hex escape), an extra underscore is prepended. Examples: .. code-block:: pycon - + >>> >> tagToIdentifier('glyf') '_g_l_y_f'