/src/harfbuzz/src/hb-draw.hh
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright © 2020 Ebrahim Byagowi |
3 | | * |
4 | | * This is part of HarfBuzz, a text shaping library. |
5 | | * |
6 | | * Permission is hereby granted, without written agreement and without |
7 | | * license or royalty fees, to use, copy, modify, and distribute this |
8 | | * software and its documentation for any purpose, provided that the |
9 | | * above copyright notice and the following two paragraphs appear in |
10 | | * all copies of this software. |
11 | | * |
12 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | | * DAMAGE. |
17 | | * |
18 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | | */ |
24 | | |
25 | | #ifndef HB_DRAW_HH |
26 | | #define HB_DRAW_HH |
27 | | |
28 | | #include "hb.hh" |
29 | | |
30 | | |
31 | | /* |
32 | | * hb_draw_funcs_t |
33 | | */ |
34 | | |
35 | | #define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \ |
36 | 0 | HB_DRAW_FUNC_IMPLEMENT (move_to) \ |
37 | 0 | HB_DRAW_FUNC_IMPLEMENT (line_to) \ |
38 | 0 | HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \ |
39 | 0 | HB_DRAW_FUNC_IMPLEMENT (cubic_to) \ |
40 | 0 | HB_DRAW_FUNC_IMPLEMENT (close_path) \ |
41 | | /* ^--- Add new callbacks here */ |
42 | | |
43 | | struct hb_draw_funcs_t |
44 | | { |
45 | | hb_object_header_t header; |
46 | | |
47 | | struct { |
48 | | #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name; |
49 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
50 | | #undef HB_DRAW_FUNC_IMPLEMENT |
51 | | } func; |
52 | | |
53 | | struct { |
54 | | #define HB_DRAW_FUNC_IMPLEMENT(name) void *name; |
55 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
56 | | #undef HB_DRAW_FUNC_IMPLEMENT |
57 | | } *user_data; |
58 | | |
59 | | struct { |
60 | | #define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name; |
61 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
62 | | #undef HB_DRAW_FUNC_IMPLEMENT |
63 | | } *destroy; |
64 | | |
65 | | void emit_move_to (void *draw_data, hb_draw_state_t &st, |
66 | | float to_x, float to_y) |
67 | 21.7k | { func.move_to (this, draw_data, &st, |
68 | 21.7k | to_x, to_y, |
69 | 21.7k | !user_data ? nullptr : user_data->move_to); } |
70 | | void emit_line_to (void *draw_data, hb_draw_state_t &st, |
71 | | float to_x, float to_y) |
72 | 109k | { func.line_to (this, draw_data, &st, |
73 | 109k | to_x, to_y, |
74 | 109k | !user_data ? nullptr : user_data->line_to); } |
75 | | void emit_quadratic_to (void *draw_data, hb_draw_state_t &st, |
76 | | float control_x, float control_y, |
77 | | float to_x, float to_y) |
78 | 90.9k | { func.quadratic_to (this, draw_data, &st, |
79 | 90.9k | control_x, control_y, |
80 | 90.9k | to_x, to_y, |
81 | 90.9k | !user_data ? nullptr : user_data->quadratic_to); } |
82 | | void emit_cubic_to (void *draw_data, hb_draw_state_t &st, |
83 | | float control1_x, float control1_y, |
84 | | float control2_x, float control2_y, |
85 | | float to_x, float to_y) |
86 | 99.1k | { func.cubic_to (this, draw_data, &st, |
87 | 99.1k | control1_x, control1_y, |
88 | 99.1k | control2_x, control2_y, |
89 | 99.1k | to_x, to_y, |
90 | 99.1k | !user_data ? nullptr : user_data->cubic_to); } |
91 | | void emit_close_path (void *draw_data, hb_draw_state_t &st) |
92 | 21.7k | { func.close_path (this, draw_data, &st, |
93 | 21.7k | !user_data ? nullptr : user_data->close_path); } |
94 | | |
95 | | |
96 | | void move_to (void *draw_data, hb_draw_state_t &st, |
97 | | float to_x, float to_y) |
98 | 23.0k | { |
99 | 23.0k | if (st.path_open) close_path (draw_data, st); |
100 | 23.0k | st.current_x = to_x; |
101 | 23.0k | st.current_y = to_y; |
102 | 23.0k | } |
103 | | |
104 | | void line_to (void *draw_data, hb_draw_state_t &st, |
105 | | float to_x, float to_y) |
106 | 105k | { |
107 | 105k | if (!st.path_open) start_path (draw_data, st); |
108 | 105k | emit_line_to (draw_data, st, to_x, to_y); |
109 | 105k | st.current_x = to_x; |
110 | 105k | st.current_y = to_y; |
111 | 105k | } |
112 | | |
113 | | void |
114 | | quadratic_to (void *draw_data, hb_draw_state_t &st, |
115 | | float control_x, float control_y, |
116 | | float to_x, float to_y) |
117 | 90.9k | { |
118 | 90.9k | if (!st.path_open) start_path (draw_data, st); |
119 | 90.9k | emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); |
120 | 90.9k | st.current_x = to_x; |
121 | 90.9k | st.current_y = to_y; |
122 | 90.9k | } |
123 | | |
124 | | void |
125 | | cubic_to (void *draw_data, hb_draw_state_t &st, |
126 | | float control1_x, float control1_y, |
127 | | float control2_x, float control2_y, |
128 | | float to_x, float to_y) |
129 | 8.50k | { |
130 | 8.50k | if (!st.path_open) start_path (draw_data, st); |
131 | 8.50k | emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); |
132 | 8.50k | st.current_x = to_x; |
133 | 8.50k | st.current_y = to_y; |
134 | 8.50k | } |
135 | | |
136 | | void |
137 | | close_path (void *draw_data, hb_draw_state_t &st) |
138 | 56.4k | { |
139 | 56.4k | if (st.path_open) |
140 | 21.7k | { |
141 | 21.7k | if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) |
142 | 3.81k | emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); |
143 | 21.7k | emit_close_path (draw_data, st); |
144 | 21.7k | } |
145 | 56.4k | st.path_open = false; |
146 | 56.4k | st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0; |
147 | 56.4k | } |
148 | | |
149 | | protected: |
150 | | |
151 | | void start_path (void *draw_data, hb_draw_state_t &st) |
152 | 21.7k | { |
153 | 21.7k | assert (!st.path_open); |
154 | 0 | emit_move_to (draw_data, st, st.current_x, st.current_y); |
155 | 21.7k | st.path_open = true; |
156 | 21.7k | st.path_start_x = st.current_x; |
157 | 21.7k | st.path_start_y = st.current_y; |
158 | 21.7k | } |
159 | | }; |
160 | | DECLARE_NULL_INSTANCE (hb_draw_funcs_t); |
161 | | |
162 | | struct hb_draw_session_t |
163 | | { |
164 | | hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f) |
165 | | : slant {slant_}, not_slanted {slant == 0.f}, |
166 | | funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT |
167 | 35.3k | {} |
168 | | |
169 | 35.3k | ~hb_draw_session_t () { close_path (); } |
170 | | |
171 | | void move_to (float to_x, float to_y) |
172 | 23.0k | { |
173 | 23.0k | if (likely (not_slanted)) |
174 | 23.0k | funcs->move_to (draw_data, st, |
175 | 23.0k | to_x, to_y); |
176 | 0 | else |
177 | 0 | funcs->move_to (draw_data, st, |
178 | 0 | to_x + to_y * slant, to_y); |
179 | 23.0k | } |
180 | | void line_to (float to_x, float to_y) |
181 | 105k | { |
182 | 105k | if (likely (not_slanted)) |
183 | 105k | funcs->line_to (draw_data, st, |
184 | 105k | to_x, to_y); |
185 | 0 | else |
186 | 0 | funcs->line_to (draw_data, st, |
187 | 0 | to_x + to_y * slant, to_y); |
188 | 105k | } |
189 | | void |
190 | | quadratic_to (float control_x, float control_y, |
191 | | float to_x, float to_y) |
192 | 90.9k | { |
193 | 90.9k | if (likely (not_slanted)) |
194 | 90.9k | funcs->quadratic_to (draw_data, st, |
195 | 90.9k | control_x, control_y, |
196 | 90.9k | to_x, to_y); |
197 | 0 | else |
198 | 0 | funcs->quadratic_to (draw_data, st, |
199 | 0 | control_x + control_y * slant, control_y, |
200 | 0 | to_x + to_y * slant, to_y); |
201 | 90.9k | } |
202 | | void |
203 | | cubic_to (float control1_x, float control1_y, |
204 | | float control2_x, float control2_y, |
205 | | float to_x, float to_y) |
206 | 8.50k | { |
207 | 8.50k | if (likely (not_slanted)) |
208 | 8.50k | funcs->cubic_to (draw_data, st, |
209 | 8.50k | control1_x, control1_y, |
210 | 8.50k | control2_x, control2_y, |
211 | 8.50k | to_x, to_y); |
212 | 0 | else |
213 | 0 | funcs->cubic_to (draw_data, st, |
214 | 0 | control1_x + control1_y * slant, control1_y, |
215 | 0 | control2_x + control2_y * slant, control2_y, |
216 | 0 | to_x + to_y * slant, to_y); |
217 | 8.50k | } |
218 | | void close_path () |
219 | 53.2k | { |
220 | 53.2k | funcs->close_path (draw_data, st); |
221 | 53.2k | } |
222 | | |
223 | | protected: |
224 | | float slant; |
225 | | bool not_slanted; |
226 | | hb_draw_funcs_t *funcs; |
227 | | void *draw_data; |
228 | | hb_draw_state_t st; |
229 | | }; |
230 | | |
231 | | #endif /* HB_DRAW_HH */ |