/src/harfbuzz/src/OT/glyf/path-builder.hh
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef OT_GLYF_PATH_BUILDER_HH |
2 | | #define OT_GLYF_PATH_BUILDER_HH |
3 | | |
4 | | |
5 | | #include "../../hb.hh" |
6 | | |
7 | | |
8 | | namespace OT { |
9 | | namespace glyf_impl { |
10 | | |
11 | | |
12 | | struct path_builder_t |
13 | | { |
14 | | hb_font_t *font; |
15 | | hb_draw_session_t *draw_session; |
16 | | |
17 | | struct optional_point_t |
18 | | { |
19 | 0 | optional_point_t () {} |
20 | 0 | optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {} |
21 | 0 | operator bool () const { return has_data; } |
22 | | |
23 | | bool has_data = false; |
24 | | float x; |
25 | | float y; |
26 | | |
27 | | optional_point_t mid (optional_point_t p) |
28 | 0 | { 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; |
30 | | |
31 | | path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : |
32 | 0 | font (font_), draw_session (&draw_session_) {} |
33 | | |
34 | | /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 |
35 | | See also: |
36 | | * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html |
37 | | * https://stackoverflow.com/a/20772557 |
38 | | * |
39 | | * Cubic support added. */ |
40 | | HB_ALWAYS_INLINE |
41 | | void consume_point (const contour_point_t &point) |
42 | 0 | { |
43 | 0 | bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; |
44 | | #ifdef HB_NO_CUBIC_GLYF |
45 | | constexpr bool is_cubic = false; |
46 | | #else |
47 | 0 | bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); |
48 | 0 | #endif |
49 | 0 | optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); |
50 | 0 | if (unlikely (!first_oncurve)) |
51 | 0 | { |
52 | 0 | if (is_on_curve) |
53 | 0 | { |
54 | 0 | first_oncurve = p; |
55 | 0 | draw_session->move_to (p.x, p.y); |
56 | 0 | } |
57 | 0 | else |
58 | 0 | { |
59 | 0 | if (is_cubic && !first_offcurve2) |
60 | 0 | { |
61 | 0 | first_offcurve2 = first_offcurve; |
62 | 0 | first_offcurve = p; |
63 | 0 | } |
64 | 0 | else if (first_offcurve) |
65 | 0 | { |
66 | 0 | optional_point_t mid = first_offcurve.mid (p); |
67 | 0 | first_oncurve = mid; |
68 | 0 | last_offcurve = p; |
69 | 0 | draw_session->move_to (mid.x, mid.y); |
70 | 0 | } |
71 | 0 | else |
72 | 0 | first_offcurve = p; |
73 | 0 | } |
74 | 0 | } |
75 | 0 | else |
76 | 0 | { |
77 | 0 | if (last_offcurve) |
78 | 0 | { |
79 | 0 | if (is_on_curve) |
80 | 0 | { |
81 | 0 | if (last_offcurve2) |
82 | 0 | { |
83 | 0 | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
84 | 0 | last_offcurve.x, last_offcurve.y, |
85 | 0 | p.x, p.y); |
86 | 0 | last_offcurve2 = optional_point_t (); |
87 | 0 | } |
88 | 0 | else |
89 | 0 | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
90 | 0 | p.x, p.y); |
91 | 0 | last_offcurve = optional_point_t (); |
92 | 0 | } |
93 | 0 | else |
94 | 0 | { |
95 | 0 | if (is_cubic && !last_offcurve2) |
96 | 0 | { |
97 | 0 | last_offcurve2 = last_offcurve; |
98 | 0 | last_offcurve = p; |
99 | 0 | } |
100 | 0 | else |
101 | 0 | { |
102 | 0 | optional_point_t mid = last_offcurve.mid (p); |
103 | |
|
104 | 0 | if (is_cubic) |
105 | 0 | { |
106 | 0 | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
107 | 0 | last_offcurve.x, last_offcurve.y, |
108 | 0 | mid.x, mid.y); |
109 | 0 | last_offcurve2 = optional_point_t (); |
110 | 0 | } |
111 | 0 | else |
112 | 0 | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
113 | 0 | mid.x, mid.y); |
114 | 0 | last_offcurve = p; |
115 | 0 | } |
116 | 0 | } |
117 | 0 | } |
118 | 0 | else |
119 | 0 | { |
120 | 0 | if (is_on_curve) |
121 | 0 | draw_session->line_to (p.x, p.y); |
122 | 0 | else |
123 | 0 | last_offcurve = p; |
124 | 0 | } |
125 | 0 | } |
126 | |
|
127 | 0 | } |
128 | | |
129 | | void contour_end () |
130 | 0 | { |
131 | 0 | if (first_offcurve && last_offcurve) |
132 | 0 | { |
133 | 0 | optional_point_t mid = last_offcurve.mid (first_offcurve2 ? |
134 | 0 | first_offcurve2 : |
135 | 0 | first_offcurve); |
136 | 0 | if (last_offcurve2) |
137 | 0 | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
138 | 0 | last_offcurve.x, last_offcurve.y, |
139 | 0 | mid.x, mid.y); |
140 | 0 | else |
141 | 0 | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
142 | 0 | mid.x, mid.y); |
143 | 0 | last_offcurve = optional_point_t (); |
144 | 0 | } |
145 | | /* now check the rest */ |
146 | |
|
147 | 0 | if (first_offcurve && first_oncurve) |
148 | 0 | { |
149 | 0 | if (first_offcurve2) |
150 | 0 | draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y, |
151 | 0 | first_offcurve.x, first_offcurve.y, |
152 | 0 | first_oncurve.x, first_oncurve.y); |
153 | 0 | else |
154 | 0 | draw_session->quadratic_to (first_offcurve.x, first_offcurve.y, |
155 | 0 | first_oncurve.x, first_oncurve.y); |
156 | 0 | } |
157 | 0 | else if (last_offcurve && first_oncurve) |
158 | 0 | { |
159 | 0 | if (last_offcurve2) |
160 | 0 | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
161 | 0 | last_offcurve.x, last_offcurve.y, |
162 | 0 | first_oncurve.x, first_oncurve.y); |
163 | 0 | else |
164 | 0 | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
165 | 0 | first_oncurve.x, first_oncurve.y); |
166 | 0 | } |
167 | 0 | else if (first_oncurve) |
168 | 0 | draw_session->line_to (first_oncurve.x, first_oncurve.y); |
169 | 0 | else if (first_offcurve) |
170 | 0 | { |
171 | 0 | float x = first_offcurve.x, y = first_offcurve.y; |
172 | 0 | draw_session->move_to (x, y); |
173 | 0 | draw_session->quadratic_to (x, y, x, y); |
174 | 0 | } |
175 | | |
176 | | /* Getting ready for the next contour */ |
177 | 0 | first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t (); |
178 | 0 | draw_session->close_path (); |
179 | 0 | } |
180 | | |
181 | 0 | void points_end () {} |
182 | | |
183 | 0 | bool is_consuming_contour_points () { return true; } |
184 | 0 | contour_point_t *get_phantoms_sink () { return nullptr; } |
185 | | }; |
186 | | |
187 | | |
188 | | } /* namespace glyf_impl */ |
189 | | } /* namespace OT */ |
190 | | |
191 | | |
192 | | #endif /* OT_GLYF_PATH_BUILDER_HH */ |