nsTextFrameUtils.h (8342B)
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 NSTEXTFRAMEUTILS_H_ 8 #define NSTEXTFRAMEUTILS_H_ 9 10 #include "gfxSkipChars.h" 11 #include "nsBidiUtils.h" 12 13 class nsAtom; 14 class nsIContent; 15 struct nsStyleText; 16 17 namespace mozilla { 18 namespace dom { 19 class Text; 20 } 21 } // namespace mozilla 22 23 #define BIG_TEXT_NODE_SIZE 4096 24 25 #define CH_NBSP 160 26 #define CH_SHY 173 27 #define CH_CJKSP 12288 // U+3000 IDEOGRAPHIC SPACE (CJK Full-Width Space) 28 29 class nsTextFrameUtils { 30 public: 31 // These constants are used as textrun flags for textframe textruns. 32 // 33 // If you add a flag, please add support for it in gfxTextRun::Dump. 34 enum class Flags : uint16_t { 35 // The following flags are set by TransformText 36 37 // the text has at least one untransformed tab character 38 HasTab = 0x01, 39 // the original text has at least one soft hyphen character 40 HasShy = 0x02, 41 // the text has at least one untransformed newline character 42 HasNewline = 0x04, 43 44 // Flag used in textrun construction to *prevent* hiding of fallback text 45 // for pending user-fonts (used for Canvas2d text). 46 DontSkipDrawingForPendingUserFonts = 0x08, 47 48 // The following flags are set by nsTextFrame 49 50 IsSimpleFlow = 0x10, 51 IncomingWhitespace = 0x20, 52 TrailingWhitespace = 0x40, 53 CompressedLeadingWhitespace = 0x80, 54 NoBreaks = 0x100, 55 IsTransformed = 0x200, 56 // This gets set if there's a break opportunity at the end of the textrun. 57 // We normally don't use this break opportunity because the following text 58 // will have a break opportunity at the start, but it's useful for line 59 // layout to know about it in case the following content is not text 60 HasTrailingBreak = 0x400, 61 62 // This is set if the textrun was created for a textframe whose 63 // NS_FRAME_IS_IN_SINGLE_CHAR_MI flag is set. This occurs if the textframe 64 // belongs to a MathML <mi> element whose embedded text consists of a 65 // single character. 66 IsSingleCharMi = 0x800, 67 68 // This is set if the text run might be observing for glyph changes. 69 MightHaveGlyphChanges = 0x1000, 70 71 // For internal use by the memory reporter when accounting for 72 // storage used by textruns. 73 // Because the reporter may visit each textrun multiple times while 74 // walking the frame trees and textrun cache, it needs to mark 75 // textruns that have been seen so as to avoid multiple-accounting. 76 RunSizeAccounted = 0x2000, 77 78 // The following are defined by gfxTextRunFactory rather than here, 79 // so that it also has access to the _INCOMING and MATH_SCRIPT flags 80 // for shaping purposes. 81 // They live in the gfxShapedText::mFlags field rather than the 82 // gfxTextRun::mFlags2 field. 83 // TEXT_TRAILING_ARABICCHAR 84 // TEXT_INCOMING_ARABICCHAR 85 // TEXT_USE_MATH_SCRIPT 86 }; 87 88 // These constants are used in TransformText to represent context information 89 // from previous textruns. 90 enum { INCOMING_NONE = 0, INCOMING_WHITESPACE = 1, INCOMING_ARABICCHAR = 2 }; 91 92 /** 93 * Returns true if aChars/aLength are something that make a space 94 * character not be whitespace when they follow the space character 95 * (combining mark or join control, ignoring intervening direction 96 * controls). 97 */ 98 static bool IsSpaceCombiningSequenceTail(const char16_t* aChars, 99 int32_t aLength); 100 static bool IsSpaceCombiningSequenceTail(const uint8_t* aChars, 101 int32_t aLength) { 102 return false; 103 } 104 105 enum CompressionMode { 106 COMPRESS_NONE, 107 COMPRESS_WHITESPACE, 108 COMPRESS_WHITESPACE_NEWLINE, 109 COMPRESS_NONE_TRANSFORM_TO_SPACE 110 }; 111 112 /** 113 * Create a text run from a run of Unicode text. The text may have whitespace 114 * compressed. A preformatted tab is sent to the text run as a single space. 115 * (Tab spacing must be performed by textframe later.) Certain other 116 * characters are discarded. 117 * 118 * @param aCompression control what is compressed to a 119 * single space character: no compression, compress spaces (not followed 120 * by combining mark) and tabs, compress those plus newlines, or 121 * no compression except newlines are discarded. 122 * @param aIncomingFlags a flag indicating whether there was whitespace 123 * or an Arabic character preceding this text. We set it to indicate if 124 * there's an Arabic character or whitespace preceding the end of this text. 125 * @param aLanguage Content language (used to select Japanese/Chinese behavior 126 * at punctuation, see https://bugzilla.mozilla.org/show_bug.cgi?id=1935148). 127 */ 128 template <class CharT> 129 static CharT* TransformText(const CharT* aText, uint32_t aLength, 130 CharT* aOutput, CompressionMode aCompression, 131 uint8_t* aIncomingFlags, gfxSkipChars* aSkipChars, 132 nsTextFrameUtils::Flags* aAnalysisFlags, 133 const nsAtom* aLanguage); 134 135 /** 136 * Returns whether aChar is a character that nsTextFrameUtils::TransformText 137 * might mark as skipped. This is used by 138 * SVGTextContentElement::GetNumberOfChars to know whether reflowing frames, 139 * so that we have the results of TransformText, is required, or whether we 140 * can use a fast path instead. 141 */ 142 template <class CharT> 143 static bool IsSkippableCharacterForTransformText(CharT aChar); 144 145 static void AppendLineBreakOffset(nsTArray<uint32_t>* aArray, 146 uint32_t aOffset) { 147 if (aArray->Length() > 0 && (*aArray)[aArray->Length() - 1] == aOffset) { 148 return; 149 } 150 aArray->AppendElement(aOffset); 151 } 152 153 static uint32_t ComputeApproximateLengthWithWhitespaceCompression( 154 mozilla::dom::Text*, const nsStyleText*); 155 static uint32_t ComputeApproximateLengthWithWhitespaceCompression( 156 const nsAString&, const nsStyleText*); 157 }; 158 159 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsTextFrameUtils::Flags) 160 161 /** 162 * nsSkipCharsRunIterator is a layout-oriented convenience wrapper over 163 * gfxSkipCharsIterator, which iterates over runs in the string. Each run 164 * consists entirely of either "unskipped" or "skipped" characters. 165 * 166 * By default, calling NextRun() iterates over only unskipped runs. Call 167 * SetVisitSkipped() to let NextRun() also iterates over skipped runs where 168 * IsSkipped() is true. 169 */ 170 class nsSkipCharsRunIterator { 171 public: 172 // Indicates whether the constructor's aRemainingLength counts only unskipped 173 // characters, or unskipped + skipped characters. 174 enum LengthMode { 175 LENGTH_UNSKIPPED_ONLY = false, 176 LENGTH_INCLUDES_SKIPPED = true 177 }; 178 nsSkipCharsRunIterator(const gfxSkipCharsIterator& aStart, 179 LengthMode aLengthIncludesSkipped, 180 uint32_t aRemainingLength) 181 : mIterator(aStart), 182 mRemainingLength(aRemainingLength), 183 mRunLength(0), 184 mSkipped(false), 185 mVisitSkipped(false), 186 mLengthIncludesSkipped(aLengthIncludesSkipped) {} 187 188 // Include skipped runs in iteration results. 189 void SetVisitSkipped() { mVisitSkipped = true; } 190 191 void SetOriginalOffset(int32_t aOffset) { 192 mIterator.SetOriginalOffset(aOffset); 193 } 194 void SetSkippedOffset(uint32_t aOffset) { 195 mIterator.SetSkippedOffset(aOffset); 196 } 197 198 // Advance to the next run. Return false when no runs remain. On success, 199 // GetRunLength() is guaranteed to return positive length. 200 bool NextRun(); 201 202 // Return true if the current run consists of skipped characters. 203 bool IsSkipped() const { return mSkipped; } 204 205 // Length of the current run. The return value is always positive. 206 int32_t GetRunLength() const { return mRunLength; } 207 208 const gfxSkipCharsIterator& GetPos() const { return mIterator; } 209 int32_t GetOriginalOffset() const { return mIterator.GetOriginalOffset(); } 210 uint32_t GetSkippedOffset() const { return mIterator.GetSkippedOffset(); } 211 212 private: 213 gfxSkipCharsIterator mIterator; 214 int32_t mRemainingLength; 215 int32_t mRunLength; 216 bool mSkipped; 217 bool mVisitSkipped; 218 bool mLengthIncludesSkipped; 219 }; 220 221 #endif /*NSTEXTFRAMEUTILS_H_*/