Bug 1207061 - Update graphite2 library to release 1.3.3. r=jdaggett a=lizzard
authorJonathan Kew <jkew@mozilla.com>
Wed, 30 Sep 2015 08:45:05 +0100
changeset 296249 d50b9f101b1958098a80a92cf82cfbfcc4eb9628
parent 296248 e869cbda78b5dad6a46ebfeb655cc6d352e5e66f
child 296250 fd81781c7307afdd08545bbdba10e5a36001d3c4
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdaggett, lizzard
bugs1207061
milestone43.0a2
Bug 1207061 - Update graphite2 library to release 1.3.3. r=jdaggett a=lizzard
gfx/graphite2/README.mozilla
gfx/graphite2/include/graphite2/Font.h
gfx/graphite2/src/Code.cpp
gfx/graphite2/src/Collider.cpp
gfx/graphite2/src/Decompressor.cpp
gfx/graphite2/src/Face.cpp
gfx/graphite2/src/Intervals.cpp
gfx/graphite2/src/Pass.cpp
gfx/graphite2/src/Segment.cpp
gfx/graphite2/src/TtfUtil.cpp
gfx/graphite2/src/inc/Collider.h
gfx/graphite2/src/inc/Compression.h
gfx/graphite2/src/inc/Decompressor.h
gfx/graphite2/src/inc/Segment.h
gfx/graphite2/src/inc/opcodes.h
--- a/gfx/graphite2/README.mozilla
+++ b/gfx/graphite2/README.mozilla
@@ -1,6 +1,6 @@
 This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev
 
-Current version derived from upstream changeset 0f9edca71849
+Current version derived from upstream changeset ff457b44c490
 
 See gfx/graphite2/moz-gr-update.sh for update procedure.
 
--- 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  2
+#define GR2_VERSION_BUGFIX  3
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 typedef struct gr_face          gr_face;
 typedef struct gr_font          gr_font;
--- a/gfx/graphite2/src/Code.cpp
+++ b/gfx/graphite2/src/Code.cpp
@@ -209,18 +209,18 @@ Machine::Code::Code(bool is_constraint, 
 
     assert((_constraint && immutable()) || !_constraint);
     dec.apply_analysis(_code, _code + _instr_count);
     _max_ref = dec.max_ref();
     
     // Now we know exactly how much code and data the program really needs
     // realloc the buffers to exactly the right size so we don't waste any 
     // memory.
-    assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_instr_count));
-    assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_data_size));
+    assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_instr_count));
+    assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_data_size));
     memmove(_code + (_instr_count+1), _data, _data_size*sizeof(byte));
     size_t const total_sz = ((_instr_count+1) + (_data_size + sizeof(instr)-1)/sizeof(instr))*sizeof(instr);
     if (_out)
         *_out += total_sz;
     else
         _code = static_cast<instr *>(realloc(_code, total_sz));
    _data = reinterpret_cast<byte *>(_code + (_instr_count+1));
 
--- a/gfx/graphite2/src/Collider.cpp
+++ b/gfx/graphite2/src/Collider.cpp
@@ -46,17 +46,17 @@ using namespace graphite2;
 ////    SHIFT-COLLIDER    ////
 
 // Initialize the Collider to hold the basic movement limits for the
 // target slot, the one we are focusing on fixing.
 bool ShiftCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float margin, float marginWeight,
     const Position &currShift, const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout)
 {
     int i;
-    float max, min;
+    float mx, mn;
     float a, shift;
     const GlyphCache &gc = seg->getFace()->glyphs();
     unsigned short gid = aSlot->gid();
     if (!gc.check(gid))
         return false;
     const BBox &bb = gc.getBoundingBBox(gid);
     const SlantBox &sb = gc.getBoundingSlantBox(gid);
     //float sx = aSlot->origin().x + currShift.x;
@@ -66,46 +66,46 @@ bool ShiftCollider::initSlot(Segment *se
     else
         _limit = limit;
     // For a ShiftCollider, these indices indicate which vector we are moving by:
     // each _ranges represents absolute space with respect to the origin of the slot. Thus take into account true origins but subtract the vmin for the slot
     for (i = 0; i < 4; ++i)
     {
         switch (i) {
             case 0 :	// x direction
-                min = _limit.bl.x + currOffset.x;
-                max = _limit.tr.x + currOffset.x;
+                mn = _limit.bl.x + currOffset.x;
+                mx = _limit.tr.x + currOffset.x;
                 _len[i] = bb.xa - bb.xi;
                 a = currOffset.y + currShift.y;
-                _ranges[i].initialise<XY>(min, max, margin, marginWeight, a);
+                _ranges[i].initialise<XY>(mn, mx, margin, marginWeight, a);
                 break;
             case 1 :	// y direction
-                min = _limit.bl.y + currOffset.y;
-                max = _limit.tr.y + currOffset.y;
+                mn = _limit.bl.y + currOffset.y;
+                mx = _limit.tr.y + currOffset.y;
                 _len[i] = bb.ya - bb.yi;
                 a = currOffset.x + currShift.x;
-                _ranges[i].initialise<XY>(min, max, margin, marginWeight, a);
+                _ranges[i].initialise<XY>(mn, mx, margin, marginWeight, a);
                 break;
             case 2 :	// sum (negatively sloped diagonal boundaries)
                 // pick closest x,y limit boundaries in s direction
                 shift = currOffset.x + currOffset.y + currShift.x + currShift.y;
-                min = -2 * std::min(currShift.x - _limit.bl.x, currShift.y - _limit.bl.y) + shift;
-                max = 2 * std::min(_limit.tr.x - currShift.x, _limit.tr.y - currShift.y) + shift;
+                mn = -2 * min(currShift.x - _limit.bl.x, currShift.y - _limit.bl.y) + shift;
+                mx = 2 * min(_limit.tr.x - currShift.x, _limit.tr.y - currShift.y) + shift;
                 _len[i] = sb.sa - sb.si;
                 a = currOffset.x - currOffset.y + currShift.x - currShift.y;
-                _ranges[i].initialise<SD>(min, max, margin / ISQRT2, marginWeight, a);
+                _ranges[i].initialise<SD>(mn, mx, margin / ISQRT2, marginWeight, a);
                 break;
             case 3 :	// diff (positively sloped diagonal boundaries)
                 // pick closest x,y limit boundaries in d direction
                 shift = currOffset.x - currOffset.y + currShift.x - currShift.y;
-                min = -2 * std::min(currShift.x - _limit.bl.x, _limit.tr.y - currShift.y) + shift;
-                max = 2 * std::min(_limit.tr.x - currShift.x, currShift.y - _limit.bl.y) + shift;
+                mn = -2 * min(currShift.x - _limit.bl.x, _limit.tr.y - currShift.y) + shift;
+                mx = 2 * min(_limit.tr.x - currShift.x, currShift.y - _limit.bl.y) + shift;
                 _len[i] = sb.da - sb.di;
                 a = currOffset.x + currOffset.y + currShift.x + currShift.y;
-                _ranges[i].initialise<SD>(min, max, margin / ISQRT2, marginWeight, a);
+                _ranges[i].initialise<SD>(mn, mx, margin / ISQRT2, marginWeight, a);
                 break;
         }
     }
 
 	_target = aSlot;
     if ((dir & 1) == 0)
     {
         // For LTR, switch and negate x limits.
@@ -170,35 +170,35 @@ void ShiftCollider::addBox_slope(bool is
                                                 (minright ? box.tr.y : box.bl.y) - c, a, 0, false);
             }
             break;
         case 2 :
             if (box.bl.x - box.tr.y < org.x - org.y + sb.da && box.tr.x - box.bl.y > org.x - org.y + sb.di)
             {
                 float d = org.x - org.y + 0.5f * (sb.di + sb.da);
                 c = 0.5f * (sb.si + sb.sa);
-                float smax = std::min(2 * box.tr.x - d, 2 * box.tr.y + d);
-                float smin = std::max(2 * box.bl.x - d, 2 * box.bl.y + d);
+                float smax = min(2 * box.tr.x - d, 2 * box.tr.y + d);
+                float smin = max(2 * box.bl.x - d, 2 * box.bl.y + d);
                 if (smin > smax) return;
                 float si;
                 a = d;
                 if (isx)
                     si = 2 * (minright ? box.tr.x : box.bl.x) - a;
                 else
                     si = 2 * (minright ? box.tr.y : box.bl.y) + a;
                 _ranges[axis].weighted<SD>(smin - c, smax - c, weight / 2, a, m / 2, si, 0, 0, isx);
             }
             break;
         case 3 :
             if (box.bl.x + box.bl.y < org.x + org.y + sb.sa && box.tr.x + box.tr.y > org.x + org.y + sb.si)
             {
                 float s = org.x + org.y + 0.5f * (sb.si + sb.sa);
                 c = 0.5f * (sb.di + sb.da);
-                float dmax = std::min(2 * box.tr.x - s, s - 2 * box.bl.y);
-                float dmin = std::max(2 * box.bl.x - s, s - 2 * box.tr.y);
+                float dmax = min(2 * box.tr.x - s, s - 2 * box.bl.y);
+                float dmin = max(2 * box.bl.x - s, s - 2 * box.tr.y);
                 if (dmin > dmax) return;
                 float di;
                 a = s;
                 if (isx)
                     di = 2 * (minright ? box.tr.x : box.bl.x) - a;
                 else
                     di = 2 * (minright ? box.tr.y : box.bl.y) + a;
                 _ranges[axis].weighted<SD>(dmin - c, dmax - c, weight / 2, a, m / 2, di, 0, 0, !isx);
@@ -263,288 +263,294 @@ inline void ShiftCollider::removeBox(con
 // with the given neighbor slot. Also determine if there is in fact a collision
 // between the target and the given slot.
 bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift,
 		bool isAfter,  // slot is logically after _target
 		bool sameCluster, bool &hasCol, bool isExclusion,
         GR_MAYBE_UNUSED json * const dbgout )
 {
     bool isCol = false;
-    const float tx = _currOffset.x + _currShift.x;
-    const float ty = _currOffset.y + _currShift.y;
-    const float td = tx - ty;
-    const float ts = tx + ty;
     const float sx = slot->origin().x - _origin.x + currShift.x;
     const float sy = slot->origin().y - _origin.y + currShift.y;
     const float sd = sx - sy;
     const float ss = sx + sy;
     float vmin, vmax;
     float omin, omax, otmin, otmax;
     float cmin, cmax;   // target limits
     float torg;
     const GlyphCache &gc = seg->getFace()->glyphs();
     const unsigned short gid = slot->gid();
     if (!gc.check(gid))
         return false;
-    const unsigned short tgid = _target->gid();
     const BBox &bb = gc.getBoundingBBox(gid);
-    const SlantBox &sb = gc.getBoundingSlantBox(gid);
-    const BBox &tbb = gc.getBoundingBBox(tgid);
-    const SlantBox &tsb = gc.getBoundingSlantBox(tgid);
 
     SlotCollision * cslot = seg->collisionInfo(slot);
     int orderFlags = 0;
     bool sameClass = _seqProxClass == 0 && cslot->seqClass() == _seqClass;
     if (sameCluster && _seqClass 
         && (sameClass || (_seqProxClass != 0 && cslot->seqClass() == _seqProxClass)))
 		// Force the target glyph to be in the specified direction from the slot we're testing.
         orderFlags = _seqOrder;
-    float seq_above_wt = cslot->seqAboveWt();
-    float seq_below_wt = cslot->seqBelowWt();
-    float seq_valign_wt = cslot->seqValignWt();
+
+    // short circuit if only interested in direct collision and we are out of range
+    if (orderFlags || (sx + bb.xa + _margin >= _limit.bl.x && sx + bb.xi - _margin <= _limit.tr.x)
+                    || (sy + bb.ya + _margin >= _limit.bl.y && sy + bb.yi - _margin <= _limit.tr.y))
 
-    // if isAfter, invert orderFlags for diagonal orders.
-    if (isAfter)
     {
-        // invert appropriate bits
-        orderFlags ^= (sameClass ? 0x3F : 0x3);
-        // consider 2 bits at a time, non overlapping. If both bits set, clear them
-        orderFlags = orderFlags ^ ((((orderFlags >> 1) & orderFlags) & 0x15) * 3);
-    }
+        const float tx = _currOffset.x + _currShift.x;
+        const float ty = _currOffset.y + _currShift.y;
+        const float td = tx - ty;
+        const float ts = tx + ty;
+        const SlantBox &sb = gc.getBoundingSlantBox(gid);
+        const unsigned short tgid = _target->gid();
+        const BBox &tbb = gc.getBoundingBBox(tgid);
+        const SlantBox &tsb = gc.getBoundingSlantBox(tgid);
+        float seq_above_wt = cslot->seqAboveWt();
+        float seq_below_wt = cslot->seqBelowWt();
+        float seq_valign_wt = cslot->seqValignWt();
+        // if isAfter, invert orderFlags for diagonal orders.
+        if (isAfter)
+        {
+            // invert appropriate bits
+            orderFlags ^= (sameClass ? 0x3F : 0x3);
+            // consider 2 bits at a time, non overlapping. If both bits set, clear them
+            orderFlags = orderFlags ^ ((((orderFlags >> 1) & orderFlags) & 0x15) * 3);
+        }
 
 #if !defined GRAPHITE2_NTRACING
-    if (dbgout)
-        dbgout->setenv(0, slot);
+        if (dbgout)
+            dbgout->setenv(0, slot);
 #endif
 
-    // Process main bounding octabox.
-    for (int i = 0; i < 4; ++i)
-    {
-        switch (i) {
-            case 0 :	// x direction
-                vmin = std::max(std::max(bb.xi - tbb.xa + sx, sb.di - tsb.da + ty + sd), sb.si - tsb.sa - ty + ss);
-                vmax = std::min(std::min(bb.xa - tbb.xi + sx, sb.da - tsb.di + ty + sd), sb.sa - tsb.si - ty + ss);
-                otmin = tbb.yi + ty;
-                otmax = tbb.ya + ty;
-                omin = bb.yi + sy;
-                omax = bb.ya + sy;
-                torg = _currOffset.x;
-                cmin = _limit.bl.x + torg;
-                cmax = _limit.tr.x - tbb.xi + tbb.xa + torg;
-                break;
-            case 1 :	// y direction
-                vmin = std::max(std::max(bb.yi - tbb.ya + sy, tsb.di - sb.da + tx - sd), sb.si - tsb.sa - tx + ss);
-                vmax = std::min(std::min(bb.ya - tbb.yi + sy, tsb.da - sb.di + tx - sd), sb.sa - tsb.si - tx + ss);
-                otmin = tbb.xi + tx;
-                otmax = tbb.xa + tx;
-                omin = bb.xi + sx;
-                omax = bb.xa + sx;
-                torg = _currOffset.y;
-                cmin = _limit.bl.y + torg;
-                cmax = _limit.tr.y - tbb.yi + tbb.ya + torg;
-                break;
-            case 2 :    // sum - moving along the positively-sloped vector, so the boundaries are the
-                        // negatively-sloped boundaries.
-                vmin = std::max(std::max(sb.si - tsb.sa + ss, 2 * (bb.yi - tbb.ya + sy) + td), 2 * (bb.xi - tbb.xa + sx) - td);
-                vmax = std::min(std::min(sb.sa - tsb.si + ss, 2 * (bb.ya - tbb.yi + sy) + td), 2 * (bb.xa - tbb.xi + sx) - td);
-                otmin = tsb.di + td;
-                otmax = tsb.da + td;
-                omin = sb.di + sd;
-                omax = sb.da + sd;
-                torg = _currOffset.x + _currOffset.y;
-                cmin = _limit.bl.x + _limit.bl.y + torg;
-                cmax = _limit.tr.x + _limit.tr.y - tsb.si + tsb.sa + torg;
-                break;
-            case 3 :    // diff - moving along the negatively-sloped vector, so the boundaries are the
-                        // positively-sloped boundaries.
-                vmin = std::max(std::max(sb.di - tsb.da + sd, 2 * (bb.xi - tbb.xa + sx) - ts), -2 * (bb.ya - tbb.yi + sy) + ts);
-                vmax = std::min(std::min(sb.da - tsb.di + sd, 2 * (bb.xa - tbb.xi + sx) - ts), -2 * (bb.yi - tbb.ya + sy) + ts);
-                otmin = tsb.si + ts;
-                otmax = tsb.sa + ts;
-                omin = sb.si + ss;
-                omax = sb.sa + ss;
-                torg = _currOffset.x - _currOffset.y;
-                cmin = _limit.bl.x - _limit.tr.y + torg;
-                cmax = _limit.tr.x - _limit.bl.y - tsb.di + tsb.da + torg;
-                break;
-            default :
-                continue;
-        }
-        
+        // Process main bounding octabox.
+        for (int i = 0; i < 4; ++i)
+        {
+            switch (i) {
+                case 0 :	// x direction
+                    vmin = max(max(bb.xi - tbb.xa + sx, sb.di - tsb.da + ty + sd), sb.si - tsb.sa - ty + ss);
+                    vmax = min(min(bb.xa - tbb.xi + sx, sb.da - tsb.di + ty + sd), sb.sa - tsb.si - ty + ss);
+                    otmin = tbb.yi + ty;
+                    otmax = tbb.ya + ty;
+                    omin = bb.yi + sy;
+                    omax = bb.ya + sy;
+                    torg = _currOffset.x;
+                    cmin = _limit.bl.x + torg;
+                    cmax = _limit.tr.x - tbb.xi + tbb.xa + torg;
+                    break;
+                case 1 :	// y direction
+                    vmin = max(max(bb.yi - tbb.ya + sy, tsb.di - sb.da + tx - sd), sb.si - tsb.sa - tx + ss);
+                    vmax = min(min(bb.ya - tbb.yi + sy, tsb.da - sb.di + tx - sd), sb.sa - tsb.si - tx + ss);
+                    otmin = tbb.xi + tx;
+                    otmax = tbb.xa + tx;
+                    omin = bb.xi + sx;
+                    omax = bb.xa + sx;
+                    torg = _currOffset.y;
+                    cmin = _limit.bl.y + torg;
+                    cmax = _limit.tr.y - tbb.yi + tbb.ya + torg;
+                    break;
+                case 2 :    // sum - moving along the positively-sloped vector, so the boundaries are the
+                            // negatively-sloped boundaries.
+                    vmin = max(max(sb.si - tsb.sa + ss, 2 * (bb.yi - tbb.ya + sy) + td), 2 * (bb.xi - tbb.xa + sx) - td);
+                    vmax = min(min(sb.sa - tsb.si + ss, 2 * (bb.ya - tbb.yi + sy) + td), 2 * (bb.xa - tbb.xi + sx) - td);
+                    otmin = tsb.di + td;
+                    otmax = tsb.da + td;
+                    omin = sb.di + sd;
+                    omax = sb.da + sd;
+                    torg = _currOffset.x + _currOffset.y;
+                    cmin = _limit.bl.x + _limit.bl.y + torg;
+                    cmax = _limit.tr.x + _limit.tr.y - tsb.si + tsb.sa + torg;
+                    break;
+                case 3 :    // diff - moving along the negatively-sloped vector, so the boundaries are the
+                            // positively-sloped boundaries.
+                    vmin = max(max(sb.di - tsb.da + sd, 2 * (bb.xi - tbb.xa + sx) - ts), -2 * (bb.ya - tbb.yi + sy) + ts);
+                    vmax = min(min(sb.da - tsb.di + sd, 2 * (bb.xa - tbb.xi + sx) - ts), -2 * (bb.yi - tbb.ya + sy) + ts);
+                    otmin = tsb.si + ts;
+                    otmax = tsb.sa + ts;
+                    omin = sb.si + ss;
+                    omax = sb.sa + ss;
+                    torg = _currOffset.x - _currOffset.y;
+                    cmin = _limit.bl.x - _limit.tr.y + torg;
+                    cmax = _limit.tr.x - _limit.bl.y - tsb.di + tsb.da + torg;
+                    break;
+                default :
+                    continue;
+            }
+            
 #if !defined GRAPHITE2_NTRACING
-        if (dbgout)
-            dbgout->setenv(1, reinterpret_cast<void *>(-1));
+            if (dbgout)
+                dbgout->setenv(1, reinterpret_cast<void *>(-1));
 #define DBGTAG(x) if (dbgout) dbgout->setenv(1, reinterpret_cast<void *>(-x));
 #else
 #define DBGTAG(x)
 #endif
 
-        if (orderFlags)
-        {
-            Position org(tx, ty);
-            float xminf = _limit.bl.x + _currOffset.x + tbb.xi;
-            float xpinf = _limit.tr.x + _currOffset.x + tbb.xa;
-            float ypinf = _limit.tr.y + _currOffset.y + tbb.ya;
-            float yminf = _limit.bl.y + _currOffset.y + tbb.yi;
-            switch (orderFlags) {
-                case SlotCollision::SEQ_ORDER_RIGHTUP :
-                {
-                    float r1Xedge = cslot->seqAboveXoff() + 0.5f * (bb.xi + bb.xa) + sx;
-                    float r3Xedge = cslot->seqBelowXlim() + bb.xa + sx + 0.5f * (tbb.xa - tbb.xi);
-                    float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
-                    
-                    // DBGTAG(1x) means the regions are up and right
-                    // region 1
-                    DBGTAG(11)
-                    addBox_slope(true, Rect(Position(xminf, r2Yedge), Position(r1Xedge, ypinf)),
-                                    tbb, tsb, org, 0, seq_above_wt, true, i);
-                    // region 2
-                    DBGTAG(12)
-                    removeBox(Rect(Position(xminf, yminf), Position(r3Xedge, r2Yedge)), tbb, tsb, org, i);
-                    // region 3, which end is zero is irrelevant since m weight is 0
-                    DBGTAG(13)
-                    addBox_slope(true, Rect(Position(r3Xedge, yminf), Position(xpinf, r2Yedge - cslot->seqValignHt())),
-                                    tbb, tsb, org, seq_below_wt, 0, true, i);
-                    // region 4
-                    DBGTAG(14)
-                    addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge), Position(xpinf, r2Yedge + cslot->seqValignHt())),
-                                    tbb, tsb, org, 0, seq_valign_wt, true, i);
-                    // region 5
-                    DBGTAG(15)
-                    addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge - cslot->seqValignHt()), Position(xpinf, r2Yedge)),
-                                    tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
-                    break;
-                }
-                case SlotCollision::SEQ_ORDER_LEFTDOWN :
-                {
-                    float r1Xedge = 0.5f * (bb.xi + bb.xa) + cslot->seqAboveXoff() + sx;
-                    float r3Xedge = bb.xi - cslot->seqBelowXlim() + sx - 0.5f * (tbb.xa - tbb.xi);
-                    float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
-                    // DBGTAG(2x) means the regions are up and right
-                    // region 1
-                    DBGTAG(21)
-                    addBox_slope(true, Rect(Position(r1Xedge, yminf), Position(xpinf, r2Yedge)),
-                                    tbb, tsb, org, 0, seq_above_wt, false, i);
-                    // region 2
-                    DBGTAG(22)
-                    removeBox(Rect(Position(r3Xedge, r2Yedge), Position(xpinf, ypinf)), tbb, tsb, org, i);
-                    // region 3
-                    DBGTAG(23)
-                    addBox_slope(true, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()), Position(r3Xedge, ypinf)),
-                                    tbb, tsb, org, seq_below_wt, 0, false, i);
-                    // region 4
-                    DBGTAG(24)
-                    addBox_slope(false, Rect(Position(xminf, r2Yedge), Position(sx + bb.xa, r2Yedge + cslot->seqValignHt())),
-                                    tbb, tsb, org, 0, seq_valign_wt, true, i);
-                    // region 5
-                    DBGTAG(25)
-                    addBox_slope(false, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()),
-                                    Position(sx + bb.xa, r2Yedge)), tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
-                    break;
-                }
-                case SlotCollision::SEQ_ORDER_NOABOVE : // enforce neighboring glyph being above
-                    DBGTAG(31);
-                    removeBox(Rect(Position(bb.xi - tbb.xa + sx, sy + bb.ya), 
-                                    Position(bb.xa - tbb.xi + sx, ypinf)), tbb, tsb, org, i);
-                    break;
-                case SlotCollision::SEQ_ORDER_NOBELOW :	// enforce neighboring glyph being below
-                    DBGTAG(32);
-                    removeBox(Rect(Position(bb.xi - tbb.xa + sx, yminf),
-                                    Position(bb.xa - tbb.xi + sx, sy + bb.yi)), tbb, tsb, org, i);
-                    break;
-                case SlotCollision::SEQ_ORDER_NOLEFT :  // enforce neighboring glyph being to the left
-                    DBGTAG(33)
-                    removeBox(Rect(Position(xminf, bb.yi - tbb.ya + sy),
-                                    Position(bb.xi - tbb.xa + sx, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
-                    break;
-                case SlotCollision::SEQ_ORDER_NORIGHT : // enforce neighboring glyph being to the right
-                    DBGTAG(34)
-                    removeBox(Rect(Position(bb.xa - tbb.xi + sx, bb.yi - tbb.ya + sy),
-                                    Position(xpinf, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
-                    break;
-                default :
-                    break;
-            }
-        }
-
-        if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
-            continue;
-
-        // Process sub-boxes that are defined for this glyph.
-        // We only need to do this if there was in fact a collision with the main octabox.
-        uint8 numsub = gc.numSubBounds(gid);
-        if (numsub > 0)
-        {
-            bool anyhits = false;
-            for (int j = 0; j < numsub; ++j)
+            if (orderFlags)
             {
-                const BBox &sbb = gc.getSubBoundingBBox(gid, j);
-                const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, j);
-                switch (i) {
-                    case 0 :    // x
-                        vmin = std::max(std::max(sbb.xi-tbb.xa+sx, ssb.di-tsb.da+sd+ty), ssb.si-tsb.sa+ss-ty);
-                        vmax = std::min(std::min(sbb.xa-tbb.xi+sx, ssb.da-tsb.di+sd+ty), ssb.sa-tsb.si+ss-ty);
-                        omin = sbb.yi + sy;
-                        omax = sbb.ya + sy;
+                Position org(tx, ty);
+                float xminf = _limit.bl.x + _currOffset.x + tbb.xi;
+                float xpinf = _limit.tr.x + _currOffset.x + tbb.xa;
+                float ypinf = _limit.tr.y + _currOffset.y + tbb.ya;
+                float yminf = _limit.bl.y + _currOffset.y + tbb.yi;
+                switch (orderFlags) {
+                    case SlotCollision::SEQ_ORDER_RIGHTUP :
+                    {
+                        float r1Xedge = cslot->seqAboveXoff() + 0.5f * (bb.xi + bb.xa) + sx;
+                        float r3Xedge = cslot->seqBelowXlim() + bb.xa + sx + 0.5f * (tbb.xa - tbb.xi);
+                        float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
+                        
+                        // DBGTAG(1x) means the regions are up and right
+                        // region 1
+                        DBGTAG(11)
+                        addBox_slope(true, Rect(Position(xminf, r2Yedge), Position(r1Xedge, ypinf)),
+                                        tbb, tsb, org, 0, seq_above_wt, true, i);
+                        // region 2
+                        DBGTAG(12)
+                        removeBox(Rect(Position(xminf, yminf), Position(r3Xedge, r2Yedge)), tbb, tsb, org, i);
+                        // region 3, which end is zero is irrelevant since m weight is 0
+                        DBGTAG(13)
+                        addBox_slope(true, Rect(Position(r3Xedge, yminf), Position(xpinf, r2Yedge - cslot->seqValignHt())),
+                                        tbb, tsb, org, seq_below_wt, 0, true, i);
+                        // region 4
+                        DBGTAG(14)
+                        addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge), Position(xpinf, r2Yedge + cslot->seqValignHt())),
+                                        tbb, tsb, org, 0, seq_valign_wt, true, i);
+                        // region 5
+                        DBGTAG(15)
+                        addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge - cslot->seqValignHt()), Position(xpinf, r2Yedge)),
+                                        tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
                         break;
-                    case 1 :    // y
-                        vmin = std::max(std::max(sbb.yi-tbb.ya+sy, tsb.di-ssb.da-sd+tx), ssb.si-tsb.sa+ss-tx);
-                        vmax = std::min(std::min(sbb.ya-tbb.yi+sy, tsb.da-ssb.di-sd+tx), ssb.sa-tsb.si+ss-tx);
-                        omin = sbb.xi + sx;
-                        omax = sbb.xa + sx;
+                    }
+                    case SlotCollision::SEQ_ORDER_LEFTDOWN :
+                    {
+                        float r1Xedge = 0.5f * (bb.xi + bb.xa) + cslot->seqAboveXoff() + sx;
+                        float r3Xedge = bb.xi - cslot->seqBelowXlim() + sx - 0.5f * (tbb.xa - tbb.xi);
+                        float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
+                        // DBGTAG(2x) means the regions are up and right
+                        // region 1
+                        DBGTAG(21)
+                        addBox_slope(true, Rect(Position(r1Xedge, yminf), Position(xpinf, r2Yedge)),
+                                        tbb, tsb, org, 0, seq_above_wt, false, i);
+                        // region 2
+                        DBGTAG(22)
+                        removeBox(Rect(Position(r3Xedge, r2Yedge), Position(xpinf, ypinf)), tbb, tsb, org, i);
+                        // region 3
+                        DBGTAG(23)
+                        addBox_slope(true, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()), Position(r3Xedge, ypinf)),
+                                        tbb, tsb, org, seq_below_wt, 0, false, i);
+                        // region 4
+                        DBGTAG(24)
+                        addBox_slope(false, Rect(Position(xminf, r2Yedge), Position(sx + bb.xa, r2Yedge + cslot->seqValignHt())),
+                                        tbb, tsb, org, 0, seq_valign_wt, true, i);
+                        // region 5
+                        DBGTAG(25)
+                        addBox_slope(false, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()),
+                                        Position(sx + bb.xa, r2Yedge)), tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
                         break;
-                    case 2 :    // sum
-                        vmin = std::max(std::max(ssb.si-tsb.sa+ss, 2*(sbb.yi-tbb.ya+sy)+td), 2*(sbb.xi-tbb.xa+sx)-td);
-                        vmax = std::min(std::min(ssb.sa-tsb.si+ss, 2*(sbb.ya-tbb.yi+sy)+td), 2*(sbb.xa-tbb.xi+sx)-td);
-                        omin = ssb.di + sd;
-                        omax = ssb.da + sd;
+                    }
+                    case SlotCollision::SEQ_ORDER_NOABOVE : // enforce neighboring glyph being above
+                        DBGTAG(31);
+                        removeBox(Rect(Position(bb.xi - tbb.xa + sx, sy + bb.ya), 
+                                        Position(bb.xa - tbb.xi + sx, ypinf)), tbb, tsb, org, i);
+                        break;
+                    case SlotCollision::SEQ_ORDER_NOBELOW :	// enforce neighboring glyph being below
+                        DBGTAG(32);
+                        removeBox(Rect(Position(bb.xi - tbb.xa + sx, yminf),
+                                        Position(bb.xa - tbb.xi + sx, sy + bb.yi)), tbb, tsb, org, i);
                         break;
-                    case 3 :    // diff
-                        vmin = std::max(std::max(ssb.di-tsb.da+sd, 2*(sbb.xi-tbb.xa+sx)-ts), -2*(sbb.ya-tbb.yi+sy)+ts);
-                        vmax = std::min(std::min(ssb.da-tsb.di+sd, 2*(sbb.xa-tbb.xi+sx)-ts), -2*(sbb.yi-tbb.ya+sy)+ts);
-                        omin = ssb.si + ss;
-                        omax = ssb.sa + ss;
+                    case SlotCollision::SEQ_ORDER_NOLEFT :  // enforce neighboring glyph being to the left
+                        DBGTAG(33)
+                        removeBox(Rect(Position(xminf, bb.yi - tbb.ya + sy),
+                                        Position(bb.xi - tbb.xa + sx, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
+                        break;
+                    case SlotCollision::SEQ_ORDER_NORIGHT : // enforce neighboring glyph being to the right
+                        DBGTAG(34)
+                        removeBox(Rect(Position(bb.xa - tbb.xi + sx, bb.yi - tbb.ya + sy),
+                                        Position(xpinf, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
+                        break;
+                    default :
                         break;
                 }
-                if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
-                    continue;
+            }
+
+            if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
+                continue;
+
+            // Process sub-boxes that are defined for this glyph.
+            // We only need to do this if there was in fact a collision with the main octabox.
+            uint8 numsub = gc.numSubBounds(gid);
+            if (numsub > 0)
+            {
+                bool anyhits = false;
+                for (int j = 0; j < numsub; ++j)
+                {
+                    const BBox &sbb = gc.getSubBoundingBBox(gid, j);
+                    const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, j);
+                    switch (i) {
+                        case 0 :    // x
+                            vmin = max(max(sbb.xi-tbb.xa+sx, ssb.di-tsb.da+sd+ty), ssb.si-tsb.sa+ss-ty);
+                            vmax = min(min(sbb.xa-tbb.xi+sx, ssb.da-tsb.di+sd+ty), ssb.sa-tsb.si+ss-ty);
+                            omin = sbb.yi + sy;
+                            omax = sbb.ya + sy;
+                            break;
+                        case 1 :    // y
+                            vmin = max(max(sbb.yi-tbb.ya+sy, tsb.di-ssb.da-sd+tx), ssb.si-tsb.sa+ss-tx);
+                            vmax = min(min(sbb.ya-tbb.yi+sy, tsb.da-ssb.di-sd+tx), ssb.sa-tsb.si+ss-tx);
+                            omin = sbb.xi + sx;
+                            omax = sbb.xa + sx;
+                            break;
+                        case 2 :    // sum
+                            vmin = max(max(ssb.si-tsb.sa+ss, 2*(sbb.yi-tbb.ya+sy)+td), 2*(sbb.xi-tbb.xa+sx)-td);
+                            vmax = min(min(ssb.sa-tsb.si+ss, 2*(sbb.ya-tbb.yi+sy)+td), 2*(sbb.xa-tbb.xi+sx)-td);
+                            omin = ssb.di + sd;
+                            omax = ssb.da + sd;
+                            break;
+                        case 3 :    // diff
+                            vmin = max(max(ssb.di-tsb.da+sd, 2*(sbb.xi-tbb.xa+sx)-ts), -2*(sbb.ya-tbb.yi+sy)+ts);
+                            vmax = min(min(ssb.da-tsb.di+sd, 2*(sbb.xa-tbb.xi+sx)-ts), -2*(sbb.yi-tbb.ya+sy)+ts);
+                            omin = ssb.si + ss;
+                            omax = ssb.sa + ss;
+                            break;
+                    }
+                    if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
+                        continue;
 
 #if !defined GRAPHITE2_NTRACING
-                if (dbgout)
-                    dbgout->setenv(1, reinterpret_cast<void *>(j));
+                    if (dbgout)
+                        dbgout->setenv(1, reinterpret_cast<void *>(j));
 #endif
+                    if (omin > otmax)
+                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
+                                                sqr(_margin - omin + otmax) * _marginWt, false);
+                    else if (omax < otmin)
+                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
+                                                sqr(_margin - otmin + omax) * _marginWt, false);
+                    else
+                        _ranges[i].exclude_with_margins(vmin, vmax, i);
+                    anyhits = true;
+                }
+                if (anyhits)
+                    isCol = true;
+            }
+            else // no sub-boxes
+            {
+#if !defined GRAPHITE2_NTRACING
+                    if (dbgout)
+                        dbgout->setenv(1, reinterpret_cast<void *>(-1));
+#endif
+                isCol = true;
                 if (omin > otmax)
                     _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
                                             sqr(_margin - omin + otmax) * _marginWt, false);
                 else if (omax < otmin)
                     _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
                                             sqr(_margin - otmin + omax) * _marginWt, false);
                 else
                     _ranges[i].exclude_with_margins(vmin, vmax, i);
-                anyhits = true;
+
             }
-            if (anyhits)
-                isCol = true;
-        }
-        else // no sub-boxes
-        {
-#if !defined GRAPHITE2_NTRACING
-                if (dbgout)
-                    dbgout->setenv(1, reinterpret_cast<void *>(-1));
-#endif
-            isCol = true;
-            if (omin > otmax)
-                _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                        sqr(_margin - omin + otmax) * _marginWt, false);
-            else if (omax < otmin)
-                _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-                                        sqr(_margin - otmin + omax) * _marginWt, false);
-            else
-                _ranges[i].exclude_with_margins(vmin, vmax, i);
-
         }
     }
     bool res = true;
     if (cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
     {
         // Set up the bogus slot representing the exclusion glyph.
         Slot *exclSlot = seg->newSlot();
         exclSlot->setGlyph(seg, cslot->exclGlyph());
@@ -877,18 +883,18 @@ bool KernCollider::initSlot(Segment *seg
         SlotCollision *c = seg->collisionInfo(s);
         if (!gc.check(s->gid()))
             return false;
         const BBox &bs = gc.getBoundingBBox(s->gid());
         float x = s->origin().x + c->shift().x + ((dir & 1) ? bs.xi : bs.xa);
         // Loop over slices.
         // Note smin might not be zero if glyph s is not at the bottom of the cluster; similarly for smax.
         float toffset = c->shift().y - _miny + 1 + s->origin().y;
-        int smin = std::max(0, int((bs.yi + toffset) / _sliceWidth));
-        int smax = std::min(numSlices - 1, int((bs.ya + toffset) / _sliceWidth + 1));
+        int smin = max(0, int((bs.yi + toffset) / _sliceWidth));
+        int smax = min(numSlices - 1, int((bs.ya + toffset) / _sliceWidth + 1));
         for (int i = smin; i <= smax; ++i)
         {
             float t;
             float y = _miny - 1 + (i + .5f) * _sliceWidth; // vertical center of slice
             if ((dir & 1) && x < _edges[i])
             {
                 t = get_edge(seg, s, currShift, y, _sliceWidth, false);
                 if (t < _edges[i])
@@ -930,32 +936,32 @@ bool KernCollider::mergeSlot(Segment *se
     const Rect &bb = seg->theGlyphBBoxTemporary(slot->gid());
     const float sx = slot->origin().x + currShift.x;
     float x = sx + (rtl > 0 ? bb.tr.x : bb.bl.x);
     // this isn't going to reduce _mingap so skip
     if ((rtl > 0 && x < _xbound - _mingap - currSpace) || (rtl <= 0 && x > _xbound + _mingap + currSpace))
         return false;
 
     const float sy = slot->origin().y + currShift.y;
-    int smin = std::max(0, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1));
-    int smax = std::min((int)_edges.size() - 1, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1));
+    int smin = max(0, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1));
+    int smax = min((int)_edges.size() - 1, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1));
     bool collides = false;
 
     for (int i = smin; i <= smax; ++i)
     {
         float t;
         float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
         if (x * rtl > _edges[i] * rtl - _mingap - currSpace)
         {
             // 2 * currSpace to account for the space that is already separating them and the space we want to add
             float m = get_edge(seg, slot, currShift, y, _sliceWidth, rtl > 0) + 2 * rtl * currSpace;
             t = rtl * (_edges[i] - m);
             // Check slices above and below (if any).
-            if (i < (int)_edges.size() - 1) t = std::min(t, rtl * (_edges[i+1] - m));
-            if (i > 0) t = std::min(t, rtl * (_edges[i-1] - m));
+            if (i < (int)_edges.size() - 1) t = min(t, rtl * (_edges[i+1] - m));
+            if (i > 0) t = min(t, rtl * (_edges[i-1] - m));
             // _mingap is positive to shrink
             if (t < _mingap)
             {
                 _mingap = t;
                 collides = true;
             }
 #if !defined GRAPHITE2_NTRACING
             // Debugging - remember the closest neighboring edge for this slice.
--- a/gfx/graphite2/src/Decompressor.cpp
+++ b/gfx/graphite2/src/Decompressor.cpp
@@ -30,78 +30,84 @@ of the License or (at your option) any l
 #include "inc/Compression.h"
 
 using namespace lz4;
 
 namespace {
 
 inline
 u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
-    if (unlikely(l == 15) && likely(s != e))
+    if (l == 15 && s != e)
     {
         u8 b = 0;
         do { l += b = *s++; } while(b==0xff && s != e);
     }
     return l;
 }
 
 bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
 {
     u8 const token = *src++;
     
     literal_len = read_literal(src, end, token >> 4);
     literal = src;
     src += literal_len;
     
-    if (unlikely(src > end - 2))
+    if (src > end - 2)
         return false;
     
     match_dist  = *src++;
     match_dist |= *src++ << 8;
     match_len = read_literal(src, end, token & 0xf);
     
-    return true;
+    return src <= end-5;
 }
 
 }
 
 int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
 {
-    if (out_size <= in_size)
+    if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
         return -1;
-
+    
     u8 const *       src     = static_cast<u8 const *>(in),
              *       literal = 0,
              * const src_end = src + in_size;
 
     u8 *       dst     = static_cast<u8*>(out),
        * const dst_end = dst + out_size;
     
     u32 literal_len = 0,
         match_len = 0,
         match_dist = 0;
     
     while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
     {
-        // Copy in literal. At this point the last full sequence must be at
-        // least MINMATCH + 5 from the end of the output buffer.
-        if (unlikely(literal + align(literal_len) > src_end
-                  || dst + align(literal_len) > dst_end - MINMATCH+5))
-            return -1;
-        dst = overrun_copy(dst, literal, literal_len);
-
+        if (literal_len != 0)
+        {
+            // Copy in literal. At this point the last full sequence must be at
+            // least MINMATCH + 5 from the end of the output buffer.
+            if (dst + align(literal_len) > dst_end - MINMATCH+5)
+                return -1;
+            dst = overrun_copy(dst, literal, literal_len);
+        }
+        
         // Copy, possibly repeating, match from earlier in the
         //  decoded output.
         u8 const * const pcpy = dst - match_dist;
-        if (unlikely(pcpy < static_cast<u8*>(out)
-                  || dst + align(match_len + MINMATCH) > dst_end))
+        if (pcpy < static_cast<u8*>(out)
+                  || dst + match_len + MINMATCH > dst_end - 5)
             return -1;
-        dst = copy(dst, pcpy, match_len + MINMATCH);
+        if (dst > pcpy+sizeof(unsigned long) 
+            && dst + align(match_len + MINMATCH) <= dst_end)
+            dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
+        else 
+            dst = safe_copy(dst, pcpy, match_len + MINMATCH);
     }
     
-    if (unlikely(literal + literal_len > src_end
-              || dst + literal_len > dst_end)) 
+    if (literal + literal_len > src_end
+              || dst + literal_len > dst_end)
         return -1;
     dst = fast_copy(dst, literal, literal_len);
     
     return dst - (u8*)out;
 }
 
--- a/gfx/graphite2/src/Face.cpp
+++ b/gfx/graphite2/src/Face.cpp
@@ -307,17 +307,17 @@ Face::Table & Face::Table::operator = (c
     this->~Table();
     new (this) Table(rhs);
     return *this;
 }
 
 Error Face::Table::decompress()
 {
     Error e;
-    if (e.test(_sz < 2 * sizeof(uint32) + 3, E_BADSIZE))
+    if (e.test(_sz < 5 * sizeof(uint32), E_BADSIZE))
         return e;
     byte * uncompressed_table = 0;
     size_t uncompressed_size = 0;
 
     const byte * p = _p;
     const uint32 version = be::read<uint32>(p);    // Table version number.
 
     // The scheme is in the top 5 bits of the 1st uint32.
--- a/gfx/graphite2/src/Intervals.cpp
+++ b/gfx/graphite2/src/Intervals.cpp
@@ -80,18 +80,18 @@ bool separated(float a, float b) {
 
 }
 
 void Zones::insert(Exclusion e)
 {
 #if !defined GRAPHITE2_NTRACING
     addDebug(&e);
 #endif
-    e.x = std::max(e.x, _pos);
-    e.xm = std::min(e.xm, _posm);
+    e.x = max(e.x, _pos);
+    e.xm = min(e.xm, _posm);
     if (e.x >= e.xm) return;
 
     for (iterator i = _exclusions.begin(), ie = _exclusions.end(); i != ie && e.x < e.xm; ++i)
     {
         const uint8 oca = e.outcode(i->x),
                     ocb = e.outcode(i->xm);
         if ((oca & ocb) != 0) continue;
 
@@ -136,18 +136,18 @@ void Zones::insert(Exclusion e)
 }
 
 
 void Zones::remove(float x, float xm)
 {
 #if !defined GRAPHITE2_NTRACING
     removeDebug(x, xm);
 #endif
-    x = std::max(x, _pos);
-    xm = std::min(xm, _posm);
+    x = max(x, _pos);
+    xm = min(xm, _posm);
     if (x >= xm) return;
 
     for (iterator i = _exclusions.begin(), ie = _exclusions.end(); i != ie; ++i)
     {
         const uint8 oca = i->outcode(x),
                     ocb = i->outcode(xm);
         if ((oca & ocb) != 0)   continue;
 
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -125,17 +125,18 @@ bool Pass::readPass(const byte * const p
     // Perform some sanity checks.
     if ( e.test(m_numTransition > m_numStates, E_BADNUMTRANS)
             || e.test(m_numSuccess > m_numStates, E_BADNUMSUCCESS)
             || e.test(m_numSuccess + m_numTransition < m_numStates, E_BADNUMSTATES)
             || e.test(m_numRules && numRanges == 0, E_NORANGES))
         return face.error(e);
 
     m_successStart = m_numStates - m_numSuccess;
-    if (e.test(p + numRanges * 6 - 4 > pass_end, E_BADPASSLENGTH)) return face.error(e);
+    // test for beyond end - 1 to account for reading uint16
+    if (e.test(p + numRanges * 6 - 2 > pass_end, E_BADPASSLENGTH)) return face.error(e);
     m_numGlyphs = be::peek<uint16>(p + numRanges * 6 - 4) + 1;
     // Calculate the start of various arrays.
     const byte * const ranges = p;
     be::skip<uint16>(p, numRanges*3);
     const byte * const o_rule_map = p;
     be::skip<uint16>(p, m_numSuccess + 1);
 
     // More sanity checks
@@ -258,17 +259,21 @@ bool Pass::readRules(const byte * rule_m
         if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
                 || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
                 || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE)
                 || e.test(!r->constraint->immutable(), E_MUTABLECCODE))
             return face.error(e);
     }
 
     byte * moved_progs = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs));
-    if (e.test(!moved_progs, E_OUTOFMEM))   return face.error(e);
+    if (e.test(!moved_progs, E_OUTOFMEM))
+    {
+        if (prog_pool_free - m_progs == 0) m_progs = 0;
+        return face.error(e);
+    }
 
     if (moved_progs != m_progs)
     {
         for (Code * c = m_codes, * const ce = c + m_numRules*2; c != ce; ++c)
         {
             c->externalProgramMoved(moved_progs - m_progs);
         }
         m_progs = moved_progs;
@@ -378,17 +383,21 @@ bool Pass::readRanges(const byte * range
     return true;
 }
 
 
 bool Pass::runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const
 {
     Slot *s = m.slotMap().segment.first();
     if (!s || !testPassConstraint(m)) return true;
-    if (reverse) m.slotMap().segment.reverseSlots();
+    if (reverse)
+    {
+        m.slotMap().segment.reverseSlots();
+        s = m.slotMap().segment.first();
+    }
     if (m_numRules)
     {
         Slot *currHigh = s->next();
 
 #if !defined GRAPHITE2_NTRACING
         if (fsm.dbgout)  *fsm.dbgout << "rules" << json::array;
         json::closer rules_array_closer(fsm.dbgout);
 #endif
--- a/gfx/graphite2/src/Segment.cpp
+++ b/gfx/graphite2/src/Segment.cpp
@@ -31,17 +31,16 @@ of the License or (at your option) any l
 #include "inc/bits.h"
 #include "inc/Segment.h"
 #include "graphite2/Font.h"
 #include "inc/CharInfo.h"
 #include "inc/debug.h"
 #include "inc/Slot.h"
 #include "inc/Main.h"
 #include "inc/CmapCache.h"
-//#include "inc/Bidi.h"
 #include "inc/Collider.h"
 #include "graphite2/Segment.h"
 
 
 using namespace graphite2;
 
 Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir)
 : m_freeSlots(NULL),
@@ -151,22 +150,16 @@ void Segment::appendSlot(int id, int cid
     const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
     m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0);
     
     aSlot->child(NULL);
     aSlot->setGlyph(this, gid, theGlyph);
     aSlot->originate(id);
     aSlot->before(id);
     aSlot->after(id);
-//    uint8 aBidi = m_silf->aBidi();
-//    if (aBidi != 0xFF)
-//    {
-//        unsigned int bAttr = glyphAttr(gid, aBidi);
-//        aSlot->setBidiClass((bAttr <= 22) * bAttr);
-//    }
     if (m_last) m_last->next(aSlot);
     aSlot->prev(m_last);
     m_last = aSlot;
     if (!m_first) m_first = aSlot;
     if (theGlyph && m_silf->aPassBits())
         m_passBits &= theGlyph->attrs()[m_silf->aPassBits()] 
                     | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
 }
@@ -404,16 +397,24 @@ void Segment::linkClusters(Slot *s, Slot
 }
 
 Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
 {
     Position currpos(0., 0.);
     float clusterMin = 0.;
     Rect bbox;
 
+    if (currdir() != isRtl)
+    {
+        Slot *temp;
+        reverseSlots();
+        temp = iStart;
+        iStart = iEnd;
+        iEnd = temp;
+    }
     if (!iStart)    iStart = m_first;
     if (!iEnd)      iEnd   = m_last;
 
     if (isRtl)
     {
         for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
         {
             if (s->isBase())
@@ -497,68 +498,16 @@ bool Segment::read_text(const Face *face
     {
     case gr_utf8:   process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
     case gr_utf16:  process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
     case gr_utf32:  process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
     }
     return true;
 }
 
-#if 0
-Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &stack);
-void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
-void resolveWhitespace(int baseLevel, Slot *s);
-Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
-
-void Segment::bidiPass(int paradir, uint8 aMirror)
-{
-    if (slotCount() == 0)
-        return;
-
-    Slot *s;
-    int baseLevel = paradir ? 1 : 0;
-    unsigned int bmask = 0;
-    unsigned int ssize = 0;
-    for (s = first(); s; s = s->next())
-    {
-        if (getSlotBidiClass(s) < 0)
-            s->setBidiClass(0);
-        bmask |= (1 << s->getBidiClass());
-        s->setBidiLevel(baseLevel);
-        if (s->getBidiClass() == 21)
-            ++ssize;
-    }
-
-    BracketPairStack bstack(ssize);
-    if (bmask & (paradir ? 0x2E7892 : 0x2E789C))
-    {
-        // O(8N) algorithm, with no working data beyond what is needed for processParens
-        int nextLevel = paradir;
-        int e, i, c;
-        process_bidi(first(), baseLevel, paradir, nextLevel, 0, 0, c = 0, i = 0, e = 0, 1, this, aMirror, bstack);
-        resolveImplicit(first(), this, aMirror);
-        resolveWhitespace(baseLevel, last());
-        s = resolveOrder(s = first(), baseLevel != 0);
-        if (s)
-        {
-            first(s); last(s->prev());
-            s->prev()->next(0); s->prev(0);
-        }
-    }
-    else if (!(dir() & 4) && baseLevel && aMirror)
-    {
-        for (s = first(); s; s = s->next())
-        {
-            unsigned short g = glyphAttr(s->gid(), aMirror);
-            if (g) s->setGlyph(this, g);
-        }
-    }
-}
-#endif
-
 void Segment::doMirror(uint16 aMirror)
 {
     Slot * s;
     for (s = m_first; s; s = s->next())
     {
         unsigned short g = glyphAttr(s->gid(), aMirror);
         if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1)))
             s->setGlyph(this, g);
--- a/gfx/graphite2/src/TtfUtil.cpp
+++ b/gfx/graphite2/src/TtfUtil.cpp
@@ -847,31 +847,33 @@ const void * FindCmapSubtable(const void
     {
         if (be::swap(pTable->encoding[i].platform_id) == nPlatformId &&
                 (nEncodingId == -1 || be::swap(pTable->encoding[i].platform_specific_id) == nEncodingId))
         {
             uint32 offset = be::swap(pTable->encoding[i].offset);
             const uint8 * pRtn = reinterpret_cast<const uint8 *>(pCmap) + offset;
             if (length)
             {
-                if (offset > length) return NULL;
+                if (offset + 2 > length) return NULL;
                 uint16 format = be::read<uint16>(pRtn);
                 if (format == 4)
                 {
+                    if (offset + 4 > length) return NULL;
                     uint16 subTableLength = be::peek<uint16>(pRtn);
                     if (i + 1 == csuPlatforms)
                     {
                         if (subTableLength > length - offset)
                             return NULL;
                     }
                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
                         return NULL;
                 }
                 if (format == 12)
                 {
+                    if (offset + 6 > length) return NULL;
                     uint32 subTableLength = be::peek<uint32>(pRtn);
                     if (i + 1 == csuPlatforms)
                     {
                         if (subTableLength > length - offset)
                             return NULL;
                     }
                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
                         return NULL;
--- a/gfx/graphite2/src/inc/Collider.h
+++ b/gfx/graphite2/src/inc/Collider.h
@@ -21,23 +21,20 @@
 
 Alternatively, the contents of this file may be used under the terms of the
 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
 License, as published by the Free Software Foundation, either version 2
 of the License or (at your option) any later version.
 */
 #pragma once
 
-#include <utility>
 #include "inc/List.h"
-//#include "inc/Slot.h"
 #include "inc/Position.h"
 #include "inc/Intervals.h"
 #include "inc/debug.h"
-//#include "inc/Segment.h"
 
 namespace graphite2 {
 
 class json;
 class Slot;
 class Segment;
 
 #define SLOTCOLSETUINTPROP(x, y) uint16 x() const { return _ ##x; } void y (uint16 v) { _ ##x = v; }
--- a/gfx/graphite2/src/inc/Compression.h
+++ b/gfx/graphite2/src/inc/Compression.h
@@ -26,28 +26,16 @@ of the License or (at your option) any l
 */
 
 #pragma once
 
 #include <cassert>
 #include <cstddef>
 #include <cstring>
 
-#include <iterator>
-
-#if ((defined GCC_VERSION && GCC_VERSION >= 302) || (defined __INTEL_COMPILER && __INTEL_COMPILER >= 800) || defined(__clang__))
-    #define expect(expr,value)    (__builtin_expect ((expr),(value)) )
-#else
-    #define expect(expr,value)    (expr)
-#endif
-
-#define likely(expr)     expect((expr) != 0, 1)
-#define unlikely(expr)   expect((expr) != 0, 0)
-
-
 namespace
 {
 
 #if defined(_MSC_VER)
 typedef unsigned __int8 u8;
 typedef unsigned __int16 u16;
 typedef unsigned __int32 u32;
 typedef unsigned __int64 u64;
@@ -67,16 +55,22 @@ void unaligned_copy(void * d, void const
   ::memcpy(d, s, S);
 }
 
 inline
 size_t align(size_t p) {
     return (p + sizeof(unsigned long)-1) & ~(sizeof(unsigned long)-1);
 }
 
+inline 
+u8 * safe_copy(u8 * d, u8 const * s, size_t n) {
+    while (n--) *d++ = *s++;
+    return d;
+}
+
 inline
 u8 * overrun_copy(u8 * d, u8 const * s, size_t n) {
     size_t const WS = sizeof(unsigned long);
     u8 const * e = s + n;
     do 
     {
         unaligned_copy<WS>(d, s);
         d += WS;
@@ -95,26 +89,15 @@ u8 * fast_copy(u8 * d, u8 const * s, siz
     size_t wn = n/WS;
     while (wn--) 
     {
         unaligned_copy<WS>(d, s);
         d += WS;
         s += WS;
     }
     n &= WS-1;
-    while (n--) {*d++ = *s++; }
-    
-    return d;
+    return safe_copy(d, s, n);
 }
 
 
-inline 
-u8 * copy(u8 * d, u8 const * s, size_t n) {
-    if (likely(d>s+sizeof(unsigned long)))
-        return overrun_copy(d,s,n);
-    else 
-        while (n--) *d++ = *s++;
-    return d;
-}
-
 } // end of anonymous namespace
 
 
--- a/gfx/graphite2/src/inc/Decompressor.h
+++ b/gfx/graphite2/src/inc/Decompressor.h
@@ -27,14 +27,30 @@ of the License or (at your option) any l
 
 #pragma once
 
 #include <cstddef>
 
 namespace lz4
 {
 
-// return value is either decompressed size of -1
+// decompress an LZ4 block
+// Parameters:
+//      @in         -   Input buffer containing an LZ4 block.
+//      @in_size    -   Size of the input LZ4 block in bytes.
+//      @out        -   Output buffer to hold decompressed results.
+//      @out_size   -   The size of the buffer pointed to by @out.
+// Invariants:
+//      @in         -   This buffer must be at least 1 machine word in length,
+//                      regardless of the actual LZ4 block size.
+//      @in_size    -   This must be at least 4 and must also be <= to the
+//                      allocated buffer @in.
+//      @out        -   This must be bigger than the input buffer and at least
+//                      13 bytes.
+//      @out_size   -   Must always be big enough to hold the expected size.
+// Return:
+//      -1          -  Decompression failed.
+//      size        -  Actual number of bytes decompressed.
 int decompress(void const *in, size_t in_size, void *out, size_t out_size);
 
 } // end of namespace shrinker
 
 
--- a/gfx/graphite2/src/inc/Segment.h
+++ b/gfx/graphite2/src/inc/Segment.h
@@ -30,21 +30,19 @@ of the License or (at your option) any l
 
 #include <cassert>
 
 #include "inc/CharInfo.h"
 #include "inc/Face.h"
 #include "inc/FeatureVal.h"
 #include "inc/GlyphCache.h"
 #include "inc/GlyphFace.h"
-//#include "inc/Silf.h"
 #include "inc/Slot.h"
 #include "inc/Position.h"
 #include "inc/List.h"
-//#include "inc/Bidi.h"
 #include "inc/Collider.h"
 
 #define MAX_SEG_GROWTH_FACTOR  256
 
 namespace graphite2 {
 
 typedef Vector<Features>        FeatureList;
 typedef Vector<Slot *>          SlotRope;
@@ -239,68 +237,12 @@ bool Segment::isWhitespace(const int cid
          + (cid >= 0x2000) * (cid <= 0x200A)
          + (cid == 0x2028)
          + (cid == 0x2029)
          + (cid == 0x202F)
          + (cid == 0x205F)
          + (cid == 0x3000)) != 0;
 }
 
-//inline
-//bool Segment::isWhitespace(const int cid) const
-//{
-//    switch (cid >> 8)
-//    {
-//        case 0x00:
-//            switch (cid)
-//            {
-//            case 0x09:
-//            case 0x0A:
-//            case 0x0B:
-//            case 0x0C:
-//            case 0x0D:
-//            case 0x20:
-//                return true;
-//            default:
-//                break;
-//            }
-//            break;
-//        case 0x16:
-//            return cid == 0x1680;
-//            break;
-//        case 0x18:
-//            return cid == 0x180E;
-//            break;
-//        case 0x20:
-//            switch (cid)
-//            {
-//            case 0x00:
-//            case 0x01:
-//            case 0x02:
-//            case 0x03:
-//            case 0x04:
-//            case 0x05:
-//            case 0x06:
-//            case 0x07:
-//            case 0x08:
-//            case 0x09:
-//            case 0x0A:
-//            case 0x28:
-//            case 0x29:
-//            case 0x2F:
-//            case 0x5F:
-//                return true
-//            default:
-//                break;
-//            }
-//            break;
-//        case 0x30:
-//            return cid == 0x3000;
-//            break;
-//    }
-//
-//    return false;
-//}
-
 } // namespace graphite2
 
 struct gr_segment : public graphite2::Segment {};
 
--- a/gfx/graphite2/src/inc/opcodes.h
+++ b/gfx/graphite2/src/inc/opcodes.h
@@ -638,17 +638,17 @@ STARTOP(push_att_to_glyph_attr)
         slotref att = slot->attachedTo();
         if (att) slot = att;
         push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
     }
 ENDOP
 
 STARTOP(temp_copy)
     slotref newSlot = seg.newSlot();
-    if (!newSlot) DIE;
+    if (!newSlot || !is) DIE;
     int16 *tempUserAttrs = newSlot->userAttrs();
     memcpy(newSlot, is, sizeof(Slot));
     memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
     newSlot->userAttrs(tempUserAttrs);
     newSlot->markCopied(true);
     *map = newSlot;
 ENDOP