Example #1
0
/*------------------------------------------------------------------------
    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);
    }
}
Example #3
0
///////////////////////////////////////////////////////////////////////////////
// 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);
}