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 #ifndef nsMathMLmtableFrame_h___
8 #define nsMathMLmtableFrame_h___
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/UniquePtr.h"
12 #include "nsMathMLContainerFrame.h"
13 #include "nsBlockFrame.h"
14 #include "nsTableWrapperFrame.h"
15 #include "nsTableRowFrame.h"
16 #include "nsTableCellFrame.h"
17 
18 namespace mozilla {
19 class PresShell;
20 }  // namespace mozilla
21 
22 //
23 // <mtable> -- table or matrix
24 //
25 
26 class nsMathMLmtableWrapperFrame final : public nsTableWrapperFrame,
27                                          public nsMathMLFrame {
28  public:
29   friend nsContainerFrame* NS_NewMathMLmtableOuterFrame(
30       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
31 
32   NS_DECL_QUERYFRAME
33   NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtableWrapperFrame)
34 
35   // overloaded nsTableWrapperFrame methods
36 
37   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
38                       const ReflowInput& aReflowInput,
39                       nsReflowStatus& aStatus) override;
40 
41   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
42                                     int32_t aModType) override;
43 
IsFrameOfType(uint32_t aFlags)44   virtual bool IsFrameOfType(uint32_t aFlags) const override {
45     return nsTableWrapperFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
46   }
47 
48  protected:
nsMathMLmtableWrapperFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)49   explicit nsMathMLmtableWrapperFrame(ComputedStyle* aStyle,
50                                       nsPresContext* aPresContext)
51       : nsTableWrapperFrame(aStyle, aPresContext, kClassID) {}
52 
53   virtual ~nsMathMLmtableWrapperFrame();
54 
55   // helper to find the row frame at a given index, positive or negative, e.g.,
56   // 1..n means the first row down to the last row, -1..-n means the last row
57   // up to the first row. Used for alignments that are relative to a given row
58   nsIFrame* GetRowFrameAt(int32_t aRowIndex);
59 };  // class nsMathMLmtableWrapperFrame
60 
61 // --------------
62 
63 class nsMathMLmtableFrame final : public nsTableFrame {
64  public:
65   NS_DECL_QUERYFRAME
66   NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtableFrame)
67 
68   friend nsContainerFrame* NS_NewMathMLmtableFrame(
69       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
70 
71   // Overloaded nsTableFrame methods
72 
73   virtual void SetInitialChildList(ChildListID aListID,
74                                    nsFrameList& aChildList) override;
75 
AppendFrames(ChildListID aListID,nsFrameList & aFrameList)76   virtual void AppendFrames(ChildListID aListID,
77                             nsFrameList& aFrameList) override {
78     nsTableFrame::AppendFrames(aListID, aFrameList);
79     RestyleTable();
80   }
81 
InsertFrames(ChildListID aListID,nsIFrame * aPrevFrame,const nsLineList::iterator * aPrevFrameLine,nsFrameList & aFrameList)82   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
83                             const nsLineList::iterator* aPrevFrameLine,
84                             nsFrameList& aFrameList) override {
85     nsTableFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine, aFrameList);
86     RestyleTable();
87   }
88 
RemoveFrame(ChildListID aListID,nsIFrame * aOldFrame)89   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override {
90     nsTableFrame::RemoveFrame(aListID, aOldFrame);
91     RestyleTable();
92   }
93 
IsFrameOfType(uint32_t aFlags)94   virtual bool IsFrameOfType(uint32_t aFlags) const override {
95     return nsTableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
96   }
97 
98   // helper to restyle and reflow the table when a row is changed -- since
99   // MathML attributes are inter-dependent and row/colspan can affect the table,
100   // it is safer (albeit grossly suboptimal) to just relayout the whole thing.
101   void RestyleTable();
102 
103   /** helper to get the column spacing style value */
104   nscoord GetColSpacing(int32_t aColIndex) override;
105 
106   /** Sums the combined cell spacing between the columns aStartColIndex to
107    *  aEndColIndex.
108    */
109   nscoord GetColSpacing(int32_t aStartColIndex, int32_t aEndColIndex) override;
110 
111   /** helper to get the row spacing style value */
112   nscoord GetRowSpacing(int32_t aRowIndex) override;
113 
114   /** Sums the combined cell spacing between the rows aStartRowIndex to
115    *  aEndRowIndex.
116    */
117   nscoord GetRowSpacing(int32_t aStartRowIndex, int32_t aEndRowIndex) override;
118 
SetColSpacingArray(const nsTArray<nscoord> & aColSpacing)119   void SetColSpacingArray(const nsTArray<nscoord>& aColSpacing) {
120     mColSpacing = aColSpacing.Clone();
121   }
122 
SetRowSpacingArray(const nsTArray<nscoord> & aRowSpacing)123   void SetRowSpacingArray(const nsTArray<nscoord>& aRowSpacing) {
124     mRowSpacing = aRowSpacing.Clone();
125   }
126 
SetFrameSpacing(nscoord aSpacingX,nscoord aSpacingY)127   void SetFrameSpacing(nscoord aSpacingX, nscoord aSpacingY) {
128     mFrameSpacingX = aSpacingX;
129     mFrameSpacingY = aSpacingY;
130   }
131 
132   /** Determines whether the placement of table cells is determined by CSS
133    * spacing based on padding and border-spacing, or one based upon the
134    * rowspacing, columnspacing and framespacing attributes.  The second
135    * approach is used if the user specifies at least one of those attributes.
136    */
137   void SetUseCSSSpacing();
GetUseCSSSpacing()138   bool GetUseCSSSpacing() { return mUseCSSSpacing; }
139 
140  protected:
nsMathMLmtableFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)141   explicit nsMathMLmtableFrame(ComputedStyle* aStyle,
142                                nsPresContext* aPresContext)
143       : nsTableFrame(aStyle, aPresContext, kClassID),
144         mFrameSpacingX(0),
145         mFrameSpacingY(0),
146         mUseCSSSpacing(false) {}
147 
148   virtual ~nsMathMLmtableFrame();
149 
150  private:
151   nsTArray<nscoord> mColSpacing;
152   nsTArray<nscoord> mRowSpacing;
153   nscoord mFrameSpacingX;
154   nscoord mFrameSpacingY;
155   bool mUseCSSSpacing;
156 };  // class nsMathMLmtableFrame
157 
158 // --------------
159 
160 class nsMathMLmtrFrame final : public nsTableRowFrame {
161  public:
162   NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtrFrame)
163 
164   friend nsContainerFrame* NS_NewMathMLmtrFrame(mozilla::PresShell* aPresShell,
165                                                 ComputedStyle* aStyle);
166 
167   // overloaded nsTableRowFrame methods
168 
169   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
170                                     int32_t aModType) override;
171 
AppendFrames(ChildListID aListID,nsFrameList & aFrameList)172   virtual void AppendFrames(ChildListID aListID,
173                             nsFrameList& aFrameList) override {
174     nsTableRowFrame::AppendFrames(aListID, aFrameList);
175     RestyleTable();
176   }
177 
InsertFrames(ChildListID aListID,nsIFrame * aPrevFrame,const nsLineList::iterator * aPrevFrameLine,nsFrameList & aFrameList)178   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
179                             const nsLineList::iterator* aPrevFrameLine,
180                             nsFrameList& aFrameList) override {
181     nsTableRowFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
182                                   aFrameList);
183     RestyleTable();
184   }
185 
RemoveFrame(ChildListID aListID,nsIFrame * aOldFrame)186   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override {
187     nsTableRowFrame::RemoveFrame(aListID, aOldFrame);
188     RestyleTable();
189   }
190 
IsFrameOfType(uint32_t aFlags)191   virtual bool IsFrameOfType(uint32_t aFlags) const override {
192     return nsTableRowFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
193   }
194 
195   // helper to restyle and reflow the table -- @see nsMathMLmtableFrame.
RestyleTable()196   void RestyleTable() {
197     nsTableFrame* tableFrame = GetTableFrame();
198     if (tableFrame && tableFrame->IsFrameOfType(nsIFrame::eMathML)) {
199       // relayout the table
200       ((nsMathMLmtableFrame*)tableFrame)->RestyleTable();
201     }
202   }
203 
204  protected:
nsMathMLmtrFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)205   explicit nsMathMLmtrFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
206       : nsTableRowFrame(aStyle, aPresContext, kClassID) {}
207 
208   virtual ~nsMathMLmtrFrame();
209 };  // class nsMathMLmtrFrame
210 
211 // --------------
212 
213 class nsMathMLmtdFrame final : public nsTableCellFrame {
214  public:
215   NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtdFrame)
216 
217   friend nsContainerFrame* NS_NewMathMLmtdFrame(mozilla::PresShell* aPresShell,
218                                                 ComputedStyle* aStyle,
219                                                 nsTableFrame* aTableFrame);
220 
221   // overloaded nsTableCellFrame methods
222 
223   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
224                     nsIFrame* aPrevInFlow) override;
225 
226   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
227                                     int32_t aModType) override;
228 
229   virtual mozilla::StyleVerticalAlignKeyword GetVerticalAlign() const override;
230   virtual nsresult ProcessBorders(nsTableFrame* aFrame,
231                                   nsDisplayListBuilder* aBuilder,
232                                   const nsDisplayListSet& aLists) override;
233 
IsFrameOfType(uint32_t aFlags)234   virtual bool IsFrameOfType(uint32_t aFlags) const override {
235     return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
236   }
237 
238   virtual LogicalMargin GetBorderWidth(WritingMode aWM) const override;
239 
240   virtual nsMargin GetBorderOverflow() override;
241 
242  protected:
nsMathMLmtdFrame(ComputedStyle * aStyle,nsTableFrame * aTableFrame)243   nsMathMLmtdFrame(ComputedStyle* aStyle, nsTableFrame* aTableFrame)
244       : nsTableCellFrame(aStyle, aTableFrame, kClassID) {}
245 
246   virtual ~nsMathMLmtdFrame();
247 };  // class nsMathMLmtdFrame
248 
249 // --------------
250 
251 class nsMathMLmtdInnerFrame final : public nsBlockFrame, public nsMathMLFrame {
252  public:
253   friend nsContainerFrame* NS_NewMathMLmtdInnerFrame(
254       mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
255 
256   NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtdInnerFrame)257   NS_DECL_FRAMEARENA_HELPERS(nsMathMLmtdInnerFrame)
258 
259   // Overloaded nsIMathMLFrame methods
260 
261   NS_IMETHOD
262   UpdatePresentationDataFromChildAt(int32_t aFirstIndex, int32_t aLastIndex,
263                                     uint32_t aFlagsValues,
264                                     uint32_t aFlagsToUpdate) override {
265     nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(
266         this, aFirstIndex, aLastIndex, aFlagsValues, aFlagsToUpdate);
267     return NS_OK;
268   }
269 
270   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
271                       const ReflowInput& aReflowInput,
272                       nsReflowStatus& aStatus) override;
273 
IsFrameOfType(uint32_t aFlags)274   virtual bool IsFrameOfType(uint32_t aFlags) const override {
275     return nsBlockFrame::IsFrameOfType(aFlags & ~nsIFrame::eMathML);
276   }
277 
278   virtual const nsStyleText* StyleTextForLineLayout() override;
279   virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
280 
IsMrowLike()281   bool IsMrowLike() override {
282     return mFrames.FirstChild() != mFrames.LastChild() || !mFrames.FirstChild();
283   }
284 
285  protected:
286   explicit nsMathMLmtdInnerFrame(ComputedStyle* aStyle,
287                                  nsPresContext* aPresContext);
288   virtual ~nsMathMLmtdInnerFrame() = default;
289 
290   mozilla::UniquePtr<nsStyleText> mUniqueStyleText;
291 
292 };  // class nsMathMLmtdInnerFrame
293 
294 #endif /* nsMathMLmtableFrame_h___ */
295