1*2d1272b8SAndroid Build Coastguard Worker #ifndef OT_GLYF_PATH_BUILDER_HH 2*2d1272b8SAndroid Build Coastguard Worker #define OT_GLYF_PATH_BUILDER_HH 3*2d1272b8SAndroid Build Coastguard Worker 4*2d1272b8SAndroid Build Coastguard Worker 5*2d1272b8SAndroid Build Coastguard Worker #include "../../hb.hh" 6*2d1272b8SAndroid Build Coastguard Worker 7*2d1272b8SAndroid Build Coastguard Worker 8*2d1272b8SAndroid Build Coastguard Worker namespace OT { 9*2d1272b8SAndroid Build Coastguard Worker namespace glyf_impl { 10*2d1272b8SAndroid Build Coastguard Worker 11*2d1272b8SAndroid Build Coastguard Worker 12*2d1272b8SAndroid Build Coastguard Worker struct path_builder_t 13*2d1272b8SAndroid Build Coastguard Worker { 14*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font; 15*2d1272b8SAndroid Build Coastguard Worker hb_draw_session_t *draw_session; 16*2d1272b8SAndroid Build Coastguard Worker 17*2d1272b8SAndroid Build Coastguard Worker struct optional_point_t 18*2d1272b8SAndroid Build Coastguard Worker { optional_point_tOT::glyf_impl::path_builder_t::optional_point_t19*2d1272b8SAndroid Build Coastguard Worker optional_point_t () {} optional_point_tOT::glyf_impl::path_builder_t::optional_point_t20*2d1272b8SAndroid Build Coastguard Worker optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {} operator boolOT::glyf_impl::path_builder_t::optional_point_t21*2d1272b8SAndroid Build Coastguard Worker operator bool () const { return has_data; } 22*2d1272b8SAndroid Build Coastguard Worker 23*2d1272b8SAndroid Build Coastguard Worker bool has_data = false; 24*2d1272b8SAndroid Build Coastguard Worker float x; 25*2d1272b8SAndroid Build Coastguard Worker float y; 26*2d1272b8SAndroid Build Coastguard Worker midOT::glyf_impl::path_builder_t::optional_point_t27*2d1272b8SAndroid Build Coastguard Worker optional_point_t mid (optional_point_t p) 28*2d1272b8SAndroid Build Coastguard Worker { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); } 29*2d1272b8SAndroid Build Coastguard Worker } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2; 30*2d1272b8SAndroid Build Coastguard Worker path_builder_tOT::glyf_impl::path_builder_t31*2d1272b8SAndroid Build Coastguard Worker path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) : 32*2d1272b8SAndroid Build Coastguard Worker font (font_), draw_session (&draw_session_) {} 33*2d1272b8SAndroid Build Coastguard Worker 34*2d1272b8SAndroid Build Coastguard Worker /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287 35*2d1272b8SAndroid Build Coastguard Worker See also: 36*2d1272b8SAndroid Build Coastguard Worker * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html 37*2d1272b8SAndroid Build Coastguard Worker * https://stackoverflow.com/a/20772557 38*2d1272b8SAndroid Build Coastguard Worker * 39*2d1272b8SAndroid Build Coastguard Worker * Cubic support added. */ 40*2d1272b8SAndroid Build Coastguard Worker HB_ALWAYS_INLINE consume_pointOT::glyf_impl::path_builder_t41*2d1272b8SAndroid Build Coastguard Worker void consume_point (const contour_point_t &point) 42*2d1272b8SAndroid Build Coastguard Worker { 43*2d1272b8SAndroid Build Coastguard Worker bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE; 44*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_CUBIC_GLYF 45*2d1272b8SAndroid Build Coastguard Worker bool is_cubic = false; 46*2d1272b8SAndroid Build Coastguard Worker #else 47*2d1272b8SAndroid Build Coastguard Worker bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC); 48*2d1272b8SAndroid Build Coastguard Worker #endif 49*2d1272b8SAndroid Build Coastguard Worker optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y)); 50*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!first_oncurve)) 51*2d1272b8SAndroid Build Coastguard Worker { 52*2d1272b8SAndroid Build Coastguard Worker if (is_on_curve) 53*2d1272b8SAndroid Build Coastguard Worker { 54*2d1272b8SAndroid Build Coastguard Worker first_oncurve = p; 55*2d1272b8SAndroid Build Coastguard Worker draw_session->move_to (p.x, p.y); 56*2d1272b8SAndroid Build Coastguard Worker } 57*2d1272b8SAndroid Build Coastguard Worker else 58*2d1272b8SAndroid Build Coastguard Worker { 59*2d1272b8SAndroid Build Coastguard Worker if (is_cubic && !first_offcurve2) 60*2d1272b8SAndroid Build Coastguard Worker { 61*2d1272b8SAndroid Build Coastguard Worker first_offcurve2 = first_offcurve; 62*2d1272b8SAndroid Build Coastguard Worker first_offcurve = p; 63*2d1272b8SAndroid Build Coastguard Worker } 64*2d1272b8SAndroid Build Coastguard Worker else if (first_offcurve) 65*2d1272b8SAndroid Build Coastguard Worker { 66*2d1272b8SAndroid Build Coastguard Worker optional_point_t mid = first_offcurve.mid (p); 67*2d1272b8SAndroid Build Coastguard Worker first_oncurve = mid; 68*2d1272b8SAndroid Build Coastguard Worker last_offcurve = p; 69*2d1272b8SAndroid Build Coastguard Worker draw_session->move_to (mid.x, mid.y); 70*2d1272b8SAndroid Build Coastguard Worker } 71*2d1272b8SAndroid Build Coastguard Worker else 72*2d1272b8SAndroid Build Coastguard Worker first_offcurve = p; 73*2d1272b8SAndroid Build Coastguard Worker } 74*2d1272b8SAndroid Build Coastguard Worker } 75*2d1272b8SAndroid Build Coastguard Worker else 76*2d1272b8SAndroid Build Coastguard Worker { 77*2d1272b8SAndroid Build Coastguard Worker if (last_offcurve) 78*2d1272b8SAndroid Build Coastguard Worker { 79*2d1272b8SAndroid Build Coastguard Worker if (is_on_curve) 80*2d1272b8SAndroid Build Coastguard Worker { 81*2d1272b8SAndroid Build Coastguard Worker if (last_offcurve2) 82*2d1272b8SAndroid Build Coastguard Worker { 83*2d1272b8SAndroid Build Coastguard Worker draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, 84*2d1272b8SAndroid Build Coastguard Worker last_offcurve.x, last_offcurve.y, 85*2d1272b8SAndroid Build Coastguard Worker p.x, p.y); 86*2d1272b8SAndroid Build Coastguard Worker last_offcurve2 = optional_point_t (); 87*2d1272b8SAndroid Build Coastguard Worker } 88*2d1272b8SAndroid Build Coastguard Worker else 89*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, 90*2d1272b8SAndroid Build Coastguard Worker p.x, p.y); 91*2d1272b8SAndroid Build Coastguard Worker last_offcurve = optional_point_t (); 92*2d1272b8SAndroid Build Coastguard Worker } 93*2d1272b8SAndroid Build Coastguard Worker else 94*2d1272b8SAndroid Build Coastguard Worker { 95*2d1272b8SAndroid Build Coastguard Worker if (is_cubic && !last_offcurve2) 96*2d1272b8SAndroid Build Coastguard Worker { 97*2d1272b8SAndroid Build Coastguard Worker last_offcurve2 = last_offcurve; 98*2d1272b8SAndroid Build Coastguard Worker last_offcurve = p; 99*2d1272b8SAndroid Build Coastguard Worker } 100*2d1272b8SAndroid Build Coastguard Worker else 101*2d1272b8SAndroid Build Coastguard Worker { 102*2d1272b8SAndroid Build Coastguard Worker optional_point_t mid = last_offcurve.mid (p); 103*2d1272b8SAndroid Build Coastguard Worker 104*2d1272b8SAndroid Build Coastguard Worker if (is_cubic) 105*2d1272b8SAndroid Build Coastguard Worker { 106*2d1272b8SAndroid Build Coastguard Worker draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, 107*2d1272b8SAndroid Build Coastguard Worker last_offcurve.x, last_offcurve.y, 108*2d1272b8SAndroid Build Coastguard Worker mid.x, mid.y); 109*2d1272b8SAndroid Build Coastguard Worker last_offcurve2 = optional_point_t (); 110*2d1272b8SAndroid Build Coastguard Worker } 111*2d1272b8SAndroid Build Coastguard Worker else 112*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, 113*2d1272b8SAndroid Build Coastguard Worker mid.x, mid.y); 114*2d1272b8SAndroid Build Coastguard Worker last_offcurve = p; 115*2d1272b8SAndroid Build Coastguard Worker } 116*2d1272b8SAndroid Build Coastguard Worker } 117*2d1272b8SAndroid Build Coastguard Worker } 118*2d1272b8SAndroid Build Coastguard Worker else 119*2d1272b8SAndroid Build Coastguard Worker { 120*2d1272b8SAndroid Build Coastguard Worker if (is_on_curve) 121*2d1272b8SAndroid Build Coastguard Worker draw_session->line_to (p.x, p.y); 122*2d1272b8SAndroid Build Coastguard Worker else 123*2d1272b8SAndroid Build Coastguard Worker last_offcurve = p; 124*2d1272b8SAndroid Build Coastguard Worker } 125*2d1272b8SAndroid Build Coastguard Worker } 126*2d1272b8SAndroid Build Coastguard Worker 127*2d1272b8SAndroid Build Coastguard Worker if (unlikely (point.is_end_point)) 128*2d1272b8SAndroid Build Coastguard Worker { 129*2d1272b8SAndroid Build Coastguard Worker if (first_offcurve && last_offcurve) 130*2d1272b8SAndroid Build Coastguard Worker { 131*2d1272b8SAndroid Build Coastguard Worker optional_point_t mid = last_offcurve.mid (first_offcurve2 ? 132*2d1272b8SAndroid Build Coastguard Worker first_offcurve2 : 133*2d1272b8SAndroid Build Coastguard Worker first_offcurve); 134*2d1272b8SAndroid Build Coastguard Worker if (last_offcurve2) 135*2d1272b8SAndroid Build Coastguard Worker draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, 136*2d1272b8SAndroid Build Coastguard Worker last_offcurve.x, last_offcurve.y, 137*2d1272b8SAndroid Build Coastguard Worker mid.x, mid.y); 138*2d1272b8SAndroid Build Coastguard Worker else 139*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, 140*2d1272b8SAndroid Build Coastguard Worker mid.x, mid.y); 141*2d1272b8SAndroid Build Coastguard Worker last_offcurve = optional_point_t (); 142*2d1272b8SAndroid Build Coastguard Worker } 143*2d1272b8SAndroid Build Coastguard Worker /* now check the rest */ 144*2d1272b8SAndroid Build Coastguard Worker 145*2d1272b8SAndroid Build Coastguard Worker if (first_offcurve && first_oncurve) 146*2d1272b8SAndroid Build Coastguard Worker { 147*2d1272b8SAndroid Build Coastguard Worker if (first_offcurve2) 148*2d1272b8SAndroid Build Coastguard Worker draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y, 149*2d1272b8SAndroid Build Coastguard Worker first_offcurve.x, first_offcurve.y, 150*2d1272b8SAndroid Build Coastguard Worker first_oncurve.x, first_oncurve.y); 151*2d1272b8SAndroid Build Coastguard Worker else 152*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (first_offcurve.x, first_offcurve.y, 153*2d1272b8SAndroid Build Coastguard Worker first_oncurve.x, first_oncurve.y); 154*2d1272b8SAndroid Build Coastguard Worker } 155*2d1272b8SAndroid Build Coastguard Worker else if (last_offcurve && first_oncurve) 156*2d1272b8SAndroid Build Coastguard Worker { 157*2d1272b8SAndroid Build Coastguard Worker if (last_offcurve2) 158*2d1272b8SAndroid Build Coastguard Worker draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y, 159*2d1272b8SAndroid Build Coastguard Worker last_offcurve.x, last_offcurve.y, 160*2d1272b8SAndroid Build Coastguard Worker first_oncurve.x, first_oncurve.y); 161*2d1272b8SAndroid Build Coastguard Worker else 162*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (last_offcurve.x, last_offcurve.y, 163*2d1272b8SAndroid Build Coastguard Worker first_oncurve.x, first_oncurve.y); 164*2d1272b8SAndroid Build Coastguard Worker } 165*2d1272b8SAndroid Build Coastguard Worker else if (first_oncurve) 166*2d1272b8SAndroid Build Coastguard Worker draw_session->line_to (first_oncurve.x, first_oncurve.y); 167*2d1272b8SAndroid Build Coastguard Worker else if (first_offcurve) 168*2d1272b8SAndroid Build Coastguard Worker { 169*2d1272b8SAndroid Build Coastguard Worker float x = first_offcurve.x, y = first_offcurve.y; 170*2d1272b8SAndroid Build Coastguard Worker draw_session->move_to (x, y); 171*2d1272b8SAndroid Build Coastguard Worker draw_session->quadratic_to (x, y, x, y); 172*2d1272b8SAndroid Build Coastguard Worker } 173*2d1272b8SAndroid Build Coastguard Worker 174*2d1272b8SAndroid Build Coastguard Worker /* Getting ready for the next contour */ 175*2d1272b8SAndroid Build Coastguard Worker first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t (); 176*2d1272b8SAndroid Build Coastguard Worker draw_session->close_path (); 177*2d1272b8SAndroid Build Coastguard Worker } 178*2d1272b8SAndroid Build Coastguard Worker } points_endOT::glyf_impl::path_builder_t179*2d1272b8SAndroid Build Coastguard Worker void points_end () {} 180*2d1272b8SAndroid Build Coastguard Worker is_consuming_contour_pointsOT::glyf_impl::path_builder_t181*2d1272b8SAndroid Build Coastguard Worker bool is_consuming_contour_points () { return true; } get_phantoms_sinkOT::glyf_impl::path_builder_t182*2d1272b8SAndroid Build Coastguard Worker contour_point_t *get_phantoms_sink () { return nullptr; } 183*2d1272b8SAndroid Build Coastguard Worker }; 184*2d1272b8SAndroid Build Coastguard Worker 185*2d1272b8SAndroid Build Coastguard Worker 186*2d1272b8SAndroid Build Coastguard Worker } /* namespace glyf_impl */ 187*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 188*2d1272b8SAndroid Build Coastguard Worker 189*2d1272b8SAndroid Build Coastguard Worker 190*2d1272b8SAndroid Build Coastguard Worker #endif /* OT_GLYF_PATH_BUILDER_HH */ 191