diff --git a/Lib/src/graphite2/README b/Lib/src/graphite2/README index 5fc197c892..85df2417aa 100644 --- a/Lib/src/graphite2/README +++ b/Lib/src/graphite2/README @@ -1,3 +1,3 @@ This directory contains the Graphite2 library from https://github.com/silnrsi/graphite -Current version derived from upstream a7096fa Allow labels to return None from graphite +Current version derived from upstream 92f59dcc Update files for release See update.sh for update procedure. diff --git a/Lib/src/graphite2/include/graphite2/Font.h b/Lib/src/graphite2/include/graphite2/Font.h index 3e8214d46b..fe569295a5 100644 --- a/Lib/src/graphite2/include/graphite2/Font.h +++ b/Lib/src/graphite2/include/graphite2/Font.h @@ -30,7 +30,7 @@ #define GR2_VERSION_MAJOR 1 #define GR2_VERSION_MINOR 3 -#define GR2_VERSION_BUGFIX 13 +#define GR2_VERSION_BUGFIX 14 #ifdef __cplusplus extern "C" diff --git a/Lib/src/graphite2/src/Bidi.cpp b/Lib/src/graphite2/src/Bidi.cpp deleted file mode 100644 index 48ec2ebfcd..0000000000 --- a/Lib/src/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/Lib/src/graphite2/src/Code.cpp b/Lib/src/graphite2/src/Code.cpp index ee3886d1f4..ec5ab298ca 100644 --- a/Lib/src/graphite2/src/Code.cpp +++ b/Lib/src/graphite2/src/Code.cpp @@ -101,6 +101,7 @@ class Machine::Code::decoder bool valid_upto(const uint16 limit, const uint16 x) const throw(); bool test_context() const throw(); bool test_ref(int8 index) const throw(); + bool test_attr(attrCode attr) const throw(); void failure(const status_t s) const throw() { _code.failure(s); } Code & _code; @@ -381,6 +382,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) valid_upto(gr_slatMax, bc[0]); if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes failure(out_of_range_data); + test_attr(attrCode(bc[0])); test_context(); break; case IATTR_SET_SLOT : @@ -388,6 +390,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) failure(underfull_stack); if (valid_upto(gr_slatMax, bc[0])) valid_upto(_max.attrid[bc[0]], bc[1]); + test_attr(attrCode(bc[0])); test_context(); break; case PUSH_SLOT_ATTR : @@ -396,6 +399,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) test_ref(int8(bc[1])); if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes failure(out_of_range_data); + test_attr(attrCode(bc[0])); break; case PUSH_GLYPH_ATTR_OBS : case PUSH_ATT_TO_GATTR_OBS : @@ -422,6 +426,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) test_ref(int8(bc[1])); valid_upto(_max.attrid[bc[0]], bc[2]); } + test_attr(attrCode(bc[0])); break; case PUSH_IGLYPH_ATTR :// not implemented ++_stack_depth; @@ -441,6 +446,7 @@ opcode Machine::Code::decoder::fetch_opcode(const byte * bc) failure(underfull_stack); if (valid_upto(gr_slatMax, bc[0])) valid_upto(_max.attrid[bc[0]], bc[1]); + test_attr(attrCode(bc[0])); test_context(); break; case PUSH_PROC_STATE : // dummy: dp[0] no check necessary @@ -683,7 +689,8 @@ bool Machine::Code::decoder::test_ref(int8 index) const throw() else { if (_max.rule_length == 0 - || (_slotref + _max.pre_context + index >= _max.rule_length)) + || (_slotref + _max.pre_context + index >= _max.rule_length) + || (_slotref + _max.pre_context + index < 0)) { failure(out_of_range_data); return false; @@ -702,6 +709,22 @@ bool Machine::Code::decoder::test_context() const throw() return true; } +bool Machine::Code::decoder::test_attr(attrCode) const throw() +{ +#if 0 // This code is coming but causes backward compatibility problems. + if (_passtype < PASS_TYPE_POSITIONING) + { + if (attr != gr_slatBreak && attr != gr_slatDir && attr != gr_slatUserDefn + && attr != gr_slatCompRef) + { + failure(out_of_range_data); + return false; + } + } +#endif + return true; +} + inline void Machine::Code::failure(const status_t s) throw() { release_buffers(); diff --git a/Lib/src/graphite2/src/Collider.cpp b/Lib/src/graphite2/src/Collider.cpp index 0e76960dca..a16146cd51 100644 --- a/Lib/src/graphite2/src/Collider.cpp +++ b/Lib/src/graphite2/src/Collider.cpp @@ -1082,8 +1082,8 @@ void SlotCollision::initFromSlot(Segment *seg, Slot *slot) return; const sparse &p = glyphFace->attrs(); _flags = p[aCol]; - _limit = Rect(Position(p[aCol+1], p[aCol+2]), - Position(p[aCol+3], p[aCol+4])); + _limit = Rect(Position(int16(p[aCol+1]), int16(p[aCol+2])), + Position(int16(p[aCol+3]), int16(p[aCol+4]))); _margin = p[aCol+5]; _marginWt = p[aCol+6]; diff --git a/Lib/src/graphite2/src/FeatureMap.cpp b/Lib/src/graphite2/src/FeatureMap.cpp index e63415dd1c..014a88fd08 100644 --- a/Lib/src/graphite2/src/FeatureMap.cpp +++ b/Lib/src/graphite2/src/FeatureMap.cpp @@ -71,7 +71,7 @@ namespace FeatureRef::FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val, - uint32 name, uint16 uiName, uint16 flags, + uint32 name, uint16 uiName, flags_t flags, FeatureSetting *settings, uint16 num_set) throw() : m_face(&face), m_nameValues(settings), @@ -79,8 +79,8 @@ FeatureRef::FeatureRef(const Face & face, m_max(max_val), m_id(name), m_nameid(uiName), - m_flags(flags), - m_numSet(num_set) + m_numSet(num_set), + m_flags(flags) { const uint8 need_bits = bit_set_count(m_mask); m_index = (bits_offset + need_bits) / SIZEOF_CHUNK; @@ -163,7 +163,8 @@ bool FeatureMap::readFeats(const Face & face) } ::new (m_feats + i) FeatureRef (face, bits, maxVal, - label, uiName, flags, + label, uiName, + FeatureRef::flags_t(flags), uiSet, num_settings); } new (&m_defaultFeatures) Features(bits/(sizeof(uint32)*8) + 1, *this); diff --git a/Lib/src/graphite2/src/Pass.cpp b/Lib/src/graphite2/src/Pass.cpp index 76d4983aee..db31c22d46 100644 --- a/Lib/src/graphite2/src/Pass.cpp +++ b/Lib/src/graphite2/src/Pass.cpp @@ -704,7 +704,7 @@ void Pass::adjustSlot(int delta, Slot * & slot_out, SlotMap & smap) const { slot_out = smap.segment.last(); ++delta; - if (!smap.highwater()) + if (!smap.highwater() || smap.highwater() == slot_out) smap.highpassed(false); } else diff --git a/Lib/src/graphite2/src/SegCache.cpp b/Lib/src/graphite2/src/SegCache.cpp deleted file mode 100644 index b577efa270..0000000000 --- a/Lib/src/graphite2/src/SegCache.cpp +++ /dev/null @@ -1,224 +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/Main.h" -#include "inc/TtfTypes.h" -#include "inc/TtfUtil.h" -#include "inc/SegCache.h" -#include "inc/SegCacheEntry.h" -#include "inc/SegCacheStore.h" -#include "inc/CmapCache.h" - - -using namespace graphite2; - -#ifndef GRAPHITE2_NSEGCACHE - -SegCache::SegCache(const SegCacheStore * store, const Features & feats) -: m_prefixLength(ePrefixLength), -// m_maxCachedSegLength(eMaxSpliceSize), - m_segmentCount(0), - m_features(feats), - m_totalAccessCount(0l), m_totalMisses(0l), - m_purgeFactor(1.0f / (ePurgeFactor * store->maxSegmentCount())) -{ - m_prefixes.raw = grzeroalloc(store->maxCmapGid() + 2); - m_prefixes.range[SEG_CACHE_MIN_INDEX] = SEG_CACHE_UNSET_INDEX; - m_prefixes.range[SEG_CACHE_MAX_INDEX] = SEG_CACHE_UNSET_INDEX; -} - -void SegCache::freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level) -{ - for (size_t i = 0; i < store->maxCmapGid(); i++) - { - if (prefixes.array[i].raw) - { - if (level + 1 < ePrefixLength) - freeLevel(store, prefixes.array[i], level + 1); - else - { - SegCachePrefixEntry * prefixEntry = prefixes.prefixEntries[i]; - delete prefixEntry; - } - } - } - free(prefixes.raw); -} - -void SegCache::clear(SegCacheStore * store) -{ - freeLevel(store, m_prefixes, 0); - m_prefixes.raw = NULL; -} - -SegCache::~SegCache() -{ - assert(m_prefixes.raw == NULL); -} - -SegCacheEntry* SegCache::cache(SegCacheStore * store, const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset) -{ - uint16 pos = 0; - if (!length) return NULL; -// assert(length < m_maxCachedSegLength); - SegCachePrefixArray pArray = m_prefixes; - while (pos + 1 < m_prefixLength) - { - uint16 gid = (pos < length)? cmapGlyphs[pos] : 0; - if (!pArray.array[gid].raw) - { - pArray.array[gid].raw = grzeroalloc(store->maxCmapGid() + 2); - if (!pArray.array[gid].raw) - return NULL; // malloc failed - if (pArray.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX) - { - pArray.range[SEG_CACHE_MIN_INDEX] = gid; - pArray.range[SEG_CACHE_MAX_INDEX] = gid; - } - else - { - if (gid < pArray.range[SEG_CACHE_MIN_INDEX]) - pArray.range[SEG_CACHE_MIN_INDEX] = gid; - else if (gid > pArray.range[SEG_CACHE_MAX_INDEX]) - pArray.range[SEG_CACHE_MAX_INDEX] = gid; - } - } - pArray = pArray.array[gid]; - ++pos; - } - uint16 gid = (pos < length)? cmapGlyphs[pos] : 0; - SegCachePrefixEntry * prefixEntry = pArray.prefixEntries[gid]; - if (!prefixEntry) - { - prefixEntry = new SegCachePrefixEntry(); - pArray.prefixEntries[gid] = prefixEntry; - if (pArray.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX) - { - pArray.range[SEG_CACHE_MIN_INDEX] = gid; - pArray.range[SEG_CACHE_MAX_INDEX] = gid; - } - else - { - if (gid < pArray.range[SEG_CACHE_MIN_INDEX]) - pArray.range[SEG_CACHE_MIN_INDEX] = gid; - else if (gid > pArray.range[SEG_CACHE_MAX_INDEX]) - pArray.range[SEG_CACHE_MAX_INDEX] = gid; - } - } - if (!prefixEntry) return NULL; - // if the cache is full run a purge - this is slow, since it walks the tree - if (m_segmentCount + 1 > store->maxSegmentCount()) - { - purge(store); - assert(m_segmentCount < store->maxSegmentCount()); - } - SegCacheEntry * pEntry = prefixEntry->cache(cmapGlyphs, length, seg, charOffset, m_totalAccessCount); - if (pEntry) ++m_segmentCount; - return pEntry; -} - -void SegCache::purge(SegCacheStore * store) -{ - unsigned long long minAccessCount = static_cast(m_totalAccessCount * m_purgeFactor + 1); - if (minAccessCount < 2) minAccessCount = 2; - unsigned long long oldAccessTime = m_totalAccessCount - store->maxSegmentCount() / eAgeFactor; - purgeLevel(store, m_prefixes, 0, minAccessCount, oldAccessTime); -} - -void SegCache::purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level, - unsigned long long minAccessCount, unsigned long long oldAccessTime) -{ - if (prefixes.range[SEG_CACHE_MIN_INDEX] == SEG_CACHE_UNSET_INDEX) return; - size_t maxGlyphCached = prefixes.range[SEG_CACHE_MAX_INDEX]; - for (size_t i = prefixes.range[SEG_CACHE_MIN_INDEX]; i <= maxGlyphCached; i++) - { - if (prefixes.array[i].raw) - { - if (level + 1 < ePrefixLength) - purgeLevel(store, prefixes.array[i], level + 1, minAccessCount, oldAccessTime); - else - { - SegCachePrefixEntry * prefixEntry = prefixes.prefixEntries[i]; - m_segmentCount -= prefixEntry->purge(minAccessCount, - oldAccessTime, m_totalAccessCount); - } - } - } -} - -uint32 SegCachePrefixEntry::purge(unsigned long long minAccessCount, - unsigned long long oldAccessTime, - unsigned long long currentTime) -{ - // ignore the purge request if another has been done recently - //if (m_lastPurge > oldAccessTime) - // return 0; - - uint32 totalPurged = 0; - // real length is length + 1 in this loop - for (uint16 length = 0; length < eMaxSpliceSize; length++) - { - if (m_entryCounts[length] == 0) - continue; - uint16 purgeCount = 0; - uint16 newIndex = 0; - for (uint16 j = 0; j < m_entryCounts[length]; j++) - { - SegCacheEntry & tempEntry = m_entries[length][j]; - // purge entries with a low access count which haven't been - // accessed recently - if (tempEntry.accessCount() <= minAccessCount && - tempEntry.lastAccess() <= oldAccessTime) - { - tempEntry.clear(); - ++purgeCount; - } - else - { - memcpy(m_entries[length] + newIndex++, m_entries[length] + j, sizeof(SegCacheEntry)); - } - } - if (purgeCount == m_entryCounts[length]) - { - assert(newIndex == 0); - m_entryCounts[length] = 0; - m_entryBSIndex[length] = 0; - free(m_entries[length]); - m_entries[length] = NULL; - } - else if (purgeCount > 0) - { - assert(m_entryCounts[length] == newIndex + purgeCount); - m_entryCounts[length] = newIndex; - } - totalPurged += purgeCount; - } - m_lastPurge = currentTime; - return totalPurged; -} - -#endif diff --git a/Lib/src/graphite2/src/SegCacheEntry.cpp b/Lib/src/graphite2/src/SegCacheEntry.cpp deleted file mode 100644 index d35912d5ae..0000000000 --- a/Lib/src/graphite2/src/SegCacheEntry.cpp +++ /dev/null @@ -1,108 +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. -*/ - -#ifndef GRAPHITE2_NSEGCACHE - -#include "inc/Main.h" -#include "inc/Slot.h" -#include "inc/Segment.h" -#include "inc/SegCache.h" -#include "inc/SegCacheEntry.h" - - -using namespace graphite2; - -SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime) - : m_glyphLength(0), m_unicode(gralloc(length)), m_glyph(NULL), - m_attr(NULL), m_justs(NULL), - m_accessCount(0), m_lastAccess(cacheTime) -{ - if (m_unicode) - for (uint16 i = 0; i < length; i++) - m_unicode[i] = cmapGlyphs[i]; - - const size_t glyphCount = seg->slotCount(), - sizeof_sjust = SlotJustify::size_of(seg->silf()->numJustLevels()); - if (!glyphCount) return; - size_t num_justs = 0, - justs_pos = 0; - if (seg->hasJustification()) - { - for (const Slot * s = seg->first(); s; s = s->next()) - { - if (s->m_justs == 0) continue; - ++num_justs; - } - m_justs = gralloc(sizeof_sjust * num_justs); - } - const Slot * slot = seg->first(); - m_glyph = new Slot[glyphCount]; - m_attr = gralloc(glyphCount * seg->numAttrs()); - if (!m_glyph || (!m_attr && seg->numAttrs())) return; - m_glyphLength = glyphCount; - Slot * slotCopy = m_glyph; - m_glyph->prev(NULL); - - uint16 pos = 0; - while (slot) - { - slotCopy->userAttrs(m_attr + pos * seg->numAttrs()); - slotCopy->m_justs = m_justs ? reinterpret_cast(m_justs + justs_pos++ * sizeof_sjust) : 0; - slotCopy->set(*slot, -static_cast(charOffset), seg->numAttrs(), seg->silf()->numJustLevels(), length); - slotCopy->index(pos); - if (slot->firstChild()) - slotCopy->m_child = m_glyph + slot->firstChild()->index(); - if (slot->attachedTo()) - slotCopy->attachTo(m_glyph + slot->attachedTo()->index()); - if (slot->nextSibling()) - slotCopy->m_sibling = m_glyph + slot->nextSibling()->index(); - slot = slot->next(); - ++slotCopy; - ++pos; - if (slot) - { - slotCopy->prev(slotCopy-1); - (slotCopy-1)->next(slotCopy); - } - } -} - - -void SegCacheEntry::clear() -{ - free(m_unicode); - free(m_attr); - free(m_justs); - delete [] m_glyph; - m_unicode = NULL; - m_glyph = NULL; - m_glyphLength = 0; - m_attr = NULL; -} - -#endif - diff --git a/Lib/src/graphite2/src/SegCacheStore.cpp b/Lib/src/graphite2/src/SegCacheStore.cpp deleted file mode 100644 index 236fb707ff..0000000000 --- a/Lib/src/graphite2/src/SegCacheStore.cpp +++ /dev/null @@ -1,47 +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. -*/ - -#ifndef GRAPHITE2_NSEGCACHE - -#include "inc/SegCacheStore.h" -#include "inc/Face.h" - - -using namespace graphite2; - -SegCacheStore::SegCacheStore(const Face & face, unsigned int numSilf, size_t maxSegments) -: m_caches(new SilfSegCache[numSilf]), - m_numSilf(numSilf), - m_maxSegments(maxSegments), - m_maxCmapGid(face.glyphs().numGlyphs()), - m_spaceGid(face.cmap()[0x20]), - m_zwspGid(face.cmap()[0x200B]) -{ -} - -#endif - diff --git a/Lib/src/graphite2/src/gr_face.cpp b/Lib/src/graphite2/src/gr_face.cpp index 712aa115fa..baa469727b 100644 --- a/Lib/src/graphite2/src/gr_face.cpp +++ b/Lib/src/graphite2/src/gr_face.cpp @@ -163,14 +163,25 @@ const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId) unsigned short gr_face_n_fref(const gr_face* pFace) { assert(pFace); - return pFace->numFeatures(); + int res = 0; + for (int i = 0; i < pFace->numFeatures(); ++i) + if (!(pFace->feature(i)->getFlags() & FeatureRef::HIDDEN)) + ++res; + return res; } const gr_feature_ref* gr_face_fref(const gr_face* pFace, gr_uint16 i) //When finished with the FeatureRef, call destroy_FeatureRef { assert(pFace); - const FeatureRef* pRef = pFace->feature(i); - return static_cast(pRef); + int count = 0; + for (int j = 0; j < pFace->numFeatures(); ++j) + { + const FeatureRef* pRef = pFace->feature(j); + if (!(pRef->getFlags() & FeatureRef::HIDDEN)) + if (count++ == i) + return static_cast(pRef); + } + return 0; } unsigned short gr_face_n_languages(const gr_face* pFace) diff --git a/Lib/src/graphite2/src/gr_slot.cpp b/Lib/src/graphite2/src/gr_slot.cpp index 21a00fdcd5..a3c6b46a7f 100644 --- a/Lib/src/graphite2/src/gr_slot.cpp +++ b/Lib/src/graphite2/src/gr_slot.cpp @@ -95,8 +95,9 @@ float gr_slot_advance_X(const gr_slot* p/*not NULL*/, const gr_face *face, const if (font) { scale = font->scale(); - if (face && font->isHinted()) - res = (res - face->glyphs().glyph(p->gid())->theAdvance().x) * scale + font->advance(p->gid()); + int gid = p->glyph(); + if (face && font->isHinted() && gid < face->glyphs().numGlyphs()) + res = (res - face->glyphs().glyph(gid)->theAdvance().x) * scale + font->advance(gid); else res = res * scale; } diff --git a/Lib/src/graphite2/src/inc/Bidi.h b/Lib/src/graphite2/src/inc/Bidi.h deleted file mode 100644 index 9593c7e149..0000000000 --- a/Lib/src/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/Lib/src/graphite2/src/inc/FeatureMap.h b/Lib/src/graphite2/src/inc/FeatureMap.h index 142a00e7e9..0f05e941a2 100644 --- a/Lib/src/graphite2/src/inc/FeatureMap.h +++ b/Lib/src/graphite2/src/inc/FeatureMap.h @@ -56,9 +56,12 @@ class FeatureRef static const uint8 SIZEOF_CHUNK = sizeof(chunk_t)*8; public: + enum flags_t : uint16 { + HIDDEN = 0x0800 + }; FeatureRef() throw(); FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val, - uint32 name, uint16 uiName, uint16 flags, + uint32 name, uint16 uiName, flags_t flags, FeatureSetting *settings, uint16 num_set) throw(); ~FeatureRef() throw(); @@ -75,6 +78,7 @@ class FeatureRef uint16 getNumSettings() const { return m_numSet; } uint16 getSettingName(uint16 index) const { return m_nameValues[index].label(); } int16 getSettingValue(uint16 index) const { return m_nameValues[index].value(); } + flags_t getFlags() const { return m_flags; } uint32 maxVal() const { return m_max; } const Face & getFace() const { assert(m_face); return *m_face;} const FeatureMap* getFeatureMap() const;// { return m_pFace;} @@ -88,9 +92,9 @@ class FeatureRef chunk_t m_mask, // bit mask to get the value from the vector m_max; // max value the value can take uint32 m_id; // feature identifier/name - uint16 m_nameid, // Name table id for feature name - m_flags, // feature flags (unused at the moment but read from the font) - m_numSet; // number of values (number of entries in m_nameValues) + uint16 m_nameid, // Name table id for feature name + m_numSet; // number of values (number of entries in m_nameValues) + flags_t m_flags; // feature flags see FeatureRef::flags_t. byte m_bits, // how many bits to shift the value into place m_index; // index into the array to find the ulong to mask @@ -103,8 +107,8 @@ FeatureRef::FeatureRef() throw() : m_face(0), m_nameValues(0), m_mask(0), m_max(0), - m_id(0), - m_nameid(0), m_flags(0), m_numSet(0), + m_id(0), m_nameid(0), m_numSet(0), + m_flags(flags_t(0)), m_bits(0), m_index(0) { } diff --git a/Lib/src/graphite2/src/inc/SegCache.h b/Lib/src/graphite2/src/inc/SegCache.h deleted file mode 100644 index b360f7c933..0000000000 --- a/Lib/src/graphite2/src/inc/SegCache.h +++ /dev/null @@ -1,316 +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 - -#ifndef GRAPHITE2_NSEGCACHE - -#include -#include "inc/Main.h" -#include "inc/Slot.h" -#include "inc/FeatureVal.h" -#include "inc/SegCacheEntry.h" -#include "inc/Segment.h" - -namespace graphite2 { - -class SegCache; -class SegCacheEntry; -class SegCacheStore; - -/** - * SegPrefixEntry stores lists of word/syllable segments - * with one list for each word length. The prefix size should be chosen so that - * these list sizes stay small since they will be searched iteratively. - */ -class SegCachePrefixEntry -{ - SegCachePrefixEntry(const SegCachePrefixEntry &); - SegCachePrefixEntry & operator = (const SegCachePrefixEntry &); - -public: - SegCachePrefixEntry() : m_lastPurge(0) - { - memset(m_entryCounts, 0, sizeof m_entryCounts); - memset(m_entryBSIndex, 0, sizeof m_entryBSIndex); - memset(m_entries, 0, sizeof m_entries); - } - - ~SegCachePrefixEntry() - { - for (size_t j = 0; j < eMaxSpliceSize; j++) - { - if (m_entryCounts[j]) - { - assert(m_entries[j]); - for (size_t k = 0; k < m_entryCounts[j]; k++) - m_entries[j][k].clear(); - - free(m_entries[j]); - } - } - } - const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const - { - if (length <= ePrefixLength) - { - assert(m_entryCounts[length-1] <= 1); - if (m_entries[length-1]) - return m_entries[length-1]; - return NULL; - } - SegCacheEntry * entry = NULL; - findPosition(cmapGlyphs, length, &entry); - return entry; - } - SegCacheEntry * cache(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, unsigned long long totalAccessCount) - { - size_t listSize = m_entryBSIndex[length-1]? (m_entryBSIndex[length-1] << 1) - 1 : 0; - SegCacheEntry * newEntries = NULL; - if (m_entryCounts[length-1] + 1u > listSize) - { - if (m_entryCounts[length-1] == 0) - listSize = 1; - else - { - // the problem comes when you get incremental numeric ids in a large doc - if (listSize >= eMaxSuffixCount) - return NULL; - listSize = (m_entryBSIndex[length-1] << 2) - 1; - } - newEntries = gralloc(listSize); - if (!newEntries) - return NULL; - } - - uint16 insertPos = 0; - if (m_entryCounts[length-1] > 0) - { - insertPos = findPosition(cmapGlyphs, length, NULL); - if (!newEntries) - { - // same buffer, shift entries up - memmove(m_entries[length-1] + insertPos + 1, m_entries[length-1] + insertPos, - sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos)); - } - else - { - memcpy(newEntries, m_entries[length-1], sizeof(SegCacheEntry) * (insertPos)); - memcpy(newEntries + insertPos + 1, m_entries[length-1] + insertPos, - sizeof(SegCacheEntry) * (m_entryCounts[length-1] - insertPos)); - - free(m_entries[length-1]); - m_entries[length-1] = newEntries; - assert (m_entryBSIndex[length-1]); - m_entryBSIndex[length-1] <<= 1; - } - } - else - { - m_entryBSIndex[length-1] = 1; - m_entries[length-1] = newEntries; - } - m_entryCounts[length-1] += 1; - new (m_entries[length-1] + insertPos) - SegCacheEntry(cmapGlyphs, length, seg, charOffset, totalAccessCount); - return m_entries[length-1] + insertPos; - } - uint32 purge(unsigned long long minAccessCount, unsigned long long oldAccessTime, - unsigned long long currentTime); - CLASS_NEW_DELETE -private: - uint16 findPosition(const uint16 * cmapGlyphs, uint16 length, SegCacheEntry ** entry) const - { - int dir = 0; - if (m_entryCounts[length-1] == 0) - { - if (entry) *entry = NULL; - return 0; - } - else if (m_entryCounts[length-1] == 1) - { - // optimize single entry case - for (int i = ePrefixLength; i < length; i++) - { - if (cmapGlyphs[i] > m_entries[length-1][0].m_unicode[i]) - { - return 1; - } - else if (cmapGlyphs[i] < m_entries[length-1][0].m_unicode[i]) - { - return 0; - } - } - if (entry) - *entry = m_entries[length-1]; - return 0; - } - uint16 searchIndex = m_entryBSIndex[length-1] - 1; - uint16 stepSize = m_entryBSIndex[length-1] >> 1; - size_t prevIndex = searchIndex; - do - { - dir = 0; - if (searchIndex >= m_entryCounts[length-1]) - { - dir = -1; - searchIndex -= stepSize; - stepSize >>= 1; - } - else - { - for (int i = ePrefixLength; i < length; i++) - { - if (cmapGlyphs[i] > m_entries[length-1][searchIndex].m_unicode[i]) - { - dir = 1; - searchIndex += stepSize; - stepSize >>= 1; - break; - } - else if (cmapGlyphs[i] < m_entries[length-1][searchIndex].m_unicode[i]) - { - dir = -1; - searchIndex -= stepSize; - stepSize >>= 1; - break; - } - } - } - if (prevIndex == searchIndex) - break; - prevIndex = searchIndex; - } while (dir != 0); - if (entry) - { - if (dir == 0) - *entry = m_entries[length-1] + searchIndex; - else - *entry = NULL; - } - else - { - // if entry is null, then this is for inserting a new value, which - // shouldn't already be in the cache - assert(dir != 0); - if (dir > 0) - ++searchIndex; - } - return searchIndex; - } - /** m_entries is a null terminated list of entries */ - uint16 m_entryCounts[eMaxSpliceSize]; - uint16 m_entryBSIndex[eMaxSpliceSize]; - SegCacheEntry * m_entries[eMaxSpliceSize]; - unsigned long long m_lastPurge; -}; - - -#define SEG_CACHE_MIN_INDEX (store->maxCmapGid()) -#define SEG_CACHE_MAX_INDEX (store->maxCmapGid()+1u) -#define SEG_CACHE_UNSET_INDEX (store->maxCmapGid()+2u) - -union SegCachePrefixArray -{ - void ** raw; - SegCachePrefixArray * array; - SegCachePrefixEntry ** prefixEntries; - uintptr * range; -}; - -class SegCache -{ -public: - SegCache(const SegCacheStore * store, const Features& features); - ~SegCache(); - - const SegCacheEntry * find(const uint16 * cmapGlyphs, size_t length) const; - SegCacheEntry * cache(SegCacheStore * store, const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset); - void purge(SegCacheStore * store); - - long long totalAccessCount() const { return m_totalAccessCount; } - size_t segmentCount() const { return m_segmentCount; } - const Features & features() const { return m_features; } - void clear(SegCacheStore * store); - - CLASS_NEW_DELETE -private: - void freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level); - void purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level, - unsigned long long minAccessCount, unsigned long long oldAccessTime); - - uint16 m_prefixLength; -// uint16 m_maxCachedSegLength; - size_t m_segmentCount; - SegCachePrefixArray m_prefixes; - Features m_features; - mutable unsigned long long m_totalAccessCount; - mutable unsigned long long m_totalMisses; - float m_purgeFactor; -}; - -inline const SegCacheEntry * SegCache::find(const uint16 * cmapGlyphs, size_t length) const -{ - uint16 pos = 0; - if (!length || length > eMaxSpliceSize) return NULL; - SegCachePrefixArray pEntry = m_prefixes.array[cmapGlyphs[0]]; - while (++pos < m_prefixLength - 1) - { - if (!pEntry.raw) - { - ++m_totalMisses; - return NULL; - } - pEntry = pEntry.array[(pos < length)? cmapGlyphs[pos] : 0]; - } - if (!pEntry.raw) - { - ++m_totalMisses; - return NULL; - } - SegCachePrefixEntry * prefixEntry = pEntry.prefixEntries[(pos < length)? cmapGlyphs[pos] : 0]; - if (!prefixEntry) - { - ++m_totalMisses; - return NULL; - } - const SegCacheEntry * entry = prefixEntry->find(cmapGlyphs, length); - if (entry) - { - ++m_totalAccessCount; - entry->accessed(m_totalAccessCount); - } - else - { - ++m_totalMisses; - } - return entry; -} - -} // namespace graphite2 - -#endif - diff --git a/Lib/src/graphite2/src/inc/SegCacheEntry.h b/Lib/src/graphite2/src/inc/SegCacheEntry.h deleted file mode 100644 index 9a7d930677..0000000000 --- a/Lib/src/graphite2/src/inc/SegCacheEntry.h +++ /dev/null @@ -1,121 +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 - -#ifndef GRAPHITE2_NSEGCACHE - -#include "inc/Main.h" -#include "inc/Slot.h" - -namespace graphite2 { - -class Segment; -class Slot; -class SegCacheEntry; -class SegCachePrefixEntry; - -enum SegCacheParameters { - /** number of characters used in initial prefix tree */ - ePrefixLength = 2, - /** Segments more recent than maxSegmentCount() / eAgeFactor are kept */ - eAgeFactor = 4, - /** Segments are purged according to the formular: - * accessCount < (totalAccesses)/(ePurgeFactor * maxSegments) */ - ePurgeFactor = 5, - /** Maximum number of Segments to store which have the same - * prefix. Needed to prevent unique identifiers flooding the cache */ - eMaxSuffixCount = 15 - -}; - -class SegCacheCharInfo -{ -public: - uint16 m_unicode; - uint16 m_before; - uint16 m_after; -}; - -/** - * SegCacheEntry stores the result of running the engine for specific unicode - * code points in the typical mid-line situation. - */ -class SegCacheEntry -{ - // Prevent any implict copying; - SegCacheEntry(const SegCacheEntry &); - SegCacheEntry & operator = (const SegCacheEntry &); - - friend class SegCachePrefixEntry; -public: - SegCacheEntry() : - m_glyphLength(0), m_unicode(NULL), m_glyph(NULL), m_attr(NULL), m_justs(0), - m_accessCount(0), m_lastAccess(0) - {} - SegCacheEntry(const uint16 * cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime); - ~SegCacheEntry() { clear(); }; - void clear(); - size_t glyphLength() const { return m_glyphLength; } - const Slot * first() const { return m_glyph; } - const Slot * last() const { return m_glyph + (m_glyphLength - 1); } - - /** Total number of times this entry has been accessed since creation */ - unsigned long long accessCount() const { return m_accessCount; } - /** "time" of last access where "time" is measured in accesses to the cache owning this entry */ - void accessed(unsigned long long cacheTime) const - { - m_lastAccess = cacheTime; ++m_accessCount; - }; - - int compareRank(const SegCacheEntry & entry) const - { - if (m_accessCount > entry.m_accessCount) return 1; - else if (m_accessCount < entry.m_accessCount) return 1; - else if (m_lastAccess > entry.m_lastAccess) return 1; - else if (m_lastAccess < entry.m_lastAccess) return -1; - return 0; - } - unsigned long long lastAccess() const { return m_lastAccess; }; - - CLASS_NEW_DELETE; -private: - - size_t m_glyphLength; - /** glyph ids resulting from cmap mapping from unicode to glyph before substitution - * the length of this array is determined by the position in the SegCachePrefixEntry */ - uint16 * m_unicode; - /** slots after shapping and positioning */ - Slot * m_glyph; - int16 * m_attr; - byte * m_justs; - mutable unsigned long long m_accessCount; - mutable unsigned long long m_lastAccess; -}; - -} // namespace graphite2 - -#endif diff --git a/Lib/src/graphite2/src/inc/SegCacheStore.h b/Lib/src/graphite2/src/inc/SegCacheStore.h deleted file mode 100644 index 1e6a6e216e..0000000000 --- a/Lib/src/graphite2/src/inc/SegCacheStore.h +++ /dev/null @@ -1,127 +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 - -#ifndef GRAPHITE2_NSEGCACHE - -#include "inc/Main.h" -#include "inc/CmapCache.h" -#include "inc/SegCache.h" - -namespace graphite2 { - -class SegCache; -class Face; - -class SilfSegCache -{ - SilfSegCache(const SilfSegCache &); - SilfSegCache & operator = (const SilfSegCache &); - -public: - SilfSegCache() : m_caches(NULL), m_cacheCount(0) {}; - ~SilfSegCache() - { - assert(m_caches == NULL); - } - void clear(SegCacheStore * cacheStore) - { - for (size_t i = 0; i < m_cacheCount; i++) - { - m_caches[i]->clear(cacheStore); - delete m_caches[i]; - } - free(m_caches); - m_caches = NULL; - m_cacheCount = 0; - } - SegCache * getOrCreate(SegCacheStore * cacheStore, const Features & features) - { - for (size_t i = 0; i < m_cacheCount; i++) - { - if (m_caches[i]->features() == features) - return m_caches[i]; - } - SegCache ** newData = gralloc(m_cacheCount+1); - if (newData) - { - if (m_cacheCount > 0) - { - memcpy(newData, m_caches, sizeof(SegCache*) * m_cacheCount); - free(m_caches); - } - m_caches = newData; - m_caches[m_cacheCount] = new SegCache(cacheStore, features); - m_cacheCount++; - return m_caches[m_cacheCount - 1]; - } - return NULL; - } - CLASS_NEW_DELETE -private: - SegCache ** m_caches; - size_t m_cacheCount; -}; - -class SegCacheStore -{ - SegCacheStore(const SegCacheStore &); - SegCacheStore & operator = (const SegCacheStore &); - -public: - SegCacheStore(const Face & face, unsigned int numSilf, size_t maxSegments); - ~SegCacheStore() - { - for (size_t i = 0; i < m_numSilf; i++) - { - m_caches[i].clear(this); - } - delete [] m_caches; - m_caches = NULL; - } - SegCache * getOrCreate(unsigned int i, const Features & features) - { - return m_caches[i].getOrCreate(this, features); - } - bool isSpaceGlyph(uint16 gid) const { return (gid == m_spaceGid) || (gid == m_zwspGid); } - uint16 maxCmapGid() const { return m_maxCmapGid; } - uint32 maxSegmentCount() const { return m_maxSegments; }; - - CLASS_NEW_DELETE -private: - SilfSegCache * m_caches; - uint8 m_numSilf; - uint32 m_maxSegments; - uint16 m_maxCmapGid; - uint16 m_spaceGid; - uint16 m_zwspGid; -}; - -} // namespace graphite2 - -#endif -