1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Robert O'Callahan <robert@ocallahan.org>
24 : * Roger B. Sidje <rbs@maths.uq.edu.au>
25 : * Pierre Phaneuf <pp@ludusdesign.com>
26 : * Prabhat Hegde <prabhat.hegde@sun.com>
27 : * Tomi Leppikangas <tomi.leppikangas@oulu.fi>
28 : * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
29 : * Daniel Glazman <glazman@netscape.com>
30 : * Neil Deakin <neil@mozdevgroup.com>
31 : * Masayuki Nakano <masayuki@d-toybox.com>
32 : * Mats Palmgren <matspal@gmail.com>
33 : * Uri Bernstein <uriber@gmail.com>
34 : * Stephen Blackheath <entangled.mooched.stephen@blacksapphire.com>
35 : *
36 : * Alternatively, the contents of this file may be used under the terms of
37 : * either of the GNU General Public License Version 2 or later (the "GPL"),
38 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
39 : * in which case the provisions of the GPL or the LGPL are applicable instead
40 : * of those above. If you wish to allow use of your version of this file only
41 : * under the terms of either the GPL or the LGPL, and not to allow others to
42 : * use your version of this file under the terms of the MPL, indicate your
43 : * decision by deleting the provisions above and replace them with the notice
44 : * and other provisions required by the GPL or the LGPL. If you do not delete
45 : * the provisions above, a recipient may use your version of this file under
46 : * the terms of any one of the MPL, the GPL or the LGPL.
47 : *
48 : * ***** END LICENSE BLOCK ***** */
49 :
50 : #ifndef nsTextFrame_h__
51 : #define nsTextFrame_h__
52 :
53 : #include "nsFrame.h"
54 : #include "nsSplittableFrame.h"
55 : #include "nsLineBox.h"
56 : #include "gfxFont.h"
57 : #include "gfxSkipChars.h"
58 : #include "gfxContext.h"
59 : #include "nsDisplayList.h"
60 :
61 : class nsTextPaintStyle;
62 : class PropertyProvider;
63 :
64 : // This state bit is set on frames that have some non-collapsed characters after
65 : // reflow
66 : #define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31)
67 :
68 : #define TEXT_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(61)
69 :
70 : class nsTextFrame : public nsFrame {
71 : public:
72 : NS_DECL_FRAMEARENA_HELPERS
73 :
74 : friend class nsContinuingTextFrame;
75 :
76 0 : nsTextFrame(nsStyleContext* aContext)
77 0 : : nsFrame(aContext)
78 : {
79 0 : NS_ASSERTION(mContentOffset == 0, "Bogus content offset");
80 0 : }
81 :
82 : // nsIFrame
83 : NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
84 : const nsRect& aDirtyRect,
85 : const nsDisplayListSet& aLists);
86 :
87 : NS_IMETHOD Init(nsIContent* aContent,
88 : nsIFrame* aParent,
89 : nsIFrame* aPrevInFlow);
90 :
91 : virtual void DestroyFrom(nsIFrame* aDestructRoot);
92 :
93 : NS_IMETHOD GetCursor(const nsPoint& aPoint,
94 : nsIFrame::Cursor& aCursor);
95 :
96 : NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo);
97 :
98 : virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
99 :
100 0 : virtual nsIFrame* GetNextContinuation() const {
101 0 : return mNextContinuation;
102 : }
103 0 : NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) {
104 0 : NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(),
105 : "setting a next continuation with incorrect type!");
106 0 : NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this),
107 : "creating a loop in continuation chain!");
108 0 : mNextContinuation = aNextContinuation;
109 0 : if (aNextContinuation)
110 0 : aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
111 0 : return NS_OK;
112 : }
113 0 : virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); }
114 0 : nsIFrame* GetNextInFlow() const {
115 0 : return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ?
116 0 : mNextContinuation : nsnull;
117 : }
118 0 : NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) {
119 0 : NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(),
120 : "setting a next in flow with incorrect type!");
121 0 : NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this),
122 : "creating a loop in continuation chain!");
123 0 : mNextContinuation = aNextInFlow;
124 0 : if (aNextInFlow)
125 0 : aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
126 0 : return NS_OK;
127 : }
128 : virtual nsIFrame* GetLastInFlow() const;
129 : virtual nsIFrame* GetLastContinuation() const;
130 :
131 0 : virtual nsSplittableType GetSplittableType() const {
132 0 : return NS_FRAME_SPLITTABLE;
133 : }
134 :
135 : /**
136 : * Get the "type" of the frame
137 : *
138 : * @see nsGkAtoms::textFrame
139 : */
140 : virtual nsIAtom* GetType() const;
141 :
142 0 : virtual bool IsFrameOfType(PRUint32 aFlags) const
143 : {
144 : // Set the frame state bit for text frames to mark them as replaced.
145 : // XXX kipp: temporary
146 : return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced |
147 0 : nsIFrame::eLineParticipant));
148 : }
149 :
150 : #ifdef DEBUG
151 : NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
152 : NS_IMETHOD GetFrameName(nsAString& aResult) const;
153 : NS_IMETHOD_(nsFrameState) GetDebugStateBits() const ;
154 : #endif
155 :
156 : virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
157 : ContentOffsets GetCharacterOffsetAtFramePoint(const nsPoint &aPoint);
158 :
159 : /**
160 : * This is called only on the primary text frame. It indicates that
161 : * the selection state of the given character range has changed.
162 : * Text in the range is unconditionally invalidated
163 : * (nsTypedSelection::Repaint depends on this).
164 : * @param aSelected true if the selection has been added to the range,
165 : * false otherwise
166 : * @param aType the type of selection added or removed
167 : */
168 : void SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
169 : SelectionType aType);
170 :
171 : virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
172 : virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
173 : bool aRespectClusters = true);
174 : virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
175 : PRInt32* aOffset, PeekWordState* aState);
176 :
177 : NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, bool aRecurse, bool *aFinished, bool *_retval);
178 :
179 : // Flags for aSetLengthFlags
180 : enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 };
181 :
182 : // Update offsets to account for new length. This may clear mTextRun.
183 : void SetLength(PRInt32 aLength, nsLineLayout* aLineLayout,
184 : PRUint32 aSetLengthFlags = 0);
185 :
186 : NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;
187 :
188 : virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end);
189 :
190 : NS_IMETHOD GetPointFromOffset(PRInt32 inOffset,
191 : nsPoint* outPoint);
192 :
193 : NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset,
194 : bool inHint,
195 : PRInt32* outFrameContentOffset,
196 : nsIFrame* *outChildFrame);
197 :
198 : virtual bool IsVisibleInSelection(nsISelection* aSelection);
199 :
200 : virtual bool IsEmpty();
201 0 : virtual bool IsSelfEmpty() { return IsEmpty(); }
202 : virtual nscoord GetBaseline() const;
203 :
204 : /**
205 : * @return true if this text frame ends with a newline character. It
206 : * should return false if this is not a text frame.
207 : */
208 : virtual bool HasTerminalNewline() const;
209 :
210 : /**
211 : * Returns true if this text frame is logically adjacent to the end of the
212 : * line.
213 : */
214 : bool IsAtEndOfLine() const;
215 :
216 : /**
217 : * Call this only after reflow the frame. Returns true if non-collapsed
218 : * characters are present.
219 : */
220 0 : bool HasNoncollapsedCharacters() const {
221 0 : return (GetStateBits() & TEXT_HAS_NONCOLLAPSED_CHARACTERS) != 0;
222 : }
223 :
224 : #ifdef ACCESSIBILITY
225 : virtual already_AddRefed<nsAccessible> CreateAccessible();
226 : #endif
227 :
228 : float GetFontSizeInflation() const;
229 0 : bool HasFontSizeInflation() const {
230 0 : return (GetStateBits() & TEXT_HAS_FONT_INFLATION) != 0;
231 : }
232 : void SetFontSizeInflation(float aInflation);
233 :
234 : virtual void MarkIntrinsicWidthsDirty();
235 : virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
236 : virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
237 : virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
238 : InlineMinWidthData *aData);
239 : virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
240 : InlinePrefWidthData *aData);
241 : virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
242 : nsSize aCBSize, nscoord aAvailableWidth,
243 : nsSize aMargin, nsSize aBorder, nsSize aPadding,
244 : bool aShrinkWrap);
245 : virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
246 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
247 : nsHTMLReflowMetrics& aMetrics,
248 : const nsHTMLReflowState& aReflowState,
249 : nsReflowStatus& aStatus);
250 : virtual bool CanContinueTextRun() const;
251 : // Method that is called for a text frame that is logically
252 : // adjacent to the end of the line (i.e. followed only by empty text frames,
253 : // placeholders or inlines containing such).
254 : struct TrimOutput {
255 : // true if we trimmed some space or changed metrics in some other way.
256 : // In this case, we should call RecomputeOverflow on this frame.
257 : bool mChanged;
258 : // true if the last character is not justifiable so should be subtracted
259 : // from the count of justifiable characters in the frame, since the last
260 : // character in a line is not justifiable.
261 : bool mLastCharIsJustifiable;
262 : // an amount to *subtract* from the frame's width (zero if !mChanged)
263 : nscoord mDeltaWidth;
264 : };
265 : TrimOutput TrimTrailingWhiteSpace(nsRenderingContext* aRC);
266 : virtual nsresult GetRenderedText(nsAString* aString = nsnull,
267 : gfxSkipChars* aSkipChars = nsnull,
268 : gfxSkipCharsIterator* aSkipIter = nsnull,
269 : PRUint32 aSkippedStartOffset = 0,
270 : PRUint32 aSkippedMaxLength = PR_UINT32_MAX);
271 :
272 : nsOverflowAreas
273 : RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState);
274 :
275 : enum TextRunType {
276 : // Anything in reflow (but not intrinsic width calculation) or
277 : // painting should use the inflated text run (i.e., with font size
278 : // inflation applied).
279 : eInflated,
280 : // Intrinsic width calculation should use the non-inflated text run.
281 : // When there is font size inflation, it will be different.
282 : eNotInflated
283 : };
284 :
285 : void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext,
286 : nsIFrame::InlineMinWidthData *aData,
287 : float aInflation, TextRunType aTextRunType);
288 : void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext,
289 : InlinePrefWidthData *aData,
290 : float aInflation, TextRunType aTextRunType);
291 :
292 : /**
293 : * Calculate the horizontal bounds of the grapheme clusters that fit entirely
294 : * inside the given left/right edges (which are positive lengths from the
295 : * respective frame edge). If an input value is zero it is ignored and the
296 : * result for that edge is zero. All out parameter values are undefined when
297 : * the method returns false.
298 : * @return true if at least one whole grapheme cluster fit between the edges
299 : */
300 : bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge,
301 : nscoord* aSnappedLeftEdge,
302 : nscoord* aSnappedRightEdge);
303 : /**
304 : * Same as above; this method also the returns the corresponding text run
305 : * offset and number of characters that fit. All out parameter values are
306 : * undefined when the method returns false.
307 : * @return true if at least one whole grapheme cluster fit between the edges
308 : */
309 : bool MeasureCharClippedText(PropertyProvider& aProvider,
310 : nscoord aLeftEdge, nscoord aRightEdge,
311 : PRUint32* aStartOffset, PRUint32* aMaxLength,
312 : nscoord* aSnappedLeftEdge,
313 : nscoord* aSnappedRightEdge);
314 : // primary frame paint method called from nsDisplayText
315 : // The private DrawText() is what applies the text to a graphics context
316 : void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
317 : const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem);
318 : // helper: paint text frame when we're impacted by at least one selection.
319 : // Return false if the text was not painted and we should continue with
320 : // the fast path.
321 : bool PaintTextWithSelection(gfxContext* aCtx,
322 : const gfxPoint& aFramePt,
323 : const gfxPoint& aTextBaselinePt,
324 : const gfxRect& aDirtyRect,
325 : PropertyProvider& aProvider,
326 : PRUint32 aContentOffset,
327 : PRUint32 aContentLength,
328 : nsTextPaintStyle& aTextPaintStyle,
329 : const nsCharClipDisplayItem::ClipEdges& aClipEdges);
330 : // helper: paint text with foreground and background colors determined
331 : // by selection(s). Also computes a mask of all selection types applying to
332 : // our text, returned in aAllTypes.
333 : // Return false if the text was not painted and we should continue with
334 : // the fast path.
335 : bool PaintTextWithSelectionColors(gfxContext* aCtx,
336 : const gfxPoint& aFramePt,
337 : const gfxPoint& aTextBaselinePt,
338 : const gfxRect& aDirtyRect,
339 : PropertyProvider& aProvider,
340 : PRUint32 aContentOffset,
341 : PRUint32 aContentLength,
342 : nsTextPaintStyle& aTextPaintStyle,
343 : SelectionDetails* aDetails,
344 : SelectionType* aAllTypes,
345 : const nsCharClipDisplayItem::ClipEdges& aClipEdges);
346 : // helper: paint text decorations for text selected by aSelectionType
347 : void PaintTextSelectionDecorations(gfxContext* aCtx,
348 : const gfxPoint& aFramePt,
349 : const gfxPoint& aTextBaselinePt,
350 : const gfxRect& aDirtyRect,
351 : PropertyProvider& aProvider,
352 : PRUint32 aContentOffset,
353 : PRUint32 aContentLength,
354 : nsTextPaintStyle& aTextPaintStyle,
355 : SelectionDetails* aDetails,
356 : SelectionType aSelectionType);
357 :
358 : virtual nscolor GetCaretColorAt(PRInt32 aOffset);
359 :
360 : PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags);
361 :
362 : #ifdef DEBUG
363 : void ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const;
364 : #endif
365 :
366 0 : PRInt32 GetContentOffset() const { return mContentOffset; }
367 0 : PRInt32 GetContentLength() const
368 : {
369 0 : NS_ASSERTION(GetContentEnd() - mContentOffset >= 0, "negative length");
370 0 : return GetContentEnd() - mContentOffset;
371 : }
372 : PRInt32 GetContentEnd() const;
373 : // This returns the length the frame thinks it *should* have after it was
374 : // last reflowed (0 if it hasn't been reflowed yet). This should be used only
375 : // when setting up the text offsets for a new continuation frame.
376 0 : PRInt32 GetContentLengthHint() const { return mContentLengthHint; }
377 :
378 : // Compute the length of the content mapped by this frame
379 : // and all its in-flow siblings. Basically this means starting at mContentOffset
380 : // and going to the end of the text node or the next bidi continuation
381 : // boundary.
382 : PRInt32 GetInFlowContentLength();
383 :
384 : /**
385 : * Acquires the text run for this content, if necessary.
386 : * @param aWhichTextRun indicates whether to get an inflated or non-inflated
387 : * text run
388 : * @param aInflation the text inflation scale
389 : * @param aReferenceContext the rendering context to use as a reference for
390 : * creating the textrun, if available (if not, we'll create one which will
391 : * just be slower)
392 : * @param aLineContainer the block ancestor for this frame, or nsnull if
393 : * unknown
394 : * @param aFlowEndInTextRun if non-null, this returns the textrun offset of
395 : * end of the text associated with this frame and its in-flow siblings
396 : * @return a gfxSkipCharsIterator set up to map DOM offsets for this frame
397 : * to offsets into the textrun; its initial offset is set to this frame's
398 : * content offset
399 : */
400 : gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun,
401 : float aInflation,
402 : gfxContext* aReferenceContext = nsnull,
403 : nsIFrame* aLineContainer = nsnull,
404 : const nsLineList::iterator* aLine = nsnull,
405 : PRUint32* aFlowEndInTextRun = nsnull);
406 : // Since we can't reference |this| in default arguments:
407 0 : gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun) {
408 : return EnsureTextRun(aWhichTextRun,
409 : (aWhichTextRun == eInflated)
410 0 : ? GetFontSizeInflation() : 1.0f);
411 : }
412 :
413 :
414 0 : gfxTextRun* GetTextRun(TextRunType aWhichTextRun) {
415 0 : if (aWhichTextRun == eInflated || !HasFontSizeInflation())
416 0 : return mTextRun;
417 0 : return GetUninflatedTextRun();
418 : }
419 : gfxTextRun* GetUninflatedTextRun();
420 : void SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun,
421 : float aInflation);
422 : /**
423 : * Notify the frame that it should drop its pointer to a text run.
424 : * Returns whether the text run was removed (i.e., whether it was
425 : * associated with this frame, either as its inflated or non-inflated
426 : * text run.
427 : */
428 : bool RemoveTextRun(gfxTextRun* aTextRun);
429 : /**
430 : * Clears out |mTextRun| (or the uninflated text run, when aInflated
431 : * is nsTextFrame::eNotInflated and there is inflation) from all frames that hold a
432 : * reference to it, starting at |aStartContinuation|, or if it's
433 : * nsnull, starting at |this|. Deletes the text run if all references
434 : * were cleared and it's not cached.
435 : */
436 : void ClearTextRun(nsTextFrame* aStartContinuation,
437 : TextRunType aWhichTextRun);
438 :
439 0 : void ClearTextRuns() {
440 0 : ClearTextRun(nsnull, nsTextFrame::eInflated);
441 0 : ClearTextRun(nsnull, nsTextFrame::eNotInflated);
442 0 : }
443 :
444 : // Get the DOM content range mapped by this frame after excluding
445 : // whitespace subject to start-of-line and end-of-line trimming.
446 : // The textrun must have been created before calling this.
447 : struct TrimmedOffsets {
448 : PRInt32 mStart;
449 : PRInt32 mLength;
450 0 : PRInt32 GetEnd() { return mStart + mLength; }
451 : };
452 : TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
453 : bool aTrimAfter);
454 :
455 : // Similar to Reflow(), but for use from nsLineLayout
456 : void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
457 : nsRenderingContext* aRenderingContext, bool aShouldBlink,
458 : nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus);
459 :
460 : bool IsFloatingFirstLetterChild() const;
461 :
462 : protected:
463 : virtual ~nsTextFrame();
464 :
465 : nsIFrame* mNextContinuation;
466 : // The key invariant here is that mContentOffset never decreases along
467 : // a next-continuation chain. And of course mContentOffset is always <= the
468 : // the text node's content length, and the mContentOffset for the first frame
469 : // is always 0. Furthermore the text mapped by a frame is determined by
470 : // GetContentOffset() and GetContentLength()/GetContentEnd(), which get
471 : // the length from the difference between this frame's offset and the next
472 : // frame's offset, or the text length if there is no next frame. This means
473 : // the frames always map the text node without overlapping or leaving any gaps.
474 : PRInt32 mContentOffset;
475 : // This does *not* indicate the length of text currently mapped by the frame;
476 : // instead it's a hint saying that this frame *wants* to map this much text
477 : // so if we create a new continuation, this is where that continuation should
478 : // start.
479 : PRInt32 mContentLengthHint;
480 : nscoord mAscent;
481 : gfxTextRun* mTextRun;
482 :
483 : /**
484 : * Return true if the frame is part of a Selection.
485 : * Helper method to implement the public IsSelected() API.
486 : */
487 : virtual bool IsFrameSelected() const;
488 :
489 : // The caller of this method must call DestroySelectionDetails() on the
490 : // return value, if that return value is not null. Calling
491 : // DestroySelectionDetails() on a null value is still OK, just not necessary.
492 : SelectionDetails* GetSelectionDetails();
493 :
494 : void UnionAdditionalOverflow(nsPresContext* aPresContext,
495 : const nsHTMLReflowState& aBlockReflowState,
496 : PropertyProvider& aProvider,
497 : nsRect* aVisualOverflowRect,
498 : bool aIncludeTextDecorations);
499 :
500 : void PaintOneShadow(PRUint32 aOffset,
501 : PRUint32 aLength,
502 : nsCSSShadowItem* aShadowDetails,
503 : PropertyProvider* aProvider,
504 : const nsRect& aDirtyRect,
505 : const gfxPoint& aFramePt,
506 : const gfxPoint& aTextBaselinePt,
507 : gfxContext* aCtx,
508 : const nscolor& aForegroundColor,
509 : const nsCharClipDisplayItem::ClipEdges& aClipEdges,
510 : nscoord aLeftSideOffset);
511 :
512 0 : struct LineDecoration {
513 : nsIFrame* mFrame;
514 :
515 : // This is represents the offset from our baseline to mFrame's baseline;
516 : // positive offsets are *above* the baseline and negative offsets below
517 : nscoord mBaselineOffset;
518 :
519 : nscolor mColor;
520 : PRUint8 mStyle;
521 :
522 0 : LineDecoration(nsIFrame *const aFrame,
523 : const nscoord aOff,
524 : const nscolor aColor,
525 : const PRUint8 aStyle)
526 : : mFrame(aFrame),
527 : mBaselineOffset(aOff),
528 : mColor(aColor),
529 0 : mStyle(aStyle)
530 0 : {}
531 :
532 0 : LineDecoration(const LineDecoration& aOther)
533 : : mFrame(aOther.mFrame),
534 : mBaselineOffset(aOther.mBaselineOffset),
535 : mColor(aOther.mColor),
536 0 : mStyle(aOther.mStyle)
537 0 : {}
538 :
539 : bool operator==(const LineDecoration& aOther) const {
540 : return mFrame == aOther.mFrame &&
541 : mStyle == aOther.mStyle &&
542 : mColor == aOther.mColor &&
543 : mBaselineOffset == aOther.mBaselineOffset;
544 : }
545 : };
546 0 : struct TextDecorations {
547 : nsAutoTArray<LineDecoration, 1> mOverlines, mUnderlines, mStrikes;
548 :
549 0 : TextDecorations() { }
550 :
551 0 : bool HasDecorationLines() const {
552 0 : return HasUnderline() || HasOverline() || HasStrikeout();
553 : }
554 0 : bool HasUnderline() const {
555 0 : return !mUnderlines.IsEmpty();
556 : }
557 0 : bool HasOverline() const {
558 0 : return !mOverlines.IsEmpty();
559 : }
560 0 : bool HasStrikeout() const {
561 0 : return !mStrikes.IsEmpty();
562 : }
563 : };
564 : void GetTextDecorations(nsPresContext* aPresContext,
565 : TextDecorations& aDecorations);
566 :
567 : void DrawTextRun(gfxContext* const aCtx,
568 : const gfxPoint& aTextBaselinePt,
569 : PRUint32 aOffset,
570 : PRUint32 aLength,
571 : PropertyProvider& aProvider,
572 : gfxFloat& aAdvanceWidth,
573 : bool aDrawSoftHyphen);
574 :
575 : void DrawTextRunAndDecorations(gfxContext* const aCtx,
576 : const gfxRect& aDirtyRect,
577 : const gfxPoint& aFramePt,
578 : const gfxPoint& aTextBaselinePt,
579 : PRUint32 aOffset,
580 : PRUint32 aLength,
581 : PropertyProvider& aProvider,
582 : const nsTextPaintStyle& aTextStyle,
583 : const nsCharClipDisplayItem::ClipEdges& aClipEdges,
584 : gfxFloat& aAdvanceWidth,
585 : bool aDrawSoftHyphen,
586 : const TextDecorations& aDecorations,
587 : const nscolor* const aDecorationOverrideColor);
588 :
589 : void DrawText(gfxContext* const aCtx,
590 : const gfxRect& aDirtyRect,
591 : const gfxPoint& aFramePt,
592 : const gfxPoint& aTextBaselinePt,
593 : PRUint32 aOffset,
594 : PRUint32 aLength,
595 : PropertyProvider& aProvider,
596 : const nsTextPaintStyle& aTextStyle,
597 : const nsCharClipDisplayItem::ClipEdges& aClipEdges,
598 : gfxFloat& aAdvanceWidth,
599 : bool aDrawSoftHyphen,
600 : const nscolor* const aDecorationOverrideColor = nsnull);
601 :
602 : // Set non empty rect to aRect, it should be overflow rect or frame rect.
603 : // If the result rect is larger than the given rect, this returns true.
604 : bool CombineSelectionUnderlineRect(nsPresContext* aPresContext,
605 : nsRect& aRect);
606 :
607 : ContentOffsets GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint,
608 : bool aForInsertionPoint);
609 :
610 : void ClearFrameOffsetCache();
611 :
612 : virtual bool HasAnyNoncollapsedCharacters();
613 :
614 : void ClearMetrics(nsHTMLReflowMetrics& aMetrics);
615 : };
616 :
617 : #endif
|