diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2016-03-15 09:13:20 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2016-03-15 09:13:20 +0000 |
commit | 9b92252d80eba01cd25cc9610ad64908af57ba08 (patch) | |
tree | 6b30c240226b3187d7fbf2f098cfc64b8a3fbd7a | |
parent | a47ea6ff25589ac48846a0df205a7a037fe5c5bd (diff) |
graphite2 1.3.7
git-svn-id: svn://tug.org/texlive/trunk@40028 c570f23f-e606-0410-a88d-b1316a301751
29 files changed, 326 insertions, 234 deletions
diff --git a/Build/source/libs/README b/Build/source/libs/README index 0d7d658df0b..b5d9d76457e 100644 --- a/Build/source/libs/README +++ b/Build/source/libs/README @@ -21,7 +21,7 @@ gd 2.1.1 - checked 14jan15 gmp 6.1.0 - checked 28dec15 http://ftp.gnu.org/gnu/gmp/ -graphite2 1.3.6 - checked 01mar16 +graphite2 1.3.7 - checked 15mar16 http://sourceforge.net/projects/silgraphite/files/graphite2/ harfbuzz 1.2.3 - checked 25feb16 diff --git a/Build/source/libs/graphite2/ChangeLog b/Build/source/libs/graphite2/ChangeLog index b6790892f5b..114bc27e066 100644 --- a/Build/source/libs/graphite2/ChangeLog +++ b/Build/source/libs/graphite2/ChangeLog @@ -1,3 +1,8 @@ +2016-03-15 Akira Kakuto <kakuto@fuk.kindai.ac.jp> + + Import graphite2-1.3.7. + * version.ac: Adjusted. + 2016-03-01 Akira Kakuto <kakuto@fuk.kindai.ac.jp> Import graphite2-1.3.6. diff --git a/Build/source/libs/graphite2/configure b/Build/source/libs/graphite2/configure index 4a2c29c0268..5f54b52840a 100755 --- a/Build/source/libs/graphite2/configure +++ b/Build/source/libs/graphite2/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for graphite2 (TeX Live) 1.3.6. +# Generated by GNU Autoconf 2.69 for graphite2 (TeX Live) 1.3.7. # # Report bugs to <tex-k@tug.org>. # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='graphite2 (TeX Live)' PACKAGE_TARNAME='graphite2--tex-live-' -PACKAGE_VERSION='1.3.6' -PACKAGE_STRING='graphite2 (TeX Live) 1.3.6' +PACKAGE_VERSION='1.3.7' +PACKAGE_STRING='graphite2 (TeX Live) 1.3.7' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1254,7 +1254,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures graphite2 (TeX Live) 1.3.6 to adapt to many kinds of systems. +\`configure' configures graphite2 (TeX Live) 1.3.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1321,7 +1321,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of graphite2 (TeX Live) 1.3.6:";; + short | recursive ) echo "Configuration of graphite2 (TeX Live) 1.3.7:";; esac cat <<\_ACEOF @@ -1419,7 +1419,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -graphite2 (TeX Live) configure 1.3.6 +graphite2 (TeX Live) configure 1.3.7 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1558,7 +1558,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by graphite2 (TeX Live) $as_me 1.3.6, which was +It was created by graphite2 (TeX Live) $as_me 1.3.7, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3481,7 +3481,7 @@ fi # Define the identity of the package. PACKAGE='graphite2--tex-live-' - VERSION='1.3.6' + VERSION='1.3.7' cat >>confdefs.h <<_ACEOF @@ -5577,7 +5577,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by graphite2 (TeX Live) $as_me 1.3.6, which was +This file was extended by graphite2 (TeX Live) $as_me 1.3.7, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5643,7 +5643,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -graphite2 (TeX Live) config.status 1.3.6 +graphite2 (TeX Live) config.status 1.3.7 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/graphite2/graphite2-PATCHES/ChangeLog b/Build/source/libs/graphite2/graphite2-PATCHES/ChangeLog index baa126ff8e2..8c9a25cb237 100644 --- a/Build/source/libs/graphite2/graphite2-PATCHES/ChangeLog +++ b/Build/source/libs/graphite2/graphite2-PATCHES/ChangeLog @@ -1,3 +1,8 @@ +2016-03-15 Akira Kakuto <kakuto@fuk.kindai.ac.jp> + + Imported graphite2-1.3.7 source tree from: + http://sourceforge.net/projects/silgraphite/files/graphite2/ + 2016-03-01 Akira Kakuto <kakuto@fuk.kindai.ac.jp> Imported graphite2-1.3.6 source tree from: diff --git a/Build/source/libs/graphite2/graphite2-PATCHES/TL-Changes b/Build/source/libs/graphite2/graphite2-PATCHES/TL-Changes index 08fa835e4f2..d67afb870d8 100644 --- a/Build/source/libs/graphite2/graphite2-PATCHES/TL-Changes +++ b/Build/source/libs/graphite2/graphite2-PATCHES/TL-Changes @@ -1,4 +1,4 @@ -Changes applied to the graphite2-1.3.6/ tree as obtained from: +Changes applied to the graphite2-1.3.7/ tree as obtained from: http://sourceforge.net/projects/silgraphite/files/graphite2/ Removed unused dirs: diff --git a/Build/source/libs/graphite2/graphite2-src/ChangeLog b/Build/source/libs/graphite2/graphite2-src/ChangeLog index 522b8101175..e2157225a71 100644 --- a/Build/source/libs/graphite2/graphite2-src/ChangeLog +++ b/Build/source/libs/graphite2/graphite2-src/ChangeLog @@ -1,3 +1,7 @@ +1.3.7 + . Bug fixes + . Start to deprecate SegCache. This will be going away in a later release. + 1.3.6 . Bug fixes diff --git a/Build/source/libs/graphite2/graphite2-src/include/graphite2/Font.h b/Build/source/libs/graphite2/graphite2-src/include/graphite2/Font.h index 30b89994e74..866294da9f1 100644 --- a/Build/source/libs/graphite2/graphite2-src/include/graphite2/Font.h +++ b/Build/source/libs/graphite2/graphite2-src/include/graphite2/Font.h @@ -30,7 +30,7 @@ #define GR2_VERSION_MAJOR 1 #define GR2_VERSION_MINOR 3 -#define GR2_VERSION_BUGFIX 6 +#define GR2_VERSION_BUGFIX 7 #ifdef __cplusplus extern "C" diff --git a/Build/source/libs/graphite2/graphite2-src/src/CachedFace.cpp b/Build/source/libs/graphite2/graphite2-src/src/CachedFace.cpp index fd599bde8aa..71cd5ca452c 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/CachedFace.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/CachedFace.cpp @@ -69,10 +69,10 @@ bool CachedFace::runGraphite(Segment *seg, const Silf *pSilf) const Slot * subSegEndSlot = subSegStartSlot; uint16 cmapGlyphs[eMaxSpliceSize]; int subSegStart = 0; - for (unsigned int i = 0; i < seg->charInfoCount(); ++i) + for (unsigned int i = 0; i < seg->charInfoCount() && subSegEndSlot; ++i) { const unsigned int length = i - subSegStart + 1; - if (length < eMaxSpliceSize) + if (length < eMaxSpliceSize && subSegEndSlot->gid() < m_cacheStore->maxCmapGid()) cmapGlyphs[length-1] = subSegEndSlot->gid(); else return false; const bool spaceOnly = m_cacheStore->isSpaceGlyph(subSegEndSlot->gid()); diff --git a/Build/source/libs/graphite2/graphite2-src/src/Code.cpp b/Build/source/libs/graphite2/graphite2-src/src/Code.cpp index aa7959708da..247a0529cfa 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Code.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Code.cpp @@ -66,11 +66,10 @@ inline bool is_return(const instr i) { struct context { - context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false; flags.inserted=false;} + context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false;} struct { uint8 changed:1, - referenced:1, - inserted:1; + referenced:1; } flags; uint8 codeRef; }; @@ -82,46 +81,40 @@ class Machine::Code::decoder { public: struct limits; - struct analysis - { - static const int NUMCONTEXTS = 256; - uint8 slotref; - context contexts[NUMCONTEXTS]; - byte max_ref; - - analysis() : slotref(0), max_ref(0) {}; - void set_ref(int index, bool incinsert=false) throw(); - void set_noref(int index) throw(); - void set_changed(int index) throw(); - - }; + static const int NUMCONTEXTS = 256; decoder(limits & lims, Code &code, enum passtype pt) throw(); bool load(const byte * bc_begin, const byte * bc_end); void apply_analysis(instr * const code, instr * code_end); - byte max_ref() { return _analysis.max_ref; } - int pre_context() const { return _pre_context; } + byte max_ref() { return _max_ref; } + int out_index() const { return _out_index; } private: + void set_ref(int index) throw(); + void set_noref(int index) throw(); + void set_changed(int index) throw(); opcode fetch_opcode(const byte * bc); void analyse_opcode(const opcode, const int8 * const dp) throw(); bool emit_opcode(opcode opc, const byte * & bc); bool validate_opcode(const opcode opc, const byte * const bc); bool valid_upto(const uint16 limit, const uint16 x) const throw(); bool test_context() const throw(); + bool test_ref(int8 index) const throw(); void failure(const status_t s) const throw() { _code.failure(s); } Code & _code; - int _pre_context; - uint16 _rule_length; + int _out_index; + uint16 _out_length; instr * _instr; byte * _data; limits & _max; - analysis _analysis; enum passtype _passtype; int _stack_depth; bool _in_ctxt_item; + int16 _slotref; + context _contexts[NUMCONTEXTS]; + byte _max_ref; }; @@ -138,11 +131,13 @@ struct Machine::Code::decoder::limits inline Machine::Code::decoder::decoder(limits & lims, Code &code, enum passtype pt) throw() : _code(code), - _pre_context(code._constraint ? 0 : lims.pre_context), - _rule_length(code._constraint ? 1 : lims.rule_length), + _out_index(code._constraint ? 0 : lims.pre_context), + _out_length(code._constraint ? 1 : lims.rule_length), _instr(code._code), _data(code._data), _max(lims), _passtype(pt), _stack_depth(0), - _in_ctxt_item(false) + _in_ctxt_item(false), + _slotref(0), + _max_ref(0) { } @@ -168,7 +163,7 @@ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte // Allocate code and data target buffers, these sizes are a worst case // estimate. Once we know their real sizes the we'll shrink them. if (_out) _code = reinterpret_cast<instr *>(*_out); - else _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin))); + else _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin, 1, is_constraint ? 0 : rule_length))); _data = reinterpret_cast<byte *>(_code + (bytecode_end - bytecode_begin)); if (!_code || !_data) { @@ -324,37 +319,47 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) case NEXT : case NEXT_N : // runtime checked case COPY_NEXT : - test_context(); - ++_pre_context; + ++_out_index; + if (_out_index < -1 || _out_index > _out_length || _slotref > _max.rule_length) + failure(out_of_range_data); break; case PUT_GLYPH_8BIT_OBS : valid_upto(_max.classes, bc[0]); test_context(); break; case PUT_SUBS_8BIT_OBS : - valid_upto(_rule_length, _pre_context + int8(bc[0])); + test_ref(int8(bc[0])); valid_upto(_max.classes, bc[1]); valid_upto(_max.classes, bc[2]); test_context(); break; case PUT_COPY : - valid_upto(_rule_length, _pre_context + int8(bc[0])); + test_ref(int8(bc[0])); test_context(); break; case INSERT : if (_passtype >= PASS_TYPE_POSITIONING) failure(invalid_opcode); - else - --_pre_context; + ++_out_length; + if (_out_index < 0) ++_out_index; + if (_out_index < -1 || _out_index >= _out_length) + failure(out_of_range_data); break; case DELETE : if (_passtype >= PASS_TYPE_POSITIONING) failure(invalid_opcode); - test_context(); + if (_out_index < _max.pre_context) + failure(out_of_range_data); + --_out_index; + --_out_length; + if (_out_index < -1 || _out_index > _out_length) + failure(out_of_range_data); break; case ASSOC : + if (bc[0] == 0) + failure(out_of_range_data); for (uint8 num = bc[0]; num; --num) - valid_upto(_rule_length, _pre_context + int8(bc[num])); + test_ref(int8(bc[num])); test_context(); break; case CNTXT_ITEM : @@ -383,42 +388,33 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) case PUSH_SLOT_ATTR : ++_stack_depth; valid_upto(gr_slatMax, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); + test_ref(int8(bc[1])); if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes failure(out_of_range_data); break; case PUSH_GLYPH_ATTR_OBS : + case PUSH_ATT_TO_GATTR_OBS : ++_stack_depth; valid_upto(_max.glyf_attrs, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); + test_ref(int8(bc[1])); break; + case PUSH_ATT_TO_GLYPH_METRIC : case PUSH_GLYPH_METRIC : ++_stack_depth; valid_upto(kgmetDescent, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); + test_ref(int8(bc[1])); // level: dp[2] no check necessary break; case PUSH_FEAT : ++_stack_depth; valid_upto(_max.features, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); - break; - case PUSH_ATT_TO_GATTR_OBS : - ++_stack_depth; - valid_upto(_max.glyf_attrs, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); - break; - case PUSH_ATT_TO_GLYPH_METRIC : - ++_stack_depth; - valid_upto(kgmetDescent, bc[0]); - valid_upto(_rule_length, _pre_context + int8(bc[1])); - // level: dp[2] no check necessary + test_ref(int8(bc[1])); break; case PUSH_ISLOT_ATTR : ++_stack_depth; if (valid_upto(gr_slatMax, bc[0])) { - valid_upto(_rule_length, _pre_context + int8(bc[1])); + test_ref(int8(bc[1])); valid_upto(_max.attrid[bc[0]], bc[2]); } break; @@ -447,7 +443,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) ++_stack_depth; break; case PUT_SUBS : - valid_upto(_rule_length, _pre_context + int8(bc[0])); + test_ref(int8(bc[0])); valid_upto(_max.classes, uint16(bc[1]<< 8) | bc[2]); valid_upto(_max.classes, uint16(bc[3]<< 8) | bc[4]); test_context(); @@ -463,7 +459,11 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) case PUSH_ATT_TO_GLYPH_ATTR : ++_stack_depth; valid_upto(_max.glyf_attrs, uint16(bc[0]<< 8) | bc[1]); - valid_upto(_rule_length, _pre_context + int8(bc[2])); + test_ref(int8(bc[2])); + break; + case SET_FEAT : + valid_upto(_max.features, bc[0]); + test_ref(int8(bc[1])); break; default: failure(invalid_opcode); @@ -476,79 +476,64 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8 * arg) throw() { - if (_code._constraint) return; - switch (opc) { case DELETE : _code._delete = true; break; + case ASSOC : + set_changed(0); +// for (uint8 num = arg[0]; num; --num) +// _analysis.set_noref(num); + break; case PUT_GLYPH_8BIT_OBS : case PUT_GLYPH : _code._modify = true; - _analysis.set_changed(0); + set_changed(0); break; case ATTR_SET : case ATTR_ADD : + case ATTR_SUB : case ATTR_SET_SLOT : case IATTR_SET_SLOT : case IATTR_SET : case IATTR_ADD : case IATTR_SUB : - _analysis.set_noref(0); + set_noref(0); break; case NEXT : case COPY_NEXT : - if (!_analysis.contexts[_analysis.slotref].flags.inserted) - ++_analysis.slotref; - _analysis.contexts[_analysis.slotref] = context(_code._instr_count+1); + ++_slotref; + _contexts[_slotref] = context(_code._instr_count+1); // if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref; break; case INSERT : - _analysis.contexts[_analysis.slotref].flags.inserted = true; + if (_slotref >= 0) --_slotref; _code._modify = true; break; case PUT_SUBS_8BIT_OBS : // slotref on 1st parameter case PUT_SUBS : _code._modify = true; - _analysis.set_changed(0); + set_changed(0); GR_FALLTHROUGH; // no break case PUT_COPY : - { - if (arg[0] != 0) { _analysis.set_changed(0); _code._modify = true; } - if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) - _analysis.set_ref(arg[0], true); - else if (arg[0] > 0) - _analysis.set_ref(arg[0], true); + if (arg[0] != 0) { set_changed(0); _code._modify = true; } + set_ref(arg[0]); break; - } - case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter - if (_code._constraint) return; - GR_FALLTHROUGH; - // no break case PUSH_GLYPH_ATTR_OBS : case PUSH_SLOT_ATTR : case PUSH_GLYPH_METRIC : + case PUSH_ATT_TO_GATTR_OBS : case PUSH_ATT_TO_GLYPH_METRIC : case PUSH_ISLOT_ATTR : case PUSH_FEAT : - if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) - _analysis.set_ref(arg[1], true); - else if (arg[1] > 0) - _analysis.set_ref(arg[1], true); + case SET_FEAT : + set_ref(arg[1]); break; case PUSH_ATT_TO_GLYPH_ATTR : - if (_code._constraint) return; - GR_FALLTHROUGH; - // no break case PUSH_GLYPH_ATTR : - if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted) - _analysis.set_ref(arg[2], true); - else if (arg[2] > 0) - _analysis.set_ref(arg[2], true); - break; - case ASSOC : // slotrefs in varargs + set_ref(arg[2]); break; default: break; @@ -584,10 +569,10 @@ bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc) // instruction and data portions. if (opc == CNTXT_ITEM) { - assert(_pre_context == 0); + assert(_out_index == 0); _in_ctxt_item = true; - _pre_context = _max.pre_context + int8(_data[-2]); - _rule_length = _max.rule_length; + _out_index = _max.pre_context + int8(_data[-2]); + _out_length = _max.rule_length; const size_t ctxt_start = _code._instr_count; byte & instr_skip = _data[-1]; @@ -602,13 +587,13 @@ bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc) instr_skip = _code._instr_count - ctxt_start; _max.bytecode = curr_end; - _rule_length = 1; - _pre_context = 0; + _out_length = 1; + _out_index = 0; _in_ctxt_item = false; } else { - _pre_context = 0; + _out_index = 0; return false; } } @@ -624,7 +609,7 @@ void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end if (_code._constraint) return; const instr temp_copy = Machine::getOpcodeTable()[TEMP_COPY].impl[0]; - for (const context * c = _analysis.contexts, * const ce = c + _analysis.slotref; c != ce; ++c) + for (const context * c = _contexts, * const ce = c + _slotref; c < ce; ++c) { if (!c->flags.referenced || !c->flags.changed) continue; @@ -649,6 +634,11 @@ bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * cons return false; } const opcode_t & op = Machine::getOpcodeTable()[opc]; + if (op.impl[_code._constraint] == 0) + { + failure(unimplemented_opcode_used); + return false; + } if (op.param_sz == VARARGS && bc >= _max.bytecode) { failure(arguments_exhausted); @@ -671,9 +661,15 @@ bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) cons return t; } +inline +bool Machine::Code::decoder::test_ref(int8 index) const throw() +{ + return valid_upto(_max.rule_length, _slotref + _max.pre_context + index); +} + bool Machine::Code::decoder::test_context() const throw() { - if (_pre_context >= _rule_length || _analysis.slotref >= analysis::NUMCONTEXTS - 1) + if (_out_index >= _out_length || _out_index < 0 || _slotref >= NUMCONTEXTS - 1) { failure(out_of_range_data); return false; @@ -689,28 +685,25 @@ void Machine::Code::failure(const status_t s) throw() { inline -void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() { - if (incinsert && contexts[slotref].flags.inserted) --index; - if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return; - contexts[index + slotref].flags.referenced = true; - if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref; +void Machine::Code::decoder::set_ref(int index) throw() { + if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return; + _contexts[index + _slotref].flags.referenced = true; + if (index + _slotref > _max_ref) _max_ref = index + _slotref; } inline -void Machine::Code::decoder::analysis::set_noref(int index) throw() { - if (contexts[slotref].flags.inserted) --index; - if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return; - if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref; +void Machine::Code::decoder::set_noref(int index) throw() { + if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return; + if (index + _slotref > _max_ref) _max_ref = index + _slotref; } inline -void Machine::Code::decoder::analysis::set_changed(int index) throw() { - if (contexts[slotref].flags.inserted) --index; - if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return; - contexts[index + slotref].flags.changed = true; - if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref; +void Machine::Code::decoder::set_changed(int index) throw() { + if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return; + _contexts[index + _slotref].flags.changed= true; + if (index + _slotref > _max_ref) _max_ref = index + _slotref; } diff --git a/Build/source/libs/graphite2/graphite2-src/src/Collider.cpp b/Build/source/libs/graphite2/graphite2-src/src/Collider.cpp index 87f067d3f7c..591b01ebe90 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Collider.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Collider.cpp @@ -26,7 +26,7 @@ of the License or (at your option) any later version. */ #include <algorithm> #include <limits> -#include <math.h> +#include <cmath> #include <string> #include <functional> #include "inc/Collider.h" diff --git a/Build/source/libs/graphite2/graphite2-src/src/Face.cpp b/Build/source/libs/graphite2/graphite2-src/src/Face.cpp index e9b1b1c177c..1ab7a60f490 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Face.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Face.cpp @@ -183,7 +183,8 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const seg->associateChars(0, seg->charInfoCount()); if (aSilf->flags() & 0x20) res &= seg->initCollisions(); - res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false); + if (res) + res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false); } #if !defined GRAPHITE2_NTRACING @@ -231,7 +232,7 @@ uint16 Face::findPseudo(uint32 uid) const return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0; } -uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const +int32 Face::getGlyphMetric(uint16 gid, uint8 metric) const { switch (metrics(metric)) { @@ -282,7 +283,7 @@ Face::Table::Table(const Face & face, const Tag n, uint32 version) throw() if (!TtfUtil::CheckTable(n, _p, _sz)) { - this->~Table(); // Make sure we release the table buffer even if the table filed it's checks + releaseBuffers(); // Make sure we release the table buffer even if the table failed it's checks return; } @@ -329,7 +330,8 @@ Error Face::Table::decompress() { uncompressed_size = hdr & 0x07ffffff; uncompressed_table = gralloc<byte>(uncompressed_size); - if (!e.test(!uncompressed_table, E_OUTOFMEM)) + if (!e.test(!uncompressed_table || uncompressed_size < 4, E_OUTOFMEM)) + memset(uncompressed_table, 0, 4); // make sure version number is initialised // coverity[forward_null : FALSE] - uncompressed_table has been checked so can't be null // coverity[checked_return : FALSE] - we test e later e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED); diff --git a/Build/source/libs/graphite2/graphite2-src/src/GlyphCache.cpp b/Build/source/libs/graphite2/graphite2-src/src/GlyphCache.cpp index 8792f9700b3..ae9035d1d4b 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/GlyphCache.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/GlyphCache.cpp @@ -116,8 +116,10 @@ private: GlyphCache::GlyphCache(const Face & face, const uint32 face_options) : _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))), - _glyphs(_glyph_loader && *_glyph_loader ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0), - _boxes(_glyph_loader && _glyph_loader->has_boxes() ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0), + _glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs() + ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0), + _boxes(_glyph_loader && _glyph_loader->has_boxes() && _glyph_loader->num_glyphs() + ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0), _num_glyphs(_glyphs ? _glyph_loader->num_glyphs() : 0), _num_attrs(_glyphs ? _glyph_loader->num_attrs() : 0), _upem(_glyphs ? _glyph_loader->units_per_em() : 0) @@ -144,7 +146,7 @@ GlyphCache::GlyphCache(const Face & face, const uint32 face_options) _glyphs[0] = 0; delete [] glyphs; } - else if (numsubs > 0) + else if (numsubs > 0 && _boxes) { GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float)); GlyphBox * currbox = boxes; @@ -285,7 +287,8 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font) if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535 || _num_attrs == 0 || _num_attrs > 0x3000 // is this hard limit appropriate? - || _num_glyphs_graphics > tmpnumgattrs) + || _num_glyphs_graphics > tmpnumgattrs + || m_pGlat.size() < 4) { _head = Face::Table(); return; @@ -294,7 +297,7 @@ GlyphCache::Loader::Loader(const Face & face, const bool dumb_font) _num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs); p = m_pGlat; version = be::read<uint32>(p); - if (version >= 0x00040000) // reject Glat tables that are too new + if (version >= 0x00040000 || (version >= 0x00030000 && m_pGlat.size() < 8)) // reject Glat tables that are too new { _head = Face::Table(); return; @@ -386,11 +389,11 @@ const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFa gloce = be::peek<uint16>(gloc); } - if (glocs >= m_pGlat.size() || gloce > m_pGlat.size()) + if (glocs + 1 >= m_pGlat.size() || gloce > m_pGlat.size()) return 0; const uint32 glat_version = be::peek<uint32>(m_pGlat); - if (glat_version == 0x00030000) + if (glat_version >= 0x00030000) { const byte * p = m_pGlat + glocs; uint16 bmap = be::read<uint16>(p); @@ -454,7 +457,7 @@ GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphF gloce = be::peek<uint16>(gloc); } - if (glocs >= m_pGlat.size() || gloce > m_pGlat.size()) + if (gloce > m_pGlat.size() || glocs + 6 >= gloce) return 0; const byte * p = m_pGlat + glocs; @@ -467,6 +470,8 @@ GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphF Rect diabound = readbox(diamax, p[0], p[2], p[1], p[3]); ::new (curr) GlyphBox(num, bmap, &diabound); be::skip<uint8>(p, 4); + if (glocs + 6 + num * 8 >= gloce) + return 0; for (int i = 0; i < num * 2; ++i) { diff --git a/Build/source/libs/graphite2/graphite2-src/src/GlyphFace.cpp b/Build/source/libs/graphite2/graphite2-src/src/GlyphFace.cpp index 9fc11b2157e..ce17e42bd47 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/GlyphFace.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/GlyphFace.cpp @@ -29,20 +29,20 @@ of the License or (at your option) any later version. using namespace graphite2; -uint16 GlyphFace::getMetric(uint8 metric) const +int32 GlyphFace::getMetric(uint8 metric) const { switch (metrics(metric)) { - case kgmetLsb : return static_cast<uint16>(m_bbox.bl.x); - case kgmetRsb : return static_cast<uint16>(m_advance.x - m_bbox.tr.x); - case kgmetBbTop : return static_cast<uint16>(m_bbox.tr.y); - case kgmetBbBottom : return static_cast<uint16>(m_bbox.bl.y); - case kgmetBbLeft : return static_cast<uint16>(m_bbox.bl.x); - case kgmetBbRight : return static_cast<uint16>(m_bbox.tr.x); - case kgmetBbHeight : return static_cast<uint16>(m_bbox.tr.y - m_bbox.bl.y); - case kgmetBbWidth : return static_cast<uint16>(m_bbox.tr.x - m_bbox.bl.x); - case kgmetAdvWidth : return static_cast<uint16>(m_advance.x); - case kgmetAdvHeight : return static_cast<uint16>(m_advance.y); + case kgmetLsb : return m_bbox.bl.x; + case kgmetRsb : return m_advance.x - m_bbox.tr.x; + case kgmetBbTop : return m_bbox.tr.y; + case kgmetBbBottom : return m_bbox.bl.y; + case kgmetBbLeft : return m_bbox.bl.x; + case kgmetBbRight : return m_bbox.tr.x; + case kgmetBbHeight : return m_bbox.tr.y - m_bbox.bl.y; + case kgmetBbWidth : return m_bbox.tr.x - m_bbox.bl.x; + case kgmetAdvWidth : return m_advance.x; + case kgmetAdvHeight : return m_advance.y; default : return 0; } } diff --git a/Build/source/libs/graphite2/graphite2-src/src/NameTable.cpp b/Build/source/libs/graphite2/graphite2-src/src/NameTable.cpp index f83adb09cd8..2baa1bbdc52 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/NameTable.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/NameTable.cpp @@ -47,15 +47,16 @@ NameTable::NameTable(const void* data, size_t length, uint16 platformId, uint16 sizeof(TtfUtil::Sfnt::NameRecord) * ( be::swap<uint16>(m_table->count) - 1))) { uint16 offset = be::swap<uint16>(m_table->string_offset); - m_nameData = reinterpret_cast<const uint8*>(pdata) + offset; - setPlatformEncoding(platformId, encodingID); - m_nameDataLength = length - offset; - } - else - { - free(const_cast<TtfUtil::Sfnt::FontNames*>(m_table)); - m_table = NULL; + if (offset < length) + { + m_nameData = reinterpret_cast<const uint8*>(pdata) + offset; + setPlatformEncoding(platformId, encodingID); + m_nameDataLength = length - offset; + return; + } } + free(const_cast<TtfUtil::Sfnt::FontNames*>(m_table)); + m_table = NULL; } uint16 NameTable::setPlatformEncoding(uint16 platformId, uint16 encodingID) @@ -144,7 +145,7 @@ void* NameTable::getName(uint16& languageId, uint16 nameId, gr_encform enc, uint return NULL; } utf16Length >>= 1; // in utf16 units - utf16::codeunit_t * utf16Name = gralloc<utf16::codeunit_t>(utf16Length); + utf16::codeunit_t * utf16Name = gralloc<utf16::codeunit_t>(utf16Length + 1); if (!utf16Name) { languageId = 0; @@ -156,6 +157,14 @@ void* NameTable::getName(uint16& languageId, uint16 nameId, gr_encform enc, uint { utf16Name[i] = be::read<uint16>(pName); } + utf16Name[utf16Length] = 0; + if (!utf16::validate(utf16Name, utf16Name + utf16Length)) + { + free(utf16Name); + languageId = 0; + length = 0; + return NULL; + } switch (enc) { case gr_utf8: diff --git a/Build/source/libs/graphite2/graphite2-src/src/Pass.cpp b/Build/source/libs/graphite2/graphite2-src/src/Pass.cpp index fcf0384a60c..6f6b91331f5 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Pass.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Pass.cpp @@ -101,7 +101,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su // Read in basic values const byte flags = be::read<byte>(p); if (e.test((flags & 0x1f) && - (pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes()), + (pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes() || !(m_silf->flags() & 0x20)), E_BADCOLLISIONPASS)) return face.error(e); m_numCollRuns = flags & 0x7; @@ -231,7 +231,11 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries, // Allocate pools m_rules = new Rule [m_numRules]; m_codes = new Code [m_numRules*2]; - const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data); + int totalSlots = 0; + const uint16 *tsort = sort_key; + for (int i = 0; i < m_numRules; ++i) + totalSlots += be::peek<uint16>(--tsort); + const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data, 2 * m_numRules, totalSlots); m_progs = gralloc<byte>(prog_pool_sz); byte * prog_pool_free = m_progs, * prog_pool_end = m_progs + prog_pool_sz; @@ -254,7 +258,7 @@ bool Pass::readRules(const byte * rule_map, const size_t num_entries, if (ac_begin > ac_end || ac_begin > ac_data_end || ac_end > ac_data_end || rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end - || vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin) > size_t(prog_pool_end - prog_pool_free)) + || vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin, 2, r->sort) > size_t(prog_pool_end - prog_pool_free)) return false; r->action = new (m_codes+n*2-2) vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free); r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true, rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free); @@ -356,7 +360,8 @@ bool Pass::readStates(const byte * starts, const byte *states, const byte * o_ru s->rules = begin; s->rules_end = (end - begin <= FiniteStateMachine::MAX_RULES)? end : begin + FiniteStateMachine::MAX_RULES; - qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry); + if (begin) // keep UBSan happy can't call qsort with null begin + qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry); } return true; @@ -454,9 +459,9 @@ bool Pass::runFSM(FiniteStateMachine& fsm, Slot * slot) const do { fsm.slots.pushSlot(slot); - if (--free_slots == 0 - || slot->gid() >= m_numGlyphs + if (slot->gid() >= m_numGlyphs || m_cols[slot->gid()] == 0xffffU + || --free_slots == 0 || state >= m_numTransition) return free_slots != 0; @@ -632,10 +637,13 @@ bool Pass::testConstraint(const Rule & r, Machine & m) const const uint16 curr_context = m.slotMap().context(); if (unsigned(r.sort - r.preContext) > m.slotMap().size() - curr_context || curr_context - r.preContext < 0) return false; - if (!*r.constraint) return true; - assert(r.constraint->constraint()); vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext; + if (map[r.sort - 1] == 0) + return false; + + if (!*r.constraint) return true; + assert(r.constraint->constraint()); for (int n = r.sort; n && map; --n, ++map) { if (!*map) continue; @@ -652,7 +660,7 @@ void SlotMap::collectGarbage(Slot * &aSlot) { for(Slot **s = begin(), *const *const se = end() - 1; s != se; ++s) { Slot *& slot = *s; - if(slot->isDeleted() || slot->isCopied()) + if(slot && (slot->isDeleted() || slot->isCopied())) { if (slot == aSlot) aSlot = slot->prev() ? slot->prev() : slot->next(); diff --git a/Build/source/libs/graphite2/graphite2-src/src/Segment.cpp b/Build/source/libs/graphite2/graphite2-src/src/Segment.cpp index ecc35f50aa0..966f75784dd 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Segment.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Segment.cpp @@ -424,6 +424,9 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo if (!iStart) iStart = m_first; if (!iEnd) iEnd = m_last; + if (!iStart || !iEnd) // only true for empty segments + return currpos; + if (isRtl) { for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev()) @@ -531,6 +534,9 @@ bool Segment::initCollisions() if (!m_collisions) return false; for (Slot *p = m_first; p; p = p->next()) - ::new (collisionInfo(p)) SlotCollision(this, p); + if (p->index() < slotCount()) + ::new (collisionInfo(p)) SlotCollision(this, p); + else + return false; return true; } diff --git a/Build/source/libs/graphite2/graphite2-src/src/Silf.cpp b/Build/source/libs/graphite2/graphite2-src/src/Silf.cpp index adfad4029a0..02876881e6f 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Silf.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Silf.cpp @@ -355,10 +355,10 @@ uint16 Silf::getClassGlyph(uint16 cid, unsigned int index) const bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi) const { assert(seg != 0); - SlotMap map(*seg, m_dir); + unsigned int maxSize = seg->slotCount() * MAX_SEG_GROWTH_FACTOR; + SlotMap map(*seg, m_dir, maxSize); FiniteStateMachine fsm(map, seg->getFace()->logger()); vm::Machine m(map); - unsigned int initSize = seg->slotCount(); uint8 lbidi = m_bPass; #if !defined GRAPHITE2_NTRACING json * const dbgout = seg->getFace()->logger(); @@ -424,7 +424,7 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi return false; // only subsitution passes can change segment length, cached subsegments are short for their text if (m.status() != vm::Machine::finished - || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize)) + || (seg->slotCount() && seg->slotCount() > maxSize)) return false; } return true; diff --git a/Build/source/libs/graphite2/graphite2-src/src/Slot.cpp b/Build/source/libs/graphite2/graphite2-src/src/Slot.cpp index 3330c8131fb..4227327c4b3 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/Slot.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/Slot.cpp @@ -85,10 +85,10 @@ void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos) m_position = m_position + relpos; } -Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal) +Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth) { SlotCollision *coll = NULL; - if (attrLevel && m_attLevel > attrLevel) return Position(0, 0); + if (depth > 100 || (attrLevel && m_attLevel > attrLevel)) return Position(0, 0); float scale = font ? font->scale() : 1.0f; Position shift(m_shift.x * (rtl * -2 + 1) + m_just, m_shift.y); float tAdvance = m_advance.x + m_just; @@ -133,13 +133,13 @@ Position Slot::finalise(const Segment *seg, const Font *font, Position & base, R if (m_child && m_child != this && m_child->attachedTo() == this) { - Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal); + Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal, depth + 1); if ((!m_parent || m_advance.x >= 0.5f) && tRes.x > res.x) res = tRes; } if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent) { - Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal); + Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal, depth + 1); if (tRes.x > res.x) res = tRes; } @@ -165,25 +165,25 @@ int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel, boo switch (metrics(metric)) { case kgmetLsb : - return static_cast<uint32>(bbox.bl.x); + return bbox.bl.x; case kgmetRsb : - return static_cast<uint32>(res.x - bbox.tr.x); + return res.x - bbox.tr.x; case kgmetBbTop : - return static_cast<uint32>(bbox.tr.y); + return bbox.tr.y; case kgmetBbBottom : - return static_cast<uint32>(bbox.bl.y); + return bbox.bl.y; case kgmetBbLeft : - return static_cast<uint32>(bbox.bl.x); + return bbox.bl.x; case kgmetBbRight : - return static_cast<uint32>(bbox.tr.x); + return bbox.tr.x; case kgmetBbWidth : - return static_cast<uint32>(bbox.tr.x - bbox.bl.x); + return bbox.tr.x - bbox.bl.x; case kgmetBbHeight : - return static_cast<uint32>(bbox.tr.y - bbox.bl.y); + return bbox.tr.y - bbox.bl.y; case kgmetAdvWidth : - return static_cast<uint32>(res.x); + return res.x; case kgmetAdvHeight : - return static_cast<uint32>(res.y); + return res.y; default : return 0; } @@ -295,9 +295,22 @@ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, cons if (idx < map.size() && map[idx]) { Slot *other = map[idx]; - if (other == this || other == m_parent) break; - if (m_parent) m_parent->removeChild(this); - if (!other->isChildOf(this) && other->child(this)) + if (other == this || other == m_parent || other->isCopied()) break; + if (m_parent) { m_parent->removeChild(this); attachTo(NULL); } + Slot *pOther = other; + int count = 0; + bool foundOther = false; + while (pOther) + { + ++count; + if (pOther == this) foundOther = true; + pOther = pOther->attachedTo(); + } + for (pOther = m_child; pOther; pOther = pOther->m_child) + ++count; + for (pOther = m_sibling; pOther; pOther = pOther->m_sibling) + ++count; + if (count < 100 && !foundOther && other->child(this)) { attachTo(other); if ((map.dir() != 0) ^ (idx > subindex)) @@ -421,31 +434,24 @@ bool Slot::sibling(Slot *ap) bool Slot::removeChild(Slot *ap) { - if (this == ap || !m_child) return false; + if (this == ap || !m_child || !ap) return false; else if (ap == m_child) { Slot *nSibling = m_child->nextSibling(); - m_child->removeSibling(nSibling); + m_child->nextSibling(NULL); m_child = nSibling; return true; } - else - return m_child->removeSibling(ap); - return true; -} - -bool Slot::removeSibling(Slot *ap) -{ - if (this == ap || !m_sibling) return false; - else if (ap == m_sibling) + for (Slot *p = m_child; p; p = p->m_sibling) { - m_sibling = m_sibling->nextSibling(); - if (m_sibling) ap->removeSibling(m_sibling); - return true; + if (p->m_sibling && p->m_sibling == ap) + { + p->m_sibling = p->m_sibling->m_sibling; + ap->nextSibling(NULL); + return true; + } } - else - return m_sibling->removeSibling(ap); - return true; + return false; } void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph) @@ -480,11 +486,13 @@ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph) } } -void Slot::floodShift(Position adj) +void Slot::floodShift(Position adj, int depth) { + if (depth > 100) + return; m_position += adj; - if (m_child) m_child->floodShift(adj); - if (m_sibling) m_sibling->floodShift(adj); + if (m_child) m_child->floodShift(adj, depth + 1); + if (m_sibling) m_sibling->floodShift(adj, depth + 1); } void SlotJustify::LoadSlot(const Slot *s, const Segment *seg) @@ -519,10 +527,9 @@ Slot * Slot::nextInCluster(const Slot *s) const bool Slot::isChildOf(const Slot *base) const { - if (m_parent == base) - return true; - else if (!m_parent) - return false; - else - return m_parent->isChildOf(base); + for (Slot *p = m_parent; p; p = p->m_parent) + if (p == base) + return true; + return false; } + diff --git a/Build/source/libs/graphite2/graphite2-src/src/TtfUtil.cpp b/Build/source/libs/graphite2/graphite2-src/src/TtfUtil.cpp index 85a4e6a0a81..75e8da11c45 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/TtfUtil.cpp +++ b/Build/source/libs/graphite2/graphite2-src/src/TtfUtil.cpp @@ -896,15 +896,17 @@ bool CheckCmapSubtable4(const void * pCmapSubtable4, const void * pCmapEnd /*, u const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4); // Bob H say some freeware TT fonts have version 1 (eg, CALIGULA.TTF) // so don't check subtable version. 21 Mar 2002 spec changes version to language. - if (be::swap(pTable->format) != 4) return false; + if (table_len < sizeof(*pTable) || be::swap(pTable->format) != 4) return false; const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4); + if (table_len < sizeof(*pTable4)) + return false; uint16 length = be::swap(pTable4->length); if (length > table_len) return false; if (length < sizeof(Sfnt::CmapSubTableFormat4)) return false; uint16 nRanges = be::swap(pTable4->seg_count_x2) >> 1; - if (length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16)) + if (!nRanges || length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16)) return false; // check last range is properly terminated uint16 chEnd = be::peek<uint16>(pTable4->end_code + nRanges - 1); @@ -1004,7 +1006,7 @@ gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, // Look up value in glyphIdArray const ptrdiff_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) + (pMid - reinterpret_cast<const uint16 *>(pTable)); - if (offset * 2 >= be::swap<uint16>(pTable->length)) + if (offset * 2 + 1 >= be::swap<uint16>(pTable->length)) return 0; gid16 nGlyphId = be::peek<uint16>(reinterpret_cast<const uint16 *>(pTable)+offset); // If this value is 0, return 0. Else add the idDelta @@ -1086,9 +1088,11 @@ bool CheckCmapSubtable12(const void *pCmapSubtable12, const void *pCmapEnd /*, u size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable12; if (!pCmapSubtable12) return false; const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12); - if (be::swap(pTable->format) != 12) + if (table_len < sizeof(*pTable) || be::swap(pTable->format) != 12) return false; const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12); + if (table_len < sizeof(*pTable12)) + return false; uint32 length = be::swap(pTable12->length); if (length > table_len) return false; diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/Code.h b/Build/source/libs/graphite2/graphite2-src/src/inc/Code.h index 5451a34809b..3985ae416e9 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/Code.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/Code.h @@ -86,7 +86,7 @@ private: void failure(const status_t) throw(); public: - static size_t estimateCodeDataOut(size_t num_bytecodes); + static size_t estimateCodeDataOut(size_t num_bytecodes, int nRules, int nSlots); Code() throw(); Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end, @@ -112,9 +112,11 @@ public: }; inline -size_t Machine::Code::estimateCodeDataOut(size_t n_bc) +size_t Machine::Code::estimateCodeDataOut(size_t n_bc, int nRules, int nSlots) { - return (n_bc + 1) * (sizeof(instr)+sizeof(byte)); + // max is: all codes are instructions + 1 for each rule + max tempcopies + // allocate space for separate maximal code and data then merge them later + return (n_bc + nRules + nSlots) * sizeof(instr) + n_bc * sizeof(byte); } diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/Face.h b/Build/source/libs/graphite2/graphite2-src/src/inc/Face.h index 7682dfaca3e..43ea4319681 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/Face.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/Face.h @@ -87,7 +87,7 @@ public: const FeatureRef * feature(uint16 index) const; // Glyph related - uint16 getGlyphMetric(uint16 gid, uint8 metric) const; + int32 getGlyphMetric(uint16 gid, uint8 metric) const; uint16 findPseudo(uint32 uid) const; // Errors diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/GlyphFace.h b/Build/source/libs/graphite2/graphite2-src/src/inc/GlyphFace.h index 89ed5aea91a..41685a55f4f 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/GlyphFace.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/GlyphFace.h @@ -51,7 +51,7 @@ public: const Position & theAdvance() const; const Rect & theBBox() const { return m_bbox; } const sparse & attrs() const { return m_attrs; } - uint16 getMetric(uint8 metric) const; + int32 getMetric(uint8 metric) const; CLASS_NEW_DELETE; private: diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/Rule.h b/Build/source/libs/graphite2/graphite2-src/src/inc/Rule.h index 36c8d89a63d..5ac21a17598 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/Rule.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/Rule.h @@ -102,7 +102,7 @@ class SlotMap { public: enum {MAX_SLOTS=64}; - SlotMap(Segment & seg, uint8 direction); + SlotMap(Segment & seg, uint8 direction, int maxSize); Slot * * begin(); Slot * * end(); @@ -121,6 +121,7 @@ public: void highpassed(bool v) { m_highpassed = v; } uint8 dir() const { return m_dir; } + int decMax() { return --m_maxSize; } Segment & segment; private: @@ -128,6 +129,7 @@ private: unsigned short m_size; unsigned short m_precontext; Slot * m_highwater; + int m_maxSize; uint8 m_dir; bool m_highpassed; }; @@ -242,8 +244,9 @@ void FiniteStateMachine::Rules::accumulate_rules(const State &state) } inline -SlotMap::SlotMap(Segment & seg, uint8 direction) -: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_dir(direction), m_highpassed(false) +SlotMap::SlotMap(Segment & seg, uint8 direction, int maxSize) +: segment(seg), m_size(0), m_precontext(0), m_highwater(0), + m_maxSize(maxSize), m_dir(direction), m_highpassed(false) { m_slot_map[0] = 0; } diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/Segment.h b/Build/source/libs/graphite2/graphite2-src/src/inc/Segment.h index 7d72f98eda4..bcba1f2a87b 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/Segment.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/Segment.h @@ -40,7 +40,7 @@ of the License or (at your option) any later version. #include "inc/List.h" #include "inc/Collider.h" -#define MAX_SEG_GROWTH_FACTOR 256 +#define MAX_SEG_GROWTH_FACTOR 64 namespace graphite2 { @@ -159,7 +159,7 @@ public: void reverseSlots(); bool isWhitespace(const int cid) const; - bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS); } + bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS) && m_collisions; } SlotCollision *collisionInfo(const Slot *s) const { return m_collisions ? m_collisions + s->index() : 0; } CLASS_NEW_DELETE diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/Slot.h b/Build/source/libs/graphite2/graphite2-src/src/inc/Slot.h index a6e05491c6d..daa11244737 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/Slot.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/Slot.h @@ -97,7 +97,7 @@ public: void after(int ind) { m_after = ind; } bool isBase() const { return (!m_parent); } void update(int numSlots, int numCharInfo, Position &relpos); - Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal); + Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth = 0); bool isDeleted() const { return (m_flags & DELETED) ? true : false; } void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; } bool isCopied() const { return (m_flags & COPIED) ? true : false; } @@ -128,10 +128,9 @@ public: void nextSibling(Slot *ap) { m_sibling = ap; } bool sibling(Slot *ap); bool removeChild(Slot *ap); - bool removeSibling(Slot *ap); int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl); void positionShift(Position a) { m_position += a; } - void floodShift(Position adj); + void floodShift(Position adj, int depth = 0); float just() const { return m_just; } void just(float j) { m_just = j; } Slot *nextInCluster(const Slot *s) const; diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/UtfCodec.h b/Build/source/libs/graphite2/graphite2-src/src/inc/UtfCodec.h index 66384ae182a..3417bac7b15 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/UtfCodec.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/UtfCodec.h @@ -40,6 +40,7 @@ struct _utf_codec static void put(codeunit_t * cp, const uchar_t , int8 & len) throw(); static uchar_t get(const codeunit_t * cp, int8 & len) throw(); + static bool validate(const codeunit_t * s, const codeunit_t * e) throw(); }; @@ -63,6 +64,12 @@ public: if (cp[0] < limit) { l = 1; return cp[0]; } else { l = -1; return 0xFFFD; } } + + inline + static bool validate(codeunit_t * s, codeunit_t * e) throw() + { + return e > s; + } }; @@ -93,12 +100,21 @@ public: const uint32 uh = cp[0]; l = 1; - if (0xD800 > uh || uh > 0xDFFF) { return uh; } + if (uh < 0xD800|| uh > 0xDFFF) { return uh; } const uint32 ul = cp[1]; - if (uh > 0xDBFF || 0xDC00 > ul || ul > 0xDFFF) { l = -1; return 0xFFFD; } + if (uh > 0xDBFF || ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; } ++l; return (uh<<10) + ul + surrogate_offset; } + + inline + static bool validate(codeunit_t * s, codeunit_t * e) throw() + { + const ptrdiff_t n = e-s; + if (n <= 0) return n == 0; + const uint32 u = *(s+(n-1)); // Get the last codepoint + return (u < 0xD800 || u > 0xDBFF); + } }; @@ -148,6 +164,24 @@ public: } return u; } + + inline + static bool validate(codeunit_t * s, codeunit_t * e) throw() + { + const ptrdiff_t n = e-s; + if (n <= 0) return n == 0; + s += (n-1); + if (*s < 0x80) return true; + if (*s >= 0xC0) return false; + if (n == 1) return true; + if (*--s < 0x80) return true; + if (*s >= 0xe0) return false; + if (n == 2 || *s >= 0xC0) return true; + if (*--s < 0x80) return true; + if (*s >= 0xF0) return false; + return true; + } + }; @@ -200,6 +234,11 @@ struct utf typedef _utf_iterator<C> iterator; typedef _utf_iterator<const C> const_iterator; + + inline + static bool validate(codeunit_t * s, codeunit_t * e) throw() { + return _utf_codec<sizeof(C)*8>::validate(s,e); + } }; diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/opcode_table.h b/Build/source/libs/graphite2/graphite2-src/src/inc/opcode_table.h index 73a99c82043..50ae1d4d077 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/opcode_table.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/opcode_table.h @@ -118,7 +118,7 @@ static const opcode_t opcode_table[] = {{do2(band)}, 0, "BITAND"}, {{do2(bnot)}, 0, "BITNOT"}, // 0x40 {{do2(setbits)}, 4, "BITSET"}, - {{do2(set_feat)}, 2, "SET_FEAT"}, + {{do_(set_feat), NILOP}, 2, "SET_FEAT"}, // featidx slot // private opcodes for internal use only, comes after all other on disk opcodes. {{do_(temp_copy), NILOP}, 0, "TEMP_COPY"} }; diff --git a/Build/source/libs/graphite2/graphite2-src/src/inc/opcodes.h b/Build/source/libs/graphite2/graphite2-src/src/inc/opcodes.h index 76da50bf409..23f595fde1f 100644 --- a/Build/source/libs/graphite2/graphite2-src/src/inc/opcodes.h +++ b/Build/source/libs/graphite2/graphite2-src/src/inc/opcodes.h @@ -242,7 +242,7 @@ ENDOP STARTOP(put_copy) declare_params(1); const int slot_ref = int8(*param); - if (is) + if (is && !is->isDeleted()) { slotref ref = slotat(slot_ref); if (ref && ref != is) @@ -267,6 +267,7 @@ STARTOP(put_copy) ENDOP STARTOP(insert) + if (smap.decMax() <= 0) DIE; Slot *newSlot = seg.newSlot(); if (!newSlot) DIE; Slot *iss = is; @@ -555,7 +556,7 @@ STARTOP(iattr_add) const int val = int(pop()); if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) { - seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir); + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); flags |= POSITIONED; } int res = is->getAttr(&seg, slat, idx); @@ -569,7 +570,7 @@ STARTOP(iattr_sub) const int val = int(pop()); if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) { - seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir); + seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir()); flags |= POSITIONED; } int res = is->getAttr(&seg, slat, idx); diff --git a/Build/source/libs/graphite2/version.ac b/Build/source/libs/graphite2/version.ac index 10ef86c5e7e..fbf987009bb 100644 --- a/Build/source/libs/graphite2/version.ac +++ b/Build/source/libs/graphite2/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current graphite2 version -m4_define([graphite2_version], [1.3.6]) +m4_define([graphite2_version], [1.3.7]) |