/src/mozilla-central/layout/mathml/nsMathMLContainerFrame.h
Line | Count | Source (jump to first uncovered line) |
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 nsMathMLContainerFrame_h___ |
8 | | #define nsMathMLContainerFrame_h___ |
9 | | |
10 | | #include "mozilla/Attributes.h" |
11 | | #include "nsContainerFrame.h" |
12 | | #include "nsBlockFrame.h" |
13 | | #include "nsInlineFrame.h" |
14 | | #include "nsMathMLOperators.h" |
15 | | #include "nsMathMLFrame.h" |
16 | | #include "mozilla/Likely.h" |
17 | | |
18 | | /* |
19 | | * Base class for MathML container frames. It acts like an inferred |
20 | | * mrow. By default, this frame uses its Reflow() method to lay its |
21 | | * children horizontally and ensure that their baselines are aligned. |
22 | | * The Reflow() method relies upon Place() to position children. |
23 | | * By overloading Place() in derived classes, it is therefore possible |
24 | | * to position children in various customized ways. |
25 | | */ |
26 | | |
27 | | // Options for the preferred size at which to stretch our stretchy children |
28 | 0 | #define STRETCH_CONSIDER_ACTUAL_SIZE 0x00000001 // just use our current size |
29 | 0 | #define STRETCH_CONSIDER_EMBELLISHMENTS 0x00000002 // size calculations include embellishments |
30 | | |
31 | | class nsMathMLContainerFrame : public nsContainerFrame, |
32 | | public nsMathMLFrame |
33 | | { |
34 | | friend class nsMathMLmfencedFrame; |
35 | | public: |
36 | | nsMathMLContainerFrame(ComputedStyle* aStyle, ClassID aID) |
37 | | : nsContainerFrame(aStyle, aID) |
38 | | , mIntrinsicWidth(NS_INTRINSIC_WIDTH_UNKNOWN) |
39 | | , mBlockStartAscent(0) |
40 | 0 | {} |
41 | | |
42 | | NS_DECL_QUERYFRAME_TARGET(nsMathMLContainerFrame) |
43 | | NS_DECL_QUERYFRAME |
44 | | NS_DECL_ABSTRACT_FRAME(nsMathMLContainerFrame) |
45 | | |
46 | | // -------------------------------------------------------------------------- |
47 | | // Overloaded nsMathMLFrame methods -- see documentation in nsIMathMLFrame.h |
48 | | |
49 | | NS_IMETHOD |
50 | | Stretch(DrawTarget* aDrawTarget, |
51 | | nsStretchDirection aStretchDirection, |
52 | | nsBoundingMetrics& aContainerSize, |
53 | | ReflowOutput& aDesiredStretchSize) override; |
54 | | |
55 | | NS_IMETHOD |
56 | | UpdatePresentationDataFromChildAt(int32_t aFirstIndex, |
57 | | int32_t aLastIndex, |
58 | | uint32_t aFlagsValues, |
59 | | uint32_t aFlagsToUpdate) override |
60 | 0 | { |
61 | 0 | PropagatePresentationDataFromChildAt(this, aFirstIndex, aLastIndex, |
62 | 0 | aFlagsValues, aFlagsToUpdate); |
63 | 0 | return NS_OK; |
64 | 0 | } |
65 | | |
66 | | // -------------------------------------------------------------------------- |
67 | | // Overloaded nsContainerFrame methods -- see documentation in nsIFrame.h |
68 | | |
69 | | virtual bool IsFrameOfType(uint32_t aFlags) const override |
70 | 0 | { |
71 | 0 | if (aFlags & (eLineParticipant | eSupportsContainLayoutAndPaint)) { |
72 | 0 | return false; |
73 | 0 | } |
74 | 0 | return nsContainerFrame::IsFrameOfType(aFlags & |
75 | 0 | ~(eMathML | eExcludesIgnorableWhitespace)); |
76 | 0 | } |
77 | | |
78 | | virtual void |
79 | | AppendFrames(ChildListID aListID, |
80 | | nsFrameList& aFrameList) override; |
81 | | |
82 | | virtual void |
83 | | InsertFrames(ChildListID aListID, |
84 | | nsIFrame* aPrevFrame, |
85 | | nsFrameList& aFrameList) override; |
86 | | |
87 | | virtual void |
88 | | RemoveFrame(ChildListID aListID, |
89 | | nsIFrame* aOldFrame) override; |
90 | | |
91 | | /** |
92 | | * Both GetMinISize and GetPrefISize use the intrinsic width metrics |
93 | | * returned by GetIntrinsicMetrics, including ink overflow. |
94 | | */ |
95 | | virtual nscoord GetMinISize(gfxContext* aRenderingContext) override; |
96 | | virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override; |
97 | | |
98 | | /** |
99 | | * Return the intrinsic horizontal metrics of the frame's content area. |
100 | | */ |
101 | | virtual void |
102 | | GetIntrinsicISizeMetrics(gfxContext* aRenderingContext, |
103 | | ReflowOutput& aDesiredSize); |
104 | | |
105 | | virtual void |
106 | | Reflow(nsPresContext* aPresContext, |
107 | | ReflowOutput& aDesiredSize, |
108 | | const ReflowInput& aReflowInput, |
109 | | nsReflowStatus& aStatus) override; |
110 | | |
111 | | virtual void DidReflow(nsPresContext* aPresContext, |
112 | | const ReflowInput* aReflowInput) override |
113 | | |
114 | 0 | { |
115 | 0 | mPresentationData.flags &= ~NS_MATHML_STRETCH_DONE; |
116 | 0 | return nsContainerFrame::DidReflow(aPresContext, aReflowInput); |
117 | 0 | } |
118 | | |
119 | | virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
120 | | const nsDisplayListSet& aLists) override; |
121 | | |
122 | | virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override; |
123 | | |
124 | | virtual void MarkIntrinsicISizesDirty() override; |
125 | | |
126 | | // Notification when an attribute is changed. The MathML module uses the |
127 | | // following paradigm: |
128 | | // |
129 | | // 1. If the MathML frame class doesn't have any cached automatic data that |
130 | | // depends on the attribute: we just reflow (e.g., this happens with <msub>, |
131 | | // <msup>, <mmultiscripts>, etc). This is the default behavior implemented |
132 | | // by this base class. |
133 | | // |
134 | | // 2. If the MathML frame class has cached automatic data that depends on |
135 | | // the attribute: |
136 | | // 2a. If the automatic data to update resides only within the descendants, |
137 | | // we just re-layout them using ReLayoutChildren(this); |
138 | | // (e.g., this happens with <ms>). |
139 | | // 2b. If the automatic data to update affects us in some way, we ask our parent |
140 | | // to re-layout its children using ReLayoutChildren(mParent); |
141 | | // Therefore, there is an overhead here in that our siblings are re-laid |
142 | | // too (e.g., this happens with <munder>, <mover>, <munderover>). |
143 | | virtual nsresult |
144 | | AttributeChanged(int32_t aNameSpaceID, |
145 | | nsAtom* aAttribute, |
146 | | int32_t aModType) override; |
147 | | |
148 | | // helper function to apply mirroring to a horizontal coordinate, if needed. |
149 | | nscoord |
150 | | MirrorIfRTL(nscoord aParentWidth, nscoord aChildWidth, nscoord aChildLeading) |
151 | 0 | { |
152 | 0 | return (StyleVisibility()->mDirection ? |
153 | 0 | aParentWidth - aChildWidth - aChildLeading : aChildLeading); |
154 | 0 | } |
155 | | |
156 | | // -------------------------------------------------------------------------- |
157 | | // Additional methods |
158 | | |
159 | | protected: |
160 | | /* Place : |
161 | | * This method is used to measure or position child frames and other |
162 | | * elements. It may be called any number of times with aPlaceOrigin |
163 | | * false to measure, and the final call of the Reflow process before |
164 | | * returning from Reflow() or Stretch() will have aPlaceOrigin true |
165 | | * to position the elements. |
166 | | * |
167 | | * IMPORTANT: This method uses GetReflowAndBoundingMetricsFor() which must |
168 | | * have been set up with SaveReflowAndBoundingMetricsFor(). |
169 | | * |
170 | | * The Place() method will use this information to compute the desired size |
171 | | * of the frame. |
172 | | * |
173 | | * @param aPlaceOrigin [in] |
174 | | * If aPlaceOrigin is false, compute your desired size using the |
175 | | * information from GetReflowAndBoundingMetricsFor. However, child |
176 | | * frames or other elements should not be repositioned. |
177 | | * |
178 | | * If aPlaceOrigin is true, reflow is finished. You should position |
179 | | * all your children, and return your desired size. You should now |
180 | | * use FinishReflowChild() on your children to complete post-reflow |
181 | | * operations. |
182 | | * |
183 | | * @param aDesiredSize [out] parameter where you should return your desired |
184 | | * size and your ascent/descent info. Compute your desired size using |
185 | | * the information from GetReflowAndBoundingMetricsFor, and include |
186 | | * any space you want for border/padding in the desired size you |
187 | | * return. |
188 | | */ |
189 | | virtual nsresult |
190 | | Place(DrawTarget* aDrawTarget, |
191 | | bool aPlaceOrigin, |
192 | | ReflowOutput& aDesiredSize); |
193 | | |
194 | | // MeasureForWidth: |
195 | | // |
196 | | // A method used by nsMathMLContainerFrame::GetIntrinsicISize to get the |
197 | | // width that a particular Place method desires. For most frames, this will |
198 | | // just call the object's Place method. However <msqrt> and <menclose> use |
199 | | // nsMathMLContainerFrame::GetIntrinsicISize to measure the child frames as |
200 | | // if in an <mrow>, and so their frames implement MeasureForWidth to use |
201 | | // nsMathMLContainerFrame::Place. |
202 | | virtual nsresult |
203 | | MeasureForWidth(DrawTarget* aDrawTarget, |
204 | | ReflowOutput& aDesiredSize); |
205 | | |
206 | | |
207 | | // helper to re-sync the automatic data in our children and notify our parent to |
208 | | // reflow us when changes (e.g., append/insert/remove) happen in our child list |
209 | | virtual nsresult |
210 | | ChildListChanged(int32_t aModType); |
211 | | |
212 | | // helper to get the preferred size that a container frame should use to fire |
213 | | // the stretch on its stretchy child frames. |
214 | | void |
215 | | GetPreferredStretchSize(DrawTarget* aDrawTarget, |
216 | | uint32_t aOptions, |
217 | | nsStretchDirection aStretchDirection, |
218 | | nsBoundingMetrics& aPreferredStretchSize); |
219 | | |
220 | | // helper used by mstyle, mphantom, mpadded and mrow in their implementation |
221 | | // of TransmitAutomaticData() to determine whether they are space-like. |
222 | | nsresult |
223 | | TransmitAutomaticDataForMrowLikeElement(); |
224 | | |
225 | | public: |
226 | | // error handlers to provide a visual feedback to the user when an error |
227 | | // (typically invalid markup) was encountered during reflow. |
228 | | nsresult |
229 | | ReflowError(DrawTarget* aDrawTarget, ReflowOutput& aDesiredSize); |
230 | | /* |
231 | | * Helper to call ReportErrorToConsole for parse errors involving |
232 | | * attribute/value pairs. |
233 | | * @param aAttribute The attribute for which the parse error occured. |
234 | | * @param aValue The value for which the parse error occured. |
235 | | */ |
236 | | nsresult |
237 | | ReportParseError(const char16_t* aAttribute, |
238 | | const char16_t* aValue); |
239 | | |
240 | | /* |
241 | | * Helper to call ReportErrorToConsole when certain tags |
242 | | * have more than the expected amount of children. |
243 | | */ |
244 | | nsresult |
245 | | ReportChildCountError(); |
246 | | |
247 | | /* |
248 | | * Helper to call ReportErrorToConsole when certain tags have |
249 | | * invalid child tags |
250 | | * @param aChildTag The tag which is forbidden in this context |
251 | | */ |
252 | | nsresult |
253 | | ReportInvalidChildError(nsAtom* aChildTag); |
254 | | |
255 | | /* |
256 | | * Helper to call ReportToConsole when an error occurs. |
257 | | * @param aParams see nsContentUtils::ReportToConsole |
258 | | */ |
259 | | nsresult |
260 | | ReportErrorToConsole(const char* aErrorMsgId, |
261 | | const char16_t** aParams = nullptr, |
262 | | uint32_t aParamCount = 0); |
263 | | |
264 | | // helper method to reflow a child frame. We are inline frames, and we don't |
265 | | // know our positions until reflow is finished. That's why we ask the |
266 | | // base method not to worry about our position. |
267 | | void |
268 | | ReflowChild(nsIFrame* aKidFrame, |
269 | | nsPresContext* aPresContext, |
270 | | ReflowOutput& aDesiredSize, |
271 | | const ReflowInput& aReflowInput, |
272 | | nsReflowStatus& aStatus); |
273 | | |
274 | | protected: |
275 | | // helper to add the inter-spacing when <math> is the immediate parent. |
276 | | // Since we don't (yet) handle the root <math> element ourselves, we need to |
277 | | // take special care of the inter-frame spacing on elements for which <math> |
278 | | // is the direct xml parent. This function will be repeatedly called from |
279 | | // left to right on the childframes of <math>, and by so doing it will |
280 | | // emulate the spacing that would have been done by a <mrow> container. |
281 | | // e.g., it fixes <math> <mi>f</mi> <mo>q</mo> <mi>f</mi> <mo>I</mo> </math> |
282 | | virtual nscoord |
283 | | FixInterFrameSpacing(ReflowOutput& aDesiredSize); |
284 | | |
285 | | // helper method to complete the post-reflow hook and ensure that embellished |
286 | | // operators don't terminate their Reflow without receiving a Stretch command. |
287 | | virtual nsresult |
288 | | FinalizeReflow(DrawTarget* aDrawTarget, ReflowOutput& aDesiredSize); |
289 | | |
290 | | // Record metrics of a child frame for recovery through the following method |
291 | | static void |
292 | | SaveReflowAndBoundingMetricsFor(nsIFrame* aFrame, |
293 | | const ReflowOutput& aReflowOutput, |
294 | | const nsBoundingMetrics& aBoundingMetrics); |
295 | | |
296 | | // helper method to facilitate getting the reflow and bounding metrics of a |
297 | | // child frame. The argument aMathMLFrameType, when non null, will return |
298 | | // the 'type' of the frame, which is used to determine the inter-frame |
299 | | // spacing. |
300 | | // IMPORTANT: This function is only meant to be called in Place() methods as |
301 | | // the information is available only when set up with the above method |
302 | | // during Reflow/Stretch() and GetPrefISize(). |
303 | | static void |
304 | | GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, |
305 | | ReflowOutput& aReflowOutput, |
306 | | nsBoundingMetrics& aBoundingMetrics, |
307 | | eMathMLFrameType* aMathMLFrameType = nullptr); |
308 | | |
309 | | // helper method to clear metrics saved with |
310 | | // SaveReflowAndBoundingMetricsFor() from all child frames. |
311 | | void ClearSavedChildMetrics(); |
312 | | |
313 | | // helper to let the update of presentation data pass through |
314 | | // a subtree that may contain non-MathML container frames |
315 | | static void |
316 | | PropagatePresentationDataFor(nsIFrame* aFrame, |
317 | | uint32_t aFlagsValues, |
318 | | uint32_t aFlagsToUpdate); |
319 | | |
320 | | public: |
321 | | static void |
322 | | PropagatePresentationDataFromChildAt(nsIFrame* aParentFrame, |
323 | | int32_t aFirstChildIndex, |
324 | | int32_t aLastChildIndex, |
325 | | uint32_t aFlagsValues, |
326 | | uint32_t aFlagsToUpdate); |
327 | | |
328 | | // Sets flags on aFrame and all descendant frames |
329 | | static void |
330 | | PropagateFrameFlagFor(nsIFrame* aFrame, |
331 | | nsFrameState aFlags); |
332 | | |
333 | | // helper to let the rebuild of automatic data (presentation data |
334 | | // and embellishement data) walk through a subtree that may contain |
335 | | // non-MathML container frames. Note that this method re-builds the |
336 | | // automatic data in the children -- not in aParentFrame itself (except |
337 | | // for those particular operations that the parent frame may do in its |
338 | | // TransmitAutomaticData()). The reason it works this way is because |
339 | | // a container frame knows what it wants for its children, whereas children |
340 | | // have no clue who their parent is. For example, it is <mfrac> who knows |
341 | | // that its children have to be in scriptsizes, and has to transmit this |
342 | | // information to them. Hence, when changes occur in a child frame, the child |
343 | | // has to request the re-build from its parent. Unfortunately, the extra cost |
344 | | // for this is that it will re-sync in the siblings of the child as well. |
345 | | static void |
346 | | RebuildAutomaticDataForChildren(nsIFrame* aParentFrame); |
347 | | |
348 | | // helper to blow away the automatic data cached in a frame's subtree and |
349 | | // re-layout its subtree to reflect changes that may have happen. In the |
350 | | // event where aParentFrame isn't a MathML frame, it will first walk up to |
351 | | // the ancestor that is a MathML frame, and re-layout from there -- this is |
352 | | // to guarantee that automatic data will be rebuilt properly. Note that this |
353 | | // method re-builds the automatic data in the children -- not in the parent |
354 | | // frame itself (except for those particular operations that the parent frame |
355 | | // may do do its TransmitAutomaticData()). @see RebuildAutomaticDataForChildren |
356 | | // |
357 | | // aBits are the bits to pass to FrameNeedsReflow() when we call it. |
358 | | static nsresult |
359 | | ReLayoutChildren(nsIFrame* aParentFrame); |
360 | | |
361 | | protected: |
362 | | // Helper method which positions child frames as an <mrow> on given baseline |
363 | | // y = aBaseline starting from x = aOffsetX, calling FinishReflowChild() |
364 | | // on the frames. |
365 | | void |
366 | | PositionRowChildFrames(nscoord aOffsetX, nscoord aBaseline); |
367 | | |
368 | | // A variant on FinishAndStoreOverflow() that uses the union of child |
369 | | // overflows, the frame bounds, and mBoundingMetrics to set and store the |
370 | | // overflow. |
371 | | void GatherAndStoreOverflow(ReflowOutput* aMetrics); |
372 | | |
373 | | /** |
374 | | * Call DidReflow() if the NS_FRAME_IN_REFLOW frame bit is set on aFirst and |
375 | | * all its next siblings up to, but not including, aStop. |
376 | | * aStop == nullptr meaning all next siblings with the bit set. |
377 | | * The method does nothing if aFirst == nullptr. |
378 | | */ |
379 | | static void DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop = nullptr); |
380 | | |
381 | | /** |
382 | | * Recompute mIntrinsicWidth if it's not already up to date. |
383 | | */ |
384 | | void UpdateIntrinsicWidth(gfxContext* aRenderingContext); |
385 | | |
386 | | nscoord mIntrinsicWidth; |
387 | | |
388 | | nscoord mBlockStartAscent; |
389 | | |
390 | | private: |
391 | | class RowChildFrameIterator; |
392 | | friend class RowChildFrameIterator; |
393 | | }; |
394 | | |
395 | | |
396 | | // -------------------------------------------------------------------------- |
397 | | // Currently, to benefit from line-breaking inside the <math> element, <math> is |
398 | | // simply mapping to nsBlockFrame or nsInlineFrame. |
399 | | // A separate implemention needs to provide: |
400 | | // 1) line-breaking |
401 | | // 2) proper inter-frame spacing |
402 | | // 3) firing of Stretch() (in which case FinalizeReflow() would have to be cleaned) |
403 | | // Issues: If/when mathml becomes a pluggable component, the separation will be needed. |
404 | | class nsMathMLmathBlockFrame final : public nsBlockFrame |
405 | | { |
406 | | public: |
407 | | NS_DECL_QUERYFRAME |
408 | | NS_DECL_FRAMEARENA_HELPERS(nsMathMLmathBlockFrame) |
409 | | |
410 | | friend nsContainerFrame* NS_NewMathMLmathBlockFrame(nsIPresShell* aPresShell, |
411 | | ComputedStyle* aStyle); |
412 | | |
413 | | // beware, mFrames is not set by nsBlockFrame |
414 | | // cannot use mFrames{.FirstChild()|.etc} since the block code doesn't set mFrames |
415 | | virtual void |
416 | | SetInitialChildList(ChildListID aListID, |
417 | | nsFrameList& aChildList) override |
418 | 0 | { |
419 | 0 | MOZ_ASSERT(aListID == kPrincipalList || aListID == kBackdropList, |
420 | 0 | "unexpected frame list"); |
421 | 0 | nsBlockFrame::SetInitialChildList(aListID, aChildList); |
422 | 0 | if (aListID == kPrincipalList) { |
423 | 0 | // re-resolve our subtree to set any mathml-expected data |
424 | 0 | nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this); |
425 | 0 | } |
426 | 0 | } |
427 | | |
428 | | virtual void |
429 | | AppendFrames(ChildListID aListID, |
430 | | nsFrameList& aFrameList) override |
431 | 0 | { |
432 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
433 | 0 | "unexpected frame list"); |
434 | 0 | nsBlockFrame::AppendFrames(aListID, aFrameList); |
435 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
436 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
437 | 0 | } |
438 | | |
439 | | virtual void |
440 | | InsertFrames(ChildListID aListID, |
441 | | nsIFrame* aPrevFrame, |
442 | | nsFrameList& aFrameList) override |
443 | 0 | { |
444 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
445 | 0 | "unexpected frame list"); |
446 | 0 | nsBlockFrame::InsertFrames(aListID, aPrevFrame, aFrameList); |
447 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
448 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
449 | 0 | } |
450 | | |
451 | | virtual void |
452 | | RemoveFrame(ChildListID aListID, |
453 | | nsIFrame* aOldFrame) override |
454 | 0 | { |
455 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
456 | 0 | "unexpected frame list"); |
457 | 0 | nsBlockFrame::RemoveFrame(aListID, aOldFrame); |
458 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
459 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
460 | 0 | } |
461 | | |
462 | 0 | virtual bool IsFrameOfType(uint32_t aFlags) const override { |
463 | 0 | return nsBlockFrame::IsFrameOfType(aFlags & |
464 | 0 | ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); |
465 | 0 | } |
466 | | |
467 | | // See nsIMathMLFrame.h |
468 | 0 | bool IsMrowLike() { |
469 | 0 | return mFrames.FirstChild() != mFrames.LastChild() || |
470 | 0 | !mFrames.FirstChild(); |
471 | 0 | } |
472 | | |
473 | | protected: |
474 | | explicit nsMathMLmathBlockFrame(ComputedStyle* aStyle) |
475 | | : nsBlockFrame(aStyle, kClassID) |
476 | 0 | { |
477 | 0 | // We should always have a float manager. Not that things can really try |
478 | 0 | // to float out of us anyway, but we need one for line layout. |
479 | 0 | // Bug 1301881: Do we still need to set NS_BLOCK_FLOAT_MGR? |
480 | 0 | // AddStateBits(NS_BLOCK_FLOAT_MGR); |
481 | 0 | } |
482 | 0 | virtual ~nsMathMLmathBlockFrame() {} |
483 | | }; |
484 | | |
485 | | // -------------- |
486 | | |
487 | | class nsMathMLmathInlineFrame final : public nsInlineFrame, |
488 | | public nsMathMLFrame |
489 | | { |
490 | | public: |
491 | | NS_DECL_QUERYFRAME |
492 | | NS_DECL_FRAMEARENA_HELPERS(nsMathMLmathInlineFrame) |
493 | | |
494 | | friend nsContainerFrame* NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, |
495 | | ComputedStyle* aStyle); |
496 | | |
497 | | virtual void |
498 | | SetInitialChildList(ChildListID aListID, |
499 | | nsFrameList& aChildList) override |
500 | 0 | { |
501 | 0 | NS_ASSERTION(aListID == kPrincipalList, "unexpected frame list"); |
502 | 0 | nsInlineFrame::SetInitialChildList(aListID, aChildList); |
503 | 0 | // re-resolve our subtree to set any mathml-expected data |
504 | 0 | nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this); |
505 | 0 | } |
506 | | |
507 | | virtual void |
508 | | AppendFrames(ChildListID aListID, |
509 | | nsFrameList& aFrameList) override |
510 | 0 | { |
511 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
512 | 0 | "unexpected frame list"); |
513 | 0 | nsInlineFrame::AppendFrames(aListID, aFrameList); |
514 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
515 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
516 | 0 | } |
517 | | |
518 | | virtual void |
519 | | InsertFrames(ChildListID aListID, |
520 | | nsIFrame* aPrevFrame, |
521 | | nsFrameList& aFrameList) override |
522 | 0 | { |
523 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
524 | 0 | "unexpected frame list"); |
525 | 0 | nsInlineFrame::InsertFrames(aListID, aPrevFrame, aFrameList); |
526 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
527 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
528 | 0 | } |
529 | | |
530 | | virtual void |
531 | | RemoveFrame(ChildListID aListID, |
532 | | nsIFrame* aOldFrame) override |
533 | 0 | { |
534 | 0 | NS_ASSERTION(aListID == kPrincipalList || aListID == kNoReflowPrincipalList, |
535 | 0 | "unexpected frame list"); |
536 | 0 | nsInlineFrame::RemoveFrame(aListID, aOldFrame); |
537 | 0 | if (MOZ_LIKELY(aListID == kPrincipalList)) |
538 | 0 | nsMathMLContainerFrame::ReLayoutChildren(this); |
539 | 0 | } |
540 | | |
541 | 0 | virtual bool IsFrameOfType(uint32_t aFlags) const override { |
542 | 0 | return nsInlineFrame::IsFrameOfType(aFlags & |
543 | 0 | ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); |
544 | 0 | } |
545 | | |
546 | | bool |
547 | 0 | IsMrowLike() override { |
548 | 0 | return mFrames.FirstChild() != mFrames.LastChild() || |
549 | 0 | !mFrames.FirstChild(); |
550 | 0 | } |
551 | | |
552 | | protected: |
553 | | explicit nsMathMLmathInlineFrame(ComputedStyle* aStyle) |
554 | | : nsInlineFrame(aStyle, kClassID) |
555 | 0 | {} |
556 | | |
557 | 0 | virtual ~nsMathMLmathInlineFrame() {} |
558 | | }; |
559 | | |
560 | | #endif /* nsMathMLContainerFrame_h___ */ |