1 #ifndef OT_GLYF_PATH_BUILDER_HH
2 #define OT_GLYF_PATH_BUILDER_HH
15 hb_draw_session_t *draw_session;
17 struct optional_point_t
19 optional_point_t () {}
20 optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
21 operator bool () const { return has_data; }
23 bool has_data = false;
27 optional_point_t mid (optional_point_t p)
28 { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); }
29 } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
31 path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) :
32 font (font_), draw_session (&draw_session_) {}
34 /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
36 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
37 * https://stackoverflow.com/a/20772557
39 * Cubic support added. */
41 void consume_point (const contour_point_t &point)
43 bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
44 #ifdef HB_NO_CUBIC_GLYF
45 bool is_cubic = false;
47 bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
49 optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
50 if (unlikely (!first_oncurve))
55 draw_session->move_to (p.x, p.y);
59 if (is_cubic && !first_offcurve2)
61 first_offcurve2 = first_offcurve;
64 else if (first_offcurve)
66 optional_point_t mid = first_offcurve.mid (p);
69 draw_session->move_to (mid.x, mid.y);
83 draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
84 last_offcurve.x, last_offcurve.y,
86 last_offcurve2 = optional_point_t ();
89 draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
91 last_offcurve = optional_point_t ();
95 if (is_cubic && !last_offcurve2)
97 last_offcurve2 = last_offcurve;
102 optional_point_t mid = last_offcurve.mid (p);
106 draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
107 last_offcurve.x, last_offcurve.y,
109 last_offcurve2 = optional_point_t ();
112 draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
121 draw_session->line_to (p.x, p.y);
127 if (unlikely (point.is_end_point))
129 if (first_offcurve && last_offcurve)
131 optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
135 draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
136 last_offcurve.x, last_offcurve.y,
139 draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
141 last_offcurve = optional_point_t ();
143 /* now check the rest */
145 if (first_offcurve && first_oncurve)
148 draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
149 first_offcurve.x, first_offcurve.y,
150 first_oncurve.x, first_oncurve.y);
152 draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
153 first_oncurve.x, first_oncurve.y);
155 else if (last_offcurve && first_oncurve)
158 draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
159 last_offcurve.x, last_offcurve.y,
160 first_oncurve.x, first_oncurve.y);
162 draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
163 first_oncurve.x, first_oncurve.y);
165 else if (first_oncurve)
166 draw_session->line_to (first_oncurve.x, first_oncurve.y);
167 else if (first_offcurve)
169 float x = first_offcurve.x, y = first_offcurve.y;
170 draw_session->move_to (x, y);
171 draw_session->quadratic_to (x, y, x, y);
174 /* Getting ready for the next contour */
175 first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
176 draw_session->close_path ();
179 void points_end () {}
181 bool is_consuming_contour_points () { return true; }
182 contour_point_t *get_phantoms_sink () { return nullptr; }
186 } /* namespace glyf_impl */
190 #endif /* OT_GLYF_PATH_BUILDER_HH */