Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef NSTEXTFRAMEUTILS_H_
7 : #define NSTEXTFRAMEUTILS_H_
8 :
9 : #include "gfxSkipChars.h"
10 : #include "nsBidiUtils.h"
11 : #include "nsUnicodeProperties.h"
12 :
13 : class nsIContent;
14 : struct nsStyleText;
15 :
16 : #define BIG_TEXT_NODE_SIZE 4096
17 :
18 : #define CH_NBSP 160
19 : #define CH_SHY 173
20 : #define CH_CJKSP 12288 // U+3000 IDEOGRAPHIC SPACE (CJK Full-Width Space)
21 :
22 : class nsTextFrameUtils {
23 : public:
24 : // These constants are used as textrun flags for textframe textruns.
25 : enum class Flags : uint16_t {
26 : // The following flags are set by TransformText
27 :
28 : // the text has at least one untransformed tab character
29 : TEXT_HAS_TAB = 0x01,
30 : // the original text has at least one soft hyphen character
31 : TEXT_HAS_SHY = 0x02,
32 : TEXT_UNUSED_FLAGS = 0x0C,
33 :
34 : // The following flags are set by nsTextFrame
35 :
36 : TEXT_IS_SIMPLE_FLOW = 0x10,
37 : TEXT_INCOMING_WHITESPACE = 0x20,
38 : TEXT_TRAILING_WHITESPACE = 0x40,
39 : TEXT_COMPRESSED_LEADING_WHITESPACE = 0x80,
40 : TEXT_NO_BREAKS = 0x100,
41 : TEXT_IS_TRANSFORMED = 0x200,
42 : // This gets set if there's a break opportunity at the end of the textrun.
43 : // We normally don't use this break opportunity because the following text
44 : // will have a break opportunity at the start, but it's useful for line
45 : // layout to know about it in case the following content is not text
46 : TEXT_HAS_TRAILING_BREAK = 0x400,
47 :
48 : // This is set if the textrun was created for a textframe whose
49 : // NS_FRAME_IS_IN_SINGLE_CHAR_MI flag is set. This occurs if the textframe
50 : // belongs to a MathML <mi> element whose embedded text consists of a
51 : // single character.
52 : TEXT_IS_SINGLE_CHAR_MI = 0x800,
53 :
54 : // This is set if the text run might be observing for glyph changes.
55 : TEXT_MIGHT_HAVE_GLYPH_CHANGES = 0x1000,
56 :
57 : // For internal use by the memory reporter when accounting for
58 : // storage used by textruns.
59 : // Because the reporter may visit each textrun multiple times while
60 : // walking the frame trees and textrun cache, it needs to mark
61 : // textruns that have been seen so as to avoid multiple-accounting.
62 : TEXT_RUN_SIZE_ACCOUNTED = 0x2000,
63 :
64 : // The following are defined by gfxTextRunFactory rather than here,
65 : // so that it also has access to the _INCOMING and MATH_SCRIPT flags
66 : // for shaping purposes.
67 : // They live in the gfxShapedText::mFlags field rather than the
68 : // gfxTextRun::mFlags2 field.
69 : // TEXT_TRAILING_ARABICCHAR
70 : // TEXT_INCOMING_ARABICCHAR
71 : // TEXT_USE_MATH_SCRIPT
72 : };
73 :
74 : // These constants are used in TransformText to represent context information
75 : // from previous textruns.
76 : enum {
77 : INCOMING_NONE = 0,
78 : INCOMING_WHITESPACE = 1,
79 : INCOMING_ARABICCHAR = 2
80 : };
81 :
82 : /**
83 : * Returns true if aChars/aLength are something that make a space
84 : * character not be whitespace when they follow the space character
85 : * (combining mark or join control, ignoring intervening direction
86 : * controls).
87 : */
88 : static bool
89 0 : IsSpaceCombiningSequenceTail(const char16_t* aChars, int32_t aLength) {
90 0 : return aLength > 0 &&
91 0 : (mozilla::unicode::IsClusterExtender(aChars[0]) ||
92 0 : (IsBidiControl(aChars[0]) &&
93 0 : IsSpaceCombiningSequenceTail(aChars + 1, aLength - 1)
94 : )
95 0 : );
96 : }
97 : static bool
98 : IsSpaceCombiningSequenceTail(const uint8_t* aChars, int32_t aLength) {
99 : return false;
100 : }
101 :
102 : enum CompressionMode {
103 : COMPRESS_NONE,
104 : COMPRESS_WHITESPACE,
105 : COMPRESS_WHITESPACE_NEWLINE,
106 : COMPRESS_NONE_TRANSFORM_TO_SPACE
107 : };
108 :
109 : /**
110 : * Create a text run from a run of Unicode text. The text may have whitespace
111 : * compressed. A preformatted tab is sent to the text run as a single space.
112 : * (Tab spacing must be performed by textframe later.) Certain other
113 : * characters are discarded.
114 : *
115 : * @param aCompression control what is compressed to a
116 : * single space character: no compression, compress spaces (not followed
117 : * by combining mark) and tabs, compress those plus newlines, or
118 : * no compression except newlines are discarded.
119 : * @param aIncomingFlags a flag indicating whether there was whitespace
120 : * or an Arabic character preceding this text. We set it to indicate if
121 : * there's an Arabic character or whitespace preceding the end of this text.
122 : */
123 : template<class CharT>
124 : static CharT* TransformText(const CharT* aText, uint32_t aLength,
125 : CharT* aOutput,
126 : CompressionMode aCompression,
127 : uint8_t* aIncomingFlags,
128 : gfxSkipChars* aSkipChars,
129 : nsTextFrameUtils::Flags* aAnalysisFlags);
130 :
131 : /**
132 : * Returns whether aChar is a character that nsTextFrameUtils::TransformText
133 : * might mark as skipped. This is used by
134 : * SVGTextContentElement::GetNumberOfChars to know whether reflowing frames,
135 : * so that we have the results of TransformText, is required, or whether we
136 : * can use a fast path instead.
137 : */
138 : template<class CharT>
139 : static bool IsSkippableCharacterForTransformText(CharT aChar);
140 :
141 : static void
142 42 : AppendLineBreakOffset(nsTArray<uint32_t>* aArray, uint32_t aOffset)
143 : {
144 42 : if (aArray->Length() > 0 && (*aArray)[aArray->Length() - 1] == aOffset)
145 12 : return;
146 30 : aArray->AppendElement(aOffset);
147 : }
148 :
149 : static uint32_t
150 : ComputeApproximateLengthWithWhitespaceCompression(nsIContent *aContent,
151 : const nsStyleText*
152 : aStyleText);
153 : };
154 :
155 632 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsTextFrameUtils::Flags)
156 :
157 : class nsSkipCharsRunIterator {
158 : public:
159 : enum LengthMode {
160 : LENGTH_UNSKIPPED_ONLY = false,
161 : LENGTH_INCLUDES_SKIPPED = true
162 : };
163 0 : nsSkipCharsRunIterator(const gfxSkipCharsIterator& aStart,
164 : LengthMode aLengthIncludesSkipped, uint32_t aLength)
165 0 : : mIterator(aStart), mRemainingLength(aLength), mRunLength(0),
166 : mVisitSkipped(false),
167 0 : mLengthIncludesSkipped(aLengthIncludesSkipped) {
168 0 : }
169 0 : void SetVisitSkipped() { mVisitSkipped = true; }
170 0 : void SetOriginalOffset(int32_t aOffset) {
171 0 : mIterator.SetOriginalOffset(aOffset);
172 0 : }
173 0 : void SetSkippedOffset(uint32_t aOffset) {
174 0 : mIterator.SetSkippedOffset(aOffset);
175 0 : }
176 :
177 : // guaranteed to return only positive-length runs
178 : bool NextRun();
179 0 : bool IsSkipped() const { return mSkipped; }
180 : // Always returns something > 0
181 0 : int32_t GetRunLength() const { return mRunLength; }
182 0 : const gfxSkipCharsIterator& GetPos() const { return mIterator; }
183 0 : int32_t GetOriginalOffset() const { return mIterator.GetOriginalOffset(); }
184 0 : uint32_t GetSkippedOffset() const { return mIterator.GetSkippedOffset(); }
185 :
186 : private:
187 : gfxSkipCharsIterator mIterator;
188 : int32_t mRemainingLength;
189 : int32_t mRunLength;
190 : bool mSkipped;
191 : bool mVisitSkipped;
192 : bool mLengthIncludesSkipped;
193 : };
194 :
195 : #endif /*NSTEXTFRAMEUTILS_H_*/
|