hb-ot-cff1-table.cc (23687B)
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.hh" 28 29 #ifndef HB_NO_CFF 30 31 #include "hb-draw.hh" 32 #include "hb-algs.hh" 33 #include "hb-ot-cff1-table.hh" 34 #include "hb-cff1-interp-cs.hh" 35 36 using namespace CFF; 37 38 struct sid_to_gid_t 39 { 40 uint16_t sid; 41 uint8_t gid; 42 43 int cmp (uint16_t a) const 44 { 45 if (a == sid) return 0; 46 return (a < sid) ? -1 : 1; 47 } 48 }; 49 50 /* SID to code */ 51 static const uint8_t standard_encoding_to_code [] = 52 { 53 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 54 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 55 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 56 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 57 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 58 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 59 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 60 178, 179, 180, 182, 183, 184, 185, 186, 187, 188, 189, 191, 193, 194, 195, 196, 61 197, 198, 199, 200, 202, 203, 205, 206, 207, 208, 225, 227, 232, 233, 234, 235, 62 241, 245, 248, 249, 250, 251 63 }; 64 65 /* SID to code */ 66 static const uint8_t expert_encoding_to_code [] = 67 { 68 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45, 46, 69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 59, 0, 0, 0, 70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, 0, 75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 0, 189, 0, 0, 188, 0, 78 0, 0, 0, 190, 202, 0, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82 0, 0, 0, 0, 0, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 48, 83 49, 50, 51, 52, 53, 54, 55, 56, 57, 60, 61, 62, 63, 65, 66, 67, 84 68, 69, 73, 76, 77, 78, 79, 82, 83, 84, 86, 89, 90, 91, 93, 94, 85 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 86 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 87 161, 162, 163, 166, 167, 168, 169, 170, 172, 175, 178, 179, 182, 183, 184, 191, 88 192, 193, 194, 195, 196, 197, 200, 204, 205, 206, 207, 208, 209, 210, 211, 212, 89 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 90 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 91 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 92 }; 93 94 /* glyph ID to SID */ 95 static const uint16_t expert_charset_to_sid [] = 96 { 97 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99, 98 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252, 99 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 100 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 101 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 102 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 103 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150, 104 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 105 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 106 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 107 373, 374, 375, 376, 377, 378 108 }; 109 110 /* glyph ID to SID */ 111 static const uint16_t expert_subset_charset_to_sid [] = 112 { 113 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242, 114 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257, 115 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272, 116 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326, 117 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 118 340, 341, 342, 343, 344, 345, 346 119 }; 120 121 /* SID to glyph ID */ 122 static const sid_to_gid_t expert_charset_sid_to_gid [] = 123 { 124 { 1, 1 }, { 13, 12 }, { 14, 13 }, { 15, 14 }, 125 { 27, 26 }, { 28, 27 }, { 99, 15 }, { 109, 46 }, 126 { 110, 47 }, { 150, 111 }, { 155, 101 }, { 158, 100 }, 127 { 163, 102 }, { 164, 112 }, { 169, 113 }, { 229, 2 }, 128 { 230, 3 }, { 231, 4 }, { 232, 5 }, { 233, 6 }, 129 { 234, 7 }, { 235, 8 }, { 236, 9 }, { 237, 10 }, 130 { 238, 11 }, { 239, 16 }, { 240, 17 }, { 241, 18 }, 131 { 242, 19 }, { 243, 20 }, { 244, 21 }, { 245, 22 }, 132 { 246, 23 }, { 247, 24 }, { 248, 25 }, { 249, 28 }, 133 { 250, 29 }, { 251, 30 }, { 252, 31 }, { 253, 32 }, 134 { 254, 33 }, { 255, 34 }, { 256, 35 }, { 257, 36 }, 135 { 258, 37 }, { 259, 38 }, { 260, 39 }, { 261, 40 }, 136 { 262, 41 }, { 263, 42 }, { 264, 43 }, { 265, 44 }, 137 { 266, 45 }, { 267, 48 }, { 268, 49 }, { 269, 50 }, 138 { 270, 51 }, { 271, 52 }, { 272, 53 }, { 273, 54 }, 139 { 274, 55 }, { 275, 56 }, { 276, 57 }, { 277, 58 }, 140 { 278, 59 }, { 279, 60 }, { 280, 61 }, { 281, 62 }, 141 { 282, 63 }, { 283, 64 }, { 284, 65 }, { 285, 66 }, 142 { 286, 67 }, { 287, 68 }, { 288, 69 }, { 289, 70 }, 143 { 290, 71 }, { 291, 72 }, { 292, 73 }, { 293, 74 }, 144 { 294, 75 }, { 295, 76 }, { 296, 77 }, { 297, 78 }, 145 { 298, 79 }, { 299, 80 }, { 300, 81 }, { 301, 82 }, 146 { 302, 83 }, { 303, 84 }, { 304, 85 }, { 305, 86 }, 147 { 306, 87 }, { 307, 88 }, { 308, 89 }, { 309, 90 }, 148 { 310, 91 }, { 311, 92 }, { 312, 93 }, { 313, 94 }, 149 { 314, 95 }, { 315, 96 }, { 316, 97 }, { 317, 98 }, 150 { 318, 99 }, { 319, 103 }, { 320, 104 }, { 321, 105 }, 151 { 322, 106 }, { 323, 107 }, { 324, 108 }, { 325, 109 }, 152 { 326, 110 }, { 327, 114 }, { 328, 115 }, { 329, 116 }, 153 { 330, 117 }, { 331, 118 }, { 332, 119 }, { 333, 120 }, 154 { 334, 121 }, { 335, 122 }, { 336, 123 }, { 337, 124 }, 155 { 338, 125 }, { 339, 126 }, { 340, 127 }, { 341, 128 }, 156 { 342, 129 }, { 343, 130 }, { 344, 131 }, { 345, 132 }, 157 { 346, 133 }, { 347, 134 }, { 348, 135 }, { 349, 136 }, 158 { 350, 137 }, { 351, 138 }, { 352, 139 }, { 353, 140 }, 159 { 354, 141 }, { 355, 142 }, { 356, 143 }, { 357, 144 }, 160 { 358, 145 }, { 359, 146 }, { 360, 147 }, { 361, 148 }, 161 { 362, 149 }, { 363, 150 }, { 364, 151 }, { 365, 152 }, 162 { 366, 153 }, { 367, 154 }, { 368, 155 }, { 369, 156 }, 163 { 370, 157 }, { 371, 158 }, { 372, 159 }, { 373, 160 }, 164 { 374, 161 }, { 375, 162 }, { 376, 163 }, { 377, 164 }, 165 { 378, 165 } 166 }; 167 168 /* SID to glyph ID */ 169 static const sid_to_gid_t expert_subset_charset_sid_to_gid [] = 170 { 171 { 1, 1 }, { 13, 8 }, { 14, 9 }, { 15, 10 }, 172 { 27, 22 }, { 28, 23 }, { 99, 11 }, { 109, 41 }, 173 { 110, 42 }, { 150, 64 }, { 155, 55 }, { 158, 54 }, 174 { 163, 56 }, { 164, 65 }, { 169, 66 }, { 231, 2 }, 175 { 232, 3 }, { 235, 4 }, { 236, 5 }, { 237, 6 }, 176 { 238, 7 }, { 239, 12 }, { 240, 13 }, { 241, 14 }, 177 { 242, 15 }, { 243, 16 }, { 244, 17 }, { 245, 18 }, 178 { 246, 19 }, { 247, 20 }, { 248, 21 }, { 249, 24 }, 179 { 250, 25 }, { 251, 26 }, { 253, 27 }, { 254, 28 }, 180 { 255, 29 }, { 256, 30 }, { 257, 31 }, { 258, 32 }, 181 { 259, 33 }, { 260, 34 }, { 261, 35 }, { 262, 36 }, 182 { 263, 37 }, { 264, 38 }, { 265, 39 }, { 266, 40 }, 183 { 267, 43 }, { 268, 44 }, { 269, 45 }, { 270, 46 }, 184 { 272, 47 }, { 300, 48 }, { 301, 49 }, { 302, 50 }, 185 { 305, 51 }, { 314, 52 }, { 315, 53 }, { 320, 57 }, 186 { 321, 58 }, { 322, 59 }, { 323, 60 }, { 324, 61 }, 187 { 325, 62 }, { 326, 63 }, { 327, 67 }, { 328, 68 }, 188 { 329, 69 }, { 330, 70 }, { 331, 71 }, { 332, 72 }, 189 { 333, 73 }, { 334, 74 }, { 335, 75 }, { 336, 76 }, 190 { 337, 77 }, { 338, 78 }, { 339, 79 }, { 340, 80 }, 191 { 341, 81 }, { 342, 82 }, { 343, 83 }, { 344, 84 }, 192 { 345, 85 }, { 346, 86 } 193 }; 194 195 /* code to SID */ 196 static const uint8_t standard_encoding_to_sid [] = 197 { 198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 201 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 202 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 203 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 204 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 205 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 209 0, 111, 112, 113, 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, 0, 123, 210 0, 124, 125, 126, 127, 128, 129, 130, 131, 0, 132, 133, 0, 134, 135, 136, 211 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212 0, 138, 0, 139, 0, 0, 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, 213 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, 148, 149, 0, 0, 0, 0 214 }; 215 216 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid) 217 { 218 if (sid < ARRAY_LENGTH (standard_encoding_to_code)) 219 return (hb_codepoint_t)standard_encoding_to_code[sid]; 220 else 221 return 0; 222 } 223 224 hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid) 225 { 226 if (sid < ARRAY_LENGTH (expert_encoding_to_code)) 227 return (hb_codepoint_t)expert_encoding_to_code[sid]; 228 else 229 return 0; 230 } 231 232 hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph) 233 { 234 if (glyph < ARRAY_LENGTH (expert_charset_to_sid)) 235 return (hb_codepoint_t)expert_charset_to_sid[glyph]; 236 else 237 return 0; 238 } 239 240 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph) 241 { 242 if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid)) 243 return (hb_codepoint_t)expert_subset_charset_to_sid[glyph]; 244 else 245 return 0; 246 } 247 248 hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid) 249 { 250 const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid); 251 return pair ? pair->gid : 0; 252 } 253 254 hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid) 255 { 256 const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid); 257 return pair ? pair->gid : 0; 258 } 259 260 hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code) 261 { 262 if (code < ARRAY_LENGTH (standard_encoding_to_sid)) 263 return (hb_codepoint_t)standard_encoding_to_sid[code]; 264 else 265 return CFF_UNDEF_SID; 266 } 267 268 struct bounds_t 269 { 270 void init () 271 { 272 min.set_int (INT_MAX, INT_MAX); 273 max.set_int (INT_MIN, INT_MIN); 274 } 275 276 void update (const point_t &pt) 277 { 278 if (pt.x < min.x) min.x = pt.x; 279 if (pt.x > max.x) max.x = pt.x; 280 if (pt.y < min.y) min.y = pt.y; 281 if (pt.y > max.y) max.y = pt.y; 282 } 283 284 void merge (const bounds_t &b) 285 { 286 if (empty ()) 287 *this = b; 288 else if (!b.empty ()) 289 { 290 if (b.min.x < min.x) min.x = b.min.x; 291 if (b.max.x > max.x) max.x = b.max.x; 292 if (b.min.y < min.y) min.y = b.min.y; 293 if (b.max.y > max.y) max.y = b.max.y; 294 } 295 } 296 297 void offset (const point_t &delta) 298 { 299 if (!empty ()) 300 { 301 min.move (delta); 302 max.move (delta); 303 } 304 } 305 306 bool empty () const { return (min.x >= max.x) || (min.y >= max.y); } 307 308 point_t min; 309 point_t max; 310 }; 311 312 struct cff1_extents_param_t 313 { 314 cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) 315 { 316 bounds.init (); 317 } 318 319 void start_path () { path_open = true; } 320 void end_path () { path_open = false; } 321 bool is_path_open () const { return path_open; } 322 323 bool path_open = false; 324 bounds_t bounds; 325 326 const OT::cff1::accelerator_t *cff; 327 }; 328 329 struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t> 330 { 331 static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt) 332 { 333 param.end_path (); 334 env.moveto (pt); 335 } 336 337 static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1) 338 { 339 if (!param.is_path_open ()) 340 { 341 param.start_path (); 342 param.bounds.update (env.get_pt ()); 343 } 344 env.moveto (pt1); 345 param.bounds.update (env.get_pt ()); 346 } 347 348 static void curve (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) 349 { 350 if (!param.is_path_open ()) 351 { 352 param.start_path (); 353 param.bounds.update (env.get_pt ()); 354 } 355 /* include control points */ 356 param.bounds.update (pt1); 357 param.bounds.update (pt2); 358 env.moveto (pt3); 359 param.bounds.update (env.get_pt ()); 360 } 361 }; 362 363 static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false); 364 365 struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t> 366 { 367 static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param) 368 { 369 unsigned int n = env.argStack.get_count (); 370 point_t delta; 371 delta.x = env.argStack[n-4]; 372 delta.y = env.argStack[n-3]; 373 hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ()); 374 hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); 375 376 bounds_t base_bounds, accent_bounds; 377 if (likely (!env.in_seac && base && accent 378 && _get_bounds (param.cff, base, base_bounds, true) 379 && _get_bounds (param.cff, accent, accent_bounds, true))) 380 { 381 param.bounds.merge (base_bounds); 382 accent_bounds.offset (delta); 383 param.bounds.merge (accent_bounds); 384 } 385 else 386 env.set_error (); 387 } 388 }; 389 390 bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac) 391 { 392 bounds.init (); 393 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; 394 395 unsigned int fd = cff->fdSelect->get_fd (glyph); 396 const hb_ubytes_t str = (*cff->charStrings)[glyph]; 397 cff1_cs_interp_env_t env (str, *cff, fd); 398 env.set_in_seac (in_seac); 399 cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env); 400 cff1_extents_param_t param (cff); 401 if (unlikely (!interp.interpret (param))) return false; 402 bounds = param.bounds; 403 return true; 404 } 405 406 bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const 407 { 408 #ifdef HB_NO_OT_FONT_CFF 409 /* XXX Remove check when this code moves to .hh file. */ 410 return true; 411 #endif 412 413 bounds_t bounds; 414 415 if (!_get_bounds (this, glyph, bounds)) 416 return false; 417 418 if (bounds.min.x >= bounds.max.x) 419 { 420 extents->width = 0; 421 extents->x_bearing = 0; 422 } 423 else 424 { 425 extents->x_bearing = roundf (bounds.min.x.to_real ()); 426 extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing); 427 } 428 if (bounds.min.y >= bounds.max.y) 429 { 430 extents->height = 0; 431 extents->y_bearing = 0; 432 } 433 else 434 { 435 extents->y_bearing = roundf (bounds.max.y.to_real ()); 436 extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing); 437 } 438 439 font->scale_glyph_extents (extents); 440 441 return true; 442 } 443 444 struct cff1_path_param_t 445 { 446 cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, 447 hb_draw_session_t &draw_session_, point_t *delta_) 448 { 449 draw_session = &draw_session_; 450 cff = cff_; 451 font = font_; 452 delta = delta_; 453 } 454 455 void move_to (const point_t &p) 456 { 457 point_t point = p; 458 if (delta) point.move (*delta); 459 draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); 460 } 461 462 void line_to (const point_t &p) 463 { 464 point_t point = p; 465 if (delta) point.move (*delta); 466 draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ())); 467 } 468 469 void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) 470 { 471 point_t point1 = p1, point2 = p2, point3 = p3; 472 if (delta) 473 { 474 point1.move (*delta); 475 point2.move (*delta); 476 point3.move (*delta); 477 } 478 draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()), 479 font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()), 480 font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ())); 481 } 482 483 void end_path () { draw_session->close_path (); } 484 485 hb_font_t *font; 486 hb_draw_session_t *draw_session; 487 point_t *delta; 488 489 const OT::cff1::accelerator_t *cff; 490 }; 491 492 struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t> 493 { 494 static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt) 495 { 496 param.move_to (pt); 497 env.moveto (pt); 498 } 499 500 static void line (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1) 501 { 502 param.line_to (pt1); 503 env.moveto (pt1); 504 } 505 506 static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1, const point_t &pt2, const point_t &pt3) 507 { 508 param.cubic_to (pt1, pt2, pt3); 509 env.moveto (pt3); 510 } 511 }; 512 513 static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, 514 hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr); 515 516 struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t> 517 { 518 static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param) 519 { 520 /* End previous path */ 521 param.end_path (); 522 523 unsigned int n = env.argStack.get_count (); 524 point_t delta; 525 delta.x = env.argStack[n-4]; 526 delta.y = env.argStack[n-3]; 527 hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ()); 528 hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); 529 530 if (unlikely (!(!env.in_seac && base && accent 531 && _get_path (param.cff, param.font, base, *param.draw_session, true) 532 && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta)))) 533 env.set_error (); 534 } 535 }; 536 537 bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, 538 hb_draw_session_t &draw_session, bool in_seac, point_t *delta) 539 { 540 if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; 541 542 unsigned int fd = cff->fdSelect->get_fd (glyph); 543 const hb_ubytes_t str = (*cff->charStrings)[glyph]; 544 cff1_cs_interp_env_t env (str, *cff, fd); 545 env.set_in_seac (in_seac); 546 cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env); 547 cff1_path_param_t param (cff, font, draw_session, delta); 548 if (unlikely (!interp.interpret (param))) return false; 549 550 /* Let's end the path specially since it is called inside seac also */ 551 param.end_path (); 552 553 return true; 554 } 555 556 bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const 557 { 558 #ifdef HB_NO_OT_FONT_CFF 559 /* XXX Remove check when this code moves to .hh file. */ 560 return true; 561 #endif 562 563 return _get_path (this, font, glyph, draw_session); 564 } 565 566 struct get_seac_param_t 567 { 568 get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {} 569 570 bool has_seac () const { return base && accent; } 571 572 const OT::cff1::accelerator_subset_t *cff; 573 hb_codepoint_t base = 0; 574 hb_codepoint_t accent = 0; 575 }; 576 577 struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t> 578 { 579 static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param) 580 { 581 unsigned int n = env.argStack.get_count (); 582 hb_codepoint_t base_char = (hb_codepoint_t)env.argStack[n-2].to_int (); 583 hb_codepoint_t accent_char = (hb_codepoint_t)env.argStack[n-1].to_int (); 584 585 param.base = param.cff->std_code_to_glyph (base_char); 586 param.accent = param.cff->std_code_to_glyph (accent_char); 587 } 588 }; 589 590 bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const 591 { 592 if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; 593 594 unsigned int fd = fdSelect->get_fd (glyph); 595 const hb_ubytes_t str = (*charStrings)[glyph]; 596 cff1_cs_interp_env_t env (str, *this, fd); 597 cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env); 598 get_seac_param_t param (this); 599 if (unlikely (!interp.interpret (param))) return false; 600 601 if (param.has_seac ()) 602 { 603 *base = param.base; 604 *accent = param.accent; 605 return true; 606 } 607 return false; 608 } 609 610 611 #endif