diff --git a/gfx/graphite2/src/Rule.cpp b/gfx/graphite2/COPYING similarity index 70% rename from gfx/graphite2/src/Rule.cpp rename to gfx/graphite2/COPYING index 34c8ae169..d40f2d845 100644 --- a/gfx/graphite2/src/Rule.cpp +++ b/gfx/graphite2/COPYING @@ -1,6 +1,6 @@ /* GRAPHITE2 LICENSING - Copyright 2011, SIL International + Copyright 2010, SIL International All rights reserved. This library is free software; you can redistribute it and/or modify @@ -19,13 +19,8 @@ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the internet at http://www.fsf.org/licenses/lgpl.html. -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. + Alternatively, you may use this library under the terms of the Mozilla + Public License (http://mozilla.org/MPL) or under the GNU General Public + License, as published by the Free Sofware Foundation; either version + 2 of the license or (at your option) any later version. */ - -#include "inc/Rule.h" -#include "inc/Segment.h" - -using namespace graphite2; diff --git a/gfx/graphite2/ChangeLog b/gfx/graphite2/ChangeLog old mode 100644 new mode 100755 index 2d5a0c113..b46562047 --- a/gfx/graphite2/ChangeLog +++ b/gfx/graphite2/ChangeLog @@ -1,3 +1,30 @@ +1.3.9 + . Add Collision COLL_ISSPACE to allow for visible spaces in collision avoidance + . Add segment and pass direction information to tracing output + . Bug fix rule length testing in 32-bit + . Increase slanted margin distances for collision avoidance + . Change kerning algorithm to simple outline expansion. Seems to make no visible difference. + . Add trace2svg to test tools + +1.3.8 + . Various bug fixes arising from fuzzing + . Fix regression that stopped piglatin from working + . Make collision avoidance kerning give more regular results + . Minor modification to clustering algorithm to handle variable width chars + +1.3.7 + . Bug fixes + . Start to deprecate SegCache. This will be going away in a later release. + +1.3.6 + . Bug fixes + +1.3.5 + . Bug fixes + . Security bug fix + . Fix ARM misalignment problem + . Track latest cmake + 1.3.4 . Transition from Mercurial to Git . Bug fixes diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla index 5dec0063e..d7f2ac906 100644 --- a/gfx/graphite2/README.mozilla +++ b/gfx/graphite2/README.mozilla @@ -1,6 +1,3 @@ -This directory contains the Graphite2 library release 1.3.8 from -https://github.com/silnrsi/graphite/releases/download/1.3.8/graphite2-minimal-1.3.8.tgz -See gfx/graphite2/moz-gr-update.sh for update procedure. - -Cherry-picked post-1.3.9 commit 1ce331d5548b98ed8b818532b2556d6f2c7a3b83 to fix -https://bugzilla.mozilla.org/show_bug.cgi?id=1345461. +This directory contains the Graphite2 library release 1.3.10 from +https://github.com/silnrsi/graphite/releases/download/1.3.10/graphite2-minimal-1.3.10.tgz +See ./gfx/graphite2/moz-gr-update.sh for update procedure. diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h index 1f2ca4eaf..729ebff88 100644 --- a/gfx/graphite2/include/graphite2/Font.h +++ b/gfx/graphite2/include/graphite2/Font.h @@ -30,7 +30,7 @@ #define GR2_VERSION_MAJOR 1 #define GR2_VERSION_MINOR 3 -#define GR2_VERSION_BUGFIX 8 +#define GR2_VERSION_BUGFIX 10 #ifdef __cplusplus extern "C" diff --git a/gfx/graphite2/include/graphite2/XmlLog.h b/gfx/graphite2/include/graphite2/XmlLog.h deleted file mode 100644 index 554132756..000000000 --- a/gfx/graphite2/include/graphite2/XmlLog.h +++ /dev/null @@ -1,55 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2010, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - - 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 -#include - -typedef enum { - GRLOG_NONE = 0x0, - GRLOG_FACE = 0x01, - GRLOG_SEGMENT = 0x02, - GRLOG_PASS = 0x04, - GRLOG_CACHE = 0x08, - - GRLOG_OPCODE = 0x80, - GRLOG_ALL = 0xFF -} GrLogMask; - -// If startGraphiteLogging returns true, logging is enabled and the FILE handle -// will be closed by graphite when stopGraphiteLogging is called. -#ifdef __cplusplus -extern "C" -{ -#endif - -GR2_API bool graphite_start_logging(FILE * logFile, GrLogMask mask); //may not do anthing if disabled in the implementation of the engine. -GR2_API void graphite_stop_logging(); - -#ifdef __cplusplus -} -#endif diff --git a/gfx/graphite2/src/Bidi.cpp b/gfx/graphite2/src/Bidi.cpp deleted file mode 100644 index 48ec2ebfc..000000000 --- a/gfx/graphite2/src/Bidi.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2011, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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. -*/ -#include "inc/Main.h" -#include "inc/Slot.h" -#include "inc/Segment.h" -#include "inc/Bidi.h" - -using namespace graphite2; - -enum DirCode { // Hungarian: dirc - Unk = -1, - N = 0, // other neutrals (default) - ON - L = 1, // left-to-right, strong - L - R = 2, // right-to-left, strong - R - AL = 3, // Arabic letter, right-to-left, strong, AR - EN = 4, // European number, left-to-right, weak - EN - EUS = 5, // European separator, left-to-right, weak - ES - ET = 6, // European number terminator, left-to-right, weak - ET - AN = 7, // Arabic number, left-to-right, weak - AN - CUS = 8, // Common number separator, left-to-right, weak - CS - WS = 9, // white space, neutral - WS - BN = 10, // boundary neutral - BN - - LRO = 11, // LTR override - RLO = 12, // RTL override - LRE = 13, // LTR embedding - RLE = 14, // RTL embedding - PDF = 15, // pop directional format - NSM = 16, // non-space mark - LRI = 17, // LRI isolate - RLI = 18, // RLI isolate - FSI = 19, // FSI isolate - PDI = 20, // pop isolate - OPP = 21, // opening paired parenthesis - CPP = 22, // closing paired parenthesis - - ON = N -}; - -enum DirMask { - WSflag = int8(1 << 7), // keep track of WS for eos handling - WSMask = int8(~(1 << 7)) -}; - -inline uint8 BaseClass(Slot *s) { return s->getBidiClass() & WSMask; } - -unsigned int bidi_class_map[] = { 0, 1, 2, 5, 4, 8, 9, 3, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0 }; -// Algorithms based on Unicode reference standard code. Thanks Asmus Freitag. - -void resolveWeak(Slot *start, int sos, int eos); -void resolveNeutrals(Slot *s, int baseLevel, int sos, int eos); -void processParens(Slot *s, Segment *seg, uint8 aMirror, int level, BracketPairStack &stack); - -inline int calc_base_level(Slot *s) -{ - int count = 0; - for ( ; s; s = s->next()) - { - int cls = s->getBidiClass(); - if (count) - { - switch(cls) - { - case LRI : - case RLI : - case FSI : - ++count; - break; - case PDI : - --count; - } - } - else - { - switch(cls) - { - case L : - return 0; - case R : - case AL : - return 1; - case LRI : - case RLI : - case FSI : - ++count; - } - } - } - return 0; -} - -// inline or not? -void do_resolves(Slot *start, int level, int sos, int eos, int &bmask, Segment *seg, uint8 aMirror, BracketPairStack &stack) -{ - if (bmask & 0x1F1178) - resolveWeak(start, sos, eos); - if (bmask & 0x200000) - processParens(start, seg, aMirror, level, stack); - if (bmask & 0x7E0361) - resolveNeutrals(start, level, sos, eos); - bmask = 0; -} - -enum maxs -{ - MAX_LEVEL = 125, -}; - -// returns where we are up to in processing -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 &bstack) -{ - int bmask = 0; - Slot *s = start; - Slot *slast = start; - Slot *scurr = 0; - Slot *stemp; - int lnextLevel = nextLevel; - int newLevel; - int empty = 1; - for ( ; s; s = s ? s->next() : s) - { - int cls = s->getBidiClass(); - bmask |= (1 << cls); - s->setBidiLevel(level); - // we keep s->prev() pointing backwards for PDI repeating - - switch (cls) - { - case BN : - if (slast == s) slast = s->next(); // ignore if at front of text - continue; - case LRE : - case LRO : - case RLE : - case RLO : - switch (cls) - { - case LRE : - case LRO : - newLevel = level + (level & 1 ? 1 : 2); - break; - case RLE : - case RLO : - newLevel = level + (level & 1 ? 2 : 1); - break; - } - s->setBidiClass(BN); - if (isolerr || newLevel > MAX_LEVEL || embederr) - { - if (!isolerr) ++embederr; - break; - } - stemp = scurr; - if (scurr) - scurr->prev(0); // don't include control in string - lnextLevel = newLevel; - scurr = s; - s->setBidiLevel(newLevel); // to make it vanish - // recurse for the new subsequence. A sequence only contains text at the same level - s = process_bidi(s->next(), newLevel, level, lnextLevel, cls < LRE, 0, cisol, isolerr, embederr, 0, seg, aMirror, bstack); - // s points at PDF or end of sequence - // try to keep extending the run and not process it until we have to - if (lnextLevel != level || !s) // if the subsequence really had something in it, or we are at the end of the run - { - if (slast != scurr) // process the run now, don't try to extend it - { - // process text preceeding embedding - do_resolves(slast, level, (prelevel > level ? prelevel : level) & 1, lnextLevel & 1, bmask, seg, aMirror, bstack); - empty = 0; - nextLevel = level; - } - else if (lnextLevel != level) // the subsequence had something - { - empty = 0; // so we aren't empty either - nextLevel = lnextLevel; // but since we really are empty, pass back our level from the subsequence - } - if (s) // if still more to process - { - prelevel = lnextLevel; // future text starts out with sos of the higher subsequence - lnextLevel = level; // and eos is our level - } - slast = s ? s->next() : s; - } - else if (stemp) - stemp->prev(s); - break; - - case PDF : - s->setBidiClass(BN); - s->prev(0); // unstitch us since we skip final stitching code when we return - if (isol || isolerr || init) // boundary error conditions - break; - if (embederr) - { - --embederr; - break; - } - if (slast != s) - { - scurr->prev(0); // if slast, then scurr. Terminate before here - do_resolves(slast, level, level & 1, level & 1, bmask, seg, aMirror, bstack); - empty = 0; - } - if (empty) - { - nextLevel = prelevel; // no contents? set our level to that of parent - s->setBidiLevel(prelevel); - } - return s; - - case FSI : - case LRI : - case RLI : - switch (cls) - { - case FSI : - if (calc_base_level(s->next())) - newLevel = level + (level & 1 ? 2 : 1); - else - newLevel = level + (level & 1 ? 1 : 2); - break; - case LRI : - newLevel = level + (level & 1 ? 1 : 2); - break; - case RLI : - newLevel = level + (level & 1 ? 2 : 1); - break; - } - if (newLevel > MAX_LEVEL || isolerr) - { - ++isolerr; - s->setBidiClass(ON | WSflag); - break; - } - ++cisol; - if (scurr) scurr->prev(s); - scurr = s; // include FSI - lnextLevel = newLevel; - // recurse for the new sub sequence - s = process_bidi(s->next(), newLevel, newLevel, lnextLevel, 0, 1, cisol, isolerr, embederr, 0, seg, aMirror, bstack); - // s points at PDI - if (s) - { - bmask |= 1 << BaseClass(s); // include the PDI in the mask - s->setBidiLevel(level); // reset its level to our level - } - lnextLevel = level; - break; - - case PDI : - if (isolerr) - { - --isolerr; - s->setBidiClass(ON | WSflag); - break; - } - if (init || !cisol) - { - s->setBidiClass(ON | WSflag); - break; - } - embederr = 0; - if (!isol) // we are in an embedded subsequence, we have to return through all those - { - if (empty) // if empty, reset the level to tell embedded parent - nextLevel = prelevel; - return s->prev(); // keep working up the stack pointing at this PDI until we get to an isolate entry - } - else // we are terminating an isolate sequence - { - if (slast != s) // process any remaining content in this subseqence - { - scurr->prev(0); - do_resolves(slast, level, prelevel & 1, level & 1, bmask, seg, aMirror, bstack); - } - --cisol; // pop the isol sequence from the stack - return s; - } - - default : - if (dirover) - s->setBidiClass((level & 1 ? R : L) | (WSflag * (cls == WS))); - } - if (s) s->prev(0); // unstitch us - if (scurr) // stitch in text for processing - scurr->prev(s); - scurr = s; // add us to text to process - } - if (slast != s) - { - do_resolves(slast, level, (level > prelevel ? level : prelevel) & 1, lnextLevel & 1, bmask, seg, aMirror, bstack); - empty = 0; - } - if (empty || isol) - nextLevel = prelevel; - return s; -} - -// === RESOLVE WEAK TYPES ================================================ - -enum bidi_state // possible states -{ - xa, // arabic letter - xr, // right leter - xl, // left letter - - ao, // arabic lett. foll by ON - ro, // right lett. foll by ON - lo, // left lett. foll by ON - - rt, // ET following R - lt, // ET following L - - cn, // EN, AN following AL - ra, // arabic number foll R - re, // european number foll R - la, // arabic number foll L - le, // european number foll L - - ac, // CS following cn - rc, // CS following ra - rs, // CS,ES following re - lc, // CS following la - ls, // CS,ES following le - - ret, // ET following re - let, // ET following le -} ; - -const bidi_state stateWeak[][10] = -{ - // N, L, R, AN, EN, AL,NSM, CS, ES, ET, -{ /*xa*/ ao, xl, xr, cn, cn, xa, xa, ao, ao, ao, /* arabic letter */ }, -{ /*xr*/ ro, xl, xr, ra, re, xa, xr, ro, ro, rt, /* right letter */ }, -{ /*xl*/ lo, xl, xr, la, le, xa, xl, lo, lo, lt, /* left letter */ }, - -{ /*ao*/ ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* arabic lett. foll by ON*/ }, -{ /*ro*/ ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* right lett. foll by ON */ }, -{ /*lo*/ lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* left lett. foll by ON */ }, - -{ /*rt*/ ro, xl, xr, ra, re, xa, rt, ro, ro, rt, /* ET following R */ }, -{ /*lt*/ lo, xl, xr, la, le, xa, lt, lo, lo, lt, /* ET following L */ }, - -{ /*cn*/ ao, xl, xr, cn, cn, xa, cn, ac, ao, ao, /* EN, AN following AL */ }, -{ /*ra*/ ro, xl, xr, ra, re, xa, ra, rc, ro, rt, /* arabic number foll R */ }, -{ /*re*/ ro, xl, xr, ra, re, xa, re, rs, rs,ret, /* european number foll R */ }, -{ /*la*/ lo, xl, xr, la, le, xa, la, lc, lo, lt, /* arabic number foll L */ }, -{ /*le*/ lo, xl, xr, la, le, xa, le, ls, ls,let, /* european number foll L */ }, - -{ /*ac*/ ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* CS following cn */ }, -{ /*rc*/ ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS following ra */ }, -{ /*rs*/ ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS,ES following re */ }, -{ /*lc*/ lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS following la */ }, -{ /*ls*/ lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS,ES following le */ }, - -{ /*ret*/ ro, xl, xr, ra, re, xa,ret, ro, ro,ret, /* ET following re */ }, -{ /*let*/ lo, xl, xr, la, le, xa,let, lo, lo,let, /* ET following le */ }, - - -}; - -enum bidi_action // possible actions -{ - // primitives - IX = 0x100, // increment - XX = 0xF, // no-op - - // actions - xxx = (XX << 4) + XX, // no-op - xIx = IX + xxx, // increment run - xxN = (XX << 4) + ON, // set current to N - xxE = (XX << 4) + EN, // set current to EN - xxA = (XX << 4) + AN, // set current to AN - xxR = (XX << 4) + R, // set current to R - xxL = (XX << 4) + L, // set current to L - Nxx = (ON << 4) + 0xF, // set run to neutral - Axx = (AN << 4) + 0xF, // set run to AN - ExE = (EN << 4) + EN, // set run to EN, set current to EN - NIx = (ON << 4) + 0xF + IX, // set run to N, increment - NxN = (ON << 4) + ON, // set run to N, set current to N - NxR = (ON << 4) + R, // set run to N, set current to R - NxE = (ON << 4) + EN, // set run to N, set current to EN - - AxA = (AN << 4) + AN, // set run to AN, set current to AN - NxL = (ON << 4) + L, // set run to N, set current to L - LxL = (L << 4) + L, // set run to L, set current to L -}; - - -const bidi_action actionWeak[][10] = -{ - // N,.. L, R, AN, EN, AL, NSM, CS,..ES, ET, -{ /*xa*/ xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN, /* arabic letter */ }, -{ /*xr*/ xxx, xxx, xxx, xxx, xxE, xxR, xxR, xxN, xxN, xIx, /* right leter */ }, -{ /*xl*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xIx, /* left letter */ }, - -{ /*ao*/ xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN, /* arabic lett. foll by ON */ }, -{ /*ro*/ xxx, xxx, xxx, xxx, xxE, xxR, xxN, xxN, xxN, xIx, /* right lett. foll by ON */ }, -{ /*lo*/ xxx, xxx, xxx, xxx, xxL, xxR, xxN, xxN, xxN, xIx, /* left lett. foll by ON */ }, - -{ /*rt*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, xIx, NxN, NxN, xIx, /* ET following R */ }, -{ /*lt*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, xIx, NxN, NxN, xIx, /* ET following L */ }, - -{ /*cn*/ xxx, xxx, xxx, xxx, xxA, xxR, xxA, xIx, xxN, xxN, /* EN, AN following AL */ }, -{ /*ra*/ xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx, /* arabic number foll R */ }, -{ /*re*/ xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE, /* european number foll R */ }, -{ /*la*/ xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx, /* arabic number foll L */ }, -{ /*le*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL, /* european number foll L */ }, - -{ /*ac*/ Nxx, Nxx, Nxx, Axx, AxA, NxR, NxN, NxN, NxN, NxN, /* CS following cn */ }, -{ /*rc*/ Nxx, Nxx, Nxx, Axx, NxE, NxR, NxN, NxN, NxN, NIx, /* CS following ra */ }, -{ /*rs*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, NxN, NxN, NxN, NIx, /* CS,ES following re */ }, -{ /*lc*/ Nxx, Nxx, Nxx, Axx, NxL, NxR, NxN, NxN, NxN, NIx, /* CS following la */ }, -{ /*ls*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, NxN, NxN, NxN, NIx, /* CS,ES following le */ }, - -{ /*ret*/xxx, xxx, xxx, xxx, xxE, xxR, xxE, xxN, xxN, xxE, /* ET following re */ }, -{ /*let*/xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xxL, /* ET following le */ }, -}; - -inline uint8 GetDeferredType(bidi_action a) { return (a >> 4) & 0xF; } -inline uint8 GetResolvedType(bidi_action a) { return a & 0xF; } -inline DirCode EmbeddingDirection(int l) { return l & 1 ? R : L; } - -// Neutrals -enum neutral_action -{ - // action to resolve previous input - nL = L, // resolve EN to L - En = 3 << 4, // resolve neutrals run to embedding level direction - Rn = R << 4, // resolve neutrals run to strong right - Ln = L << 4, // resolved neutrals run to strong left - In = (1<<8), // increment count of deferred neutrals - LnL = (1<<4)+L, // set run and EN to L -}; - -// ->prev() here means ->next() -void SetDeferredRunClass(Slot *s, Slot *sRun, int nval) -{ - if (!sRun || s == sRun) return; - for (Slot *p = sRun; p != s; p = p->prev()) - if (p->getBidiClass() == WS) p->setBidiClass(nval | WSflag); - else if (BaseClass(p) != BN) p->setBidiClass(nval | (p->getBidiClass() & WSflag)); -} - -void SetThisDeferredRunClass(Slot *s, Slot *sRun, int nval) -{ - if (!sRun) return; - for (Slot *p = sRun, *e = s->prev(); p != e; p = p->prev()) - if (p->getBidiClass() == WS) p->setBidiClass(nval | WSflag); - else if (BaseClass(p) != BN) p->setBidiClass(nval | (p->getBidiClass() & WSflag)); -} - -void resolveWeak(Slot *start, int sos, int eos) -{ - int state = (sos & 1) ? xr : xl; - int cls; - Slot *s = start; - Slot *sRun = NULL; - Slot *sLast = s; - - for ( ; s; s = s->prev()) - { - sLast = s; - cls = BaseClass(s); - switch (cls) - { - case BN : - if (s == start) start = s->prev(); // skip initial BNs for NSM resolving - continue; - case LRI : - case RLI : - case FSI : - case PDI : - { - Slot *snext = s->prev(); - if (snext && snext->getBidiClass() == NSM) - snext->setBidiClass(ON); - s->setBidiClass(ON | WSflag); - } - break; - - case NSM : - if (s == start) - { - cls = EmbeddingDirection(sos); - s->setBidiClass(cls); - } - break; - } - - bidi_action action = actionWeak[state][bidi_class_map[cls]]; - int clsRun = GetDeferredType(action); - if (clsRun != XX) - { - SetDeferredRunClass(s, sRun, clsRun); - sRun = NULL; - } - int clsNew = GetResolvedType(action); - if (clsNew != XX) - s->setBidiClass(clsNew); - if (!sRun && (IX & action)) - sRun = s; - state = stateWeak[state][bidi_class_map[cls]]; - } - - cls = EmbeddingDirection(eos); - int clsRun = GetDeferredType(actionWeak[state][bidi_class_map[cls]]); - if (clsRun != XX) - SetThisDeferredRunClass(sLast, sRun, clsRun); -} - -void processParens(Slot *s, Segment *seg, uint8 aMirror, int level, BracketPairStack &stack) -{ - uint8 mask = 0; - int8 lastDir = -1; - BracketPair *p; - for ( ; s; s = s->prev()) // walk the sequence - { - uint16 ogid = seg->glyphAttr(s->gid(), aMirror) || s->gid(); - int cls = BaseClass(s); - - switch(cls) - { - case OPP : - stack.orin(mask); - stack.push(ogid, s, lastDir, lastDir != CPP); - mask = 0; - lastDir = OPP; - break; - case CPP : - stack.orin(mask); - p = stack.scan(s->gid()); - if (!p) break; - mask = 0; - stack.close(p, s); - lastDir = CPP; - break; - case L : - lastDir = L; - mask |= 1; - break; - case R : - case AL : - case AN : - case EN : - lastDir = R; - mask |= 2; - } - } - if (stack.size()) - { - for (p = stack.start(); p; p =p->next()) // walk the stack - { - if (p->close() && p->mask()) - { - int dir = (level & 1) + 1; - if (p->mask() & dir) - { } - else if (p->mask() & (1 << (~level & 1))) // if inside has strong other embedding - { - int ldir = p->before(); - if ((p->before() == OPP || p->before() == CPP) && p->prev()) - { - for (BracketPair *q = p->prev(); q; q = q->prev()) - { - ldir = q->open()->getBidiClass(); - if (ldir < 3) break; - ldir = q->before(); - if (ldir < 3) break; - } - if (ldir > 2) ldir = 0; - } - if (ldir > 0 && (ldir - 1) != (level & 1)) // is dir given opp. to level dir (ldir == R or L) - dir = (~level & 1) + 1; - } - p->open()->setBidiClass(dir); - p->close()->setBidiClass(dir); - } - } - stack.clear(); - } -} - -int GetDeferredNeutrals(int action, int level) -{ - action = (action >> 4) & 0xF; - if (action == (En >> 4)) - return EmbeddingDirection(level); - else - return action; -} - -int GetResolvedNeutrals(int action) -{ - return action & 0xF; -} - -// state values -enum neutral_state -{ - // new temporary class - r, // R and characters resolved to R - l, // L and characters resolved to L - rn, // N preceded by right - ln, // N preceded by left - a, // AN preceded by left (the abbrev 'la' is used up above) - na, // N preceeded by a -} ; - -const uint8 neutral_class_map[] = { 0, 1, 2, 0, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -const int actionNeutrals[][5] = -{ -// cls= N, L, R, AN, EN, state = -{ In, 0, 0, 0, 0, }, // r right -{ In, 0, 0, 0, L, }, // l left - -{ In, En, Rn, Rn, Rn, }, // rn N preceded by right -{ In, Ln, En, En, LnL, }, // ln N preceded by left - -{ In, 0, 0, 0, L, }, // a AN preceded by left -{ In, En, Rn, Rn, En, }, // na N preceded by a -} ; - -const int stateNeutrals[][5] = -{ -// cls= N, L, R, AN, EN state = -{ rn, l, r, r, r, }, // r right -{ ln, l, r, a, l, }, // l left - -{ rn, l, r, r, r, }, // rn N preceded by right -{ ln, l, r, a, l, }, // ln N preceded by left - -{ na, l, r, a, l, }, // a AN preceded by left -{ na, l, r, a, l, }, // na N preceded by la -} ; - -void resolveNeutrals(Slot *s, int baseLevel, int sos, int eos) -{ - int state = (sos & 1) ? r : l; - int cls; - Slot *sRun = NULL; - Slot *sLast = s; - int level = baseLevel; - - for ( ; s; s = s->prev()) - { - sLast = s; - cls = BaseClass(s); - switch (cls) - { - case BN : - continue; - case LRI : - case RLI : - case FSI : - s->setBidiClass(BN | WSflag); - continue; - - default : - int action = actionNeutrals[state][neutral_class_map[cls]]; - int clsRun = GetDeferredNeutrals(action, level); - if (clsRun != N) - { - SetDeferredRunClass(s, sRun, clsRun); - sRun = NULL; - } - int clsNew = GetResolvedNeutrals(action); - if (clsNew != N) - s->setBidiClass(clsNew); - if (!sRun && (action & In)) - sRun = s; - state = stateNeutrals[state][neutral_class_map[cls]]; - } - } - cls = EmbeddingDirection(eos); - int clsRun = GetDeferredNeutrals(actionNeutrals[state][neutral_class_map[cls]], level); - if (clsRun != N) - SetThisDeferredRunClass(sLast, sRun, clsRun); -} - -const int addLevel[][4] = -{ - // cls = L, R, AN, EN level = -/* even */ { 0, 1, 2, 2, }, // EVEN -/* odd */ { 1, 0, 1, 1, }, // ODD - -}; - -void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror) -{ - bool rtl = seg->dir() & 1; - int level = rtl; - Slot *slast = 0; - for ( ; s; s = s->next()) - { - int cls = BaseClass(s); - s->prev(slast); // restitch the prev() side of the doubly linked list - slast = s; - if (cls == AN) - cls = AL; // use AL value as the index for AN, no property change - if (cls < 5 && cls > 0) - { - level = s->getBidiLevel(); - level += addLevel[level & 1][cls - 1]; - s->setBidiLevel(level); - } - if (aMirror) - { - int hasChar = seg->glyphAttr(s->gid(), aMirror + 1); - if ( ((level & 1) && (!(seg->dir() & 4) || !hasChar)) - || ((rtl ^ (level & 1)) && (seg->dir() & 4) && hasChar) ) - { - unsigned short g = seg->glyphAttr(s->gid(), aMirror); - if (g) s->setGlyph(seg, g); - } - } - } -} - -void resolveWhitespace(int baseLevel, Slot *s) -{ - for ( ; s; s = s->prev()) - { - int8 cls = s->getBidiClass(); - if (cls == WS || (cls & WSflag)) - s->setBidiLevel(baseLevel); - else if (cls != BN) - break; - } -} - - -/* -Stitch two spans together to make another span (with ends tied together). -If the level is odd then swap the order of the two spans -*/ -inline -Slot * join(int level, Slot * a, Slot * b) -{ - if (!a) return b; - if (level & 1) { Slot * const t = a; a = b; b = t; } - Slot * const t = b->prev(); - a->prev()->next(b); b->prev(a->prev()); // splice middle - t->next(a); a->prev(t); // splice ends - return a; -} - -/* -Given the first slot in a run of slots with the same bidi level, turn the run -into it's own little doubly linked list ring (a span) with the two ends joined together. -If the run is rtl then reverse its direction. -Returns the first slot after the span -*/ -Slot * span(Slot * & cs, const bool rtl) -{ - Slot * r = cs, * re = cs; cs = cs->next(); - if (rtl) - { - Slot * t = r->next(); r->next(r->prev()); r->prev(t); - for (int l = r->getBidiLevel(); cs && (l == cs->getBidiLevel() || cs->getBidiClass() == BN); cs = cs->prev()) - { - re = cs; - t = cs->next(); cs->next(cs->prev()); cs->prev(t); - } - r->next(re); - re->prev(r); - r = re; - } - else - { - for (int l = r->getBidiLevel(); cs && (l == cs->getBidiLevel() || cs->getBidiClass() == BN); cs = cs->next()) - re = cs; - r->prev(re); - re->next(r); - } - if (cs) cs->prev(0); - return r; -} - -inline int getlevel(const Slot *cs, const int level) -{ - while (cs && cs->getBidiClass() == BN) - { cs = cs->next(); } - if (cs) - return cs->getBidiLevel(); - else - return level; -} - -Slot *resolveOrder(Slot * & cs, const bool reordered, const int level) -{ - Slot * r = 0; - int ls; - while (cs && level <= (ls = getlevel(cs, level) - reordered)) - { - r = join(level, r, level < ls - ? resolveOrder(/* updates */cs, reordered, level+1) // find span of heighest level - : span(/* updates */cs, level & 1)); - } - return r; -} diff --git a/gfx/graphite2/src/CMakeLists.txt b/gfx/graphite2/src/CMakeLists.txt index 4f1e7e5db..08e1c8fa3 100644 --- a/gfx/graphite2/src/CMakeLists.txt +++ b/gfx/graphite2/src/CMakeLists.txt @@ -111,6 +111,9 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector" LINK_FLAGS "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}" LINKER_LANGUAGE C) + if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86|i.86") + add_definitions(-mfpmath=sse -msse2) + endif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86|i.86") if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(-Wdouble-promotion) endif (CMAKE_COMPILER_IS_GNUCXX) @@ -135,7 +138,7 @@ endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set_target_properties(graphite2 PROPERTIES - COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector" + COMPILE_FLAGS "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector -mfpmath=sse -msse2" LINK_FLAGS "-nodefaultlibs" LINKER_LANGUAGE C) target_link_libraries(graphite2 c) diff --git a/gfx/graphite2/src/Collider.cpp b/gfx/graphite2/src/Collider.cpp index 2df46ebc4..035bb9a31 100644 --- a/gfx/graphite2/src/Collider.cpp +++ b/gfx/graphite2/src/Collider.cpp @@ -262,7 +262,7 @@ inline void ShiftCollider::removeBox(const Rect &box, const BBox &bb, const Slan // Adjust the movement limits for the target to avoid having it collide // 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 ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cslot, const Position &currShift, bool isAfter, // slot is logically after _target bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout ) @@ -282,7 +282,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif return false; const BBox &bb = gc.getBoundingBBox(gid); - SlotCollision * cslot = seg->collisionInfo(slot); + // SlotCollision * cslot = seg->collisionInfo(slot); int orderFlags = 0; bool sameClass = _seqProxClass == 0 && cslot->seqClass() == _seqClass; if (sameCluster && _seqClass @@ -306,6 +306,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif float seq_above_wt = cslot->seqAboveWt(); float seq_below_wt = cslot->seqBelowWt(); float seq_valign_wt = cslot->seqValignWt(); + float lmargin = _margin; // if isAfter, invert orderFlags for diagonal orders. if (isAfter) { @@ -334,6 +335,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif torg = _currOffset.x; cmin = _limit.bl.x + torg; cmax = _limit.tr.x - tbb.xi + tbb.xa + torg; + lmargin = _margin; 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); @@ -345,6 +347,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif torg = _currOffset.y; cmin = _limit.bl.y + torg; cmax = _limit.tr.y - tbb.yi + tbb.ya + torg; + lmargin = _margin; break; case 2 : // sum - moving along the positively-sloped vector, so the boundaries are the // negatively-sloped boundaries. @@ -357,6 +360,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif 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; + lmargin = _margin / ISQRT2; break; case 3 : // diff - moving along the negatively-sloped vector, so the boundaries are the // positively-sloped boundaries. @@ -369,6 +373,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif 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; + lmargin = _margin / ISQRT2; break; default : continue; @@ -470,7 +475,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif } } - if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin) + if (vmax < cmin - lmargin || vmin > cmax + lmargin || omax < otmin - lmargin || omin > otmax + lmargin) continue; // Process sub-boxes that are defined for this glyph. @@ -509,7 +514,7 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif omax = ssb.sa + ss; break; } - if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin) + if (vmax < cmin - lmargin || vmin > cmax + lmargin || omax < otmin - lmargin || omin > otmax + lmargin) continue; #if !defined GRAPHITE2_NTRACING @@ -517,11 +522,11 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif dbgout->setenv(1, reinterpret_cast(j)); #endif if (omin > otmax) - _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0, - sqr(_margin - omin + otmax) * _marginWt, false); + _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0, + sqr(lmargin - 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); + _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0, + sqr(lmargin - otmin + omax) * _marginWt, false); else _ranges[i].exclude_with_margins(vmin, vmax, i); anyhits = true; @@ -537,11 +542,11 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif #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); + _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0, + sqr(lmargin - 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); + _ranges[i].weightedAxis(i, vmin - lmargin, vmax + lmargin, 0, 0, 0, 0, 0, + sqr(lmargin - otmin + omax) * _marginWt, false); else _ranges[i].exclude_with_margins(vmin, vmax, i); @@ -556,7 +561,8 @@ bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShif exclSlot->setGlyph(seg, cslot->exclGlyph()); Position exclOrigin(slot->origin() + cslot->exclOffset()); exclSlot->origin(exclOrigin); - res &= mergeSlot(seg, exclSlot, currShift, isAfter, sameCluster, isCol, true, dbgout ); + SlotCollision exclInfo(seg, exclSlot); + res &= mergeSlot(seg, exclSlot, &exclInfo, currShift, isAfter, sameCluster, isCol, true, dbgout ); seg->freeSlot(exclSlot); } hasCol |= isCol; @@ -752,7 +758,7 @@ static float localmin(float al, float au, float bl, float bu, float x) } // Return the given edge of the glyph at height y, taking any slant box into account. -static float get_edge(Segment *seg, const Slot *s, const Position &shift, float y, float width, bool isRight) +static float get_edge(Segment *seg, const Slot *s, const Position &shift, float y, float width, float margin, bool isRight) { const GlyphCache &gc = seg->getFace()->glyphs(); unsigned short gid = s->gid(); @@ -767,15 +773,15 @@ static float get_edge(Segment *seg, const Slot *s, const Position &shift, float { const BBox &sbb = gc.getSubBoundingBBox(gid, i); const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, i); - if (sy + sbb.yi > y + width / 2 || sy + sbb.ya < y - width / 2) + if (sy + sbb.yi - margin > y + width / 2 || sy + sbb.ya + margin < y - width / 2) continue; if (isRight) { - float x = sx + sbb.xa; + float x = sx + sbb.xa + margin; if (x > res) { - float td = sx - sy + ssb.da + y; - float ts = sx + sy + ssb.sa - y; + float td = sx - sy + ssb.da + margin + y; + float ts = sx + sy + ssb.sa + margin - y; x = localmax(td - width / 2, td + width / 2, ts - width / 2, ts + width / 2, x); if (x > res) res = x; @@ -783,11 +789,11 @@ static float get_edge(Segment *seg, const Slot *s, const Position &shift, float } else { - float x = sx + sbb.xi; + float x = sx + sbb.xi - margin; if (x < res) { - float td = sx - sy + ssb.di + y; - float ts = sx + sy + ssb.si - y; + float td = sx - sy + ssb.di - margin + y; + float ts = sx + sy + ssb.si - margin - y; x = localmin(td - width / 2, td + width / 2, ts - width / 2, ts + width / 2, x); if (x < res) res = x; @@ -802,9 +808,9 @@ static float get_edge(Segment *seg, const Slot *s, const Position &shift, float float td = sx - sy + y; float ts = sx + sy - y; if (isRight) - res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa); + res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa) + margin; else - res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi); + res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi) - margin; } return res; } @@ -865,6 +871,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float _edges.pop_back(); } } + goto done; } numSlices = _edges.size(); @@ -896,7 +903,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float float y = _miny - 1 + (i + .5f) * _sliceWidth; // vertical center of slice if ((dir & 1) && x < _edges[i]) { - t = get_edge(seg, s, c->shift(), y, _sliceWidth, false); + t = get_edge(seg, s, c->shift(), y, _sliceWidth, margin, false); if (t < _edges[i]) { _edges[i] = t; @@ -906,7 +913,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float } else if (!(dir & 1) && x > _edges[i]) { - t = get_edge(seg, s, c->shift(), y, _sliceWidth, true); + t = get_edge(seg, s, c->shift(), y, _sliceWidth, margin, true); if (t > _edges[i]) { _edges[i] = t; @@ -916,6 +923,7 @@ bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float } } } + done: _mingap = (float)1e38; _target = aSlot; _margin = margin; @@ -946,22 +954,17 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift if (smin > smax) return false; bool collides = false; - float below = smin > 0 ? _edges[smin-1] * rtl : 1e38f; - float here = _edges[smin] * rtl; - float above = smin < (int)_edges.size() - 1 ? _edges[smin+1] * rtl : 1e38f; for (int i = smin; i <= smax; ++i) { float t; + float here = _edges[i] * rtl; float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth); // vertical center of slice - if ( (x > here - _mingap - currSpace) - || (x > below - _mingap - currSpace) - || (x > above - _mingap - currSpace)) + if ( (x > here - _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) * rtl + 2 * currSpace; - // Check slices above and below (if any). - t = min(min(here, below), above) - m; + float m = get_edge(seg, slot, currShift, y, _sliceWidth, 0., rtl > 0) * rtl + 2 * currSpace; + t = here - m; // _mingap is positive to shrink if (t < _mingap) { @@ -977,8 +980,6 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift } #endif } - below = here; here = above; - above = i < (int)_edges.size() - 2 ? _edges[i+2] * rtl : 1e38f; } return collides; // note that true is not a necessarily reliable value @@ -987,9 +988,10 @@ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift // Return the amount to kern by. Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot, - int dir, float margin, GR_MAYBE_UNUSED json * const dbgout) + int dir, GR_MAYBE_UNUSED json * const dbgout) { - float resultNeeded = (1 - 2 * (dir & 1)) * (_mingap - margin); + float resultNeeded = (1 - 2 * (dir & 1)) * _mingap; + // float resultNeeded = (1 - 2 * (dir & 1)) * (_mingap - margin); float result = min(_limit.tr.x - _offsetPrev.x, max(resultNeeded, _limit.bl.x - _offsetPrev.x)); #if !defined GRAPHITE2_NTRACING @@ -998,7 +1000,6 @@ Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slo *dbgout << json::object // slot << "slot" << objectid(dslot(seg, _target)) << "gid" << _target->gid() - << "margin" << _margin << "limit" << _limit << "miny" << _miny << "maxy" << _maxy @@ -1093,3 +1094,7 @@ float SlotCollision::getKern(int dir) const return 0; } +bool SlotCollision::ignore() const +{ + return ((flags() & SlotCollision::COLL_IGNORE) || (flags() & SlotCollision::COLL_ISSPACE)); +} diff --git a/gfx/graphite2/src/Decompressor.cpp b/gfx/graphite2/src/Decompressor.cpp index 084570ff3..4b8b1b495 100644 --- a/gfx/graphite2/src/Decompressor.cpp +++ b/gfx/graphite2/src/Decompressor.cpp @@ -51,7 +51,7 @@ bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u literal = src; src += literal_len; - if (src > end - 2) + if (src > end - 2 || src < literal) return false; match_dist = *src++; @@ -85,7 +85,7 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size) { // 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)) + if (align(literal_len) > unsigned(dst_end - dst - (MINMATCH+5)) || dst_end - dst < MINMATCH + 5) return -1; dst = overrun_copy(dst, literal, literal_len); } @@ -94,7 +94,9 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size) // decoded output. u8 const * const pcpy = dst - match_dist; if (pcpy < static_cast(out) - || dst + match_len + MINMATCH > dst_end - 5) + || pcpy >= dst + || match_len > unsigned(dst_end - dst - (MINMATCH+5)) + || dst_end - dst < MINMATCH + 5) return -1; if (dst > pcpy+sizeof(unsigned long) && dst + align(match_len + MINMATCH) <= dst_end) @@ -103,8 +105,8 @@ int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size) dst = safe_copy(dst, pcpy, match_len + MINMATCH); } - if (literal + literal_len > src_end - || dst + literal_len > dst_end) + if (literal_len > src_end - literal + || literal_len > dst_end - dst) return -1; dst = fast_copy(dst, literal, literal_len); diff --git a/gfx/graphite2/src/Face.cpp b/gfx/graphite2/src/Face.cpp index 1ab7a60f4..81b5ced8c 100644 --- a/gfx/graphite2/src/Face.cpp +++ b/gfx/graphite2/src/Face.cpp @@ -190,9 +190,10 @@ bool Face::runGraphite(Segment *seg, const Silf *aSilf) const #if !defined GRAPHITE2_NTRACING if (dbgout) { - seg->positionSlots(0, 0, 0, aSilf->dir()); + seg->positionSlots(0, 0, 0, seg->currdir()); *dbgout << json::item << json::close // Close up the passes array + << "outputdir" << (seg->currdir() ? "rtl" : "ltr") << "output" << json::array; for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); @@ -331,10 +332,12 @@ Error Face::Table::decompress() uncompressed_size = hdr & 0x07ffffff; uncompressed_table = gralloc(uncompressed_size); if (!e.test(!uncompressed_table || uncompressed_size < 4, E_OUTOFMEM)) + { memset(uncompressed_table, 0, 4); // make sure version number is initialised // coverity[forward_null : FALSE] - uncompressed_table has been checked so can't be null // coverity[checked_return : FALSE] - we test e later e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED); + } break; } diff --git a/gfx/graphite2/src/FeatureMap.cpp b/gfx/graphite2/src/FeatureMap.cpp index 990616770..d0fc55ddf 100644 --- a/gfx/graphite2/src/FeatureMap.cpp +++ b/gfx/graphite2/src/FeatureMap.cpp @@ -275,7 +275,8 @@ bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const else if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap()) return false; //incompatible - pDest.reserve(m_index + 1); + if (m_index >= pDest.size()) + pDest.resize(m_index+1); pDest[m_index] &= ~m_mask; pDest[m_index] |= (uint32(val) << m_bits); return true; diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp index b521d5e5a..c4ab807b8 100644 --- a/gfx/graphite2/src/GlyphCache.cpp +++ b/gfx/graphite2/src/GlyphCache.cpp @@ -380,12 +380,16 @@ const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFa be::skip(gloc,2); if (_long_fmt) { + if (8 + glyphid * sizeof(uint32) > m_pGloc.size()) + return 0; be::skip(gloc, glyphid); glocs = be::read(gloc); gloce = be::peek(gloc); } else { + if (8 + glyphid * sizeof(uint16) > m_pGloc.size()) + return 0; be::skip(gloc, glyphid); glocs = be::read(gloc); gloce = be::peek(gloc); diff --git a/gfx/graphite2/src/GlyphFaceCache.cpp b/gfx/graphite2/src/GlyphFaceCache.cpp deleted file mode 100644 index 9abb1aa9d..000000000 --- a/gfx/graphite2/src/GlyphFaceCache.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2010, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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. -*/ -#include "inc/GlyphFaceCache.h" -#include "graphite2/Font.h" -#include "inc/Face.h" //for the tags -#include "inc/Endian.h" - -using namespace graphite2; - -/*virtual*/ bool GlyphFaceCacheHeader::initialize(const Face & face, const bool dumb_font) //return result indicates success. Do not use if failed. -{ - if ((m_pLoca = face.getTable(Tag::loca, &m_lLoca)) == NULL) return false; - if ((m_pHead = face.getTable(Tag::head)) == NULL) return false; - if ((m_pGlyf = face.getTable(Tag::glyf, &m_lGlyf)) == NULL) return false; - if ((m_pHmtx = face.getTable(Tag::hmtx, &m_lHmtx)) == NULL) return false; - if ((m_pHHea = face.getTable(Tag::hhea)) == NULL) return false; - - const void* pMaxp = face.getTable(Tag::maxp); - if (pMaxp == NULL) return false; - m_nGlyphs = m_nGlyphsWithGraphics = (unsigned short)TtfUtil::GlyphCount(pMaxp); - if (TtfUtil::LocaLookup(m_nGlyphs-1, m_pLoca, m_lLoca, m_pHead) == size_t(-1)) - return false; // This will fail if m_nGlyphs is wildly out of range. - - if (!dumb_font) - { - if ((m_pGlat = face.getTable(Tag::Glat, &m_lGlat)) == NULL) return false; - m_fGlat = be::peek(m_pGlat); - size_t lGloc; - if ((m_pGloc = face.getTable(Tag::Gloc, &lGloc)) == NULL) return false; - if (lGloc < 6) return false; - int version = be::read(m_pGloc); - if (version != 0x00010000) return false; - - const uint16 locFlags = be::read(m_pGloc); - m_numAttrs = be::read(m_pGloc); - if (m_numAttrs > 0x1000) return false; // is this hard limit appropriate? - - if (locFlags & 1) - { - m_locFlagsUse32Bit = true; - m_nGlyphsWithAttributes = (unsigned short)((lGloc - 12) / 4); - } - else - { - m_locFlagsUse32Bit = false; - m_nGlyphsWithAttributes = (unsigned short)((lGloc - 10) / 2); - } - - if (m_nGlyphsWithAttributes > m_nGlyphs) - m_nGlyphs = m_nGlyphsWithAttributes; - } - - return true; -} - -GlyphFaceCache* GlyphFaceCache::makeCache(const GlyphFaceCacheHeader& hdr) -{ - return new (hdr) GlyphFaceCache(hdr); -} - -GlyphFaceCache::GlyphFaceCache(const GlyphFaceCacheHeader& hdr) -: GlyphFaceCacheHeader(hdr) -{ - unsigned int nGlyphs = numGlyphs(); - - for (unsigned int i = 0; i < nGlyphs; i++) - { - *glyphPtrDirect(i) = NULL; - } -} - -GlyphFaceCache::~GlyphFaceCache() -{ - unsigned int nGlyphs = numGlyphs(); - int deltaPointers = (*glyphPtrDirect(nGlyphs-1u) - *glyphPtrDirect(0u)); - if ((nGlyphs > 0u) && (deltaPointers == static_cast(nGlyphs - 1))) - { - for (unsigned int i=0 ; i~GlyphFace(); - } - free (*glyphPtrDirect(0)); - } - else - { - for (unsigned int i=0 ; i~GlyphFace(); - free(p); - } - } - } -} - -void GlyphFaceCache::loadAllGlyphs() -{ - unsigned int nGlyphs = numGlyphs(); -// size_t sparse_size = 0; - GlyphFace * glyphs = gralloc(nGlyphs); - for (unsigned short glyphid = 0; glyphid < nGlyphs; glyphid++) - { - GlyphFace **p = glyphPtrDirect(glyphid); - *p = &(glyphs[glyphid]); - new(*p) GlyphFace(*this, glyphid); -// sparse_size += (*p)->m_attrs._sizeof(); - } -// const size_t flat_size = nGlyphs*(sizeof(uint16*) + sizeof(uint16)*numAttrs()); -// assert(sparse_size <= flat_size); -} - -/*virtual*/ const GlyphFace *GlyphFaceCache::glyph(unsigned short glyphid) const //result may be changed by subsequent call with a different glyphid -{ - GlyphFace **p = glyphPtrDirect(glyphid); - if (*p) - return *p; - - *p = (GlyphFace*)malloc(sizeof(GlyphFace)); - new(*p) GlyphFace(*this, glyphid); - return *p; -} diff --git a/gfx/graphite2/src/Intervals.cpp b/gfx/graphite2/src/Intervals.cpp index 1e34e5987..9b1da5a1b 100644 --- a/gfx/graphite2/src/Intervals.cpp +++ b/gfx/graphite2/src/Intervals.cpp @@ -59,7 +59,9 @@ Zones::Exclusion & Zones::Exclusion::operator += (Exclusion const & rhs) { inline uint8 Zones::Exclusion::outcode(float val) const { float p = val; - return ((p >= xm) << 1) | (p < x); + //float d = std::numeric_limits::epsilon(); + float d = 0.; + return ((p - xm >= d) << 1) | (x - p > d); } void Zones::exclude_with_margins(float xmin, float xmax, int axis) { @@ -74,6 +76,9 @@ namespace inline bool separated(float a, float b) { return a != b; + //int exp; + //float res = frexpf(fabs(a - b), &exp); + //return (*(unsigned int *)(&res) > 4); //return std::fabs(a-b) > std::numeric_limits::epsilon(); // std::epsilon may not work. but 0.5 fails exising 64 bit tests //return std::fabs(a-b) > 0.5f; } diff --git a/gfx/graphite2/src/MozGrMalloc.h b/gfx/graphite2/src/MozGrMalloc.h old mode 100644 new mode 100755 diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp index 7289406c0..683143c50 100644 --- a/gfx/graphite2/src/Pass.cpp +++ b/gfx/graphite2/src/Pass.cpp @@ -171,7 +171,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su const uint16 * const o_actions = reinterpret_cast(p); be::skip(p, m_numRules + 1); const byte * const states = p; - if (e.test(p + 2u*m_numTransition*m_numColumns >= pass_end, E_BADPASSLENGTH)) return face.error(e); + if (e.test(2u*m_numTransition*m_numColumns >= (unsigned)(pass_end - p), E_BADPASSLENGTH)) return face.error(e); be::skip(p, m_numTransition*m_numColumns); be::skip(p); if (e.test(p != pcCode, E_BADPASSCCODEPTR)) return face.error(e); @@ -192,7 +192,7 @@ bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t su m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len, precontext[0], be::peek(sort_keys), *m_silf, face, PASS_TYPE_UNKNOWN); if (e.test(!m_cPConstraint, E_OUTOFMEM) - || e.test(!m_cPConstraint, m_cPConstraint.status() + E_CODEFAILURE)) + || e.test(m_cPConstraint.status() != Code::loaded, m_cPConstraint.status() + E_CODEFAILURE)) return face.error(e); face.error_context(face.error_context() - 1); } @@ -523,7 +523,7 @@ void Pass::findNDoRule(Slot * & slot, Machine &m, FiniteStateMachine & fsm) cons if (r != re) { const int adv = doAction(r->rule->action, slot, m); - dumpRuleEventOutput(fsm, m, *r->rule, slot); + dumpRuleEventOutput(fsm, *r->rule, slot); if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot); adjustSlot(adv, slot, fsm.slots); *fsm.dbgout << "cursor" << objectid(dslot(&fsm.slots.segment, slot)) @@ -579,7 +579,7 @@ void Pass::dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEnt } -void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, const Rule & r, Slot * const last_slot) const +void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * const last_slot) const { *fsm.dbgout << json::item << json::flat << json::object << "id" << &r - m_rules @@ -597,7 +597,7 @@ void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, cons << json::close // close "input" << "slots" << json::array; const Position rsb_prepos = last_slot ? last_slot->origin() : fsm.slots.segment.advance(); - fsm.slots.segment.positionSlots(0, 0, 0, m.slotMap().dir()); + fsm.slots.segment.positionSlots(0, 0, 0, fsm.slots.segment.currdir()); for(Slot * slot = output_slot(fsm.slots, 0); slot != last_slot; slot = slot->next()) *fsm.dbgout << dslot(&fsm.slots.segment, slot); @@ -635,7 +635,7 @@ bool Pass::testPassConstraint(Machine & m) const bool Pass::testConstraint(const Rule & r, Machine & m) const { const uint16 curr_context = m.slotMap().context(); - if (unsigned(r.sort - r.preContext) > m.slotMap().size() - curr_context + if (unsigned(r.sort + curr_context - r.preContext) > m.slotMap().size() || curr_context - r.preContext < 0) return false; vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext; @@ -879,8 +879,11 @@ bool Pass::collisionKern(Segment *seg, int dir, json * const dbgout) const const SlotCollision * c = seg->collisionInfo(s); const Rect &bbox = seg->theGlyphBBoxTemporary(s->gid()); float y = s->origin().y + c->shift().y; - ymax = max(y + bbox.tr.y, ymax); - ymin = min(y + bbox.bl.y, ymin); + if (!(c->flags() & SlotCollision::COLL_ISSPACE)) + { + ymax = max(y + bbox.tr.y, ymax); + ymin = min(y + bbox.bl.y, ymin); + } if (start && (c->flags() & (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX)) == (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX)) resolveKern(seg, s, start, dir, ymin, ymax, dbgout); @@ -962,8 +965,8 @@ bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start, { SlotCollision *cNbor = seg->collisionInfo(nbor); bool sameCluster = nbor->isChildOf(base); - if (nbor != slotFix // don't process if this is the slot of interest - && !(cNbor->flags() & SlotCollision::COLL_IGNORE) // don't process if ignoring + if (nbor != slotFix // don't process if this is the slot of interest + && !(cNbor->ignore()) // don't process if ignoring && (nbor == base || sameCluster // process if in the same cluster as slotFix || !inKernCluster(seg, nbor) // or this cluster is not to be kerned || (rtl ^ ignoreForKern)) // or it comes before(ltr) or after(rtl) @@ -971,7 +974,7 @@ bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start, || !(cNbor->flags() & SlotCollision::COLL_FIX) // merge in immovable stuff || ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster) // ignore other kernable clusters || (cNbor->flags() & SlotCollision::COLL_ISCOL)) // test against other collided glyphs - && !coll.mergeSlot(seg, nbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout)) + && !coll.mergeSlot(seg, nbor, cNbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout)) return false; else if (nbor == slotFix) // Switching sides of this glyph - if we were ignoring kernable stuff before, don't anymore. @@ -1052,7 +1055,7 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start return 0.; const Rect &bb = seg->theGlyphBBoxTemporary(nbor->gid()); SlotCollision *cNbor = seg->collisionInfo(nbor); - if (bb.bl.y == 0.f && bb.tr.y == 0.f) + if ((bb.bl.y == 0.f && bb.tr.y == 0.f) || (cNbor->flags() & SlotCollision::COLL_ISSPACE)) { if (m_kernColls == InWord) break; @@ -1066,7 +1069,7 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start float y = nbor->origin().y + cNbor->shift().y; ymax = max(y + bb.tr.y, ymax); ymin = min(y + bb.bl.y, ymin); - if (nbor != slotFix && !(cNbor->flags() & SlotCollision::COLL_IGNORE)) + if (nbor != slotFix && !cNbor->ignore()) { seenEnd = true; if (!isInit) @@ -1089,7 +1092,7 @@ float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start } if (collides) { - Position mv = coll.resolve(seg, slotFix, dir, cFix->margin(), dbgout); + Position mv = coll.resolve(seg, slotFix, dir, dbgout); coll.shift(mv, dir); Position delta = slotFix->advancePos() + mv - cFix->shift(); slotFix->advance(delta); diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp index 966f75784..3020bfd36 100644 --- a/gfx/graphite2/src/Segment.cpp +++ b/gfx/graphite2/src/Segment.cpp @@ -412,8 +412,9 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo Position currpos(0., 0.); float clusterMin = 0.; Rect bbox; + bool reorder = (currdir() != isRtl); - if (currdir() != isRtl) + if (reorder) { Slot *temp; reverseSlots(); @@ -443,6 +444,8 @@ Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bo currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal); } } + if (reorder) + reverseSlots(); return currpos; } diff --git a/gfx/graphite2/src/Silf.cpp b/gfx/graphite2/src/Silf.cpp index 02876881e..e36b50289 100644 --- a/gfx/graphite2/src/Silf.cpp +++ b/gfx/graphite2/src/Silf.cpp @@ -155,8 +155,8 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, be::skip(p, be::read(p)); // don't use scriptTag array. if (e.test(p + sizeof(uint16) + sizeof(uint32) >= silf_end, E_BADSCRIPTTAGS)) { releaseBuffers(); return face.error(e); } m_gEndLine = be::read(p); // lbGID - const byte * o_passes = p, - * const passes_start = silf_start + be::read(p); + const byte * o_passes = p; + uint32 passes_start = be::read(p); const size_t num_attrs = face.glyphs().numAttrs(); if (e.test(m_aPseudo >= num_attrs, E_BADAPSEUDO) @@ -164,7 +164,7 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, || e.test(m_aBidi >= num_attrs, E_BADABIDI) || e.test(m_aMirror>= num_attrs, E_BADAMIRROR) || e.test(m_aCollision && m_aCollision >= num_attrs - 5, E_BADACOLLISION) - || e.test(m_numPasses > 128, E_BADNUMPASSES) || e.test(passes_start >= silf_end, E_BADPASSESSTART) + || e.test(m_numPasses > 128, E_BADNUMPASSES) || e.test(passes_start >= lSilf, E_BADPASSESSTART) || e.test(m_pPass < m_sPass, E_BADPASSBOUND) || e.test(m_pPass > m_numPasses, E_BADPPASS) || e.test(m_sPass > m_numPasses, E_BADSPASS) || e.test(m_jPass < m_pPass, E_BADJPASSBOUND) || e.test(m_jPass > m_numPasses, E_BADJPASS) || e.test((m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses)), E_BADBPASS) @@ -174,11 +174,11 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, return face.error(e); } be::skip(p, m_numPasses); - if (e.test(p + sizeof(uint16) >= passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); } + if (e.test(unsigned(p - silf_start) + sizeof(uint16) >= passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); } m_numPseudo = be::read(p); be::skip(p, 3); // searchPseudo, pseudoSelector, pseudoShift m_pseudos = new Pseudo[m_numPseudo]; - if (e.test(p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO) + if (e.test(unsigned(p - silf_start) + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO) || e.test(!m_pseudos, E_OUTOFMEM)) { releaseBuffers(); return face.error(e); @@ -189,20 +189,20 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, m_pseudos[i].gid = be::read(p); } - const size_t clen = readClassMap(p, passes_start - p, version, e); + const size_t clen = readClassMap(p, passes_start + silf_start - p, version, e); m_passes = new Pass[m_numPasses]; - if (e || e.test(p + clen > passes_start, E_BADPASSESSTART) + if (e || e.test(clen > unsigned(passes_start + silf_start - p), E_BADPASSESSTART) || e.test(!m_passes, E_OUTOFMEM)) { releaseBuffers(); return face.error(e); } for (size_t i = 0; i < m_numPasses; ++i) { - const byte * const pass_start = silf_start + be::read(o_passes), - * const pass_end = silf_start + be::peek(o_passes); + uint32 pass_start = be::read(o_passes); + uint32 pass_end = be::peek(o_passes); face.error_context((face.error_context() & 0xFF00) + EC_ASILF + (i << 16)); if (e.test(pass_start > pass_end, E_BADPASSSTART) || e.test(pass_start < passes_start, E_BADPASSSTART) - || e.test(pass_end > silf_end, E_BADPASSEND)) { + || e.test(pass_end > lSilf, E_BADPASSEND)) { releaseBuffers(); return face.error(e); } @@ -213,7 +213,7 @@ bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, else pt = PASS_TYPE_LINEBREAK; m_passes[i].init(this); - if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face, pt, + if (!m_passes[i].readPass(silf_start + pass_start, pass_end - pass_start, pass_start, face, pt, version, e)) { releaseBuffers(); @@ -293,7 +293,8 @@ size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version, Error if (e.test(*o + 4 > max_off, E_HIGHCLASSOFFSET) // LookupClass doesn't stretch over max_off || e.test(lookup[0] == 0 // A LookupClass with no looks is a suspicious thing ... || lookup[0] * 2 + *o + 4 > max_off // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off] - || lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO)) // rangeShift: numIDs - searchRange + || lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO) // rangeShift: numIDs - searchRange + || e.test(((o[1] - *o) & 1) != 0, ERROROFFSET)) // glyphs are in pairs so difference must be even. return ERROROFFSET; } @@ -384,9 +385,12 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi if (dbgout) { *dbgout << json::item << json::object +// << "pindex" << i // for debugging << "id" << -1 + << "slotsdir" << (seg->currdir() ? "rtl" : "ltr") + << "passdir" << (m_dir & 1 ? "rtl" : "ltr") << "slots" << json::array; - seg->positionSlots(0, 0, 0, m_dir); + seg->positionSlots(0, 0, 0, seg->currdir()); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close @@ -408,9 +412,12 @@ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi if (dbgout) { *dbgout << json::item << json::object +// << "pindex" << i // for debugging << "id" << i+1 + << "slotsdir" << (seg->currdir() ? "rtl" : "ltr") + << "passdir" << ((m_dir & 1) ^ m_passes[i].reverseDir() ? "rtl" : "ltr") << "slots" << json::array; - seg->positionSlots(0, 0, 0, m_dir); + seg->positionSlots(0, 0, 0, seg->currdir()); for(Slot * s = seg->first(); s; s = s->next()) *dbgout << dslot(seg, s); *dbgout << json::close; diff --git a/gfx/graphite2/src/XmlTraceLog.cpp b/gfx/graphite2/src/XmlTraceLog.cpp deleted file mode 100644 index f34d15018..000000000 --- a/gfx/graphite2/src/XmlTraceLog.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2010, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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. -*/ - -#include -#include -#include "Main.h" -#include "XmlTraceLog.h" - - -using namespace graphite2; - -#ifndef DISABLE_TRACING - -/*static*/ XmlTraceLog XmlTraceLog::sm_NullLog(NULL, NULL, GRLOG_NONE); -XmlTraceLog * XmlTraceLog::sLog = &sm_NullLog; - -XmlTraceLog::XmlTraceLog(FILE * file, const char * ns, GrLogMask logMask) - : m_file(file), m_depth(0), m_mask(logMask) -{ - if (!m_file) return; - int deep = 0; -#ifdef ENABLE_DEEP_TRACING - deep = 1; -#endif - fprintf(m_file, "\n<%s xmlns=\"%s\" mask=\"%x\" deep=\"%d\">", - xmlTraceLogElements[ElementTopLevel].mName, ns, logMask, deep); - m_elementStack[m_depth++] = ElementTopLevel; - m_elementEmpty = true; - m_inElement = false; - m_lastNodeText = false; -} - -XmlTraceLog::~XmlTraceLog() -{ - if (m_file && m_file != stdout && m_file != stderr) - { - assert(m_depth == 1); - while (m_depth > 0) - { - closeElement(m_elementStack[m_depth-1]); - } - fclose(m_file); - m_file = NULL; - } -} - -void XmlTraceLog::addSingleElement(XmlTraceLogElement eId, const int value) -{ - if (!m_file) return; - if (m_inElement) - { - if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - fprintf(m_file, ">"); - } - if (xmlTraceLogElements[eId].mFlags & m_mask) - { - if (!m_lastNodeText) - { - fprintf(m_file, "\n"); - for (size_t i = 0; i < m_depth; i++) - { - fprintf(m_file, " "); - } - } - fprintf(m_file, "<%s val=\"%d\"/>", xmlTraceLogElements[eId].mName, value); - } - m_inElement = false; - m_lastNodeText = false; -} - -void XmlTraceLog::writeElementArray(XmlTraceLogElement eId, XmlTraceLogAttribute aId, int16 values [], size_t length) -{ - if (!m_file) return; - if (xmlTraceLogElements[eId].mFlags & m_mask) - { - if(m_inElement && xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - { - fprintf(m_file, ">"); - m_inElement = false; - } - // line break after 5 columns - for (size_t i = 0; i < length; i++) - { - if (i % 5 == 0) - { - fprintf(m_file, "\n"); - for (size_t j = 0; j < m_depth; j++) - { - fprintf(m_file, " "); - } - } - fprintf(m_file, "<%s index=\"%d\" %s=\"%d\"/>", xmlTraceLogElements[eId].mName, int(i), - xmlTraceLogAttributes[aId], (int)values[i]); - } - } -} - -void XmlTraceLog::writeText(const char * utf8) -{ - if (!m_file) return; - if (m_inElement) - { - if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - { - fprintf(m_file, ">"); - } - m_inElement = false; - } - if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - { - escapeIfNeeded(utf8); - } - m_lastNodeText = true; -} - -void XmlTraceLog::writeUnicode(const uint32 code) -{ - if (!m_file) return; - if (m_inElement) - { - if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - { - fprintf(m_file, ">"); - } - m_inElement = false; - } - if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask) - { - fprintf(m_file, "&#x%02x;", code); - } - m_lastNodeText = true; -} - -void XmlTraceLog::escapeIfNeeded(const char * data) -{ - size_t length = strlen(data); - for (size_t i = 0; i < length; i++) - { - switch (data[i]) - { - case '<': - fprintf(m_file, "<"); - break; - case '>': - fprintf(m_file, ">"); - break; - case '&': - fprintf(m_file, "&"); - break; - case '"': - fprintf(m_file, """); - break; - default: - fprintf(m_file, "%c", data[i]); - } - } -} - -static const int MAX_MSG_LEN = 1024; - -void XmlTraceLog::error(const char * msg, ...) -{ - if (!m_file) return; - openElement(ElementError); - va_list args; - va_start(args, msg); - char buffer[MAX_MSG_LEN]; -#ifndef NDEBUG - int len = -#endif - vsnprintf(buffer, MAX_MSG_LEN, msg, args); - assert(len + 1 < MAX_MSG_LEN); - writeText(buffer); - va_end(args); - closeElement(ElementError); -} - -void XmlTraceLog::warning(const char * msg, ...) -{ - if (!m_file) return; - openElement(ElementWarning); - va_list args; - va_start(args, msg); - char buffer[MAX_MSG_LEN]; -#ifndef NDEBUG - int len = -#endif - vsnprintf(buffer, MAX_MSG_LEN, msg, args); - assert(len + 1 < MAX_MSG_LEN); - writeText(buffer); - va_end(args); - closeElement(ElementWarning); -} - -#endif //!DISABLE_TRACING diff --git a/gfx/graphite2/src/XmlTraceLogTags.cpp b/gfx/graphite2/src/XmlTraceLogTags.cpp deleted file mode 100644 index b6ec970ac..000000000 --- a/gfx/graphite2/src/XmlTraceLogTags.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2010, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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. -*/ -#include "Main.h" -#include "XmlTraceLogTags.h" - - -using namespace graphite2; - -#ifndef DISABLE_TRACING - - -// start this at same line number as in XmlTraceLogTags.h -const XmlTraceLogTag graphite2::xmlTraceLogElements[NumElements] = { - XmlTraceLogTag("Graphite2Log", GRLOG_ALL), - XmlTraceLogTag("Face", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("Glyphs", GRLOG_FACE), - XmlTraceLogTag("GlyphFace", GRLOG_FACE), - XmlTraceLogTag("Attr", GRLOG_FACE), - XmlTraceLogTag("Silf", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("SilfSub", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("Pass", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("Pseudo", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("ClassMap", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("LookupClass", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("Lookup", GRLOG_FACE | GRLOG_PASS), - XmlTraceLogTag("Range", GRLOG_PASS), - XmlTraceLogTag("RuleMap", GRLOG_PASS), - XmlTraceLogTag("Rule", GRLOG_PASS), - XmlTraceLogTag("StartState", GRLOG_PASS), - XmlTraceLogTag("StateTransitions", GRLOG_PASS), - XmlTraceLogTag("TR", GRLOG_PASS), - XmlTraceLogTag("TD", GRLOG_PASS), - XmlTraceLogTag("Constraint", GRLOG_PASS), - XmlTraceLogTag("Constraints", GRLOG_PASS), - XmlTraceLogTag("Actions", GRLOG_PASS), - XmlTraceLogTag("Action", GRLOG_PASS), - XmlTraceLogTag("Features", GRLOG_PASS), - XmlTraceLogTag("Feature", GRLOG_PASS), - XmlTraceLogTag("FeatureSetting", GRLOG_PASS), - XmlTraceLogTag("Segment", GRLOG_SEGMENT), - XmlTraceLogTag("Slot", GRLOG_SEGMENT), - XmlTraceLogTag("Text", GRLOG_SEGMENT), - XmlTraceLogTag("OpCode", GRLOG_OPCODE), - XmlTraceLogTag("TestRule", GRLOG_OPCODE), - XmlTraceLogTag("DoRule", GRLOG_OPCODE), - XmlTraceLogTag("RunPass", GRLOG_OPCODE), - XmlTraceLogTag("Params", GRLOG_OPCODE), - XmlTraceLogTag("Push", GRLOG_OPCODE), - XmlTraceLogTag("SubSeg", GRLOG_SEGMENT), - XmlTraceLogTag("SegCache", GRLOG_CACHE), - XmlTraceLogTag("SegCacheEntry", GRLOG_CACHE), - XmlTraceLogTag("Glyph", GRLOG_CACHE), - XmlTraceLogTag("PassResult", GRLOG_OPCODE), - - XmlTraceLogTag("Error", GRLOG_ALL), - XmlTraceLogTag("Warning", GRLOG_ALL) - // Nothing corresponds to NumElements -}; - - - -// start this at same line number as in XmlTraceLogTags.h -const char * graphite2::xmlTraceLogAttributes[NumAttributes] = { - "index", - "version", - "major", - "minor", - "num", - "glyphId", - "advance", - "advanceX", - "advanceY", - "attrId", - "attrVal", - "compilerMajor", - "compilerMinor", - "numPasses",//AttrNumPasses, - "subPass",//AttrSubPass, - "posPass",//AttrPosPass, - "justPass",//AttrJustPass, - "bidiPass",//AttrBidiPass, - "preContext",//AttrPreContext, - "postContext",//AttrPostContext, - "pseudoGlyph",//AttrPseudoGlyph, - "breakWeight",//AttrBreakWeight, - "directionality",//AttrDirectionality, - "numJustLevels",//AttrNumJustLevels, - "numLigCompAttr",//AttrLigComp, - "numUserDefinedAttr",//AttrUserDefn, - "maxNumLigComp",//AttrNumLigComp, - "numCriticalFeatures",//AttrNumCritFeatures, - "numScripts",//AttrNumScripts - "lineBreakglyph",//,AttrLBGlyph, - "numPseudo", - "numClasses", - "numLinear", - "passId",//AttrPassId, - "flags",//AttrFlags, - "maxRuleLoop",//AttrMaxRuleLoop, - "maxRuleContext",//AttrMaxRuleContext, - "maxBackup",//AttrMaxBackup, - "numRules",//AttrNumRules, - "numRows",//AttrNumRows, - "numTransitionStates",//AttrNumTransition, - "numSuccessStates",//AttrNumSuccess, - "numColumns",//AttrNumColumns, - "numRanges",//AttrNumRanges, - "minPrecontext",//AttrMinPrecontext, - "maxPrecontext",//AttrMaxPrecontext, - "firstId", - "lastId", - "colId", - "successId", - "ruleId", - "contextLength", - "state", - "value", - "sortKey", - "precontext", - "action", - "actionCode", - "arg1", - "arg2", - "arg3", - "arg4", - "arg5", - "arg6", - "arg7", - "arg8", - "label", - "length", - "x", - "y", - "before", - "after", - "encoding", - "name", - "result", - "default", - "accessCount", - "lastAccess", - "misses" -}; - -#endif diff --git a/gfx/graphite2/src/inc/Bidi.h b/gfx/graphite2/src/inc/Bidi.h deleted file mode 100644 index 9593c7e14..000000000 --- a/gfx/graphite2/src/inc/Bidi.h +++ /dev/null @@ -1,126 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2013, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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 - -namespace graphite2 -{ - -class BracketPair -{ -public: - BracketPair(uint16 g, Slot *s, uint8 b, BracketPair *p, BracketPair *l) : _open(s), _close(0), _parent(p), _next(0), _prev(l), _gid(g), _mask(0), _before(b) {}; - uint16 gid() const { return _gid; } - Slot *open() const { return _open; } - Slot *close() const { return _close; } - uint8 mask() const { return _mask; } - int8 before() const { return _before; } - BracketPair *parent() const { return _parent; } - void close(Slot *s) { _close = s; } - BracketPair *next() const { return _next; } - BracketPair *prev() const { return _prev; } - void next(BracketPair *n) { _next = n; } - void orin(uint8 m) { _mask |= m; } -private: - Slot * _open; // Slot of opening paren - Slot * _close; // Slot of closing paren - BracketPair * _parent; // pair this pair is in or NULL - BracketPair * _next; // next pair along the string - BracketPair * _prev; // pair that closed last before we opened - uint16 _gid; // gid of closing paren - uint8 _mask; // bitmap (2 bits) of directions within the pair - int8 _before; // most recent strong type (L, R, OPP, CPP) -}; - -class BracketPairStack -{ -public: - BracketPairStack(int s) : _stack(grzeroalloc(s)), _ip(_stack - 1), _top(0), _last(0), _lastclose(0), _size(s) {} - ~BracketPairStack() { free(_stack); } - -public: - BracketPair *scan(uint16 gid); - void close(BracketPair *tos, Slot *s); - BracketPair *push(uint16 gid, Slot *pos, uint8 before, int prevopen); - void orin(uint8 mask); - void clear() { _ip = _stack - 1; _top = 0; _last = 0; _lastclose = 0; } - int size() const { return _size; } - BracketPair *start() const { return _stack; } - - CLASS_NEW_DELETE - -private: - - BracketPair *_stack; // start of storage - BracketPair *_ip; // where to add the next pair - BracketPair *_top; // current parent - BracketPair *_last; // end of next() chain - BracketPair *_lastclose; // last pair to close - int _size; // capacity -}; - -inline BracketPair *BracketPairStack::scan(uint16 gid) -{ - BracketPair *res = _top; - while (res >= _stack) - { - if (res->gid() == gid) - return res; - res = res->parent(); - } - return 0; -} - -inline void BracketPairStack::close(BracketPair *tos, Slot *s) -{ - for ( ; _last && _last != tos && !_last->close(); _last = _last->parent()) - { } - tos->close(s); - _last->next(NULL); - _lastclose = tos; - _top = tos->parent(); -} - -inline BracketPair *BracketPairStack::push(uint16 gid, Slot *pos, uint8 before, int prevopen) -{ - if (++_ip - _stack < _size && _stack) - { - ::new (_ip) BracketPair(gid, pos, before, _top, prevopen ? _last : _lastclose); - if (_last) _last->next(_ip); - _last = _ip; - } - _top = _ip; - return _ip; -} - -inline void BracketPairStack::orin(uint8 mask) -{ - BracketPair *t = _top; - for ( ; t; t = t->parent()) - t->orin(mask); -} - -} diff --git a/gfx/graphite2/src/inc/Collider.h b/gfx/graphite2/src/inc/Collider.h index bcbf3a224..5d953b4a4 100644 --- a/gfx/graphite2/src/inc/Collider.h +++ b/gfx/graphite2/src/inc/Collider.h @@ -54,7 +54,8 @@ public: COLL_KERN = 16, // collisions with this glyph are fixed by adding kerning space after it COLL_ISCOL = 32, // this glyph has a collision COLL_KNOWN = 64, // we've figured out what's happening with this glyph - COLL_TEMPLOCK = 128, // Lock glyphs that have been given priority positioning + COLL_ISSPACE = 128, // treat this glyph as a space with regard to kerning + COLL_TEMPLOCK = 256, // Lock glyphs that have been given priority positioning ////COLL_JUMPABLE = 128, // moving glyphs may jump this stationary glyph in any direction - DELETE ////COLL_OVERLAP = 256, // use maxoverlap to restrict - DELETE }; @@ -93,6 +94,7 @@ public: SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt) float getKern(int dir) const; + bool ignore() const; private: Rect _limit; @@ -131,7 +133,7 @@ public: bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin, float marginMin, const Position &currShift, const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout); - bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, bool isAfter, + bool mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cinfo, const Position &currShift, bool isAfter, bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout); Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout); void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode); @@ -191,7 +193,7 @@ public: const Position &currShift, const Position &offsetPrev, int dir, float ymin, float ymax, json * const dbgout); bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout); - Position resolve(Segment *seg, Slot *slot, int dir, float margin, json * const dbgout); + Position resolve(Segment *seg, Slot *slot, int dir, json * const dbgout); void shift(const Position &mv, int dir); CLASS_NEW_DELETE; diff --git a/gfx/graphite2/src/inc/GlyphFaceCache.h b/gfx/graphite2/src/inc/GlyphFaceCache.h deleted file mode 100644 index 4afdfbe01..000000000 --- a/gfx/graphite2/src/inc/GlyphFaceCache.h +++ /dev/null @@ -1,103 +0,0 @@ -/* GRAPHITE2 LICENSING - - Copyright 2010, SIL International - All rights reserved. - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2.1 of License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should also have received a copy of the GNU Lesser General Public - License along with this library in the file named "LICENSE". - If not, write to the Free Software Foundation, 51 Franklin Street, - Suite 500, Boston, MA 02110-1335, USA or visit their web page on the - internet at http://www.fsf.org/licenses/lgpl.html. - -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 "inc/GlyphFace.h" -#include "graphite2/Font.h" - -namespace graphite2 { - -class Segment; -class Face; -class FeatureVal; - - -class GlyphFaceCacheHeader -{ -public: - bool initialize(const Face & face, const bool dumb_font); //return result indicates success. Do not use if failed. - unsigned short numGlyphs() const { return m_nGlyphs; } - unsigned short numAttrs() const { return m_numAttrs; } - -private: -friend class Face; -friend class GlyphFace; - const byte* m_pHead, - * m_pHHea, - * m_pHmtx, - * m_pGlat, - * m_pGloc, - * m_pGlyf, - * m_pLoca; - size_t m_lHmtx, - m_lGlat, - m_lGlyf, - m_lLoca; - - uint32 m_fGlat; - unsigned short m_numAttrs, // number of glyph attributes per glyph - m_nGlyphsWithGraphics, //i.e. boundary box and advance - m_nGlyphsWithAttributes, - m_nGlyphs; // number of glyphs in the font. Max of the above 2. - bool m_locFlagsUse32Bit; -}; - -class GlyphFaceCache : public GlyphFaceCacheHeader -{ -public: - static GlyphFaceCache* makeCache(const GlyphFaceCacheHeader& hdr /*, EGlyphCacheStrategy requested */); - - GlyphFaceCache(const GlyphFaceCacheHeader& hdr); - ~GlyphFaceCache(); - - const GlyphFace *glyphSafe(unsigned short glyphid) const { return glyphid=numAttrs()) return 0; const GlyphFace*p=glyphSafe(gid); return p?p->getAttr(gattr):0; } - - void * operator new (size_t s, const GlyphFaceCacheHeader& hdr) - { - return malloc(s + sizeof(GlyphFace*)*hdr.numGlyphs()); - } - // delete in case an exception is thrown in constructor - void operator delete(void* p, const GlyphFaceCacheHeader& ) throw() - { - free(p); - } - - const GlyphFace *glyph(unsigned short glyphid) const; //result may be changed by subsequent call with a different glyphid - void loadAllGlyphs(); - - CLASS_NEW_DELETE - -private: - GlyphFace **glyphPtrDirect(unsigned short glyphid) const { return (GlyphFace **)((const char*)(this)+sizeof(GlyphFaceCache)+sizeof(GlyphFace*)*glyphid);} - -private: //defensive - GlyphFaceCache(const GlyphFaceCache&); - GlyphFaceCache& operator=(const GlyphFaceCache&); -}; - -} // namespace graphite2 diff --git a/gfx/graphite2/src/inc/Pass.h b/gfx/graphite2/src/inc/Pass.h index 82da2caf1..074d501d9 100644 --- a/gfx/graphite2/src/inc/Pass.h +++ b/gfx/graphite2/src/inc/Pass.h @@ -74,7 +74,7 @@ private: uint16 glyphToCol(const uint16 gid) const; bool runFSM(FiniteStateMachine & fsm, Slot * slot) const; void dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const; - void dumpRuleEventOutput(const FiniteStateMachine & fsm, vm::Machine & m, const Rule & r, Slot * os) const; + void dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * os) const; void adjustSlot(int delta, Slot * & slot_out, SlotMap &) const; bool collisionShift(Segment *seg, int dir, json * const dbgout) const; bool collisionKern(Segment *seg, int dir, json * const dbgout) const; diff --git a/gfx/graphite2/src/inc/Shrinker.h b/gfx/graphite2/src/inc/Shrinker.h deleted file mode 100644 index e4db2f135..000000000 --- a/gfx/graphite2/src/inc/Shrinker.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (c) 2012, Siyuan Fu - Copyright (c) 2015, SIL International - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -#include -#include -#include - -#include - -//the code from LZ4 -#if (GCC_VERSION >= 302) || (__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; -#else -#include -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -#endif - -ptrdiff_t const MINMATCH = 4; - -template -inline -void unaligned_copy(void * d, void const * s) { - ::memcpy(d, s, S); -} - -inline -u8 * memcpy_nooverlap(u8 * d, u8 const * s, size_t n) { - size_t const WS = sizeof(unsigned long); - u8 const * e = s + n; - do - { - unaligned_copy(d, s); - d += WS; - s += WS; - } - while (s < e); - d-=(s-e); - - return d; -} - - -inline -u8 * memcpy_nooverlap_surpass(u8 * d, u8 const * s, size_t n) { - size_t const WS = sizeof(unsigned long); - size_t wn = n/WS; - while (wn--) - { - unaligned_copy(d, s); - d += WS; - s += WS; - } - n &= WS-1; - while (n--) {*d++ = *s++; } - - return d; -} - - -inline -u8 * memcpy_(u8 * d, u8 const * s, size_t n) { - if (likely(d>s+sizeof(unsigned long))) - return memcpy_nooverlap(d,s,n); - else while (n--) *d++ = *s++; - return d; -} - -} // end of anonymous namespace - - diff --git a/gfx/graphite2/src/inc/UtfCodec.h b/gfx/graphite2/src/inc/UtfCodec.h index 3417bac7b..9dc760fdc 100644 --- a/gfx/graphite2/src/inc/UtfCodec.h +++ b/gfx/graphite2/src/inc/UtfCodec.h @@ -124,7 +124,7 @@ struct _utf_codec<8> private: static const int8 sz_lut[16]; static const byte mask_lut[5]; - + static const uchar_t limit = 0x110000; public: typedef uint8 codeunit_t; @@ -157,7 +157,7 @@ public: case 0: l = -1; return 0xFFFD; } - if (l != seq_sz || toolong) + if (l != seq_sz || toolong || u >= limit) { l = -l; return 0xFFFD; diff --git a/gfx/graphite2/src/inc/locale2lcid.h b/gfx/graphite2/src/inc/locale2lcid.h index bc3e3d830..25d5c0a3c 100644 --- a/gfx/graphite2/src/inc/locale2lcid.h +++ b/gfx/graphite2/src/inc/locale2lcid.h @@ -36,8 +36,8 @@ namespace graphite2 { struct IsoLangEntry { unsigned short mnLang; - const char maLangStr[4]; - const char maCountry[3]; + char maLangStr[4]; + char maCountry[3]; }; // Windows Language ID, Locale ISO-639 language, country code as used in diff --git a/gfx/graphite2/src/moz.build b/gfx/graphite2/src/moz.build old mode 100644 new mode 100755 index 4008b7706..7fb0f2614 --- a/gfx/graphite2/src/moz.build +++ b/gfx/graphite2/src/moz.build @@ -1,4 +1,4 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -23,7 +23,6 @@ else: # This should contain all of the _SOURCES from files.mk, except *_machine.cpp UNIFIED_SOURCES += [ - 'Bidi.cpp', 'CachedFace.cpp', 'CmapCache.cpp', 'Code.cpp', @@ -45,7 +44,6 @@ UNIFIED_SOURCES += [ 'Intervals.cpp', 'json.cpp', 'Justifier.cpp', - 'NameTable.cpp', 'Pass.cpp', 'Position.cpp', 'SegCache.cpp', @@ -59,6 +57,12 @@ UNIFIED_SOURCES += [ 'UtfCodec.cpp', ] +# Excluded from UNIFIED_SOURCES because from other files breaks it, +# see bug 1272647. +SOURCES += [ + 'NameTable.cpp', +] + # tell graphite2 not to export symbols, we'll be linking it directly with # thebes DEFINES['GRAPHITE2_STATIC'] = True