hb-draw.hh (6274B)
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 HB_DRAW_FUNC_IMPLEMENT (move_to) \ 37 HB_DRAW_FUNC_IMPLEMENT (line_to) \ 38 HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \ 39 HB_DRAW_FUNC_IMPLEMENT (cubic_to) \ 40 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 { func.move_to (this, draw_data, &st, 68 to_x, to_y, 69 !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 { func.line_to (this, draw_data, &st, 73 to_x, to_y, 74 !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 { func.quadratic_to (this, draw_data, &st, 79 control_x, control_y, 80 to_x, to_y, 81 !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 { func.cubic_to (this, draw_data, &st, 87 control1_x, control1_y, 88 control2_x, control2_y, 89 to_x, to_y, 90 !user_data ? nullptr : user_data->cubic_to); } 91 void emit_close_path (void *draw_data, hb_draw_state_t &st) 92 { func.close_path (this, draw_data, &st, 93 !user_data ? nullptr : user_data->close_path); } 94 95 96 void 97 HB_ALWAYS_INLINE 98 move_to (void *draw_data, hb_draw_state_t &st, 99 float to_x, float to_y) 100 { 101 if (unlikely (st.path_open)) close_path (draw_data, st); 102 103 st.current_x = to_x; 104 st.current_y = to_y; 105 } 106 107 void 108 HB_ALWAYS_INLINE 109 line_to (void *draw_data, hb_draw_state_t &st, 110 float to_x, float to_y) 111 { 112 if (unlikely (!st.path_open)) start_path (draw_data, st); 113 114 emit_line_to (draw_data, st, to_x, to_y); 115 116 st.current_x = to_x; 117 st.current_y = to_y; 118 } 119 120 void 121 HB_ALWAYS_INLINE 122 quadratic_to (void *draw_data, hb_draw_state_t &st, 123 float control_x, float control_y, 124 float to_x, float to_y) 125 { 126 if (unlikely (!st.path_open)) start_path (draw_data, st); 127 128 emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y); 129 130 st.current_x = to_x; 131 st.current_y = to_y; 132 } 133 134 void 135 HB_ALWAYS_INLINE 136 cubic_to (void *draw_data, hb_draw_state_t &st, 137 float control1_x, float control1_y, 138 float control2_x, float control2_y, 139 float to_x, float to_y) 140 { 141 if (unlikely (!st.path_open)) start_path (draw_data, st); 142 143 emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y); 144 145 st.current_x = to_x; 146 st.current_y = to_y; 147 } 148 149 void 150 HB_ALWAYS_INLINE 151 close_path (void *draw_data, hb_draw_state_t &st) 152 { 153 if (likely (st.path_open)) 154 { 155 if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y)) 156 emit_line_to (draw_data, st, st.path_start_x, st.path_start_y); 157 emit_close_path (draw_data, st); 158 } 159 st.path_open = false; 160 st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0; 161 } 162 163 protected: 164 165 void start_path (void *draw_data, hb_draw_state_t &st) 166 { 167 assert (!st.path_open); 168 emit_move_to (draw_data, st, st.current_x, st.current_y); 169 st.path_open = true; 170 st.path_start_x = st.current_x; 171 st.path_start_y = st.current_y; 172 } 173 }; 174 DECLARE_NULL_INSTANCE (hb_draw_funcs_t); 175 176 struct hb_draw_session_t 177 { 178 hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_) 179 : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT 180 {} 181 182 ~hb_draw_session_t () { close_path (); } 183 184 HB_ALWAYS_INLINE 185 void move_to (float to_x, float to_y) 186 { 187 funcs->move_to (draw_data, st, 188 to_x, to_y); 189 } 190 HB_ALWAYS_INLINE 191 void line_to (float to_x, float to_y) 192 { 193 funcs->line_to (draw_data, st, 194 to_x, to_y); 195 } 196 void 197 HB_ALWAYS_INLINE 198 quadratic_to (float control_x, float control_y, 199 float to_x, float to_y) 200 { 201 funcs->quadratic_to (draw_data, st, 202 control_x, control_y, 203 to_x, to_y); 204 } 205 void 206 HB_ALWAYS_INLINE 207 cubic_to (float control1_x, float control1_y, 208 float control2_x, float control2_y, 209 float to_x, float to_y) 210 { 211 funcs->cubic_to (draw_data, st, 212 control1_x, control1_y, 213 control2_x, control2_y, 214 to_x, to_y); 215 } 216 HB_ALWAYS_INLINE 217 void close_path () 218 { 219 funcs->close_path (draw_data, st); 220 } 221 222 public: 223 hb_draw_funcs_t *funcs; 224 void *draw_data; 225 hb_draw_state_t st; 226 }; 227 228 229 HB_INTERNAL hb_draw_funcs_t * 230 hb_draw_extents_get_funcs (); 231 232 233 #endif /* HB_DRAW_HH */