diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2018-12-22 00:39:38 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2018-12-22 00:39:38 +0000 |
commit | aefa260469999e53f3b8ea263fda94cdddef8ce3 (patch) | |
tree | e1182a668216a25f19d5f18ffcfec27cc7925b96 /Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh | |
parent | 27205aecce351fee6bb1ad9a7c43d4b542e28a1a (diff) |
harfbuzz-2.3.0
git-svn-id: svn://tug.org/texlive/trunk@49473 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh new file mode 100644 index 00000000000..8000d76b8bd --- /dev/null +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh @@ -0,0 +1,294 @@ +/* + * 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" +#include <math.h> +#include <float.h> + +namespace CFF { + +using namespace OT; + +/* an opstr and the parsed out dict value(s) */ +struct DictVal : OpStr +{ + void init () { single_val.set_int (0); } + void fini () {} + + Number single_val; +}; + +typedef DictVal NumDictVal; + +template <typename VAL> struct DictValues : ParsedValues<VAL> {}; + +template <typename OPSTR=OpStr> +struct TopDictValues : DictValues<OPSTR> +{ + void init () + { + DictValues<OPSTR>::init (); + charStringsOffset = 0; + FDArrayOffset = 0; + } + void fini () { DictValues<OPSTR>::fini (); } + + unsigned int calculate_serialized_op_size (const OPSTR& opstr) const + { + switch (opstr.op) + { + case OpCode_CharStrings: + case OpCode_FDArray: + return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op); + + default: + return opstr.str.len; + } + } + + unsigned int charStringsOffset; + unsigned int FDArrayOffset; +}; + +struct DictOpSet : OpSet<Number> +{ + static void process_op (OpCode op, InterpEnv<Number>& env) + { + switch (op) { + case OpCode_longintdict: /* 5-byte integer */ + env.argStack.push_longint_from_substr (env.substr); + break; + + case OpCode_BCD: /* real number */ + env.argStack.push_real (parse_bcd (env.substr)); + break; + + default: + OpSet<Number>::process_op (op, env); + break; + } + } + + static double parse_bcd (SubByteStr& substr) + { + bool neg = false; + double int_part = 0; + uint64_t frac_part = 0; + uint32_t frac_count = 0; + bool exp_neg = false; + uint32_t exp_part = 0; + bool exp_overflow = false; + enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART; + enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; + const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */ + const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */ + + double value = 0.0; + unsigned char byte = 0; + for (uint32_t i = 0;; i++) + { + char d; + if ((i & 1) == 0) + { + if (!substr.avail ()) + { + substr.set_error (); + return 0.0; + } + byte = substr[0]; + substr.inc (); + d = byte >> 4; + } + else + d = byte & 0x0F; + + switch (d) + { + case RESERVED: + substr.set_error (); + return value; + + case END: + value = (double)(neg? -int_part: int_part); + if (frac_count > 0) + { + double frac = (frac_part / pow (10.0, (double)frac_count)); + if (neg) frac = -frac; + value += frac; + } + if (unlikely (exp_overflow)) + { + if (value == 0.0) + return value; + if (exp_neg) + return neg? -DBL_MIN: DBL_MIN; + else + return neg? -DBL_MAX: DBL_MAX; + } + if (exp_part != 0) + { + if (exp_neg) + value /= pow (10.0, (double)exp_part); + else + value *= pow (10.0, (double)exp_part); + } + return value; + + case NEG: + if (i != 0) + { + substr.set_error (); + return 0.0; + } + neg = true; + break; + + case DECIMAL: + if (part != INT_PART) + { + substr.set_error (); + return value; + } + part = FRAC_PART; + break; + + case EXP_NEG: + exp_neg = true; + HB_FALLTHROUGH; + + case EXP_POS: + if (part == EXP_PART) + { + substr.set_error (); + return value; + } + part = EXP_PART; + break; + + default: + switch (part) { + default: + case INT_PART: + int_part = (int_part * 10) + d; + break; + + case FRAC_PART: + if (likely (frac_part <= MAX_FRACT / 10)) + { + frac_part = (frac_part * 10) + (unsigned)d; + frac_count++; + } + break; + + case EXP_PART: + if (likely (exp_part * 10 + d <= MAX_EXP)) + { + exp_part = (exp_part * 10) + d; + } + else + exp_overflow = true; + break; + } + } + } + + return value; + } + + static bool is_hint_op (OpCode 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 <typename VAL=OpStr> +struct TopDictOpSet : DictOpSet +{ + static void process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & 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: + DictOpSet::process_op (op, env); + break; + } + } +}; + +template <typename OPSET, typename PARAM, typename ENV=NumInterpEnv> +struct DictInterpreter : Interpreter<ENV> +{ + bool interpret (PARAM& param) + { + param.init (); + while (SUPER::env.substr.avail ()) + { + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error ())) + return false; + } + + return true; + } + + private: + typedef Interpreter<ENV> SUPER; +}; + +} /* namespace CFF */ + +#endif /* HB_CFF_INTERP_DICT_COMMON_HH */ |