/src/harfbuzz/src/OT/glyf/path-builder.hh
Line | Count | Source |
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 | 18.2M | optional_point_t () {} |
20 | 69.6M | optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {} |
21 | 125M | 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 | 15.9M | { 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 | 2.17M | 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 | 53.6M | { |
43 | 53.6M | 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 | 53.6M | bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); |
48 | 53.6M | #endif |
49 | 53.6M | optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); |
50 | 53.6M | if (unlikely (!first_oncurve)) |
51 | 2.19M | { |
52 | 2.19M | if (is_on_curve) |
53 | 1.04M | { |
54 | 1.04M | first_oncurve = p; |
55 | 1.04M | draw_session->move_to (p.x, p.y); |
56 | 1.04M | } |
57 | 1.14M | else |
58 | 1.14M | { |
59 | 1.14M | if (is_cubic && !first_offcurve2) |
60 | 32.6k | { |
61 | 32.6k | first_offcurve2 = first_offcurve; |
62 | 32.6k | first_offcurve = p; |
63 | 32.6k | } |
64 | 1.11M | else if (first_offcurve) |
65 | 365k | { |
66 | 365k | optional_point_t mid = first_offcurve.mid (p); |
67 | 365k | first_oncurve = mid; |
68 | 365k | last_offcurve = p; |
69 | 365k | draw_session->move_to (mid.x, mid.y); |
70 | 365k | } |
71 | 750k | else |
72 | 750k | first_offcurve = p; |
73 | 1.14M | } |
74 | 2.19M | } |
75 | 51.4M | else |
76 | 51.4M | { |
77 | 51.4M | if (last_offcurve) |
78 | 20.4M | { |
79 | 20.4M | if (is_on_curve) |
80 | 1.04M | { |
81 | 1.04M | if (last_offcurve2) |
82 | 107k | { |
83 | 107k | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
84 | 107k | last_offcurve.x, last_offcurve.y, |
85 | 107k | p.x, p.y); |
86 | 107k | last_offcurve2 = optional_point_t (); |
87 | 107k | } |
88 | 941k | else |
89 | 941k | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
90 | 941k | p.x, p.y); |
91 | 1.04M | last_offcurve = optional_point_t (); |
92 | 1.04M | } |
93 | 19.3M | else |
94 | 19.3M | { |
95 | 19.3M | if (is_cubic && !last_offcurve2) |
96 | 4.15M | { |
97 | 4.15M | last_offcurve2 = last_offcurve; |
98 | 4.15M | last_offcurve = p; |
99 | 4.15M | } |
100 | 15.2M | else |
101 | 15.2M | { |
102 | 15.2M | optional_point_t mid = last_offcurve.mid (p); |
103 | | |
104 | 15.2M | if (is_cubic) |
105 | 3.98M | { |
106 | 3.98M | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
107 | 3.98M | last_offcurve.x, last_offcurve.y, |
108 | 3.98M | mid.x, mid.y); |
109 | 3.98M | last_offcurve2 = optional_point_t (); |
110 | 3.98M | } |
111 | 11.2M | else |
112 | 11.2M | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
113 | 11.2M | mid.x, mid.y); |
114 | 15.2M | last_offcurve = p; |
115 | 15.2M | } |
116 | 19.3M | } |
117 | 20.4M | } |
118 | 31.0M | else |
119 | 31.0M | { |
120 | 31.0M | if (is_on_curve) |
121 | 29.9M | draw_session->line_to (p.x, p.y); |
122 | 1.12M | else |
123 | 1.12M | last_offcurve = p; |
124 | 31.0M | } |
125 | 51.4M | } |
126 | | |
127 | 53.6M | } |
128 | | |
129 | | void contour_end () |
130 | 1.82M | { |
131 | 1.82M | if (first_offcurve && last_offcurve) |
132 | 344k | { |
133 | 344k | optional_point_t mid = last_offcurve.mid (first_offcurve2 ? |
134 | 228k | first_offcurve2 : |
135 | 344k | first_offcurve); |
136 | 344k | if (last_offcurve2) |
137 | 53.6k | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
138 | 53.6k | last_offcurve.x, last_offcurve.y, |
139 | 53.6k | mid.x, mid.y); |
140 | 290k | else |
141 | 290k | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
142 | 290k | mid.x, mid.y); |
143 | 344k | last_offcurve = optional_point_t (); |
144 | 344k | } |
145 | | /* now check the rest */ |
146 | | |
147 | 1.82M | if (first_offcurve && first_oncurve) |
148 | 367k | { |
149 | 367k | if (first_offcurve2) |
150 | 231k | draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y, |
151 | 231k | first_offcurve.x, first_offcurve.y, |
152 | 231k | first_oncurve.x, first_oncurve.y); |
153 | 135k | else |
154 | 135k | draw_session->quadratic_to (first_offcurve.x, first_offcurve.y, |
155 | 135k | first_oncurve.x, first_oncurve.y); |
156 | 367k | } |
157 | 1.45M | else if (last_offcurve && first_oncurve) |
158 | 97.2k | { |
159 | 97.2k | if (last_offcurve2) |
160 | 17.0k | draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, |
161 | 17.0k | last_offcurve.x, last_offcurve.y, |
162 | 17.0k | first_oncurve.x, first_oncurve.y); |
163 | 80.1k | else |
164 | 80.1k | draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, |
165 | 80.1k | first_oncurve.x, first_oncurve.y); |
166 | 97.2k | } |
167 | 1.35M | else if (first_oncurve) |
168 | 950k | draw_session->line_to (first_oncurve.x, first_oncurve.y); |
169 | 407k | else if (first_offcurve) |
170 | 407k | { |
171 | 407k | float x = first_offcurve.x, y = first_offcurve.y; |
172 | 407k | draw_session->move_to (x, y); |
173 | 407k | draw_session->quadratic_to (x, y, x, y); |
174 | 407k | } |
175 | | |
176 | | /* Getting ready for the next contour */ |
177 | 1.82M | first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t (); |
178 | 1.82M | draw_session->close_path (); |
179 | 1.82M | } |
180 | | |
181 | 934k | void points_end () {} |
182 | | |
183 | 2.13M | bool is_consuming_contour_points () { return true; } |
184 | 934k | 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 */ |