From 1ec8e76bcf9aa9ec31718c9a2bb80f89219383e4 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 11 Dec 2023 11:28:34 +0800 Subject: [PATCH] Correct implementation of UTP * src/sfnt.c (sfnt_interpret_utp): Derive which flags to reset from the freedom vector. --- src/sfnt.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/sfnt.c b/src/sfnt.c index 44906b12ce9..f9ffc86da58 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -7450,6 +7450,8 @@ static void sfnt_interpret_utp (struct sfnt_interpreter *interpreter, uint32_t p) { + unsigned char mask; + if (!interpreter->state.zp0) { if (p >= interpreter->twilight_zone_size) @@ -7463,7 +7465,31 @@ sfnt_interpret_utp (struct sfnt_interpreter *interpreter, || p >= interpreter->glyph_zone->num_points) TRAP ("UTP[] p lies outside glyph zone"); - interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X; + /* The flags unset by UTP are subject to which axes in the freedom + vector are significant, as stated in the TrueType reference + manual by this needless mouthful: + + A point may be touched in the x-direction, the y-direction, or + in both the x and y-directions. The position of the freedom + vector determines whether the point is untouched in the + x-direction, the y-direction, or both. If the vector is set to + the x-axis, the point will be untouched in the x-direction. If + the vector is set to the y-axis, the point will be untouched in + the y-direction. Otherwise the point will be untouched in both + directions. + + A points that is marked as untouched will be moved by an IUP[] + instruction even if the point was previously touched. */ + + mask = 0xff; + + if (interpreter->state.freedom_vector.x) + mask &= ~SFNT_POINT_TOUCHED_X; + + if (interpreter->state.freedom_vector.y) + mask &= ~SFNT_POINT_TOUCHED_Y; + + interpreter->glyph_zone->flags[p] &= mask; } /* Save the specified unit VECTOR into INTERPRETER's graphics state as -- 2.39.2