b134a80c36
* gnu/packages/patches/icecat-update-graphite2-pt2.patch: New file. * gnu-system.am (dist_patch_DATA): Add it. * gnu/packages/gnuzilla.scm (icecat)[source]: Add patch.
861 lines
32 KiB
Diff
861 lines
32 KiB
Diff
Copied from upstream:
|
|
https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/ec9cff7bb543
|
|
|
|
# HG changeset patch
|
|
# User Jonathan Kew <jkew@mozilla.com>
|
|
# 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 <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),
|
|
uint16 (*LookupCodePoint)(const void *, unsigned int, int)>
|
|
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<uint16>(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<uint32>(p);
|
|
const uint16 flags = be::read<uint16>(p);
|
|
_num_attrs = be::read<uint16>(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<byte>(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<uint16>(--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<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;
|
|
const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(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<uint16>(pStartCode + iRange) > nUnicodePrev)
|
|
iRange--;
|
|
- while (be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
|
|
+ while (iRange < nRange - 1 && be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
|
|
iRange++;
|
|
|
|
// Now iRange is the range containing nUnicodePrev.
|
|
unsigned int nStartCode = be::peek<uint16>(pStartCode + iRange);
|
|
unsigned int nEndCode = be::peek<uint16>(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<uint16>(pStartCode + iRange + 1);
|
|
+ return (iRange + 1 >= nRange) ? 0xFFFF : be::peek<uint16>(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<const Sfnt::CmapSubTable *>(pCmapSubtable12);
|
|
if (be::swap(pTable->format) != 12)
|
|
return false;
|
|
const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(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_t>(*++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<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0));
|
|
+ Machine::status_t dumstat = Machine::finished;
|
|
+ return static_cast<const opcode_t *>(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<const stack_t *>(
|
|
- 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);
|
|
}
|
|
|