Exemplo n.º 1
0
QList<TextShaper::TextRun> TextShaper::itemizeBiDi()
{
	QList<TextRun> textRuns;
	UBiDi *obj = ubidi_open();
	UErrorCode err = U_ZERO_ERROR;

	UBiDiLevel parLevel = UBIDI_LTR;
	ParagraphStyle style = m_story.paragraphStyle(m_firstChar);
	if (style.direction() == ParagraphStyle::RTL)
		parLevel = UBIDI_RTL;

	ubidi_setPara(obj, (const UChar*) m_text.utf16(), m_text.length(), parLevel, NULL, &err);
	if (U_SUCCESS(err))
	{
		int32_t count = ubidi_countRuns(obj, &err);
		if (U_SUCCESS(err))
		{
			textRuns.reserve(count);
			for (int32_t i = 0; i < count; i++)
			{
				int32_t start, length;
				UBiDiDirection dir = ubidi_getVisualRun(obj, i, &start, &length);
				textRuns.append(TextRun(start, length, dir));
			}
		}
	}

	ubidi_close(obj);
	return textRuns;
}
Exemplo n.º 2
0
U_CAPI void U_EXPORT2
ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
    /* ubidi_countRuns() checks all of its and our arguments */
    if(ubidi_countRuns(pBiDi, pErrorCode)<=0) {
        /* no op */
    } else if(indexMap==NULL) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    } else {
        /* fill a visual-to-logical index map using the runs[] */
        Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
        int32_t logicalStart, visualStart, visualLimit;

        visualStart=0;
        for(; runs<runsLimit; ++runs) {
            logicalStart=runs->logicalStart;
            visualLimit=runs->visualLimit;
            if(IS_EVEN_RUN(logicalStart)) {
                do { /* LTR */
                    *indexMap++ = logicalStart++;
                } while(++visualStart<visualLimit);
            } else {
                REMOVE_ODD_BIT(logicalStart);
                logicalStart+=visualLimit-visualStart;  /* logicalLimit */
                do { /* RTL */
                    *indexMap++ = --logicalStart;
                } while(++visualStart<visualLimit);
            }
            /* visualStart==visualLimit; */
        }
    }
}
Exemplo n.º 3
0
U_CAPI void U_EXPORT2
ubidi_getLogicalRun(const UBiDi * pBiDi, int32_t logicalPosition,
                    int32_t * pLogicalLimit, UBiDiLevel * pLevel)
{
	UErrorCode errorCode;
	int32_t runCount, visualStart, logicalLimit, logicalFirst, i;
	Run iRun;

	errorCode = U_ZERO_ERROR;
	RETURN_VOID_IF_BAD_RANGE(logicalPosition, 0, pBiDi->length, errorCode);
	/* ubidi_countRuns will check VALID_PARA_OR_LINE */
	runCount = ubidi_countRuns((UBiDi *)pBiDi, &errorCode);
	if (U_FAILURE(errorCode))
	{
		return;
	}
	/* this is done based on runs rather than on levels since levels have
	   a special interpretation when UBIDI_REORDER_RUNS_ONLY
	 */
	visualStart = logicalLimit = 0;
	iRun = pBiDi->runs[0];

	for (i = 0; i < runCount; i++)
	{
		iRun = pBiDi->runs[i];
		logicalFirst = GET_INDEX(iRun.logicalStart);
		logicalLimit = logicalFirst + iRun.visualLimit - visualStart;
		if ((logicalPosition >= logicalFirst) &&
		    (logicalPosition < logicalLimit))
		{
			break;
		}
		visualStart = iRun.visualLimit;
	}
	if (pLogicalLimit)
	{
		*pLogicalLimit = logicalLimit;
	}
	if (pLevel)
	{
		if (pBiDi->reorderingMode == UBIDI_REORDER_RUNS_ONLY)
		{
			*pLevel = (UBiDiLevel)GET_ODD_BIT(iRun.logicalStart);
		}
		else if (pBiDi->direction != UBIDI_MIXED || logicalPosition >= pBiDi->trailingWSStart)
		{
			*pLevel = GET_PARALEVEL(pBiDi, logicalPosition);
		}
		else
		{
			*pLevel = pBiDi->levels[logicalPosition];
		}
	}
}
Exemplo n.º 4
0
void CTextRenderer::UpdateTextCache_BiDi(array<CHarfbuzzGlyph>* pGlyphChain, const char* pText)
{
	//Use ICU for bidirectional text
	//note: bidirectional texts appear for example when a latin username is displayed in a arabic text
	UErrorCode ICUError = U_ZERO_ERROR;
	UnicodeString UTF16Text = icu::UnicodeString::fromUTF8(pText);
	UBiDi* pICUBiDi = ubidi_openSized(UTF16Text.length(), 0, &ICUError);
	
	//Perform the BiDi algorithm
	//TODO: change UBIDI_DEFAULT_LTR by some variable dependend of the user config
	ubidi_setPara(pICUBiDi, UTF16Text.getBuffer(), UTF16Text.length(), (Localization()->GetWritingDirection() == CLocalization::DIRECTION_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR), 0, &ICUError);
	
	if(U_SUCCESS(ICUError))
	{
		UBiDiLevel ICULevel = 1&ubidi_getParaLevel(pICUBiDi);
		UBiDiDirection Direction = ubidi_getDirection(pICUBiDi);

		if(Direction != UBIDI_MIXED)
		{
			UpdateTextCache_Font(pGlyphChain, UTF16Text.getBuffer(), 0, UTF16Text.length(), (Direction == UBIDI_RTL));
		}
		else
		{
			int CharStart = 0;
			UBiDiLevel level;
			int NumberOfParts = ubidi_countRuns(pICUBiDi, &ICUError);
			if(U_SUCCESS(ICUError))
			{
				for(int i=0; i<NumberOfParts; i++)
				{
					int Start;
					int SubLength;
					Direction = ubidi_getVisualRun(pICUBiDi, i, &Start, &SubLength);

					UpdateTextCache_Font(pGlyphChain, UTF16Text.getBuffer(), Start, SubLength, (Direction == UBIDI_RTL));
				}
			}
			else
			{
				dbg_msg("TextRenderer", "BiDi algorithm failed (ubidi_countRuns): %s", u_errorName(ICUError));
				return;
			}
		}
    }
    else
    {
		dbg_msg("TextRenderer", "BiDi algorithm failed: %s", u_errorName(ICUError));
		return;
	}
}
Exemplo n.º 5
0
void text_itemizer::itemize_direction(unsigned start, unsigned end)
{
    direction_runs_.clear();
    UErrorCode error = U_ZERO_ERROR;
    int32_t length = end - start;
    UBiDi *bidi = ubidi_openSized(length, 0, &error);
    if (!bidi || U_FAILURE(error))
    {
        MAPNIK_LOG_ERROR(text_itemizer) << "Failed to create bidi object: " << u_errorName(error) << "\n";
        return;
    }
    ubidi_setPara(bidi, text_.getBuffer() + start, length, UBIDI_DEFAULT_LTR, 0, &error);
    if (U_SUCCESS(error))
    {
        UBiDiDirection direction = ubidi_getDirection(bidi);
        if (direction != UBIDI_MIXED)
        {
            direction_runs_.emplace_back(direction, start, end);
        }
        else
        {
            // mixed-directional
            int32_t count = ubidi_countRuns(bidi, &error);
            if(U_SUCCESS(error))
            {
                for(int i=0; i<count; ++i)
                {
                    int32_t vis_length;
                    int32_t run_start;
                    direction = ubidi_getVisualRun(bidi, i, &run_start, &vis_length);
                    run_start += start; //Add offset to compensate offset in setPara
                    direction_runs_.emplace_back(direction, run_start, run_start+vis_length);
                }
            }
        }
    }
    else
    {
        MAPNIK_LOG_ERROR(text_itemizer) << "ICU error: " << u_errorName(error) << "\n"; //TODO: Exception
    }
    ubidi_close(bidi);
}
Exemplo n.º 6
0
/**
 * TODO: if we care about performance, we might just want to use an int[] instead of a Run[].
 */
extern "C" jobjectArray Java_java_text_Bidi_ubidi_1getRuns(JNIEnv* env, jclass, jlong ptr) {
    UBiDi* ubidi = uBiDi(ptr);
    UErrorCode status = U_ZERO_ERROR;
    int runCount = ubidi_countRuns(ubidi, &status);
    if (maybeThrowIcuException(env, "ubidi_countRuns", status)) {
        return NULL;
    }
    static jmethodID bidiRunConstructor =
            env->GetMethodID(JniConstants::bidiRunClass, "<init>", "(III)V");
    jobjectArray runs = env->NewObjectArray(runCount, JniConstants::bidiRunClass, NULL);
    UBiDiLevel level = 0;
    int start = 0;
    int limit = 0;
    for (int i = 0; i < runCount; ++i) {
        ubidi_getLogicalRun(ubidi, start, &limit, &level);
        jobject run = env->NewObject(JniConstants::bidiRunClass, bidiRunConstructor, start, limit, level);
        env->SetObjectArrayElement(runs, i, run);
        start = limit;
    }
    return runs;
}
Exemplo n.º 7
0
TextGroup::TextGroup(const std::string &input, hb_script_t script, const std::string &lang, hb_direction_t overallDirection)
    :script_(script)
     ,lang_(lang)
     ,overallDirection_(overallDirection)
{
    if(hb_script_get_horizontal_direction(script_) == HB_DIRECTION_LTR)
    {
        addRun(input, HB_DIRECTION_LTR);
    }
    else
    {
        auto text = UnicodeString::fromUTF8(input);
        auto length = text.length();
        printf("Hominlinx-->TextGroup::TextGroup str unicodelen[%d] ====text[0x%x]\n",length, text.charAt(0) );

        UErrorCode err = U_ZERO_ERROR;
        UBiDi *bidi = ubidi_openSized(length, 0, &err);//Bidrectional text
        ubidi_setPara(bidi, text.getBuffer(), length, hbDirectionToUBIDILevel(overallDirection_), 0, &err);
        auto direction = ubidi_getDirection(bidi);

        if(direction != UBIDI_MIXED)
        {
            addRun(input, uciDirectionToHB(direction));
        }
        else
        {
            auto count = ubidi_countRuns(bidi, &err);

            for(int i=0; i < count; ++i)
            {
                int32_t start, length;
                direction = ubidi_getVisualRun(bidi, i, &start, &length);
                addRun(text, direction, start, start + length);
            }

        }

        ubidi_close(bidi);
    }
}
Exemplo n.º 8
0
JNIEXPORT void JNICALL Java_java_text_Bidi_nativeBidiChars
  (JNIEnv *env, jclass cls, jobject jbidi, jcharArray text, jint tStart, jbyteArray embs, jint eStart, jint length, jint dir)
{
    UErrorCode err = U_ZERO_ERROR;
    UBiDi* bidi = ubidi_openSized(length, length, &err);
    if (!U_FAILURE(err)) {
        jchar *cText = (jchar*)(*env)->GetPrimitiveArrayCritical(env, text, NULL);
        if (cText) {
            UBiDiLevel baseLevel = (UBiDiLevel)dir;
            jbyte *cEmbs = 0;
	    uint8_t *cEmbsAdj = 0;
            if (embs != NULL) {
                cEmbs = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, embs, NULL);
		if (cEmbs) {
		    cEmbsAdj = (uint8_t*)(cEmbs + eStart);
		}
            }
            ubidi_setPara(bidi, cText + tStart, length, baseLevel, cEmbsAdj, &err);
	    if (cEmbs) {
		(*env)->ReleasePrimitiveArrayCritical(env, embs, cEmbs, JNI_ABORT);
	    }

            (*env)->ReleasePrimitiveArrayCritical(env, text, cText, JNI_ABORT);

            if (!U_FAILURE(err)) {
                jint resDir = (jint)ubidi_getDirection(bidi);
                jint resLevel = (jint)ubidi_getParaLevel(bidi);
                jint resRunCount = 0;
                jintArray resRuns = 0;
                jintArray resCWS = 0;
                if (resDir == UBIDI_MIXED) {
                    resRunCount = (jint)ubidi_countRuns(bidi, &err);
                    if (!U_FAILURE(err)) {
                        if (resRunCount) {
                            jint* cResRuns = (jint*)calloc(resRunCount * 2, sizeof(jint));
                                  if (cResRuns) {
                                    UTextOffset limit = 0;
                                    UBiDiLevel level;
                                    jint *p = cResRuns;
                                    while (limit < length) {
                                        ubidi_getLogicalRun(bidi, limit, &limit, &level);
                                        *p++ = (jint)limit;
                                        *p++ = (jint)level;
                                    }

                                    {
                                        const DirProp *dp = bidi->dirProps;
                                        jint ccws = 0;
                                        jint n = 0;
                                        p = cResRuns;
                                        do {
                                            if ((*(p+1) ^ resLevel) & 0x1) {
                                                while (n < *p) {
                                                    if (dp[n++] == WS) {
                                                        ++ccws;
                                                    }
                                                }
                                            } else {
                                                n = *p;
                                            }
                                            p += 2;
                                        } while (n < length);

                                        resCWS = (*env)->NewIntArray(env, ccws);
                                        if (resCWS) {
                                            jint* cResCWS = (jint*)(*env)->GetPrimitiveArrayCritical(env, resCWS, NULL);
                                            if (cResCWS) {
                                                jint ccws = 0;
                                                jint n = 0;
                                                p = cResRuns;
                                                do {
                                                    if ((*(p+1) ^ resLevel) & 0x1) {
                                                        while (n < *p) {
                                                            if (dp[n] == WS) {
                                                                cResCWS[ccws++] = n;
                                                            }
                                                            ++n;
                                                        }
                                                    } else {
                                                        n = *p;
                                                    }
                                                    p += 2;
                                                } while (n < length);
                                                (*env)->ReleasePrimitiveArrayCritical(env, resCWS, cResCWS, 0);
                                            }
                                        }
                                    }

                                    resRuns = (*env)->NewIntArray(env, resRunCount * 2);
				    if (resRuns) {
					(*env)->SetIntArrayRegion(env, resRuns, 0, resRunCount * 2, cResRuns);
				    }
                                    free(cResRuns);
                                }
                            }
                        }
                    }

                resetBidi(env, cls, jbidi, resDir, resLevel, length, resRuns, resCWS);
            }
        }
        ubidi_close(bidi);
    }
}
Exemplo n.º 9
0
U_CAPI void U_EXPORT2
ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
    if(indexMap==NULL) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return;
    }
    /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
    ubidi_countRuns(pBiDi, pErrorCode);
    if(U_SUCCESS(*pErrorCode)) {
        /* fill a visual-to-logical index map using the runs[] */
        Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
        int32_t logicalStart, visualStart, visualLimit, *pi=indexMap;

        if (pBiDi->resultLength<=0) {
            return;
        }
        visualStart=0;
        for(; runs<runsLimit; ++runs) {
            logicalStart=runs->logicalStart;
            visualLimit=runs->visualLimit;
            if(IS_EVEN_RUN(logicalStart)) {
                do { /* LTR */
                    *pi++ = logicalStart++;
                } while(++visualStart<visualLimit);
            } else {
                REMOVE_ODD_BIT(logicalStart);
                logicalStart+=visualLimit-visualStart;  /* logicalLimit */
                do { /* RTL */
                    *pi++ = --logicalStart;
                } while(++visualStart<visualLimit);
            }
            /* visualStart==visualLimit; */
        }

        if(pBiDi->insertPoints.size>0) {
            int32_t markFound=0, runCount=pBiDi->runCount;
            int32_t insertRemove, i, j, k;
            runs=pBiDi->runs;
            /* count all inserted marks */
            for(i=0; i<runCount; i++) {
                insertRemove=runs[i].insertRemove;
                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
                    markFound++;
                }
                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
                    markFound++;
                }
            }
            /* move back indexes by number of preceding marks */
            k=pBiDi->resultLength;
            for(i=runCount-1; i>=0 && markFound>0; i--) {
                insertRemove=runs[i].insertRemove;
                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
                    indexMap[--k]= UBIDI_MAP_NOWHERE;
                    markFound--;
                }
                visualStart= i>0 ? runs[i-1].visualLimit : 0;
                for(j=runs[i].visualLimit-1; j>=visualStart && markFound>0; j--) {
                    indexMap[--k]=indexMap[j];
                }
                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
                    indexMap[--k]= UBIDI_MAP_NOWHERE;
                    markFound--;
                }
            }
        }
        else if(pBiDi->controlCount>0) {
            int32_t runCount=pBiDi->runCount, logicalEnd;
            int32_t insertRemove, length, i, j, k, m;
            UChar uchar;
            UBool evenRun;
            runs=pBiDi->runs;
            visualStart=0;
            /* move forward indexes by number of preceding controls */
            k=0;
            for(i=0; i<runCount; i++, visualStart+=length) {
                length=runs[i].visualLimit-visualStart;
                insertRemove=runs[i].insertRemove;
                /* if no control found yet, nothing to do in this run */
                if((insertRemove==0)&&(k==visualStart)) {
                    k+=length;
                    continue;
                }
                /* if no control in this run */
                if(insertRemove==0) {
                    visualLimit=runs[i].visualLimit;
                    for(j=visualStart; j<visualLimit; j++) {
                        indexMap[k++]=indexMap[j];
                    }
                    continue;
                }
                logicalStart=runs[i].logicalStart;
                evenRun=IS_EVEN_RUN(logicalStart);
                REMOVE_ODD_BIT(logicalStart);
                logicalEnd=logicalStart+length-1;
                for(j=0; j<length; j++) {
                    m= evenRun ? logicalStart+j : logicalEnd-j;
                    uchar=pBiDi->text[m];
                    if(!IS_BIDI_CONTROL_CHAR(uchar)) {
                        indexMap[k++]=m;
                    }
                }
            }
        }
    }
}
Exemplo n.º 10
0
U_CAPI void U_EXPORT2
ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
    /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
    ubidi_countRuns(pBiDi, pErrorCode);
    if(U_FAILURE(*pErrorCode)) {
        /* no op */
    } else if(indexMap==NULL) {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    } else {
        /* fill a logical-to-visual index map using the runs[] */
        int32_t visualStart, visualLimit, i, j, k;
        int32_t logicalStart, logicalLimit;
        Run *runs=pBiDi->runs;
        if (pBiDi->length<=0) {
            return;
        }
        if (pBiDi->length>pBiDi->resultLength) {
            uprv_memset(indexMap, 0xFF, pBiDi->length*sizeof(int32_t));
        }

        visualStart=0;
        for(j=0; j<pBiDi->runCount; ++j) {
            logicalStart=GET_INDEX(runs[j].logicalStart);
            visualLimit=runs[j].visualLimit;
            if(IS_EVEN_RUN(runs[j].logicalStart)) {
                do { /* LTR */
                    indexMap[logicalStart++]=visualStart++;
                } while(visualStart<visualLimit);
            } else {
                logicalStart+=visualLimit-visualStart;  /* logicalLimit */
                do { /* RTL */
                    indexMap[--logicalStart]=visualStart++;
                } while(visualStart<visualLimit);
            }
            /* visualStart==visualLimit; */
        }

        if(pBiDi->insertPoints.size>0) {
            int32_t markFound=0, runCount=pBiDi->runCount;
            int32_t length, insertRemove;
            visualStart=0;
            /* add number of marks found until each index */
            for(i=0; i<runCount; i++, visualStart+=length) {
                length=runs[i].visualLimit-visualStart;
                insertRemove=runs[i].insertRemove;
                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
                    markFound++;
                }
                if(markFound>0) {
                    logicalStart=GET_INDEX(runs[i].logicalStart);
                    logicalLimit=logicalStart+length;
                    for(j=logicalStart; j<logicalLimit; j++) {
                        indexMap[j]+=markFound;
                    }
                }
                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
                    markFound++;
                }
            }
        }
        else if(pBiDi->controlCount>0) {
            int32_t controlFound=0, runCount=pBiDi->runCount;
            int32_t length, insertRemove;
            UBool evenRun;
            UChar uchar;
            visualStart=0;
            /* subtract number of controls found until each index */
            for(i=0; i<runCount; i++, visualStart+=length) {
                length=runs[i].visualLimit-visualStart;
                insertRemove=runs[i].insertRemove;
                /* no control found within previous runs nor within this run */
                if((controlFound-insertRemove)==0) {
                    continue;
                }
                logicalStart=runs[i].logicalStart;
                evenRun=IS_EVEN_RUN(logicalStart);
                REMOVE_ODD_BIT(logicalStart);
                logicalLimit=logicalStart+length;
                /* if no control within this run */
                if(insertRemove==0) {
                    for(j=logicalStart; j<logicalLimit; j++) {
                        indexMap[j]-=controlFound;
                    }
                    continue;
                }
                for(j=0; j<length; j++) {
                    k= evenRun ? logicalStart+j : logicalLimit-j-1;
                    uchar=pBiDi->text[k];
                    if(IS_BIDI_CONTROL_CHAR(uchar)) {
                        controlFound++;
                        indexMap[k]=UBIDI_MAP_NOWHERE;
                        continue;
                    }
                    indexMap[k]-=controlFound;
                }
            }
        }
    }
}
Exemplo n.º 11
0
U_CAPI int32_t U_EXPORT2
ubidi_writeReordered(UBiDi *pBiDi,
                     UChar *dest, int32_t destSize,
                     uint16_t options,
                     UErrorCode *pErrorCode) {
    const UChar *text;
    UChar *saveDest;
    int32_t length, destCapacity;
    int32_t run, runCount, logicalStart, runLength;

    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
        return 0;
    }

    /* more error checking */
    if( pBiDi==NULL ||
        (text=pBiDi->text)==NULL || (length=pBiDi->length)<0 ||
        destSize<0 || (destSize>0 && dest==NULL))
    {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    /* do input and output overlap? */
    if( dest!=NULL &&
        ((text>=dest && text<dest+destSize) ||
         (dest>=text && dest<text+pBiDi->originalLength)))
    {
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }

    if(length==0) {
        /* nothing to do */
        return u_terminateUChars(dest, destSize, 0, pErrorCode);
    }

    runCount=ubidi_countRuns(pBiDi, pErrorCode);
    if(U_FAILURE(*pErrorCode)) {
        return 0;
    }

    /* destSize shrinks, later destination length=destCapacity-destSize */
    saveDest=dest;
    destCapacity=destSize;

    /*
     * Option "insert marks" implies UBIDI_INSERT_LRM_FOR_NUMERIC if the
     * reordering mode (checked below) is appropriate.
     */
    if(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
        options|=UBIDI_INSERT_LRM_FOR_NUMERIC;
        options&=~UBIDI_REMOVE_BIDI_CONTROLS;
    }
    /*
     * Option "remove controls" implies UBIDI_REMOVE_BIDI_CONTROLS
     * and cancels UBIDI_INSERT_LRM_FOR_NUMERIC.
     */
    if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
        options|=UBIDI_REMOVE_BIDI_CONTROLS;
        options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
    }
    /*
     * If we do not perform the "inverse BiDi" algorithm, then we
     * don't need to insert any LRMs, and don't need to test for it.
     */
    if((pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
       (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_LIKE_DIRECT)  &&
       (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) &&
       (pBiDi->reorderingMode != UBIDI_REORDER_RUNS_ONLY)) {
        options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
    }
    /*
     * Iterate through all visual runs and copy the run text segments to
     * the destination, according to the options.
     *
     * The tests for where to insert LRMs ignore the fact that there may be
     * BN codes or non-BMP code points at the beginning and end of a run;
     * they may insert LRMs unnecessarily but the tests are faster this way
     * (this would have to be improved for UTF-8).
     *
     * Note that the only errors that are set by doWriteXY() are buffer overflow
     * errors. Ignore them until the end, and continue for preflighting.
     */
    if(!(options&UBIDI_OUTPUT_REVERSE)) {
        /* forward output */
        if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
            /* do not insert BiDi controls */
            for(run=0; run<runCount; ++run) {
                if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
                    runLength=doWriteForward(text+logicalStart, runLength,
                                             dest, destSize,
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
                } else {
                    runLength=doWriteReverse(text+logicalStart, runLength,
                                             dest, destSize,
                                             options, pErrorCode);
                }
                dest+=runLength;
                destSize-=runLength;
            }
        } else {
            /* insert BiDi controls for "inverse BiDi" */
            const DirProp *dirProps=pBiDi->dirProps;
            const UChar *src;
            UChar uc;
            UBiDiDirection dir;
            int32_t markFlag;

            for(run=0; run<runCount; ++run) {
                dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
                src=text+logicalStart;
                /* check if something relevant in insertPoints */
                markFlag=pBiDi->runs[run].insertRemove;
                if(markFlag<0) {        /* BiDi controls count */
                    markFlag=0;
                }

                if(UBIDI_LTR==dir) {
                    if((pBiDi->isInverse) &&
                       (/*run>0 &&*/ dirProps[logicalStart]!=L)) {
                        markFlag |= LRM_BEFORE;
                    }
                    if (markFlag & LRM_BEFORE) {
                        uc=LRM_CHAR;
                    }
                    else if (markFlag & RLM_BEFORE) {
                        uc=RLM_CHAR;
                    }
                    else  uc=0;
                    if(uc) {
                        if(destSize>0) {
                            *dest++=uc;
                        }
                        --destSize;
                    }

                    runLength=doWriteForward(src, runLength,
                                             dest, destSize,
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
                    dest+=runLength;
                    destSize-=runLength;

                    if((pBiDi->isInverse) &&
                       (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) {
                        markFlag |= LRM_AFTER;
                    }
                    if (markFlag & LRM_AFTER) {
                        uc=LRM_CHAR;
                    }
                    else if (markFlag & RLM_AFTER) {
                        uc=RLM_CHAR;
                    }
                    else  uc=0;
                    if(uc) {
                        if(destSize>0) {
                            *dest++=uc;
                        }
                        --destSize;
                    }
                } else {                /* RTL run */
                    if((pBiDi->isInverse) &&
                       (/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1])))) {
                        markFlag |= RLM_BEFORE;
                    }
                    if (markFlag & LRM_BEFORE) {
                        uc=LRM_CHAR;
                    }
                    else if (markFlag & RLM_BEFORE) {
                        uc=RLM_CHAR;
                    }
                    else  uc=0;
                    if(uc) {
                        if(destSize>0) {
                            *dest++=uc;
                        }
                        --destSize;
                    }

                    runLength=doWriteReverse(src, runLength,
                                             dest, destSize,
                                             options, pErrorCode);
                    dest+=runLength;
                    destSize-=runLength;

                    if((pBiDi->isInverse) &&
                       (/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart])))) {
                        markFlag |= RLM_AFTER;
                    }
                    if (markFlag & LRM_AFTER) {
                        uc=LRM_CHAR;
                    }
                    else if (markFlag & RLM_AFTER) {
                        uc=RLM_CHAR;
                    }
                    else  uc=0;
                    if(uc) {
                        if(destSize>0) {
                            *dest++=uc;
                        }
                        --destSize;
                    }
                }
            }
        }
    } else {
        /* reverse output */
        if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
            /* do not insert BiDi controls */
            for(run=runCount; --run>=0;) {
                if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
                    runLength=doWriteReverse(text+logicalStart, runLength,
                                             dest, destSize,
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
                } else {
                    runLength=doWriteForward(text+logicalStart, runLength,
                                             dest, destSize,
                                             options, pErrorCode);
                }
                dest+=runLength;
                destSize-=runLength;
            }
        } else {
            /* insert BiDi controls for "inverse BiDi" */
            const DirProp *dirProps=pBiDi->dirProps;
            const UChar *src;
            UBiDiDirection dir;

            for(run=runCount; --run>=0;) {
                /* reverse output */
                dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
                src=text+logicalStart;

                if(UBIDI_LTR==dir) {
                    if(/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L) {
                        if(destSize>0) {
                            *dest++=LRM_CHAR;
                        }
                        --destSize;
                    }

                    runLength=doWriteReverse(src, runLength,
                                             dest, destSize,
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
                    dest+=runLength;
                    destSize-=runLength;

                    if(/*run>0 &&*/ dirProps[logicalStart]!=L) {
                        if(destSize>0) {
                            *dest++=LRM_CHAR;
                        }
                        --destSize;
                    }
                } else {
                    if(/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart]))) {
                        if(destSize>0) {
                            *dest++=RLM_CHAR;
                        }
                        --destSize;
                    }

                    runLength=doWriteForward(src, runLength,
                                             dest, destSize,
                                             options, pErrorCode);
                    dest+=runLength;
                    destSize-=runLength;

                    if(/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) {
                        if(destSize>0) {
                            *dest++=RLM_CHAR;
                        }
                        --destSize;
                    }
                }
            }
        }
    }

    return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode);
}
Exemplo n.º 12
0
extern "C" jint Java_java_text_Bidi_ubidi_1countRuns(JNIEnv* env, jclass, jlong ptr) {
    UErrorCode status = U_ZERO_ERROR;
    int count = ubidi_countRuns(uBiDi(ptr), &status);
    maybeThrowIcuException(env, "ubidi_countRuns", status);
    return count;
}
Exemplo n.º 13
0
void font_face_set::get_string_info(string_info & info)
{
    unsigned width = 0;
    unsigned height = 0;
    UErrorCode err = U_ZERO_ERROR;
    UnicodeString const& ustr = info.get_string();
    const UChar * text = ustr.getBuffer();
    UBiDi * bidi = ubidi_openSized(ustr.length(),0,&err);

    if (U_SUCCESS(err))
    {
        ubidi_setPara(bidi,text,ustr.length(), UBIDI_DEFAULT_LTR,0,&err);

        if (U_SUCCESS(err))
        {
            int32_t count = ubidi_countRuns(bidi,&err);
            int32_t logicalStart;
            int32_t length;

            for (int32_t i=0; i< count;++i)
            {
                if (UBIDI_LTR == ubidi_getVisualRun(bidi,i,&logicalStart,&length))
                {
                    do {
                        UChar ch = text[logicalStart++];
                        dimension_t char_dim = character_dimensions(ch);
                        info.add_info(ch, char_dim.width, char_dim.height);
                        width += char_dim.width;
                        height = char_dim.height > height ? char_dim.height : height;

                    } while (--length > 0);
                }
                else
                {
                    logicalStart += length;

                    int32_t j=0,i=length;
                    UnicodeString arabic;
                    UChar * buf = arabic.getBuffer(length);
                    do {
                        UChar ch = text[--logicalStart];
                        buf[j++] = ch;
                    } while (--i > 0);

                    arabic.releaseBuffer(length);
                    if ( *arabic.getBuffer() >= 0x0600 && *arabic.getBuffer() <= 0x06ff)
                    {
                        UnicodeString shaped;
                        u_shapeArabic(arabic.getBuffer(),arabic.length(),shaped.getBuffer(arabic.length()),arabic.length(),
                                      U_SHAPE_LETTERS_SHAPE|U_SHAPE_LENGTH_FIXED_SPACES_NEAR|
                                      U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
                                      ,&err);

                        shaped.releaseBuffer(arabic.length());

                        if (U_SUCCESS(err))
                        {
                            for (int j=0;j<shaped.length();++j)
                            {
                                dimension_t char_dim = character_dimensions(shaped[j]);
                                info.add_info(shaped[j], char_dim.width, char_dim.height);
                                width += char_dim.width;
                                height = char_dim.height > height ? char_dim.height : height;
                            }
                        }
                    } else {
                        // Non-Arabic RTL
                        for (int j=0;j<arabic.length();++j)
                        {
                            dimension_t char_dim = character_dimensions(arabic[j]);
                            info.add_info(arabic[j], char_dim.width, char_dim.height);
                            width += char_dim.width;
                            height = char_dim.height > height ? char_dim.height : height;
                        }
                    }
                }
            }
        }
        ubidi_close(bidi);
    }

    info.set_dimensions(width, height);
}
Exemplo n.º 14
0
int icu_bidi_runs(lua_State *L) {
  size_t input_l;
  const char* input = luaL_checklstring(L, 1, &input_l);
  const char* direction = luaL_checkstring(L, 2);

  UChar *input_as_uchar;
  int32_t l;
  utf8_to_uchar(input, input_l, input_as_uchar, l);

  UBiDiLevel paraLevel = 0;
  if (strncasecmp(direction, "RTL", 3) == 0) {
    paraLevel = 1;
  }
  /* Now let's bidi! */
  UBiDi* bidi = ubidi_open();
  UErrorCode err = U_ZERO_ERROR;
  ubidi_setPara(bidi, input_as_uchar, l, paraLevel, NULL, &err);
  if (!U_SUCCESS(err)) {
    free(input_as_uchar);
    ubidi_close(bidi);
    return luaL_error(L, "Error in bidi %s", u_errorName(err));
  }

  int count = ubidi_countRuns(bidi,&err);
  int start, length;

  lua_checkstack(L,count);
  for (int i=0; i < count; i++) {
    UBiDiDirection dir = ubidi_getVisualRun(bidi, i, &start, &length);
    lua_newtable(L);
    // Convert back to UTF8...
    int32_t l3 = 0;
    char* possibleOutbuf = malloc(4*length);
    if(!possibleOutbuf) {
      return luaL_error(L, "Couldn't malloc");
    }
    u_strToUTF8(possibleOutbuf, 4 * length, &l3, input_as_uchar+start, length, &err);
    if (!U_SUCCESS(err)) {
      free(possibleOutbuf);
      return luaL_error(L, "Bidi run too big? %s", u_errorName(err));
    }
    lua_pushstring(L, "run");
    lua_pushstring(L, possibleOutbuf);
    free(possibleOutbuf);
    lua_settable(L, -3);

    lua_pushstring(L, "start");
    int32_t new_start = start;
    // Length/start is given in terms of UTF16 codepoints.
    // But we want a count of Unicode characters. This means
    // surrogate pairs need to be counted as 1.
    for (int j=0; j< start; j++) {
      if (U_IS_TRAIL(*(input_as_uchar+j))) new_start--;
    }
    lua_pushinteger(L, new_start);
    lua_settable(L, -3);

    lua_pushstring(L, "length");
    for (int j=start; j< start+length; j++) {
      if (U_IS_TRAIL(*(input_as_uchar+j))) length--;
    }
    lua_pushinteger(L, length);
    lua_settable(L, -3);

    lua_pushstring(L, "dir");
    lua_pushstring(L, dir == UBIDI_RTL ? "RTL" : "LTR");
    lua_settable(L, -3);

    lua_pushstring(L, "level");
    lua_pushinteger(L, ubidi_getLevelAt(bidi, start));
    lua_settable(L, -3);
  }

  free(input_as_uchar);
  ubidi_close(bidi);
  return count;
}
Exemplo n.º 15
0
std::vector<StyledText> BiDi::processStyledText(const StyledText& input, std::set<std::size_t> lineBreakPoints) {
    std::vector<StyledText> lines;
    const auto& inputText = input.first;
    const auto& styleIndices = input.second;
    
    UErrorCode errorCode = U_ZERO_ERROR;
    
    ubidi_setPara(impl->bidiText, mbgl::utf16char_cast<const UChar*>(inputText.c_str()), static_cast<int32_t>(inputText.size()),
                  UBIDI_DEFAULT_LTR, nullptr, &errorCode);
    
    if (U_FAILURE(errorCode)) {
        throw std::runtime_error(std::string("BiDi::processStyledText: ") + u_errorName(errorCode));
    }
    
    mergeParagraphLineBreaks(lineBreakPoints);
    
    std::size_t lineStartIndex = 0;
    
    for (std::size_t lineBreakPoint : lineBreakPoints) {
        StyledText line;
        line.second.reserve(lineBreakPoint - lineStartIndex);

        errorCode = U_ZERO_ERROR;
        ubidi_setLine(impl->bidiText, static_cast<int32_t>(lineStartIndex), static_cast<int32_t>(lineBreakPoint), impl->bidiLine, &errorCode);
        if (U_FAILURE(errorCode)) {
            throw std::runtime_error(std::string("BiDi::processStyledText (setLine): ") + u_errorName(errorCode));
        }
        
        errorCode = U_ZERO_ERROR;
        uint32_t runCount = ubidi_countRuns(impl->bidiLine, &errorCode);
        if (U_FAILURE(errorCode)) {
            throw std::runtime_error(std::string("BiDi::processStyledText (countRuns): ") + u_errorName(errorCode));
        }
        
        for (uint32_t runIndex = 0; runIndex < runCount; runIndex++) {
            int32_t runLogicalStart;
            int32_t runLength;
            UBiDiDirection direction = ubidi_getVisualRun(impl->bidiLine, runIndex, &runLogicalStart, &runLength);
            const bool isReversed = direction == UBIDI_RTL;
            
            std::size_t logicalStart = lineStartIndex + runLogicalStart;
            std::size_t logicalEnd = logicalStart + runLength;
            if (isReversed) {
                // Within this reversed section, iterate logically backwards
                // Each time we see a change in style, render a reversed chunk
                // of everything since the last change
                std::size_t styleRunStart = logicalEnd;
                uint8_t currentStyleIndex = styleIndices.at(styleRunStart - 1);
                for (std::size_t i = logicalEnd - 1; i >= logicalStart; i--) {
                    if (currentStyleIndex != styleIndices.at(i) || i == logicalStart) {
                        std::size_t styleRunEnd = i == logicalStart ? i : i + 1;
                        std::u16string reversed = writeReverse(inputText, styleRunEnd, styleRunStart);
                        line.first += reversed;
                        for (std::size_t j = 0; j < reversed.size(); j++) {
                            line.second.push_back(currentStyleIndex);
                        }
                        currentStyleIndex = styleIndices.at(i);
                        styleRunStart = styleRunEnd;
                    }
                    if (i == 0) {
                        break;
                    }
                }
                
            } else {
                line.first += input.first.substr(logicalStart, runLength);
                line.second.insert(line.second.end(), styleIndices.begin() + logicalStart, styleIndices.begin() + logicalStart + runLength);
            }
        }

        lines.push_back(line);
        lineStartIndex = lineBreakPoint;
    }

    return lines;
}
Exemplo n.º 16
0
nsresult nsBidi::CountRuns(int32_t* aRunCount)
{
  UErrorCode errorCode = U_ZERO_ERROR;
  *aRunCount = ubidi_countRuns(mBiDi, &errorCode);
  return ICUUtils::UErrorToNsResult(errorCode);
}