8000 Update FreeType to 2.13.3 by QuLogic · Pull Request #29816 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Update FreeType to 2.13.3 #29816

New issue 8000

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ repos:
- id: check-docstring-first
exclude: lib/matplotlib/typing.py # docstring used for attribute flagged by check
- id: end-of-file-fixer
exclude_types: [svg]
exclude_types: [diff, svg]
- id: mixed-line-ending
- id: name-tests-test
args: ["--pytest-test-first"]
- id: no-commit-to-branch # Default is master and main.
- id: trailing-whitespace
exclude_types: [svg]
exclude_types: [diff, svg]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.15.0
hooks:
Expand Down
13 changes: 11 additions & 2 deletions extern/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@ else
# must match the value in `lib/matplotlib.__init__.py`. Also update the docs
# in `docs/devel/dependencies.rst`. Bump the cache key in
# `.circleci/config.yml` when changing requirements.
LOCAL_FREETYPE_VERSION = '2.6.1'
LOCAL_FREETYPE_VERSION = '2.13.3'

freetype_proj = subproject(
f'freetype-@LOCAL_FREETYPE_VERSION@',
default_options: ['default_library=static'])
default_options: [
'default_library=static',
'brotli=disabled',
'bzip2=disabled',
'harfbuzz=disabled',
'mmap=auto',
'png=disabled',
'tests=disabled',
'zlib=internal',
])
freetype_dep = freetype_proj.get_variable('freetype_dep')
endif

Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ def _val_or_rc(val, rc_name):
def _init_tests():
# The version of FreeType to install locally for running the tests. This must match
# the value in `meson.build`.
LOCAL_FREETYPE_VERSION = '2.6.1'
LOCAL_FREETYPE_VERSION = '2.13.3'

from matplotlib import ft2font
if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
Expand Down
72 changes: 45 additions & 27 deletions lib/matplotlib/_mathtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import enum
import functools
import logging
import math
import os
import re
import types
Expand Down Expand Up @@ -128,47 +129,62 @@
def to_vector(self) -> VectorParse:
w, h, d = map(
np.ceil, [self.box.width, self.box.height, self.box.depth])
gs = [(info.font, info.fontsize, info.num, ox, h - oy + info.offset)
gs = [(info.font, info.fontsize, info.num, ox, -oy + info.offset)
for ox, oy, info in self.glyphs]
rs = [(x1, h - y2, x2 - x1, y2 - y1)
rs = [(x1, -y2, x2 - x1, y2 - y1)
for x1, y1, x2, y2 in self.rects]
return VectorParse(w, h + d, d, gs, rs)

def to_raster(self, *, antialiased: bool) -> RasterParse:
# Metrics y's and mathtext y's are oriented in opposite directions,
# hence the switch between ymin and ymax.
xmin = min([*[ox + info.metrics.xmin for ox, oy, info in self.glyphs],
*[x1 for x1, y1, x2, y2 in self.rects], 0]) - 1
ymin = min([*[oy - info.metrics.ymax for ox, oy, info in self.glyphs],
*[y1 for x1, y1, x2, y2 in self.rects], 0]) - 1
xmax = max([*[ox + info.metrics.xmax for ox, oy, info in self.glyphs],
*[x2 for x1, y1, x2, y2 in self.rects], 0]) + 1
ymax = max([*[oy - info.metrics.ymin for ox, oy, info in self.glyphs],
*[y2 for x1, y1, x2, y2 in self.rects], 0]) + 1
xmin0 = min([*[ox + info.metrics.xmin for ox, oy, info in self.glyphs],
*[x1 for x1, y1, x2, y2 in self.rects], 0])
ymin0 = min([*[oy - max(info.metrics.ymax, info.metrics.iceberg)
for ox, oy, info in self.glyphs],
*[y1 for x1, y1, x2, y2 in self.rects], 0])
xmax0 = max([*[ox + info.metrics.xmax for ox, oy, info in self.glyphs],
*[x2 for x1, y1, x2, y2 in self.rects], 0])
ymax0 = max([*[oy - info.metrics.ymin for ox, oy, info in self.glyphs],
*[y2 for x1, y1, x2, y2 in self.rects], 0])
# Rasterizing can leak into the neighboring pixel, hence the +/-1; it
# will be cropped at the end.
xmin = math.floor(xmin0 - 1)
ymin = math.floor(ymin0 - 1)
xmax = math.ceil(xmax0 + 1)
ymax = math.ceil(ymax0 + 1)
w = xmax - xmin
h = ymax - ymin - self.box.depth
d = ymax - ymin - self.box.height
image = FT2Image(int(np.ceil(w)), int(np.ceil(h + max(d, 0))))
h = max(-ymin, 0)
d = max(ymax, 0)
image = FT2Image(w, h + d)

# Ideally, we could just use self.glyphs and self.rects here, shifting
# their coordinates by (-xmin, -ymin), but this yields slightly
# different results due to floating point slop; shipping twice is the
# old approach and keeps baseline images backcompat.
shifted = ship(self.box, (-xmin, -ymin))

for ox, oy, info in shifted.glyphs:
for ox, oy, info in self.glyphs:
ox -= xmin
oy -= (-h + info.offset)
info.font.draw_glyph_to_bitmap(
image, int(ox), int(oy - info.metrics.iceberg), info.glyph,
antialiased=antialiased)
for x1, y1, x2, y2 in shifted.rects:
image, ox, oy, info.glyph, antialiased=antialiased)

Check failure on line 165 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Argument 2 to "draw_glyph_to_bitmap" of "FT2Font" has incompatible type "float"; expected "int" [arg-type] Raw Output: lib/matplotlib/_mathtext.py:165: error: Argument 2 to "draw_glyph_to_bitmap" of "FT2Font" has incompatible type "float"; expected "int" [arg-type]

Check failure on line 165 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Argument 3 to "draw_glyph_to_bitmap" of "FT2Font" has incompatible type "float"; expected "int" [arg-type] Raw Output: lib/matplotlib/_mathtext.py:165: error: Argument 3 to "draw_glyph_to_bitmap" of "FT2Font" has incompatible type "float"; expected "int" [arg-type]
for x1, y1, x2, y2 in self.rects:
x1 -= xmin
x2 -= xmin
y1 -= -h
y2 -= -h
height = max(int(y2 - y1) - 1, 0)
if height == 0:
center = (y2 + y1) / 2
y = int(center - (height + 1) / 2)
else:
y = int(y1)
image.draw_rect_filled(int(x1), y, int(np.ceil(x2)), y + height)
return RasterParse(0, 0, w, h + d, d, image)
image.draw_rect_filled(int(x1), y, math.ceil(x2), y + height)

image = np.asarray(image)

Check failure on line 179 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "FT2Image") [assignment] Raw Output: lib/matplotlib/_mathtext.py:179: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "FT2Image") [assignment]
while h and (image[0] == 0).all():

Check failure on line 180 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Value of type "FT2Image" is not indexable [index] Raw Output: lib/matplotlib/_mathtext.py:180: error: Value of type "FT2Image" is not indexable [index]
image = image[1:]

Check failure on line 181 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Value of type "FT2Image" is not indexable [index] Raw Output: lib/matplotlib/_mathtext.py:181: error: Value of type "FT2Image" is not indexable [index]
h -= 1
while d and (image[-1] == 0).all():

Check failure on line 183 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Value of type "FT2Image" is not indexable [index] Raw Output: lib/matplotlib/_mathtext.py:183: error: Value of type "FT2Image" is not indexable [index]
image = image[:-1]

Check failure on line 184 in lib/matplotlib/_mathtext.py

View workflow job for this annotation

GitHub Actions / mypy

[mypy] reported by reviewdog 🐶 Value of type "FT2Image" is not indexable [index] Raw Output: lib/matplotlib/_mathtext.py:184: error: Value of type "FT2Image" is not indexable [index]
d -= 1
return RasterParse(
xmin - xmin0, d - ymax0, xmax0 - xmin0, ymax0 - ymin0, d, image)


class FontMetrics(NamedTuple):
Expand Down Expand Up @@ -421,7 +437,9 @@
info1 = self._get_info(font1, fontclass1, sym1, fontsize1, dpi)
info2 = self._get_info(font2, fontclass2, sym2, fontsize2, dpi)
font = info1.font
return font.get_kerning(info1.num, info2.num, Kerning.DEFAULT) / 64
return font.get_kerning(font.get_char_index(info1.num),
font.get_char_index(info2.num),
Kerning.DEFAULT) / 64
return super().get_kern(font1, fontclass1, sym1, fontsize1,
font2, fontclass2, sym2, fontsize2, dpi)

Expand Down Expand Up @@ -1602,7 +1620,7 @@
cur_v = 0.
cur_h = 0.
off_h = ox
off_v = oy + box.height
off_v = oy
output = Output(box)

def clamp(value: float) -> float:
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
yd = descent * cos(radians(angle))
x = round(x + ox + xd)
y = round(y - oy + yd)
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
self._renderer.draw_text_image(font_image, x, y, angle, gc)

def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
# docstring inherited
Expand Down
38 changes: 8 additions & 30 deletions lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,40 +617,18 @@ def _get_pdf_charprocs(font_path, glyph_ids):
procs = {}
for glyph_id in glyph_ids:
g = font.load_glyph(glyph_id, LoadFlags.NO_SCALE)
# NOTE: We should be using round(), but instead use
# "(x+.5).astype(int)" to keep backcompat with the old ttconv code
# (this is different for negative x's).
d1 = (np.array([g.horiAdvance, 0, *g.bbox]) * conv + .5).astype(int)
d1 = [
round(g.horiAdvance * conv), 0,
# Round bbox corners *outwards*, so that they indeed bound th glyph.
math.floor(g.bbox[0] * conv), math.floor(g.bbox[1] * conv),
math.ceil(g.bbox[2] * conv), math.ceil(g.bbox[3] * conv),
]
v, c = font.get_path()
v = (v * 64).astype(int) # Back to TrueType's internal units (1/64's).
# Backcompat with old ttconv code: control points between two quads are
# omitted if they are exactly at the midpoint between the control of
# the quad before and the quad after, but ttconv used to interpolate
# *after* conversion to PS units, causing floating point errors. Here
# we reproduce ttconv's logic, detecting these "implicit" points and
# re-interpolating them. Note that occasionally (e.g. with DejaVu Sans
# glyph "0") a point detected as "implicit" is actually explicit, and
# will thus be shifted by 1.
quads, = np.nonzero(c == 3)
quads_on = quads[1::2]
quads_mid_on = np.array(
sorted({*quads_on} & {*(quads - 1)} & {*(quads + 1)}), int)
implicit = quads_mid_on[
(v[quads_mid_on] # As above, use astype(int), not // division
== ((v[quads_mid_on - 1] + v[quads_mid_on + 1]) / 2).astype(int))
.all(axis=1)]
if (font.postscript_name, glyph_id) in [
("DejaVuSerif-Italic", 77), # j
("DejaVuSerif-Italic", 135), # \AA
]:
v[:, 0] -= 1 # Hard-coded backcompat (FreeType shifts glyph by 1).
v = (v * conv + .5).astype(int) # As above re: truncation vs rounding.
v[implicit] = (( # Fix implicit points; again, truncate.
(v[implicit - 1] + v[implicit + 1]) / 2).astype(int))
v = (v * 64 * conv).round() # Back to TrueType's internal units (1/64's).
procs[font.get_glyph_name(glyph_id)] = (
" ".join(map(str, d1)).encode("ascii") + b" d1\n"
+ _path.convert_to_string(
Path(v, c), None, None, False, None, -1,
Path(v, c), None, None, False, None, 0,
# no code for quad Beziers triggers auto-conversion to cubics.
[b"m", b"l", b"", b"c", b"h"], True)
+ b"f")
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/mpl-data/matplotlibrc
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,9 @@
## ("native" is a synonym.)
## - force_autohint: Use FreeType's auto-hinter. ("auto" is a synonym.)
## - no_hinting: Disable hinting. ("none" is a synonym.)
#text.hinting: force_autohint
#text.hinting: default

#text.hinting_factor: 8 # Specifies the amount of softness for hinting in the
#text.hinting_factor: 1 # Specifies the amount of softness for hinting in the
# horizontal direction. A value of 1 will hint to full
# pixels. A value of 2 will hint to half pixels etc.
#text.kerning_factor: 0 # Specifies the scaling factor for kerning values. This
Expand Down
5 changes: 3 additions & 2 deletions lib/matplotlib/mpl-data/stylelib/_classic_test_patch.mplstyle
10000
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# This patch should go on top of the "classic" style and exists solely to avoid
# changing baseline images.

text.kerning_factor : 6

ytick.alignment: center_baseline

hatch.color: edge

text.hinting: default
text.hinting_factor: 1
8 changes: 6 additions & 2 deletions lib/matplotlib/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@

def set_font_settings_for_testing():
mpl.rcParams['font.family'] = 'DejaVu Sans'
mpl.rcParams['text.hinting'] = 'none'
mpl.rcParams['text.hinting_factor'] = 8
if getattr(mpl, '_called_from_pytest', False):
mpl.rcParams['text.hinting'] = 'default'
mpl.rcParams['text.hinting_factor'] = 1
else:
mpl.rcParams['text.hinting'] = 'none'
mpl.rcParams['text.hinting_factor'] = 8

Check warning on line 27 in lib/matplotlib/testing/__init__.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/testing/__init__.py#L26-L27

Added lines #L26 - L27 were not covered by tests


def set_reproducibility_for_testing():
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_baseline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/bxp_rangewhis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/canonical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/extent_units.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/fill_units.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hexbin_log.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hist_density.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hist_offset.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/hlines_basic.png
10000
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/imshow_clip.pdf
Binary file not shown.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/imshow_clip.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/markevery.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/pie_default.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/rc_grid.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/rc_spines.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/single_point.png
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/symlog.pdf
Binary file not shown.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/vlines_basic.png
Binary file modified lib/matplotlib/tests/baseline_images/test_backend_pdf/kerning.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading
0