layout/base/nsBidiPresUtils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef nsBidiPresUtils_h___
     8 #define nsBidiPresUtils_h___
    10 #include "nsBidi.h"
    11 #include "nsBidiUtils.h"
    12 #include "nsHashKeys.h"
    13 #include "nsCoord.h"
    15 #ifdef DrawText
    16 #undef DrawText
    17 #endif
    19 struct BidiParagraphData;
    20 struct BidiLineData;
    21 class nsIFrame;
    22 class nsBlockFrame;
    23 class nsPresContext;
    24 class nsRenderingContext;
    25 class nsBlockInFlowLineIterator;
    26 class nsStyleContext;
    27 template<class T> class nsTHashtable;
    28 namespace mozilla { class WritingMode; }
    30 /**
    31  * A structure representing some continuation state for each frame on the line,
    32  * used to determine the first and the last continuation frame for each
    33  * continuation chain on the line.
    34  */
    35 struct nsFrameContinuationState : public nsVoidPtrHashKey
    36 {
    37   nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
    39   /**
    40    * The first visual frame in the continuation chain containing this frame, or
    41    * nullptr if this frame is the first visual frame in the chain.
    42    */
    43   nsIFrame* mFirstVisualFrame;
    45   /**
    46    * The number of frames in the continuation chain containing this frame, if
    47    * this frame is the first visual frame of the chain, or 0 otherwise.
    48    */
    49   uint32_t mFrameCount;
    51   /**
    52    * TRUE if this frame is the first visual frame of its continuation chain on
    53    * this line and the chain has some frames on the previous lines.
    54    */
    55   bool mHasContOnPrevLines;
    57   /**
    58    * TRUE if this frame is the first visual frame of its continuation chain on
    59    * this line and the chain has some frames left for next lines.
    60    */
    61   bool mHasContOnNextLines;
    62 };
    64 /*
    65  * Following type is used to pass needed hashtable to reordering methods
    66  */
    67 typedef nsTHashtable<nsFrameContinuationState> nsContinuationStates;
    69 /**
    70  * A structure representing a logical position which should be resolved
    71  * into its visual position during BiDi processing.
    72  */
    73 struct nsBidiPositionResolve
    74 {
    75   // [in] Logical index within string.
    76   int32_t logicalIndex;
    77   // [out] Visual index within string.
    78   // If the logical position was not found, set to kNotFound.
    79   int32_t visualIndex;
    80   // [out] Visual position of the character, from the left (on the X axis), in twips.
    81   // Eessentially, this is the X position (relative to the rendering context) where the text was drawn + the font metric of the visual string to the left of the given logical position.
    82   // If the logical position was not found, set to kNotFound.
    83   int32_t visualLeftTwips;
    84   // [out] Visual width of the character, in twips.
    85   // If the logical position was not found, set to kNotFound.
    86   int32_t visualWidth;
    87 };
    89 class nsBidiPresUtils {
    90 public:
    91   nsBidiPresUtils();
    92   ~nsBidiPresUtils();
    94   /**
    95    * Interface for the processor used by ProcessText. Used by process text to
    96    * collect information about the width of subruns and to notify where each
    97    * subrun should be rendered.
    98    */
    99   class BidiProcessor {
   100   public:
   101     virtual ~BidiProcessor() { }
   103     /**
   104      * Sets the current text with the given length and the given direction.
   105      *
   106      * @remark The reason that the function gives a string instead of an index
   107      *  is that ProcessText copies and modifies the string passed to it, so
   108      *  passing an index would be impossible.
   109      * 
   110      * @param aText The string of text.
   111      * @param aLength The length of the string of text.
   112      * @param aDirection The direction of the text. The string will never have
   113      *  mixed direction.
   114      */
   115     virtual void SetText(const char16_t*   aText,
   116                          int32_t            aLength,
   117                          nsBidiDirection    aDirection) = 0;
   119     /**
   120      * Returns the measured width of the text given in SetText. If SetText was
   121      * not called with valid parameters, the result of this call is undefined.
   122      * This call is guaranteed to only be called once between SetText calls.
   123      * Will be invoked before DrawText.
   124      */
   125     virtual nscoord GetWidth() = 0;
   127     /**
   128      * Draws the text given in SetText to a rendering context. If SetText was
   129      * not called with valid parameters, the result of this call is undefined.
   130      * This call is guaranteed to only be called once between SetText calls.
   131      * 
   132      * @param aXOffset The offset of the left side of the substring to be drawn
   133      *  from the beginning of the overall string passed to ProcessText.
   134      * @param aWidth The width returned by GetWidth.
   135      */
   136     virtual void DrawText(nscoord   aXOffset,
   137                           nscoord   aWidth) = 0;
   138   };
   140   /**
   141    * Make Bidi engine calculate the embedding levels of the frames that are
   142    * descendants of a given block frame.
   143    *
   144    * @param aBlockFrame          The block frame
   145    *
   146    *  @lina 06/18/2000
   147    */
   148   static nsresult Resolve(nsBlockFrame* aBlockFrame);
   149   static nsresult ResolveParagraph(nsBlockFrame* aBlockFrame,
   150                                    BidiParagraphData* aBpd);
   151   static void ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
   152                                           BidiParagraphData* aBpd);
   154   /**
   155    * Reorder this line using Bidi engine.
   156    * Update frame array, following the new visual sequence.
   157    * 
   158    * @lina 05/02/2000
   159    */
   160   static void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
   161                             int32_t              aNumFramesOnLine,
   162                             mozilla::WritingMode aLineWM,
   163                             nscoord&             aLineWidth);
   165   /**
   166    * Format Unicode text, taking into account bidi capabilities
   167    * of the platform. The formatting includes: reordering, Arabic shaping,
   168    * symmetric and numeric swapping, removing control characters.
   169    *
   170    * @lina 06/18/2000 
   171    */
   172   static nsresult FormatUnicodeText(nsPresContext* aPresContext,
   173                                     char16_t*      aText,
   174                                     int32_t&        aTextLength,
   175                                     nsCharType      aCharType,
   176                                     bool            aIsOddLevel);
   178   /**
   179    * Reorder plain text using the Unicode Bidi algorithm and send it to
   180    * a rendering context for rendering.
   181    *
   182    * @param[in] aText  the string to be rendered (in logical order)
   183    * @param aLength the number of characters in the string
   184    * @param aBaseLevel the base embedding level of the string
   185    *  odd values are right-to-left; even values are left-to-right, plus special
   186    *  constants as follows (defined in nsBidi.h)
   187    *  NSBIDI_LTR - left-to-right string
   188    *  NSBIDI_RTL - right-to-left string
   189    *  NSBIDI_DEFAULT_LTR - auto direction determined by first strong character,
   190    *                       default is left-to-right
   191    *  NSBIDI_DEFAULT_RTL - auto direction determined by first strong character,
   192    *                       default is right-to-left
   193    *
   194    * @param aPresContext the presentation context
   195    * @param aRenderingContext the rendering context to render to
   196    * @param aTextRunConstructionContext the rendering context to be used to construct the textrun (affects font hinting)
   197    * @param aX the x-coordinate to render the string
   198    * @param aY the y-coordinate to render the string
   199    * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nullptr if this functionality is not required
   200    * @param aPosResolveCount number of items in the aPosResolve array
   201    */
   202   static nsresult RenderText(const char16_t*       aText,
   203                              int32_t                aLength,
   204                              nsBidiLevel            aBaseLevel,
   205                              nsPresContext*         aPresContext,
   206                              nsRenderingContext&    aRenderingContext,
   207                              nsRenderingContext&    aTextRunConstructionContext,
   208                              nscoord                aX,
   209                              nscoord                aY,
   210                              nsBidiPositionResolve* aPosResolve = nullptr,
   211                              int32_t                aPosResolveCount = 0)
   212   {
   213     return ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
   214                                           aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
   215   }
   217   static nscoord MeasureTextWidth(const char16_t*     aText,
   218                                   int32_t              aLength,
   219                                   nsBidiLevel          aBaseLevel,
   220                                   nsPresContext*       aPresContext,
   221                                   nsRenderingContext&  aRenderingContext)
   222   {
   223     nscoord length;
   224     nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext,
   225                                                  aRenderingContext, aRenderingContext,
   226                                                  MODE_MEASURE, 0, 0, nullptr, 0, &length);
   227     return NS_SUCCEEDED(rv) ? length : 0;
   228   }
   230   /**
   231    * Check if a line is reordered, i.e., if the child frames are not
   232    * all laid out left-to-right.
   233    * @param aFirstFrameOnLine : first frame of the line to be tested
   234    * @param aNumFramesOnLine : number of frames on this line
   235    * @param[out] aLeftMost : leftmost frame on this line
   236    * @param[out] aRightMost : rightmost frame on this line
   237    */
   238   static bool CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
   239                                int32_t    aNumFramesOnLine,
   240                                nsIFrame** aLeftmost,
   241                                nsIFrame** aRightmost);
   243   /**
   244    * Get the frame to the right of the given frame, on the same line.
   245    * @param aFrame : We're looking for the frame to the right of this frame.
   246    *                 If null, return the leftmost frame on the line.
   247    * @param aFirstFrameOnLine : first frame of the line to be tested
   248    * @param aNumFramesOnLine : number of frames on this line
   249    */
   250   static nsIFrame* GetFrameToRightOf(const nsIFrame*  aFrame,
   251                                      nsIFrame*        aFirstFrameOnLine,
   252                                      int32_t          aNumFramesOnLine);
   254   /**
   255    * Get the frame to the left of the given frame, on the same line.
   256    * @param aFrame : We're looking for the frame to the left of this frame.
   257    *                 If null, return the rightmost frame on the line.
   258    * @param aFirstFrameOnLine : first frame of the line to be tested
   259    * @param aNumFramesOnLine : number of frames on this line
   260    */
   261   static nsIFrame* GetFrameToLeftOf(const nsIFrame*  aFrame,
   262                                     nsIFrame*        aFirstFrameOnLine,
   263                                     int32_t          aNumFramesOnLine);
   265   static nsIFrame* GetFirstLeaf(nsIFrame* aFrame);
   267   /**
   268    * Get the bidi embedding level of the given (inline) frame.
   269    */
   270   static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
   272   /**
   273    * Get the paragraph depth of the given (inline) frame.
   274    */
   275   static uint8_t GetParagraphDepth(nsIFrame* aFrame);
   277   /**
   278    * Get the bidi base level of the given (inline) frame.
   279    */
   280   static nsBidiLevel GetFrameBaseLevel(nsIFrame* aFrame);
   282   enum Mode { MODE_DRAW, MODE_MEASURE };
   284   /**
   285    * Reorder plain text using the Unicode Bidi algorithm and send it to
   286    * a processor for rendering or measuring
   287    *
   288    * @param[in] aText  the string to be processed (in logical order)
   289    * @param aLength the number of characters in the string
   290    * @param aBaseLevel the base embedding level of the string
   291    *  odd values are right-to-left; even values are left-to-right, plus special
   292    *  constants as follows (defined in nsBidi.h)
   293    *  NSBIDI_LTR - left-to-right string
   294    *  NSBIDI_RTL - right-to-left string
   295    *  NSBIDI_DEFAULT_LTR - auto direction determined by first strong character,
   296    *                       default is left-to-right
   297    *  NSBIDI_DEFAULT_RTL - auto direction determined by first strong character,
   298    *                       default is right-to-left
   299    *
   300    * @param aPresContext the presentation context
   301    * @param aprocessor the bidi processor
   302    * @param aMode the operation to process
   303    *  MODE_DRAW - invokes DrawText on the processor for each substring
   304    *  MODE_MEASURE - does not invoke DrawText on the processor
   305    *  Note that the string is always measured, regardless of mode
   306    * @param[in,out] aPosResolve array of logical positions to resolve into
   307    *  visual positions; can be nullptr if this functionality is not required
   308    * @param aPosResolveCount number of items in the aPosResolve array
   309    * @param[out] aWidth Pointer to where the width will be stored (may be null)
   310    */
   311   static nsresult ProcessText(const char16_t*       aText,
   312                               int32_t                aLength,
   313                               nsBidiLevel            aBaseLevel,
   314                               nsPresContext*         aPresContext,
   315                               BidiProcessor&         aprocessor,
   316                               Mode                   aMode,
   317                               nsBidiPositionResolve* aPosResolve,
   318                               int32_t                aPosResolveCount,
   319                               nscoord*               aWidth,
   320                               nsBidi*                aBidiEngine);
   322   /**
   323    * Make a copy of a string, converting from logical to visual order
   324    *
   325    * @param aSource the source string
   326    * @param aDest the destination string
   327    * @param aBaseDirection the base direction of the string
   328    *       (NSBIDI_LTR or NSBIDI_RTL to force the base direction;
   329    *        NSBIDI_DEFAULT_LTR or NSBIDI_DEFAULT_RTL to let the bidi engine
   330    *        determine the direction from rules P2 and P3 of the bidi algorithm.
   331    *  @see nsBidi::GetPara
   332    * @param aOverride if TRUE, the text has a bidi override, according to
   333    *                    the direction in aDir
   334    */
   335   static void CopyLogicalToVisual(const nsAString& aSource,
   336                                   nsAString& aDest,
   337                                   nsBidiLevel aBaseDirection,
   338                                   bool aOverride);
   340   /**
   341    * Use style attributes to determine the base paragraph level to pass to the
   342    * bidi algorithm.
   343    *
   344    * If |unicode-bidi| is set to "[-moz-]plaintext", returns NSBIDI_DEFAULT_LTR,
   345    * in other words the direction is determined from the first strong character
   346    * in the text according to rules P2 and P3 of the bidi algorithm, or LTR if
   347    * there is no strong character.
   348    *
   349    * Otherwise returns NSBIDI_LTR or NSBIDI_RTL depending on the value of
   350    * |direction|
   351    */
   352   static nsBidiLevel BidiLevelFromStyle(nsStyleContext* aStyleContext);
   354 private:
   355   static nsresult
   356   ProcessTextForRenderingContext(const char16_t*       aText,
   357                                  int32_t                aLength,
   358                                  nsBidiLevel            aBaseLevel,
   359                                  nsPresContext*         aPresContext,
   360                                  nsRenderingContext&    aRenderingContext,
   361                                  nsRenderingContext&    aTextRunConstructionContext,
   362                                  Mode                   aMode,
   363                                  nscoord                aX, // DRAW only
   364                                  nscoord                aY, // DRAW only
   365                                  nsBidiPositionResolve* aPosResolve,  /* may be null */
   366                                  int32_t                aPosResolveCount,
   367                                  nscoord*               aWidth /* may be null */);
   369   /**
   370    * Traverse the child frames of the block element and:
   371    *  Set up an array of the frames in logical order
   372    *  Create a string containing the text content of all the frames
   373    *  If we encounter content that requires us to split the element into more
   374    *  than one paragraph for bidi resolution, resolve the paragraph up to that
   375    *  point.
   376    */
   377   static void TraverseFrames(nsBlockFrame*              aBlockFrame,
   378                              nsBlockInFlowLineIterator* aLineIter,
   379                              nsIFrame*                  aCurrentFrame,
   380                              BidiParagraphData*         aBpd);
   382   /*
   383    * Position aFrame and its descendants to their visual places. Also if aFrame
   384    * is not leaf, resize it to embrace its children.
   385    *
   386    * @param aFrame               The frame which itself and its children are
   387    *                             going to be repositioned
   388    * @param aIsEvenLevel         TRUE means the embedding level of this frame
   389    *                             is even (LTR)
   390    * @param[in,out] aStart       IN value is the starting position of aFrame
   391    *                             (without considering its inline-start margin)
   392    *                             OUT value will be the ending position of aFrame
   393    *                             (after adding its inline-end margin)
   394    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
   395    */
   396   static void RepositionFrame(nsIFrame*              aFrame,
   397                               bool                   aIsEvenLevel,
   398                               nscoord&               aStart,
   399                               nsContinuationStates*  aContinuationStates,
   400                               mozilla::WritingMode   aLineWM,
   401                               nscoord&               aLineWidth);
   403   /*
   404    * Initialize the continuation state(nsFrameContinuationState) to
   405    * (nullptr, 0) for aFrame and its descendants.
   406    *
   407    * @param aFrame               The frame which itself and its descendants will
   408    *                             be initialized
   409    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
   410    */
   411   static void InitContinuationStates(nsIFrame*              aFrame,
   412                                      nsContinuationStates*  aContinuationStates);
   414   /*
   415    * Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
   416    * aIsRightMost values. Also set continuation states of aContinuationStates.
   417    *
   418    * A frame is leftmost if it's the first appearance of its continuation chain
   419    * on the line and the chain is on its first line if it's LTR or the chain is
   420    * on its last line if it's RTL.
   421    * A frame is rightmost if it's the last appearance of its continuation chain
   422    * on the line and the chain is on its first line if it's RTL or the chain is
   423    * on its last line if it's LTR.
   424    *
   425    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
   426    * @param[out] aIsLeftMost     TRUE means aFrame is leftmost frame or continuation
   427    * @param[out] aIsRightMost    TRUE means aFrame is rightmost frame or continuation
   428    */
   429    static void IsFirstOrLast(nsIFrame*              aFrame,
   430                              nsContinuationStates*  aContinuationStates,
   431                              bool&                  aIsFirst /* out */,
   432                              bool&                  aIsLast /* out */);
   434   /**
   435    *  Adjust frame positions following their visual order
   436    *
   437    *  @param aFirstChild the first kid
   438    *
   439    *  @lina 04/11/2000
   440    */
   441   static void RepositionInlineFrames(BidiLineData* aBld,
   442                                      nsIFrame* aFirstChild,
   443                                      mozilla::WritingMode aLineWM,
   444                                      nscoord& aLineWidth);
   446   /**
   447    * Helper method for Resolve()
   448    * Truncate a text frame to the end of a single-directional run and possibly
   449    * create a continuation frame for the remainder of its content.
   450    *
   451    * @param aFrame       the original frame
   452    * @param aNewFrame    [OUT] the new frame that was created
   453    * @param aFrameIndex  [IN/OUT] index of aFrame in mLogicalFrames
   454    * @param aStart       [IN] the start of the content mapped by aFrame (and 
   455    *                          any fluid continuations)
   456    * @param aEnd         [IN] the offset of the end of the single-directional
   457    *                          text run.
   458    * @see Resolve()
   459    * @see RemoveBidiContinuation()
   460    */
   461   static inline
   462   nsresult EnsureBidiContinuation(nsIFrame*       aFrame,
   463                                   nsIFrame**      aNewFrame,
   464                                   int32_t&        aFrameIndex,
   465                                   int32_t         aStart,
   466                                   int32_t         aEnd);
   468   /**
   469    * Helper method for Resolve()
   470    * Convert one or more bidi continuation frames created in a previous reflow by
   471    * EnsureBidiContinuation() into fluid continuations.
   472    * @param aFrame       the frame whose continuations are to be removed
   473    * @param aFirstIndex  index of aFrame in mLogicalFrames
   474    * @param aLastIndex   index of the last frame to be removed
   475    * @param aOffset      [OUT] count of directional frames removed. Since
   476    *                     directional frames have control characters
   477    *                     corresponding to them in mBuffer, the pointers to
   478    *                     mBuffer in Resolve() will need to be updated after
   479    *                     deleting the frames.
   480    *
   481    * @see Resolve()
   482    * @see EnsureBidiContinuation()
   483    */
   484   static void RemoveBidiContinuation(BidiParagraphData* aBpd,
   485                                      nsIFrame*          aFrame,
   486                                      int32_t            aFirstIndex,
   487                                      int32_t            aLastIndex,
   488                                      int32_t&           aOffset);
   489   static void CalculateCharType(nsBidi*          aBidiEngine,
   490                                 const char16_t* aText,
   491                                 int32_t&         aOffset,
   492                                 int32_t          aCharTypeLimit,
   493                                 int32_t&         aRunLimit,
   494                                 int32_t&         aRunLength,
   495                                 int32_t&         aRunCount,
   496                                 uint8_t&         aCharType,
   497                                 uint8_t&         aPrevCharType);
   499   static void StripBidiControlCharacters(char16_t* aText,
   500                                          int32_t&   aTextLength);
   502   static bool WriteLogicalToVisual(const char16_t* aSrc,
   503                                      uint32_t aSrcLength,
   504                                      char16_t* aDest,
   505                                      nsBidiLevel aBaseDirection,
   506                                      nsBidi* aBidiEngine);
   508   static void WriteReverse(const char16_t* aSrc,
   509                            uint32_t aSrcLength,
   510                            char16_t* aDest);
   511 };
   513 #endif /* nsBidiPresUtils_h___ */

mercurial