/* ****************************************************************************** * * Copyright (C) 1999-2001, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** * file name: ubidi.h * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 1999jul27 * created by: Markus W. Scherer */ #ifndef UBIDI_H #define UBIDI_H #include "unicode/utypes.h" #include "unicode/uchar.h" /* * javadoc-style comments are intended to be transformed into HTML * using DOC++ - see * http://www.zib.de/Visual/software/doc++/index.html . * * The HTML documentation is created with * doc++ -H ubidi.h * * The following #define trick allows us to do it all in one file * and still be able to compile it. */ /*#define DOCXX_TAG*/ /*#define BIDI_SAMPLE_CODE*/ /** *\file * \brief 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.

* * @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:

* * *
 * \code
 *#include "unicode/ubidi.h"
 *
 *typedef enum {
 *     styleNormal=0, styleSelected=1,
 *     styleBold=2, styleItalics=4,
 *     styleSuper=8, styleSub=16
 *} Style;
 *
 *typedef struct { UTextOffset limit; Style style; } StyleRun;
 *
 *int getTextWidth(const UChar *text, UTextOffset start, UTextOffset 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, UTextOffset start, UTextOffset *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, UTextOffset start, UTextOffset 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,
 *                           UTextOffset start, UTextOffset limit,
 *                           UBiDiDirection direction,
 *                           const StyleRun *styleRuns, int styleRunCount) {
 *     int i;
 *
 *     // iterate over style runs
 *     if(direction==UBIDI_LTR) {
 *         int styleLimit;
 *
 *         for(i=0; ilimit) { 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=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) {
 *                 UTextOffset 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);
 *}
 *\endcode
 * 
*/ /*DOCXX_TAG*/ /*@{*/ /** * UBiDiLevel is the type of the level values in this * BiDi implementation. * It holds an embedding level and indicates the visual direction * by its bit 0 (even/odd value).

* * It can also hold non-level values for the * paraLevel and embeddingLevels * arguments of ubidi_setPara(); there: *