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;
	}
}
Example #2
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);
}
Example #3
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);
    }
}
Example #4
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);
    }
}
Example #5
0
extern "C" jint Java_java_text_Bidi_ubidi_1getDirection(JNIEnv*, jclass, jlong ptr) {
    return ubidi_getDirection(uBiDi(ptr));
}
Example #6
0
nsresult nsBidi::GetDirection(nsBidiDirection* aDirection)
{
  *aDirection = nsBidiDirection(ubidi_getDirection(mBiDi));
  return NS_OK;
}