2007-09-23 19:19:14 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
#ifndef nsTextFrame_h__
|
|
|
|
#define nsTextFrame_h__
|
|
|
|
|
|
|
|
#include "nsFrame.h"
|
2009-08-31 11:25:35 -07:00
|
|
|
#include "nsSplittableFrame.h"
|
2007-09-23 19:19:14 -07:00
|
|
|
#include "nsLineBox.h"
|
|
|
|
#include "gfxFont.h"
|
|
|
|
#include "gfxSkipChars.h"
|
2008-06-12 15:02:32 -07:00
|
|
|
#include "gfxContext.h"
|
2011-06-22 11:11:48 -07:00
|
|
|
#include "nsDisplayList.h"
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
class nsTextPaintStyle;
|
|
|
|
class PropertyProvider;
|
|
|
|
|
2008-02-14 01:08:33 -08:00
|
|
|
// This state bit is set on frames that have some non-collapsed characters after
|
|
|
|
// reflow
|
2010-06-08 22:28:14 -07:00
|
|
|
#define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31)
|
2008-02-14 01:08:33 -08:00
|
|
|
|
2011-11-23 18:48:23 -08:00
|
|
|
#define TEXT_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(61)
|
|
|
|
|
2012-08-04 18:01:19 -07:00
|
|
|
typedef nsFrame nsTextFrameBase;
|
|
|
|
|
|
|
|
class nsTextFrame : public nsTextFrameBase {
|
2007-09-23 19:19:14 -07:00
|
|
|
public:
|
2012-08-04 18:01:19 -07:00
|
|
|
NS_DECL_QUERYFRAME_TARGET(nsTextFrame)
|
2009-09-12 09:49:24 -07:00
|
|
|
NS_DECL_FRAMEARENA_HELPERS
|
|
|
|
|
2008-01-04 09:09:35 -08:00
|
|
|
friend class nsContinuingTextFrame;
|
|
|
|
|
2011-11-23 18:48:23 -08:00
|
|
|
nsTextFrame(nsStyleContext* aContext)
|
2012-08-04 18:01:19 -07:00
|
|
|
: nsTextFrameBase(aContext)
|
2007-09-23 19:19:14 -07:00
|
|
|
{
|
|
|
|
NS_ASSERTION(mContentOffset == 0, "Bogus content offset");
|
|
|
|
}
|
|
|
|
|
2012-08-04 18:01:19 -07:00
|
|
|
// nsQueryFrame
|
|
|
|
NS_DECL_QUERYFRAME
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
// nsIFrame
|
|
|
|
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
const nsDisplayListSet& aLists);
|
|
|
|
|
|
|
|
NS_IMETHOD Init(nsIContent* aContent,
|
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIFrame* aPrevInFlow);
|
|
|
|
|
2009-12-23 21:21:15 -08:00
|
|
|
virtual void DestroyFrom(nsIFrame* aDestructRoot);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
NS_IMETHOD GetCursor(const nsPoint& aPoint,
|
|
|
|
nsIFrame::Cursor& aCursor);
|
|
|
|
|
2009-08-04 18:38:10 -07:00
|
|
|
NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2008-10-26 03:11:34 -07:00
|
|
|
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
virtual nsIFrame* GetNextContinuation() const {
|
|
|
|
return mNextContinuation;
|
|
|
|
}
|
|
|
|
NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) {
|
|
|
|
NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(),
|
|
|
|
"setting a next continuation with incorrect type!");
|
|
|
|
NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this),
|
|
|
|
"creating a loop in continuation chain!");
|
|
|
|
mNextContinuation = aNextContinuation;
|
|
|
|
if (aNextContinuation)
|
|
|
|
aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); }
|
|
|
|
nsIFrame* GetNextInFlow() const {
|
|
|
|
return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ?
|
2012-07-30 07:20:58 -07:00
|
|
|
mNextContinuation : nullptr;
|
2007-09-23 19:19:14 -07:00
|
|
|
}
|
|
|
|
NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) {
|
|
|
|
NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(),
|
|
|
|
"setting a next in flow with incorrect type!");
|
|
|
|
NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this),
|
|
|
|
"creating a loop in continuation chain!");
|
|
|
|
mNextContinuation = aNextInFlow;
|
|
|
|
if (aNextInFlow)
|
|
|
|
aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
virtual nsIFrame* GetLastInFlow() const;
|
|
|
|
virtual nsIFrame* GetLastContinuation() const;
|
|
|
|
|
|
|
|
virtual nsSplittableType GetSplittableType() const {
|
|
|
|
return NS_FRAME_SPLITTABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the "type" of the frame
|
|
|
|
*
|
|
|
|
* @see nsGkAtoms::textFrame
|
|
|
|
*/
|
|
|
|
virtual nsIAtom* GetType() const;
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool IsFrameOfType(PRUint32 aFlags) const
|
2007-09-23 19:19:14 -07:00
|
|
|
{
|
|
|
|
// Set the frame state bit for text frames to mark them as replaced.
|
|
|
|
// XXX kipp: temporary
|
|
|
|
return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced |
|
|
|
|
nsIFrame::eLineParticipant));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
|
|
|
|
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
|
|
|
NS_IMETHOD_(nsFrameState) GetDebugStateBits() const ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint);
|
2009-05-14 17:46:24 -07:00
|
|
|
ContentOffsets GetCharacterOffsetAtFramePoint(const nsPoint &aPoint);
|
|
|
|
|
2009-07-26 15:05:41 -07:00
|
|
|
/**
|
|
|
|
* This is called only on the primary text frame. It indicates that
|
|
|
|
* the selection state of the given character range has changed.
|
|
|
|
* Text in the range is unconditionally invalidated
|
2012-06-10 16:44:50 -07:00
|
|
|
* (Selection::Repaint depends on this).
|
2009-07-26 15:05:41 -07:00
|
|
|
* @param aSelected true if the selection has been added to the range,
|
|
|
|
* false otherwise
|
|
|
|
* @param aType the type of selection added or removed
|
|
|
|
*/
|
2011-12-20 01:15:41 -08:00
|
|
|
void SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
|
2009-07-26 15:05:41 -07:00
|
|
|
SelectionType aType);
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
|
|
|
|
virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
|
|
|
|
bool aRespectClusters = true);
|
|
|
|
virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
|
2007-09-23 19:19:14 -07:00
|
|
|
PRInt32* aOffset, PeekWordState* aState);
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, bool aRecurse, bool *aFinished, bool *_retval);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2011-02-21 00:02:23 -08:00
|
|
|
// Flags for aSetLengthFlags
|
|
|
|
enum { ALLOW_FRAME_CREATION_AND_DESTRUCTION = 0x01 };
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
// Update offsets to account for new length. This may clear mTextRun.
|
2011-02-21 00:02:23 -08:00
|
|
|
void SetLength(PRInt32 aLength, nsLineLayout* aLineLayout,
|
|
|
|
PRUint32 aSetLengthFlags = 0);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;
|
|
|
|
|
|
|
|
virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end);
|
|
|
|
|
|
|
|
NS_IMETHOD GetPointFromOffset(PRInt32 inOffset,
|
|
|
|
nsPoint* outPoint);
|
|
|
|
|
|
|
|
NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool inHint,
|
2007-09-23 19:19:14 -07:00
|
|
|
PRInt32* outFrameContentOffset,
|
|
|
|
nsIFrame* *outChildFrame);
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool IsVisibleInSelection(nsISelection* aSelection);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool IsEmpty();
|
|
|
|
virtual bool IsSelfEmpty() { return IsEmpty(); }
|
2010-08-31 11:54:44 -07:00
|
|
|
virtual nscoord GetBaseline() const;
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
/**
|
2011-10-17 07:59:28 -07:00
|
|
|
* @return true if this text frame ends with a newline character. It
|
|
|
|
* should return false if this is not a text frame.
|
2007-09-23 19:19:14 -07:00
|
|
|
*/
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool HasTerminalNewline() const;
|
2007-11-07 20:07:00 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if this text frame is logically adjacent to the end of the
|
|
|
|
* line.
|
|
|
|
*/
|
2011-09-28 23:19:26 -07:00
|
|
|
bool IsAtEndOfLine() const;
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2008-02-14 01:08:33 -08:00
|
|
|
/**
|
|
|
|
* Call this only after reflow the frame. Returns true if non-collapsed
|
|
|
|
* characters are present.
|
|
|
|
*/
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasNoncollapsedCharacters() const {
|
2008-02-14 01:08:33 -08:00
|
|
|
return (GetStateBits() & TEXT_HAS_NONCOLLAPSED_CHARACTERS) != 0;
|
|
|
|
}
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
#ifdef ACCESSIBILITY
|
2012-05-28 18:18:45 -07:00
|
|
|
virtual already_AddRefed<Accessible> CreateAccessible();
|
2007-09-23 19:19:14 -07:00
|
|
|
#endif
|
2011-11-23 18:48:23 -08:00
|
|
|
|
|
|
|
float GetFontSizeInflation() const;
|
2012-07-25 14:25:26 -07:00
|
|
|
bool IsCurrentFontInflation(float aInflation) const;
|
2011-11-23 18:48:23 -08:00
|
|
|
bool HasFontSizeInflation() const {
|
|
|
|
return (GetStateBits() & TEXT_HAS_FONT_INFLATION) != 0;
|
|
|
|
}
|
|
|
|
void SetFontSizeInflation(float aInflation);
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
virtual void MarkIntrinsicWidthsDirty();
|
2011-04-07 18:04:40 -07:00
|
|
|
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
|
|
|
|
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
|
|
|
|
virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
|
2007-09-23 19:19:14 -07:00
|
|
|
InlineMinWidthData *aData);
|
2011-04-07 18:04:40 -07:00
|
|
|
virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
|
2007-09-23 19:19:14 -07:00
|
|
|
InlinePrefWidthData *aData);
|
2011-04-07 18:04:40 -07:00
|
|
|
virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
|
2007-09-23 19:19:14 -07:00
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
2012-03-16 11:01:05 -07:00
|
|
|
PRUint32 aFlags) MOZ_OVERRIDE;
|
2007-10-12 01:30:54 -07:00
|
|
|
virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
|
2007-09-23 19:19:14 -07:00
|
|
|
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus);
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool CanContinueTextRun() const;
|
2007-12-01 01:24:24 -08:00
|
|
|
// Method that is called for a text frame that is logically
|
|
|
|
// adjacent to the end of the line (i.e. followed only by empty text frames,
|
|
|
|
// placeholders or inlines containing such).
|
|
|
|
struct TrimOutput {
|
|
|
|
// true if we trimmed some space or changed metrics in some other way.
|
2010-10-06 21:25:45 -07:00
|
|
|
// In this case, we should call RecomputeOverflow on this frame.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mChanged;
|
2007-12-01 01:24:24 -08:00
|
|
|
// true if the last character is not justifiable so should be subtracted
|
|
|
|
// from the count of justifiable characters in the frame, since the last
|
|
|
|
// character in a line is not justifiable.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mLastCharIsJustifiable;
|
2007-12-01 01:24:24 -08:00
|
|
|
// an amount to *subtract* from the frame's width (zero if !mChanged)
|
|
|
|
nscoord mDeltaWidth;
|
|
|
|
};
|
2011-04-07 18:04:40 -07:00
|
|
|
TrimOutput TrimTrailingWhiteSpace(nsRenderingContext* aRC);
|
2012-07-30 07:20:58 -07:00
|
|
|
virtual nsresult GetRenderedText(nsAString* aString = nullptr,
|
|
|
|
gfxSkipChars* aSkipChars = nullptr,
|
|
|
|
gfxSkipCharsIterator* aSkipIter = nullptr,
|
2007-09-23 19:19:14 -07:00
|
|
|
PRUint32 aSkippedStartOffset = 0,
|
|
|
|
PRUint32 aSkippedMaxLength = PR_UINT32_MAX);
|
|
|
|
|
2011-11-23 18:48:23 -08:00
|
|
|
nsOverflowAreas
|
|
|
|
RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2012-01-24 17:21:29 -08:00
|
|
|
enum TextRunType {
|
|
|
|
// Anything in reflow (but not intrinsic width calculation) or
|
|
|
|
// painting should use the inflated text run (i.e., with font size
|
|
|
|
// inflation applied).
|
|
|
|
eInflated,
|
|
|
|
// Intrinsic width calculation should use the non-inflated text run.
|
|
|
|
// When there is font size inflation, it will be different.
|
|
|
|
eNotInflated
|
|
|
|
};
|
|
|
|
|
2011-04-07 18:04:40 -07:00
|
|
|
void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext,
|
2012-01-24 17:21:29 -08:00
|
|
|
nsIFrame::InlineMinWidthData *aData,
|
2012-03-26 22:37:16 -07:00
|
|
|
TextRunType aTextRunType);
|
2011-04-07 18:04:40 -07:00
|
|
|
void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext,
|
2012-01-24 17:21:29 -08:00
|
|
|
InlinePrefWidthData *aData,
|
2012-03-26 22:37:16 -07:00
|
|
|
TextRunType aTextRunType);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2011-06-22 11:11:48 -07:00
|
|
|
/**
|
|
|
|
* Calculate the horizontal bounds of the grapheme clusters that fit entirely
|
|
|
|
* inside the given left/right edges (which are positive lengths from the
|
|
|
|
* respective frame edge). If an input value is zero it is ignored and the
|
|
|
|
* result for that edge is zero. All out parameter values are undefined when
|
|
|
|
* the method returns false.
|
|
|
|
* @return true if at least one whole grapheme cluster fit between the edges
|
|
|
|
*/
|
2011-11-23 18:48:23 -08:00
|
|
|
bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge,
|
2011-06-22 11:11:48 -07:00
|
|
|
nscoord* aSnappedLeftEdge,
|
|
|
|
nscoord* aSnappedRightEdge);
|
|
|
|
/**
|
|
|
|
* Same as above; this method also the returns the corresponding text run
|
|
|
|
* offset and number of characters that fit. All out parameter values are
|
|
|
|
* undefined when the method returns false.
|
|
|
|
* @return true if at least one whole grapheme cluster fit between the edges
|
|
|
|
*/
|
2011-11-23 18:48:23 -08:00
|
|
|
bool MeasureCharClippedText(PropertyProvider& aProvider,
|
2011-06-22 11:11:48 -07:00
|
|
|
nscoord aLeftEdge, nscoord aRightEdge,
|
|
|
|
PRUint32* aStartOffset, PRUint32* aMaxLength,
|
|
|
|
nscoord* aSnappedLeftEdge,
|
|
|
|
nscoord* aSnappedRightEdge);
|
2012-08-08 04:37:12 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Object with various callbacks for PaintText() to invoke for different parts
|
|
|
|
* of the frame's text rendering, when we're generating paths rather than
|
|
|
|
* painting.
|
|
|
|
*
|
|
|
|
* Callbacks are invoked in the following order:
|
|
|
|
*
|
|
|
|
* (NotifyBeforeSelectionBackground NotifySelectionBackgroundPathEmitted)?
|
|
|
|
* (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)*
|
|
|
|
* NotifyBeforeText
|
|
|
|
* NotifyGlyphPathEmitted*
|
|
|
|
* NotifyAfterText
|
|
|
|
* (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)*
|
|
|
|
* (NotifyBeforeSelectionDecorationLine NotifySelectionDecorationLinePathEmitted)*
|
|
|
|
*
|
|
|
|
* The color of each part of the frame's text rendering is passed as an argument
|
|
|
|
* to the NotifyBefore* callback for that part. The nscolor can take on one of
|
|
|
|
* the three selection special colors defined in LookAndFeel.h --
|
|
|
|
* NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR and
|
|
|
|
* NS_40PERCENT_FOREGROUND_COLOR.
|
|
|
|
*/
|
|
|
|
struct DrawPathCallbacks : gfxTextRun::DrawCallbacks
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Called just before any paths have been emitted to the gfxContext
|
|
|
|
* for the glyphs of the frame's text.
|
|
|
|
*/
|
|
|
|
virtual void NotifyBeforeText(nscolor aColor) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just after all the paths have been emitted to the gfxContext
|
|
|
|
* for the glyphs of the frame's text.
|
|
|
|
*/
|
|
|
|
virtual void NotifyAfterText() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just before a path corresponding to the selection background
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifyBeforeSelectionBackground(nscolor aColor) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just after a path corresponding to the selection background
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifySelectionBackgroundPathEmitted() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just before a path corresponding to a text decoration line
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifyBeforeDecorationLine(nscolor aColor) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just after a path corresponding to a text decoration line
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifyDecorationLinePathEmitted() { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just before a path corresponding to a selection decoration line
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifyBeforeSelectionDecorationLine(nscolor aColor) { }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just after a path corresponding to a selection decoration line
|
|
|
|
* has been emitted to the gfxContext.
|
|
|
|
*/
|
|
|
|
virtual void NotifySelectionDecorationLinePathEmitted() { }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Primary frame paint method called from nsDisplayText. Can also be used
|
|
|
|
// to generate paths rather than paint the frame's text by passing a callback
|
|
|
|
// object. The private DrawText() is what applies the text to a graphics
|
|
|
|
// context.
|
2011-04-07 18:04:40 -07:00
|
|
|
void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
2012-08-08 04:37:12 -07:00
|
|
|
const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem,
|
|
|
|
DrawPathCallbacks* aCallbacks = nullptr);
|
2007-09-23 19:19:14 -07:00
|
|
|
// helper: paint text frame when we're impacted by at least one selection.
|
2011-06-29 17:56:50 -07:00
|
|
|
// Return false if the text was not painted and we should continue with
|
2007-09-23 19:19:14 -07:00
|
|
|
// the fast path.
|
2011-06-29 17:56:50 -07:00
|
|
|
bool PaintTextWithSelection(gfxContext* aCtx,
|
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
const gfxRect& aDirtyRect,
|
|
|
|
PropertyProvider& aProvider,
|
|
|
|
PRUint32 aContentOffset,
|
|
|
|
PRUint32 aContentLength,
|
|
|
|
nsTextPaintStyle& aTextPaintStyle,
|
2012-08-08 04:37:12 -07:00
|
|
|
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
|
|
|
DrawPathCallbacks* aCallbacks);
|
2007-09-23 19:19:14 -07:00
|
|
|
// helper: paint text with foreground and background colors determined
|
|
|
|
// by selection(s). Also computes a mask of all selection types applying to
|
|
|
|
// our text, returned in aAllTypes.
|
2011-06-29 17:56:50 -07:00
|
|
|
// Return false if the text was not painted and we should continue with
|
|
|
|
// the fast path.
|
|
|
|
bool PaintTextWithSelectionColors(gfxContext* aCtx,
|
2007-09-23 19:19:14 -07:00
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
const gfxRect& aDirtyRect,
|
|
|
|
PropertyProvider& aProvider,
|
2011-06-29 17:56:49 -07:00
|
|
|
PRUint32 aContentOffset,
|
|
|
|
PRUint32 aContentLength,
|
2007-09-23 19:19:14 -07:00
|
|
|
nsTextPaintStyle& aTextPaintStyle,
|
|
|
|
SelectionDetails* aDetails,
|
2011-08-03 11:30:58 -07:00
|
|
|
SelectionType* aAllTypes,
|
2012-08-08 04:37:12 -07:00
|
|
|
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
|
|
|
DrawPathCallbacks* aCallbacks);
|
2007-09-23 19:19:14 -07:00
|
|
|
// helper: paint text decorations for text selected by aSelectionType
|
|
|
|
void PaintTextSelectionDecorations(gfxContext* aCtx,
|
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
const gfxRect& aDirtyRect,
|
|
|
|
PropertyProvider& aProvider,
|
2011-06-29 17:56:49 -07:00
|
|
|
PRUint32 aContentOffset,
|
|
|
|
PRUint32 aContentLength,
|
2007-09-23 19:19:14 -07:00
|
|
|
nsTextPaintStyle& aTextPaintStyle,
|
|
|
|
SelectionDetails* aDetails,
|
2012-08-08 04:37:12 -07:00
|
|
|
SelectionType aSelectionType,
|
|
|
|
DrawPathCallbacks* aCallbacks);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2010-03-31 19:35:48 -07:00
|
|
|
virtual nscolor GetCaretColorAt(PRInt32 aOffset);
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2007-11-21 03:00:16 -08:00
|
|
|
void ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const;
|
2007-09-23 19:19:14 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
PRInt32 GetContentOffset() const { return mContentOffset; }
|
2008-01-04 09:09:35 -08:00
|
|
|
PRInt32 GetContentLength() const
|
|
|
|
{
|
|
|
|
NS_ASSERTION(GetContentEnd() - mContentOffset >= 0, "negative length");
|
|
|
|
return GetContentEnd() - mContentOffset;
|
|
|
|
}
|
2007-09-23 19:19:14 -07:00
|
|
|
PRInt32 GetContentEnd() const;
|
|
|
|
// This returns the length the frame thinks it *should* have after it was
|
|
|
|
// last reflowed (0 if it hasn't been reflowed yet). This should be used only
|
|
|
|
// when setting up the text offsets for a new continuation frame.
|
|
|
|
PRInt32 GetContentLengthHint() const { return mContentLengthHint; }
|
|
|
|
|
|
|
|
// Compute the length of the content mapped by this frame
|
|
|
|
// and all its in-flow siblings. Basically this means starting at mContentOffset
|
|
|
|
// and going to the end of the text node or the next bidi continuation
|
|
|
|
// boundary.
|
|
|
|
PRInt32 GetInFlowContentLength();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Acquires the text run for this content, if necessary.
|
2012-02-06 15:37:08 -08:00
|
|
|
* @param aWhichTextRun indicates whether to get an inflated or non-inflated
|
|
|
|
* text run
|
|
|
|
* @param aReferenceContext the rendering context to use as a reference for
|
|
|
|
* creating the textrun, if available (if not, we'll create one which will
|
|
|
|
* just be slower)
|
2012-07-30 07:20:58 -07:00
|
|
|
* @param aLineContainer the block ancestor for this frame, or nullptr if
|
2012-02-06 15:37:08 -08:00
|
|
|
* unknown
|
2007-09-23 19:19:14 -07:00
|
|
|
* @param aFlowEndInTextRun if non-null, this returns the textrun offset of
|
|
|
|
* end of the text associated with this frame and its in-flow siblings
|
|
|
|
* @return a gfxSkipCharsIterator set up to map DOM offsets for this frame
|
|
|
|
* to offsets into the textrun; its initial offset is set to this frame's
|
|
|
|
* content offset
|
|
|
|
*/
|
2011-11-23 18:48:23 -08:00
|
|
|
gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun,
|
2012-07-30 07:20:58 -07:00
|
|
|
gfxContext* aReferenceContext = nullptr,
|
|
|
|
nsIFrame* aLineContainer = nullptr,
|
|
|
|
const nsLineList::iterator* aLine = nullptr,
|
|
|
|
PRUint32* aFlowEndInTextRun = nullptr);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2011-11-23 18:48:23 -08:00
|
|
|
gfxTextRun* GetTextRun(TextRunType aWhichTextRun) {
|
|
|
|
if (aWhichTextRun == eInflated || !HasFontSizeInflation())
|
|
|
|
return mTextRun;
|
|
|
|
return GetUninflatedTextRun();
|
|
|
|
}
|
|
|
|
gfxTextRun* GetUninflatedTextRun();
|
|
|
|
void SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun,
|
|
|
|
float aInflation);
|
2010-10-14 21:03:33 -07:00
|
|
|
/**
|
2011-11-23 18:48:23 -08:00
|
|
|
* Notify the frame that it should drop its pointer to a text run.
|
|
|
|
* Returns whether the text run was removed (i.e., whether it was
|
|
|
|
* associated with this frame, either as its inflated or non-inflated
|
|
|
|
* text run.
|
2010-10-14 21:03:33 -07:00
|
|
|
*/
|
2011-11-23 18:48:23 -08:00
|
|
|
bool RemoveTextRun(gfxTextRun* aTextRun);
|
|
|
|
/**
|
|
|
|
* Clears out |mTextRun| (or the uninflated text run, when aInflated
|
|
|
|
* is nsTextFrame::eNotInflated and there is inflation) from all frames that hold a
|
|
|
|
* reference to it, starting at |aStartContinuation|, or if it's
|
2012-07-30 07:20:58 -07:00
|
|
|
* nullptr, starting at |this|. Deletes the text run if all references
|
2011-11-23 18:48:23 -08:00
|
|
|
* were cleared and it's not cached.
|
|
|
|
*/
|
|
|
|
void ClearTextRun(nsTextFrame* aStartContinuation,
|
|
|
|
TextRunType aWhichTextRun);
|
|
|
|
|
|
|
|
void ClearTextRuns() {
|
2012-07-30 07:20:58 -07:00
|
|
|
ClearTextRun(nullptr, nsTextFrame::eInflated);
|
2012-05-23 08:27:15 -07:00
|
|
|
if (HasFontSizeInflation()) {
|
2012-07-30 07:20:58 -07:00
|
|
|
ClearTextRun(nullptr, nsTextFrame::eNotInflated);
|
2012-05-23 08:27:15 -07:00
|
|
|
}
|
2011-11-23 18:48:23 -08:00
|
|
|
}
|
2007-09-23 19:19:14 -07:00
|
|
|
|
|
|
|
// Get the DOM content range mapped by this frame after excluding
|
|
|
|
// whitespace subject to start-of-line and end-of-line trimming.
|
|
|
|
// The textrun must have been created before calling this.
|
|
|
|
struct TrimmedOffsets {
|
|
|
|
PRInt32 mStart;
|
|
|
|
PRInt32 mLength;
|
2012-07-08 18:09:51 -07:00
|
|
|
PRInt32 GetEnd() const { return mStart + mLength; }
|
2007-09-23 19:19:14 -07:00
|
|
|
};
|
|
|
|
TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aTrimAfter);
|
2007-09-23 19:19:14 -07:00
|
|
|
|
2010-08-25 11:54:46 -07:00
|
|
|
// Similar to Reflow(), but for use from nsLineLayout
|
|
|
|
void ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
2011-09-28 23:19:26 -07:00
|
|
|
nsRenderingContext* aRenderingContext, bool aShouldBlink,
|
2010-08-25 11:54:46 -07:00
|
|
|
nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus);
|
|
|
|
|
2012-02-21 15:50:16 -08:00
|
|
|
bool IsFloatingFirstLetterChild() const;
|
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
protected:
|
|
|
|
virtual ~nsTextFrame();
|
2009-03-08 12:01:02 -07:00
|
|
|
|
2007-09-23 19:19:14 -07:00
|
|
|
nsIFrame* mNextContinuation;
|
|
|
|
// The key invariant here is that mContentOffset never decreases along
|
|
|
|
// a next-continuation chain. And of course mContentOffset is always <= the
|
|
|
|
// the text node's content length, and the mContentOffset for the first frame
|
|
|
|
// is always 0. Furthermore the text mapped by a frame is determined by
|
|
|
|
// GetContentOffset() and GetContentLength()/GetContentEnd(), which get
|
|
|
|
// the length from the difference between this frame's offset and the next
|
|
|
|
// frame's offset, or the text length if there is no next frame. This means
|
|
|
|
// the frames always map the text node without overlapping or leaving any gaps.
|
|
|
|
PRInt32 mContentOffset;
|
|
|
|
// This does *not* indicate the length of text currently mapped by the frame;
|
|
|
|
// instead it's a hint saying that this frame *wants* to map this much text
|
|
|
|
// so if we create a new continuation, this is where that continuation should
|
|
|
|
// start.
|
|
|
|
PRInt32 mContentLengthHint;
|
|
|
|
nscoord mAscent;
|
|
|
|
gfxTextRun* mTextRun;
|
|
|
|
|
2011-12-20 01:15:41 -08:00
|
|
|
/**
|
|
|
|
* Return true if the frame is part of a Selection.
|
|
|
|
* Helper method to implement the public IsSelected() API.
|
|
|
|
*/
|
|
|
|
virtual bool IsFrameSelected() const;
|
|
|
|
|
2008-08-13 21:18:02 -07:00
|
|
|
// The caller of this method must call DestroySelectionDetails() on the
|
|
|
|
// return value, if that return value is not null. Calling
|
|
|
|
// DestroySelectionDetails() on a null value is still OK, just not necessary.
|
2007-09-23 19:19:14 -07:00
|
|
|
SelectionDetails* GetSelectionDetails();
|
2011-08-03 11:30:58 -07:00
|
|
|
|
|
|
|
void UnionAdditionalOverflow(nsPresContext* aPresContext,
|
2011-11-23 18:48:23 -08:00
|
|
|
const nsHTMLReflowState& aBlockReflowState,
|
2011-08-03 11:30:58 -07:00
|
|
|
PropertyProvider& aProvider,
|
|
|
|
nsRect* aVisualOverflowRect,
|
|
|
|
bool aIncludeTextDecorations);
|
2008-02-16 07:31:27 -08:00
|
|
|
|
2008-06-12 15:02:32 -07:00
|
|
|
void PaintOneShadow(PRUint32 aOffset,
|
|
|
|
PRUint32 aLength,
|
2008-07-07 17:56:52 -07:00
|
|
|
nsCSSShadowItem* aShadowDetails,
|
2008-06-12 15:02:32 -07:00
|
|
|
PropertyProvider* aProvider,
|
2009-09-18 11:18:35 -07:00
|
|
|
const nsRect& aDirtyRect,
|
2008-06-12 15:02:32 -07:00
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
gfxContext* aCtx,
|
2011-06-22 11:11:48 -07:00
|
|
|
const nscolor& aForegroundColor,
|
|
|
|
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
2012-05-17 03:34:06 -07:00
|
|
|
nscoord aLeftSideOffset,
|
|
|
|
gfxRect& aBoundingBox);
|
2008-06-12 15:02:32 -07:00
|
|
|
|
2011-08-03 11:30:58 -07:00
|
|
|
struct LineDecoration {
|
|
|
|
nsIFrame* mFrame;
|
|
|
|
|
|
|
|
// This is represents the offset from our baseline to mFrame's baseline;
|
|
|
|
// positive offsets are *above* the baseline and negative offsets below
|
|
|
|
nscoord mBaselineOffset;
|
|
|
|
|
|
|
|
nscolor mColor;
|
|
|
|
PRUint8 mStyle;
|
|
|
|
|
|
|
|
LineDecoration(nsIFrame *const aFrame,
|
|
|
|
const nscoord aOff,
|
|
|
|
const nscolor aColor,
|
|
|
|
const PRUint8 aStyle)
|
|
|
|
: mFrame(aFrame),
|
|
|
|
mBaselineOffset(aOff),
|
|
|
|
mColor(aColor),
|
|
|
|
mStyle(aStyle)
|
|
|
|
{}
|
|
|
|
|
|
|
|
LineDecoration(const LineDecoration& aOther)
|
|
|
|
: mFrame(aOther.mFrame),
|
|
|
|
mBaselineOffset(aOther.mBaselineOffset),
|
|
|
|
mColor(aOther.mColor),
|
|
|
|
mStyle(aOther.mStyle)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool operator==(const LineDecoration& aOther) const {
|
|
|
|
return mFrame == aOther.mFrame &&
|
|
|
|
mStyle == aOther.mStyle &&
|
|
|
|
mColor == aOther.mColor &&
|
|
|
|
mBaselineOffset == aOther.mBaselineOffset;
|
|
|
|
}
|
|
|
|
};
|
2008-02-16 07:31:27 -08:00
|
|
|
struct TextDecorations {
|
2011-08-03 11:30:58 -07:00
|
|
|
nsAutoTArray<LineDecoration, 1> mOverlines, mUnderlines, mStrikes;
|
|
|
|
|
|
|
|
TextDecorations() { }
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasDecorationLines() const {
|
2011-04-22 22:13:09 -07:00
|
|
|
return HasUnderline() || HasOverline() || HasStrikeout();
|
2008-02-16 07:31:27 -08:00
|
|
|
}
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasUnderline() const {
|
2011-08-03 11:30:58 -07:00
|
|
|
return !mUnderlines.IsEmpty();
|
2008-02-16 07:31:27 -08:00
|
|
|
}
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasOverline() const {
|
2011-08-03 11:30:58 -07:00
|
|
|
return !mOverlines.IsEmpty();
|
2008-02-16 07:31:27 -08:00
|
|
|
}
|
2011-09-28 23:19:26 -07:00
|
|
|
bool HasStrikeout() const {
|
2011-08-03 11:30:58 -07:00
|
|
|
return !mStrikes.IsEmpty();
|
2008-02-16 07:31:27 -08:00
|
|
|
}
|
|
|
|
};
|
2011-08-03 11:30:58 -07:00
|
|
|
void GetTextDecorations(nsPresContext* aPresContext,
|
|
|
|
TextDecorations& aDecorations);
|
2008-03-29 14:25:15 -07:00
|
|
|
|
2011-08-03 11:30:58 -07:00
|
|
|
void DrawTextRun(gfxContext* const aCtx,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
PRUint32 aOffset,
|
|
|
|
PRUint32 aLength,
|
|
|
|
PropertyProvider& aProvider,
|
2012-08-08 04:37:12 -07:00
|
|
|
nscolor aTextColor,
|
2011-08-03 11:30:58 -07:00
|
|
|
gfxFloat& aAdvanceWidth,
|
2012-08-08 04:37:12 -07:00
|
|
|
bool aDrawSoftHyphen,
|
|
|
|
DrawPathCallbacks* aCallbacks);
|
2011-08-03 11:30:58 -07:00
|
|
|
|
|
|
|
void DrawTextRunAndDecorations(gfxContext* const aCtx,
|
2011-09-16 12:23:29 -07:00
|
|
|
const gfxRect& aDirtyRect,
|
2011-08-03 11:30:58 -07:00
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
PRUint32 aOffset,
|
|
|
|
PRUint32 aLength,
|
|
|
|
PropertyProvider& aProvider,
|
|
|
|
const nsTextPaintStyle& aTextStyle,
|
2012-08-08 04:37:12 -07:00
|
|
|
nscolor aTextColor,
|
2011-08-03 11:30:58 -07:00
|
|
|
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
|
|
|
gfxFloat& aAdvanceWidth,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aDrawSoftHyphen,
|
2011-08-03 11:30:58 -07:00
|
|
|
const TextDecorations& aDecorations,
|
2012-08-08 04:37:12 -07:00
|
|
|
const nscolor* const aDecorationOverrideColor,
|
|
|
|
DrawPathCallbacks* aCallbacks);
|
2011-08-03 11:30:58 -07:00
|
|
|
|
|
|
|
void DrawText(gfxContext* const aCtx,
|
2011-09-16 12:23:29 -07:00
|
|
|
const gfxRect& aDirtyRect,
|
2011-08-03 11:30:58 -07:00
|
|
|
const gfxPoint& aFramePt,
|
|
|
|
const gfxPoint& aTextBaselinePt,
|
|
|
|
PRUint32 aOffset,
|
|
|
|
PRUint32 aLength,
|
|
|
|
PropertyProvider& aProvider,
|
|
|
|
const nsTextPaintStyle& aTextStyle,
|
2012-08-08 04:37:12 -07:00
|
|
|
nscolor aTextColor,
|
2011-08-03 11:30:58 -07:00
|
|
|
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
|
|
|
gfxFloat& aAdvanceWidth,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aDrawSoftHyphen,
|
2012-08-08 04:37:12 -07:00
|
|
|
const nscolor* const aDecorationOverrideColor = nullptr,
|
|
|
|
DrawPathCallbacks* aCallbacks = nullptr);
|
2011-08-03 11:30:58 -07:00
|
|
|
|
2009-04-03 00:26:28 -07:00
|
|
|
// Set non empty rect to aRect, it should be overflow rect or frame rect.
|
2011-10-17 07:59:28 -07:00
|
|
|
// If the result rect is larger than the given rect, this returns true.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
2009-04-03 00:26:28 -07:00
|
|
|
nsRect& aRect);
|
2008-04-11 01:44:58 -07:00
|
|
|
|
2009-05-14 17:46:24 -07:00
|
|
|
ContentOffsets GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aForInsertionPoint);
|
2010-08-10 08:16:17 -07:00
|
|
|
|
|
|
|
void ClearFrameOffsetCache();
|
2010-08-13 15:58:26 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
virtual bool HasAnyNoncollapsedCharacters();
|
2011-02-14 22:11:18 -08:00
|
|
|
|
|
|
|
void ClearMetrics(nsHTMLReflowMetrics& aMetrics);
|
2007-09-23 19:19:14 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|