1 /* 2 * Copyright © 2018 Adobe Inc. 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 * Adobe Author(s): Michiharu Ariza 25 */ 26 27 #include "hb-ot-cff2-table.hh" 28 #include "hb-cff2-interp-cs.hh" 29 30 using namespace CFF; 31 32 struct extents_param_t 33 { 34 void init () 35 { 36 path_open = false; 37 min_x.set_int (0x7FFFFFFF); 38 min_y.set_int (0x7FFFFFFF); 39 max_x.set_int (-0x80000000); 40 max_y.set_int (-0x80000000); 41 } 42 43 void start_path () { path_open = true; } 44 void end_path () { path_open = false; } 45 bool is_path_open () const { return path_open; } 46 47 void update_bounds (const point_t &pt) 48 { 49 if (pt.x < min_x) min_x = pt.x; 50 if (pt.x > max_x) max_x = pt.x; 51 if (pt.y < min_y) min_y = pt.y; 52 if (pt.y > max_y) max_y = pt.y; 53 } 54 55 bool path_open; 56 number_t min_x; 57 number_t min_y; 58 number_t max_x; 59 number_t max_y; 60 }; 61 62 struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t> 63 { 64 static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt) 65 { 66 param.end_path (); 67 env.moveto (pt); 68 } 69 70 static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1) 71 { 72 if (!param.is_path_open ()) 73 { 74 param.start_path (); 75 param.update_bounds (env.get_pt ()); 76 } 77 env.moveto (pt1); 78 param.update_bounds (env.get_pt ()); 79 } 80 81 static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) 82 { 83 if (!param.is_path_open ()) 84 { 85 param.start_path (); 86 param.update_bounds (env.get_pt ()); 87 } 88 /* include control points */ 89 param.update_bounds (pt1); 90 param.update_bounds (pt2); 91 env.moveto (pt3); 92 param.update_bounds (env.get_pt ()); 93 } 94 }; 95 96 struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {}; 97 98 bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, 99 hb_codepoint_t glyph, 100 hb_glyph_extents_t *extents) const 101 { 102 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; 103 104 unsigned int num_coords; 105 const int *coords = hb_font_get_var_coords_normalized (font, &num_coords); 106 unsigned int fd = fdSelect->get_fd (glyph); 107 cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp; 108 const byte_str_t str = (*charStrings)[glyph]; 109 interp.env.init (str, *this, fd, coords, num_coords); 110 extents_param_t param; 111 param.init (); 112 if (unlikely (!interp.interpret (param))) return false; 113 114 if (param.min_x >= param.max_x) 115 { 116 extents->width = 0; 117 extents->x_bearing = 0; 118 } 119 else 120 { 121 extents->x_bearing = (int32_t)param.min_x.floor (); 122 extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing; 123 } 124 if (param.min_y >= param.max_y) 125 { 126 extents->height = 0; 127 extents->y_bearing = 0; 128 } 129 else 130 { 131 extents->y_bearing = (int32_t)param.max_y.ceil (); 132 extents->height = (int32_t)param.min_y.floor () - extents->y_bearing; 133 } 134 135 return true; 136 }