/work/workdir/UnpackedTarball/harfbuzz/src/hb-draw.hh
Line | Count | Source |
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 | 0 | HB_DRAW_FUNC_IMPLEMENT (set_budget) \ |
42 | 0 | HB_DRAW_FUNC_IMPLEMENT (get_budget) \ |
43 | 0 | HB_DRAW_FUNC_IMPLEMENT (get_budget_remaining) \ |
44 | | /* ^--- Add new callbacks here */ |
45 | | |
46 | | struct hb_draw_funcs_t |
47 | | { |
48 | | hb_object_header_t header; |
49 | | |
50 | | struct { |
51 | | #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name; |
52 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
53 | | #undef HB_DRAW_FUNC_IMPLEMENT |
54 | | } func; |
55 | | |
56 | | struct { |
57 | | #define HB_DRAW_FUNC_IMPLEMENT(name) void *name; |
58 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
59 | | #undef HB_DRAW_FUNC_IMPLEMENT |
60 | | } *user_data; |
61 | | |
62 | | struct { |
63 | | #define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name; |
64 | | HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS |
65 | | #undef HB_DRAW_FUNC_IMPLEMENT |
66 | | } *destroy; |
67 | | |
68 | | void emit_move_to (void *draw_data, hb_draw_state_t &st, |
69 | | float to_x, float to_y) |
70 | 598 | { func.move_to (this, draw_data, &st, |
71 | 598 | to_x, to_y, |
72 | 598 | !user_data ? nullptr : user_data->move_to); } |
73 | | void emit_line_to (void *draw_data, hb_draw_state_t &st, |
74 | | float to_x, float to_y) |
75 | 2.54k | { func.line_to (this, draw_data, &st, |
76 | 2.54k | to_x, to_y, |
77 | 2.54k | !user_data ? nullptr : user_data->line_to); } |
78 | | void emit_quadratic_to (void *draw_data, hb_draw_state_t &st, |
79 | | float control_x, float control_y, |
80 | | float to_x, float to_y) |
81 | 634 | { func.quadratic_to (this, draw_data, &st, |
82 | 634 | control_x, control_y, |
83 | 634 | to_x, to_y, |
84 | 634 | !user_data ? nullptr : user_data->quadratic_to); } |
85 | | void emit_cubic_to (void *draw_data, hb_draw_state_t &st, |
86 | | float control1_x, float control1_y, |
87 | | float control2_x, float control2_y, |
88 | | float to_x, float to_y) |
89 | 317 | { func.cubic_to (this, draw_data, &st, |
90 | 317 | control1_x, control1_y, |
91 | 317 | control2_x, control2_y, |
92 | 317 | to_x, to_y, |
93 | 317 | !user_data ? nullptr : user_data->cubic_to); } |
94 | | void emit_close_path (void *draw_data, hb_draw_state_t &st) |
95 | 598 | { func.close_path (this, draw_data, &st, |
96 | 598 | !user_data ? nullptr : user_data->close_path); } |
97 | | |
98 | | bool set_budget (void *draw_data, int64_t budget) |
99 | 0 | { |
100 | 0 | if (budget < 0 && budget != HB_BUDGET_DEFAULT) |
101 | 0 | budget = 0; |
102 | 0 | return func.set_budget (this, draw_data, budget, |
103 | 0 | !user_data ? nullptr : user_data->set_budget); |
104 | 0 | } |
105 | | int64_t get_budget (void *draw_data) |
106 | 0 | { return func.get_budget (this, draw_data, |
107 | 0 | !user_data ? nullptr : user_data->get_budget); } |
108 | | int64_t *get_budget_remaining_ptr (void *draw_data) |
109 | 664 | { return func.get_budget_remaining (this, draw_data, |
110 | 664 | !user_data ? nullptr : user_data->get_budget_remaining); } |
111 | | |
112 | | |
113 | | void |
114 | | HB_ALWAYS_INLINE |
115 | | move_to (void *draw_data, hb_draw_state_t &st, |
116 | | float to_x, float to_y) |
117 | 299 | { |
118 | 299 | if (unlikely (st.path_open)) close_path (draw_data, st); |
119 | | |
120 | 299 | st.current_x = to_x; |
121 | 299 | st.current_y = to_y; |
122 | 299 | } |
123 | | |
124 | | void |
125 | | HB_ALWAYS_INLINE |
126 | | line_to (void *draw_data, hb_draw_state_t &st, |
127 | | float to_x, float to_y) |
128 | 1.27k | { |
129 | 1.27k | if (unlikely (!st.path_open)) start_path (draw_data, st); |
130 | | |
131 | 1.27k | emit_line_to (draw_data, st, to_x, to_y); |
132 | | |
133 | 1.27k | st.current_x = to_x; |
134 | 1.27k | st.current_y = to_y; |
135 | 1.27k | } |
136 | | |
137 | | void |
138 | | HB_ALWAYS_INLINE |
139 | | quadratic_to (void *draw_data, hb_draw_state_t &st, |
140 | | float control_x, float control_y, |
141 | | float to_x, float to_y) |
142 | 317 | { |
143 | 317 | if (unlikely (!st.path_open)) start_path (draw_data, st); |
144 | | |
145 | 317 | emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); |
146 | | |
147 | 317 | st.current_x = to_x; |
148 | 317 | st.current_y = to_y; |
149 | 317 | } |
150 | | |
151 | | void |
152 | | HB_ALWAYS_INLINE |
153 | | cubic_to (void *draw_data, hb_draw_state_t &st, |
154 | | float control1_x, float control1_y, |
155 | | float control2_x, float control2_y, |
156 | | float to_x, float to_y) |
157 | 0 | { |
158 | 0 | if (unlikely (!st.path_open)) start_path (draw_data, st); |
159 | |
|
160 | 0 | emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); |
161 | |
|
162 | 0 | st.current_x = to_x; |
163 | 0 | st.current_y = to_y; |
164 | 0 | } |
165 | | |
166 | | void |
167 | | HB_ALWAYS_INLINE |
168 | | close_path (void *draw_data, hb_draw_state_t &st) |
169 | 631 | { |
170 | 631 | if (likely (st.path_open)) |
171 | 299 | { |
172 | 299 | if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) |
173 | 0 | emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); |
174 | 299 | emit_close_path (draw_data, st); |
175 | 299 | } |
176 | 631 | st.path_open = false; |
177 | 631 | st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0; |
178 | 631 | } |
179 | | |
180 | | protected: |
181 | | |
182 | | void start_path (void *draw_data, hb_draw_state_t &st) |
183 | 299 | { |
184 | 299 | assert (!st.path_open); |
185 | 299 | emit_move_to (draw_data, st, st.current_x, st.current_y); |
186 | 299 | st.path_open = true; |
187 | 299 | st.path_start_x = st.current_x; |
188 | 299 | st.path_start_y = st.current_y; |
189 | 299 | } |
190 | | }; |
191 | | DECLARE_NULL_INSTANCE (hb_draw_funcs_t); |
192 | | |
193 | | struct hb_draw_session_t |
194 | | { |
195 | | hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_) |
196 | 332 | : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT, |
197 | 332 | local_budget {HB_BUDGET_GLYPH}, budget {funcs->get_budget_remaining_ptr (draw_data)} |
198 | 332 | { |
199 | 332 | if (!budget) |
200 | 332 | budget = &local_budget; |
201 | 332 | } |
202 | | |
203 | 332 | ~hb_draw_session_t () { close_path (); } |
204 | | |
205 | | HB_ALWAYS_INLINE |
206 | | void move_to (float to_x, float to_y) |
207 | 299 | { |
208 | 299 | funcs->move_to (draw_data, st, |
209 | 299 | to_x, to_y); |
210 | 299 | } |
211 | | HB_ALWAYS_INLINE |
212 | | void line_to (float to_x, float to_y) |
213 | 1.27k | { |
214 | 1.27k | funcs->line_to (draw_data, st, |
215 | 1.27k | to_x, to_y); |
216 | 1.27k | } |
217 | | void |
218 | | HB_ALWAYS_INLINE |
219 | | quadratic_to (float control_x, float control_y, |
220 | | float to_x, float to_y) |
221 | 317 | { |
222 | 317 | funcs->quadratic_to (draw_data, st, |
223 | 317 | control_x, control_y, |
224 | 317 | to_x, to_y); |
225 | 317 | } |
226 | | void |
227 | | HB_ALWAYS_INLINE |
228 | | cubic_to (float control1_x, float control1_y, |
229 | | float control2_x, float control2_y, |
230 | | float to_x, float to_y) |
231 | 0 | { |
232 | 0 | funcs->cubic_to (draw_data, st, |
233 | 0 | control1_x, control1_y, |
234 | 0 | control2_x, control2_y, |
235 | 0 | to_x, to_y); |
236 | 0 | } |
237 | | HB_ALWAYS_INLINE |
238 | | void close_path () |
239 | 631 | { |
240 | 631 | funcs->close_path (draw_data, st); |
241 | 631 | } |
242 | | |
243 | 334 | int64_t &get_budget () { return *budget; } |
244 | | |
245 | | public: |
246 | | hb_draw_funcs_t *funcs; |
247 | | void *draw_data; |
248 | | hb_draw_state_t st; |
249 | | int64_t local_budget; |
250 | | int64_t *budget; |
251 | | }; |
252 | | |
253 | | |
254 | | HB_INTERNAL hb_draw_funcs_t * |
255 | | hb_draw_extents_get_funcs (); |
256 | | |
257 | | |
258 | | #endif /* HB_DRAW_HH */ |