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