/*------------------------------------------------------------------------ Function: resolveWeak Resolves the directionality of numeric and other weak character types Implements rules X10 and W1-W6 of the Unicode Bidirectional Algorithm. Input: Array of embedding levels Character count In/Out: Array of directional classes Note: On input only these directional classes are expected AL, HL, R, L, ON, BN, NSM, AN, EN, ES, ET, CS, ------------------------------------------------------------------------*/ static void resolveWeak(int baselevel, WORD *pcls, WORD *plevel, int cch) { int state = odd(baselevel) ? xr : xl; int cls; int level = baselevel; int action, clsRun, clsNew; int cchRun = 0; int ich = 0; for (; ich < cch; ich++) { /* ignore boundary neutrals */ if (pcls[ich] == BN) { /* must flatten levels unless at a level change; */ plevel[ich] = level; /* lookahead for level changes */ if (ich + 1 == cch && level != baselevel) { /* have to fixup last BN before end of the loop, since * its fix-upped value will be needed below the assert */ pcls[ich] = EmbeddingDirection(level); } else if (ich + 1 < cch && level != plevel[ich+1] && pcls[ich+1] != BN) { /* fixup LAST BN in front / after a level run to make * it act like the SOR/EOR in rule X10 */ int newlevel = plevel[ich+1]; if (level > newlevel) { newlevel = level; } plevel[ich] = newlevel; /* must match assigned level */ pcls[ich] = EmbeddingDirection(newlevel); level = plevel[ich+1]; } else { /* don't interrupt runs */ if (cchRun) { cchRun++; } continue; } } ASSERT(pcls[ich] <= BN); cls = pcls[ich]; action = actionWeak[state][cls]; /* resolve the directionality for deferred runs */ clsRun = GetDeferredType(action); if (clsRun != XX) { SetDeferredRun(pcls, cchRun, ich, clsRun); cchRun = 0; } /* resolve the directionality class at the current location */ clsNew = GetResolvedType(action); if (clsNew != XX) pcls[ich] = clsNew; /* increment a deferred run */ if (IX & action) cchRun++; state = stateWeak[state][cls]; } /* resolve any deferred runs * use the direction of the current level to emulate PDF */ cls = EmbeddingDirection(level); /* resolve the directionality for deferred runs */ clsRun = GetDeferredType(actionWeak[state][cls]); if (clsRun != XX) SetDeferredRun(pcls, cchRun, ich, clsRun); }
/*------------------------------------------------------------------------ Function: resolveWeak Resolves the directionality of numeric and other weak character types Implements rules X10 and W1-W6 of the Unicode Bidirectional Algorithm. Input: Array of embedding levels Character count In/Out: Array of directional classes Note: On input only these directional classes are expected AL, HL, R, L, ON, BN, NSM, AN, EN, ES, ET, CS, ------------------------------------------------------------------------*/ void resolveWeak(int baselevel, int *pcls, int *plevel, int cch) { int state = odd(baselevel) ? xl : xr; int action; int cls; int clsRun; int clsNew; int level = baselevel; int cchRun = 0; int ich = 0; for (; ich < cch; ich++) { // ignore boundary neutrals if (pcls[ich] == BN) { // must flatten levels unless at a level change; plevel[ich] = level; // lookahead for level changes if (ich + 1 == cch && level != baselevel) { // have to fixup last BN before end of the loop, since // its fix-upped value will be needed below the assert pcls[ich] = EmbeddingDirection(level); } else if (ich + 1 < cch && level != plevel[ich+1] && pcls[ich+1] != BN) { // fixup LAST BN in front / after a level run to make // it act like the SOR/EOR in rule X10 int newlevel = plevel[ich+1]; if (level > newlevel) { newlevel = level; } plevel[ich] = newlevel; // must match assigned level pcls[ich] = EmbeddingDirection(newlevel); level = plevel[ich+1]; } else { // don't interrupt runs if (cchRun) { cchRun++; } continue; } } cls = pcls[ich]; action = actionWeak[state][cls]; // resolve the directionality for deferred runs clsRun = GetDeferredType(action); if (clsRun != XX) { SetDeferredRun(pcls, cchRun, ich, clsRun); cchRun = 0; } // resolve the directionality class at the current location clsNew = GetResolvedType(action); if (clsNew != XX) { pcls[ich] = clsNew; } // increment a deferred run if (IX & action) { cchRun++; } state = stateWeak[state][cls]; } // resolve any deferred runs // use the direction of the current level to emulate PDF cls = EmbeddingDirection(level); // resolve the directionality for deferred runs clsRun = GetDeferredType(actionWeak[state][cls]); if (clsRun != XX) { SetDeferredRun(pcls, cchRun, ich, clsRun); } }
/////////////////////////////////////////////////////////////////////////////// // BidiResolveWeak // void BidiResolveWeak(int nBaseEmbeddingLevel, AnalysisInfo* pAnalysisInfoArray, size_t count) { // Compile-time assert that somebody hasn't messed with the kBidiClass ordering. EA_COMPILETIME_ASSERT((N == 0) && (ON == 0) && (L == 1) && (R == 2) && (AN == 3) && (EN == 4) && (AL == 5) && (NSM == 6) && (CS == 7) && (ES == 8) && (ET == 9) && (BN == 10) && (S == 11) && (WS == 12) && (B == 13) && (RLO == 14) && (RLE == 15) && (LRO == 16) && (LRE == 17) && (PDF == 18)); int level = nBaseEmbeddingLevel; WeakState weakState = (nBaseEmbeddingLevel & 1) ? xr : xl; size_t nRunLength = 0; BidiClass bidiClass; size_t i; for(i = 0; i < count; i++) { // We expect mBidiClass to be one of: ON, L, R, AN, EN, AL, NSM, CS, ES, ET, BN. EA_ASSERT(pAnalysisInfoArray[i].mBidiClass <= kBidiClassBN); // Ignore boundary neutrals if(pAnalysisInfoArray[i].mBidiClass == kBidiClassBN) { // must flatten levels unless at a level change; pAnalysisInfoArray[i].mnBidiLevel = level; // Look ahead for level changes. if(((i + 1) == count) && (level != nBaseEmbeddingLevel)) { // Need to fixup last kBidiClassBN before end of the loop, // since its fix-upped value will be needed below the assert. pAnalysisInfoArray[i].mBidiClass = GetEmbeddingDirection(level); } else if(((i + 1) < count) && (level != pAnalysisInfoArray[i + 1].mnBidiLevel) && (pAnalysisInfoArray[i + 1].mBidiClass != kBidiClassBN)) { // Fixup the last kBidiClassBN in front / after a level // run to make it act like the SOR/EOR in rule X10. int newLevel = pAnalysisInfoArray[i + 1].mnBidiLevel; if(level > newLevel) newLevel = level; pAnalysisInfoArray[i].mnBidiLevel = newLevel; // Must match assigned level. pAnalysisInfoArray[i].mBidiClass = GetEmbeddingDirection(newLevel); level = pAnalysisInfoArray[i + 1].mnBidiLevel; } else { // Don't interrupt runs if(nRunLength) nRunLength++; continue; } } // We expect mBidiClass to be one of: ON, L, R, AN, EN, AL, NSM, CS, ES, ET, BN. EA_ASSERT(pAnalysisInfoArray[i].mBidiClass <= kBidiClassBN); bidiClass = pAnalysisInfoArray[i].mBidiClass; // Set the directionality for deferred runs. const WeakStateAction weakStateAction = gWeakStateActionTable[weakState][bidiClass]; const BidiClass clsRun = GetDeferredType(weakStateAction); if((uint32_t)clsRun != XX) { SetBidiClass(pAnalysisInfoArray + (i - nRunLength), nRunLength, clsRun); nRunLength = 0; } // Resolve the directionality class at the current location BidiClass clsNew = GetResolvedType(weakStateAction); if((uint32_t)clsNew != XX) pAnalysisInfoArray[i].mBidiClass = clsNew; // Increment a deferred run. if(IX & weakStateAction) nRunLength++; weakState = gWeakStateTable[weakState][bidiClass]; } // Resolve any deferred runs. Use the direction of the current // level to emulate PDF (pop directional format). bidiClass = GetEmbeddingDirection(level); // Resolve the directionality for deferred runs. const WeakStateAction weakStateAction = gWeakStateActionTable[weakState][bidiClass]; const BidiClass clsRun = GetDeferredType(weakStateAction); if((uint32_t)clsRun != XX) SetBidiClass(pAnalysisInfoArray + (i - nRunLength), nRunLength, clsRun); }