1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsTextFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,706 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsTextFrame_h__ 1.10 +#define nsTextFrame_h__ 1.11 + 1.12 +#include "mozilla/Attributes.h" 1.13 +#include "nsFrame.h" 1.14 +#include "nsSplittableFrame.h" 1.15 +#include "nsLineBox.h" 1.16 +#include "gfxFont.h" 1.17 +#include "gfxSkipChars.h" 1.18 +#include "nsDisplayList.h" 1.19 + 1.20 +class nsTextPaintStyle; 1.21 +class PropertyProvider; 1.22 + 1.23 +typedef nsFrame nsTextFrameBase; 1.24 + 1.25 +class nsDisplayTextGeometry; 1.26 +class nsDisplayText; 1.27 + 1.28 +class nsTextFrameTextRunCache { 1.29 +public: 1.30 + static void Init(); 1.31 + static void Shutdown(); 1.32 +}; 1.33 + 1.34 +class nsTextFrame : public nsTextFrameBase { 1.35 +public: 1.36 + NS_DECL_QUERYFRAME_TARGET(nsTextFrame) 1.37 + NS_DECL_FRAMEARENA_HELPERS 1.38 + 1.39 + friend class nsContinuingTextFrame; 1.40 + friend class nsDisplayTextGeometry; 1.41 + friend class nsDisplayText; 1.42 + 1.43 + nsTextFrame(nsStyleContext* aContext) 1.44 + : nsTextFrameBase(aContext) 1.45 + { 1.46 + NS_ASSERTION(mContentOffset == 0, "Bogus content offset"); 1.47 + } 1.48 + 1.49 + // nsQueryFrame 1.50 + NS_DECL_QUERYFRAME 1.51 + 1.52 + // nsIFrame 1.53 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.54 + const nsRect& aDirtyRect, 1.55 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.56 + 1.57 + virtual void Init(nsIContent* aContent, 1.58 + nsIFrame* aParent, 1.59 + nsIFrame* aPrevInFlow) MOZ_OVERRIDE; 1.60 + 1.61 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.62 + 1.63 + virtual nsresult GetCursor(const nsPoint& aPoint, 1.64 + nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; 1.65 + 1.66 + virtual nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) MOZ_OVERRIDE; 1.67 + 1.68 + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; 1.69 + 1.70 + virtual nsIFrame* GetNextContinuation() const MOZ_OVERRIDE { 1.71 + return mNextContinuation; 1.72 + } 1.73 + virtual void SetNextContinuation(nsIFrame* aNextContinuation) MOZ_OVERRIDE { 1.74 + NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(), 1.75 + "setting a next continuation with incorrect type!"); 1.76 + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this), 1.77 + "creating a loop in continuation chain!"); 1.78 + mNextContinuation = aNextContinuation; 1.79 + if (aNextContinuation) 1.80 + aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); 1.81 + } 1.82 + virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE { return GetNextInFlow(); } 1.83 + nsIFrame* GetNextInFlow() const { 1.84 + return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? 1.85 + mNextContinuation : nullptr; 1.86 + } 1.87 + virtual void SetNextInFlow(nsIFrame* aNextInFlow) MOZ_OVERRIDE { 1.88 + NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(), 1.89 + "setting a next in flow with incorrect type!"); 1.90 + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this), 1.91 + "creating a loop in continuation chain!"); 1.92 + mNextContinuation = aNextInFlow; 1.93 + if (aNextInFlow) 1.94 + aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); 1.95 + } 1.96 + virtual nsIFrame* LastInFlow() const MOZ_OVERRIDE; 1.97 + virtual nsIFrame* LastContinuation() const MOZ_OVERRIDE; 1.98 + 1.99 + virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE { 1.100 + return NS_FRAME_SPLITTABLE; 1.101 + } 1.102 + 1.103 + /** 1.104 + * Get the "type" of the frame 1.105 + * 1.106 + * @see nsGkAtoms::textFrame 1.107 + */ 1.108 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.109 + 1.110 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.111 + { 1.112 + // Set the frame state bit for text frames to mark them as replaced. 1.113 + // XXX kipp: temporary 1.114 + return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | 1.115 + nsIFrame::eLineParticipant)); 1.116 + } 1.117 + 1.118 + virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; 1.119 + virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; 1.120 + 1.121 +#ifdef DEBUG_FRAME_DUMP 1.122 + void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE; 1.123 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.124 + void ToCString(nsCString& aBuf, int32_t* aTotalContentLength) const; 1.125 +#endif 1.126 + 1.127 +#ifdef DEBUG 1.128 + virtual nsFrameState GetDebugStateBits() const MOZ_OVERRIDE; 1.129 +#endif 1.130 + 1.131 + virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE; 1.132 + ContentOffsets GetCharacterOffsetAtFramePoint(const nsPoint &aPoint); 1.133 + 1.134 + /** 1.135 + * This is called only on the primary text frame. It indicates that 1.136 + * the selection state of the given character range has changed. 1.137 + * Text in the range is unconditionally invalidated 1.138 + * (Selection::Repaint depends on this). 1.139 + * @param aSelected true if the selection has been added to the range, 1.140 + * false otherwise 1.141 + * @param aType the type of selection added or removed 1.142 + */ 1.143 + void SetSelectedRange(uint32_t aStart, uint32_t aEnd, bool aSelected, 1.144 + SelectionType aType); 1.145 + 1.146 + virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; 1.147 + virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, 1.148 + bool aRespectClusters = true) MOZ_OVERRIDE; 1.149 + virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, 1.150 + int32_t* aOffset, PeekWordState* aState) MOZ_OVERRIDE; 1.151 + 1.152 + virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval) MOZ_OVERRIDE; 1.153 + 1.154 + // Flags for aSetLengthFlags 1.155 + enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 }; 1.156 + 1.157 + // Update offsets to account for new length. This may clear mTextRun. 1.158 + void SetLength(int32_t aLength, nsLineLayout* aLineLayout, 1.159 + uint32_t aSetLengthFlags = 0); 1.160 + 1.161 + virtual nsresult GetOffsets(int32_t &start, int32_t &end)const MOZ_OVERRIDE; 1.162 + 1.163 + virtual void AdjustOffsetsForBidi(int32_t start, int32_t end) MOZ_OVERRIDE; 1.164 + 1.165 + virtual nsresult GetPointFromOffset(int32_t inOffset, 1.166 + nsPoint* outPoint) MOZ_OVERRIDE; 1.167 + 1.168 + virtual nsresult GetChildFrameContainingOffset(int32_t inContentOffset, 1.169 + bool inHint, 1.170 + int32_t* outFrameContentOffset, 1.171 + nsIFrame** outChildFrame) MOZ_OVERRIDE; 1.172 + 1.173 + virtual bool IsVisibleInSelection(nsISelection* aSelection) MOZ_OVERRIDE; 1.174 + 1.175 + virtual bool IsEmpty() MOZ_OVERRIDE; 1.176 + virtual bool IsSelfEmpty() MOZ_OVERRIDE { return IsEmpty(); } 1.177 + virtual nscoord GetBaseline() const MOZ_OVERRIDE; 1.178 + 1.179 + virtual bool HasSignificantTerminalNewline() const MOZ_OVERRIDE; 1.180 + 1.181 + /** 1.182 + * Returns true if this text frame is logically adjacent to the end of the 1.183 + * line. 1.184 + */ 1.185 + bool IsAtEndOfLine() const; 1.186 + 1.187 + /** 1.188 + * Call this only after reflow the frame. Returns true if non-collapsed 1.189 + * characters are present. 1.190 + */ 1.191 + bool HasNoncollapsedCharacters() const { 1.192 + return (GetStateBits() & TEXT_HAS_NONCOLLAPSED_CHARACTERS) != 0; 1.193 + } 1.194 + 1.195 +#ifdef ACCESSIBILITY 1.196 + virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; 1.197 +#endif 1.198 + 1.199 + float GetFontSizeInflation() const; 1.200 + bool IsCurrentFontInflation(float aInflation) const; 1.201 + bool HasFontSizeInflation() const { 1.202 + return (GetStateBits() & TEXT_HAS_FONT_INFLATION) != 0; 1.203 + } 1.204 + void SetFontSizeInflation(float aInflation); 1.205 + 1.206 + virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; 1.207 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.208 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.209 + virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, 1.210 + InlineMinWidthData *aData) MOZ_OVERRIDE; 1.211 + virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, 1.212 + InlinePrefWidthData *aData) MOZ_OVERRIDE; 1.213 + virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, 1.214 + nsSize aCBSize, nscoord aAvailableWidth, 1.215 + nsSize aMargin, nsSize aBorder, nsSize aPadding, 1.216 + uint32_t aFlags) MOZ_OVERRIDE; 1.217 + virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE; 1.218 + virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext, 1.219 + nscoord* aX, 1.220 + nscoord* aXMost) MOZ_OVERRIDE; 1.221 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.222 + nsHTMLReflowMetrics& aMetrics, 1.223 + const nsHTMLReflowState& aReflowState, 1.224 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.225 + virtual bool CanContinueTextRun() const MOZ_OVERRIDE; 1.226 + // Method that is called for a text frame that is logically 1.227 + // adjacent to the end of the line (i.e. followed only by empty text frames, 1.228 + // placeholders or inlines containing such). 1.229 + struct TrimOutput { 1.230 + // true if we trimmed some space or changed metrics in some other way. 1.231 + // In this case, we should call RecomputeOverflow on this frame. 1.232 + bool mChanged; 1.233 + // true if the last character is not justifiable so should be subtracted 1.234 + // from the count of justifiable characters in the frame, since the last 1.235 + // character in a line is not justifiable. 1.236 + bool mLastCharIsJustifiable; 1.237 + // an amount to *subtract* from the frame's width (zero if !mChanged) 1.238 + nscoord mDeltaWidth; 1.239 + }; 1.240 + TrimOutput TrimTrailingWhiteSpace(nsRenderingContext* aRC); 1.241 + virtual nsresult GetRenderedText(nsAString* aString = nullptr, 1.242 + gfxSkipChars* aSkipChars = nullptr, 1.243 + gfxSkipCharsIterator* aSkipIter = nullptr, 1.244 + uint32_t aSkippedStartOffset = 0, 1.245 + uint32_t aSkippedMaxLength = UINT32_MAX) MOZ_OVERRIDE; 1.246 + 1.247 + nsOverflowAreas 1.248 + RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState); 1.249 + 1.250 + enum TextRunType { 1.251 + // Anything in reflow (but not intrinsic width calculation) or 1.252 + // painting should use the inflated text run (i.e., with font size 1.253 + // inflation applied). 1.254 + eInflated, 1.255 + // Intrinsic width calculation should use the non-inflated text run. 1.256 + // When there is font size inflation, it will be different. 1.257 + eNotInflated 1.258 + }; 1.259 + 1.260 + void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, 1.261 + nsIFrame::InlineMinWidthData *aData, 1.262 + TextRunType aTextRunType); 1.263 + void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, 1.264 + InlinePrefWidthData *aData, 1.265 + TextRunType aTextRunType); 1.266 + 1.267 + /** 1.268 + * Calculate the horizontal bounds of the grapheme clusters that fit entirely 1.269 + * inside the given left/right edges (which are positive lengths from the 1.270 + * respective frame edge). If an input value is zero it is ignored and the 1.271 + * result for that edge is zero. All out parameter values are undefined when 1.272 + * the method returns false. 1.273 + * @return true if at least one whole grapheme cluster fit between the edges 1.274 + */ 1.275 + bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge, 1.276 + nscoord* aSnappedLeftEdge, 1.277 + nscoord* aSnappedRightEdge); 1.278 + /** 1.279 + * Same as above; this method also the returns the corresponding text run 1.280 + * offset and number of characters that fit. All out parameter values are 1.281 + * undefined when the method returns false. 1.282 + * @return true if at least one whole grapheme cluster fit between the edges 1.283 + */ 1.284 + bool MeasureCharClippedText(PropertyProvider& aProvider, 1.285 + nscoord aLeftEdge, nscoord aRightEdge, 1.286 + uint32_t* aStartOffset, uint32_t* aMaxLength, 1.287 + nscoord* aSnappedLeftEdge, 1.288 + nscoord* aSnappedRightEdge); 1.289 + 1.290 + /** 1.291 + * Object with various callbacks for PaintText() to invoke for different parts 1.292 + * of the frame's text rendering, when we're generating paths rather than 1.293 + * painting. 1.294 + * 1.295 + * Callbacks are invoked in the following order: 1.296 + * 1.297 + * (NotifyBeforeSelectionBackground NotifySelectionBackgroundPathEmitted)? 1.298 + * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* 1.299 + * NotifyBeforeText 1.300 + * (NotifyGlyphPathEmitted | 1.301 + * (NotifyBeforeSVGGlyphPainted NotifyAfterSVGGlyphPainted))* 1.302 + * NotifyAfterText 1.303 + * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* 1.304 + * (NotifyBeforeSelectionDecorationLine NotifySelectionDecorationLinePathEmitted)* 1.305 + * 1.306 + * The color of each part of the frame's text rendering is passed as an argument 1.307 + * to the NotifyBefore* callback for that part. The nscolor can take on one of 1.308 + * the three selection special colors defined in LookAndFeel.h -- 1.309 + * NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR and 1.310 + * NS_40PERCENT_FOREGROUND_COLOR. 1.311 + */ 1.312 + struct DrawPathCallbacks : gfxTextRunDrawCallbacks 1.313 + { 1.314 + /** 1.315 + * @param aShouldPaintSVGGlyphs Whether SVG glyphs should be painted. 1.316 + */ 1.317 + DrawPathCallbacks(bool aShouldPaintSVGGlyphs = false) 1.318 + : gfxTextRunDrawCallbacks(aShouldPaintSVGGlyphs) 1.319 + { 1.320 + } 1.321 + 1.322 + /** 1.323 + * Called just before any paths have been emitted to the gfxContext 1.324 + * for the glyphs of the frame's text. 1.325 + */ 1.326 + virtual void NotifyBeforeText(nscolor aColor) { } 1.327 + 1.328 + /** 1.329 + * Called just after all the paths have been emitted to the gfxContext 1.330 + * for the glyphs of the frame's text. 1.331 + */ 1.332 + virtual void NotifyAfterText() { } 1.333 + 1.334 + /** 1.335 + * Called just before a path corresponding to the selection background 1.336 + * has been emitted to the gfxContext. 1.337 + */ 1.338 + virtual void NotifyBeforeSelectionBackground(nscolor aColor) { } 1.339 + 1.340 + /** 1.341 + * Called just after a path corresponding to the selection background 1.342 + * has been emitted to the gfxContext. 1.343 + */ 1.344 + virtual void NotifySelectionBackgroundPathEmitted() { } 1.345 + 1.346 + /** 1.347 + * Called just before a path corresponding to a text decoration line 1.348 + * has been emitted to the gfxContext. 1.349 + */ 1.350 + virtual void NotifyBeforeDecorationLine(nscolor aColor) { } 1.351 + 1.352 + /** 1.353 + * Called just after a path corresponding to a text decoration line 1.354 + * has been emitted to the gfxContext. 1.355 + */ 1.356 + virtual void NotifyDecorationLinePathEmitted() { } 1.357 + 1.358 + /** 1.359 + * Called just before a path corresponding to a selection decoration line 1.360 + * has been emitted to the gfxContext. 1.361 + */ 1.362 + virtual void NotifyBeforeSelectionDecorationLine(nscolor aColor) { } 1.363 + 1.364 + /** 1.365 + * Called just after a path corresponding to a selection decoration line 1.366 + * has been emitted to the gfxContext. 1.367 + */ 1.368 + virtual void NotifySelectionDecorationLinePathEmitted() { } 1.369 + }; 1.370 + 1.371 + // Primary frame paint method called from nsDisplayText. Can also be used 1.372 + // to generate paths rather than paint the frame's text by passing a callback 1.373 + // object. The private DrawText() is what applies the text to a graphics 1.374 + // context. 1.375 + void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, 1.376 + const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem, 1.377 + gfxTextContextPaint* aContextPaint = nullptr, 1.378 + DrawPathCallbacks* aCallbacks = nullptr); 1.379 + // helper: paint text frame when we're impacted by at least one selection. 1.380 + // Return false if the text was not painted and we should continue with 1.381 + // the fast path. 1.382 + bool PaintTextWithSelection(gfxContext* aCtx, 1.383 + const gfxPoint& aFramePt, 1.384 + const gfxPoint& aTextBaselinePt, 1.385 + const gfxRect& aDirtyRect, 1.386 + PropertyProvider& aProvider, 1.387 + uint32_t aContentOffset, 1.388 + uint32_t aContentLength, 1.389 + nsTextPaintStyle& aTextPaintStyle, 1.390 + const nsCharClipDisplayItem::ClipEdges& aClipEdges, 1.391 + gfxTextContextPaint* aContextPaint, 1.392 + DrawPathCallbacks* aCallbacks); 1.393 + // helper: paint text with foreground and background colors determined 1.394 + // by selection(s). Also computes a mask of all selection types applying to 1.395 + // our text, returned in aAllTypes. 1.396 + // Return false if the text was not painted and we should continue with 1.397 + // the fast path. 1.398 + bool PaintTextWithSelectionColors(gfxContext* aCtx, 1.399 + const gfxPoint& aFramePt, 1.400 + const gfxPoint& aTextBaselinePt, 1.401 + const gfxRect& aDirtyRect, 1.402 + PropertyProvider& aProvider, 1.403 + uint32_t aContentOffset, 1.404 + uint32_t aContentLength, 1.405 + nsTextPaintStyle& aTextPaintStyle, 1.406 + SelectionDetails* aDetails, 1.407 + SelectionType* aAllTypes, 1.408 + const nsCharClipDisplayItem::ClipEdges& aClipEdges, 1.409 + DrawPathCallbacks* aCallbacks); 1.410 + // helper: paint text decorations for text selected by aSelectionType 1.411 + void PaintTextSelectionDecorations(gfxContext* aCtx, 1.412 + const gfxPoint& aFramePt, 1.413 + const gfxPoint& aTextBaselinePt, 1.414 + const gfxRect& aDirtyRect, 1.415 + PropertyProvider& aProvider, 1.416 + uint32_t aContentOffset, 1.417 + uint32_t aContentLength, 1.418 + nsTextPaintStyle& aTextPaintStyle, 1.419 + SelectionDetails* aDetails, 1.420 + SelectionType aSelectionType, 1.421 + DrawPathCallbacks* aCallbacks); 1.422 + 1.423 + virtual nscolor GetCaretColorAt(int32_t aOffset) MOZ_OVERRIDE; 1.424 + 1.425 + int16_t GetSelectionStatus(int16_t* aSelectionFlags); 1.426 + 1.427 + int32_t GetContentOffset() const { return mContentOffset; } 1.428 + int32_t GetContentLength() const 1.429 + { 1.430 + NS_ASSERTION(GetContentEnd() - mContentOffset >= 0, "negative length"); 1.431 + return GetContentEnd() - mContentOffset; 1.432 + } 1.433 + int32_t GetContentEnd() const; 1.434 + // This returns the length the frame thinks it *should* have after it was 1.435 + // last reflowed (0 if it hasn't been reflowed yet). This should be used only 1.436 + // when setting up the text offsets for a new continuation frame. 1.437 + int32_t GetContentLengthHint() const { return mContentLengthHint; } 1.438 + 1.439 + // Compute the length of the content mapped by this frame 1.440 + // and all its in-flow siblings. Basically this means starting at mContentOffset 1.441 + // and going to the end of the text node or the next bidi continuation 1.442 + // boundary. 1.443 + int32_t GetInFlowContentLength(); 1.444 + 1.445 + /** 1.446 + * Acquires the text run for this content, if necessary. 1.447 + * @param aWhichTextRun indicates whether to get an inflated or non-inflated 1.448 + * text run 1.449 + * @param aReferenceContext the rendering context to use as a reference for 1.450 + * creating the textrun, if available (if not, we'll create one which will 1.451 + * just be slower) 1.452 + * @param aLineContainer the block ancestor for this frame, or nullptr if 1.453 + * unknown 1.454 + * @param aFlowEndInTextRun if non-null, this returns the textrun offset of 1.455 + * end of the text associated with this frame and its in-flow siblings 1.456 + * @return a gfxSkipCharsIterator set up to map DOM offsets for this frame 1.457 + * to offsets into the textrun; its initial offset is set to this frame's 1.458 + * content offset 1.459 + */ 1.460 + gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun, 1.461 + gfxContext* aReferenceContext = nullptr, 1.462 + nsIFrame* aLineContainer = nullptr, 1.463 + const nsLineList::iterator* aLine = nullptr, 1.464 + uint32_t* aFlowEndInTextRun = nullptr); 1.465 + 1.466 + gfxTextRun* GetTextRun(TextRunType aWhichTextRun) { 1.467 + if (aWhichTextRun == eInflated || !HasFontSizeInflation()) 1.468 + return mTextRun; 1.469 + return GetUninflatedTextRun(); 1.470 + } 1.471 + gfxTextRun* GetUninflatedTextRun(); 1.472 + void SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun, 1.473 + float aInflation); 1.474 + bool IsInTextRunUserData() const { 1.475 + return GetStateBits() & 1.476 + (TEXT_IN_TEXTRUN_USER_DATA | TEXT_IN_UNINFLATED_TEXTRUN_USER_DATA); 1.477 + } 1.478 + /** 1.479 + * Notify the frame that it should drop its pointer to a text run. 1.480 + * Returns whether the text run was removed (i.e., whether it was 1.481 + * associated with this frame, either as its inflated or non-inflated 1.482 + * text run. 1.483 + */ 1.484 + bool RemoveTextRun(gfxTextRun* aTextRun); 1.485 + /** 1.486 + * Clears out |mTextRun| (or the uninflated text run, when aInflated 1.487 + * is nsTextFrame::eNotInflated and there is inflation) from all frames that hold a 1.488 + * reference to it, starting at |aStartContinuation|, or if it's 1.489 + * nullptr, starting at |this|. Deletes the text run if all references 1.490 + * were cleared and it's not cached. 1.491 + */ 1.492 + void ClearTextRun(nsTextFrame* aStartContinuation, 1.493 + TextRunType aWhichTextRun); 1.494 + 1.495 + void ClearTextRuns() { 1.496 + ClearTextRun(nullptr, nsTextFrame::eInflated); 1.497 + if (HasFontSizeInflation()) { 1.498 + ClearTextRun(nullptr, nsTextFrame::eNotInflated); 1.499 + } 1.500 + } 1.501 + 1.502 + /** 1.503 + * Wipe out references to textrun(s) without deleting the textruns. 1.504 + */ 1.505 + void DisconnectTextRuns(); 1.506 + 1.507 + // Get the DOM content range mapped by this frame after excluding 1.508 + // whitespace subject to start-of-line and end-of-line trimming. 1.509 + // The textrun must have been created before calling this. 1.510 + struct TrimmedOffsets { 1.511 + int32_t mStart; 1.512 + int32_t mLength; 1.513 + int32_t GetEnd() const { return mStart + mLength; } 1.514 + }; 1.515 + TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, 1.516 + bool aTrimAfter, bool aPostReflow = true); 1.517 + 1.518 + // Similar to Reflow(), but for use from nsLineLayout 1.519 + void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, 1.520 + nsRenderingContext* aRenderingContext, 1.521 + nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus); 1.522 + 1.523 + bool IsFloatingFirstLetterChild() const; 1.524 + 1.525 +protected: 1.526 + virtual ~nsTextFrame(); 1.527 + 1.528 + nsIFrame* mNextContinuation; 1.529 + // The key invariant here is that mContentOffset never decreases along 1.530 + // a next-continuation chain. And of course mContentOffset is always <= the 1.531 + // the text node's content length, and the mContentOffset for the first frame 1.532 + // is always 0. Furthermore the text mapped by a frame is determined by 1.533 + // GetContentOffset() and GetContentLength()/GetContentEnd(), which get 1.534 + // the length from the difference between this frame's offset and the next 1.535 + // frame's offset, or the text length if there is no next frame. This means 1.536 + // the frames always map the text node without overlapping or leaving any gaps. 1.537 + int32_t mContentOffset; 1.538 + // This does *not* indicate the length of text currently mapped by the frame; 1.539 + // instead it's a hint saying that this frame *wants* to map this much text 1.540 + // so if we create a new continuation, this is where that continuation should 1.541 + // start. 1.542 + int32_t mContentLengthHint; 1.543 + nscoord mAscent; 1.544 + gfxTextRun* mTextRun; 1.545 + 1.546 + /** 1.547 + * Return true if the frame is part of a Selection. 1.548 + * Helper method to implement the public IsSelected() API. 1.549 + */ 1.550 + virtual bool IsFrameSelected() const MOZ_OVERRIDE; 1.551 + 1.552 + // The caller of this method must call DestroySelectionDetails() on the 1.553 + // return value, if that return value is not null. Calling 1.554 + // DestroySelectionDetails() on a null value is still OK, just not necessary. 1.555 + SelectionDetails* GetSelectionDetails(); 1.556 + 1.557 + void UnionAdditionalOverflow(nsPresContext* aPresContext, 1.558 + const nsHTMLReflowState& aBlockReflowState, 1.559 + PropertyProvider& aProvider, 1.560 + nsRect* aVisualOverflowRect, 1.561 + bool aIncludeTextDecorations); 1.562 + 1.563 + void PaintOneShadow(uint32_t aOffset, 1.564 + uint32_t aLength, 1.565 + nsCSSShadowItem* aShadowDetails, 1.566 + PropertyProvider* aProvider, 1.567 + const nsRect& aDirtyRect, 1.568 + const gfxPoint& aFramePt, 1.569 + const gfxPoint& aTextBaselinePt, 1.570 + gfxContext* aCtx, 1.571 + const nscolor& aForegroundColor, 1.572 + const nsCharClipDisplayItem::ClipEdges& aClipEdges, 1.573 + nscoord aLeftSideOffset, 1.574 + gfxRect& aBoundingBox); 1.575 + 1.576 + struct LineDecoration { 1.577 + nsIFrame* mFrame; 1.578 + 1.579 + // This is represents the offset from our baseline to mFrame's baseline; 1.580 + // positive offsets are *above* the baseline and negative offsets below 1.581 + nscoord mBaselineOffset; 1.582 + 1.583 + nscolor mColor; 1.584 + uint8_t mStyle; 1.585 + 1.586 + LineDecoration(nsIFrame *const aFrame, 1.587 + const nscoord aOff, 1.588 + const nscolor aColor, 1.589 + const uint8_t aStyle) 1.590 + : mFrame(aFrame), 1.591 + mBaselineOffset(aOff), 1.592 + mColor(aColor), 1.593 + mStyle(aStyle) 1.594 + {} 1.595 + 1.596 + LineDecoration(const LineDecoration& aOther) 1.597 + : mFrame(aOther.mFrame), 1.598 + mBaselineOffset(aOther.mBaselineOffset), 1.599 + mColor(aOther.mColor), 1.600 + mStyle(aOther.mStyle) 1.601 + {} 1.602 + 1.603 + bool operator==(const LineDecoration& aOther) const { 1.604 + return mFrame == aOther.mFrame && 1.605 + mStyle == aOther.mStyle && 1.606 + mColor == aOther.mColor && 1.607 + mBaselineOffset == aOther.mBaselineOffset; 1.608 + } 1.609 + 1.610 + bool operator!=(const LineDecoration& aOther) const { 1.611 + return !(*this == aOther); 1.612 + } 1.613 + }; 1.614 + struct TextDecorations { 1.615 + nsAutoTArray<LineDecoration, 1> mOverlines, mUnderlines, mStrikes; 1.616 + 1.617 + TextDecorations() { } 1.618 + 1.619 + bool HasDecorationLines() const { 1.620 + return HasUnderline() || HasOverline() || HasStrikeout(); 1.621 + } 1.622 + bool HasUnderline() const { 1.623 + return !mUnderlines.IsEmpty(); 1.624 + } 1.625 + bool HasOverline() const { 1.626 + return !mOverlines.IsEmpty(); 1.627 + } 1.628 + bool HasStrikeout() const { 1.629 + return !mStrikes.IsEmpty(); 1.630 + } 1.631 + bool operator==(const TextDecorations& aOther) const { 1.632 + return mOverlines == aOther.mOverlines && 1.633 + mUnderlines == aOther.mUnderlines && 1.634 + mStrikes == aOther.mStrikes; 1.635 + } 1.636 + 1.637 + bool operator!=(const TextDecorations& aOther) const { 1.638 + return !(*this == aOther); 1.639 + } 1.640 + 1.641 + }; 1.642 + enum TextDecorationColorResolution { 1.643 + eResolvedColors, 1.644 + eUnresolvedColors 1.645 + }; 1.646 + void GetTextDecorations(nsPresContext* aPresContext, 1.647 + TextDecorationColorResolution aColorResolution, 1.648 + TextDecorations& aDecorations); 1.649 + 1.650 + void DrawTextRun(gfxContext* const aCtx, 1.651 + const gfxPoint& aTextBaselinePt, 1.652 + uint32_t aOffset, 1.653 + uint32_t aLength, 1.654 + PropertyProvider& aProvider, 1.655 + nscolor aTextColor, 1.656 + gfxFloat& aAdvanceWidth, 1.657 + bool aDrawSoftHyphen, 1.658 + gfxTextContextPaint* aContextPaint, 1.659 + DrawPathCallbacks* aCallbacks); 1.660 + 1.661 + void DrawTextRunAndDecorations(gfxContext* const aCtx, 1.662 + const gfxRect& aDirtyRect, 1.663 + const gfxPoint& aFramePt, 1.664 + const gfxPoint& aTextBaselinePt, 1.665 + uint32_t aOffset, 1.666 + uint32_t aLength, 1.667 + PropertyProvider& aProvider, 1.668 + const nsTextPaintStyle& aTextStyle, 1.669 + nscolor aTextColor, 1.670 + const nsCharClipDisplayItem::ClipEdges& aClipEdges, 1.671 + gfxFloat& aAdvanceWidth, 1.672 + bool aDrawSoftHyphen, 1.673 + const TextDecorations& aDecorations, 1.674 + const nscolor* const aDecorationOverrideColor, 1.675 + gfxTextContextPaint* aContextPaint, 1.676 + DrawPathCallbacks* aCallbacks); 1.677 + 1.678 + void DrawText(gfxContext* const aCtx, 1.679 + const gfxRect& aDirtyRect, 1.680 + const gfxPoint& aFramePt, 1.681 + const gfxPoint& aTextBaselinePt, 1.682 + uint32_t aOffset, 1.683 + uint32_t aLength, 1.684 + PropertyProvider& aProvider, 1.685 + const nsTextPaintStyle& aTextStyle, 1.686 + nscolor aTextColor, 1.687 + const nsCharClipDisplayItem::ClipEdges& aClipEdges, 1.688 + gfxFloat& aAdvanceWidth, 1.689 + bool aDrawSoftHyphen, 1.690 + const nscolor* const aDecorationOverrideColor = nullptr, 1.691 + gfxTextContextPaint* aContextPaint = nullptr, 1.692 + DrawPathCallbacks* aCallbacks = nullptr); 1.693 + 1.694 + // Set non empty rect to aRect, it should be overflow rect or frame rect. 1.695 + // If the result rect is larger than the given rect, this returns true. 1.696 + bool CombineSelectionUnderlineRect(nsPresContext* aPresContext, 1.697 + nsRect& aRect); 1.698 + 1.699 + ContentOffsets GetCharacterOffsetAtFramePointInternal(nsPoint aPoint, 1.700 + bool aForInsertionPoint); 1.701 + 1.702 + void ClearFrameOffsetCache(); 1.703 + 1.704 + virtual bool HasAnyNoncollapsedCharacters() MOZ_OVERRIDE; 1.705 + 1.706 + void ClearMetrics(nsHTMLReflowMetrics& aMetrics); 1.707 +}; 1.708 + 1.709 +#endif