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 #ifndef HB_CFF1_INTERP_CS_HH 27 #define HB_CFF1_INTERP_CS_HH 28 29 #include "hb.hh" 30 #include "hb-cff-interp-cs-common.hh" 31 32 namespace CFF { 33 34 using namespace OT; 35 36 typedef BiasedSubrs<CFF1Subrs> CFF1BiasedSubrs; 37 38 struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs> 39 { 40 template <typename ACC> initCFF::CFF1CSInterpEnv41 void init (const ByteStr &str, ACC &acc, unsigned int fd) 42 { 43 SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs); 44 processed_width = false; 45 has_width = false; 46 arg_start = 0; 47 in_seac = false; 48 } 49 finiCFF::CFF1CSInterpEnv50 void fini () { SUPER::fini (); } 51 set_widthCFF::CFF1CSInterpEnv52 void set_width (bool has_width_) 53 { 54 if (likely (!processed_width && (SUPER::argStack.get_count () > 0))) 55 { 56 if (has_width_) 57 { 58 width = SUPER::argStack[0]; 59 has_width = true; 60 arg_start = 1; 61 } 62 } 63 processed_width = true; 64 } 65 clear_argsCFF::CFF1CSInterpEnv66 void clear_args () 67 { 68 arg_start = 0; 69 SUPER::clear_args (); 70 } 71 set_in_seacCFF::CFF1CSInterpEnv72 void set_in_seac (bool _in_seac) { in_seac = _in_seac; } 73 74 bool processed_width; 75 bool has_width; 76 unsigned int arg_start; 77 Number width; 78 bool in_seac; 79 80 private: 81 typedef CSInterpEnv<Number, CFF1Subrs> SUPER; 82 }; 83 84 template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF1CSInterpEnv, PARAM> > 85 struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH> 86 { 87 /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */ 88 /* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */ 89 process_opCFF::CFF1CSOpSet90 static void process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param) 91 { 92 switch (op) { 93 case OpCode_dotsection: 94 SUPER::flush_args_and_op (op, env, param); 95 break; 96 97 case OpCode_endchar: 98 OPSET::check_width (op, env, param); 99 if (env.argStack.get_count () >= 4) 100 { 101 OPSET::process_seac (env, param); 102 } 103 OPSET::flush_args_and_op (op, env, param); 104 env.set_endchar (true); 105 break; 106 107 default: 108 SUPER::process_op (op, env, param); 109 } 110 } 111 check_widthCFF::CFF1CSOpSet112 static void check_width (OpCode op, CFF1CSInterpEnv &env, PARAM& param) 113 { 114 if (!env.processed_width) 115 { 116 bool has_width = false; 117 switch (op) 118 { 119 case OpCode_endchar: 120 case OpCode_hstem: 121 case OpCode_hstemhm: 122 case OpCode_vstem: 123 case OpCode_vstemhm: 124 case OpCode_hintmask: 125 case OpCode_cntrmask: 126 has_width = ((env.argStack.get_count () & 1) != 0); 127 break; 128 case OpCode_hmoveto: 129 case OpCode_vmoveto: 130 has_width = (env.argStack.get_count () > 1); 131 break; 132 case OpCode_rmoveto: 133 has_width = (env.argStack.get_count () > 2); 134 break; 135 default: 136 return; 137 } 138 env.set_width (has_width); 139 } 140 } 141 process_seacCFF::CFF1CSOpSet142 static void process_seac (CFF1CSInterpEnv &env, PARAM& param) 143 { 144 } 145 flush_argsCFF::CFF1CSOpSet146 static void flush_args (CFF1CSInterpEnv &env, PARAM& param) 147 { 148 SUPER::flush_args (env, param); 149 env.clear_args (); /* pop off width */ 150 } 151 152 private: 153 typedef CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH> SUPER; 154 }; 155 156 template <typename OPSET, typename PARAM> 157 struct CFF1CSInterpreter : CSInterpreter<CFF1CSInterpEnv, OPSET, PARAM> {}; 158 159 } /* namespace CFF */ 160 161 #endif /* HB_CFF1_INTERP_CS_HH */ 162