/* * Copyright © 2018 Adobe Inc. * * This is part of HarfBuzz, a text shaping library. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Adobe Author(s): Michiharu Ariza */ #ifndef HB_CFF_INTERP_DICT_COMMON_HH #define HB_CFF_INTERP_DICT_COMMON_HH #include "hb-cff-interp-common.hh" namespace CFF { using namespace OT; /* an opstr and the parsed out dict value(s) */ struct dict_val_t : op_str_t { void init () { single_val.set_int (0); } void fini () {} number_t single_val; }; typedef dict_val_t num_dict_val_t; template struct dict_values_t : parsed_values_t {}; template struct top_dict_values_t : dict_values_t { void init () { dict_values_t::init (); charStringsOffset = 0; FDArrayOffset = 0; } void fini () { dict_values_t::fini (); } unsigned int charStringsOffset; unsigned int FDArrayOffset; }; struct dict_opset_t : opset_t { static void process_op (op_code_t op, interp_env_t& env) { switch (op) { case OpCode_longintdict: /* 5-byte integer */ env.argStack.push_longint_from_substr (env.str_ref); break; case OpCode_BCD: /* real number */ env.argStack.push_real (parse_bcd (env.str_ref)); break; default: opset_t::process_op (op, env); break; } } /* Turns CFF's BCD format into strtod understandable string */ static double parse_bcd (byte_str_ref_t& str_ref) { if (unlikely (str_ref.in_error ())) return .0; enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; char buf[32]; unsigned char byte = 0; for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count) { unsigned nibble; if (!(i & 1)) { if (unlikely (!str_ref.avail ())) break; byte = str_ref[0]; str_ref.inc (); nibble = byte >> 4; } else nibble = byte & 0x0F; if (unlikely (nibble == RESERVED)) break; else if (nibble == END) { const char *p = buf; double pv; if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */))) break; return pv; } else { buf[count] = "0123456789.EE?-?"[nibble]; if (nibble == EXP_NEG) { ++count; if (unlikely (count == ARRAY_LENGTH (buf))) break; buf[count] = '-'; } } } str_ref.set_error (); return .0; } static bool is_hint_op (op_code_t op) { switch (op) { case OpCode_BlueValues: case OpCode_OtherBlues: case OpCode_FamilyBlues: case OpCode_FamilyOtherBlues: case OpCode_StemSnapH: case OpCode_StemSnapV: case OpCode_StdHW: case OpCode_StdVW: case OpCode_BlueScale: case OpCode_BlueShift: case OpCode_BlueFuzz: case OpCode_ForceBold: case OpCode_LanguageGroup: case OpCode_ExpansionFactor: return true; default: return false; } } }; template struct top_dict_opset_t : dict_opset_t { static void process_op (op_code_t op, interp_env_t& env, top_dict_values_t & dictval) { switch (op) { case OpCode_CharStrings: dictval.charStringsOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FDArray: dictval.FDArrayOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FontMatrix: env.clear_args (); break; default: dict_opset_t::process_op (op, env); break; } } }; template struct dict_interpreter_t : interpreter_t { bool interpret (PARAM& param) { param.init (); while (SUPER::env.str_ref.avail ()) { OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); if (unlikely (SUPER::env.in_error ())) return false; } return true; } private: typedef interpreter_t SUPER; }; } /* namespace CFF */ #endif /* HB_CFF_INTERP_DICT_COMMON_HH */