1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* rendering object for CSS display:inline objects */
8 
9 #ifndef nsInlineFrame_h___
10 #define nsInlineFrame_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "nsContainerFrame.h"
14 
15 class nsLineLayout;
16 
17 namespace mozilla {
18 class PresShell;
19 }  // namespace mozilla
20 
21 /**
22  * Inline frame class.
23  *
24  * This class manages a list of child frames that are inline frames. Working
25  * with nsLineLayout, the class will reflow and place inline frames on a line.
26  */
27 class nsInlineFrame : public nsContainerFrame {
28  public:
29   NS_DECL_QUERYFRAME
30   NS_DECL_FRAMEARENA_HELPERS(nsInlineFrame)
31 
32   friend nsInlineFrame* NS_NewInlineFrame(mozilla::PresShell* aPresShell,
33                                           ComputedStyle* aStyle);
34 
35   // nsIFrame overrides
36   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
37                                 const nsDisplayListSet& aLists) override;
38 
39 #ifdef ACCESSIBILITY
40   virtual mozilla::a11y::AccType AccessibleType() override;
41 #endif
42 
43 #ifdef DEBUG_FRAME_DUMP
44   virtual nsresult GetFrameName(nsAString& aResult) const override;
45 #endif
46 
IsFrameOfType(uint32_t aFlags)47   virtual bool IsFrameOfType(uint32_t aFlags) const override {
48     if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint |
49                   eSupportsAspectRatio)) {
50       return false;
51     }
52     return nsContainerFrame::IsFrameOfType(
53         aFlags &
54         ~(nsIFrame::eBidiInlineContainer | nsIFrame::eLineParticipant));
55   }
56 
57   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0,
58                                bool aRebuildDisplayItems = true) override;
59   virtual void InvalidateFrameWithRect(
60       const nsRect& aRect, uint32_t aDisplayItemKey = 0,
61       bool aRebuildDisplayItems = true) override;
62 
63   virtual bool IsEmpty() override;
64   virtual bool IsSelfEmpty() override;
65 
66   virtual FrameSearchResult PeekOffsetCharacter(
67       bool aForward, int32_t* aOffset,
68       PeekOffsetCharacterOptions aOptions =
69           PeekOffsetCharacterOptions()) override;
70 
71   virtual void DestroyFrom(nsIFrame* aDestructRoot,
72                            PostDestroyData& aPostDestroyData) override;
73   void StealFrame(nsIFrame* aChild) override;
74 
75   // nsIHTMLReflow overrides
76   virtual void AddInlineMinISize(gfxContext* aRenderingContext,
77                                  InlineMinISizeData* aData) override;
78   virtual void AddInlinePrefISize(gfxContext* aRenderingContext,
79                                   InlinePrefISizeData* aData) override;
80   SizeComputationResult ComputeSize(
81       gfxContext* aRenderingContext, mozilla::WritingMode aWM,
82       const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
83       const mozilla::LogicalSize& aMargin,
84       const mozilla::LogicalSize& aBorderPadding,
85       const mozilla::StyleSizeOverrides& aSizeOverrides,
86       mozilla::ComputeSizeFlags aFlags) override;
87   virtual nsRect ComputeTightBounds(DrawTarget* aDrawTarget) const override;
88   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
89                       const ReflowInput& aReflowInput,
90                       nsReflowStatus& aStatus) override;
91 
92   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
93                                     int32_t aModType) override;
94 
95   virtual bool CanContinueTextRun() const override;
96 
97   virtual void PullOverflowsFromPrevInFlow() override;
98   virtual nscoord GetLogicalBaseline(
99       mozilla::WritingMode aWritingMode) const override;
100   virtual bool DrainSelfOverflowList() override;
101 
102   /**
103    * Return true if the frame is first visual frame or first continuation
104    */
IsFirst()105   bool IsFirst() const {
106     // If the frame's bidi visual state is set, return is-first state
107     // else return true if it's the first continuation.
108     return HasAnyStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET)
109                ? HasAnyStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_FIRST)
110                : !GetPrevInFlow();
111   }
112 
113   /**
114    * Return true if the frame is last visual frame or last continuation.
115    */
IsLast()116   bool IsLast() const {
117     // If the frame's bidi visual state is set, return is-last state
118     // else return true if it's the last continuation.
119     return HasAnyStateBits(NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET)
120                ? HasAnyStateBits(NS_INLINE_FRAME_BIDI_VISUAL_IS_LAST)
121                : !GetNextInFlow();
122   }
123 
124   // Restyles the block wrappers around our non-inline-outside kids.
125   // This will only be called when such wrappers in fact exist.
126   void UpdateStyleOfOwnedAnonBoxesForIBSplit(
127       mozilla::ServoRestyleState& aRestyleState);
128 
129  protected:
130   // Additional reflow input used during our reflow methods
131   struct InlineReflowInput {
132     nsIFrame* mPrevFrame;
133     nsInlineFrame* mNextInFlow;
134     nsIFrame* mLineContainer;
135     nsLineLayout* mLineLayout;
136     bool mSetParentPointer;  // when reflowing child frame first set its
137                              // parent frame pointer
138 
InlineReflowInputInlineReflowInput139     InlineReflowInput() {
140       mPrevFrame = nullptr;
141       mNextInFlow = nullptr;
142       mLineContainer = nullptr;
143       mLineLayout = nullptr;
144       mSetParentPointer = false;
145     }
146   };
147 
nsInlineFrame(ComputedStyle * aStyle,nsPresContext * aPresContext,ClassID aID)148   nsInlineFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, ClassID aID)
149       : nsContainerFrame(aStyle, aPresContext, aID),
150         mBaseline(NS_INTRINSIC_ISIZE_UNKNOWN) {}
151 
152   LogicalSides GetLogicalSkipSides() const override;
153 
154   void ReflowFrames(nsPresContext* aPresContext,
155                     const ReflowInput& aReflowInput, InlineReflowInput& rs,
156                     ReflowOutput& aMetrics, nsReflowStatus& aStatus);
157 
158   void ReflowInlineFrame(nsPresContext* aPresContext,
159                          const ReflowInput& aReflowInput, InlineReflowInput& rs,
160                          nsIFrame* aFrame, nsReflowStatus& aStatus);
161 
162   // Returns whether there's any frame that PullOneFrame would pull from
163   // aNextInFlow or any of aNextInFlow's next-in-flows.
164   static bool HasFramesToPull(nsInlineFrame* aNextInFlow);
165 
166   virtual nsIFrame* PullOneFrame(nsPresContext*, InlineReflowInput&);
167 
168   virtual void PushFrames(nsPresContext* aPresContext, nsIFrame* aFromChild,
169                           nsIFrame* aPrevSibling, InlineReflowInput& aState);
170 
171  private:
nsInlineFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)172   explicit nsInlineFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
173       : nsInlineFrame(aStyle, aPresContext, kClassID) {}
174 
175   /**
176    * Move any frames on our overflow list to the end of our principal list.
177    * @param aInFirstLine whether we're in a first-line frame.
178    * @return true if there were any overflow frames
179    */
180   bool DrainSelfOverflowListInternal(bool aInFirstLine);
181 
182  protected:
183   nscoord mBaseline;
184 };
185 
186 //----------------------------------------------------------------------
187 
188 /**
189  * Variation on inline-frame used to manage lines for line layout in
190  * special situations (:first-line style in particular).
191  */
192 class nsFirstLineFrame final : public nsInlineFrame {
193  public:
194   NS_DECL_FRAMEARENA_HELPERS(nsFirstLineFrame)
195 
196   friend nsFirstLineFrame* NS_NewFirstLineFrame(mozilla::PresShell* aPresShell,
197                                                 ComputedStyle* aStyle);
198 
199 #ifdef DEBUG_FRAME_DUMP
200   virtual nsresult GetFrameName(nsAString& aResult) const override;
201 #endif
202   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
203                       const ReflowInput& aReflowInput,
204                       nsReflowStatus& aStatus) override;
205 
206   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
207                     nsIFrame* aPrevInFlow) override;
208   virtual void PullOverflowsFromPrevInFlow() override;
209   virtual bool DrainSelfOverflowList() override;
210 
211  protected:
nsFirstLineFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)212   explicit nsFirstLineFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
213       : nsInlineFrame(aStyle, aPresContext, kClassID) {}
214 
215   nsIFrame* PullOneFrame(nsPresContext*, InlineReflowInput&) override;
216 };
217 
218 #endif /* nsInlineFrame_h___ */
219