|
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 nsTextFrame_h__ |
|
7 #define nsTextFrame_h__ |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "nsFrame.h" |
|
11 #include "nsSplittableFrame.h" |
|
12 #include "nsLineBox.h" |
|
13 #include "gfxFont.h" |
|
14 #include "gfxSkipChars.h" |
|
15 #include "nsDisplayList.h" |
|
16 |
|
17 class nsTextPaintStyle; |
|
18 class PropertyProvider; |
|
19 |
|
20 typedef nsFrame nsTextFrameBase; |
|
21 |
|
22 class nsDisplayTextGeometry; |
|
23 class nsDisplayText; |
|
24 |
|
25 class nsTextFrameTextRunCache { |
|
26 public: |
|
27 static void Init(); |
|
28 static void Shutdown(); |
|
29 }; |
|
30 |
|
31 class nsTextFrame : public nsTextFrameBase { |
|
32 public: |
|
33 NS_DECL_QUERYFRAME_TARGET(nsTextFrame) |
|
34 NS_DECL_FRAMEARENA_HELPERS |
|
35 |
|
36 friend class nsContinuingTextFrame; |
|
37 friend class nsDisplayTextGeometry; |
|
38 friend class nsDisplayText; |
|
39 |
|
40 nsTextFrame(nsStyleContext* aContext) |
|
41 : nsTextFrameBase(aContext) |
|
42 { |
|
43 NS_ASSERTION(mContentOffset == 0, "Bogus content offset"); |
|
44 } |
|
45 |
|
46 // nsQueryFrame |
|
47 NS_DECL_QUERYFRAME |
|
48 |
|
49 // nsIFrame |
|
50 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
|
51 const nsRect& aDirtyRect, |
|
52 const nsDisplayListSet& aLists) MOZ_OVERRIDE; |
|
53 |
|
54 virtual void Init(nsIContent* aContent, |
|
55 nsIFrame* aParent, |
|
56 nsIFrame* aPrevInFlow) MOZ_OVERRIDE; |
|
57 |
|
58 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; |
|
59 |
|
60 virtual nsresult GetCursor(const nsPoint& aPoint, |
|
61 nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; |
|
62 |
|
63 virtual nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) MOZ_OVERRIDE; |
|
64 |
|
65 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; |
|
66 |
|
67 virtual nsIFrame* GetNextContinuation() const MOZ_OVERRIDE { |
|
68 return mNextContinuation; |
|
69 } |
|
70 virtual void SetNextContinuation(nsIFrame* aNextContinuation) MOZ_OVERRIDE { |
|
71 NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(), |
|
72 "setting a next continuation with incorrect type!"); |
|
73 NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this), |
|
74 "creating a loop in continuation chain!"); |
|
75 mNextContinuation = aNextContinuation; |
|
76 if (aNextContinuation) |
|
77 aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); |
|
78 } |
|
79 virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE { return GetNextInFlow(); } |
|
80 nsIFrame* GetNextInFlow() const { |
|
81 return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? |
|
82 mNextContinuation : nullptr; |
|
83 } |
|
84 virtual void SetNextInFlow(nsIFrame* aNextInFlow) MOZ_OVERRIDE { |
|
85 NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(), |
|
86 "setting a next in flow with incorrect type!"); |
|
87 NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this), |
|
88 "creating a loop in continuation chain!"); |
|
89 mNextContinuation = aNextInFlow; |
|
90 if (aNextInFlow) |
|
91 aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); |
|
92 } |
|
93 virtual nsIFrame* LastInFlow() const MOZ_OVERRIDE; |
|
94 virtual nsIFrame* LastContinuation() const MOZ_OVERRIDE; |
|
95 |
|
96 virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE { |
|
97 return NS_FRAME_SPLITTABLE; |
|
98 } |
|
99 |
|
100 /** |
|
101 * Get the "type" of the frame |
|
102 * |
|
103 * @see nsGkAtoms::textFrame |
|
104 */ |
|
105 virtual nsIAtom* GetType() const MOZ_OVERRIDE; |
|
106 |
|
107 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE |
|
108 { |
|
109 // Set the frame state bit for text frames to mark them as replaced. |
|
110 // XXX kipp: temporary |
|
111 return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | |
|
112 nsIFrame::eLineParticipant)); |
|
113 } |
|
114 |
|
115 virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; |
|
116 virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; |
|
117 |
|
118 #ifdef DEBUG_FRAME_DUMP |
|
119 void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE; |
|
120 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; |
|
121 void ToCString(nsCString& aBuf, int32_t* aTotalContentLength) const; |
|
122 #endif |
|
123 |
|
124 #ifdef DEBUG |
|
125 virtual nsFrameState GetDebugStateBits() const MOZ_OVERRIDE; |
|
126 #endif |
|
127 |
|
128 virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE; |
|
129 ContentOffsets GetCharacterOffsetAtFramePoint(const nsPoint &aPoint); |
|
130 |
|
131 /** |
|
132 * This is called only on the primary text frame. It indicates that |
|
133 * the selection state of the given character range has changed. |
|
134 * Text in the range is unconditionally invalidated |
|
135 * (Selection::Repaint depends on this). |
|
136 * @param aSelected true if the selection has been added to the range, |
|
137 * false otherwise |
|
138 * @param aType the type of selection added or removed |
|
139 */ |
|
140 void SetSelectedRange(uint32_t aStart, uint32_t aEnd, bool aSelected, |
|
141 SelectionType aType); |
|
142 |
|
143 virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; |
|
144 virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, |
|
145 bool aRespectClusters = true) MOZ_OVERRIDE; |
|
146 virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, |
|
147 int32_t* aOffset, PeekWordState* aState) MOZ_OVERRIDE; |
|
148 |
|
149 virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval) MOZ_OVERRIDE; |
|
150 |
|
151 // Flags for aSetLengthFlags |
|
152 enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 }; |
|
153 |
|
154 // Update offsets to account for new length. This may clear mTextRun. |
|
155 void SetLength(int32_t aLength, nsLineLayout* aLineLayout, |
|
156 uint32_t aSetLengthFlags = 0); |
|
157 |
|
158 virtual nsresult GetOffsets(int32_t &start, int32_t &end)const MOZ_OVERRIDE; |
|
159 |
|
160 virtual void AdjustOffsetsForBidi(int32_t start, int32_t end) MOZ_OVERRIDE; |
|
161 |
|
162 virtual nsresult GetPointFromOffset(int32_t inOffset, |
|
163 nsPoint* outPoint) MOZ_OVERRIDE; |
|
164 |
|
165 virtual nsresult GetChildFrameContainingOffset(int32_t inContentOffset, |
|
166 bool inHint, |
|
167 int32_t* outFrameContentOffset, |
|
168 nsIFrame** outChildFrame) MOZ_OVERRIDE; |
|
169 |
|
170 virtual bool IsVisibleInSelection(nsISelection* aSelection) MOZ_OVERRIDE; |
|
171 |
|
172 virtual bool IsEmpty() MOZ_OVERRIDE; |
|
173 virtual bool IsSelfEmpty() MOZ_OVERRIDE { return IsEmpty(); } |
|
174 virtual nscoord GetBaseline() const MOZ_OVERRIDE; |
|
175 |
|
176 virtual bool HasSignificantTerminalNewline() const MOZ_OVERRIDE; |
|
177 |
|
178 /** |
|
179 * Returns true if this text frame is logically adjacent to the end of the |
|
180 * line. |
|
181 */ |
|
182 bool IsAtEndOfLine() const; |
|
183 |
|
184 /** |
|
185 * Call this only after reflow the frame. Returns true if non-collapsed |
|
186 * characters are present. |
|
187 */ |
|
188 bool HasNoncollapsedCharacters() const { |
|
189 return (GetStateBits() & TEXT_HAS_NONCOLLAPSED_CHARACTERS) != 0; |
|
190 } |
|
191 |
|
192 #ifdef ACCESSIBILITY |
|
193 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; |
|
194 #endif |
|
195 |
|
196 float GetFontSizeInflation() const; |
|
197 bool IsCurrentFontInflation(float aInflation) const; |
|
198 bool HasFontSizeInflation() const { |
|
199 return (GetStateBits() & TEXT_HAS_FONT_INFLATION) != 0; |
|
200 } |
|
201 void SetFontSizeInflation(float aInflation); |
|
202 |
|
203 virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; |
|
204 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; |
|
205 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; |
|
206 virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, |
|
207 InlineMinWidthData *aData) MOZ_OVERRIDE; |
|
208 virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, |
|
209 InlinePrefWidthData *aData) MOZ_OVERRIDE; |
|
210 virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, |
|
211 nsSize aCBSize, nscoord aAvailableWidth, |
|
212 nsSize aMargin, nsSize aBorder, nsSize aPadding, |
|
213 uint32_t aFlags) MOZ_OVERRIDE; |
|
214 virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE; |
|
215 virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext, |
|
216 nscoord* aX, |
|
217 nscoord* aXMost) MOZ_OVERRIDE; |
|
218 virtual nsresult Reflow(nsPresContext* aPresContext, |
|
219 nsHTMLReflowMetrics& aMetrics, |
|
220 const nsHTMLReflowState& aReflowState, |
|
221 nsReflowStatus& aStatus) MOZ_OVERRIDE; |
|
222 virtual bool CanContinueTextRun() const MOZ_OVERRIDE; |
|
223 // Method that is called for a text frame that is logically |
|
224 // adjacent to the end of the line (i.e. followed only by empty text frames, |
|
225 // placeholders or inlines containing such). |
|
226 struct TrimOutput { |
|
227 // true if we trimmed some space or changed metrics in some other way. |
|
228 // In this case, we should call RecomputeOverflow on this frame. |
|
229 bool mChanged; |
|
230 // true if the last character is not justifiable so should be subtracted |
|
231 // from the count of justifiable characters in the frame, since the last |
|
232 // character in a line is not justifiable. |
|
233 bool mLastCharIsJustifiable; |
|
234 // an amount to *subtract* from the frame's width (zero if !mChanged) |
|
235 nscoord mDeltaWidth; |
|
236 }; |
|
237 TrimOutput TrimTrailingWhiteSpace(nsRenderingContext* aRC); |
|
238 virtual nsresult GetRenderedText(nsAString* aString = nullptr, |
|
239 gfxSkipChars* aSkipChars = nullptr, |
|
240 gfxSkipCharsIterator* aSkipIter = nullptr, |
|
241 uint32_t aSkippedStartOffset = 0, |
|
242 uint32_t aSkippedMaxLength = UINT32_MAX) MOZ_OVERRIDE; |
|
243 |
|
244 nsOverflowAreas |
|
245 RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState); |
|
246 |
|
247 enum TextRunType { |
|
248 // Anything in reflow (but not intrinsic width calculation) or |
|
249 // painting should use the inflated text run (i.e., with font size |
|
250 // inflation applied). |
|
251 eInflated, |
|
252 // Intrinsic width calculation should use the non-inflated text run. |
|
253 // When there is font size inflation, it will be different. |
|
254 eNotInflated |
|
255 }; |
|
256 |
|
257 void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, |
|
258 nsIFrame::InlineMinWidthData *aData, |
|
259 TextRunType aTextRunType); |
|
260 void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, |
|
261 InlinePrefWidthData *aData, |
|
262 TextRunType aTextRunType); |
|
263 |
|
264 /** |
|
265 * Calculate the horizontal bounds of the grapheme clusters that fit entirely |
|
266 * inside the given left/right edges (which are positive lengths from the |
|
267 * respective frame edge). If an input value is zero it is ignored and the |
|
268 * result for that edge is zero. All out parameter values are undefined when |
|
269 * the method returns false. |
|
270 * @return true if at least one whole grapheme cluster fit between the edges |
|
271 */ |
|
272 bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge, |
|
273 nscoord* aSnappedLeftEdge, |
|
274 nscoord* aSnappedRightEdge); |
|
275 /** |
|
276 * Same as above; this method also the returns the corresponding text run |
|
277 * offset and number of characters that fit. All out parameter values are |
|
278 * undefined when the method returns false. |
|
279 * @return true if at least one whole grapheme cluster fit between the edges |
|
280 */ |
|
281 bool MeasureCharClippedText(PropertyProvider& aProvider, |
|
282 nscoord aLeftEdge, nscoord aRightEdge, |
|
283 uint32_t* aStartOffset, uint32_t* aMaxLength, |
|
284 nscoord* aSnappedLeftEdge, |
|
285 nscoord* aSnappedRightEdge); |
|
286 |
|
287 /** |
|
288 * Object with various callbacks for PaintText() to invoke for different parts |
|
289 * of the frame's text rendering, when we're generating paths rather than |
|
290 * painting. |
|
291 * |
|
292 * Callbacks are invoked in the following order: |
|
293 * |
|
294 * (NotifyBeforeSelectionBackground NotifySelectionBackgroundPathEmitted)? |
|
295 * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* |
|
296 * NotifyBeforeText |
|
297 * (NotifyGlyphPathEmitted | |
|
298 * (NotifyBeforeSVGGlyphPainted NotifyAfterSVGGlyphPainted))* |
|
299 * NotifyAfterText |
|
300 * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* |
|
301 * (NotifyBeforeSelectionDecorationLine NotifySelectionDecorationLinePathEmitted)* |
|
302 * |
|
303 * The color of each part of the frame's text rendering is passed as an argument |
|
304 * to the NotifyBefore* callback for that part. The nscolor can take on one of |
|
305 * the three selection special colors defined in LookAndFeel.h -- |
|
306 * NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR and |
|
307 * NS_40PERCENT_FOREGROUND_COLOR. |
|
308 */ |
|
309 struct DrawPathCallbacks : gfxTextRunDrawCallbacks |
|
310 { |
|
311 /** |
|
312 * @param aShouldPaintSVGGlyphs Whether SVG glyphs should be painted. |
|
313 */ |
|
314 DrawPathCallbacks(bool aShouldPaintSVGGlyphs = false) |
|
315 : gfxTextRunDrawCallbacks(aShouldPaintSVGGlyphs) |
|
316 { |
|
317 } |
|
318 |
|
319 /** |
|
320 * Called just before any paths have been emitted to the gfxContext |
|
321 * for the glyphs of the frame's text. |
|
322 */ |
|
323 virtual void NotifyBeforeText(nscolor aColor) { } |
|
324 |
|
325 /** |
|
326 * Called just after all the paths have been emitted to the gfxContext |
|
327 * for the glyphs of the frame's text. |
|
328 */ |
|
329 virtual void NotifyAfterText() { } |
|
330 |
|
331 /** |
|
332 * Called just before a path corresponding to the selection background |
|
333 * has been emitted to the gfxContext. |
|
334 */ |
|
335 virtual void NotifyBeforeSelectionBackground(nscolor aColor) { } |
|
336 |
|
337 /** |
|
338 * Called just after a path corresponding to the selection background |
|
339 * has been emitted to the gfxContext. |
|
340 */ |
|
341 virtual void NotifySelectionBackgroundPathEmitted() { } |
|
342 |
|
343 /** |
|
344 * Called just before a path corresponding to a text decoration line |
|
345 * has been emitted to the gfxContext. |
|
346 */ |
|
347 virtual void NotifyBeforeDecorationLine(nscolor aColor) { } |
|
348 |
|
349 /** |
|
350 * Called just after a path corresponding to a text decoration line |
|
351 * has been emitted to the gfxContext. |
|
352 */ |
|
353 virtual void NotifyDecorationLinePathEmitted() { } |
|
354 |
|
355 /** |
|
356 * Called just before a path corresponding to a selection decoration line |
|
357 * has been emitted to the gfxContext. |
|
358 */ |
|
359 virtual void NotifyBeforeSelectionDecorationLine(nscolor aColor) { } |
|
360 |
|
361 /** |
|
362 * Called just after a path corresponding to a selection decoration line |
|
363 * has been emitted to the gfxContext. |
|
364 */ |
|
365 virtual void NotifySelectionDecorationLinePathEmitted() { } |
|
366 }; |
|
367 |
|
368 // Primary frame paint method called from nsDisplayText. Can also be used |
|
369 // to generate paths rather than paint the frame's text by passing a callback |
|
370 // object. The private DrawText() is what applies the text to a graphics |
|
371 // context. |
|
372 void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, |
|
373 const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem, |
|
374 gfxTextContextPaint* aContextPaint = nullptr, |
|
375 DrawPathCallbacks* aCallbacks = nullptr); |
|
376 // helper: paint text frame when we're impacted by at least one selection. |
|
377 // Return false if the text was not painted and we should continue with |
|
378 // the fast path. |
|
379 bool PaintTextWithSelection(gfxContext* aCtx, |
|
380 const gfxPoint& aFramePt, |
|
381 const gfxPoint& aTextBaselinePt, |
|
382 const gfxRect& aDirtyRect, |
|
383 PropertyProvider& aProvider, |
|
384 uint32_t aContentOffset, |
|
385 uint32_t aContentLength, |
|
386 nsTextPaintStyle& aTextPaintStyle, |
|
387 const nsCharClipDisplayItem::ClipEdges& aClipEdges, |
|
388 gfxTextContextPaint* aContextPaint, |
|
389 DrawPathCallbacks* aCallbacks); |
|
390 // helper: paint text with foreground and background colors determined |
|
391 // by selection(s). Also computes a mask of all selection types applying to |
|
392 // our text, returned in aAllTypes. |
|
393 // Return false if the text was not painted and we should continue with |
|
394 // the fast path. |
|
395 bool PaintTextWithSelectionColors(gfxContext* aCtx, |
|
396 const gfxPoint& aFramePt, |
|
397 const gfxPoint& aTextBaselinePt, |
|
398 const gfxRect& aDirtyRect, |
|
399 PropertyProvider& aProvider, |
|
400 uint32_t aContentOffset, |
|
401 uint32_t aContentLength, |
|
402 nsTextPaintStyle& aTextPaintStyle, |
|
403 SelectionDetails* aDetails, |
|
404 SelectionType* aAllTypes, |
|
405 const nsCharClipDisplayItem::ClipEdges& aClipEdges, |
|
406 DrawPathCallbacks* aCallbacks); |
|
407 // helper: paint text decorations for text selected by aSelectionType |
|
408 void PaintTextSelectionDecorations(gfxContext* aCtx, |
|
409 const gfxPoint& aFramePt, |
|
410 const gfxPoint& aTextBaselinePt, |
|
411 const gfxRect& aDirtyRect, |
|
412 PropertyProvider& aProvider, |
|
413 uint32_t aContentOffset, |
|
414 uint32_t aContentLength, |
|
415 nsTextPaintStyle& aTextPaintStyle, |
|
416 SelectionDetails* aDetails, |
|
417 SelectionType aSelectionType, |
|
418 DrawPathCallbacks* aCallbacks); |
|
419 |
|
420 virtual nscolor GetCaretColorAt(int32_t aOffset) MOZ_OVERRIDE; |
|
421 |
|
422 int16_t GetSelectionStatus(int16_t* aSelectionFlags); |
|
423 |
|
424 int32_t GetContentOffset() const { return mContentOffset; } |
|
425 int32_t GetContentLength() const |
|
426 { |
|
427 NS_ASSERTION(GetContentEnd() - mContentOffset >= 0, "negative length"); |
|
428 return GetContentEnd() - mContentOffset; |
|
429 } |
|
430 int32_t GetContentEnd() const; |
|
431 // This returns the length the frame thinks it *should* have after it was |
|
432 // last reflowed (0 if it hasn't been reflowed yet). This should be used only |
|
433 // when setting up the text offsets for a new continuation frame. |
|
434 int32_t GetContentLengthHint() const { return mContentLengthHint; } |
|
435 |
|
436 // Compute the length of the content mapped by this frame |
|
437 // and all its in-flow siblings. Basically this means starting at mContentOffset |
|
438 // and going to the end of the text node or the next bidi continuation |
|
439 // boundary. |
|
440 int32_t GetInFlowContentLength(); |
|
441 |
|
442 /** |
|
443 * Acquires the text run for this content, if necessary. |
|
444 * @param aWhichTextRun indicates whether to get an inflated or non-inflated |
|
445 * text run |
|
446 * @param aReferenceContext the rendering context to use as a reference for |
|
447 * creating the textrun, if available (if not, we'll create one which will |
|
448 * just be slower) |
|
449 * @param aLineContainer the block ancestor for this frame, or nullptr if |
|
450 * unknown |
|
451 * @param aFlowEndInTextRun if non-null, this returns the textrun offset of |
|
452 * end of the text associated with this frame and its in-flow siblings |
|
453 * @return a gfxSkipCharsIterator set up to map DOM offsets for this frame |
|
454 * to offsets into the textrun; its initial offset is set to this frame's |
|
455 * content offset |
|
456 */ |
|
457 gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun, |
|
458 gfxContext* aReferenceContext = nullptr, |
|
459 nsIFrame* aLineContainer = nullptr, |
|
460 const nsLineList::iterator* aLine = nullptr, |
|
461 uint32_t* aFlowEndInTextRun = nullptr); |
|
462 |
|
463 gfxTextRun* GetTextRun(TextRunType aWhichTextRun) { |
|
464 if (aWhichTextRun == eInflated || !HasFontSizeInflation()) |
|
465 return mTextRun; |
|
466 return GetUninflatedTextRun(); |
|
467 } |
|
468 gfxTextRun* GetUninflatedTextRun(); |
|
469 void SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun, |
|
470 float aInflation); |
|
471 bool IsInTextRunUserData() const { |
|
472 return GetStateBits() & |
|
473 (TEXT_IN_TEXTRUN_USER_DATA | TEXT_IN_UNINFLATED_TEXTRUN_USER_DATA); |
|
474 } |
|
475 /** |
|
476 * Notify the frame that it should drop its pointer to a text run. |
|
477 * Returns whether the text run was removed (i.e., whether it was |
|
478 * associated with this frame, either as its inflated or non-inflated |
|
479 * text run. |
|
480 */ |
|
481 bool RemoveTextRun(gfxTextRun* aTextRun); |
|
482 /** |
|
483 * Clears out |mTextRun| (or the uninflated text run, when aInflated |
|
484 * is nsTextFrame::eNotInflated and there is inflation) from all frames that hold a |
|
485 * reference to it, starting at |aStartContinuation|, or if it's |
|
486 * nullptr, starting at |this|. Deletes the text run if all references |
|
487 * were cleared and it's not cached. |
|
488 */ |
|
489 void ClearTextRun(nsTextFrame* aStartContinuation, |
|
490 TextRunType aWhichTextRun); |
|
491 |
|
492 void ClearTextRuns() { |
|
493 ClearTextRun(nullptr, nsTextFrame::eInflated); |
|
494 if (HasFontSizeInflation()) { |
|
495 ClearTextRun(nullptr, nsTextFrame::eNotInflated); |
|
496 } |
|
497 } |
|
498 |
|
499 /** |
|
500 * Wipe out references to textrun(s) without deleting the textruns. |
|
501 */ |
|
502 void DisconnectTextRuns(); |
|
503 |
|
504 // Get the DOM content range mapped by this frame after excluding |
|
505 // whitespace subject to start-of-line and end-of-line trimming. |
|
506 // The textrun must have been created before calling this. |
|
507 struct TrimmedOffsets { |
|
508 int32_t mStart; |
|
509 int32_t mLength; |
|
510 int32_t GetEnd() const { return mStart + mLength; } |
|
511 }; |
|
512 TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, |
|
513 bool aTrimAfter, bool aPostReflow = true); |
|
514 |
|
515 // Similar to Reflow(), but for use from nsLineLayout |
|
516 void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, |
|
517 nsRenderingContext* aRenderingContext, |
|
518 nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus); |
|
519 |
|
520 bool IsFloatingFirstLetterChild() const; |
|
521 |
|
522 protected: |
|
523 virtual ~nsTextFrame(); |
|
524 |
|
525 nsIFrame* mNextContinuation; |
|
526 // The key invariant here is that mContentOffset never decreases along |
|
527 // a next-continuation chain. And of course mContentOffset is always <= the |
|
528 // the text node's content length, and the mContentOffset for the first frame |
|
529 // is always 0. Furthermore the text mapped by a frame is determined by |
|
530 // GetContentOffset() and GetContentLength()/GetContentEnd(), which get |
|
531 // the length from the difference between this frame's offset and the next |
|
532 // frame's offset, or the text length if there is no next frame. This means |
|
533 // the frames always map the text node without overlapping or leaving any gaps. |
|
534 int32_t mContentOffset; |
|
535 // This does *not* indicate the length of text currently mapped by the frame; |
|
536 // instead it's a hint saying that this frame *wants* to map this much text |
|
537 // so if we create a new continuation, this is where that continuation should |
|
538 // start. |
|
539 int32_t mContentLengthHint; |
|
540 nscoord mAscent; |
|
541 gfxTextRun* mTextRun; |
|
542 |
|
543 /** |
|
544 * Return true if the frame is part of a Selection. |
|
545 * Helper method to implement the public IsSelected() API. |
|
546 */ |
|
547 virtual bool IsFrameSelected() const MOZ_OVERRIDE; |
|
548 |
|
549 // The caller of this method must call DestroySelectionDetails() on the |
|
550 // return value, if that return value is not null. Calling |
|
551 // DestroySelectionDetails() on a null value is still OK, just not necessary. |
|
552 SelectionDetails* GetSelectionDetails(); |
|
553 |
|
554 void UnionAdditionalOverflow(nsPresContext* aPresContext, |
|
555 const nsHTMLReflowState& aBlockReflowState, |
|
556 PropertyProvider& aProvider, |
|
557 nsRect* aVisualOverflowRect, |
|
558 bool aIncludeTextDecorations); |
|
559 |
|
560 void PaintOneShadow(uint32_t aOffset, |
|
561 uint32_t aLength, |
|
562 nsCSSShadowItem* aShadowDetails, |
|
563 PropertyProvider* aProvider, |
|
564 const nsRect& aDirtyRect, |
|
565 const gfxPoint& aFramePt, |
|
566 const gfxPoint& aTextBaselinePt, |
|
567 gfxContext* aCtx, |
|
568 const nscolor& aForegroundColor, |
|
569 const nsCharClipDisplayItem::ClipEdges& aClipEdges, |
|
570 nscoord aLeftSideOffset, |
|
571 gfxRect& aBoundingBox); |
|
572 |
|
573 struct LineDecoration { |
|
574 nsIFrame* mFrame; |
|
575 |
|
576 // This is represents the offset from our baseline to mFrame's baseline; |
|
577 // positive offsets are *above* the baseline and negative offsets below |
|
578 nscoord mBaselineOffset; |
|
579 |
|
580 nscolor mColor; |
|
581 uint8_t mStyle; |
|
582 |
|
583 LineDecoration(nsIFrame *const aFrame, |
|
584 const nscoord aOff, |
|
585 const nscolor aColor, |
|
586 const uint8_t aStyle) |
|
587 : mFrame(aFrame), |
|
588 mBaselineOffset(aOff), |
|
589 mColor(aColor), |
|
590 mStyle(aStyle) |
|
591 {} |
|
592 |
|
593 LineDecoration(const LineDecoration& aOther) |
|
594 : mFrame(aOther.mFrame), |
|
595 mBaselineOffset(aOther.mBaselineOffset), |
|
596 mColor(aOther.mColor), |
|
597 mStyle(aOther.mStyle) |
|
598 {} |
|
599 |
|
600 bool operator==(const LineDecoration& aOther) const { |
|
601 return mFrame == aOther.mFrame && |
|
602 mStyle == aOther.mStyle && |
|
603 mColor == aOther.mColor && |
|
604 mBaselineOffset == aOther.mBaselineOffset; |
|
605 } |
|
606 |
|
607 bool operator!=(const LineDecoration& aOther) const { |
|
608 return !(*this == aOther); |
|
609 } |
|
610 }; |
|
611 struct TextDecorations { |
|
612 nsAutoTArray<LineDecoration, 1> mOverlines, mUnderlines, mStrikes; |
|
613 |
|
614 TextDecorations() { } |
|
615 |
|
616 bool HasDecorationLines() const { |
|
617 return HasUnderline() || HasOverline() || HasStrikeout(); |
|
618 } |
|
619 bool HasUnderline() const { |
|
620 return !mUnderlines.IsEmpty(); |
|
621 } |
|
622 bool HasOverline() const { |
|
623 return !mOverlines.IsEmpty(); |
|
624 } |
|
625 bool HasStrikeout() const { |
|
626 return !mStrikes.IsEmpty(); |
|
627 } |
|
628 bool operator==(const TextDecorations& aOther) const { |
|
629 return mOverlines == aOther.mOverlines && |
|
630 mUnderlines == aOther.mUnderlines && |
|
631 mStrikes == aOther.mStrikes; |
|
632 } |
|
633 |
|
634 bool operator!=(const TextDecorations& aOther) const { |
|
635 return !(*this == aOther); |
|
636 } |
|
637 |
|
638 }; |
|
639 enum TextDecorationColorResolution { |
|
640 eResolvedColors, |
|
641 eUnresolvedColors |
|
642 }; |
|
643 void GetTextDecorations(nsPresContext* aPresContext, |
|
644 TextDecorationColorResolution aColorResolution, |
|
645 TextDecorations& aDecorations); |
|
646 |
|
647 void DrawTextRun(gfxContext* const aCtx, |
|
648 const gfxPoint& aTextBaselinePt, |
|
649 uint32_t aOffset, |
|
650 uint32_t aLength, |
|
651 PropertyProvider& aProvider, |
|
652 nscolor aTextColor, |
|
653 gfxFloat& aAdvanceWidth, |
|
654 bool aDrawSoftHyphen, |
|
655 gfxTextContextPaint* aContextPaint, |
|
656 DrawPathCallbacks* aCallbacks); |
|
657 |
|
658 void DrawTextRunAndDecorations(gfxContext* const aCtx, |
|
659 const gfxRect& aDirtyRect, |
|
660 const gfxPoint& aFramePt, |
|
661 const gfxPoint& aTextBaselinePt, |
|
662 uint32_t aOffset, |
|
663 uint32_t aLength, |
|
664 PropertyProvider& aProvider, |
|
665 const nsTextPaintStyle& aTextStyle, |
|
666 nscolor aTextColor, |
|
667 const nsCharClipDisplayItem::ClipEdges& aClipEdges, |
|
668 gfxFloat& aAdvanceWidth, |
|
669 bool aDrawSoftHyphen, |
|
670 const TextDecorations& aDecorations, |
|
671 const nscolor* const aDecorationOverrideColor, |
|
672 gfxTextContextPaint* aContextPaint, |
|
673 DrawPathCallbacks* aCallbacks); |
|
674 |
|
675 void DrawText(gfxContext* const aCtx, |
|
676 const gfxRect& aDirtyRect, |
|
677 const gfxPoint& aFramePt, |
|
678 const gfxPoint& aTextBaselinePt, |
|
679 uint32_t aOffset, |
|
680 uint32_t aLength, |
|
681 PropertyProvider& aProvider, |
|
682 const nsTextPaintStyle& aTextStyle, |
|
683 nscolor aTextColor, |
|
684 const nsCharClipDisplayItem::ClipEdges& aClipEdges, |
|
685 gfxFloat& aAdvanceWidth, |
|
686 bool aDrawSoftHyphen, |
|
687 const nscolor* const aDecorationOverrideColor = nullptr, |
|
688 gfxTextContextPaint* aContextPaint = nullptr, |
|
689 DrawPathCallbacks* aCallbacks = nullptr); |
|
690 |
|
691 // Set non empty rect to aRect, it should be overflow rect or frame rect. |
|
692 // If the result rect is larger than the given rect, this returns true. |
|
693 bool CombineSelectionUnderlineRect(nsPresContext* aPresContext, |
|
694 nsRect& aRect); |
|
695 |
|
696 ContentOffsets GetCharacterOffsetAtFramePointInternal(nsPoint aPoint, |
|
697 bool aForInsertionPoint); |
|
698 |
|
699 void ClearFrameOffsetCache(); |
|
700 |
|
701 virtual bool HasAnyNoncollapsedCharacters() MOZ_OVERRIDE; |
|
702 |
|
703 void ClearMetrics(nsHTMLReflowMetrics& aMetrics); |
|
704 }; |
|
705 |
|
706 #endif |