LCOV - code coverage report
Current view: directory - gfx/graphite2/src - Bidi.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 180 0 0.0 %
Date: 2012-06-02 Functions: 14 0 0.0 %

       1                 : /*  GRAPHITE2 LICENSING
       2                 : 
       3                 :     Copyright 2010, SIL International
       4                 :     All rights reserved.
       5                 : 
       6                 :     This library is free software; you can redistribute it and/or modify
       7                 :     it under the terms of the GNU Lesser General Public License as published
       8                 :     by the Free Software Foundation; either version 2.1 of License, or
       9                 :     (at your option) any later version.
      10                 : 
      11                 :     This program is distributed in the hope that it will be useful,
      12                 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :     Lesser General Public License for more details.
      15                 : 
      16                 :     You should also have received a copy of the GNU Lesser General Public
      17                 :     License along with this library in the file named "LICENSE".
      18                 :     If not, write to the Free Software Foundation, 51 Franklin Street,
      19                 :     suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
      20                 :     internet at http://www.fsf.org/licenses/lgpl.html.
      21                 : 
      22                 : Alternatively, the contents of this file may be used under the terms of the
      23                 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
      24                 : License, as published by the Free Software Foundation, either version 2
      25                 : of the License or (at your option) any later version.
      26                 : */
      27                 : #include "inc/Main.h"
      28                 : #include "inc/Slot.h"
      29                 : #include "inc/Segment.h"
      30                 : 
      31                 : using namespace graphite2;
      32                 : 
      33                 : enum DirCode {  // Hungarian: dirc
      34                 :         Unk        = -1,
      35                 :         N          =  0,   // other neutrals (default) - ON
      36                 :         L          =  1,   // left-to-right, strong - L
      37                 :         R          =  2,   // right-to-left, strong - R
      38                 :         AL         =  3,   // Arabic letter, right-to-left, strong, AR
      39                 :         EN         =  4,   // European number, left-to-right, weak - EN
      40                 :         ES         =  5,   // European separator, left-to-right, weak - ES
      41                 :         ET         =  6,   // European number terminator, left-to-right, weak - ET
      42                 :         AN         =  7,   // Arabic number, left-to-right, weak - AN
      43                 :         CS         =  8,   // Common number separator, left-to-right, weak - CS
      44                 :         WS         =  9,   // white space, neutral - WS
      45                 :         BN         = 10,   // boundary neutral - BN
      46                 : 
      47                 :         LRO        = 11,   // LTR override
      48                 :         RLO        = 12,   // RTL override
      49                 :         LRE        = 13,   // LTR embedding
      50                 :         RLE        = 14,   // RTL embedding
      51                 :         PDF        = 15,   // pop directional format
      52                 :         NSM        = 16,   // non-space mark
      53                 : 
      54                 :         ON = N
      55                 : };
      56                 : 
      57                 : enum DirMask {
      58                 :     Nmask = 1,
      59                 :     Lmask = 2,
      60                 :     Rmask = 4,
      61                 :     ALmask = 8,
      62                 :     ENmask = 0x10,
      63                 :     ESmask = 0x20,
      64                 :     ETmask = 0x40,
      65                 :     ANmask = 0x80,
      66                 :     CSmask = 0x100,
      67                 :     WSmask = 0x200,
      68                 :     BNmask = 0x400,
      69                 :     LROmask = 0x800,
      70                 :     RLOmask = 0x1000,
      71                 :     LREmask = 0x2000,
      72                 :     RLEmask = 0x4000,
      73                 :     PDFmask = 0x8000,
      74                 :     NSMmask = 0x10000
      75                 : };
      76                 : 
      77                 : unsigned int bidi_class_map[] = { 0, 1, 2, 5, 4, 8, 9, 3, 7, 0, 0, 0, 0, 0, 0, 0, 6 };
      78                 : // Algorithms based on Unicode reference standard code. Thanks Asmus Freitag.
      79                 : #define MAX_LEVEL 61
      80                 : 
      81               0 : Slot *resolveExplicit(int level, int dir, Slot *s, int nNest = 0)
      82                 : {
      83               0 :     int nLastValid = nNest;
      84               0 :     Slot *res = NULL;
      85               0 :     for ( ; s && !res; s = s->next())
      86                 :     {
      87               0 :         int cls = s->getBidiClass();
      88               0 :         switch(cls)
      89                 :         {
      90                 :         case LRO:
      91                 :         case LRE:
      92               0 :             nNest++;
      93               0 :             if (level & 1)
      94               0 :                 s->setBidiLevel(level + 1);
      95                 :             else
      96               0 :                 s->setBidiLevel(level + 2);
      97               0 :             if (s->getBidiLevel() > MAX_LEVEL)
      98               0 :                 s->setBidiLevel(level);
      99                 :             else
     100                 :             {
     101               0 :                 s = resolveExplicit(s->getBidiLevel(), (cls == LRE ? N : L), s->next(), nNest);
     102               0 :                 nNest--;
     103               0 :                 if (s) continue; else break;
     104                 :             }
     105               0 :             cls = BN;
     106               0 :             s->setBidiClass(cls);
     107               0 :             break;
     108                 : 
     109                 :         case RLO:
     110                 :         case RLE:
     111               0 :             nNest++;
     112               0 :             if (level & 1)
     113               0 :                 s->setBidiLevel(level + 2);
     114                 :             else
     115               0 :                 s->setBidiLevel(level + 1);
     116               0 :             if (s->getBidiLevel() > MAX_LEVEL)
     117               0 :                 s->setBidiLevel(level);
     118                 :             else
     119                 :             {
     120               0 :                 s = resolveExplicit(s->getBidiLevel(), (cls == RLE ? N : R), s->next(), nNest);
     121               0 :                 nNest--;
     122               0 :                 if (s) continue; else break;
     123                 :             }
     124               0 :             cls = BN;
     125               0 :             s->setBidiClass(cls);
     126               0 :             break;
     127                 : 
     128                 :         case PDF:
     129               0 :             cls = BN;
     130               0 :             s->setBidiClass(cls);
     131               0 :             if (nNest)
     132                 :             {
     133               0 :                 if (nLastValid < nNest)
     134               0 :                     --nNest;
     135                 :                 else
     136               0 :                     res = s;
     137                 :             }
     138               0 :             break;
     139                 :         }
     140                 : 
     141               0 :         if (dir != N)
     142               0 :             cls = dir;
     143               0 :         if (s)
     144                 :         {
     145               0 :             s->setBidiLevel(level);
     146               0 :             if (s->getBidiClass() != BN)
     147               0 :                 s->setBidiClass(cls);
     148                 :         }
     149                 :         else
     150               0 :             break;
     151                 :     }
     152               0 :     return res;
     153                 : }
     154                 : 
     155                 : // === RESOLVE WEAK TYPES ================================================
     156                 : 
     157                 : enum bidi_state // possible states
     158                 : {
     159                 :         xa,             //      arabic letter
     160                 :         xr,             //      right leter
     161                 :         xl,             //      left letter
     162                 : 
     163                 :         ao,             //      arabic lett. foll by ON
     164                 :         ro,             //      right lett. foll by ON
     165                 :         lo,             //      left lett. foll by ON
     166                 : 
     167                 :         rt,             //      ET following R
     168                 :         lt,             //      ET following L
     169                 : 
     170                 :         cn,             //      EN, AN following AL
     171                 :         ra,             //      arabic number foll R
     172                 :         re,             //      european number foll R
     173                 :         la,             //      arabic number foll L
     174                 :         le,             //      european number foll L
     175                 : 
     176                 :         ac,             //      CS following cn
     177                 :         rc,             //      CS following ra
     178                 :         rs,             //      CS,ES following re
     179                 :         lc,             //      CS following la
     180                 :         ls,             //      CS,ES following le
     181                 : 
     182                 :         ret,            //      ET following re
     183                 :         let,            //      ET following le
     184                 : } ;
     185                 : 
     186                 : enum bidi_state_mask
     187                 : {
     188                 :     xamask = 1,
     189                 :     xrmask = 2,
     190                 :     xlmask = 4,
     191                 :     aomask = 8,
     192                 :     romask = 0x10,
     193                 :     lomask = 0x20,
     194                 :     rtmask = 0x40,
     195                 :     ltmask = 0x80,
     196                 :     cnmask = 0x100,
     197                 :     ramask = 0x200,
     198                 :     remask = 0x400,
     199                 :     lamask = 0x800,
     200                 :     lemask = 0x1000,
     201                 :     acmask = 0x2000,
     202                 :     rcmask = 0x4000,
     203                 :     rsmask = 0x8000,
     204                 :     lcmask = 0x10000,
     205                 :     lsmask = 0x20000,
     206                 :     retmask = 0x40000,
     207                 :     letmask = 0x80000
     208                 : };
     209                 : 
     210                 : const bidi_state stateWeak[][10] =
     211                 : {
     212                 :         //      N,  L,  R,  AN, EN, AL,NSM, CS, ES, ET,
     213                 : { /*xa*/        ao, xl, xr, cn, cn, xa, xa, ao, ao, ao, /* arabic letter          */ },
     214                 : { /*xr*/        ro, xl, xr, ra, re, xa, xr, ro, ro, rt, /* right letter           */ },
     215                 : { /*xl*/        lo, xl, xr, la, le, xa, xl, lo, lo, lt, /* left letter            */ },
     216                 : 
     217                 : { /*ao*/        ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* arabic lett. foll by ON*/ },
     218                 : { /*ro*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* right lett. foll by ON */ },
     219                 : { /*lo*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* left lett. foll by ON  */ },
     220                 : 
     221                 : { /*rt*/        ro, xl, xr, ra, re, xa, rt, ro, ro, rt, /* ET following R         */ },
     222                 : { /*lt*/        lo, xl, xr, la, le, xa, lt, lo, lo, lt, /* ET following L         */ },
     223                 : 
     224                 : { /*cn*/        ao, xl, xr, cn, cn, xa, cn, ac, ao, ao, /* EN, AN following AL    */ },
     225                 : { /*ra*/        ro, xl, xr, ra, re, xa, ra, rc, ro, rt, /* arabic number foll R   */ },
     226                 : { /*re*/        ro, xl, xr, ra, re, xa, re, rs, rs,ret, /* european number foll R */ },
     227                 : { /*la*/        lo, xl, xr, la, le, xa, la, lc, lo, lt, /* arabic number foll L   */ },
     228                 : { /*le*/        lo, xl, xr, la, le, xa, le, ls, ls,let, /* european number foll L */ },
     229                 : 
     230                 : { /*ac*/        ao, xl, xr, cn, cn, xa, ao, ao, ao, ao, /* CS following cn        */ },
     231                 : { /*rc*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS following ra        */ },
     232                 : { /*rs*/        ro, xl, xr, ra, re, xa, ro, ro, ro, rt, /* CS,ES following re     */ },
     233                 : { /*lc*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS following la        */ },
     234                 : { /*ls*/        lo, xl, xr, la, le, xa, lo, lo, lo, lt, /* CS,ES following le     */ },
     235                 : 
     236                 : { /*ret*/ ro, xl, xr, ra, re, xa,ret, ro, ro,ret, /* ET following re              */ },
     237                 : { /*let*/ lo, xl, xr, la, le, xa,let, lo, lo,let, /* ET following le              */ },
     238                 : 
     239                 : 
     240                 : };
     241                 : 
     242                 : enum bidi_action // possible actions
     243                 : {
     244                 :         // primitives
     245                 :         IX = 0x100,                     // increment
     246                 :         XX = 0xF,                       // no-op
     247                 : 
     248                 :         // actions
     249                 :         xxx = (XX << 4) + XX,           // no-op
     250                 :         xIx = IX + xxx,                         // increment run
     251                 :         xxN = (XX << 4) + ON,           // set current to N
     252                 :         xxE = (XX << 4) + EN,           // set current to EN
     253                 :         xxA = (XX << 4) + AN,           // set current to AN
     254                 :         xxR = (XX << 4) + R,            // set current to R
     255                 :         xxL = (XX << 4) + L,            // set current to L
     256                 :         Nxx = (ON << 4) + 0xF,          // set run to neutral
     257                 :         Axx = (AN << 4) + 0xF,          // set run to AN
     258                 :         ExE = (EN << 4) + EN,           // set run to EN, set current to EN
     259                 :         NIx = (ON << 4) + 0xF + IX,     // set run to N, increment
     260                 :         NxN = (ON << 4) + ON,           // set run to N, set current to N
     261                 :         NxR = (ON << 4) + R,            // set run to N, set current to R
     262                 :         NxE = (ON << 4) + EN,           // set run to N, set current to EN
     263                 : 
     264                 :         AxA = (AN << 4) + AN,           // set run to AN, set current to AN
     265                 :         NxL = (ON << 4) + L,            // set run to N, set current to L
     266                 :         LxL = (L << 4) + L,             // set run to L, set current to L
     267                 : };
     268                 : 
     269                 : 
     270                 : const bidi_action actionWeak[][10] =
     271                 : {
     272                 :           //   N,.. L,   R,  AN,  EN,  AL, NSM,  CS,..ES,  ET,
     273                 : { /*xa*/ xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN, /* arabic letter             */ },
     274                 : { /*xr*/ xxx, xxx, xxx, xxx, xxE, xxR, xxR, xxN, xxN, xIx, /* right leter               */ },
     275                 : { /*xl*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xIx, /* left letter               */ },
     276                 : 
     277                 : { /*ao*/ xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN, /* arabic lett. foll by ON   */ },
     278                 : { /*ro*/ xxx, xxx, xxx, xxx, xxE, xxR, xxN, xxN, xxN, xIx, /* right lett. foll by ON    */ },
     279                 : { /*lo*/ xxx, xxx, xxx, xxx, xxL, xxR, xxN, xxN, xxN, xIx, /* left lett. foll by ON     */ },
     280                 : 
     281                 : { /*rt*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, xIx, NxN, NxN, xIx, /* ET following R            */ },
     282                 : { /*lt*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, xIx, NxN, NxN, xIx, /* ET following L            */ },
     283                 : 
     284                 : { /*cn*/ xxx, xxx, xxx, xxx, xxA, xxR, xxA, xIx, xxN, xxN, /* EN, AN following  AL      */ },
     285                 : { /*ra*/ xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx, /* arabic number foll R      */ },
     286                 : { /*re*/ xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE, /* european number foll R    */ },
     287                 : { /*la*/ xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx, /* arabic number foll L      */ },
     288                 : { /*le*/ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL, /* european number foll L    */ },
     289                 : 
     290                 : { /*ac*/ Nxx, Nxx, Nxx, Axx, AxA, NxR, NxN, NxN, NxN, NxN, /* CS following cn           */ },
     291                 : { /*rc*/ Nxx, Nxx, Nxx, Axx, NxE, NxR, NxN, NxN, NxN, NIx, /* CS following ra           */ },
     292                 : { /*rs*/ Nxx, Nxx, Nxx, Nxx, ExE, NxR, NxN, NxN, NxN, NIx, /* CS,ES following re        */ },
     293                 : { /*lc*/ Nxx, Nxx, Nxx, Axx, NxL, NxR, NxN, NxN, NxN, NIx, /* CS following la           */ },
     294                 : { /*ls*/ Nxx, Nxx, Nxx, Nxx, LxL, NxR, NxN, NxN, NxN, NIx, /* CS,ES following le        */ },
     295                 : 
     296                 : { /*ret*/xxx, xxx, xxx, xxx, xxE, xxR, xxE, xxN, xxN, xxE, /* ET following re           */ },
     297                 : { /*let*/xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xxL, /* ET following le           */ },
     298                 : };
     299                 : 
     300               0 : inline uint8    GetDeferredType(bidi_action a)          { return (a >> 4) & 0xF; }
     301               0 : inline uint8    GetResolvedType(bidi_action a)          { return a & 0xF; }
     302               0 : inline DirCode  EmbeddingDirection(int l)               { return l & 1 ? R : L; }
     303                 : inline bool     IsDeferredState(bidi_state a)           { return (1 << a) & (rtmask | ltmask | acmask | rcmask | rsmask | lcmask | lsmask); }
     304                 : inline bool     IsModifiedClass(DirCode a)              { return (1 << a) & (ALmask | NSMmask | ESmask | CSmask | ETmask | ENmask); }
     305                 : 
     306               0 : void SetDeferredRunClass(Slot *s, Slot *sRun, int nval)
     307                 : {
     308               0 :     if (!sRun || s == sRun) return;
     309               0 :     for (Slot *p = s->prev(); p != sRun; p = p->prev())
     310               0 :         p->setBidiClass(nval);
     311                 : }
     312                 : 
     313               0 : void resolveWeak(int baseLevel, Slot *s)
     314                 : {
     315               0 :     int state = (baseLevel & 1) ? xr : xl;
     316                 :     int cls;
     317               0 :     int level = baseLevel;
     318               0 :     Slot *sRun = NULL;
     319               0 :     Slot *sLast = s;
     320                 : 
     321               0 :     for ( ; s; s = s->next())
     322                 :     {
     323               0 :         sLast = s;
     324               0 :         cls = s->getBidiClass();
     325               0 :         if (cls == BN)
     326                 :         {
     327               0 :             s->setBidiLevel(level);
     328               0 :             if (!s->next() && level != baseLevel)
     329               0 :                 s->setBidiClass(EmbeddingDirection(level));
     330               0 :             else if (s->next() && level != s->next()->getBidiLevel() && s->next()->getBidiClass() != BN)
     331                 :             {
     332               0 :                 int newLevel = s->next()->getBidiLevel();
     333               0 :                 if (level > newLevel)
     334               0 :                     newLevel = level;
     335               0 :                 s->setBidiLevel(newLevel);
     336               0 :                 s->setBidiClass(EmbeddingDirection(newLevel));
     337               0 :                 level  = s->next()->getBidiLevel();
     338                 :             }
     339                 :             else
     340               0 :                 continue;
     341                 :         }
     342                 : 
     343               0 :         bidi_action action = actionWeak[state][bidi_class_map[cls]];
     344               0 :         int clsRun = GetDeferredType(action);
     345               0 :         if (clsRun != XX)
     346                 :         {
     347               0 :             SetDeferredRunClass(s, sRun, clsRun);
     348               0 :             sRun = NULL;
     349                 :         }
     350               0 :         int clsNew = GetResolvedType(action);
     351               0 :         if (clsNew != XX)
     352               0 :             s->setBidiClass(clsNew);
     353               0 :         if (!sRun && (IX & action))
     354               0 :             sRun = s->prev();
     355               0 :         state = stateWeak[state][bidi_class_map[cls]];
     356                 :     }
     357                 : 
     358               0 :     cls = EmbeddingDirection(level);
     359               0 :     int clsRun = GetDeferredType(actionWeak[state][bidi_class_map[cls]]);
     360               0 :     if (clsRun != XX)
     361               0 :         SetDeferredRunClass(sLast, sRun, clsRun);
     362               0 : }
     363                 : 
     364                 : // Neutrals
     365                 : enum neutral_action
     366                 : {
     367                 :         // action to resolve previous input
     368                 :         nL = L,         // resolve EN to L
     369                 :         En = 3 << 4,    // resolve neutrals run to embedding level direction
     370                 :         Rn = R << 4,    // resolve neutrals run to strong right
     371                 :         Ln = L << 4,    // resolved neutrals run to strong left
     372                 :         In = (1<<8),    // increment count of deferred neutrals
     373                 :         LnL = (1<<4)+L, // set run and EN to L
     374                 : };
     375                 : 
     376               0 : int GetDeferredNeutrals(int action, int level)
     377                 : {
     378               0 :         action = (action >> 4) & 0xF;
     379               0 :         if (action == (En >> 4))
     380               0 :             return EmbeddingDirection(level);
     381                 :         else
     382               0 :             return action;
     383                 : }
     384                 : 
     385               0 : int GetResolvedNeutrals(int action)
     386                 : {
     387               0 :         action = action & 0xF;
     388               0 :         if (action == In)
     389               0 :             return 0;
     390                 :         else
     391               0 :             return action;
     392                 : }
     393                 : 
     394                 : // state values
     395                 : enum neutral_state
     396                 : {
     397                 :         // new temporary class
     398                 :         r,  // R and characters resolved to R
     399                 :         l,  // L and characters resolved to L
     400                 :         rn, // N preceded by right
     401                 :         ln, // N preceded by left
     402                 :         a,  // AN preceded by left (the abbrev 'la' is used up above)
     403                 :         na, // N preceeded by a
     404                 : } ;
     405                 : 
     406                 : const uint8 neutral_class_map[] = { 0, 1, 2, 0, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 };
     407                 : 
     408                 : const int actionNeutrals[][5] =
     409                 : {
     410                 : //      N,      L,      R, AN, EN, = cls
     411                 :                                 // state =
     412                 : {       In,  0,  0,  0,  0, },  // r    right
     413                 : {       In,  0,  0,  0,  L, },  // l    left
     414                 : 
     415                 : {       In, En, Rn, Rn, Rn, },  // rn   N preceded by right
     416                 : {       In, Ln, En, En, LnL, }, // ln   N preceded by left
     417                 : 
     418                 : {       In,  0,  0,  0,  L, },  // a   AN preceded by left
     419                 : {       In, En, Rn, Rn, En, },  // na   N  preceded by a
     420                 : } ;
     421                 : 
     422                 : const int stateNeutrals[][5] =
     423                 : {
     424                 : //       N, L,  R,      AN, EN = cls
     425                 :                                                 // state =
     426                 : {       rn, l,  r,      r,      r, },           // r   right
     427                 : {       ln, l,  r,      a,      l, },           // l   left
     428                 : 
     429                 : {       rn, l,  r,      r,      r, },           // rn  N preceded by right
     430                 : {       ln, l,  r,      a,      l, },           // ln  N preceded by left
     431                 : 
     432                 : {       na, l,  r,      a,      l, },           // a  AN preceded by left
     433                 : {       na, l,  r,      a,      l, },           // na  N preceded by la
     434                 : } ;
     435                 : 
     436               0 : void resolveNeutrals(int baseLevel, Slot *s)
     437                 : {
     438               0 :     int state = baseLevel ? r : l;
     439                 :     int cls;
     440               0 :     Slot *sRun = NULL;
     441               0 :     Slot *sLast = s;
     442               0 :     int level = baseLevel;
     443                 : 
     444               0 :     for ( ; s; s = s->next())
     445                 :     {
     446               0 :         sLast = s;
     447               0 :         cls = s->getBidiClass();
     448               0 :         if (cls == BN)
     449                 :         {
     450               0 :             if (sRun)
     451               0 :                 sRun = sRun->prev();
     452               0 :             continue;
     453                 :         }
     454                 : 
     455               0 :         int action = actionNeutrals[state][neutral_class_map[cls]];
     456               0 :         int clsRun = GetDeferredNeutrals(action, level);
     457               0 :         if (clsRun != N)
     458                 :         {
     459               0 :             SetDeferredRunClass(s, sRun, clsRun);
     460               0 :             sRun = NULL;
     461                 :         }
     462               0 :         int clsNew = GetResolvedNeutrals(action);
     463               0 :         if (clsNew != N)
     464               0 :             s->setBidiClass(clsNew);
     465               0 :         state = stateNeutrals[state][neutral_class_map[cls]];
     466               0 :         level = s->getBidiLevel();
     467                 :     }
     468               0 :     cls = EmbeddingDirection(level);
     469               0 :     int clsRun = GetDeferredNeutrals(actionNeutrals[state][neutral_class_map[cls]], level);
     470               0 :     if (clsRun != N)
     471               0 :         SetDeferredRunClass(sLast, sRun, clsRun);
     472               0 : }
     473                 : 
     474                 : const int addLevel[][4] =
     475                 : {
     476                 :                 //    L,  R,    AN, EN = cls
     477                 :                                                 // level =
     478                 : /* even */      { 0,    1,      2,      2, },   // EVEN
     479                 : /* odd  */      { 1,    0,      1,      1, },   // ODD
     480                 : 
     481                 : };
     482                 : 
     483               0 : void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror)
     484                 : {
     485               0 :     bool rtl = seg->dir() & 1;
     486               0 :     for ( ; s; s = s->next())
     487                 :     {
     488               0 :         int cls = s->getBidiClass();
     489               0 :         if (cls == BN)
     490               0 :             continue;
     491               0 :         else if (cls == AN)
     492               0 :             cls = AL;
     493               0 :         if (cls < 5 && cls > 0)
     494                 :         {
     495               0 :             int level = s->getBidiLevel();
     496               0 :             level += addLevel[level & 1][cls - 1];
     497               0 :             s->setBidiLevel(level);
     498               0 :             if (aMirror)
     499                 :             {
     500               0 :                 int hasChar = seg->glyphAttr(s->gid(), aMirror + 1);
     501               0 :                 if ( ((level & 1) && (!(seg->dir() & 4) || !hasChar)) 
     502               0 :                   || ((rtl ^ (level & 1)) && (seg->dir() & 4) && hasChar) )
     503                 :                 {
     504               0 :                     unsigned short g = seg->glyphAttr(s->gid(), aMirror);
     505               0 :                     if (g) s->setGlyph(seg, g);
     506                 :                 }
     507                 :             }
     508                 :         }
     509                 :     }
     510               0 : }
     511                 : 
     512               0 : void resolveWhitespace(int baseLevel, Segment *seg, uint8 aBidi, Slot *s)
     513                 : {
     514               0 :     for ( ; s; s = s->prev())
     515                 :     {
     516               0 :         int cls = seg->glyphAttr(s->gid(), aBidi);
     517               0 :         if (cls == WS)
     518               0 :             s->setBidiLevel(baseLevel);
     519                 :         else
     520               0 :             break;
     521                 :     }
     522               0 : }
     523                 : 
     524                 : 
     525                 : inline
     526               0 : Slot * join(int level, Slot * a, Slot * b)
     527                 : {
     528               0 :     if (!a) return b;
     529               0 :     if (level & 1)  { Slot * const t = a; a = b; b = t; }
     530               0 :     Slot * const t = b->prev();
     531               0 :     a->prev()->next(b); b->prev(a->prev()); // splice middle
     532               0 :     t->next(a); a->prev(t);                 // splice ends
     533               0 :     return a;
     534                 : }
     535                 : 
     536                 : 
     537               0 : Slot * span(Slot * & cs, const bool rtl)
     538                 : {
     539               0 :     Slot * r = cs, * re = cs; cs = cs->next();
     540               0 :     if (rtl)
     541                 :     {
     542               0 :         Slot * t = r->next(); r->next(r->prev()); r->prev(t);
     543               0 :         for (int l = r->getBidiLevel(); cs && l == cs->getBidiLevel(); cs = cs->prev())
     544                 :         {
     545               0 :             re = cs;
     546               0 :             t = cs->next(); cs->next(cs->prev()); cs->prev(t);
     547                 :         }
     548               0 :         r->next(re);
     549               0 :         re->prev(r);
     550               0 :         r = re;
     551                 :     }
     552                 :     else
     553                 :     {
     554               0 :         for (int l = r->getBidiLevel(); cs && l == cs->getBidiLevel(); cs = cs->next())
     555               0 :             re = cs;
     556               0 :         r->prev(re);
     557               0 :         re->next(r);
     558                 :     }
     559               0 :     if (cs) cs->prev(0);
     560               0 :     return r;
     561                 : }
     562                 : 
     563                 : 
     564               0 : Slot *resolveOrder(Slot * & cs, const bool reordered, const int level)
     565                 : {
     566               0 :     Slot * r = 0;
     567                 :     int ls;
     568               0 :     while (cs && level <= (ls = cs->getBidiLevel() - reordered))
     569                 :     {
     570                 :         r = join(level, r, level >= ls
     571               0 :                                 ? span(cs, level & 1)
     572               0 :                                 : resolveOrder(cs, reordered, level+1));
     573                 :     }
     574               0 :     return r;
     575                 : }
     576                 : 

Generated by: LCOV version 1.7