Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/api/next_api_changes/deprecations/31521-ES.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Font hinting factor is deprecated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Due to internal changes to support complex text rendering, the hinting factor on fonts is
no longer used. Setting the ``text.hinting_factor`` rcParam to any value other than None
is deprecated, and the rcParam will be removed in the future. Likewise, passing the
``hinting_factor`` argument to the `.FT2Font` constructor is deprecated.
4 changes: 2 additions & 2 deletions lib/matplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,8 +779,8 @@ def __setitem__(self, key, val):
cval = valid_key(val)
except ValueError as ve:
raise ValueError(f"Key {key}: {ve}") from None
if key == "text.kerning_factor" and cval is not None:
_api.warn_deprecated("3.11", name="text.kerning_factor", obj_type="rcParam")
if key in {"text.hinting_factor", "text.kerning_factor"} and cval is not None:
_api.warn_deprecated("3.11", name=key, obj_type="rcParam")
self._set(key, cval)

def __getitem__(self, key):
Expand Down
4 changes: 1 addition & 3 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,9 @@ def _draw_text_glyphs_and_boxes(self, gc, x, y, angle, glyphs, boxes):
load_flags = get_hinting_flag()
for font, size, glyph_index, slant, extend, dx, dy in glyphs: # dy is upwards.
font.set_size(size, self.dpi)
hf = font._hinting_factor
font._set_transform(
(0x10000 * np.array([[cos, -sin], [sin, cos]])
@ [[extend, extend * slant], [0, 1]]
@ [[1 / hf, 0], [0, 1]]).round().astype(int),
@ [[extend, extend * slant], [0, 1]]).round().astype(int),
[round(0x40 * (x + dx * cos - dy * sin)),
# FreeType's y is upwards.
round(0x40 * (self.height - y + dx * sin + dy * cos))]
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ def _flush(self):


def _get_pdf_charprocs(font_path, glyph_indices):
font = get_font(font_path, hinting_factor=1)
font = get_font(font_path)
conv = 1000 / font.units_per_EM # Conversion to PS units (1/1000's).
procs = {}
for glyph_index in glyph_indices:
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_ps.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def _font_to_ps_type3(font_path, subset_index, glyph_indices):
The string representation of a Type 3 font, which can be included
verbatim into a PostScript file.
"""
font = get_font(font_path, hinting_factor=1)
font = get_font(font_path)

preamble = """\
%!PS-Adobe-3.0 Resource-Font
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/dviread.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ def get_metrics(self, idx):

class TtfMetrics:
def __init__(self, filename):
self._face = font_manager.get_font(filename, hinting_factor=1)
self._face = font_manager.get_font(filename)

def get_metrics(self, idx):
# _mul1220 uses a truncating bitshift for compatibility with dvitype.
Expand Down
15 changes: 6 additions & 9 deletions lib/matplotlib/font_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1731,11 +1731,11 @@ def is_opentype_cff_font(filename):


@lru_cache(64)
def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id,
def _get_font(font_filepaths, *, _kerning_factor, thread_id,
enable_last_resort):
(first_fontpath, first_fontindex), *rest = font_filepaths
fallback_list = [
ft2font.FT2Font(fpath, hinting_factor, face_index=index,
ft2font.FT2Font(fpath, face_index=index,
_kerning_factor=_kerning_factor)
for fpath, index in rest
]
Expand All @@ -1749,12 +1749,12 @@ def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id,
# already in the list.
if enable_last_resort:
fallback_list.append(
ft2font.FT2Font(last_resort_path, hinting_factor,
ft2font.FT2Font(last_resort_path,
_kerning_factor=_kerning_factor,
_warn_if_used=True))
last_resort_index = len(fallback_list)
font = ft2font.FT2Font(
first_fontpath, hinting_factor, face_index=first_fontindex,
first_fontpath, face_index=first_fontindex,
_fallback_list=fallback_list,
_kerning_factor=_kerning_factor
)
Expand Down Expand Up @@ -1783,6 +1783,7 @@ def _cached_realpath(path):
return os.path.realpath(path)


@_api.delete_parameter('3.11', 'hinting_factor')
def get_font(font_filepaths, hinting_factor=None):
"""
Get an `.ft2font.FT2Font` object given a list of file paths.
Expand Down Expand Up @@ -1816,20 +1817,16 @@ def get_font(font_filepaths, hinting_factor=None):
if isinstance(fname, FontPath) else (_cached_realpath(fname), 0)
for fname in font_filepaths)

hinting_factor = mpl._val_or_rc(hinting_factor, 'text.hinting_factor')

font = _get_font(
# must be a tuple to be cached
paths,
hinting_factor,
_kerning_factor=mpl.rcParams['text.kerning_factor'],
# also key on the thread ID to prevent segfaults with multi-threading
thread_id=threading.get_ident(),
enable_last_resort=mpl.rcParams['font.enable_last_resort'],
)
# Ensure the transform is always consistent.
font._set_transform([[round(0x10000 / font._hinting_factor), 0], [0, 0x10000]],
[0, 0])
font._set_transform([[0x10000, 0], [0, 0x10000]], [0, 0])
return font


Expand Down
1 change: 0 additions & 1 deletion lib/matplotlib/font_manager.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ class FontManager:
def is_opentype_cff_font(filename: str) -> bool: ...
def get_font(
font_filepaths: Iterable[str | bytes | os.PathLike | FontPath] | str | bytes | os.PathLike | FontPath,
hinting_factor: int | None = ...,
) -> ft2font.FT2Font: ...

fontManager: FontManager
Expand Down
1 change: 0 additions & 1 deletion lib/matplotlib/ft2font.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ class FT2Font(Buffer):
def __init__(
self,
filename: str | bytes | PathLike | BinaryIO,
hinting_factor: int = ...,
*,
face_index: int = ...,
_fallback_list: list[FT2Font] | None = ...,
Expand Down
4 changes: 1 addition & 3 deletions lib/matplotlib/mpl-data/matplotlibrc
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,7 @@
## - no_hinting: Disable hinting. ("none" is a synonym.)
#text.hinting: default

#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.hinting_factor: None # This setting does nothing and is deprecated.
#text.kerning_factor: None # Specifies the scaling factor for kerning values. Values
# other than 0, 6, or None have no defined meaning.
# This setting is deprecated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ ytick.alignment: center_baseline
hatch.color: edge

text.hinting: default
text.hinting_factor: 1
2 changes: 0 additions & 2 deletions lib/matplotlib/mpl-data/stylelib/bmh.mplstyle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ patch.facecolor: blue
patch.edgecolor: eeeeee
patch.antialiased: True

text.hinting_factor : 8

mathtext.fontset : cm

axes.facecolor: eeeeee
Expand Down
3 changes: 0 additions & 3 deletions lib/matplotlib/mpl-data/stylelib/classic.mplstyle
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,6 @@ text.hinting : auto # May be one of the following:
# or the autohinter if none is available.
# For backward compatibility, this value may also be
# True === 'auto' or False === 'none'.
text.hinting_factor : 8 # 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.antialiased : True # If True (default), the text will be antialiased.
# This only affects the Agg backend.
Expand Down
10 changes: 4 additions & 6 deletions lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ def _convert_validator_spec(key, conv):
"text.latex.preamble": validate_string,
"text.hinting": ["default", "no_autohint", "force_autohint",
"no_hinting", "auto", "native", "either", "none"],
"text.hinting_factor": validate_int,
"text.hinting_factor": validate_int_or_None,
"text.kerning_factor": validate_int_or_None,
"text.antialiased": validate_bool,
"text.parse_math": validate_bool,
Expand Down Expand Up @@ -1875,11 +1875,9 @@ class _Subsection:
),
_Param(
"text.hinting_factor",
default=1,
validator=validate_int,
description="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."
default=None,
validator=validate_int_or_None,
description="[DEPRECATED] This setting has no effect."
),
_Param(
"text.kerning_factor",
Expand Down
1 change: 0 additions & 1 deletion lib/matplotlib/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
def set_font_settings_for_testing():
mpl.rcParams['font.family'] = 'DejaVu Sans'
mpl.rcParams['text.hinting'] = 'default'
mpl.rcParams['text.hinting_factor'] = 1


def set_reproducibility_for_testing():
Expand Down
20 changes: 0 additions & 20 deletions lib/matplotlib/tests/test_font_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import sys
import warnings

import numpy as np
import pytest

from unittest.mock import MagicMock, patch
Expand Down Expand Up @@ -118,25 +117,6 @@ def test_get_fontconfig_fonts():
assert len(_get_fontconfig_fonts()) > 1


@pytest.mark.parametrize('factor', [2, 4, 6, 8])
def test_hinting_factor(factor):
font = findfont(FontProperties(family=["sans-serif"]))

font1 = get_font(font, hinting_factor=1)
font1.clear()
font1.set_size(12, 100)
font1.set_text('abc')
expected = font1.get_width_height()

hinted_font = get_font(font, hinting_factor=factor)
hinted_font.clear()
hinted_font.set_size(12, 100)
hinted_font.set_text('abc')
# Check that hinting only changes text layout by a small (10%) amount.
np.testing.assert_allclose(hinted_font.get_width_height(), expected,
rtol=0.1)


def test_utf16m_sfnt():
try:
# seguisbi = Microsoft Segoe UI Semibold
Expand Down
24 changes: 14 additions & 10 deletions lib/matplotlib/tests/test_ft2font.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ def test_ft2font_invalid_args(tmp_path):
# hinting_factor argument.
with pytest.raises(TypeError, match='incompatible constructor arguments'):
ft2font.FT2Font(file, 1.3)
with pytest.raises(ValueError, match='hinting_factor must be greater than 0'):
with pytest.warns(mpl.MatplotlibDeprecationWarning,
match='text.hinting_factor rcParam was deprecated .+ 3.11'):
mpl.rcParams['text.hinting_factor'] = 8
with pytest.warns(mpl.MatplotlibDeprecationWarning,
match='The hinting_factor parameter was deprecated'):
ft2font.FT2Font(file, 0)

with pytest.raises(TypeError, match='incompatible constructor arguments'):
Expand Down Expand Up @@ -236,7 +240,7 @@ def test_ft2font_clear():

def test_ft2font_set_size():
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
font.set_text('ABabCDcd')
orig = font.get_width_height()
Expand Down Expand Up @@ -791,7 +795,7 @@ def test_ft2font_get_sfnt_table(font_name, header):
def test_ft2font_get_kerning(left, right, unscaled, unfitted, default):
file = fm.findfont('DejaVu Sans')
# With unscaled, these settings should produce exact values found in FontForge.
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(100, 100)
assert font.get_kerning(font.get_char_index(ord(left)),
font.get_char_index(ord(right)),
Expand Down Expand Up @@ -830,7 +834,7 @@ def test_ft2font_get_kerning(left, right, unscaled, unfitted, default):

def test_ft2font_set_text():
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
xys = font.set_text('')
np.testing.assert_array_equal(xys, np.empty((0, 2)))
Expand Down Expand Up @@ -867,23 +871,23 @@ def test_ft2font_set_text():
)
def test_ft2font_language_invalid(input):
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
with pytest.raises(TypeError):
font.set_text('foo', language=input)


def test_ft2font_language():
# This is just a smoke test.
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_text('foo')
font.set_text('foo', language='en')
font.set_text('foo', language=[('en', 1, 2)])


def test_ft2font_loading():
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
for glyph in [font.load_char(ord('M')),
font.load_glyph(font.get_char_index(ord('M')))]:
Expand Down Expand Up @@ -924,13 +928,13 @@ def test_ft2font_drawing():
])
expected *= 255
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
font.set_text('M')
font.draw_glyphs_to_bitmap(antialiased=False)
image = font.get_image()
np.testing.assert_array_equal(image, expected)
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
glyph = font.load_char(ord('M'))
image = np.zeros(expected.shape, np.uint8)
Expand All @@ -940,7 +944,7 @@ def test_ft2font_drawing():

def test_ft2font_get_path():
file = fm.findfont('DejaVu Sans')
font = ft2font.FT2Font(file, hinting_factor=1)
font = ft2font.FT2Font(file)
font.set_size(12, 72)
vertices, codes = font.get_path()
assert vertices.shape == (0, 2)
Expand Down
14 changes: 0 additions & 14 deletions lib/matplotlib/tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,20 +591,6 @@ def test_nonfinite_pos():
fig.canvas.draw()


def test_hinting_factor_backends():
plt.rcParams['text.hinting_factor'] = 1
fig = plt.figure()
t = fig.text(0.5, 0.5, 'some text')

fig.savefig(io.BytesIO(), format='svg')
expected = t.get_window_extent().intervalx

fig.savefig(io.BytesIO(), format='png')
# Backends should apply hinting_factor consistently (within 10%).
np.testing.assert_allclose(t.get_window_extent().intervalx, expected,
rtol=0.1)


@needs_usetex
def test_usetex_is_copied():
# Indirectly tests that update_from (which is used to copy tick label
Expand Down
16 changes: 5 additions & 11 deletions src/ft2font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,8 @@ FT2Font::get_path(std::vector<double> &vertices, std::vector<unsigned char> &cod
codes.push_back(CLOSEPOLY);
}

FT2Font::FT2Font(long hinting_factor_, std::vector<FT2Font *> &fallback_list,
bool warn_if_used)
FT2Font::FT2Font(std::vector<FT2Font *> &fallback_list, bool warn_if_used)
: warn_if_used(warn_if_used), image({1, 1}), face(nullptr), fallbacks(fallback_list),
hinting_factor(hinting_factor_),
// set default kerning factor to 0, i.e., no kerning manipulation
kerning_factor(0)
{
Expand Down Expand Up @@ -274,8 +272,8 @@ void FT2Font::set_size(double ptsize, double dpi)
{
FT_CHECK(
FT_Set_Char_Size,
face, (FT_F26Dot6)(ptsize * 64), 0, (FT_UInt)(dpi * hinting_factor), (FT_UInt)dpi);
FT_Matrix transform = { 65536 / hinting_factor, 0, 0, 65536 };
face, (FT_F26Dot6)(ptsize * 64), 0, (FT_UInt)dpi, (FT_UInt)dpi);
FT_Matrix transform = { 65536, 0, 0, 65536 };
FT_Set_Transform(face, &transform, nullptr);

for (auto & fallback : fallbacks) {
Expand Down Expand Up @@ -315,7 +313,7 @@ int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_Kerning_Mode mode)

FT_Vector delta;
if (!FT_Get_Kerning(face, left, right, mode, &delta)) {
return (int)(delta.x) / (hinting_factor << kerning_factor);
return (int)(delta.x) / (1 << kerning_factor);
} else {
return 0;
}
Expand Down Expand Up @@ -527,11 +525,7 @@ void FT2Font::set_text(
bbox.yMin = std::min(bbox.yMin, glyph_bbox.yMin);
bbox.yMax = std::max(bbox.yMax, glyph_bbox.yMax);

if ((flags & FT_LOAD_NO_HINTING) != 0) {
pen.x += rglyph.x_advance - rglyph.x_offset;
} else {
pen.x += hinting_factor * rglyph.x_advance - rglyph.x_offset;
}
pen.x += rglyph.x_advance - rglyph.x_offset;
pen.y += rglyph.y_advance - rglyph.y_offset;

glyphs.push_back(thisGlyph);
Expand Down
Loading
Loading