jpayne@69: /* jpayne@69: ****************************************************************************** jpayne@69: * jpayne@69: * © 2016 and later: Unicode, Inc. and others. jpayne@69: * License & terms of use: http://www.unicode.org/copyright.html jpayne@69: * jpayne@69: ****************************************************************************** jpayne@69: * file name: ubiditransform.h jpayne@69: * encoding: UTF-8 jpayne@69: * tab size: 8 (not used) jpayne@69: * indentation:4 jpayne@69: * jpayne@69: * created on: 2016jul24 jpayne@69: * created by: Lina Kemmel jpayne@69: * jpayne@69: */ jpayne@69: jpayne@69: #ifndef UBIDITRANSFORM_H jpayne@69: #define UBIDITRANSFORM_H jpayne@69: jpayne@69: #include "unicode/utypes.h" jpayne@69: #include "unicode/ubidi.h" jpayne@69: #include "unicode/uchar.h" jpayne@69: #include "unicode/localpointer.h" jpayne@69: jpayne@69: /** jpayne@69: * \file jpayne@69: * \brief Bidi Transformations jpayne@69: */ jpayne@69: jpayne@69: /** jpayne@69: * `UBiDiOrder` indicates the order of text. jpayne@69: * jpayne@69: * This bidi transformation engine supports all possible combinations (4 in jpayne@69: * total) of input and output text order: jpayne@69: * jpayne@69: * - : unless the output direction is RTL, this jpayne@69: * corresponds to a normal operation of the Bidi algorithm as described in the jpayne@69: * Unicode Technical Report and implemented by `UBiDi` when the jpayne@69: * reordering mode is set to `UBIDI_REORDER_DEFAULT`. Visual RTL jpayne@69: * mode is not supported by `UBiDi` and is accomplished through jpayne@69: * reversing a visual LTR string, jpayne@69: * jpayne@69: * - : unless the input direction is RTL, this jpayne@69: * corresponds to an "inverse bidi algorithm" in `UBiDi` with the jpayne@69: * reordering mode set to `UBIDI_REORDER_INVERSE_LIKE_DIRECT`. jpayne@69: * Visual RTL mode is not not supported by `UBiDi` and is jpayne@69: * accomplished through reversing a visual LTR string, jpayne@69: * jpayne@69: * - : if the input and output base directions jpayne@69: * mismatch, this corresponds to the `UBiDi` implementation with the jpayne@69: * reordering mode set to `UBIDI_REORDER_RUNS_ONLY`; and if the jpayne@69: * input and output base directions are identical, the transformation engine jpayne@69: * will only handle character mirroring and Arabic shaping operations without jpayne@69: * reordering, jpayne@69: * jpayne@69: * - : this reordering mode is not supported by jpayne@69: * the `UBiDi` engine; it implies character mirroring, Arabic jpayne@69: * shaping, and - if the input/output base directions mismatch - string jpayne@69: * reverse operations. jpayne@69: * @see ubidi_setInverse jpayne@69: * @see ubidi_setReorderingMode jpayne@69: * @see UBIDI_REORDER_DEFAULT jpayne@69: * @see UBIDI_REORDER_INVERSE_LIKE_DIRECT jpayne@69: * @see UBIDI_REORDER_RUNS_ONLY jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: typedef enum { jpayne@69: /** 0: Constant indicating a logical order. jpayne@69: * This is the default for input text. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: UBIDI_LOGICAL = 0, jpayne@69: /** 1: Constant indicating a visual order. jpayne@69: * This is a default for output text. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: UBIDI_VISUAL jpayne@69: } UBiDiOrder; jpayne@69: jpayne@69: /** jpayne@69: * UBiDiMirroring indicates whether or not characters with the jpayne@69: * "mirrored" property in RTL runs should be replaced with their mirror-image jpayne@69: * counterparts. jpayne@69: * @see UBIDI_DO_MIRRORING jpayne@69: * @see ubidi_setReorderingOptions jpayne@69: * @see ubidi_writeReordered jpayne@69: * @see ubidi_writeReverse jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: typedef enum { jpayne@69: /** 0: Constant indicating that character mirroring should not be jpayne@69: * performed. jpayne@69: * This is the default. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: UBIDI_MIRRORING_OFF = 0, jpayne@69: /** 1: Constant indicating that character mirroring should be performed. jpayne@69: * This corresponds to calling ubidi_writeReordered or jpayne@69: * ubidi_writeReverse with the jpayne@69: * UBIDI_DO_MIRRORING option bit set. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: UBIDI_MIRRORING_ON jpayne@69: } UBiDiMirroring; jpayne@69: jpayne@69: /** jpayne@69: * Forward declaration of the UBiDiTransform structure that stores jpayne@69: * information used by the layout transformation engine. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: typedef struct UBiDiTransform UBiDiTransform; jpayne@69: jpayne@69: /** jpayne@69: * Performs transformation of text from the bidi layout defined by the input jpayne@69: * ordering scheme to the bidi layout defined by the output ordering scheme, jpayne@69: * and applies character mirroring and Arabic shaping operations.

jpayne@69: * In terms of UBiDi, such a transformation implies: jpayne@69: *

    jpayne@69: *
  • calling ubidi_setReorderingMode as needed (when the jpayne@69: * reordering mode is other than normal),
  • jpayne@69: *
  • calling ubidi_setInverse as needed (when text should be jpayne@69: * transformed from a visual to a logical form),
  • jpayne@69: *
  • resolving embedding levels of each character in the input text by jpayne@69: * calling ubidi_setPara,
  • jpayne@69: *
  • reordering the characters based on the computed embedding levels, also jpayne@69: * performing character mirroring as needed, and streaming the result to the jpayne@69: * output, by calling ubidi_writeReordered,
  • jpayne@69: *
  • performing Arabic digit and letter shaping on the output text by calling jpayne@69: * u_shapeArabic.
  • jpayne@69: *
jpayne@69: * An "ordering scheme" encompasses the base direction and the order of text, jpayne@69: * and these characteristics must be defined by the caller for both input and jpayne@69: * output explicitly .

jpayne@69: * There are 36 possible combinations of ordering schemes, jpayne@69: * which are partially supported by UBiDi already. Examples of the jpayne@69: * currently supported combinations: jpayne@69: *

    jpayne@69: *
  • : this is equivalent to calling jpayne@69: * ubidi_setPara with paraLevel == UBIDI_LTR,
  • jpayne@69: *
  • : this is equivalent to calling jpayne@69: * ubidi_setPara with paraLevel == UBIDI_RTL,
  • jpayne@69: *
  • : this is equivalent to jpayne@69: * calling ubidi_setPara with jpayne@69: * paraLevel == UBIDI_DEFAULT_LTR,
  • jpayne@69: *
  • : this is equivalent to jpayne@69: * calling ubidi_setPara with jpayne@69: * paraLevel == UBIDI_DEFAULT_RTL,
  • jpayne@69: *
  • : this is equivalent to jpayne@69: * calling ubidi_setInverse(UBiDi*, TRUE) and then jpayne@69: * ubidi_setPara with paraLevel == UBIDI_LTR,
  • jpayne@69: *
  • : this is equivalent to jpayne@69: * calling ubidi_setInverse(UBiDi*, TRUE) and then jpayne@69: * ubidi_setPara with paraLevel == UBIDI_RTL.
  • jpayne@69: *
jpayne@69: * All combinations that involve the Visual RTL scheme are unsupported by jpayne@69: * UBiDi, for instance: jpayne@69: *
    jpayne@69: *
  • ,
  • jpayne@69: *
  • .
  • jpayne@69: *
jpayne@69: *

Example of usage of the transformation engine:
jpayne@69: *

jpayne@69:  * \code
jpayne@69:  * UChar text1[] = {'a', 'b', 'c', 0x0625, '1', 0};
jpayne@69:  * UChar text2[] = {'a', 'b', 'c', 0x0625, '1', 0};
jpayne@69:  * UErrorCode errorCode = U_ZERO_ERROR;
jpayne@69:  * // Run a transformation.
jpayne@69:  * ubiditransform_transform(pBidiTransform,
jpayne@69:  *          text1, -1, text2, -1,
jpayne@69:  *          UBIDI_LTR, UBIDI_VISUAL,
jpayne@69:  *          UBIDI_RTL, UBIDI_LOGICAL,
jpayne@69:  *          UBIDI_MIRRORING_OFF,
jpayne@69:  *          U_SHAPE_DIGITS_AN2EN | U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
jpayne@69:  *          &errorCode);
jpayne@69:  * // Do something with text2.
jpayne@69:  *  text2[4] = '2';
jpayne@69:  * // Run a reverse transformation.
jpayne@69:  * ubiditransform_transform(pBidiTransform,
jpayne@69:  *          text2, -1, text1, -1,
jpayne@69:  *          UBIDI_RTL, UBIDI_LOGICAL,
jpayne@69:  *          UBIDI_LTR, UBIDI_VISUAL,
jpayne@69:  *          UBIDI_MIRRORING_OFF,
jpayne@69:  *          U_SHAPE_DIGITS_EN2AN | U_SHAPE_DIGIT_TYPE_AN_EXTENDED,
jpayne@69:  *          &errorCode);
jpayne@69:  *\endcode
jpayne@69:  * 
jpayne@69: *

jpayne@69: * jpayne@69: * @param pBiDiTransform A pointer to a UBiDiTransform object jpayne@69: * allocated with ubiditransform_open() or jpayne@69: * NULL.

jpayne@69: * This object serves for one-time setup to amortize initialization jpayne@69: * overheads. Use of this object is not thread-safe. All other threads jpayne@69: * should allocate a new UBiDiTransform object by calling jpayne@69: * ubiditransform_open() before using it. Alternatively, jpayne@69: * a caller can set this parameter to NULL, in which case jpayne@69: * the object will be allocated by the engine on the fly.

jpayne@69: * @param src A pointer to the text that the Bidi layout transformations will jpayne@69: * be performed on. jpayne@69: *

Note: the text must be (at least) jpayne@69: * srcLength long.

jpayne@69: * @param srcLength The length of the text, in number of UChars. If jpayne@69: * length == -1 then the text must be zero-terminated. jpayne@69: * @param dest A pointer to where the processed text is to be copied. jpayne@69: * @param destSize The size of the dest buffer, in number of jpayne@69: * UChars. If the U_SHAPE_LETTERS_UNSHAPE option is set, jpayne@69: * then the destination length could be as large as jpayne@69: * srcLength * 2. Otherwise, the destination length will jpayne@69: * not exceed srcLength. If the caller reserves the last jpayne@69: * position for zero-termination, it should be excluded from jpayne@69: * destSize. jpayne@69: *

destSize == -1 is allowed and makes sense when jpayne@69: * dest was holds some meaningful value, e.g. that of jpayne@69: * src. In this case dest must be jpayne@69: * zero-terminated.

jpayne@69: * @param inParaLevel A base embedding level of the input as defined in jpayne@69: * ubidi_setPara documentation for the jpayne@69: * paraLevel parameter. jpayne@69: * @param inOrder An order of the input, which can be one of the jpayne@69: * UBiDiOrder values. jpayne@69: * @param outParaLevel A base embedding level of the output as defined in jpayne@69: * ubidi_setPara documentation for the jpayne@69: * paraLevel parameter. jpayne@69: * @param outOrder An order of the output, which can be one of the jpayne@69: * UBiDiOrder values. jpayne@69: * @param doMirroring Indicates whether or not to perform character mirroring, jpayne@69: * and can accept one of the UBiDiMirroring values. jpayne@69: * @param shapingOptions Arabic digit and letter shaping options defined in the jpayne@69: * ushape.h documentation. jpayne@69: *

Note: Direction indicator options are computed by jpayne@69: * the transformation engine based on the effective ordering schemes, so jpayne@69: * user-defined direction indicators will be ignored.

jpayne@69: * @param pErrorCode A pointer to an error code value. jpayne@69: * jpayne@69: * @return The destination length, i.e. the number of UChars written to jpayne@69: * dest. If the transformation fails, the return value jpayne@69: * will be 0 (and the error code will be written to jpayne@69: * pErrorCode). jpayne@69: * jpayne@69: * @see UBiDiLevel jpayne@69: * @see UBiDiOrder jpayne@69: * @see UBiDiMirroring jpayne@69: * @see ubidi_setPara jpayne@69: * @see u_shapeArabic jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: U_STABLE uint32_t U_EXPORT2 jpayne@69: ubiditransform_transform(UBiDiTransform *pBiDiTransform, jpayne@69: const UChar *src, int32_t srcLength, jpayne@69: UChar *dest, int32_t destSize, jpayne@69: UBiDiLevel inParaLevel, UBiDiOrder inOrder, jpayne@69: UBiDiLevel outParaLevel, UBiDiOrder outOrder, jpayne@69: UBiDiMirroring doMirroring, uint32_t shapingOptions, jpayne@69: UErrorCode *pErrorCode); jpayne@69: jpayne@69: /** jpayne@69: * Allocates a UBiDiTransform object. This object can be reused, jpayne@69: * e.g. with different ordering schemes, mirroring or shaping options.

jpayne@69: * Note:The object can only be reused in the same thread. jpayne@69: * All other threads should allocate a new UBiDiTransform object jpayne@69: * before using it.

jpayne@69: * Example of usage:

jpayne@69: *

jpayne@69:  * \code
jpayne@69:  * UErrorCode errorCode = U_ZERO_ERROR;
jpayne@69:  * // Open a new UBiDiTransform.
jpayne@69:  * UBiDiTransform* transform = ubiditransform_open(&errorCode);
jpayne@69:  * // Run a transformation.
jpayne@69:  * ubiditransform_transform(transform,
jpayne@69:  *          text1, -1, text2, -1,
jpayne@69:  *          UBIDI_RTL, UBIDI_LOGICAL,
jpayne@69:  *          UBIDI_LTR, UBIDI_VISUAL,
jpayne@69:  *          UBIDI_MIRRORING_ON,
jpayne@69:  *          U_SHAPE_DIGITS_EN2AN,
jpayne@69:  *          &errorCode);
jpayne@69:  * // Do something with the output text and invoke another transformation using
jpayne@69:  * //   that text as input.
jpayne@69:  * ubiditransform_transform(transform,
jpayne@69:  *          text2, -1, text3, -1,
jpayne@69:  *          UBIDI_LTR, UBIDI_VISUAL,
jpayne@69:  *          UBIDI_RTL, UBIDI_VISUAL,
jpayne@69:  *          UBIDI_MIRRORING_ON,
jpayne@69:  *          0, &errorCode);
jpayne@69:  *\endcode
jpayne@69:  * 
jpayne@69: *

jpayne@69: * The UBiDiTransform object must be deallocated by calling jpayne@69: * ubiditransform_close(). jpayne@69: * jpayne@69: * @return An empty UBiDiTransform object. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: U_STABLE UBiDiTransform* U_EXPORT2 jpayne@69: ubiditransform_open(UErrorCode *pErrorCode); jpayne@69: jpayne@69: /** jpayne@69: * Deallocates the given UBiDiTransform object. jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: U_STABLE void U_EXPORT2 jpayne@69: ubiditransform_close(UBiDiTransform *pBidiTransform); jpayne@69: jpayne@69: #if U_SHOW_CPLUSPLUS_API jpayne@69: jpayne@69: U_NAMESPACE_BEGIN jpayne@69: jpayne@69: /** jpayne@69: * \class LocalUBiDiTransformPointer jpayne@69: * "Smart pointer" class, closes a UBiDiTransform via ubiditransform_close(). jpayne@69: * For most methods see the LocalPointerBase base class. jpayne@69: * jpayne@69: * @see LocalPointerBase jpayne@69: * @see LocalPointer jpayne@69: * @stable ICU 58 jpayne@69: */ jpayne@69: U_DEFINE_LOCAL_OPEN_POINTER(LocalUBiDiTransformPointer, UBiDiTransform, ubiditransform_close); jpayne@69: jpayne@69: U_NAMESPACE_END jpayne@69: jpayne@69: #endif jpayne@69: jpayne@69: #endif