LCOV - code coverage report
Current view: top level - dom/base - nsLineBreaker.h (source / functions) Hit Total Coverage
Test: output.info Lines: 10 18 55.6 %
Date: 2017-07-14 16:53:18 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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/. */
       6             : 
       7             : #ifndef NSLINEBREAKER_H_
       8             : #define NSLINEBREAKER_H_
       9             : 
      10             : #include "nsString.h"
      11             : #include "nsTArray.h"
      12             : #include "nsILineBreaker.h"
      13             : 
      14             : class nsIAtom;
      15             : class nsHyphenator;
      16             : 
      17             : /**
      18             :  * A receiver of line break data.
      19             :  */
      20          21 : class nsILineBreakSink {
      21             : public:
      22             :   /**
      23             :    * Sets the break data for a substring of the associated text chunk.
      24             :    * One or more of these calls will be performed; the union of all substrings
      25             :    * will cover the entire text chunk. Substrings may overlap (i.e., we may
      26             :    * set the break-before state of a character more than once).
      27             :    * @param aBreakBefore the break-before states for the characters in the substring.
      28             :    * These are enum values from gfxTextRun::CompressedGlyph:
      29             :    *    FLAG_BREAK_TYPE_NONE     - no linebreak is allowed here
      30             :    *    FLAG_BREAK_TYPE_NORMAL   - a normal (whitespace) linebreak
      31             :    *    FLAG_BREAK_TYPE_HYPHEN   - a hyphenation point
      32             :    */
      33             :   virtual void SetBreaks(uint32_t aStart, uint32_t aLength, uint8_t* aBreakBefore) = 0;
      34             : 
      35             :   /**
      36             :    * Indicates which characters should be capitalized. Only called if
      37             :    * BREAK_NEED_CAPITALIZATION was requested.
      38             :    */
      39             :   virtual void SetCapitalization(uint32_t aStart, uint32_t aLength, bool* aCapitalize) = 0;
      40             : };
      41             : 
      42             : /**
      43             :  * A line-breaking state machine. You feed text into it via AppendText calls
      44             :  * and it computes the possible line breaks. Because break decisions can
      45             :  * require a lot of context, the breaks for a piece of text are sometimes not
      46             :  * known until later text has been seen (or all text ends). So breaks are
      47             :  * returned via a call to SetBreaks on the nsILineBreakSink object passed
      48             :  * with each text chunk, which might happen during the corresponding AppendText
      49             :  * call, or might happen during a later AppendText call or even a Reset()
      50             :  * call.
      51             :  *
      52             :  * The linebreak results MUST NOT depend on how the text is broken up
      53             :  * into AppendText calls.
      54             :  *
      55             :  * The current strategy is that we break the overall text into
      56             :  * whitespace-delimited "words". Then those words are passed to the nsILineBreaker
      57             :  * service for deeper analysis if they contain a "complex" character as described
      58             :  * below.
      59             :  *
      60             :  * This class also handles detection of which characters should be capitalized
      61             :  * for text-transform:capitalize. This is a good place to handle that because
      62             :  * we have all the context we need.
      63             :  */
      64             : class nsLineBreaker {
      65             : public:
      66             :   nsLineBreaker();
      67             :   ~nsLineBreaker();
      68             : 
      69         301 :   static inline bool IsSpace(char16_t u) { return NS_IsSpace(u); }
      70             : 
      71          67 :   static inline bool IsComplexASCIIChar(char16_t u)
      72             :   {
      73         133 :     return !((0x0030 <= u && u <= 0x0039) ||
      74         177 :              (0x0041 <= u && u <= 0x005A) ||
      75         110 :              (0x0061 <= u && u <= 0x007A) ||
      76          67 :              (0x000a == u));
      77             :   }
      78             : 
      79           0 :   static inline bool IsComplexChar(char16_t u)
      80             :   {
      81           0 :     return IsComplexASCIIChar(u) ||
      82           0 :            NS_NeedsPlatformNativeHandling(u) ||
      83           0 :            (0x1100 <= u && u <= 0x11ff) || // Hangul Jamo
      84           0 :            (0x2000 <= u && u <= 0x21ff) || // Punctuations and Symbols
      85           0 :            (0x2e80 <= u && u <= 0xd7ff) || // several CJK blocks
      86           0 :            (0xf900 <= u && u <= 0xfaff) || // CJK Compatibility Idographs
      87           0 :            (0xff00 <= u && u <= 0xffef);   // Halfwidth and Fullwidth Forms
      88             :   }
      89             : 
      90             :   // Break opportunities exist at the end of each run of breakable whitespace
      91             :   // (see IsSpace above). Break opportunities can also exist between pairs of
      92             :   // non-whitespace characters, as determined by nsILineBreaker. We pass a whitespace-
      93             :   // delimited word to nsILineBreaker if it contains at least one character
      94             :   // matching IsComplexChar.
      95             :   // We provide flags to control on a per-chunk basis where breaks are allowed.
      96             :   // At any character boundary, exactly one text chunk governs whether a
      97             :   // break is allowed at that boundary.
      98             :   //
      99             :   // We operate on text after whitespace processing has been applied, so
     100             :   // other characters (e.g. tabs and newlines) may have been converted to
     101             :   // spaces.
     102             : 
     103             :   /**
     104             :    * Flags passed with each chunk of text.
     105             :    */
     106             :   enum {
     107             :     /*
     108             :      * Do not introduce a break opportunity at the start of this chunk of text.
     109             :      */
     110             :     BREAK_SUPPRESS_INITIAL = 0x01,
     111             :     /**
     112             :      * Do not introduce a break opportunity in the interior of this chunk of text.
     113             :      * Also, whitespace in this chunk is treated as non-breakable.
     114             :      */
     115             :     BREAK_SUPPRESS_INSIDE = 0x02,
     116             :     /**
     117             :      * The sink currently is already set up to have no breaks in it;
     118             :      * if no breaks are possible, nsLineBreaker does not need to call
     119             :      * SetBreaks on it. This is useful when handling large quantities of
     120             :      * preformatted text; the textruns will never have any breaks set on them,
     121             :      * and there is no need to ever actually scan the text for breaks, except
     122             :      * at the end of textruns in case context is needed for following breakable
     123             :      * text.
     124             :      */
     125             :     BREAK_SKIP_SETTING_NO_BREAKS = 0x04,
     126             :     /**
     127             :      * We need to be notified of characters that should be capitalized
     128             :      * (as in text-transform:capitalize) in this chunk of text.
     129             :      */
     130             :     BREAK_NEED_CAPITALIZATION = 0x08,
     131             :     /**
     132             :      * Auto-hyphenation is enabled, so we need to get a hyphenator
     133             :      * (if available) and use it to find breakpoints.
     134             :      */
     135             :     BREAK_USE_AUTO_HYPHENATION = 0x10
     136             :   };
     137             : 
     138             :   /**
     139             :    * Append "invisible whitespace". This acts like whitespace, but there is
     140             :    * no actual text associated with it. Only the BREAK_SUPPRESS_INSIDE flag
     141             :    * is relevant here.
     142             :    */
     143             :   nsresult AppendInvisibleWhitespace(uint32_t aFlags);
     144             : 
     145             :   /**
     146             :    * Feed Unicode text into the linebreaker for analysis. aLength must be
     147             :    * nonzero.
     148             :    * @param aSink can be null if the breaks are not actually needed (we may
     149             :    * still be setting up state for later breaks)
     150             :    */
     151             :   nsresult AppendText(nsIAtom* aHyphenationLanguage, const char16_t* aText, uint32_t aLength,
     152             :                       uint32_t aFlags, nsILineBreakSink* aSink);
     153             :   /**
     154             :    * Feed 8-bit text into the linebreaker for analysis. aLength must be nonzero.
     155             :    * @param aSink can be null if the breaks are not actually needed (we may
     156             :    * still be setting up state for later breaks)
     157             :    */
     158             :   nsresult AppendText(nsIAtom* aHyphenationLanguage, const uint8_t* aText, uint32_t aLength,
     159             :                       uint32_t aFlags, nsILineBreakSink* aSink);
     160             :   /**
     161             :    * Reset all state. This means the current run has ended; any outstanding
     162             :    * calls through nsILineBreakSink are made, and all outstanding references to
     163             :    * nsILineBreakSink objects are dropped.
     164             :    * After this call, this linebreaker can be reused.
     165             :    * This must be called at least once between any call to AppendText() and
     166             :    * destroying the object.
     167             :    * @param aTrailingBreak this is set to true when there is a break opportunity
     168             :    * at the end of the text. This will normally only be declared true when there
     169             :    * is breakable whitespace at the end.
     170             :    */
     171             :   nsresult Reset(bool* aTrailingBreak);
     172             : 
     173             :   /*
     174             :    * Set word-break mode for linebreaker.  This is set by word-break property.
     175             :    * @param aMode is nsILineBreaker::kWordBreak_* value.
     176             :    */
     177          21 :   void SetWordBreak(uint8_t aMode) { mWordBreak = aMode; }
     178             : 
     179             : private:
     180             :   // This is a list of text sources that make up the "current word" (i.e.,
     181             :   // run of text which does not contain any whitespace). All the mLengths
     182             :   // are are nonzero, these cannot overlap.
     183             :   struct TextItem {
     184           9 :     TextItem(nsILineBreakSink* aSink, uint32_t aSinkOffset, uint32_t aLength,
     185             :              uint32_t aFlags)
     186           9 :       : mSink(aSink), mSinkOffset(aSinkOffset), mLength(aLength), mFlags(aFlags) {}
     187             : 
     188             :     nsILineBreakSink* mSink;
     189             :     uint32_t          mSinkOffset;
     190             :     uint32_t          mLength;
     191             :     uint32_t          mFlags;
     192             :   };
     193             : 
     194             :   // State for the nonwhitespace "word" that started in previous text and hasn't
     195             :   // finished yet.
     196             : 
     197             :   // When the current word ends, this computes the linebreak opportunities
     198             :   // *inside* the word (excluding either end) and sets them through the
     199             :   // appropriate sink(s). Then we clear the current word state.
     200             :   nsresult FlushCurrentWord();
     201             : 
     202             :   void UpdateCurrentWordLanguage(nsIAtom *aHyphenationLanguage);
     203             : 
     204             :   void FindHyphenationPoints(nsHyphenator *aHyphenator,
     205             :                              const char16_t *aTextStart,
     206             :                              const char16_t *aTextLimit,
     207             :                              uint8_t *aBreakState);
     208             : 
     209             :   AutoTArray<char16_t,100> mCurrentWord;
     210             :   // All the items that contribute to mCurrentWord
     211             :   AutoTArray<TextItem,2>    mTextItems;
     212             :   nsIAtom*                    mCurrentWordLanguage;
     213             :   bool                        mCurrentWordContainsMixedLang;
     214             :   bool                        mCurrentWordContainsComplexChar;
     215             : 
     216             :   // True if the previous character was breakable whitespace
     217             :   bool                        mAfterBreakableSpace;
     218             :   // True if a break must be allowed at the current position because
     219             :   // a run of breakable whitespace ends here
     220             :   bool                        mBreakHere;
     221             :   // line break mode by "word-break" style
     222             :   uint8_t                     mWordBreak;
     223             : };
     224             : 
     225             : #endif /*NSLINEBREAKER_H_*/

Generated by: LCOV version 1.13