Merge pull request #4107 from harfbuzz/cubic-glyf

[glyf] Support cubic curves
This commit is contained in:
Behdad Esfahbod 2023-02-11 09:20:51 -07:00 committed by GitHub
commit c6c1c6ddf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 13 deletions

View File

@ -20,7 +20,7 @@ struct SimpleGlyph
FLAG_X_SAME = 0x10, FLAG_X_SAME = 0x10,
FLAG_Y_SAME = 0x20, FLAG_Y_SAME = 0x20,
FLAG_OVERLAP_SIMPLE = 0x40, FLAG_OVERLAP_SIMPLE = 0x40,
FLAG_RESERVED2 = 0x80 FLAG_CUBIC = 0x80
}; };
const GlyphHeader &header; const GlyphHeader &header;

View File

@ -26,22 +26,29 @@ struct path_builder_t
optional_point_t lerp (optional_point_t p, float t) optional_point_t lerp (optional_point_t p, float t)
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); } { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
} first_oncurve, first_offcurve, last_offcurve; } first_oncurve, first_offcurve, last_offcurve, last_offcurve2;
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{ {
font = font_; font = font_;
draw_session = &draw_session_; draw_session = &draw_session_;
first_oncurve = first_offcurve = last_offcurve = optional_point_t (); first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
} }
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
See also: See also:
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
* https://stackoverflow.com/a/20772557 */ * https://stackoverflow.com/a/20772557
*
* Cubic support added (incomplete). */
void consume_point (const contour_point_t &point) void consume_point (const contour_point_t &point)
{ {
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
#ifdef HB_NO_CUBIC_GLYF
bool is_cubic = false;
#else
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
#endif
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
if (!first_oncurve) if (!first_oncurve)
{ {
@ -69,16 +76,41 @@ struct path_builder_t
{ {
if (is_on_curve) if (is_on_curve)
{ {
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, if (last_offcurve2)
p.x, p.y); {
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
last_offcurve.x, last_offcurve.y,
p.x, p.y);
last_offcurve2 = optional_point_t ();
}
else
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
p.x, p.y);
last_offcurve = optional_point_t (); last_offcurve = optional_point_t ();
} }
else else
{ {
optional_point_t mid = last_offcurve.lerp (p, .5f); if (is_cubic && !last_offcurve2)
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, {
mid.x, mid.y); last_offcurve2 = last_offcurve;
last_offcurve = p; last_offcurve = p;
}
else
{
optional_point_t mid = last_offcurve.lerp (p, .5f);
if (is_cubic)
{
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
last_offcurve.x, last_offcurve.y,
mid.x, mid.y);
last_offcurve2 = optional_point_t ();
}
else
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
mid.x, mid.y);
last_offcurve = p;
}
} }
} }
else else
@ -105,8 +137,15 @@ struct path_builder_t
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y, draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
first_oncurve.x, first_oncurve.y); first_oncurve.x, first_oncurve.y);
else if (last_offcurve && first_oncurve) else if (last_offcurve && first_oncurve)
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, {
first_oncurve.x, first_oncurve.y); if (last_offcurve2)
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
last_offcurve.x, last_offcurve.y,
first_oncurve.x, first_oncurve.y);
else
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
first_oncurve.x, first_oncurve.y);
}
else if (first_oncurve) else if (first_oncurve)
draw_session->line_to (first_oncurve.x, first_oncurve.y); draw_session->line_to (first_oncurve.x, first_oncurve.y);
else if (first_offcurve) else if (first_offcurve)
@ -117,7 +156,7 @@ struct path_builder_t
} }
/* Getting ready for the next contour */ /* Getting ready for the next contour */
first_oncurve = first_offcurve = last_offcurve = optional_point_t (); first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
draw_session->close_path (); draw_session->close_path ();
} }
} }

View File

@ -37,6 +37,7 @@
#ifndef HB_EXPERIMENTAL_API #ifndef HB_EXPERIMENTAL_API
#define HB_NO_BEYOND_64K #define HB_NO_BEYOND_64K
#define HB_NO_CUBIC_GLYF
#define HB_NO_VAR_COMPOSITES #define HB_NO_VAR_COMPOSITES
#endif #endif