Loading layout/base/moz.build +0 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ EXPORTS += [ "LayoutLogging.h", "MobileViewportManager.h", "nsAutoLayoutPhase.h", "nsBidi.h", "nsBidiPresUtils.h", "nsCaret.h", "nsChangeHint.h", Loading Loading @@ -109,7 +108,6 @@ UNIFIED_SOURCES += [ "LayoutTelemetryTools.cpp", "MobileViewportManager.cpp", "MotionPathUtils.cpp", "nsBidi.cpp", "nsBidiPresUtils.cpp", "nsCaret.cpp", "nsCounterManager.cpp", Loading layout/base/nsBidi.cppdeleted 100644 → 0 +0 −42 Original line number Diff line number Diff line /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "nsBidi.h" nsresult nsBidi::CountRuns(int32_t* aRunCount) { UErrorCode errorCode = U_ZERO_ERROR; *aRunCount = ubidi_countRuns(mBiDi, &errorCode); if (U_SUCCESS(errorCode)) { mLength = ubidi_getProcessedLength(mBiDi); mLevels = mLength > 0 ? ubidi_getLevels(mBiDi, &errorCode) : nullptr; } return ICUUtils::UErrorToNsResult(errorCode); } void nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, nsBidiLevel* aLevel) { MOZ_ASSERT(mLevels, "CountRuns hasn't been run?"); MOZ_RELEASE_ASSERT(aLogicalStart < mLength, "Out of bound"); // This function implements an alternative approach to get logical // run that is based on levels of characters, which would avoid O(n^2) // performance issue when used in a loop over runs. // Per comment in ubidi_getLogicalRun, that function doesn't use this // approach because levels have special interpretation when reordering // mode is UBIDI_REORDER_RUNS_ONLY. Since we don't use this mode in // Gecko, it should be safe to just use levels for this function. MOZ_ASSERT(ubidi_getReorderingMode(mBiDi) != UBIDI_REORDER_RUNS_ONLY, "Don't support UBIDI_REORDER_RUNS_ONLY mode"); nsBidiLevel level = mLevels[aLogicalStart]; int32_t limit; for (limit = aLogicalStart + 1; limit < mLength; limit++) { if (mLevels[limit] != level) { break; } } *aLogicalLimit = limit; *aLevel = level; } layout/base/nsBidi.hdeleted 100644 → 0 +0 −208 Original line number Diff line number Diff line /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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_h__ #define nsBidi_h__ #include "unicode/ubidi.h" #include "ICUUtils.h" #include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations // nsBidi implemented as a simple wrapper around the bidi reordering engine // from ICU. // We could eliminate this and let callers use the ICU functions directly // once we no longer care about building without ICU available. 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>. */ nsBidi() { mBiDi = ubidi_open(); } /** @brief Destructor. */ ~nsBidi() { ubidi_close(mBiDi); } /** * Perform the Unicode Bidi algorithm. * * @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) { UErrorCode error = U_ZERO_ERROR; ubidi_setPara(mBiDi, reinterpret_cast<const UChar*>(aText), aLength, aParaLevel, nullptr, &error); return ICUUtils::UErrorToNsResult(error); } /** * 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 */ nsBidiDirection GetDirection() { return nsBidiDirection(ubidi_getDirection(mBiDi)); } /** * Get the paragraph level of the text. * * @param aParaLevel receives a <code>NSBIDI_XXX</code> value indicating * the paragraph level * * @see nsBidiLevel */ nsBidiLevel GetParaLevel() { return ubidi_getParaLevel(mBiDi); } /** * 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. * <code>CountRuns</code> should be called before this. * before the runs are retrieved. * * @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 cannot be <code>nullptr</code>. * * @param aLevel will receive the level of the run. * This pointer cannot be <code>nullptr</code>. */ void 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. * * @returns 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) { * dir = pBidi->GetVisualRun(i, &logicalStart, &length); * 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. */ nsBidiDirection GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, int32_t* aLength) { return nsBidiDirection( ubidi_getVisualRun(mBiDi, aRunIndex, aLogicalStart, aLength)); } /** * 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 void ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, int32_t* aIndexMap) { ubidi_reorderVisual(aLevels, aLength, aIndexMap); } private: nsBidi(const nsBidi&) = delete; void operator=(const nsBidi&) = delete; UBiDi* mBiDi; // The two fields below are updated when CountRuns is called. const nsBidiLevel* mLevels = nullptr; int32_t mLength = 0; }; #endif // _nsBidi_h_ Loading
layout/base/moz.build +0 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ EXPORTS += [ "LayoutLogging.h", "MobileViewportManager.h", "nsAutoLayoutPhase.h", "nsBidi.h", "nsBidiPresUtils.h", "nsCaret.h", "nsChangeHint.h", Loading Loading @@ -109,7 +108,6 @@ UNIFIED_SOURCES += [ "LayoutTelemetryTools.cpp", "MobileViewportManager.cpp", "MotionPathUtils.cpp", "nsBidi.cpp", "nsBidiPresUtils.cpp", "nsCaret.cpp", "nsCounterManager.cpp", Loading
layout/base/nsBidi.cppdeleted 100644 → 0 +0 −42 Original line number Diff line number Diff line /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "nsBidi.h" nsresult nsBidi::CountRuns(int32_t* aRunCount) { UErrorCode errorCode = U_ZERO_ERROR; *aRunCount = ubidi_countRuns(mBiDi, &errorCode); if (U_SUCCESS(errorCode)) { mLength = ubidi_getProcessedLength(mBiDi); mLevels = mLength > 0 ? ubidi_getLevels(mBiDi, &errorCode) : nullptr; } return ICUUtils::UErrorToNsResult(errorCode); } void nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, nsBidiLevel* aLevel) { MOZ_ASSERT(mLevels, "CountRuns hasn't been run?"); MOZ_RELEASE_ASSERT(aLogicalStart < mLength, "Out of bound"); // This function implements an alternative approach to get logical // run that is based on levels of characters, which would avoid O(n^2) // performance issue when used in a loop over runs. // Per comment in ubidi_getLogicalRun, that function doesn't use this // approach because levels have special interpretation when reordering // mode is UBIDI_REORDER_RUNS_ONLY. Since we don't use this mode in // Gecko, it should be safe to just use levels for this function. MOZ_ASSERT(ubidi_getReorderingMode(mBiDi) != UBIDI_REORDER_RUNS_ONLY, "Don't support UBIDI_REORDER_RUNS_ONLY mode"); nsBidiLevel level = mLevels[aLogicalStart]; int32_t limit; for (limit = aLogicalStart + 1; limit < mLength; limit++) { if (mLevels[limit] != level) { break; } } *aLogicalLimit = limit; *aLevel = level; }
layout/base/nsBidi.hdeleted 100644 → 0 +0 −208 Original line number Diff line number Diff line /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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_h__ #define nsBidi_h__ #include "unicode/ubidi.h" #include "ICUUtils.h" #include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations // nsBidi implemented as a simple wrapper around the bidi reordering engine // from ICU. // We could eliminate this and let callers use the ICU functions directly // once we no longer care about building without ICU available. 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>. */ nsBidi() { mBiDi = ubidi_open(); } /** @brief Destructor. */ ~nsBidi() { ubidi_close(mBiDi); } /** * Perform the Unicode Bidi algorithm. * * @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) { UErrorCode error = U_ZERO_ERROR; ubidi_setPara(mBiDi, reinterpret_cast<const UChar*>(aText), aLength, aParaLevel, nullptr, &error); return ICUUtils::UErrorToNsResult(error); } /** * 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 */ nsBidiDirection GetDirection() { return nsBidiDirection(ubidi_getDirection(mBiDi)); } /** * Get the paragraph level of the text. * * @param aParaLevel receives a <code>NSBIDI_XXX</code> value indicating * the paragraph level * * @see nsBidiLevel */ nsBidiLevel GetParaLevel() { return ubidi_getParaLevel(mBiDi); } /** * 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. * <code>CountRuns</code> should be called before this. * before the runs are retrieved. * * @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 cannot be <code>nullptr</code>. * * @param aLevel will receive the level of the run. * This pointer cannot be <code>nullptr</code>. */ void 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. * * @returns 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) { * dir = pBidi->GetVisualRun(i, &logicalStart, &length); * 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. */ nsBidiDirection GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, int32_t* aLength) { return nsBidiDirection( ubidi_getVisualRun(mBiDi, aRunIndex, aLogicalStart, aLength)); } /** * 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 void ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, int32_t* aIndexMap) { ubidi_reorderVisual(aLevels, aLength, aIndexMap); } private: nsBidi(const nsBidi&) = delete; void operator=(const nsBidi&) = delete; UBiDi* mBiDi; // The two fields below are updated when CountRuns is called. const nsBidiLevel* mLevels = nullptr; int32_t mLength = 0; }; #endif // _nsBidi_h_