Logo Search packages:      
Sourcecode: icu version File versions  Download package

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 Standard Annex #9, version 13, also described in The Unicode Standard, Version 4.0 .

Note: Libraries that perform a bidirectional algorithm and reorder strings accordingly are sometimes called "Storage Layout Engines". ICU's Bidi and shaping (u_shapeArabic()) APIs can be used at the core of such "Storage Layout Engines".

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.

Author:
Markus W. Scherer
Version:
1.0

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) {
             styleLimit=styleRun[i].limit;
             if(start<styleLimit) {
                 if(styleLimit>limit) { styleLimit=limit; }
                 renderRun(text, start, styleLimit,
                           direction, styleRun[i].style);
                 if(styleLimit==limit) { break; }
                 start=styleLimit;
             }
         }
     } else {
         int styleStart;

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

 // 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) {
         return;
     }

     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) {
            styleRunCount=1;
             styleRuns=&styleRun;
         }

        // 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(;;) {
                     limit=length;
                     styleRunLimit=styleRunCount;
                     getLineBreak(text, start, &limit, para,
                                  styleRuns, styleRunStart, &styleRunLimit,
                                 &width);
                     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,
                                    styleRuns+styleRunStart,
                                    styleRunLimit-styleRunStart);
                     }
                     if(limit==length) { break; }
                     start=limit;
                     styleRunStart=styleRunLimit-1;
                     if(start>=styleRuns[styleRunStart].limit) {
                         ++styleRunStart;
                     }
                 }

                 ubidi_close(line);
             }
        }
    }

     ubidi_close(para);
 *}
 *

Definition in file ubidi.h.

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

Go to the source code of this file.
#define U_BIDI_CLASS_DEFAULT   U_CHAR_DIRECTION_COUNT
#define UBIDI_DEFAULT_LTR   0xfe
#define UBIDI_DEFAULT_RTL   0xff
#define UBIDI_DO_MIRRORING   2
#define UBIDI_INSERT_LRM_FOR_NUMERIC   4
#define UBIDI_KEEP_BASE_COMBINING   1
#define UBIDI_LEVEL_OVERRIDE   0x80
#define UBIDI_MAP_NOWHERE   (-1)
#define UBIDI_MAX_EXPLICIT_LEVEL   61
#define UBIDI_OUTPUT_REVERSE   16
#define UBIDI_REMOVE_BIDI_CONTROLS   8
enum  UBiDiDirection { UBIDI_LTR, UBIDI_RTL, UBIDI_MIXED }
enum  UBiDiReorderingMode {
  UBIDI_REORDER_DEFAULT = 0, UBIDI_REORDER_NUMBERS_SPECIAL, UBIDI_REORDER_GROUP_NUMBERS_WITH_R, UBIDI_REORDER_RUNS_ONLY,
  UBIDI_REORDER_INVERSE_NUMBERS_AS_L, UBIDI_REORDER_INVERSE_LIKE_DIRECT, UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL, UBIDI_REORDER_COUNT
}
enum  UBiDiReorderingOption { UBIDI_OPTION_DEFAULT = 0, UBIDI_OPTION_INSERT_MARKS = 1, UBIDI_OPTION_REMOVE_CONTROLS = 2, UBIDI_OPTION_STREAMING = 4 }
typedef struct UBiDi UBiDi
typedef UCharDirection U_CALLCONV UBiDiClassCallback (const void *context, UChar32 c)
typedef enum UBiDiDirection UBiDiDirection
typedef uint8_t UBiDiLevel
U_STABLE void U_EXPORT2 ubidi_close (UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_countParagraphs (UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_countRuns (UBiDi *pBiDi, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_getClassCallback (UBiDi *pBiDi, UBiDiClassCallback **fn, const void **context)
U_CDECL_END U_STABLE
UCharDirection U_EXPORT2 
ubidi_getCustomizedClass (UBiDi *pBiDi, UChar32 c)
U_STABLE UBiDiDirection U_EXPORT2 ubidi_getDirection (const UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_getLength (const UBiDi *pBiDi)
U_STABLE UBiDiLevel U_EXPORT2 ubidi_getLevelAt (const UBiDi *pBiDi, int32_t charIndex)
U_STABLE const UBiDiLevel
*U_EXPORT2 
ubidi_getLevels (UBiDi *pBiDi, UErrorCode *pErrorCode)
U_STABLE int32_t U_EXPORT2 ubidi_getLogicalIndex (UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_getLogicalMap (UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_getLogicalRun (const UBiDi *pBiDi, int32_t logicalPosition, int32_t *pLogicalLimit, UBiDiLevel *pLevel)
U_STABLE int32_t U_EXPORT2 ubidi_getParagraph (const UBiDi *pBiDi, int32_t charIndex, int32_t *pParaStart, int32_t *pParaLimit, UBiDiLevel *pParaLevel, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_getParagraphByIndex (const UBiDi *pBiDi, int32_t paraIndex, int32_t *pParaStart, int32_t *pParaLimit, UBiDiLevel *pParaLevel, UErrorCode *pErrorCode)
U_STABLE UBiDiLevel U_EXPORT2 ubidi_getParaLevel (const UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_getProcessedLength (const UBiDi *pBiDi)
U_STABLE UBiDiReorderingMode
U_EXPORT2 
ubidi_getReorderingMode (UBiDi *pBiDi)
U_STABLE uint32_t U_EXPORT2 ubidi_getReorderingOptions (UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_getResultLength (const UBiDi *pBiDi)
U_STABLE const UChar *U_EXPORT2 ubidi_getText (const UBiDi *pBiDi)
U_STABLE int32_t U_EXPORT2 ubidi_getVisualIndex (UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_getVisualMap (UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode)
U_STABLE UBiDiDirection U_EXPORT2 ubidi_getVisualRun (UBiDi *pBiDi, int32_t runIndex, int32_t *pLogicalStart, int32_t *pLength)
U_STABLE void U_EXPORT2 ubidi_invertMap (const int32_t *srcMap, int32_t *destMap, int32_t length)
U_STABLE UBool U_EXPORT2 ubidi_isInverse (UBiDi *pBiDi)
U_STABLE UBool U_EXPORT2 ubidi_isOrderParagraphsLTR (UBiDi *pBiDi)
U_STABLE UBiDi *U_EXPORT2 ubidi_open (void)
U_STABLE UBiDi *U_EXPORT2 ubidi_openSized (int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_orderParagraphsLTR (UBiDi *pBiDi, UBool orderParagraphsLTR)
U_STABLE void U_EXPORT2 ubidi_reorderLogical (const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
U_STABLE void U_EXPORT2 ubidi_reorderVisual (const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
U_STABLE void U_EXPORT2 ubidi_setClassCallback (UBiDi *pBiDi, UBiDiClassCallback *newFn, const void *newContext, UBiDiClassCallback **oldFn, const void **oldContext, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_setInverse (UBiDi *pBiDi, UBool isInverse)
U_STABLE void U_EXPORT2 ubidi_setLine (const UBiDi *pParaBiDi, int32_t start, int32_t limit, UBiDi *pLineBiDi, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_setPara (UBiDi *pBiDi, const UChar *text, int32_t length, UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels, UErrorCode *pErrorCode)
U_STABLE void U_EXPORT2 ubidi_setReorderingMode (UBiDi *pBiDi, UBiDiReorderingMode reorderingMode)
U_STABLE void U_EXPORT2 ubidi_setReorderingOptions (UBiDi *pBiDi, uint32_t reorderingOptions)
U_STABLE int32_t U_EXPORT2 ubidi_writeReordered (UBiDi *pBiDi, UChar *dest, int32_t destSize, uint16_t options, UErrorCode *pErrorCode)
U_STABLE 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