Skip to content

Commit 8caff88

Browse files
anntzerQuLogic
authored andcommitted
Remove ttconv backwards-compatibility code
1 parent cf6069a commit 8caff88

File tree

2 files changed

+25
-60
lines changed

2 files changed

+25
-60
lines changed

lib/matplotlib/backends/backend_pdf.py

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -617,40 +617,18 @@ def _get_pdf_charprocs(font_path, glyph_ids):
617617
procs = {}
618618
for glyph_id in glyph_ids:
619619
g = font.load_glyph(glyph_id, LoadFlags.NO_SCALE)
620-
# NOTE: We should be using round(), but instead use
621-
# "(x+.5).astype(int)" to keep backcompat with the old ttconv code
622-
# (this is different for negative x's).
623-
d1 = (np.array([g.horiAdvance, 0, *g.bbox]) * conv + .5).astype(int)
620+
d1 = [
621+
round(g.horiAdvance * conv), 0,
622+
# Round bbox corners *outwards*, so that they indeed bound the glyph.
623+
math.floor(g.bbox[0] * conv), math.floor(g.bbox[1] * conv),
624+
math.ceil(g.bbox[2] * conv), math.ceil(g.bbox[3] * conv),
625+
]
624626
v, c = font.get_path()
625-
v = (v * 64).astype(int) # Back to TrueType's internal units (1/64's).
626-
# Backcompat with old ttconv code: control points between two quads are
627-
# omitted if they are exactly at the midpoint between the control of
628-
# the quad before and the quad after, but ttconv used to interpolate
629-
# *after* conversion to PS units, causing floating point errors. Here
630-
# we reproduce ttconv's logic, detecting these "implicit" points and
631-
# re-interpolating them. Note that occasionally (e.g. with DejaVu Sans
632-
# glyph "0") a point detected as "implicit" is actually explicit, and
633-
# will thus be shifted by 1.
634-
quads, = np.nonzero(c == 3)
635-
quads_on = quads[1::2]
636-
quads_mid_on = np.array(
637-
sorted({*quads_on} & {*(quads - 1)} & {*(quads + 1)}), int)
638-
implicit = quads_mid_on[
639-
(v[quads_mid_on] # As above, use astype(int), not // division
640-
== ((v[quads_mid_on - 1] + v[quads_mid_on + 1]) / 2).astype(int))
641-
.all(axis=1)]
642-
if (font.postscript_name, glyph_id) in [
643-
("DejaVuSerif-Italic", 77), # j
644-
("DejaVuSerif-Italic", 135), # \AA
645-
]:
646-
v[:, 0] -= 1 # Hard-coded backcompat (FreeType shifts glyph by 1).
647-
v = (v * conv + .5).astype(int) # As above re: truncation vs rounding.
648-
v[implicit] = (( # Fix implicit points; again, truncate.
649-
(v[implicit - 1] + v[implicit + 1]) / 2).astype(int))
627+
v = (v * 64 * conv).round() # Back to TrueType's internal units (1/64's).
650628
procs[font.get_glyph_name(glyph_id)] = (
651629
" ".join(map(str, d1)).encode("ascii") + b" d1\n"
652630
+ _path.convert_to_string(
653-
Path(v, c), None, None, False, None, -1,
631+
Path(v, c), None, None, False, None, 0,
654632
# no code for quad Beziers triggers auto-conversion to cubics.
655633
[b"m", b"l", b"", b"c", b"h"], True)
656634
+ b"f")

src/_path.h

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,38 +1066,25 @@ void quad2cubic(double x0, double y0,
10661066
void __add_number(double val, char format_code, int precision,
10671067
std::string& buffer)
10681068
{
1069-
if (precision == -1) {
1070-
// Special-case for compat with old ttconv code, which *truncated*
1071-
// values with a cast to int instead of rounding them as printf
1072-
// would do. The only point where non-integer values arise is from
1073-
// quad2cubic conversion (as we already perform a first truncation
1074-
// on Python's side), which can introduce additional floating point
1075-
// error (by adding 2/3 delta-x and then 1/3 delta-x), so compensate by
1076-
// first rounding to the closest 1/3 and then truncating.
1077-
char str[255];
1078-
PyOS_snprintf(str, 255, "%d", (int)(round(val * 3)) / 3);
1079-
buffer += str;
1080-
} else {
1081-
char *str = PyOS_double_to_string(
1082-
val, format_code, precision, Py_DTSF_ADD_DOT_0, nullptr);
1083-
// Delete trailing zeros and decimal point
1084-
char *c = str + strlen(str) - 1; // Start at last character.
1085-
// Rewind through all the zeros and, if present, the trailing decimal
1086-
// point. Py_DTSF_ADD_DOT_0 ensures we won't go past the start of str.
1087-
while (*c == '0') {
1088-
--c;
1089-
}
1090-
if (*c == '.') {
1091-
--c;
1092-
}
1093-
try {
1094-
buffer.append(str, c + 1);
1095-
} catch (std::bad_alloc& e) {
1096-
PyMem_Free(str);
1097-
throw e;
1098-
}
1069+
char *str = PyOS_double_to_string(
1070+
val, format_code, precision, Py_DTSF_ADD_DOT_0, nullptr);
1071+
// Delete trailing zeros and decimal point
1072+
char *c = str + strlen(str) - 1; // Start at last character.
1073+
// Rewind through all the zeros and, if present, the trailing decimal
1074+
// point. Py_DTSF_ADD_DOT_0 ensures we won't go past the start of str.
1075+
while (*c == '0') {
1076+
--c;
1077+
}
1078+
if (*c == '.') {
1079+
--c;
1080+
}
1081+
try {
1082+
buffer.append(str, c + 1);
1083+
} catch (std::bad_alloc& e) {
10991084
PyMem_Free(str);
1085+
throw e;
11001086
}
1087+
PyMem_Free(str);
11011088
}
11021089

11031090

0 commit comments

Comments
 (0)