1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright © 2018 Adobe Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * This is part of HarfBuzz, a text shaping library. 5cb93a386Sopenharmony_ci * 6cb93a386Sopenharmony_ci * Permission is hereby granted, without written agreement and without 7cb93a386Sopenharmony_ci * license or royalty fees, to use, copy, modify, and distribute this 8cb93a386Sopenharmony_ci * software and its documentation for any purpose, provided that the 9cb93a386Sopenharmony_ci * above copyright notice and the following two paragraphs appear in 10cb93a386Sopenharmony_ci * all copies of this software. 11cb93a386Sopenharmony_ci * 12cb93a386Sopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13cb93a386Sopenharmony_ci * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14cb93a386Sopenharmony_ci * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15cb93a386Sopenharmony_ci * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16cb93a386Sopenharmony_ci * DAMAGE. 17cb93a386Sopenharmony_ci * 18cb93a386Sopenharmony_ci * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19cb93a386Sopenharmony_ci * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20cb93a386Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21cb93a386Sopenharmony_ci * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22cb93a386Sopenharmony_ci * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23cb93a386Sopenharmony_ci * 24cb93a386Sopenharmony_ci * Adobe Author(s): Michiharu Ariza 25cb93a386Sopenharmony_ci */ 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci#include "hb.hh" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci#ifndef HB_NO_OT_FONT_CFF 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci#include "hb-ot-cff2-table.hh" 32cb93a386Sopenharmony_ci#include "hb-cff2-interp-cs.hh" 33cb93a386Sopenharmony_ci#include "hb-draw.hh" 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ciusing namespace CFF; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_cistruct cff2_extents_param_t 38cb93a386Sopenharmony_ci{ 39cb93a386Sopenharmony_ci void init () 40cb93a386Sopenharmony_ci { 41cb93a386Sopenharmony_ci path_open = false; 42cb93a386Sopenharmony_ci min_x.set_int (INT_MAX); 43cb93a386Sopenharmony_ci min_y.set_int (INT_MAX); 44cb93a386Sopenharmony_ci max_x.set_int (INT_MIN); 45cb93a386Sopenharmony_ci max_y.set_int (INT_MIN); 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci void start_path () { path_open = true; } 49cb93a386Sopenharmony_ci void end_path () { path_open = false; } 50cb93a386Sopenharmony_ci bool is_path_open () const { return path_open; } 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci void update_bounds (const point_t &pt) 53cb93a386Sopenharmony_ci { 54cb93a386Sopenharmony_ci if (pt.x < min_x) min_x = pt.x; 55cb93a386Sopenharmony_ci if (pt.x > max_x) max_x = pt.x; 56cb93a386Sopenharmony_ci if (pt.y < min_y) min_y = pt.y; 57cb93a386Sopenharmony_ci if (pt.y > max_y) max_y = pt.y; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci bool path_open; 61cb93a386Sopenharmony_ci number_t min_x; 62cb93a386Sopenharmony_ci number_t min_y; 63cb93a386Sopenharmony_ci number_t max_x; 64cb93a386Sopenharmony_ci number_t max_y; 65cb93a386Sopenharmony_ci}; 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cistruct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t> 68cb93a386Sopenharmony_ci{ 69cb93a386Sopenharmony_ci static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt) 70cb93a386Sopenharmony_ci { 71cb93a386Sopenharmony_ci param.end_path (); 72cb93a386Sopenharmony_ci env.moveto (pt); 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1) 76cb93a386Sopenharmony_ci { 77cb93a386Sopenharmony_ci if (!param.is_path_open ()) 78cb93a386Sopenharmony_ci { 79cb93a386Sopenharmony_ci param.start_path (); 80cb93a386Sopenharmony_ci param.update_bounds (env.get_pt ()); 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci env.moveto (pt1); 83cb93a386Sopenharmony_ci param.update_bounds (env.get_pt ()); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) 87cb93a386Sopenharmony_ci { 88cb93a386Sopenharmony_ci if (!param.is_path_open ()) 89cb93a386Sopenharmony_ci { 90cb93a386Sopenharmony_ci param.start_path (); 91cb93a386Sopenharmony_ci param.update_bounds (env.get_pt ()); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci /* include control points */ 94cb93a386Sopenharmony_ci param.update_bounds (pt1); 95cb93a386Sopenharmony_ci param.update_bounds (pt2); 96cb93a386Sopenharmony_ci env.moveto (pt3); 97cb93a386Sopenharmony_ci param.update_bounds (env.get_pt ()); 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci}; 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_cistruct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {}; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cibool OT::cff2::accelerator_t::get_extents (hb_font_t *font, 104cb93a386Sopenharmony_ci hb_codepoint_t glyph, 105cb93a386Sopenharmony_ci hb_glyph_extents_t *extents) const 106cb93a386Sopenharmony_ci{ 107cb93a386Sopenharmony_ci#ifdef HB_NO_OT_FONT_CFF 108cb93a386Sopenharmony_ci /* XXX Remove check when this code moves to .hh file. */ 109cb93a386Sopenharmony_ci return true; 110cb93a386Sopenharmony_ci#endif 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci unsigned int fd = fdSelect->get_fd (glyph); 115cb93a386Sopenharmony_ci cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp; 116cb93a386Sopenharmony_ci const byte_str_t str = (*charStrings)[glyph]; 117cb93a386Sopenharmony_ci interp.env.init (str, *this, fd, font->coords, font->num_coords); 118cb93a386Sopenharmony_ci cff2_extents_param_t param; 119cb93a386Sopenharmony_ci param.init (); 120cb93a386Sopenharmony_ci if (unlikely (!interp.interpret (param))) return false; 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci if (param.min_x >= param.max_x) 123cb93a386Sopenharmony_ci { 124cb93a386Sopenharmony_ci extents->width = 0; 125cb93a386Sopenharmony_ci extents->x_bearing = 0; 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci else 128cb93a386Sopenharmony_ci { 129cb93a386Sopenharmony_ci extents->x_bearing = font->em_scalef_x (param.min_x.to_real ()); 130cb93a386Sopenharmony_ci extents->width = font->em_scalef_x (param.max_x.to_real ()) - extents->x_bearing; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci if (param.min_y >= param.max_y) 133cb93a386Sopenharmony_ci { 134cb93a386Sopenharmony_ci extents->height = 0; 135cb93a386Sopenharmony_ci extents->y_bearing = 0; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci else 138cb93a386Sopenharmony_ci { 139cb93a386Sopenharmony_ci extents->y_bearing = font->em_scalef_y (param.max_y.to_real ()); 140cb93a386Sopenharmony_ci extents->height = font->em_scalef_y (param.min_y.to_real ()) - extents->y_bearing; 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci return true; 144cb93a386Sopenharmony_ci} 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci#ifdef HB_EXPERIMENTAL_API 147cb93a386Sopenharmony_cistruct cff2_path_param_t 148cb93a386Sopenharmony_ci{ 149cb93a386Sopenharmony_ci cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_) 150cb93a386Sopenharmony_ci { 151cb93a386Sopenharmony_ci draw_helper = &draw_helper_; 152cb93a386Sopenharmony_ci font = font_; 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci void move_to (const point_t &p) 156cb93a386Sopenharmony_ci { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci void line_to (const point_t &p) 159cb93a386Sopenharmony_ci { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); } 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) 162cb93a386Sopenharmony_ci { 163cb93a386Sopenharmony_ci draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()), 164cb93a386Sopenharmony_ci font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()), 165cb93a386Sopenharmony_ci font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ())); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci protected: 169cb93a386Sopenharmony_ci draw_helper_t *draw_helper; 170cb93a386Sopenharmony_ci hb_font_t *font; 171cb93a386Sopenharmony_ci}; 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_cistruct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t> 174cb93a386Sopenharmony_ci{ 175cb93a386Sopenharmony_ci static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt) 176cb93a386Sopenharmony_ci { 177cb93a386Sopenharmony_ci param.move_to (pt); 178cb93a386Sopenharmony_ci env.moveto (pt); 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1) 182cb93a386Sopenharmony_ci { 183cb93a386Sopenharmony_ci param.line_to (pt1); 184cb93a386Sopenharmony_ci env.moveto (pt1); 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) 188cb93a386Sopenharmony_ci { 189cb93a386Sopenharmony_ci param.cubic_to (pt1, pt2, pt3); 190cb93a386Sopenharmony_ci env.moveto (pt3); 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci}; 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cistruct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {}; 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_cibool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const 197cb93a386Sopenharmony_ci{ 198cb93a386Sopenharmony_ci#ifdef HB_NO_OT_FONT_CFF 199cb93a386Sopenharmony_ci /* XXX Remove check when this code moves to .hh file. */ 200cb93a386Sopenharmony_ci return true; 201cb93a386Sopenharmony_ci#endif 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci unsigned int fd = fdSelect->get_fd (glyph); 206cb93a386Sopenharmony_ci cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp; 207cb93a386Sopenharmony_ci const byte_str_t str = (*charStrings)[glyph]; 208cb93a386Sopenharmony_ci interp.env.init (str, *this, fd, font->coords, font->num_coords); 209cb93a386Sopenharmony_ci cff2_path_param_t param (font, draw_helper); 210cb93a386Sopenharmony_ci if (unlikely (!interp.interpret (param))) return false; 211cb93a386Sopenharmony_ci return true; 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci#endif 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci#endif 216