summaryrefslogtreecommitdiffstats
path: root/layout/base/nsBidi_noICU.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/nsBidi_noICU.h')
-rw-r--r--layout/base/nsBidi_noICU.h709
1 files changed, 709 insertions, 0 deletions
diff --git a/layout/base/nsBidi_noICU.h b/layout/base/nsBidi_noICU.h
new file mode 100644
index 000000000..a3f5aef1c
--- /dev/null
+++ b/layout/base/nsBidi_noICU.h
@@ -0,0 +1,709 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsBidi_noICU_h__
+#define nsBidi_noICU_h__
+
+#include "nsBidiUtils.h"
+#include "nsIFrame.h" // for frame property declaration
+
+// Bidi reordering engine from ICU
+/*
+ * 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 nsBidi.h
+ */
+
+/**
+ * @mainpage BIDI algorithm for Mozilla (from ICU)
+ *
+ * <h2>BIDI algorithm for Mozilla</h2>
+ *
+ * This is an implementation of the Unicode Bidirectional algorithm.
+ * The algorithm is defined in the
+ * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Technical Report 9</a>,
+ * version 5, also described in The Unicode Standard, Version 3.0 .<p>
+ *
+ * <h3>General remarks about the API:</h3>
+ *
+ * The <quote>limit</quote> of a sequence of characters is the position just after their
+ * last character, i.e., one more than that position.<p>
+ *
+ * Some of the API functions provide access to <quote>runs</quote>.
+ * Such a <quote>run</quote> is defined as a sequence of characters
+ * that are at the same embedding level
+ * after performing the BIDI algorithm.<p>
+ *
+ * @author Markus W. Scherer. Ported to Mozilla by Simon Montagu
+ * @version 1.0
+ */
+
+/**
+ * Special value which can be returned by the mapping functions when a logical
+ * index has no corresponding visual index or vice-versa.
+ * @see GetVisualIndex
+ * @see GetVisualMap
+ * @see GetLogicalIndex
+ * @see GetLogicalMap
+ */
+#define NSBIDI_MAP_NOWHERE (-1)
+
+/* miscellaneous definitions ------------------------------------------------ */
+
+/* helper macros for each allocated array member */
+#define GETDIRPROPSMEMORY(length) nsBidi::GetMemory((void **)&mDirPropsMemory, \
+ &mDirPropsSize, \
+ (length))
+
+#define GETLEVELSMEMORY(length) nsBidi::GetMemory((void **)&mLevelsMemory, \
+ &mLevelsSize, \
+ (length))
+
+#define GETRUNSMEMORY(length) nsBidi::GetMemory((void **)&mRunsMemory, \
+ &mRunsSize, \
+ (length)*sizeof(Run))
+
+#define GETISOLATESMEMORY(length) nsBidi::GetMemory((void **)&mIsolatesMemory, \
+ &mIsolatesSize, \
+ (length)*sizeof(Isolate))
+
+#define GETOPENINGSMEMORY(length) nsBidi::GetMemory((void **)&mOpeningsMemory, \
+ &mOpeningsSize, \
+ (length)*sizeof(Opening))
+
+/*
+ * Sometimes, bit values are more appropriate
+ * to deal with directionality properties.
+ * Abbreviations in these macro names refer to names
+ * used in the Bidi algorithm.
+ */
+typedef uint8_t DirProp;
+
+#define DIRPROP_FLAG(dir) (1UL<<(dir))
+
+/* special flag for multiple runs from explicit embedding codes */
+#define DIRPROP_FLAG_MULTI_RUNS (1UL<<31)
+
+/* are there any characters that are LTR or RTL? */
+#define MASK_LTR (DIRPROP_FLAG(L)|DIRPROP_FLAG(EN)|DIRPROP_FLAG(ENL)| \
+ DIRPROP_FLAG(ENR)|DIRPROP_FLAG(AN)|DIRPROP_FLAG(LRE)| \
+ DIRPROP_FLAG(LRO)|DIRPROP_FLAG(LRI))
+#define MASK_RTL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)|DIRPROP_FLAG(RLE)| \
+ DIRPROP_FLAG(RLO)|DIRPROP_FLAG(RLI))
+#define MASK_R_AL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL))
+
+/* explicit embedding codes */
+#define MASK_EXPLICIT (DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO)|DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO)|DIRPROP_FLAG(PDF))
+
+/* explicit isolate codes */
+#define MASK_ISO (DIRPROP_FLAG(LRI)|DIRPROP_FLAG(RLI)|DIRPROP_FLAG(FSI)|DIRPROP_FLAG(PDI))
+
+#define MASK_BN_EXPLICIT (DIRPROP_FLAG(BN)|MASK_EXPLICIT)
+
+/* paragraph and segment separators */
+#define MASK_B_S (DIRPROP_FLAG(B)|DIRPROP_FLAG(S))
+
+/* all types that are counted as White Space or Neutral in some steps */
+#define MASK_WS (MASK_B_S|DIRPROP_FLAG(WS)|MASK_BN_EXPLICIT|MASK_ISO)
+
+/* types that are neutrals or could becomes neutrals in (Wn) */
+#define MASK_POSSIBLE_N (DIRPROP_FLAG(O_N)|DIRPROP_FLAG(CS)|DIRPROP_FLAG(ES)|DIRPROP_FLAG(ET)|MASK_WS)
+
+/*
+ * These types may be changed to "e",
+ * the embedding type (L or R) of the run,
+ * in the Bidi algorithm (N2)
+ */
+#define MASK_EMBEDDING (DIRPROP_FLAG(NSM)|MASK_POSSIBLE_N)
+
+/* the dirProp's L and R are defined to 0 and 1 values in nsCharType */
+#define GET_LR_FROM_LEVEL(level) ((DirProp)((level)&1))
+
+#define IS_DEFAULT_LEVEL(level) (((level)&0xfe)==0xfe)
+
+/*
+ * The following bit is used for the directional isolate status.
+ * Stack entries corresponding to isolate sequences are greater than ISOLATE.
+ */
+#define ISOLATE 0x0100
+
+/* number of isolate entries allocated initially without malloc */
+#define SIMPLE_ISOLATES_SIZE 5
+
+/* number of isolate run entries for paired brackets allocated initially without malloc */
+#define SIMPLE_OPENINGS_COUNT 8
+
+/* handle surrogate pairs --------------------------------------------------- */
+
+#define IS_FIRST_SURROGATE(uchar) (((uchar)&0xfc00)==0xd800)
+#define IS_SECOND_SURROGATE(uchar) (((uchar)&0xfc00)==0xdc00)
+
+/* get the UTF-32 value directly from the surrogate pseudo-characters */
+#define SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
+#define GET_UTF_32(first, second) (((first)<<10UL)+(second)-SURROGATE_OFFSET)
+
+#if !ENABLE_INTL_API // these are provided by ICU if present in the build
+
+#define UTF_ERROR_VALUE 0xffff
+/* definitions with forward iteration --------------------------------------- */
+
+/*
+ * all the macros that go forward assume that
+ * the initial offset is 0<=i<length;
+ * they update the offset
+ */
+
+/* fast versions, no error-checking */
+
+#define UTF16_APPEND_CHAR_UNSAFE(s, i, c){ \
+ if((uint32_t)(c)<=0xffff) { \
+ (s)[(i)++]=(char16_t)(c); \
+ } else { \
+ (s)[(i)++]=(char16_t)((c)>>10)+0xd7c0; \
+ (s)[(i)++]=(char16_t)(c)&0x3ff|0xdc00; \
+ } \
+}
+
+/* safe versions with error-checking and optional regularity-checking */
+
+#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \
+ if((PRUInt32)(c)<=0xffff) { \
+ (s)[(i)++]=(char16_t)(c); \
+ } else if((PRUInt32)(c)<=0x10ffff) { \
+ if((i)+1<(length)) { \
+ (s)[(i)++]=(char16_t)((c)>>10)+0xd7c0; \
+ (s)[(i)++]=(char16_t)(c)&0x3ff|0xdc00; \
+ } else /* not enough space */ { \
+ (s)[(i)++]=UTF_ERROR_VALUE; \
+ } \
+ } else /* c>0x10ffff, write error value */ { \
+ (s)[(i)++]=UTF_ERROR_VALUE; \
+ } \
+}
+
+/* definitions with backward iteration -------------------------------------- */
+
+/*
+ * all the macros that go backward assume that
+ * the valid buffer range starts at offset 0
+ * and that the initial offset is 0<i<=length;
+ * they update the offset
+ */
+
+/* fast versions, no error-checking */
+
+/*
+ * Get a single code point from an offset that points behind the last
+ * of the code units that belong to that code point.
+ * Assume 0<=i<length.
+ */
+#define UTF16_PREV_CHAR_UNSAFE(s, i, c) { \
+ (c)=(s)[--(i)]; \
+ if(IS_SECOND_SURROGATE(c)) { \
+ (c)=GET_UTF_32((s)[--(i)], (c)); \
+ } \
+}
+
+#define UTF16_BACK_1_UNSAFE(s, i) { \
+ if(IS_SECOND_SURROGATE((s)[--(i)])) { \
+ --(i); \
+ } \
+}
+
+#define UTF16_BACK_N_UNSAFE(s, i, n) { \
+ int32_t __N=(n); \
+ while(__N>0) { \
+ UTF16_BACK_1_UNSAFE(s, i); \
+ --__N; \
+ } \
+}
+
+/* safe versions with error-checking and optional regularity-checking */
+
+#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \
+ (c)=(s)[--(i)]; \
+ if(IS_SECOND_SURROGATE(c)) { \
+ char16_t __c2; \
+ if((i)>(start) && IS_FIRST_SURROGATE(__c2=(s)[(i)-1])) { \
+ --(i); \
+ (c)=GET_UTF_32(__c2, (c)); \
+ /* strict: ((c)&0xfffe)==0xfffe is caught by UTF_IS_ERROR() */ \
+ } else if(strict) {\
+ /* unmatched second surrogate */ \
+ (c)=UTF_ERROR_VALUE; \
+ } \
+ } else if(strict && IS_FIRST_SURROGATE(c)) { \
+ /* unmatched first surrogate */ \
+ (c)=UTF_ERROR_VALUE; \
+ /* else strict: (c)==0xfffe is caught by UTF_IS_ERROR() */ \
+ } \
+}
+
+#define UTF16_BACK_1_SAFE(s, start, i) { \
+ if(IS_SECOND_SURROGATE((s)[--(i)]) && (i)>(start) && IS_FIRST_SURROGATE((s)[(i)-1])) { \
+ --(i); \
+ } \
+}
+
+#define UTF16_BACK_N_SAFE(s, start, i, n) { \
+ int32_t __N=(n); \
+ while(__N>0 && (i)>(start)) { \
+ UTF16_BACK_1_SAFE(s, start, i); \
+ --__N; \
+ } \
+}
+
+#define UTF_PREV_CHAR_UNSAFE(s, i, c) UTF16_PREV_CHAR_UNSAFE(s, i, c)
+#define UTF_PREV_CHAR_SAFE(s, start, i, c, strict) UTF16_PREV_CHAR_SAFE(s, start, i, c, strict)
+#define UTF_BACK_1_UNSAFE(s, i) UTF16_BACK_1_UNSAFE(s, i)
+#define UTF_BACK_1_SAFE(s, start, i) UTF16_BACK_1_SAFE(s, start, i)
+#define UTF_BACK_N_UNSAFE(s, i, n) UTF16_BACK_N_UNSAFE(s, i, n)
+#define UTF_BACK_N_SAFE(s, start, i, n) UTF16_BACK_N_SAFE(s, start, i, n)
+#define UTF_APPEND_CHAR_UNSAFE(s, i, c) UTF16_APPEND_CHAR_UNSAFE(s, i, c)
+#define UTF_APPEND_CHAR_SAFE(s, i, length, c) UTF16_APPEND_CHAR_SAFE(s, i, length, c)
+
+#define UTF_PREV_CHAR(s, start, i, c) UTF_PREV_CHAR_SAFE(s, start, i, c, false)
+#define UTF_BACK_1(s, start, i) UTF_BACK_1_SAFE(s, start, i)
+#define UTF_BACK_N(s, start, i, n) UTF_BACK_N_SAFE(s, start, i, n)
+#define UTF_APPEND_CHAR(s, i, length, c) UTF_APPEND_CHAR_SAFE(s, i, length, c)
+
+#endif // !ENABLE_INTL_API
+
+struct Isolate {
+ int32_t start1;
+ int16_t stateImp;
+ int16_t state;
+};
+
+// For bracket matching
+
+#define FOUND_L DIRPROP_FLAG(L)
+#define FOUND_R DIRPROP_FLAG(R)
+
+struct Opening {
+ int32_t position; /* position of opening bracket */
+ int32_t match; /* matching char or -position of closing bracket */
+ int32_t contextPos; /* position of last strong char found before opening */
+ uint16_t flags; /* bits for L or R/AL found within the pair */
+ DirProp contextDir; /* L or R according to last strong char before opening */
+ uint8_t filler; /* to complete a nice multiple of 4 chars */
+};
+
+struct IsoRun {
+ int32_t contextPos; /* position of char determining context */
+ uint16_t start; /* index of first opening entry for this run */
+ uint16_t limit; /* index after last opening entry for this run */
+ nsBidiLevel level; /* level of this run */
+ DirProp lastStrong; /* bidi class of last strong char found in this run */
+ DirProp lastBase; /* bidi class of last base char found in this run */
+ DirProp contextDir; /* L or R to use as context for following openings */
+};
+
+class nsBidi;
+
+/* Run structure for reordering --------------------------------------------- */
+
+typedef struct Run {
+ int32_t logicalStart; /* first character of the run; b31 indicates even/odd level */
+ int32_t visualLimit; /* last visual position of the run +1 */
+} Run;
+
+/* in a Run, logicalStart will get this bit set if the run level is odd */
+#define INDEX_ODD_BIT (1UL<<31)
+
+#define MAKE_INDEX_ODD_PAIR(index, level) (index|((uint32_t)level<<31))
+#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((uint32_t)level<<31))
+#define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT)
+
+#define GET_INDEX(x) ((x)&~INDEX_ODD_BIT)
+#define GET_ODD_BIT(x) ((uint32_t)(x)>>31)
+#define IS_ODD_RUN(x) (((x)&INDEX_ODD_BIT)!=0)
+#define IS_EVEN_RUN(x) (((x)&INDEX_ODD_BIT)==0)
+
+typedef uint32_t Flags;
+
+enum { DirProp_L=0, DirProp_R=1, DirProp_EN=2, DirProp_AN=3, DirProp_ON=4, DirProp_S=5, DirProp_B=6 }; /* reduced dirProp */
+
+#define IMPTABLEVELS_COLUMNS (DirProp_B + 2)
+typedef const uint8_t ImpTab[][IMPTABLEVELS_COLUMNS];
+typedef const uint8_t (*PImpTab)[IMPTABLEVELS_COLUMNS];
+
+typedef const uint8_t ImpAct[];
+typedef const uint8_t *PImpAct;
+
+struct LevState {
+ PImpTab pImpTab; /* level table pointer */
+ PImpAct pImpAct; /* action map array */
+ int32_t startON; /* start of ON sequence */
+ int32_t state; /* current state */
+ int32_t runStart; /* start position of the run */
+ nsBidiLevel runLevel; /* run level before implicit solving */
+};
+
+/**
+ * This class holds information about a paragraph of text
+ * with Bidi-algorithm-related details, or about one line of
+ * such a paragraph.<p>
+ * Reordering can be done on a line, or on a paragraph which is
+ * then interpreted as one single line.<p>
+ *
+ * On construction, the class is initially empty. It is assigned
+ * the Bidi properties of a paragraph by <code>SetPara</code>
+ * or the Bidi properties of a line of a paragraph by
+ * <code>SetLine</code>.<p>
+ * A Bidi class can be reused for as long as it is not deallocated
+ * by calling its destructor.<p>
+ * <code>SetPara</code> will allocate additional memory for
+ * internal structures as necessary.
+ */
+class nsBidi
+{
+public:
+ /** @brief Default constructor.
+ *
+ * The nsBidi object is initially empty. It is assigned
+ * the Bidi properties of a paragraph by <code>SetPara()</code>
+ * or the Bidi properties of a line of a paragraph by
+ * <code>GetLine()</code>.<p>
+ * This object can be reused for as long as it is not destroyed.<p>
+ * <code>SetPara()</code> will allocate additional memory for
+ * internal structures as necessary.
+ *
+ */
+ nsBidi();
+
+ /** @brief Destructor. */
+ virtual ~nsBidi();
+
+
+ /**
+ * Perform the Unicode Bidi algorithm. It is defined in the
+ * <a href="http://www.unicode.org/unicode/reports/tr9/">Unicode Technical Report 9</a>,
+ * version 5,
+ * also described in The Unicode Standard, Version 3.0 .<p>
+ *
+ * This function takes a single plain text paragraph with or without
+ * externally specified embedding levels from <quote>styled</quote> text
+ * and computes the left-right-directionality of each character.<p>
+ *
+ * If the entire paragraph consists of text of only one direction, then
+ * the function may not perform all the steps described by the algorithm,
+ * i.e., some levels may not be the same as if all steps were performed.
+ * This is not relevant for unidirectional text.<br>
+ * For example, in pure LTR text with numbers the numbers would get
+ * a resolved level of 2 higher than the surrounding text according to
+ * the algorithm. This implementation may set all resolved levels to
+ * the same value in such a case.<p>
+ *
+ * The text must be externally split into separate paragraphs (rule P1).
+ * Paragraph separators (B) should appear at most at the very end.
+ *
+ * @param aText is a pointer to the single-paragraph text that the
+ * Bidi algorithm will be performed on
+ * (step (P1) of the algorithm is performed externally).
+ * <strong>The text must be (at least) <code>aLength</code> long.</strong>
+ *
+ * @param aLength is the length of the text; if <code>aLength==-1</code> then
+ * the text must be zero-terminated.
+ *
+ * @param aParaLevel specifies the default level for the paragraph;
+ * it is typically 0 (LTR) or 1 (RTL).
+ * If the function shall determine the paragraph level from the text,
+ * then <code>aParaLevel</code> can be set to
+ * either <code>NSBIDI_DEFAULT_LTR</code>
+ * or <code>NSBIDI_DEFAULT_RTL</code>;
+ * if there is no strongly typed character, then
+ * the desired default is used (0 for LTR or 1 for RTL).
+ * Any other value between 0 and <code>NSBIDI_MAX_EXPLICIT_LEVEL</code> is also valid,
+ * with odd levels indicating RTL.
+ */
+ nsresult SetPara(const char16_t *aText, int32_t aLength, nsBidiLevel aParaLevel);
+
+ /**
+ * Get the directionality of the text.
+ *
+ * @param aDirection receives a <code>NSBIDI_XXX</code> value that indicates if the entire text
+ * represented by this object is unidirectional,
+ * and which direction, or if it is mixed-directional.
+ *
+ * @see nsBidiDirection
+ */
+ nsresult GetDirection(nsBidiDirection* aDirection);
+
+ /**
+ * Get the paragraph level of the text.
+ *
+ * @param aParaLevel receives a <code>NSBIDI_XXX</code> value indicating the paragraph level
+ *
+ * @see nsBidiLevel
+ */
+ nsresult GetParaLevel(nsBidiLevel* aParaLevel);
+
+ /**
+ * Get a logical run.
+ * This function returns information about a run and is used
+ * to retrieve runs in logical order.<p>
+ * This is especially useful for line-breaking on a paragraph.
+ *
+ * @param aLogicalStart is the first character of the run.
+ *
+ * @param aLogicalLimit will receive the limit of the run.
+ * The l-value that you point to here may be the
+ * same expression (variable) as the one for
+ * <code>aLogicalStart</code>.
+ * This pointer can be <code>nullptr</code> if this
+ * value is not necessary.
+ *
+ * @param aLevel will receive the level of the run.
+ * This pointer can be <code>nullptr</code> if this
+ * value is not necessary.
+ */
+ nsresult GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, nsBidiLevel* aLevel);
+
+ /**
+ * Get the number of runs.
+ * This function may invoke the actual reordering on the
+ * <code>nsBidi</code> object, after <code>SetPara</code>
+ * may have resolved only the levels of the text. Therefore,
+ * <code>CountRuns</code> may have to allocate memory,
+ * and may fail doing so.
+ *
+ * @param aRunCount will receive the number of runs.
+ */
+ nsresult CountRuns(int32_t* aRunCount);
+
+ /**
+ * Get one run's logical start, length, and directionality,
+ * which can be 0 for LTR or 1 for RTL.
+ * In an RTL run, the character at the logical start is
+ * visually on the right of the displayed run.
+ * The length is the number of characters in the run.<p>
+ * <code>CountRuns</code> should be called
+ * before the runs are retrieved.
+ *
+ * @param aRunIndex is the number of the run in visual order, in the
+ * range <code>[0..CountRuns-1]</code>.
+ *
+ * @param aLogicalStart is the first logical character index in the text.
+ * The pointer may be <code>nullptr</code> if this index is not needed.
+ *
+ * @param aLength is the number of characters (at least one) in the run.
+ * The pointer may be <code>nullptr</code> if this is not needed.
+ *
+ * @param aDirection will receive the directionality of the run,
+ * <code>NSBIDI_LTR==0</code> or <code>NSBIDI_RTL==1</code>,
+ * never <code>NSBIDI_MIXED</code>.
+ *
+ * @see CountRuns<p>
+ *
+ * Example:
+ * @code
+ * int32_t i, count, logicalStart, visualIndex=0, length;
+ * nsBidiDirection dir;
+ * pBidi->CountRuns(&count);
+ * for(i=0; i<count; ++i) {
+ * pBidi->GetVisualRun(i, &logicalStart, &length, &dir);
+ * if(NSBIDI_LTR==dir) {
+ * do { // LTR
+ * show_char(text[logicalStart++], visualIndex++);
+ * } while(--length>0);
+ * } else {
+ * logicalStart+=length; // logicalLimit
+ * do { // RTL
+ * show_char(text[--logicalStart], visualIndex++);
+ * } while(--length>0);
+ * }
+ * }
+ * @endcode
+ *
+ * Note that in right-to-left runs, code like this places
+ * modifier letters before base characters and second surrogates
+ * before first ones.
+ */
+ nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, int32_t* aLength, nsBidiDirection* aDirection);
+
+ /**
+ * This is a convenience function that does not use a nsBidi object.
+ * It is intended to be used for when an application has determined the levels
+ * of objects (character sequences) and just needs to have them reordered (L2).
+ * This is equivalent to using <code>GetVisualMap</code> on a
+ * <code>nsBidi</code> object.
+ *
+ * @param aLevels is an array with <code>aLength</code> levels that have been determined by
+ * the application.
+ *
+ * @param aLength is the number of levels in the array, or, semantically,
+ * the number of objects to be reordered.
+ * It must be <code>aLength>0</code>.
+ *
+ * @param aIndexMap is a pointer to an array of <code>aLength</code>
+ * indexes which will reflect the reordering of the characters.
+ * The array does not need to be initialized.<p>
+ * The index map will result in <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>.
+ */
+ static nsresult ReorderVisual(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap);
+
+ /**
+ * Reverse a Right-To-Left run of Unicode text.
+ *
+ * This function preserves the integrity of characters with multiple
+ * code units and (optionally) modifier letters.
+ * Characters can be replaced by mirror-image characters
+ * in the destination buffer. Note that "real" mirroring has
+ * to be done in a rendering engine by glyph selection
+ * and that for many "mirrored" characters there are no
+ * Unicode characters as mirror-image equivalents.
+ * There are also options to insert or remove Bidi control
+ * characters; see the description of the <code>aDestSize</code>
+ * and <code>aOptions</code> parameters and of the option bit flags.
+ *
+ * Since no Bidi controls are inserted here, this function will never
+ * write more than <code>aSrcLength</code> characters to <code>aDest</code>.
+ *
+ * @param aSrc A pointer to the RTL run text.
+ *
+ * @param aSrcLength The length of the RTL run.
+ * If the <code>NSBIDI_REMOVE_BIDI_CONTROLS</code> option
+ * is set, then the destination length may be less than
+ * <code>aSrcLength</code>.
+ * If this option is not set, then the destination length
+ * will be exactly <code>aSrcLength</code>.
+ *
+ * @param aDest A pointer to where the reordered text is to be copied.
+ * <code>aSrc[aSrcLength]</code> and <code>aDest[aSrcLength]</code>
+ * must not overlap.
+ *
+ * @param aOptions A bit set of options for the reordering that control
+ * how the reordered text is written.
+ *
+ * @param aDestSize will receive the number of characters that were written to <code>aDest</code>.
+ */
+ nsresult WriteReverse(const char16_t *aSrc, int32_t aSrcLength, char16_t *aDest, uint16_t aOptions, int32_t *aDestSize);
+
+protected:
+ friend class nsBidiPresUtils;
+
+ class BracketData {
+ public:
+ explicit BracketData(const nsBidi* aBidi);
+ ~BracketData();
+
+ void ProcessBoundary(int32_t aLastDirControlCharPos,
+ nsBidiLevel aContextLevel,
+ nsBidiLevel aEmbeddingLevel,
+ const DirProp* aDirProps);
+ void ProcessLRI_RLI(nsBidiLevel aLevel);
+ void ProcessPDI();
+ bool AddOpening(char16_t aMatch, int32_t aPosition);
+ void FixN0c(int32_t aOpeningIndex, int32_t aNewPropPosition,
+ DirProp aNewProp, DirProp* aDirProps);
+ DirProp ProcessClosing(int32_t aOpenIdx, int32_t aPosition,
+ DirProp* aDirProps);
+ bool ProcessChar(int32_t aPosition, char16_t aCh, DirProp* aDirProps,
+ nsBidiLevel* aLevels);
+
+ private:
+ // array of opening entries which should be enough in most cases;
+ // no malloc() needed
+ Opening mSimpleOpenings[SIMPLE_OPENINGS_COUNT];
+ Opening* mOpenings; // pointer to current array of entries,
+ // either mSimpleOpenings or malloced array
+
+ Opening* mOpeningsMemory;
+ size_t mOpeningsSize;
+
+ // array of nested isolated sequence entries; can never exceed
+ // UBIDI_MAX_EXPLICIT_LEVEL
+ // + 1 for index 0
+ // + 1 for before the first isolated sequence
+ IsoRun mIsoRuns[NSBIDI_MAX_EXPLICIT_LEVEL+2];
+ int32_t mIsoRunLast; // index of last used entry in mIsoRuns
+
+ int32_t mOpeningsCount; // number of allocated entries in mOpenings
+ };
+
+ /** length of the current text */
+ int32_t mLength;
+
+ /** memory sizes in bytes */
+ size_t mDirPropsSize, mLevelsSize, mRunsSize;
+ size_t mIsolatesSize;
+
+ /** allocated memory */
+ DirProp* mDirPropsMemory;
+ nsBidiLevel* mLevelsMemory;
+ Run* mRunsMemory;
+ Isolate* mIsolatesMemory;
+
+ DirProp* mDirProps;
+ nsBidiLevel* mLevels;
+
+ /** the paragraph level */
+ nsBidiLevel mParaLevel;
+
+ /** flags is a bit set for which directional properties are in the text */
+ Flags mFlags;
+
+ /** the overall paragraph or line directionality - see nsBidiDirection */
+ nsBidiDirection mDirection;
+
+ /** characters after trailingWSStart are WS and are */
+ /* implicitly at the paraLevel (rule (L1)) - levels may not reflect that */
+ int32_t mTrailingWSStart;
+
+ /** fields for line reordering */
+ int32_t mRunCount; /* ==-1: runs not set up yet */
+ Run* mRuns;
+
+ /** for non-mixed text, we only need a tiny array of runs (no malloc()) */
+ Run mSimpleRuns[1];
+
+ /* maxium of current nesting depth of isolate sequences */
+ /* Within ResolveExplicitLevels() and checkExpicitLevels(), this is the maximal
+ nesting encountered.
+ Within ResolveImplicitLevels(), this is the index of the current isolates
+ stack entry. */
+ int32_t mIsolateCount;
+ Isolate* mIsolates;
+
+ /** for simple text, have a small stack (no malloc()) */
+ Isolate mSimpleIsolates[SIMPLE_ISOLATES_SIZE];
+
+private:
+
+ void Init();
+
+ static bool GetMemory(void **aMemory, size_t* aSize, size_t aSizeNeeded);
+
+ void Free();
+
+ void GetDirProps(const char16_t *aText);
+
+ void ResolveExplicitLevels(nsBidiDirection *aDirection, const char16_t *aText);
+
+ nsBidiDirection DirectionFromFlags(Flags aFlags);
+
+ void ProcessPropertySeq(LevState *pLevState, uint8_t _prop, int32_t start, int32_t limit);
+
+ void ResolveImplicitLevels(int32_t aStart, int32_t aLimit, DirProp aSOR, DirProp aEOR);
+
+ void AdjustWSLevels();
+
+ void SetTrailingWSStart();
+
+ bool GetRuns();
+
+ void GetSingleRun(nsBidiLevel aLevel);
+
+ void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel);
+
+ static bool PrepareReorder(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel);
+};
+
+#endif // _nsBidi_noICU_h_