Skip to content

Commit a3cc592

Browse files
committed
New FreeType wrapper.
TODO: ttc support violates the assumption that the filename suffices to identify the face (when caching). We need to generate a uniquer id or just key off the face object. [ci skip]
1 parent 3c1f423 commit a3cc592

File tree

20 files changed

+1279
-458
lines changed

20 files changed

+1279
-458
lines changed

examples/misc/font_indexing.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
"""
1010
from __future__ import print_function
1111
import matplotlib
12-
from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, KERNING_UNFITTED, KERNING_UNSCALED
12+
from matplotlib import _ft2
1313

1414

15-
#fname = '/usr/share/fonts/sfd/FreeSans.ttf'
1615
fname = matplotlib.get_data_path() + '/fonts/ttf/DejaVuSans.ttf'
17-
font = FT2Font(fname)
18-
font.set_charmap(0)
16+
font = _ft2.Face(fname)
17+
font.set_charmap(0) # FIXME
1918

2019
codes = font.get_charmap().items()
2120
#dsu = [(ccode, glyphind) for ccode, glyphind in codes]
@@ -34,11 +33,8 @@
3433
coded[name] = ccode
3534
glyphd[name] = glyphind
3635

37-
code = coded['A']
38-
glyph = font.load_char(code)
39-
#print(glyph.bbox)
4036
print(glyphd['A'], glyphd['V'], coded['A'], coded['V'])
41-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_DEFAULT))
42-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_UNFITTED))
43-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_UNSCALED))
44-
print('AV', font.get_kerning(glyphd['A'], glyphd['T'], KERNING_UNSCALED))
37+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], _ft2.Kerning.DEFAULT))
38+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], _ft2.Kerning.UNFITTED))
39+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], _ft2.Kerning.UNSCALED))
40+
print('AV', font.get_kerning(glyphd['A'], glyphd['T'], _ft2.Kerning.UNSCALED))

examples/misc/ftface_props.py

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,54 @@
11
"""
2-
============
3-
Ftface Props
4-
============
5-
6-
This is a demo script to show you how to use all the properties of an
7-
FT2Font object. These describe global font properties. For
8-
individual character metrics, use the Glyph object, as returned by
9-
load_char
2+
===============
3+
Face properties
4+
===============
5+
6+
This is a demo script to show you how to use all the properties of a Face
7+
object. These describe global font properties. For individual character
8+
metrics, use the Glyph object, as loaded from the glyph attribute after calling
9+
load_char.
1010
"""
1111
from __future__ import print_function
1212
import matplotlib
13-
import matplotlib.ft2font as ft
14-
15-
16-
#fname = '/usr/local/share/matplotlib/VeraIt.ttf'
17-
fname = matplotlib.get_data_path() + '/fonts/ttf/DejaVuSans-Oblique.ttf'
18-
#fname = '/usr/local/share/matplotlib/cmr10.ttf'
19-
20-
font = ft.FT2Font(fname)
21-
22-
print('Num faces :', font.num_faces) # number of faces in file
23-
print('Num glyphs :', font.num_glyphs) # number of glyphs in the face
24-
print('Family name :', font.family_name) # face family name
25-
print('Style name :', font.style_name) # face style name
26-
print('PS name :', font.postscript_name) # the postscript name
27-
print('Num fixed :', font.num_fixed_sizes) # number of embedded bitmap in face
28-
29-
# the following are only available if face.scalable
30-
if font.scalable:
31-
# the face global bounding box (xmin, ymin, xmax, ymax)
32-
print('Bbox :', font.bbox)
33-
# number of font units covered by the EM
34-
print('EM :', font.units_per_EM)
35-
# the ascender in 26.6 units
36-
print('Ascender :', font.ascender)
37-
# the descender in 26.6 units
38-
print('Descender :', font.descender)
39-
# the height in 26.6 units
40-
print('Height :', font.height)
41-
# maximum horizontal cursor advance
42-
print('Max adv width :', font.max_advance_width)
43-
# same for vertical layout
44-
print('Max adv height :', font.max_advance_height)
45-
# vertical position of the underline bar
46-
print('Underline pos :', font.underline_position)
47-
# vertical thickness of the underline
48-
print('Underline thickness :', font.underline_thickness)
49-
50-
for style in ('Italic',
51-
'Bold',
52-
'Scalable',
53-
'Fixed sizes',
54-
'Fixed width',
55-
'SFNT',
56-
'Horizontal',
57-
'Vertical',
58-
'Kerning',
59-
'Fast glyphs',
60-
'Multiple masters',
61-
'Glyph names',
62-
'External stream'):
63-
bitpos = getattr(ft, style.replace(' ', '_').upper()) - 1
64-
print('%-17s:' % style, bool(font.style_flags & (1 << bitpos)))
65-
66-
print(dir(font))
67-
68-
print(font.get_kerning)
13+
from matplotlib import font_manager, _ft2
14+
15+
16+
fname = matplotlib.get_data_path() + "/fonts/ttf/DejaVuSans-Oblique.ttf"
17+
font = font_manager.get_font(fname)
18+
19+
print("Faces in file :", font.num_faces)
20+
print("Glyphs in face :", font.num_glyphs)
21+
print("Family name :", font.family_name)
22+
print("Style name :", font.style_name)
23+
print("Postscript name :", font.get_postscript_name())
24+
print("Embedded bitmap strikes:", font.num_fixed_sizes)
25+
26+
if font.face_flags & _ft2.FACE_FLAG_SCALABLE:
27+
print('Global bbox (xmin, ymin, xmax, ymax):', font.bbox)
28+
print('Font units per EM :', font.units_per_EM)
29+
print('Ascender (pixels) :', font.ascender)
30+
print('Descender (pixels) :', font.descender)
31+
print('Height (pixels) :', font.height)
32+
print('Max horizontal advance :', font.max_advance_width)
33+
print('Max vertical advance :', font.max_advance_height)
34+
print('Underline position :', font.underline_position)
35+
print('Underline thickness :', font.underline_thickness)
36+
37+
for style in ['Style flag italic',
38+
'Style flag bold']:
39+
flag = getattr(_ft2, style.replace(' ', '_').upper()) - 1
40+
print('%-26s:' % style, bool(font.style_flags & flag))
41+
42+
for style in ['Face flag scalable',
43+
'Face flag fixed sizes',
44+
'Face flag fixed width',
45+
'Face flag SFNT',
46+
'Face flag horizontal',
47+
'Face flag vertical',
48+
'Face flag kerning',
49+
'Face flag fast glyphs',
50+
'Face flag multiple masters',
51+
'Face flag glyph names',
52+
'Face flag external stream']:
53+
flag = getattr(_ft2, style.replace(' ', '_').upper())
54+
print('%-26s:' % style, bool(font.face_flags & flag))

examples/text_labels_and_annotations/font_table_ttf_sgskip.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import os
1616

1717
import matplotlib
18-
from matplotlib.ft2font import FT2Font
18+
from matplotlib import _ft2
1919
from matplotlib.font_manager import FontProperties
2020
import matplotlib.pyplot as plt
2121

@@ -35,8 +35,8 @@
3535
fontname = os.path.join(matplotlib.get_data_path(),
3636
'fonts', 'ttf', 'DejaVuSans.ttf')
3737

38-
font = FT2Font(fontname)
39-
codes = sorted(font.get_charmap().items())
38+
font = _ft2.Face(fontname)
39+
codes = sorted(font.get_charmap().items()) # FIXME
4040

4141
# a 16,16 array of character strings
4242
chars = [['' for c in range(16)] for r in range(16)]

lib/matplotlib/backends/backend_agg.py

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* alpha blending
1313
* DPI scaling properly - everything scales properly (dashes, linewidths, etc)
1414
* draw polygon
15-
* freetype2 w/ ft2font
15+
* freetype2
1616
1717
TODO:
1818
@@ -28,19 +28,15 @@
2828
import numpy as np
2929
from collections import OrderedDict
3030
from math import radians, cos, sin
31-
from matplotlib import cbook, rcParams, __version__
31+
32+
from matplotlib import (
33+
_ft2, _png, cbook, colors as mcolors, font_manager, rcParams, __version__)
3234
from matplotlib.backend_bases import (
3335
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase, cursors)
34-
from matplotlib.font_manager import findfont, get_font
35-
from matplotlib.ft2font import (LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING,
36-
LOAD_DEFAULT, LOAD_NO_AUTOHINT)
36+
from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg
3737
from matplotlib.mathtext import MathTextParser
3838
from matplotlib.path import Path
3939
from matplotlib.transforms import Bbox, BboxBase
40-
from matplotlib import colors as mcolors
41-
42-
from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg
43-
from matplotlib import _png
4440

4541
try:
4642
from PIL import Image
@@ -52,12 +48,12 @@
5248

5349
def get_hinting_flag():
5450
mapping = {
55-
True: LOAD_FORCE_AUTOHINT,
56-
False: LOAD_NO_HINTING,
57-
'either': LOAD_DEFAULT,
58-
'native': LOAD_NO_AUTOHINT,
59-
'auto': LOAD_FORCE_AUTOHINT,
60-
'none': LOAD_NO_HINTING
51+
True: _ft2.LOAD_FORCE_AUTOHINT,
52+
False: _ft2.LOAD_NO_HINTING,
53+
'either': _ft2.LOAD_DEFAULT,
54+
'native': _ft2.LOAD_NO_AUTOHINT,
55+
'auto': _ft2.LOAD_FORCE_AUTOHINT,
56+
'none': _ft2.LOAD_NO_HINTING
6157
}
6258
return mapping[rcParams['text.hinting']]
6359

@@ -110,9 +106,9 @@ def __setstate__(self, state):
110106

111107
def _get_hinting_flag(self):
112108
if rcParams['text.hinting']:
113-
return LOAD_FORCE_AUTOHINT
109+
return _ft2.LOAD_FORCE_AUTOHINT
114110
else:
115-
return LOAD_NO_HINTING
111+
return _ft2.LOAD_NO_HINTING
116112

117113
# for filtering to work with rasterization, methods needs to be wrapped.
118114
# maybe there is better way to do it.
@@ -183,7 +179,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
183179
yd = descent * cos(radians(angle))
184180
x = np.round(x + ox + xd)
185181
y = np.round(y - oy + yd)
186-
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
182+
self._renderer.draw_text_image(font_image, x, y, angle, gc)
187183

188184
def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
189185
"""
@@ -197,24 +193,15 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
197193

198194
if font is None:
199195
return None
200-
if len(s) == 1 and ord(s) > 127:
201-
font.load_char(ord(s), flags=flags)
202-
else:
203-
# We pass '0' for angle here, since it will be rotated (in raster
204-
# space) in the following call to draw_text_image).
205-
font.set_text(s, 0, flags=flags)
206-
font.draw_glyphs_to_bitmap(antialiased=rcParams['text.antialiased'])
207-
d = font.get_descent() / 64.0
196+
layout = _ft2.Layout.simple(s, font, flags)
197+
d = -np.floor(layout.yMin)
208198
# The descent needs to be adjusted for the angle
209-
xo, yo = font.get_bitmap_offset()
210-
xo /= 64.0
211-
yo /= 64.0
212199
xd = -d * sin(radians(angle))
213200
yd = d * cos(radians(angle))
214201

215-
#print x, y, int(x), int(y), s
216202
self._renderer.draw_text_image(
217-
font, np.round(x - xd + xo), np.round(y + yd + yo) + 1, angle, gc)
203+
layout.render(), # FIXME Antialiasing.
204+
np.round(x - xd), np.round(y + yd), angle, gc)
218205

219206
def get_text_width_height_descent(self, s, prop, ismath):
220207
"""
@@ -238,13 +225,10 @@ def get_text_width_height_descent(self, s, prop, ismath):
238225

239226
flags = get_hinting_flag()
240227
font = self._get_agg_font(prop)
241-
font.set_text(s, 0.0, flags=flags)
242-
w, h = font.get_width_height() # width and height of unrotated string
243-
d = font.get_descent()
244-
w /= 64.0 # convert from subpixels
245-
h /= 64.0
246-
d /= 64.0
247-
return w, h, d
228+
layout = _ft2.Layout.simple(s, font, flags)
229+
return (layout.xMax - layout.xMin,
230+
layout.yMax - layout.yMin,
231+
-layout.yMin)
248232

249233
def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
250234
# todo, handle props, angle, origins
@@ -271,13 +255,10 @@ def _get_agg_font(self, prop):
271255
"""
272256
Get the font for text instance t, cacheing for efficiency
273257
"""
274-
fname = findfont(prop)
275-
font = get_font(fname)
276-
277-
font.clear()
258+
fname = font_manager.findfont(prop)
259+
font = font_manager.get_font(fname)
278260
size = prop.get_size_in_points()
279-
font.set_size(size, self.dpi)
280-
261+
font.set_char_size(size, self.dpi)
281262
return font
282263

283264
def points_to_pixels(self, points):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy