Skip to content

Commit

Permalink
freetypePen: format code with Black
Browse files Browse the repository at this point in the history
  • Loading branch information
takaakifuji committed Jan 31, 2022
1 parent 48cbe7b commit 5f2c492
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 55 deletions.
100 changes: 74 additions & 26 deletions Lib/fontTools/pens/freetypePen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

"""Pen to rasterize paths with FreeType."""

__all__ = ['FreeTypePen']
__all__ = ["FreeTypePen"]

import os
import ctypes
Expand All @@ -15,14 +15,22 @@
from freetype.raw import FT_Outline_Get_Bitmap, FT_Outline_Get_BBox, FT_Outline_Get_CBox
from freetype.ft_types import FT_Pos
from freetype.ft_structs import FT_Vector, FT_BBox, FT_Bitmap, FT_Outline
from freetype.ft_enums import FT_OUTLINE_NONE, FT_OUTLINE_EVEN_ODD_FILL, FT_PIXEL_MODE_GRAY, FT_CURVE_TAG_ON, FT_CURVE_TAG_CONIC, FT_CURVE_TAG_CUBIC
from freetype.ft_enums import (
FT_OUTLINE_NONE,
FT_OUTLINE_EVEN_ODD_FILL,
FT_PIXEL_MODE_GRAY,
FT_CURVE_TAG_ON,
FT_CURVE_TAG_CONIC,
FT_CURVE_TAG_CUBIC,
)
from freetype.ft_errors import FT_Exception

from fontTools.pens.basePen import BasePen, PenError
from fontTools.misc.roundTools import otRound
from fontTools.misc.transform import Transform

Contour = collections.namedtuple('Contour', ('points', 'tags'))
Contour = collections.namedtuple("Contour", ("points", "tags"))


class FreeTypePen(BasePen):
"""Pen to rasterize paths with FreeType. Requires `freetype-py` module.
Expand Down Expand Up @@ -115,15 +123,19 @@ def outline(self, transform=None, evenOdd=False):
evenOdd: Pass ``True`` for even-odd fill instead of non-zero.
"""
transform = transform or Transform()
if not hasattr(transform, 'transformPoint'):
if not hasattr(transform, "transformPoint"):
transform = Transform(*transform)
n_contours = len(self.contours)
n_points = sum((len(contour.points) for contour in self.contours))
n_points = sum((len(contour.points) for contour in self.contours))
points = []
for contour in self.contours:
for point in contour.points:
point = transform.transformPoint(point)
points.append(FT_Vector(FT_Pos(otRound(point[0] * 64)), FT_Pos(otRound(point[1] * 64))))
points.append(
FT_Vector(
FT_Pos(otRound(point[0] * 64)), FT_Pos(otRound(point[1] * 64))
)
)
tags = []
for contour in self.contours:
for tag in contour.tags:
Expand All @@ -137,13 +149,15 @@ def outline(self, transform=None, evenOdd=False):
return FT_Outline(
(ctypes.c_short)(n_contours),
(ctypes.c_short)(n_points),
(FT_Vector * n_points)(*points),
(FT_Vector * n_points)(*points),
(ctypes.c_ubyte * n_points)(*tags),
(ctypes.c_short * n_contours)(*contours),
(ctypes.c_int)(flags)
(ctypes.c_int)(flags),
)

def buffer(self, width=None, height=None, transform=None, contain=False, evenOdd=False):
def buffer(
self, width=None, height=None, transform=None, contain=False, evenOdd=False
):
"""Renders the current contours within a bitmap buffer.
Args:
Expand Down Expand Up @@ -185,13 +199,18 @@ def buffer(self, width=None, height=None, transform=None, contain=False, evenOdd
"""
transform = transform or Transform()
if not hasattr(transform, 'transformPoint'):
if not hasattr(transform, "transformPoint"):
transform = Transform(*transform)
contain_x, contain_y = contain or width is None, contain or height is None
if contain_x or contain_y:
dx, dy = transform.dx, transform.dy
bbox = self.bbox
p1, p2, p3, p4 = transform.transformPoint((bbox[0], bbox[1])), transform.transformPoint((bbox[2], bbox[1])), transform.transformPoint((bbox[0], bbox[3])), transform.transformPoint((bbox[2], bbox[3]))
p1, p2, p3, p4 = (
transform.transformPoint((bbox[0], bbox[1])),
transform.transformPoint((bbox[2], bbox[1])),
transform.transformPoint((bbox[0], bbox[3])),
transform.transformPoint((bbox[2], bbox[3])),
)
px, py = (p1[0], p2[0], p3[0], p4[0]), (p1[1], p2[1], p3[1], p4[1])
if contain_x:
if width is None:
Expand All @@ -218,15 +237,19 @@ def buffer(self, width=None, height=None, transform=None, contain=False, evenOdd
(ctypes.c_short)(256),
(ctypes.c_ubyte)(FT_PIXEL_MODE_GRAY),
(ctypes.c_char)(0),
(ctypes.c_void_p)(None)
(ctypes.c_void_p)(None),
)
outline = self.outline(transform=transform, evenOdd=evenOdd)
err = FT_Outline_Get_Bitmap(freetype.get_handle(), ctypes.byref(outline), ctypes.byref(bitmap))
err = FT_Outline_Get_Bitmap(
freetype.get_handle(), ctypes.byref(outline), ctypes.byref(bitmap)
)
if err != 0:
raise FT_Exception(err)
return buf.raw, (width, height)

def array(self, width=None, height=None, transform=None, contain=False, evenOdd=False):
def array(
self, width=None, height=None, transform=None, contain=False, evenOdd=False
):
"""Returns the rendered contours as a numpy array. Requires `numpy`.
Args:
Expand Down Expand Up @@ -266,10 +289,19 @@ def array(self, width=None, height=None, transform=None, contain=False, evenOdd=
(<class 'numpy.ndarray'>, (1000, 500))
"""
import numpy as np
buf, size = self.buffer(width=width, height=height, transform=transform, contain=contain, evenOdd=evenOdd)
return np.frombuffer(buf, 'B').reshape((size[1], size[0])) / 255.0

def show(self, width=None, height=None, transform=None, contain=False, evenOdd=False):
buf, size = self.buffer(
width=width,
height=height,
transform=transform,
contain=contain,
evenOdd=evenOdd,
)
return np.frombuffer(buf, "B").reshape((size[1], size[0])) / 255.0

def show(
self, width=None, height=None, transform=None, contain=False, evenOdd=False
):
"""Plots the rendered contours with `pyplot`. Requires `numpy` and
`matplotlib`.
Expand Down Expand Up @@ -304,11 +336,20 @@ def show(self, width=None, height=None, transform=None, contain=False, evenOdd=F
>> pen.show(width=500, height=1000)
"""
from matplotlib import pyplot as plt
a = self.array(width=width, height=height, transform=transform, contain=contain, evenOdd=evenOdd)
plt.imshow(a, cmap='gray_r', vmin=0, vmax=1)

a = self.array(
width=width,
height=height,
transform=transform,
contain=contain,
evenOdd=evenOdd,
)
plt.imshow(a, cmap="gray_r", vmin=0, vmax=1)
plt.show()

def image(self, width=None, height=None, transform=None, contain=False, evenOdd=False):
def image(
self, width=None, height=None, transform=None, contain=False, evenOdd=False
):
"""Returns the rendered contours as a PIL image. Requires `Pillow`.
Can be used to display a glyph image in Jupyter Notebook.
Expand Down Expand Up @@ -349,9 +390,16 @@ def image(self, width=None, height=None, transform=None, contain=False, evenOdd=
(<class 'PIL.Image.Image'>, (500, 1000))
"""
from PIL import Image
buf, size = self.buffer(width=width, height=height, transform=transform, contain=contain, evenOdd=evenOdd)
img = Image.new('L', size, 0)
img.putalpha(Image.frombuffer('L', size, buf))

buf, size = self.buffer(
width=width,
height=height,
transform=transform,
contain=contain,
evenOdd=evenOdd,
)
img = Image.new("L", size, 0)
img.putalpha(Image.frombuffer("L", size, buf))
return img

@property
Expand Down Expand Up @@ -386,14 +434,14 @@ def _moveTo(self, pt):

def _lineTo(self, pt):
if not (self.contours and len(self.contours[-1].points) > 0):
raise PenError('Contour missing required initial moveTo')
raise PenError("Contour missing required initial moveTo")
contour = self.contours[-1]
contour.points.append(pt)
contour.tags.append(FT_CURVE_TAG_ON)

def _curveToOne(self, p1, p2, p3):
if not (self.contours and len(self.contours[-1].points) > 0):
raise PenError('Contour missing required initial moveTo')
raise PenError("Contour missing required initial moveTo")
t1, t2, t3 = FT_CURVE_TAG_CUBIC, FT_CURVE_TAG_CUBIC, FT_CURVE_TAG_ON
contour = self.contours[-1]
for p, t in ((p1, t1), (p2, t2), (p3, t3)):
Expand All @@ -402,7 +450,7 @@ def _curveToOne(self, p1, p2, p3):

def _qCurveToOne(self, p1, p2):
if not (self.contours and len(self.contours[-1].points) > 0):
raise PenError('Contour missing required initial moveTo')
raise PenError("Contour missing required initial moveTo")
t1, t2 = FT_CURVE_TAG_CONIC, FT_CURVE_TAG_ON
contour = self.contours[-1]
for p, t in ((p1, t1), (p2, t2)):
Expand Down
Loading

0 comments on commit 5f2c492

Please sign in to comment.