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