1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 /* rendering object for CSS display:inline objects */
7 
8 #ifndef nsInlineFrame_h___
9 #define nsInlineFrame_h___
10 
11 #include "mozilla/Attributes.h"
12 #include "nsContainerFrame.h"
13 
14 class nsLineLayout;
15 
16 /**
17  * Inline frame class.
18  *
19  * This class manages a list of child frames that are inline frames. Working with
20  * nsLineLayout, the class will reflow and place inline frames on a line.
21  */
22 class nsInlineFrame : public nsContainerFrame
23 {
24 public:
25   NS_DECL_QUERYFRAME_TARGET(nsInlineFrame)
26   NS_DECL_QUERYFRAME
27   NS_DECL_FRAMEARENA_HELPERS
28 
29   friend nsInlineFrame* NS_NewInlineFrame(nsIPresShell* aPresShell,
30                                           nsStyleContext* aContext);
GenerateStateKey(nsIContent * aContent,nsIDocument * aDocument,nsACString & aKey)31 
32   // nsIFrame overrides
33   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
34                                 const nsRect&           aDirtyRect,
35                                 const nsDisplayListSet& aLists) override;
36 
37 #ifdef ACCESSIBILITY
38   virtual mozilla::a11y::AccType AccessibleType() override;
39 #endif
40 
41 #ifdef DEBUG_FRAME_DUMP
42   virtual nsresult GetFrameName(nsAString& aResult) const override;
43 #endif
44   virtual nsIAtom* GetType() const override;
45 
46   virtual bool IsFrameOfType(uint32_t aFlags) const override
47   {
48     if (aFlags & eSupportsCSSTransforms) {
49       return false;
50     }
51     return nsContainerFrame::IsFrameOfType(aFlags &
52       ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant));
53   }
54 
55   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
56   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
57 
58   virtual bool IsEmpty() override;
59   virtual bool IsSelfEmpty() override;
60 
61   virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
62                                      bool aRespectClusters = true) override;
63 
64   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
65   virtual nsresult StealFrame(nsIFrame* aChild) override;
66 
67   // nsIHTMLReflow overrides
68   virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
69                                  InlineMinISizeData *aData) override;
70   virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
71                                   InlinePrefISizeData *aData) override;
72   virtual mozilla::LogicalSize
73   ComputeSize(nsRenderingContext *aRenderingContext,
74               mozilla::WritingMode aWritingMode,
75               const mozilla::LogicalSize& aCBSize,
76               nscoord aAvailableISize,
77               const mozilla::LogicalSize& aMargin,
78               const mozilla::LogicalSize& aBorder,
79               const mozilla::LogicalSize& aPadding,
80               ComputeSizeFlags aFlags) override;
81   virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const override;
82   virtual void Reflow(nsPresContext* aPresContext,
83                       ReflowOutput& aDesiredSize,
84                       const ReflowInput& aReflowInput,
85                       nsReflowStatus& aStatus) override;
86 
87   virtual nsresult AttributeChanged(int32_t aNameSpaceID,
88                                     nsIAtom* aAttribute,
89                                     int32_t aModType) override;
90 
91   virtual bool CanContinueTextRun() const override;
92 
93   virtual void PullOverflowsFromPrevInFlow() override;
94   virtual nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const override;
95   virtual bool DrainSelfOverflowList() override;
96 
97   /**
98    * Return true if the frame is first visual frame or first continuation
99    */
100   bool IsFirst() const {
101     // If the frame's bidi visual state is set, return is-first state
102     // else return true if it's the first continuation.
103     return (GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET)
104              ? !!(GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST)
105              : (!GetPrevInFlow());
106   }
107 
108   /**
109    * Return true if the frame is last visual frame or last continuation.
110    */
111   bool IsLast() const {
112     // If the frame's bidi visual state is set, return is-last state
113     // else return true if it's the last continuation.
114     return (GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET)
115              ? !!(GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST)
116              : (!GetNextInFlow());
117   }
118 
119 protected:
120   // Additional reflow state used during our reflow methods
121   struct InlineReflowInput {
122     nsIFrame* mPrevFrame;
123     nsInlineFrame* mNextInFlow;
124     nsIFrame*      mLineContainer;
125     nsLineLayout*  mLineLayout;
126     bool mSetParentPointer;  // when reflowing child frame first set its
127                                      // parent frame pointer
128 
129     InlineReflowInput()  {
130       mPrevFrame = nullptr;
131       mNextInFlow = nullptr;
132       mLineContainer = nullptr;
133       mLineLayout = nullptr;
134       mSetParentPointer = false;
135     }
136   };
137 
138   explicit nsInlineFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
139 
140   virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
141 
142   void ReflowFrames(nsPresContext* aPresContext,
143                     const ReflowInput& aReflowInput,
144                     InlineReflowInput& rs,
145                     ReflowOutput& aMetrics,
146                     nsReflowStatus& aStatus);
147 
148   void ReflowInlineFrame(nsPresContext* aPresContext,
149                          const ReflowInput& aReflowInput,
150                          InlineReflowInput& rs,
151                          nsIFrame* aFrame,
152                          nsReflowStatus& aStatus);
153 
154   /**
155    * Reparent floats whose placeholders are inline descendants of aFrame from
156    * whatever block they're currently parented by to aOurBlock.
157    * @param aReparentSiblings if this is true, we follow aFrame's
158    * GetNextSibling chain reparenting them all
159    */
160   void ReparentFloatsForInlineChild(nsIFrame* aOurBlock, nsIFrame* aFrame,
161                                     bool aReparentSiblings);
162 
163   virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
164                                  InlineReflowInput& rs,
165                                  bool* aIsComplete);
166 
167   virtual void PushFrames(nsPresContext* aPresContext,
168                           nsIFrame* aFromChild,
169                           nsIFrame* aPrevSibling,
170                           InlineReflowInput& aState);
171 
172 private:
173   // Helper method for DrainSelfOverflowList() to deal with lazy parenting
174   // (which we only do for nsInlineFrame, not nsFirstLineFrame).
175   enum DrainFlags {
176     eDontReparentFrames = 1, // skip reparenting the overflow list frames
177     eInFirstLine = 2, // the request is for an inline descendant of a nsFirstLineFrame
178     eForDestroy = 4, // the request is from DestroyFrom; in this case we do the
179                      // minimal work required since the frame is about to be
180                      // destroyed (just fixup parent pointers)
181   };
182   /**
183    * Move any frames on our overflow list to the end of our principal list.
184    * @param aFlags one or more of the above DrainFlags
185    * @param aLineContainer the nearest line container ancestor
186    * @return true if there were any overflow frames
187    */
188   bool DrainSelfOverflowListInternal(DrainFlags aFlags,
189                                      nsIFrame* aLineContainer);
190 protected:
191   nscoord mBaseline;
192 };
193 
194 //----------------------------------------------------------------------
195 
196 /**
197  * Variation on inline-frame used to manage lines for line layout in
198  * special situations (:first-line style in particular).
199  */
200 class nsFirstLineFrame final : public nsInlineFrame {
201 public:
202   NS_DECL_FRAMEARENA_HELPERS
203 
204   friend nsFirstLineFrame* NS_NewFirstLineFrame(nsIPresShell* aPresShell,
205                                                 nsStyleContext* aContext);
206 
207 #ifdef DEBUG_FRAME_DUMP
208   virtual nsresult GetFrameName(nsAString& aResult) const override;
209 #endif
210   virtual nsIAtom* GetType() const override;
211   virtual void Reflow(nsPresContext* aPresContext,
212                       ReflowOutput& aDesiredSize,
213                       const ReflowInput& aReflowInput,
214                       nsReflowStatus& aStatus) override;
215 
216   virtual void Init(nsIContent*       aContent,
217                     nsContainerFrame* aParent,
218                     nsIFrame*         aPrevInFlow) override;
219   virtual void PullOverflowsFromPrevInFlow() override;
220   virtual bool DrainSelfOverflowList() override;
221 
222 protected:
223   explicit nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
224 
225   virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
226                                  InlineReflowInput& rs,
227                                  bool* aIsComplete) override;
228 };
229 
230 #endif /* nsInlineFrame_h___ */
231