Logo Search packages:      
Sourcecode: icu version File versions

ubidi.h File Reference

Detailed Description

C API: BIDI algorithm.

BIDI algorithm for ICU

This is an implementation of the Unicode Bidirectional algorithm. The algorithm is defined in the Unicode Technical Report 9, version 5, also described in The Unicode Standard, Version 3.0 .

General remarks about the API:

In functions with an error code parameter, the pErrorCode pointer must be valid and the value that it points to must not indicate a failure before the function call. Otherwise, the function returns immediately. After the function call, the value indicates success or failure.

The "limit" of a sequence of characters is the position just after their last character, i.e., one more than that position.

Some of the API functions provide access to "runs". Such a "run" is defined as a sequence of characters that are at the same embedding level after performing the BIDI algorithm.

Markus W. Scherer

Sample code for the ICU BIDI API

Rendering a paragraph with the ICU BiDi API

This is (hypothetical) sample code that illustrates how the ICU BiDi API could be used to render a paragraph of text. Rendering code depends highly on the graphics system, therefore this sample code must make a lot of assumptions, which may or may not match any existing graphics system's properties.

The basic assumptions are:

 *#include "unicode/ubidi.h"

 *typedef enum {
     styleNormal=0, styleSelected=1,
     styleBold=2, styleItalics=4,
     styleSuper=8, styleSub=16
 *} Style;

 *typedef struct { int32_t limit; Style style; } StyleRun;

 *int getTextWidth(const UChar *text, int32_t start, int32_t limit,
                  const StyleRun *styleRuns, int styleRunCount);

 // set *pLimit and *pStyleRunLimit for a line
 // from text[start] and from styleRuns[styleRunStart]
 // using ubidi_getLogicalRun(para, ...)
 *void getLineBreak(const UChar *text, int32_t start, int32_t *pLimit,
                  UBiDi *para,
                  const StyleRun *styleRuns, int styleRunStart, int *pStyleRunLimit,
                  int *pLineWidth);

 // render runs on a line sequentially, always from left to right

 // prepare rendering a new line
 *void startLine(UBiDiDirection textDirection, int lineWidth);

 // render a run of text and advance to the right by the run width
 // the text[start..limit-1] is always in logical order
 *void renderRun(const UChar *text, int32_t start, int32_t limit,
               UBiDiDirection textDirection, Style style);

 // We could compute a cross-product
 // from the style runs with the directional runs
 // and then reorder it.
 // Instead, here we iterate over each run type
 // and render the intersections -
 // with shortcuts in simple (and common) cases.
 // renderParagraph() is the main function.

 // render a directional run with
 // (possibly) multiple style runs intersecting with it
 *void renderDirectionalRun(const UChar *text,
                           int32_t start, int32_t limit,
                           UBiDiDirection direction,
                           const StyleRun *styleRuns, int styleRunCount) {
     int i;

     // iterate over style runs
     if(direction==UBIDI_LTR) {
         int styleLimit;

         for(i=0; i<styleRunCount; ++i) {
             if(start<styleLimit) {
                 if(styleLimit>limit) { styleLimit=limit; }
                 renderRun(text, start, styleLimit,
                           direction, styleRun[i].style);
                 if(styleLimit==limit) { break; }
     } else {
         int styleStart;

         for(i=styleRunCount-1; i>=0; --i) {
             if(i>0) {
             } else {
             if(limit>=styleStart) {
                 if(styleStart<start) { styleStart=start; }
                 renderRun(text, styleStart, limit,
                           direction, styleRun[i].style);
                 if(styleStart==start) { break; }

 // the line object represents text[start..limit-1]
 void renderLine(UBiDi *line, const UChar *text,
                 int32_t start, int32_t limit,
                 const StyleRun *styleRuns, int styleRunCount) {
     UBiDiDirection direction=ubidi_getDirection(line);
     if(direction!=UBIDI_MIXED) {
         // unidirectional
         if(styleRunCount<=1) {
             renderRun(text, start, limit, direction, styleRuns[0].style);
         } else {
             renderDirectionalRun(text, start, limit,
                                  direction, styleRuns, styleRunCount);
     } else {
         // mixed-directional
         int32_t count, i, length;
         UBiDiLevel level;

         count=ubidi_countRuns(para, pErrorCode);
         if(U_SUCCESS(*pErrorCode)) {
             if(styleRunCount<=1) {
                 Style style=styleRuns[0].style;

                 // iterate over directional runs
                for(i=0; i<count; ++i) {
                    direction=ubidi_getVisualRun(para, i, &start, &length);
                     renderRun(text, start, start+length, direction, style);
             } else {
                 int32_t j;

                 // iterate over both directional and style runs
                 for(i=0; i<count; ++i) {
                     direction=ubidi_getVisualRun(line, i, &start, &length);
                     renderDirectionalRun(text, start, start+length,
                                          direction, styleRuns, styleRunCount);

 *void renderParagraph(const UChar *text, int32_t length,
                     UBiDiDirection textDirection,
                      const StyleRun *styleRuns, int styleRunCount,
                      int lineWidth,
                      UErrorCode *pErrorCode) {
     UBiDi *para;

     if(pErrorCode==NULL || U_FAILURE(*pErrorCode) || length<=0) {

     para=ubidi_openSized(length, 0, pErrorCode);
     if(para==NULL) { return; }

     ubidi_setPara(para, text, length,
                   textDirection ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR,
                   NULL, pErrorCode);
     if(U_SUCCESS(*pErrorCode)) {
         UBiDiLevel paraLevel=1&ubidi_getParaLevel(para);
         StyleRun styleRun={ length, styleNormal };
         int width;

         if(styleRuns==NULL || styleRunCount<=0) {

        // assume styleRuns[styleRunCount-1].limit>=length

         width=getTextWidth(text, 0, length, styleRuns, styleRunCount);
         if(width<=lineWidth) {
             // everything fits onto one line

            // prepare rendering a new line from either left or right
             startLine(paraLevel, width);

             renderLine(para, text, 0, length,
                        styleRuns, styleRunCount);
         } else {
             UBiDi *line;

             // we need to render several lines
             line=ubidi_openSized(length, 0, pErrorCode);
             if(line!=NULL) {
                 int32_t start=0, limit;
                 int styleRunStart=0, styleRunLimit;

                 for(;;) {
                     getLineBreak(text, start, &limit, para,
                                  styleRuns, styleRunStart, &styleRunLimit,
                     ubidi_setLine(para, start, limit, line, pErrorCode);
                     if(U_SUCCESS(*pErrorCode)) {
                         // prepare rendering a new line
                         // from either left or right
                         startLine(paraLevel, width);

                         renderLine(line, text, start, limit,
                     if(limit==length) { break; }
                     if(start>=styleRuns[styleRunStart].limit) {



Definition in file ubidi.h.

#include "unicode/utypes.h"
#include "unicode/uchar.h"

Go to the source code of this file.
#define UBIDI_DEFAULT_LTR   0xfe
#define UBIDI_DEFAULT_RTL   0xff
typedef struct UBiDi UBiDi
typedef enum UBiDiDirection UBiDiDirection
typedef uint8_t UBiDiLevel
U_CAPI void U_EXPORT2 ubidi_close (UBiDi *pBiDi)
U_CAPI int32_t U_EXPORT2 ubidi_countRuns (UBiDi *pBiDi, UErrorCode *pErrorCode)
U_CAPI UBiDiDirection U_EXPORT2 ubidi_getDirection (const UBiDi *pBiDi)
U_CAPI int32_t U_EXPORT2 ubidi_getLength (const UBiDi *pBiDi)
U_CAPI UBiDiLevel U_EXPORT2 ubidi_getLevelAt (const UBiDi *pBiDi, int32_t charIndex)
U_CAPI const UBiDiLevel *U_EXPORT2 ubidi_getLevels (UBiDi *pBiDi, UErrorCode *pErrorCode)
U_CAPI int32_t U_EXPORT2 ubidi_getLogicalIndex (UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode)
U_CAPI void U_EXPORT2 ubidi_getLogicalMap (UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode)
U_CAPI void U_EXPORT2 ubidi_getLogicalRun (const UBiDi *pBiDi, int32_t logicalStart, int32_t *pLogicalLimit, UBiDiLevel *pLevel)
U_CAPI UBiDiLevel U_EXPORT2 ubidi_getParaLevel (const UBiDi *pBiDi)
U_CAPI const UChar *U_EXPORT2 ubidi_getText (const UBiDi *pBiDi)
U_CAPI int32_t U_EXPORT2 ubidi_getVisualIndex (UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode)
U_CAPI void U_EXPORT2 ubidi_getVisualMap (UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode)
U_CAPI UBiDiDirection U_EXPORT2 ubidi_getVisualRun (UBiDi *pBiDi, int32_t runIndex, int32_t *pLogicalStart, int32_t *pLength)
U_CAPI void U_EXPORT2 ubidi_invertMap (const int32_t *srcMap, int32_t *destMap, int32_t length)
U_CAPI UBool U_EXPORT2 ubidi_isInverse (UBiDi *pBiDi)
U_CAPI UBiDi *U_EXPORT2 ubidi_open (void)
U_CAPI UBiDi *U_EXPORT2 ubidi_openSized (int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode)
U_CAPI void U_EXPORT2 ubidi_reorderLogical (const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
U_CAPI void U_EXPORT2 ubidi_reorderVisual (const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
U_CAPI void U_EXPORT2 ubidi_setInverse (UBiDi *pBiDi, UBool isInverse)
U_CAPI void U_EXPORT2 ubidi_setLine (const UBiDi *pParaBiDi, int32_t start, int32_t limit, UBiDi *pLineBiDi, UErrorCode *pErrorCode)
U_CAPI void U_EXPORT2 ubidi_setPara (UBiDi *pBiDi, const UChar *text, int32_t length, UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels, UErrorCode *pErrorCode)
U_CAPI int32_t U_EXPORT2 ubidi_writeReordered (UBiDi *pBiDi, UChar *dest, int32_t destSize, uint16_t options, UErrorCode *pErrorCode)
U_CAPI int32_t U_EXPORT2 ubidi_writeReverse (const UChar *src, int32_t srcLength, UChar *dest, int32_t destSize, uint16_t options, UErrorCode *pErrorCode)

Generated by  Doxygen 1.6.0   Back to index