michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* rendering object for CSS display:inline objects */ michael@0: michael@0: #ifndef nsInlineFrame_h___ michael@0: #define nsInlineFrame_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsContainerFrame.h" michael@0: michael@0: class nsLineLayout; michael@0: michael@0: typedef nsContainerFrame nsInlineFrameBase; michael@0: michael@0: /** michael@0: * Inline frame class. michael@0: * michael@0: * This class manages a list of child frames that are inline frames. Working with michael@0: * nsLineLayout, the class will reflow and place inline frames on a line. michael@0: */ michael@0: class nsInlineFrame : public nsInlineFrameBase michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsInlineFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: friend nsIFrame* NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: // nsIFrame overrides michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: if (aFlags & eSupportsCSSTransforms) { michael@0: return false; michael@0: } michael@0: return nsContainerFrame::IsFrameOfType(aFlags & michael@0: ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant)); michael@0: } michael@0: michael@0: virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; michael@0: virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsEmpty() MOZ_OVERRIDE; michael@0: virtual bool IsSelfEmpty() MOZ_OVERRIDE; michael@0: michael@0: virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, michael@0: bool aRespectClusters = true) MOZ_OVERRIDE; michael@0: michael@0: // nsIHTMLReflow overrides michael@0: virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, michael@0: InlineMinWidthData *aData) MOZ_OVERRIDE; michael@0: virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, michael@0: InlinePrefWidthData *aData) MOZ_OVERRIDE; michael@0: virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, michael@0: nsSize aCBSize, nscoord aAvailableWidth, michael@0: nsSize aMargin, nsSize aBorder, nsSize aPadding, michael@0: uint32_t aFlags) MOZ_OVERRIDE; michael@0: virtual nsRect ComputeTightBounds(gfxContext* aContext) const MOZ_OVERRIDE; michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual bool CanContinueTextRun() const MOZ_OVERRIDE; michael@0: michael@0: virtual void PullOverflowsFromPrevInFlow() MOZ_OVERRIDE; michael@0: virtual nscoord GetBaseline() const MOZ_OVERRIDE; michael@0: virtual bool DrainSelfOverflowList() MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Return true if the frame is first visual frame or first continuation michael@0: */ michael@0: bool IsFirst() const { michael@0: // If the frame's bidi visual state is set, return is-first state michael@0: // else return true if it's the first continuation. michael@0: return (GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) michael@0: ? !!(GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST) michael@0: : (!GetPrevInFlow()); michael@0: } michael@0: michael@0: /** michael@0: * Return true if the frame is last visual frame or last continuation. michael@0: */ michael@0: bool IsLast() const { michael@0: // If the frame's bidi visual state is set, return is-last state michael@0: // else return true if it's the last continuation. michael@0: return (GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) michael@0: ? !!(GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST) michael@0: : (!GetNextInFlow()); michael@0: } michael@0: michael@0: protected: michael@0: // Additional reflow state used during our reflow methods michael@0: struct InlineReflowState { michael@0: nsIFrame* mPrevFrame; michael@0: nsInlineFrame* mNextInFlow; michael@0: nsIFrame* mLineContainer; michael@0: nsLineLayout* mLineLayout; michael@0: bool mSetParentPointer; // when reflowing child frame first set its michael@0: // parent frame pointer michael@0: michael@0: InlineReflowState() { michael@0: mPrevFrame = nullptr; michael@0: mNextInFlow = nullptr; michael@0: mLineContainer = nullptr; michael@0: mLineLayout = nullptr; michael@0: mSetParentPointer = false; michael@0: } michael@0: }; michael@0: michael@0: nsInlineFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} michael@0: michael@0: virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; michael@0: michael@0: nsresult ReflowFrames(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: InlineReflowState& rs, michael@0: nsHTMLReflowMetrics& aMetrics, michael@0: nsReflowStatus& aStatus); michael@0: michael@0: nsresult ReflowInlineFrame(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: InlineReflowState& rs, michael@0: nsIFrame* aFrame, michael@0: nsReflowStatus& aStatus); michael@0: michael@0: /** michael@0: * Reparent floats whose placeholders are inline descendants of aFrame from michael@0: * whatever block they're currently parented by to aOurBlock. michael@0: * @param aReparentSiblings if this is true, we follow aFrame's michael@0: * GetNextSibling chain reparenting them all michael@0: */ michael@0: void ReparentFloatsForInlineChild(nsIFrame* aOurBlock, nsIFrame* aFrame, michael@0: bool aReparentSiblings); michael@0: michael@0: virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext, michael@0: InlineReflowState& rs, michael@0: bool* aIsComplete); michael@0: michael@0: virtual void PushFrames(nsPresContext* aPresContext, michael@0: nsIFrame* aFromChild, michael@0: nsIFrame* aPrevSibling, michael@0: InlineReflowState& aState); michael@0: michael@0: private: michael@0: // Helper method for DrainSelfOverflowList() to deal with lazy parenting michael@0: // (which we only do for nsInlineFrame, not nsFirstLineFrame). michael@0: enum DrainFlags { michael@0: eDontReparentFrames = 1, // skip reparenting the overflow list frames michael@0: eInFirstLine = 2, // the request is for an inline descendant of a nsFirstLineFrame michael@0: }; michael@0: /** michael@0: * Move any frames on our overflow list to the end of our principal list. michael@0: * @param aFlags one or more of the above DrainFlags michael@0: * @param aLineContainer the nearest line container ancestor michael@0: * @return true if there were any overflow frames michael@0: */ michael@0: bool DrainSelfOverflowListInternal(DrainFlags aFlags, michael@0: nsIFrame* aLineContainer); michael@0: protected: michael@0: nscoord mBaseline; michael@0: }; michael@0: michael@0: //---------------------------------------------------------------------- michael@0: michael@0: /** michael@0: * Variation on inline-frame used to manage lines for line layout in michael@0: * special situations (:first-line style in particular). michael@0: */ michael@0: class nsFirstLineFrame MOZ_FINAL : public nsInlineFrame { michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: friend nsIFrame* NS_NewFirstLineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual void Init(nsIContent* aContent, nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: virtual void PullOverflowsFromPrevInFlow() MOZ_OVERRIDE; michael@0: virtual bool DrainSelfOverflowList() MOZ_OVERRIDE; michael@0: michael@0: protected: michael@0: nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {} michael@0: michael@0: virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext, michael@0: InlineReflowState& rs, michael@0: bool* aIsComplete) MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: #endif /* nsInlineFrame_h___ */