Copied from upstream: https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/ec9cff7bb543 # HG changeset patch # User Jonathan Kew # Date 1456760339 0 # Node ID ec9cff7bb5439b2b4c1249ff9376d07a80172c27 # Parent 6f4d5130238790fa5810c76ffeb9eccc65efa8c9 Bug 1248876 - Update graphite2 to upstream release 1.3.6. r=jrmuizel a=sledru diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla --- a/gfx/graphite2/README.mozilla +++ b/gfx/graphite2/README.mozilla @@ -1,7 +1,3 @@ -This directory contains the Graphite2 library release 1.3.5 from -https://github.com/silnrsi/graphite/releases/download/1.3.5/graphite2-minimal-1.3.5.tgz +This directory contains the Graphite2 library release 1.3.6 from +https://github.com/silnrsi/graphite/releases/download/1.3.6/graphite-minimal-1.3.6.tgz See gfx/graphite2/moz-gr-update.sh for update procedure. - -Also includes two post-1.3.5 fixes: -a8b3ac2aed0eb132cd80efe7de88f8153e73c829 -e569e28d83491fedb31b9220493f3c07f6ec6d80 diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h --- a/gfx/graphite2/include/graphite2/Font.h +++ b/gfx/graphite2/include/graphite2/Font.h @@ -25,17 +25,17 @@ either version 2 of the License or (at your option) any later version. */ #pragma once #include "graphite2/Types.h" #define GR2_VERSION_MAJOR 1 #define GR2_VERSION_MINOR 3 -#define GR2_VERSION_BUGFIX 5 +#define GR2_VERSION_BUGFIX 6 #ifdef __cplusplus extern "C" { #endif typedef struct gr_face gr_face; typedef struct gr_font gr_font; diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh --- a/gfx/graphite2/moz-gr-update.sh +++ b/gfx/graphite2/moz-gr-update.sh @@ -14,17 +14,17 @@ RELEASE=$1 if [ "x$RELEASE" == "x" ] then echo "Must provide the version number to be used." exit 1 fi -TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz" +TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite-minimal-$RELEASE.tgz" foo=`basename $0` TMPFILE=`mktemp -t ${foo}` || exit 1 curl -L "$TARBALL" -o "$TMPFILE" tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1 rm "$TMPFILE" diff --git a/gfx/graphite2/src/CmapCache.cpp b/gfx/graphite2/src/CmapCache.cpp --- a/gfx/graphite2/src/CmapCache.cpp +++ b/gfx/graphite2/src/CmapCache.cpp @@ -33,43 +33,43 @@ of the License or (at your option) any l using namespace graphite2; const void * bmp_subtable(const Face::Table & cmap) { const void * stbl; if (!cmap.size()) return 0; - if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap.size()) - || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap.size()) - || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap.size()) - || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap.size()) - || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap.size())) + if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap + cmap.size()) + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap + cmap.size()) + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap + cmap.size()) + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap + cmap.size()) + || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap + cmap.size())) return stbl; return 0; } const void * smp_subtable(const Face::Table & cmap) { const void * stbl; if (!cmap.size()) return 0; - if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap.size()) - || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap.size())) + if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap + cmap.size()) + || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap + cmap.size())) return stbl; return 0; } template bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit) { int rangeKey = 0; uint32 codePoint = NextCodePoint(cst, 0, &rangeKey), prevCodePoint = 0; - while (codePoint != limit) + while (codePoint < limit) { unsigned int block = codePoint >> 8; if (!blocks[block]) { blocks[block] = grzeroalloc(0x100); if (!blocks[block]) return false; } diff --git a/gfx/graphite2/src/Code.cpp b/gfx/graphite2/src/Code.cpp --- a/gfx/graphite2/src/Code.cpp +++ b/gfx/graphite2/src/Code.cpp @@ -79,18 +79,19 @@ struct context class Machine::Code::decoder { public: struct limits; struct analysis { + static const int NUMCONTEXTS = 256; uint8 slotref; - context contexts[256]; + 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(); }; @@ -363,29 +364,33 @@ opcode Machine::Code::decoder::fetch_opc break; case ATTR_SET : case ATTR_ADD : case ATTR_SUB : case ATTR_SET_SLOT : if (--_stack_depth < 0) failure(underfull_stack); valid_upto(gr_slatMax, bc[0]); + if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes + failure(out_of_range_data); test_context(); break; case IATTR_SET_SLOT : if (--_stack_depth < 0) failure(underfull_stack); if (valid_upto(gr_slatMax, bc[0])) valid_upto(_max.attrid[bc[0]], bc[1]); test_context(); break; case PUSH_SLOT_ATTR : ++_stack_depth; valid_upto(gr_slatMax, bc[0]); valid_upto(_rule_length, _pre_context + 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 : ++_stack_depth; valid_upto(_max.glyf_attrs, bc[0]); valid_upto(_rule_length, _pre_context + int8(bc[1])); break; case PUSH_GLYPH_METRIC : ++_stack_depth; @@ -656,24 +661,24 @@ bool Machine::Code::decoder::validate_op return false; } return true; } bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw() { - const bool t = x < limit; + const bool t = (limit != 0) && (x < limit); if (!t) failure(out_of_range_data); return t; } bool Machine::Code::decoder::test_context() const throw() { - if (_pre_context >= _rule_length) + if (_pre_context >= _rule_length || _analysis.slotref >= analysis::NUMCONTEXTS - 1) { failure(out_of_range_data); return false; } return true; } inline @@ -681,34 +686,34 @@ void Machine::Code::failure(const status release_buffers(); _status = s; } inline void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() { if (incinsert && contexts[slotref].flags.inserted) --index; - if (index + slotref < 0) return; + 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; } inline void Machine::Code::decoder::analysis::set_noref(int index) throw() { if (contexts[slotref].flags.inserted) --index; - if (index + slotref < 0) return; + if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return; if ((index > 0 || !contexts[index + slotref].flags.inserted) && 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) return; + 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::release_buffers() throw() { if (_own) diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp --- a/gfx/graphite2/src/GlyphCache.cpp +++ b/gfx/graphite2/src/GlyphCache.cpp @@ -260,17 +260,17 @@ GlyphCache::Loader::Loader(const Face & _head = Face::Table(); return; } if (!dumb_font) { if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL - || m_pGloc.size() < 6) + || m_pGloc.size() < 8) { _head = Face::Table(); return; } const byte * p = m_pGloc; int version = be::read(p); const uint16 flags = be::read(p); _num_attrs = be::read(p); diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp --- a/gfx/graphite2/src/Pass.cpp +++ b/gfx/graphite2/src/Pass.cpp @@ -233,17 +233,17 @@ bool Pass::readRules(const byte * rule_m 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); m_progs = gralloc(prog_pool_sz); byte * prog_pool_free = m_progs, * prog_pool_end = m_progs + prog_pool_sz; if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e); Rule * r = m_rules + m_numRules - 1; - for (size_t n = m_numRules; n; --n, --r, ac_end = ac_begin, rc_end = rc_begin) + for (size_t n = m_numRules; r >= m_rules; --n, --r, ac_end = ac_begin, rc_end = rc_begin) { face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + ((n - 1) << 24)); r->preContext = *--precontext; r->sort = be::peek(--sort_key); #ifndef NDEBUG r->rule_idx = n - 1; #endif if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt) @@ -405,16 +405,17 @@ bool Pass::runGraphite(vm::Machine & m, json::closer rules_array_closer(fsm.dbgout); #endif m.slotMap().highwater(currHigh); int lc = m_iMaxLoop; do { findNDoRule(s, m, fsm); + if (m.status() != Machine::finished) return false; if (s && (s == m.slotMap().highwater() || m.slotMap().highpassed() || --lc == 0)) { if (!lc) s = m.slotMap().highwater(); lc = m_iMaxLoop; if (s) m.slotMap().highwater(s->next()); } } while (s); @@ -495,17 +496,22 @@ void Pass::findNDoRule(Slot * & slot, Ma { assert(slot); if (runFSM(fsm, slot)) { // Search for the first rule which passes the constraint const RuleEntry * r = fsm.rules.begin(), * const re = fsm.rules.end(); - while (r != re && !testConstraint(*r->rule, m)) ++r; + while (r != re && !testConstraint(*r->rule, m)) + { + ++r; + if (m.status() != Machine::finished) + return; + } #if !defined GRAPHITE2_NTRACING if (fsm.dbgout) { if (fsm.rules.size() != 0) { *fsm.dbgout << json::item << json::object; dumpRuleEventConsidered(fsm, *r); @@ -530,16 +536,17 @@ void Pass::findNDoRule(Slot * & slot, Ma } } else #endif { if (r != re) { const int adv = doAction(r->rule->action, slot, m); + if (m.status() != Machine::finished) return; if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot); adjustSlot(adv, slot, fsm.slots); return; } } } slot = slot->next(); diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp --- a/gfx/graphite2/src/Segment.cpp +++ b/gfx/graphite2/src/Segment.cpp @@ -205,18 +205,23 @@ Slot *Segment::newSlot() void Segment::freeSlot(Slot *aSlot) { if (m_last == aSlot) m_last = aSlot->prev(); if (m_first == aSlot) m_first = aSlot->next(); if (aSlot->attachedTo()) aSlot->attachedTo()->removeChild(aSlot); while (aSlot->firstChild()) { - aSlot->firstChild()->attachTo(NULL); - aSlot->removeChild(aSlot->firstChild()); + if (aSlot->firstChild()->attachedTo() == aSlot) + { + aSlot->firstChild()->attachTo(NULL); + aSlot->removeChild(aSlot->firstChild()); + } + else + aSlot->firstChild(NULL); } // reset the slot incase it is reused ::new (aSlot) Slot(aSlot->userAttrs()); memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16)); // Update generation counter for debug #if !defined GRAPHITE2_NTRACING if (m_face->logger()) ++aSlot->userAttrs()[m_silf->numUser()]; diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp --- a/gfx/graphite2/src/Slot.cpp +++ b/gfx/graphite2/src/Slot.cpp @@ -192,16 +192,18 @@ int32 Slot::clusterMetric(const Segment #define SLOTGETCOLATTR(x) { SlotCollision *c = seg->collisionInfo(this); return c ? int(c-> x) : 0; } int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const { if (ind == gr_slatUserDefnV1) { ind = gr_slatUserDefn; subindex = 0; + if (seg->numAttrs() == 0) + return 0; } else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth) { int indx = ind - gr_slatJStretch; return getJustify(seg, indx / 5, indx % 5); } switch (ind) @@ -269,16 +271,18 @@ int Slot::getAttr(const Segment *seg, at break; } void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map) { if (ind == gr_slatUserDefnV1) { ind = gr_slatUserDefn; subindex = 0; + if (seg->numAttrs() == 0) + return; } else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth) { int indx = ind - gr_slatJStretch; return setJustify(seg, indx / 5, indx % 5, value); } switch (ind) @@ -416,32 +420,32 @@ bool Slot::sibling(Slot *ap) } bool Slot::removeChild(Slot *ap) { if (this == ap || !m_child) return false; else if (ap == m_child) { Slot *nSibling = m_child->nextSibling(); - m_child->sibling(NULL); + m_child->removeSibling(nSibling); 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) { m_sibling = m_sibling->nextSibling(); - ap->sibling(NULL); + if (m_sibling) ap->removeSibling(m_sibling); return true; } else return m_sibling->removeSibling(ap); return true; } void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph) diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp --- a/gfx/graphite2/src/TtfUtil.cpp +++ b/gfx/graphite2/src/TtfUtil.cpp @@ -884,18 +884,19 @@ const void * FindCmapSubtable(const void } return 0; } /*---------------------------------------------------------------------------------------------- Check the Microsoft Unicode subtable for expected values ----------------------------------------------------------------------------------------------*/ -bool CheckCmapSubtable4(const void * pCmapSubtable4, size_t table_len /*, unsigned int maxgid*/) +bool CheckCmapSubtable4(const void * pCmapSubtable4, const void * pCmapEnd /*, unsigned int maxgid*/) { + size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable4; if (!pCmapSubtable4) return false; const Sfnt::CmapSubTable * pTable = reinterpret_cast(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; const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast(pCmapSubtable4); uint16 length = be::swap(pTable4->length); if (length > table_len) @@ -1044,17 +1045,17 @@ unsigned int CmapSubtable4NextCodepoint( *pRangeKey = nRange - 1; return 0xFFFF; } int iRange = (pRangeKey) ? *pRangeKey : 0; // Just in case we have a bad key: while (iRange > 0 && be::peek(pStartCode + iRange) > nUnicodePrev) iRange--; - while (be::peek(pTable->end_code + iRange) < nUnicodePrev) + while (iRange < nRange - 1 && be::peek(pTable->end_code + iRange) < nUnicodePrev) iRange++; // Now iRange is the range containing nUnicodePrev. unsigned int nStartCode = be::peek(pStartCode + iRange); unsigned int nEndCode = be::peek(pTable->end_code + iRange); if (nStartCode > nUnicodePrev) // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable @@ -1069,36 +1070,37 @@ unsigned int CmapSubtable4NextCodepoint( return nUnicodePrev + 1; } // Otherwise the next codepoint is the first one in the next range. // There is guaranteed to be a next range because there must be one that // ends with 0xFFFF. if (pRangeKey) *pRangeKey = iRange + 1; - return be::peek(pStartCode + iRange + 1); + return (iRange + 1 >= nRange) ? 0xFFFF : be::peek(pStartCode + iRange + 1); } /*---------------------------------------------------------------------------------------------- Check the Microsoft UCS-4 subtable for expected values. ----------------------------------------------------------------------------------------------*/ -bool CheckCmapSubtable12(const void *pCmapSubtable12, size_t table_len /*, unsigned int maxgid*/) +bool CheckCmapSubtable12(const void *pCmapSubtable12, const void *pCmapEnd /*, unsigned int maxgid*/) { + size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable12; if (!pCmapSubtable12) return false; const Sfnt::CmapSubTable * pTable = reinterpret_cast(pCmapSubtable12); if (be::swap(pTable->format) != 12) return false; const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast(pCmapSubtable12); uint32 length = be::swap(pTable12->length); if (length > table_len) return false; if (length < sizeof(Sfnt::CmapSubTableFormat12)) return false; uint32 num_groups = be::swap(pTable12->num_groups); - if (length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3)) + if (num_groups > 0x10000000 || length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3)) return false; #if 0 for (unsigned int i = 0; i < num_groups; ++i) { if (be::swap(pTable12->group[i].end_char_code) - be::swap(pTable12->group[i].start_char_code) + be::swap(pTable12->group[i].start_glyph_id) > maxgid) return false; if (i > 0 && be::swap(pTable12->group[i].start_char_code) <= be::swap(pTable12->group[i-1].end_char_code)) return false; @@ -1161,17 +1163,17 @@ unsigned int CmapSubtable12NextCodepoint *pRangeKey = nRange; return 0x10FFFF; } int iRange = (pRangeKey) ? *pRangeKey : 0; // Just in case we have a bad key: while (iRange > 0 && be::swap(pTable->group[iRange].start_char_code) > nUnicodePrev) iRange--; - while (be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev) + while (iRange < nRange - 1 && be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev) iRange++; // Now iRange is the range containing nUnicodePrev. unsigned int nStartCode = be::swap(pTable->group[iRange].start_char_code); unsigned int nEndCode = be::swap(pTable->group[iRange].end_char_code); if (nStartCode > nUnicodePrev) diff --git a/gfx/graphite2/src/call_machine.cpp b/gfx/graphite2/src/call_machine.cpp --- a/gfx/graphite2/src/call_machine.cpp +++ b/gfx/graphite2/src/call_machine.cpp @@ -67,32 +67,34 @@ using namespace vm; struct regbank { slotref is; slotref * map; SlotMap & smap; slotref * const map_base; const instr * & ip; uint8 direction; int8 flags; + Machine::status_t & status; }; typedef bool (* ip_t)(registers); // Pull in the opcode definitions // We pull these into a private namespace so these otherwise common names dont // pollute the toplevel namespace. namespace { #define smap reg.smap #define seg smap.segment #define is reg.is #define ip reg.ip #define map reg.map #define mapb reg.map_base #define flags reg.flags #define dir reg.direction +#define status reg.status #include "inc/opcodes.h" #undef smap #undef seg #undef is #undef ip #undef map @@ -108,17 +110,17 @@ Machine::stack_t Machine::run(const ins { assert(program != 0); // Declare virtual machine registers const instr * ip = program-1; const byte * dp = data; stack_t * sp = _stack + Machine::STACK_GUARD, * const sb = sp; - regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0}; + regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status}; // Run the program while ((reinterpret_cast(*++ip))(dp, sp, sb, reg)) {} const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; check_final_stack(sp); map = reg.map; *map = reg.is; diff --git a/gfx/graphite2/src/direct_machine.cpp b/gfx/graphite2/src/direct_machine.cpp --- a/gfx/graphite2/src/direct_machine.cpp +++ b/gfx/graphite2/src/direct_machine.cpp @@ -57,36 +57,37 @@ using namespace vm; namespace { const void * direct_run(const bool get_table_mode, const instr * program, const byte * data, Machine::stack_t * stack, slotref * & __map, uint8 _dir, + Machine::status_t & status, SlotMap * __smap=0) { // We need to define and return to opcode table from within this function // other inorder to take the addresses of the instruction bodies. #include "inc/opcode_table.h" if (get_table_mode) return opcode_table; // Declare virtual machine registers - const instr * ip = program; - const byte * dp = data; - Machine::stack_t * sp = stack + Machine::STACK_GUARD, - * const sb = sp; - SlotMap & smap = *__smap; - Segment & seg = smap.segment; - slotref is = *__map, - * map = __map, - * const mapb = smap.begin()+smap.context(); - uint8 dir = _dir; - int8 flags = 0; + const instr * ip = program; + const byte * dp = data; + Machine::stack_t * sp = stack + Machine::STACK_GUARD, + * const sb = sp; + SlotMap & smap = *__smap; + Segment & seg = smap.segment; + slotref is = *__map, + * map = __map, + * const mapb = smap.begin()+smap.context(); + uint8 dir = _dir; + int8 flags = 0; // start the program goto **ip; // Pull in the opcode definitions #include "inc/opcodes.h" end: @@ -95,25 +96,26 @@ const void * direct_run(const bool return sp; } } const opcode_t * Machine::getOpcodeTable() throw() { slotref * dummy; - return static_cast(direct_run(true, 0, 0, 0, dummy, 0)); + Machine::status_t dumstat = Machine::finished; + return static_cast(direct_run(true, 0, 0, 0, dummy, 0, dumstat)); } Machine::stack_t Machine::run(const instr * program, const byte * data, slotref * & is) { assert(program != 0); const stack_t *sp = static_cast( - direct_run(false, program, data, _stack, is, _map.dir(), &_map)); + direct_run(false, program, data, _stack, is, _map.dir(), _status, &_map)); const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; check_final_stack(sp); return ret; } diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h --- a/gfx/graphite2/src/inc/Code.h +++ b/gfx/graphite2/src/inc/Code.h @@ -109,17 +109,17 @@ public: int32 run(Machine &m, slotref * & map) const; CLASS_NEW_DELETE; }; inline size_t Machine::Code::estimateCodeDataOut(size_t n_bc) { - return n_bc * (sizeof(instr)+sizeof(byte)); + return (n_bc + 1) * (sizeof(instr)+sizeof(byte)); } inline Machine::Code::Code() throw() : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded), _constraint(false), _modify(false), _delete(false), _own(false) { diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h --- a/gfx/graphite2/src/inc/Machine.h +++ b/gfx/graphite2/src/inc/Machine.h @@ -135,17 +135,18 @@ public: class Code; enum status_t { finished = 0, stack_underflow, stack_not_empty, stack_overflow, - slot_offset_out_bounds + slot_offset_out_bounds, + died_early }; Machine(SlotMap &) throw(); static const opcode_t * getOpcodeTable() throw(); CLASS_NEW_DELETE; SlotMap & slotMap() const throw(); diff --git a/gfx/graphite2/src/inc/TtfUtil.h b/gfx/graphite2/src/inc/TtfUtil.h --- a/gfx/graphite2/src/inc/TtfUtil.h +++ b/gfx/graphite2/src/inc/TtfUtil.h @@ -132,21 +132,21 @@ public: int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId, int *nameIdList, int cNameIds, short *langIdList); void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument); #endif ////////////////////////////////// cmap lookup tools const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3, int nEncodingId = 1, size_t length = 0); - bool CheckCmapSubtable4(const void * pCmap31, size_t table_len /*, unsigned int maxgid*/); + bool CheckCmapSubtable4(const void * pCmap31, const void * pCmapEnd /*, unsigned int maxgid*/); gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0); unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId, int * pRangeKey = 0); - bool CheckCmapSubtable12(const void *pCmap310, size_t table_len /*, unsigned int maxgid*/); + bool CheckCmapSubtable12(const void *pCmap310, const void * pCmapEnd /*, unsigned int maxgid*/); gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0); unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId, int * pRangeKey = 0); ///////////////////////////////// horizontal metric data for a glyph bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void * pHhea, int & nLsb, unsigned int & nAdvWid); diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h --- a/gfx/graphite2/src/inc/opcodes.h +++ b/gfx/graphite2/src/inc/opcodes.h @@ -71,17 +71,17 @@ of the License or (at your option) any l #define use_params(n) dp += n #define declare_params(n) const byte * param = dp; \ use_params(n); #define push(n) { *++sp = n; } #define pop() (*sp--) #define slotat(x) (map[(x)]) -#define DIE { is=seg.last(); EXIT(1); } +#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); } #define POSITIONED 1 STARTOP(nop) do {} while (0); ENDOP STARTOP(push_byte) declare_params(1); @@ -387,30 +387,30 @@ STARTOP(attr_set) ENDOP STARTOP(attr_add) declare_params(1); const attrCode slat = attrCode(uint8(*param)); 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, 0); is->setAttr(&seg, slat, 0, val + res, smap); ENDOP STARTOP(attr_sub) declare_params(1); const attrCode slat = attrCode(uint8(*param)); 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, 0); is->setAttr(&seg, slat, 0, res - val, smap); ENDOP STARTOP(attr_set_slot) declare_params(1); @@ -429,17 +429,17 @@ STARTOP(iattr_set_slot) ENDOP STARTOP(push_slot_attr) declare_params(2); const attrCode slat = attrCode(uint8(param[0])); const int slot_ref = int8(param[1]); 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; } slotref slot = slotat(slot_ref); if (slot) { int res = slot->getAttr(&seg, slat, 0); push(res); } @@ -505,17 +505,17 @@ ENDOP STARTOP(push_islot_attr) declare_params(3); const attrCode slat = attrCode(uint8(param[0])); const int slot_ref = int8(param[1]), idx = uint8(param[2]); 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; } slotref slot = slotat(slot_ref); if (slot) { int res = slot->getAttr(&seg, slat, idx); push(res); }