Line data Source code
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 : #include "nsMathMLContainerFrame.h"
7 :
8 : #include "gfxContext.h"
9 : #include "gfxUtils.h"
10 : #include "mozilla/gfx/2D.h"
11 : #include "nsLayoutUtils.h"
12 : #include "nsPresContext.h"
13 : #include "nsIPresShell.h"
14 : #include "nsStyleContext.h"
15 : #include "nsNameSpaceManager.h"
16 : #include "nsIDOMMutationEvent.h"
17 : #include "nsGkAtoms.h"
18 : #include "nsDisplayList.h"
19 : #include "mozilla/Likely.h"
20 : #include "nsIScriptError.h"
21 : #include "nsContentUtils.h"
22 : #include "nsMathMLElement.h"
23 :
24 : using namespace mozilla;
25 : using namespace mozilla::gfx;
26 :
27 : //
28 : // nsMathMLContainerFrame implementation
29 : //
30 :
31 0 : NS_QUERYFRAME_HEAD(nsMathMLContainerFrame)
32 0 : NS_QUERYFRAME_ENTRY(nsIMathMLFrame)
33 0 : NS_QUERYFRAME_ENTRY(nsMathMLContainerFrame)
34 0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
35 :
36 : // =============================================================================
37 :
38 : // error handlers
39 : // provide a feedback to the user when a frame with bad markup can not be rendered
40 : nsresult
41 0 : nsMathMLContainerFrame::ReflowError(DrawTarget* aDrawTarget,
42 : ReflowOutput& aDesiredSize)
43 : {
44 : // clear all other flags and record that there is an error with this frame
45 0 : mEmbellishData.flags = 0;
46 0 : mPresentationData.flags = NS_MATHML_ERROR;
47 :
48 : ///////////////
49 : // Set font
50 : RefPtr<nsFontMetrics> fm =
51 0 : nsLayoutUtils::GetInflatedFontMetricsForFrame(this);
52 :
53 : // bounding metrics
54 0 : nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
55 : mBoundingMetrics =
56 : nsLayoutUtils::AppUnitBoundsOfString(errorMsg.get(), errorMsg.Length(),
57 0 : *fm, aDrawTarget);
58 :
59 : // reflow metrics
60 0 : WritingMode wm = aDesiredSize.GetWritingMode();
61 0 : aDesiredSize.SetBlockStartAscent(fm->MaxAscent());
62 0 : nscoord descent = fm->MaxDescent();
63 0 : aDesiredSize.BSize(wm) = aDesiredSize.BlockStartAscent() + descent;
64 0 : aDesiredSize.ISize(wm) = mBoundingMetrics.width;
65 :
66 : // Also return our bounding metrics
67 0 : aDesiredSize.mBoundingMetrics = mBoundingMetrics;
68 :
69 0 : return NS_OK;
70 : }
71 :
72 : class nsDisplayMathMLError : public nsDisplayItem {
73 : public:
74 0 : nsDisplayMathMLError(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
75 0 : : nsDisplayItem(aBuilder, aFrame) {
76 0 : MOZ_COUNT_CTOR(nsDisplayMathMLError);
77 0 : }
78 : #ifdef NS_BUILD_REFCNT_LOGGING
79 0 : virtual ~nsDisplayMathMLError() {
80 0 : MOZ_COUNT_DTOR(nsDisplayMathMLError);
81 0 : }
82 : #endif
83 :
84 : virtual void Paint(nsDisplayListBuilder* aBuilder,
85 : gfxContext* aCtx) override;
86 0 : NS_DISPLAY_DECL_NAME("MathMLError", TYPE_MATHML_ERROR)
87 : };
88 :
89 0 : void nsDisplayMathMLError::Paint(nsDisplayListBuilder* aBuilder,
90 : gfxContext* aCtx)
91 : {
92 : // Set color and font ...
93 : RefPtr<nsFontMetrics> fm =
94 0 : nsLayoutUtils::GetFontMetricsForFrame(mFrame, 1.0f);
95 :
96 0 : nsPoint pt = ToReferenceFrame();
97 0 : int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
98 0 : DrawTarget* drawTarget = aCtx->GetDrawTarget();
99 0 : Rect rect = NSRectToSnappedRect(nsRect(pt, mFrame->GetSize()),
100 : appUnitsPerDevPixel,
101 0 : *drawTarget);
102 0 : ColorPattern red(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
103 0 : drawTarget->FillRect(rect, red);
104 :
105 0 : aCtx->SetColor(Color(1.f, 1.f, 1.f));
106 0 : nscoord ascent = fm->MaxAscent();
107 0 : NS_NAMED_LITERAL_STRING(errorMsg, "invalid-markup");
108 0 : nsLayoutUtils::DrawUniDirString(errorMsg.get(), uint32_t(errorMsg.Length()),
109 0 : nsPoint(pt.x, pt.y + ascent), *fm, *aCtx);
110 0 : }
111 :
112 : /* /////////////
113 : * nsIMathMLFrame - support methods for stretchy elements
114 : * =============================================================================
115 : */
116 :
117 : static bool
118 0 : IsForeignChild(const nsIFrame* aFrame)
119 : {
120 : // This counts nsMathMLmathBlockFrame as a foreign child, because it
121 : // uses block reflow
122 0 : return !(aFrame->IsFrameOfType(nsIFrame::eMathML)) || aFrame->IsBlockFrame();
123 : }
124 :
125 0 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(HTMLReflowOutputProperty,
126 : ReflowOutput)
127 :
128 : /* static */ void
129 0 : nsMathMLContainerFrame::SaveReflowAndBoundingMetricsFor(nsIFrame* aFrame,
130 : const ReflowOutput& aReflowOutput,
131 : const nsBoundingMetrics& aBoundingMetrics)
132 : {
133 0 : ReflowOutput* reflowOutput = new ReflowOutput(aReflowOutput);
134 0 : reflowOutput->mBoundingMetrics = aBoundingMetrics;
135 0 : aFrame->SetProperty(HTMLReflowOutputProperty(), reflowOutput);
136 0 : }
137 :
138 : // helper method to facilitate getting the reflow and bounding metrics
139 : /* static */ void
140 0 : nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame,
141 : ReflowOutput& aReflowOutput,
142 : nsBoundingMetrics& aBoundingMetrics,
143 : eMathMLFrameType* aMathMLFrameType)
144 : {
145 0 : NS_PRECONDITION(aFrame, "null arg");
146 :
147 : ReflowOutput* reflowOutput =
148 0 : aFrame->GetProperty(HTMLReflowOutputProperty());
149 :
150 : // IMPORTANT: This function is only meant to be called in Place() methods
151 : // where it is assumed that SaveReflowAndBoundingMetricsFor has recorded the
152 : // information.
153 0 : NS_ASSERTION(reflowOutput, "Didn't SaveReflowAndBoundingMetricsFor frame!");
154 0 : if (reflowOutput) {
155 0 : aReflowOutput = *reflowOutput;
156 0 : aBoundingMetrics = reflowOutput->mBoundingMetrics;
157 : }
158 :
159 0 : if (aMathMLFrameType) {
160 0 : if (!IsForeignChild(aFrame)) {
161 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
162 0 : if (mathMLFrame) {
163 0 : *aMathMLFrameType = mathMLFrame->GetMathMLFrameType();
164 0 : return;
165 : }
166 : }
167 0 : *aMathMLFrameType = eMathMLFrameType_UNKNOWN;
168 : }
169 :
170 : }
171 :
172 : void
173 0 : nsMathMLContainerFrame::ClearSavedChildMetrics()
174 : {
175 0 : nsIFrame* childFrame = mFrames.FirstChild();
176 0 : while (childFrame) {
177 0 : childFrame->DeleteProperty(HTMLReflowOutputProperty());
178 0 : childFrame = childFrame->GetNextSibling();
179 : }
180 0 : }
181 :
182 : // helper to get the preferred size that a container frame should use to fire
183 : // the stretch on its stretchy child frames.
184 : void
185 0 : nsMathMLContainerFrame::GetPreferredStretchSize(DrawTarget* aDrawTarget,
186 : uint32_t aOptions,
187 : nsStretchDirection aStretchDirection,
188 : nsBoundingMetrics& aPreferredStretchSize)
189 : {
190 0 : if (aOptions & STRETCH_CONSIDER_ACTUAL_SIZE) {
191 : // when our actual size is ok, just use it
192 0 : aPreferredStretchSize = mBoundingMetrics;
193 : }
194 0 : else if (aOptions & STRETCH_CONSIDER_EMBELLISHMENTS) {
195 : // compute our up-to-date size using Place()
196 0 : ReflowOutput reflowOutput(GetWritingMode());
197 0 : Place(aDrawTarget, false, reflowOutput);
198 0 : aPreferredStretchSize = reflowOutput.mBoundingMetrics;
199 : }
200 : else {
201 : // compute a size that includes embellishments iff the container stretches
202 : // in the same direction as the embellished operator.
203 0 : bool stretchAll = aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL ?
204 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) :
205 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags);
206 0 : NS_ASSERTION(aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL ||
207 : aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL,
208 : "You must specify a direction in which to stretch");
209 0 : NS_ASSERTION(NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) ||
210 : stretchAll,
211 : "invalid call to GetPreferredStretchSize");
212 0 : bool firstTime = true;
213 0 : nsBoundingMetrics bm, bmChild;
214 : nsIFrame* childFrame =
215 0 : stretchAll ? PrincipalChildList().FirstChild() : mPresentationData.baseFrame;
216 0 : while (childFrame) {
217 : // initializations in case this child happens not to be a MathML frame
218 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
219 0 : if (mathMLFrame) {
220 0 : nsEmbellishData embellishData;
221 0 : nsPresentationData presentationData;
222 0 : mathMLFrame->GetEmbellishData(embellishData);
223 0 : mathMLFrame->GetPresentationData(presentationData);
224 0 : if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) &&
225 0 : embellishData.direction == aStretchDirection &&
226 0 : presentationData.baseFrame) {
227 : // embellishements are not included, only consider the inner first child itself
228 : // XXXkt Does that mean the core descendent frame should be used
229 : // instead of the base child?
230 0 : nsIMathMLFrame* mathMLchildFrame = do_QueryFrame(presentationData.baseFrame);
231 0 : if (mathMLchildFrame) {
232 0 : mathMLFrame = mathMLchildFrame;
233 : }
234 : }
235 0 : mathMLFrame->GetBoundingMetrics(bmChild);
236 : }
237 : else {
238 0 : ReflowOutput unused(GetWritingMode());
239 0 : GetReflowAndBoundingMetricsFor(childFrame, unused, bmChild);
240 : }
241 :
242 0 : if (firstTime) {
243 0 : firstTime = false;
244 0 : bm = bmChild;
245 0 : if (!stretchAll) {
246 : // we may get here for cases such as <msup><mo>...</mo> ... </msup>,
247 : // or <maction>...<mo>...</mo></maction>.
248 0 : break;
249 : }
250 : }
251 : else {
252 0 : if (aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
253 : // if we get here, it means this is container that will stack its children
254 : // vertically and fire an horizontal stretch on each them. This is the case
255 : // for \munder, \mover, \munderover. We just sum-up the size vertically.
256 0 : bm.descent += bmChild.ascent + bmChild.descent;
257 : // Sometimes non-spacing marks (when width is zero) are positioned
258 : // to the left of the origin, but it is the distance between left
259 : // and right bearing that is important rather than the offsets from
260 : // the origin.
261 0 : if (bmChild.width == 0) {
262 0 : bmChild.rightBearing -= bmChild.leftBearing;
263 0 : bmChild.leftBearing = 0;
264 : }
265 0 : if (bm.leftBearing > bmChild.leftBearing)
266 0 : bm.leftBearing = bmChild.leftBearing;
267 0 : if (bm.rightBearing < bmChild.rightBearing)
268 0 : bm.rightBearing = bmChild.rightBearing;
269 : }
270 0 : else if (aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) {
271 : // just sum-up the sizes horizontally.
272 0 : bm += bmChild;
273 : }
274 : else {
275 0 : NS_ERROR("unexpected case in GetPreferredStretchSize");
276 0 : break;
277 : }
278 : }
279 0 : childFrame = childFrame->GetNextSibling();
280 : }
281 0 : aPreferredStretchSize = bm;
282 : }
283 0 : }
284 :
285 : NS_IMETHODIMP
286 0 : nsMathMLContainerFrame::Stretch(DrawTarget* aDrawTarget,
287 : nsStretchDirection aStretchDirection,
288 : nsBoundingMetrics& aContainerSize,
289 : ReflowOutput& aDesiredStretchSize)
290 : {
291 0 : if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) {
292 :
293 0 : if (NS_MATHML_STRETCH_WAS_DONE(mPresentationData.flags)) {
294 0 : NS_WARNING("it is wrong to fire stretch more than once on a frame");
295 0 : return NS_OK;
296 : }
297 0 : mPresentationData.flags |= NS_MATHML_STRETCH_DONE;
298 :
299 0 : if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
300 0 : NS_WARNING("it is wrong to fire stretch on a erroneous frame");
301 0 : return NS_OK;
302 : }
303 :
304 : // Pass the stretch to the base child ...
305 :
306 0 : nsIFrame* baseFrame = mPresentationData.baseFrame;
307 0 : if (baseFrame) {
308 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(baseFrame);
309 0 : NS_ASSERTION(mathMLFrame, "Something is wrong somewhere");
310 0 : if (mathMLFrame) {
311 :
312 : // And the trick is that the child's rect.x is still holding the descent,
313 : // and rect.y is still holding the ascent ...
314 0 : ReflowOutput childSize(aDesiredStretchSize);
315 0 : GetReflowAndBoundingMetricsFor(baseFrame, childSize, childSize.mBoundingMetrics);
316 :
317 : // See if we should downsize and confine the stretch to us...
318 : // XXX there may be other cases where we can downsize the stretch,
319 : // e.g., the first ∑ might appear big in the following situation
320 : // <math xmlns='http://www.w3.org/1998/Math/MathML'>
321 : // <mstyle>
322 : // <msub>
323 : // <msub><mo>∑</mo><mfrac><mi>a</mi><mi>b</mi></mfrac></msub>
324 : // <msub><mo>∑</mo><mfrac><mi>a</mi><mi>b</mi></mfrac></msub>
325 : // </msub>
326 : // </mstyle>
327 : // </math>
328 0 : nsBoundingMetrics containerSize = aContainerSize;
329 0 : if (aStretchDirection != mEmbellishData.direction &&
330 0 : mEmbellishData.direction != NS_STRETCH_DIRECTION_UNSUPPORTED) {
331 0 : NS_ASSERTION(mEmbellishData.direction != NS_STRETCH_DIRECTION_DEFAULT,
332 : "Stretches may have a default direction, operators can not.");
333 0 : if (mEmbellishData.direction == NS_STRETCH_DIRECTION_VERTICAL ?
334 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) :
335 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) {
336 0 : GetPreferredStretchSize(aDrawTarget, 0,
337 0 : mEmbellishData.direction, containerSize);
338 : // Stop further recalculations
339 0 : aStretchDirection = mEmbellishData.direction;
340 : } else {
341 : // We aren't going to stretch the child, so just use the child metrics.
342 0 : containerSize = childSize.mBoundingMetrics;
343 : }
344 : }
345 :
346 : // do the stretching...
347 : mathMLFrame->Stretch(aDrawTarget,
348 0 : aStretchDirection, containerSize, childSize);
349 : // store the updated metrics
350 : SaveReflowAndBoundingMetricsFor(baseFrame, childSize,
351 0 : childSize.mBoundingMetrics);
352 :
353 : // Remember the siblings which were _deferred_.
354 : // Now that this embellished child may have changed, we need to
355 : // fire the stretch on its siblings using our updated size
356 :
357 0 : if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ||
358 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags)) {
359 :
360 : nsStretchDirection stretchDir =
361 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ?
362 0 : NS_STRETCH_DIRECTION_VERTICAL : NS_STRETCH_DIRECTION_HORIZONTAL;
363 :
364 : GetPreferredStretchSize(aDrawTarget, STRETCH_CONSIDER_EMBELLISHMENTS,
365 0 : stretchDir, containerSize);
366 :
367 0 : nsIFrame* childFrame = mFrames.FirstChild();
368 0 : while (childFrame) {
369 0 : if (childFrame != mPresentationData.baseFrame) {
370 0 : mathMLFrame = do_QueryFrame(childFrame);
371 0 : if (mathMLFrame) {
372 : // retrieve the metrics that was stored at the previous pass
373 : GetReflowAndBoundingMetricsFor(childFrame,
374 0 : childSize, childSize.mBoundingMetrics);
375 : // do the stretching...
376 : mathMLFrame->Stretch(aDrawTarget, stretchDir,
377 0 : containerSize, childSize);
378 : // store the updated metrics
379 : SaveReflowAndBoundingMetricsFor(childFrame, childSize,
380 0 : childSize.mBoundingMetrics);
381 : }
382 : }
383 0 : childFrame = childFrame->GetNextSibling();
384 : }
385 : }
386 :
387 : // re-position all our children
388 0 : nsresult rv = Place(aDrawTarget, true, aDesiredStretchSize);
389 0 : if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
390 : // Make sure the child frames get their DidReflow() calls.
391 0 : DidReflowChildren(mFrames.FirstChild());
392 : }
393 :
394 : // If our parent is not embellished, it means we are the outermost embellished
395 : // container and so we put the spacing, otherwise we don't include the spacing,
396 : // the outermost embellished container will take care of it.
397 :
398 0 : nsEmbellishData parentData;
399 0 : GetEmbellishDataFrom(GetParent(), parentData);
400 : // ensure that we are the embellished child, not just a sibling
401 : // (need to test coreFrame since <mfrac> resets other things)
402 0 : if (parentData.coreFrame != mEmbellishData.coreFrame) {
403 : // (we fetch values from the core since they may use units that depend
404 : // on style data, and style changes could have occurred in the core since
405 : // our last visit there)
406 0 : nsEmbellishData coreData;
407 0 : GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
408 :
409 0 : mBoundingMetrics.width +=
410 0 : coreData.leadingSpace + coreData.trailingSpace;
411 0 : aDesiredStretchSize.Width() = mBoundingMetrics.width;
412 0 : aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
413 :
414 0 : nscoord dx = (StyleVisibility()->mDirection ?
415 0 : coreData.trailingSpace : coreData.leadingSpace);
416 0 : if (dx != 0) {
417 0 : mBoundingMetrics.leftBearing += dx;
418 0 : mBoundingMetrics.rightBearing += dx;
419 0 : aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
420 0 : aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
421 :
422 0 : nsIFrame* childFrame = mFrames.FirstChild();
423 0 : while (childFrame) {
424 0 : childFrame->SetPosition(childFrame->GetPosition()
425 0 : + nsPoint(dx, 0));
426 0 : childFrame = childFrame->GetNextSibling();
427 : }
428 : }
429 : }
430 :
431 : // Finished with these:
432 0 : ClearSavedChildMetrics();
433 : // Set our overflow area
434 0 : GatherAndStoreOverflow(&aDesiredStretchSize);
435 : }
436 : }
437 : }
438 0 : return NS_OK;
439 : }
440 :
441 : nsresult
442 0 : nsMathMLContainerFrame::FinalizeReflow(DrawTarget* aDrawTarget,
443 : ReflowOutput& aDesiredSize)
444 : {
445 : // During reflow, we use rect.x and rect.y as placeholders for the child's ascent
446 : // and descent in expectation of a stretch command. Hence we need to ensure that
447 : // a stretch command will actually be fired later on, after exiting from our
448 : // reflow. If the stretch is not fired, the rect.x, and rect.y will remain
449 : // with inappropriate data causing children to be improperly positioned.
450 : // This helper method checks to see if our parent will fire a stretch command
451 : // targeted at us. If not, we go ahead and fire an involutive stretch on
452 : // ourselves. This will clear all the rect.x and rect.y, and return our
453 : // desired size.
454 :
455 :
456 : // First, complete the post-reflow hook.
457 : // We use the information in our children rectangles to position them.
458 : // If placeOrigin==false, then Place() will not touch rect.x, and rect.y.
459 : // They will still be holding the ascent and descent for each child.
460 :
461 : // The first clause caters for any non-embellished container.
462 : // The second clause is for a container which won't fire stretch even though it is
463 : // embellished, e.g., as in <mfrac><mo>...</mo> ... </mfrac>, the test is convoluted
464 : // because it excludes the particular case of the core <mo>...</mo> itself.
465 : // (<mo> needs to fire stretch on its MathMLChar in any case to initialize it)
466 0 : bool placeOrigin = !NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) ||
467 0 : (mEmbellishData.coreFrame != this && !mPresentationData.baseFrame &&
468 0 : mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED);
469 0 : nsresult rv = Place(aDrawTarget, placeOrigin, aDesiredSize);
470 :
471 : // Place() will call FinishReflowChild() when placeOrigin is true but if
472 : // it returns before reaching FinishReflowChild() due to errors we need
473 : // to fulfill the reflow protocol by calling DidReflow for the child frames
474 : // that still needs it here (or we may crash - bug 366012).
475 : // If placeOrigin is false we should reach Place() with aPlaceOrigin == true
476 : // through Stretch() eventually.
477 0 : if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
478 0 : GatherAndStoreOverflow(&aDesiredSize);
479 0 : DidReflowChildren(PrincipalChildList().FirstChild());
480 0 : return rv;
481 : }
482 :
483 0 : bool parentWillFireStretch = false;
484 0 : if (!placeOrigin) {
485 : // This means the rect.x and rect.y of our children were not set!!
486 : // Don't go without checking to see if our parent will later fire a Stretch() command
487 : // targeted at us. The Stretch() will cause the rect.x and rect.y to clear...
488 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(GetParent());
489 0 : if (mathMLFrame) {
490 0 : nsEmbellishData embellishData;
491 0 : nsPresentationData presentationData;
492 0 : mathMLFrame->GetEmbellishData(embellishData);
493 0 : mathMLFrame->GetPresentationData(presentationData);
494 0 : if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(presentationData.flags) ||
495 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(presentationData.flags) ||
496 0 : (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags)
497 0 : && presentationData.baseFrame == this))
498 : {
499 0 : parentWillFireStretch = true;
500 : }
501 : }
502 0 : if (!parentWillFireStretch) {
503 : // There is nobody who will fire the stretch for us, we do it ourselves!
504 :
505 : bool stretchAll =
506 : /* NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) || */
507 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags);
508 :
509 : nsStretchDirection stretchDir;
510 0 : if (mEmbellishData.coreFrame == this || /* case of a bare <mo>...</mo> itself */
511 0 : (mEmbellishData.direction == NS_STRETCH_DIRECTION_HORIZONTAL &&
512 0 : stretchAll) || /* or <mover><mo>...</mo>...</mover>, or friends */
513 0 : mEmbellishData.direction == NS_STRETCH_DIRECTION_UNSUPPORTED) { /* Doesn't stretch */
514 0 : stretchDir = mEmbellishData.direction;
515 : } else {
516 : // Let the Stretch() call decide the direction.
517 0 : stretchDir = NS_STRETCH_DIRECTION_DEFAULT;
518 : }
519 : // Use our current size as computed earlier by Place()
520 : // The stretch call will detect if this is incorrect and recalculate the size.
521 0 : nsBoundingMetrics defaultSize = aDesiredSize.mBoundingMetrics;
522 :
523 0 : Stretch(aDrawTarget, stretchDir, defaultSize, aDesiredSize);
524 : #ifdef DEBUG
525 : {
526 : // The Place() call above didn't request FinishReflowChild(),
527 : // so let's check that we eventually did through Stretch().
528 0 : for (nsIFrame* childFrame : PrincipalChildList()) {
529 0 : NS_ASSERTION(!(childFrame->GetStateBits() & NS_FRAME_IN_REFLOW),
530 : "DidReflow() was never called");
531 : }
532 : }
533 : #endif
534 : }
535 : }
536 :
537 : // Also return our bounding metrics
538 0 : aDesiredSize.mBoundingMetrics = mBoundingMetrics;
539 :
540 : // see if we should fix the spacing
541 0 : FixInterFrameSpacing(aDesiredSize);
542 :
543 0 : if (!parentWillFireStretch) {
544 : // Not expecting a stretch.
545 : // Finished with these:
546 0 : ClearSavedChildMetrics();
547 : // Set our overflow area.
548 0 : GatherAndStoreOverflow(&aDesiredSize);
549 : }
550 :
551 0 : return NS_OK;
552 : }
553 :
554 :
555 : /* /////////////
556 : * nsIMathMLFrame - support methods for scripting elements (nested frames
557 : * within msub, msup, msubsup, munder, mover, munderover, mmultiscripts,
558 : * mfrac, mroot, mtable).
559 : * =============================================================================
560 : */
561 :
562 : // helper to let the update of presentation data pass through
563 : // a subtree that may contain non-mathml container frames
564 : /* static */ void
565 0 : nsMathMLContainerFrame::PropagatePresentationDataFor(nsIFrame* aFrame,
566 : uint32_t aFlagsValues,
567 : uint32_t aFlagsToUpdate)
568 : {
569 0 : if (!aFrame || !aFlagsToUpdate)
570 0 : return;
571 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
572 0 : if (mathMLFrame) {
573 : // update
574 : mathMLFrame->UpdatePresentationData(aFlagsValues,
575 0 : aFlagsToUpdate);
576 : // propagate using the base method to make sure that the control
577 : // is passed on to MathML frames that may be overloading the method
578 : mathMLFrame->UpdatePresentationDataFromChildAt(0, -1,
579 0 : aFlagsValues, aFlagsToUpdate);
580 : }
581 : else {
582 : // propagate down the subtrees
583 0 : for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
584 : PropagatePresentationDataFor(childFrame,
585 0 : aFlagsValues, aFlagsToUpdate);
586 : }
587 : }
588 : }
589 :
590 : /* static */ void
591 0 : nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame* aParentFrame,
592 : int32_t aFirstChildIndex,
593 : int32_t aLastChildIndex,
594 : uint32_t aFlagsValues,
595 : uint32_t aFlagsToUpdate)
596 : {
597 0 : if (!aParentFrame || !aFlagsToUpdate)
598 0 : return;
599 0 : int32_t index = 0;
600 0 : for (nsIFrame* childFrame : aParentFrame->PrincipalChildList()) {
601 0 : if ((index >= aFirstChildIndex) &&
602 0 : ((aLastChildIndex <= 0) || ((aLastChildIndex > 0) &&
603 : (index <= aLastChildIndex)))) {
604 : PropagatePresentationDataFor(childFrame,
605 0 : aFlagsValues, aFlagsToUpdate);
606 : }
607 0 : index++;
608 : }
609 : }
610 :
611 : /* //////////////////
612 : * Frame construction
613 : * =============================================================================
614 : */
615 :
616 :
617 : void
618 0 : nsMathMLContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
619 : const nsRect& aDirtyRect,
620 : const nsDisplayListSet& aLists)
621 : {
622 : // report an error if something wrong was found in this frame
623 0 : if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
624 0 : if (!IsVisibleForPainting(aBuilder))
625 0 : return;
626 :
627 0 : aLists.Content()->AppendNewToTop(
628 0 : new (aBuilder) nsDisplayMathMLError(aBuilder, this));
629 0 : return;
630 : }
631 :
632 0 : DisplayBorderBackgroundOutline(aBuilder, aLists);
633 :
634 0 : BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists,
635 0 : DISPLAY_CHILD_INLINE);
636 :
637 : #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX)
638 : // for visual debug
639 : // ----------------
640 : // if you want to see your bounding box, make sure to properly fill
641 : // your mBoundingMetrics and mReference point, and set
642 : // mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS
643 : // in the Init() of your sub-class
644 : DisplayBoundingMetrics(aBuilder, this, mReference, mBoundingMetrics, aLists);
645 : #endif
646 : }
647 :
648 : // Note that this method re-builds the automatic data in the children -- not
649 : // in aParentFrame itself (except for those particular operations that the
650 : // parent frame may do in its TransmitAutomaticData()).
651 : /* static */ void
652 0 : nsMathMLContainerFrame::RebuildAutomaticDataForChildren(nsIFrame* aParentFrame)
653 : {
654 : // 1. As we descend the tree, make each child frame inherit data from
655 : // the parent
656 : // 2. As we ascend the tree, transmit any specific change that we want
657 : // down the subtrees
658 0 : for (nsIFrame* childFrame : aParentFrame->PrincipalChildList()) {
659 0 : nsIMathMLFrame* childMathMLFrame = do_QueryFrame(childFrame);
660 0 : if (childMathMLFrame) {
661 0 : childMathMLFrame->InheritAutomaticData(aParentFrame);
662 : }
663 0 : RebuildAutomaticDataForChildren(childFrame);
664 : }
665 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(aParentFrame);
666 0 : if (mathMLFrame) {
667 0 : mathMLFrame->TransmitAutomaticData();
668 : }
669 0 : }
670 :
671 : /* static */ nsresult
672 0 : nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame)
673 : {
674 0 : if (!aParentFrame)
675 0 : return NS_OK;
676 :
677 : // walk-up to the first frame that is a MathML frame, stop if we reach <math>
678 0 : nsIFrame* frame = aParentFrame;
679 : while (1) {
680 0 : nsIFrame* parent = frame->GetParent();
681 0 : if (!parent || !parent->GetContent())
682 0 : break;
683 :
684 : // stop if it is a MathML frame
685 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(frame);
686 0 : if (mathMLFrame)
687 0 : break;
688 :
689 : // stop if we reach the root <math> tag
690 0 : nsIContent* content = frame->GetContent();
691 0 : NS_ASSERTION(content, "dangling frame without a content node");
692 0 : if (!content)
693 0 : break;
694 0 : if (content->IsMathMLElement(nsGkAtoms::math))
695 0 : break;
696 :
697 0 : frame = parent;
698 0 : }
699 :
700 : // re-sync the presentation data and embellishment data of our children
701 0 : RebuildAutomaticDataForChildren(frame);
702 :
703 : // Ask our parent frame to reflow us
704 0 : nsIFrame* parent = frame->GetParent();
705 0 : NS_ASSERTION(parent, "No parent to pass the reflow request up to");
706 0 : if (!parent)
707 0 : return NS_OK;
708 :
709 0 : frame->PresContext()->PresShell()->
710 0 : FrameNeedsReflow(frame, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
711 :
712 0 : return NS_OK;
713 : }
714 :
715 : // There are precise rules governing children of a MathML frame,
716 : // and properties such as the scriptlevel depends on those rules.
717 : // Hence for things to work, callers must use Append/Insert/etc wisely.
718 :
719 : nsresult
720 0 : nsMathMLContainerFrame::ChildListChanged(int32_t aModType)
721 : {
722 : // If this is an embellished frame we need to rebuild the
723 : // embellished hierarchy by walking-up to the parent of the
724 : // outermost embellished container.
725 0 : nsIFrame* frame = this;
726 0 : if (mEmbellishData.coreFrame) {
727 0 : nsIFrame* parent = GetParent();
728 0 : nsEmbellishData embellishData;
729 0 : for ( ; parent; frame = parent, parent = parent->GetParent()) {
730 0 : GetEmbellishDataFrom(parent, embellishData);
731 0 : if (embellishData.coreFrame != mEmbellishData.coreFrame)
732 0 : break;
733 : }
734 : }
735 0 : return ReLayoutChildren(frame);
736 : }
737 :
738 : void
739 0 : nsMathMLContainerFrame::AppendFrames(ChildListID aListID,
740 : nsFrameList& aFrameList)
741 : {
742 0 : MOZ_ASSERT(aListID == kPrincipalList);
743 0 : mFrames.AppendFrames(this, aFrameList);
744 0 : ChildListChanged(nsIDOMMutationEvent::ADDITION);
745 0 : }
746 :
747 : void
748 0 : nsMathMLContainerFrame::InsertFrames(ChildListID aListID,
749 : nsIFrame* aPrevFrame,
750 : nsFrameList& aFrameList)
751 : {
752 0 : MOZ_ASSERT(aListID == kPrincipalList);
753 0 : mFrames.InsertFrames(this, aPrevFrame, aFrameList);
754 0 : ChildListChanged(nsIDOMMutationEvent::ADDITION);
755 0 : }
756 :
757 : void
758 0 : nsMathMLContainerFrame::RemoveFrame(ChildListID aListID,
759 : nsIFrame* aOldFrame)
760 : {
761 0 : MOZ_ASSERT(aListID == kPrincipalList);
762 0 : mFrames.DestroyFrame(aOldFrame);
763 0 : ChildListChanged(nsIDOMMutationEvent::REMOVAL);
764 0 : }
765 :
766 : nsresult
767 0 : nsMathMLContainerFrame::AttributeChanged(int32_t aNameSpaceID,
768 : nsIAtom* aAttribute,
769 : int32_t aModType)
770 : {
771 : // XXX Since they are numerous MathML attributes that affect layout, and
772 : // we can't check all of them here, play safe by requesting a reflow.
773 : // XXXldb This should only do work for attributes that cause changes!
774 0 : PresContext()->PresShell()->
775 0 : FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
776 :
777 0 : return NS_OK;
778 : }
779 :
780 : void
781 0 : nsMathMLContainerFrame::GatherAndStoreOverflow(ReflowOutput* aMetrics)
782 : {
783 0 : mBlockStartAscent = aMetrics->BlockStartAscent();
784 :
785 : // nsIFrame::FinishAndStoreOverflow likes the overflow area to include the
786 : // frame rectangle.
787 0 : aMetrics->SetOverflowAreasToDesiredBounds();
788 :
789 0 : ComputeCustomOverflow(aMetrics->mOverflowAreas);
790 :
791 : // mBoundingMetrics does not necessarily include content of <mpadded>
792 : // elements whose mBoundingMetrics may not be representative of the true
793 : // bounds, and doesn't include the CSS2 outline rectangles of children, so
794 : // make such to include child overflow areas.
795 0 : UnionChildOverflow(aMetrics->mOverflowAreas);
796 :
797 0 : FinishAndStoreOverflow(aMetrics);
798 0 : }
799 :
800 : bool
801 0 : nsMathMLContainerFrame::ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas)
802 : {
803 : // All non-child-frame content such as nsMathMLChars (and most child-frame
804 : // content) is included in mBoundingMetrics.
805 : nsRect boundingBox(mBoundingMetrics.leftBearing,
806 0 : mBlockStartAscent - mBoundingMetrics.ascent,
807 0 : mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing,
808 0 : mBoundingMetrics.ascent + mBoundingMetrics.descent);
809 :
810 : // REVIEW: Maybe this should contribute only to visual overflow
811 : // and not scrollable?
812 0 : aOverflowAreas.UnionAllWith(boundingBox);
813 0 : return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
814 : }
815 :
816 : void
817 0 : nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
818 : nsPresContext* aPresContext,
819 : ReflowOutput& aDesiredSize,
820 : const ReflowInput& aReflowInput,
821 : nsReflowStatus& aStatus)
822 : {
823 : // Having foreign/hybrid children, e.g., from html markups, is not defined by
824 : // the MathML spec. But it can happen in practice, e.g., <html:img> allows us
825 : // to do some cool demos... or we may have a child that is an nsInlineFrame
826 : // from a generated content such as :before { content: open-quote } or
827 : // :after { content: close-quote }. Unfortunately, the other frames out-there
828 : // may expect their own invariants that are not met when we mix things.
829 : // Hence we do not claim their support, but we will nevertheless attempt to keep
830 : // them in the flow, if we can get their desired size. We observed that most
831 : // frames may be reflowed generically, but nsInlineFrames need extra care.
832 :
833 : #ifdef DEBUG
834 0 : nsInlineFrame* inlineFrame = do_QueryFrame(aChildFrame);
835 0 : NS_ASSERTION(!inlineFrame, "Inline frames should be wrapped in blocks");
836 : #endif
837 :
838 : nsContainerFrame::
839 0 : ReflowChild(aChildFrame, aPresContext, aDesiredSize, aReflowInput,
840 0 : 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
841 :
842 0 : if (aDesiredSize.BlockStartAscent() == ReflowOutput::ASK_FOR_BASELINE) {
843 : // This will be suitable for inline frames, which are wrapped in a block.
844 : nscoord ascent;
845 0 : WritingMode wm = aDesiredSize.GetWritingMode();
846 0 : if (!nsLayoutUtils::GetLastLineBaseline(wm, aChildFrame, &ascent)) {
847 : // We don't expect any other block children so just place the frame on
848 : // the baseline instead of going through DidReflow() and
849 : // GetBaseline(). This is what nsFrame::GetBaseline() will do anyway.
850 0 : aDesiredSize.SetBlockStartAscent(aDesiredSize.BSize(wm));
851 : } else {
852 0 : aDesiredSize.SetBlockStartAscent(ascent);
853 : }
854 : }
855 0 : if (IsForeignChild(aChildFrame)) {
856 : // use ComputeTightBounds API as aDesiredSize.mBoundingMetrics is not set.
857 0 : nsRect r = aChildFrame->ComputeTightBounds(aReflowInput.mRenderingContext->GetDrawTarget());
858 0 : aDesiredSize.mBoundingMetrics.leftBearing = r.x;
859 0 : aDesiredSize.mBoundingMetrics.rightBearing = r.XMost();
860 0 : aDesiredSize.mBoundingMetrics.ascent = aDesiredSize.BlockStartAscent() - r.y;
861 0 : aDesiredSize.mBoundingMetrics.descent = r.YMost() - aDesiredSize.BlockStartAscent();
862 0 : aDesiredSize.mBoundingMetrics.width = aDesiredSize.Width();
863 : }
864 0 : }
865 :
866 : void
867 0 : nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
868 : ReflowOutput& aDesiredSize,
869 : const ReflowInput& aReflowInput,
870 : nsReflowStatus& aStatus)
871 : {
872 0 : MarkInReflow();
873 0 : mPresentationData.flags &= ~NS_MATHML_ERROR;
874 0 : aDesiredSize.Width() = aDesiredSize.Height() = 0;
875 0 : aDesiredSize.SetBlockStartAscent(0);
876 0 : aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
877 :
878 : /////////////
879 : // Reflow children
880 : // Asking each child to cache its bounding metrics
881 :
882 0 : nsReflowStatus childStatus;
883 0 : nsIFrame* childFrame = mFrames.FirstChild();
884 0 : while (childFrame) {
885 : ReflowOutput childDesiredSize(aReflowInput, // ???
886 0 : aDesiredSize.mFlags);
887 0 : WritingMode wm = childFrame->GetWritingMode();
888 0 : LogicalSize availSize = aReflowInput.ComputedSize(wm);
889 0 : availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
890 : ReflowInput childReflowInput(aPresContext, aReflowInput,
891 0 : childFrame, availSize);
892 : ReflowChild(childFrame, aPresContext, childDesiredSize,
893 0 : childReflowInput, childStatus);
894 : //NS_ASSERTION(childStatus.IsComplete(), "bad status");
895 : SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
896 0 : childDesiredSize.mBoundingMetrics);
897 0 : childFrame = childFrame->GetNextSibling();
898 : }
899 :
900 : /////////////
901 : // If we are a container which is entitled to stretch its children, then we
902 : // ask our stretchy children to stretch themselves
903 :
904 : // The stretching of siblings of an embellished child is _deferred_ until
905 : // after finishing the stretching of the embellished child - bug 117652
906 :
907 0 : DrawTarget* drawTarget = aReflowInput.mRenderingContext->GetDrawTarget();
908 :
909 0 : if (!NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags) &&
910 0 : (NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ||
911 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags))) {
912 :
913 : // get the stretchy direction
914 : nsStretchDirection stretchDir =
915 0 : NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags)
916 0 : ? NS_STRETCH_DIRECTION_VERTICAL
917 0 : : NS_STRETCH_DIRECTION_HORIZONTAL;
918 :
919 : // what size should we use to stretch our stretchy children
920 : // We don't use STRETCH_CONSIDER_ACTUAL_SIZE -- because our size is not known yet
921 : // We don't use STRETCH_CONSIDER_EMBELLISHMENTS -- because we don't want to
922 : // include them in the caculations of the size of stretchy elements
923 0 : nsBoundingMetrics containerSize;
924 0 : GetPreferredStretchSize(drawTarget, 0, stretchDir, containerSize);
925 :
926 : // fire the stretch on each child
927 0 : childFrame = mFrames.FirstChild();
928 0 : while (childFrame) {
929 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
930 0 : if (mathMLFrame) {
931 : // retrieve the metrics that was stored at the previous pass
932 0 : ReflowOutput childDesiredSize(aReflowInput);
933 : GetReflowAndBoundingMetricsFor(childFrame,
934 0 : childDesiredSize, childDesiredSize.mBoundingMetrics);
935 :
936 : mathMLFrame->Stretch(drawTarget, stretchDir,
937 0 : containerSize, childDesiredSize);
938 : // store the updated metrics
939 : SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
940 0 : childDesiredSize.mBoundingMetrics);
941 : }
942 0 : childFrame = childFrame->GetNextSibling();
943 : }
944 : }
945 :
946 : /////////////
947 : // Place children now by re-adjusting the origins to align the baselines
948 0 : FinalizeReflow(drawTarget, aDesiredSize);
949 :
950 0 : aStatus.Reset();
951 0 : NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
952 0 : }
953 :
954 : static nscoord AddInterFrameSpacingToSize(ReflowOutput& aDesiredSize,
955 : nsMathMLContainerFrame* aFrame);
956 :
957 : /* virtual */ void
958 0 : nsMathMLContainerFrame::MarkIntrinsicISizesDirty()
959 : {
960 0 : mIntrinsicWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
961 0 : nsContainerFrame::MarkIntrinsicISizesDirty();
962 0 : }
963 :
964 : void
965 0 : nsMathMLContainerFrame::UpdateIntrinsicWidth(gfxContext* aRenderingContext)
966 : {
967 0 : if (mIntrinsicWidth == NS_INTRINSIC_WIDTH_UNKNOWN) {
968 0 : ReflowOutput desiredSize(GetWritingMode());
969 0 : GetIntrinsicISizeMetrics(aRenderingContext, desiredSize);
970 :
971 : // Include the additional width added by FixInterFrameSpacing to ensure
972 : // consistent width calculations.
973 0 : AddInterFrameSpacingToSize(desiredSize, this);
974 0 : mIntrinsicWidth = desiredSize.ISize(GetWritingMode());
975 : }
976 0 : }
977 :
978 : /* virtual */ nscoord
979 0 : nsMathMLContainerFrame::GetMinISize(gfxContext* aRenderingContext)
980 : {
981 : nscoord result;
982 0 : DISPLAY_MIN_WIDTH(this, result);
983 0 : UpdateIntrinsicWidth(aRenderingContext);
984 0 : result = mIntrinsicWidth;
985 0 : return result;
986 : }
987 :
988 : /* virtual */ nscoord
989 0 : nsMathMLContainerFrame::GetPrefISize(gfxContext* aRenderingContext)
990 : {
991 : nscoord result;
992 0 : DISPLAY_PREF_WIDTH(this, result);
993 0 : UpdateIntrinsicWidth(aRenderingContext);
994 0 : result = mIntrinsicWidth;
995 0 : return result;
996 : }
997 :
998 : /* virtual */ void
999 0 : nsMathMLContainerFrame::GetIntrinsicISizeMetrics(gfxContext* aRenderingContext,
1000 : ReflowOutput& aDesiredSize)
1001 : {
1002 : // Get child widths
1003 0 : nsIFrame* childFrame = mFrames.FirstChild();
1004 0 : while (childFrame) {
1005 0 : ReflowOutput childDesiredSize(GetWritingMode()); // ???
1006 :
1007 0 : nsMathMLContainerFrame* containerFrame = do_QueryFrame(childFrame);
1008 0 : if (containerFrame) {
1009 : containerFrame->GetIntrinsicISizeMetrics(aRenderingContext,
1010 0 : childDesiredSize);
1011 : } else {
1012 : // XXX This includes margin while Reflow currently doesn't consider
1013 : // margin, so we may end up with too much space, but, with stretchy
1014 : // characters, this is an approximation anyway.
1015 : nscoord width =
1016 : nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
1017 0 : nsLayoutUtils::PREF_ISIZE);
1018 :
1019 0 : childDesiredSize.Width() = width;
1020 0 : childDesiredSize.mBoundingMetrics.width = width;
1021 0 : childDesiredSize.mBoundingMetrics.leftBearing = 0;
1022 0 : childDesiredSize.mBoundingMetrics.rightBearing = width;
1023 :
1024 : nscoord x, xMost;
1025 0 : if (NS_SUCCEEDED(childFrame->GetPrefWidthTightBounds(aRenderingContext,
1026 : &x, &xMost))) {
1027 0 : childDesiredSize.mBoundingMetrics.leftBearing = x;
1028 0 : childDesiredSize.mBoundingMetrics.rightBearing = xMost;
1029 : }
1030 : }
1031 :
1032 : SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
1033 0 : childDesiredSize.mBoundingMetrics);
1034 :
1035 0 : childFrame = childFrame->GetNextSibling();
1036 : }
1037 :
1038 : // Measure
1039 0 : nsresult rv = MeasureForWidth(aRenderingContext->GetDrawTarget(), aDesiredSize);
1040 0 : if (NS_FAILED(rv)) {
1041 0 : ReflowError(aRenderingContext->GetDrawTarget(), aDesiredSize);
1042 : }
1043 :
1044 0 : ClearSavedChildMetrics();
1045 0 : }
1046 :
1047 : /* virtual */ nsresult
1048 0 : nsMathMLContainerFrame::MeasureForWidth(DrawTarget* aDrawTarget,
1049 : ReflowOutput& aDesiredSize)
1050 : {
1051 0 : return Place(aDrawTarget, false, aDesiredSize);
1052 : }
1053 :
1054 :
1055 : // see spacing table in Chapter 18, TeXBook (p.170)
1056 : // Our table isn't quite identical to TeX because operators have
1057 : // built-in values for lspace & rspace in the Operator Dictionary.
1058 : static int32_t kInterFrameSpacingTable[eMathMLFrameType_COUNT][eMathMLFrameType_COUNT] =
1059 : {
1060 : // in units of muspace.
1061 : // upper half of the byte is set if the
1062 : // spacing is not to be used for scriptlevel > 0
1063 :
1064 : /* Ord OpOrd OpInv OpUsr Inner Italic Upright */
1065 : /*Ord */ {0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00},
1066 : /*OpOrd*/ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1067 : /*OpInv*/ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1068 : /*OpUsr*/ {0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01},
1069 : /*Inner*/ {0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01},
1070 : /*Italic*/ {0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01},
1071 : /*Upright*/ {0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00}
1072 : };
1073 :
1074 : #define GET_INTERSPACE(scriptlevel_, frametype1_, frametype2_, space_) \
1075 : /* no space if there is a frame that we know nothing about */ \
1076 : if (frametype1_ == eMathMLFrameType_UNKNOWN || \
1077 : frametype2_ == eMathMLFrameType_UNKNOWN) \
1078 : space_ = 0; \
1079 : else { \
1080 : space_ = kInterFrameSpacingTable[frametype1_][frametype2_]; \
1081 : space_ = (scriptlevel_ > 0 && (space_ & 0xF0)) \
1082 : ? 0 /* spacing is disabled */ \
1083 : : space_ & 0x0F; \
1084 : } \
1085 :
1086 : // This function computes the inter-space between two frames. However,
1087 : // since invisible operators need special treatment, the inter-space may
1088 : // be delayed when an invisible operator is encountered. In this case,
1089 : // the function will carry the inter-space forward until it is determined
1090 : // that it can be applied properly (i.e., until we encounter a visible
1091 : // frame where to decide whether to accept or reject the inter-space).
1092 : // aFromFrameType: remembers the frame when the carry-forward initiated.
1093 : // aCarrySpace: keeps track of the inter-space that is delayed.
1094 : // @returns: current inter-space (which is 0 when the true inter-space is
1095 : // delayed -- and thus has no effect since the frame is invisible anyway).
1096 : static nscoord
1097 0 : GetInterFrameSpacing(int32_t aScriptLevel,
1098 : eMathMLFrameType aFirstFrameType,
1099 : eMathMLFrameType aSecondFrameType,
1100 : eMathMLFrameType* aFromFrameType, // IN/OUT
1101 : int32_t* aCarrySpace) // IN/OUT
1102 : {
1103 0 : eMathMLFrameType firstType = aFirstFrameType;
1104 0 : eMathMLFrameType secondType = aSecondFrameType;
1105 :
1106 : int32_t space;
1107 0 : GET_INTERSPACE(aScriptLevel, firstType, secondType, space);
1108 :
1109 : // feedback control to avoid the inter-space to be added when not necessary
1110 0 : if (secondType == eMathMLFrameType_OperatorInvisible) {
1111 : // see if we should start to carry the space forward until we
1112 : // encounter a visible frame
1113 0 : if (*aFromFrameType == eMathMLFrameType_UNKNOWN) {
1114 0 : *aFromFrameType = firstType;
1115 0 : *aCarrySpace = space;
1116 : }
1117 : // keep carrying *aCarrySpace forward, while returning 0 for this stage
1118 0 : space = 0;
1119 : }
1120 0 : else if (*aFromFrameType != eMathMLFrameType_UNKNOWN) {
1121 : // no carry-forward anymore, get the real inter-space between
1122 : // the two frames of interest
1123 :
1124 0 : firstType = *aFromFrameType;
1125 :
1126 : // But... the invisible operator that we encountered earlier could
1127 : // be sitting between italic and upright identifiers, e.g.,
1128 : //
1129 : // 1. <mi>sin</mi> <mo>⁡</mo> <mi>x</mi>
1130 : // 2. <mi>x</mi> <mo>&InvisibileTime;</mo> <mi>sin</mi>
1131 : //
1132 : // the trick to get the inter-space in either situation
1133 : // is to promote "<mi>sin</mi><mo>⁡</mo>" and
1134 : // "<mo>&InvisibileTime;</mo><mi>sin</mi>" to user-defined operators...
1135 0 : if (firstType == eMathMLFrameType_UprightIdentifier) {
1136 0 : firstType = eMathMLFrameType_OperatorUserDefined;
1137 : }
1138 0 : else if (secondType == eMathMLFrameType_UprightIdentifier) {
1139 0 : secondType = eMathMLFrameType_OperatorUserDefined;
1140 : }
1141 :
1142 0 : GET_INTERSPACE(aScriptLevel, firstType, secondType, space);
1143 :
1144 : // Now, we have two values: the computed space and the space that
1145 : // has been carried forward until now. Which value do we pick?
1146 : // If the second type is an operator (e.g., fence), it already has
1147 : // built-in lspace & rspace, so we let them win. Otherwise we pick
1148 : // the max between the two values that we have.
1149 0 : if (secondType != eMathMLFrameType_OperatorOrdinary &&
1150 0 : space < *aCarrySpace)
1151 0 : space = *aCarrySpace;
1152 :
1153 : // reset everything now that the carry-forward is done
1154 0 : *aFromFrameType = eMathMLFrameType_UNKNOWN;
1155 0 : *aCarrySpace = 0;
1156 : }
1157 :
1158 0 : return space;
1159 : }
1160 :
1161 0 : static nscoord GetThinSpace(const nsStyleFont* aStyleFont)
1162 : {
1163 0 : return NSToCoordRound(float(aStyleFont->mFont.size)*float(3) / float(18));
1164 : }
1165 :
1166 0 : class nsMathMLContainerFrame::RowChildFrameIterator {
1167 : public:
1168 0 : explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame) :
1169 : mParentFrame(aParentFrame),
1170 : mReflowOutput(aParentFrame->GetWritingMode()),
1171 : mX(0),
1172 : mCarrySpace(0),
1173 : mFromFrameType(eMathMLFrameType_UNKNOWN),
1174 0 : mRTL(aParentFrame->StyleVisibility()->mDirection)
1175 : {
1176 0 : if (!mRTL) {
1177 0 : mChildFrame = aParentFrame->mFrames.FirstChild();
1178 : } else {
1179 0 : mChildFrame = aParentFrame->mFrames.LastChild();
1180 : }
1181 :
1182 0 : if (!mChildFrame)
1183 0 : return;
1184 :
1185 0 : InitMetricsForChild();
1186 : }
1187 :
1188 0 : RowChildFrameIterator& operator++()
1189 : {
1190 : // add child size + italic correction
1191 0 : mX += mReflowOutput.mBoundingMetrics.width + mItalicCorrection;
1192 :
1193 0 : if (!mRTL) {
1194 0 : mChildFrame = mChildFrame->GetNextSibling();
1195 : } else {
1196 0 : mChildFrame = mChildFrame->GetPrevSibling();
1197 : }
1198 :
1199 0 : if (!mChildFrame)
1200 0 : return *this;
1201 :
1202 0 : eMathMLFrameType prevFrameType = mChildFrameType;
1203 0 : InitMetricsForChild();
1204 :
1205 : // add inter frame spacing
1206 0 : const nsStyleFont* font = mParentFrame->StyleFont();
1207 : nscoord space =
1208 0 : GetInterFrameSpacing(font->mScriptLevel,
1209 : prevFrameType, mChildFrameType,
1210 0 : &mFromFrameType, &mCarrySpace);
1211 0 : mX += space * GetThinSpace(font);
1212 0 : return *this;
1213 : }
1214 :
1215 0 : nsIFrame* Frame() const { return mChildFrame; }
1216 0 : nscoord X() const { return mX; }
1217 0 : const ReflowOutput& GetReflowOutput() const { return mReflowOutput; }
1218 0 : nscoord Ascent() const { return mReflowOutput.BlockStartAscent(); }
1219 0 : nscoord Descent() const { return mReflowOutput.Height() - mReflowOutput.BlockStartAscent(); }
1220 0 : const nsBoundingMetrics& BoundingMetrics() const {
1221 0 : return mReflowOutput.mBoundingMetrics;
1222 : }
1223 :
1224 : private:
1225 : const nsMathMLContainerFrame* mParentFrame;
1226 : nsIFrame* mChildFrame;
1227 : ReflowOutput mReflowOutput;
1228 : nscoord mX;
1229 :
1230 : nscoord mItalicCorrection;
1231 : eMathMLFrameType mChildFrameType;
1232 : int32_t mCarrySpace;
1233 : eMathMLFrameType mFromFrameType;
1234 :
1235 : bool mRTL;
1236 :
1237 0 : void InitMetricsForChild()
1238 : {
1239 0 : GetReflowAndBoundingMetricsFor(mChildFrame, mReflowOutput, mReflowOutput.mBoundingMetrics,
1240 0 : &mChildFrameType);
1241 : nscoord leftCorrection, rightCorrection;
1242 0 : GetItalicCorrection(mReflowOutput.mBoundingMetrics,
1243 0 : leftCorrection, rightCorrection);
1244 0 : if (!mChildFrame->GetPrevSibling() &&
1245 0 : mParentFrame->GetContent()->IsMathMLElement(nsGkAtoms::msqrt_)) {
1246 : // Remove leading correction in <msqrt> because the sqrt glyph itself is
1247 : // there first.
1248 0 : if (!mRTL) {
1249 0 : leftCorrection = 0;
1250 : } else {
1251 0 : rightCorrection = 0;
1252 : }
1253 : }
1254 : // add left correction -- this fixes the problem of the italic 'f'
1255 : // e.g., <mo>q</mo> <mi>f</mi> <mo>I</mo>
1256 0 : mX += leftCorrection;
1257 0 : mItalicCorrection = rightCorrection;
1258 0 : }
1259 : };
1260 :
1261 : /* virtual */ nsresult
1262 0 : nsMathMLContainerFrame::Place(DrawTarget* aDrawTarget,
1263 : bool aPlaceOrigin,
1264 : ReflowOutput& aDesiredSize)
1265 : {
1266 : // This is needed in case this frame is empty (i.e., no child frames)
1267 0 : mBoundingMetrics = nsBoundingMetrics();
1268 :
1269 0 : RowChildFrameIterator child(this);
1270 0 : nscoord ascent = 0, descent = 0;
1271 0 : while (child.Frame()) {
1272 0 : if (descent < child.Descent())
1273 0 : descent = child.Descent();
1274 0 : if (ascent < child.Ascent())
1275 0 : ascent = child.Ascent();
1276 : // add the child size
1277 0 : mBoundingMetrics.width = child.X();
1278 0 : mBoundingMetrics += child.BoundingMetrics();
1279 0 : ++child;
1280 : }
1281 : // Add the italic correction at the end (including the last child).
1282 : // This gives a nice gap between math and non-math frames, and still
1283 : // gives the same math inter-spacing in case this frame connects to
1284 : // another math frame
1285 0 : mBoundingMetrics.width = child.X();
1286 :
1287 0 : aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
1288 0 : aDesiredSize.Height() = ascent + descent;
1289 0 : aDesiredSize.SetBlockStartAscent(ascent);
1290 0 : aDesiredSize.mBoundingMetrics = mBoundingMetrics;
1291 :
1292 0 : mReference.x = 0;
1293 0 : mReference.y = aDesiredSize.BlockStartAscent();
1294 :
1295 : //////////////////
1296 : // Place Children
1297 :
1298 0 : if (aPlaceOrigin) {
1299 0 : PositionRowChildFrames(0, aDesiredSize.BlockStartAscent());
1300 : }
1301 :
1302 0 : return NS_OK;
1303 : }
1304 :
1305 : void
1306 0 : nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX,
1307 : nscoord aBaseline)
1308 : {
1309 0 : RowChildFrameIterator child(this);
1310 0 : while (child.Frame()) {
1311 0 : nscoord dx = aOffsetX + child.X();
1312 0 : nscoord dy = aBaseline - child.Ascent();
1313 0 : FinishReflowChild(child.Frame(), PresContext(), child.GetReflowOutput(),
1314 0 : nullptr, dx, dy, 0);
1315 0 : ++child;
1316 : }
1317 0 : }
1318 :
1319 : // helpers to fix the inter-spacing when <math> is the only parent
1320 : // e.g., it fixes <math> <mi>f</mi> <mo>q</mo> <mi>f</mi> <mo>I</mo> </math>
1321 :
1322 : static nscoord
1323 0 : GetInterFrameSpacingFor(int32_t aScriptLevel,
1324 : nsIFrame* aParentFrame,
1325 : nsIFrame* aChildFrame)
1326 : {
1327 0 : nsIFrame* childFrame = aParentFrame->PrincipalChildList().FirstChild();
1328 0 : if (!childFrame || aChildFrame == childFrame)
1329 0 : return 0;
1330 :
1331 0 : int32_t carrySpace = 0;
1332 0 : eMathMLFrameType fromFrameType = eMathMLFrameType_UNKNOWN;
1333 0 : eMathMLFrameType prevFrameType = eMathMLFrameType_UNKNOWN;
1334 0 : eMathMLFrameType childFrameType = nsMathMLFrame::GetMathMLFrameTypeFor(childFrame);
1335 0 : childFrame = childFrame->GetNextSibling();
1336 0 : while (childFrame) {
1337 0 : prevFrameType = childFrameType;
1338 0 : childFrameType = nsMathMLFrame::GetMathMLFrameTypeFor(childFrame);
1339 : nscoord space = GetInterFrameSpacing(aScriptLevel,
1340 0 : prevFrameType, childFrameType, &fromFrameType, &carrySpace);
1341 0 : if (aChildFrame == childFrame) {
1342 : // get thinspace
1343 0 : nsStyleContext* parentContext = aParentFrame->StyleContext();
1344 0 : nscoord thinSpace = GetThinSpace(parentContext->StyleFont());
1345 : // we are done
1346 0 : return space * thinSpace;
1347 : }
1348 0 : childFrame = childFrame->GetNextSibling();
1349 : }
1350 :
1351 0 : NS_NOTREACHED("child not in the childlist of its parent");
1352 0 : return 0;
1353 : }
1354 :
1355 : static nscoord
1356 0 : AddInterFrameSpacingToSize(ReflowOutput& aDesiredSize,
1357 : nsMathMLContainerFrame* aFrame)
1358 : {
1359 0 : nscoord gap = 0;
1360 0 : nsIFrame* parent = aFrame->GetParent();
1361 0 : nsIContent* parentContent = parent->GetContent();
1362 0 : if (MOZ_UNLIKELY(!parentContent)) {
1363 0 : return 0;
1364 : }
1365 0 : if (parentContent->IsAnyOfMathMLElements(nsGkAtoms::math,
1366 : nsGkAtoms::mtd_)) {
1367 0 : gap = GetInterFrameSpacingFor(aFrame->StyleFont()->mScriptLevel,
1368 0 : parent, aFrame);
1369 : // add our own italic correction
1370 0 : nscoord leftCorrection = 0, italicCorrection = 0;
1371 0 : aFrame->GetItalicCorrection(aDesiredSize.mBoundingMetrics,
1372 0 : leftCorrection, italicCorrection);
1373 0 : gap += leftCorrection;
1374 0 : if (gap) {
1375 0 : aDesiredSize.mBoundingMetrics.leftBearing += gap;
1376 0 : aDesiredSize.mBoundingMetrics.rightBearing += gap;
1377 0 : aDesiredSize.mBoundingMetrics.width += gap;
1378 0 : aDesiredSize.Width() += gap;
1379 : }
1380 0 : aDesiredSize.mBoundingMetrics.width += italicCorrection;
1381 0 : aDesiredSize.Width() += italicCorrection;
1382 : }
1383 0 : return gap;
1384 : }
1385 :
1386 : nscoord
1387 0 : nsMathMLContainerFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize)
1388 : {
1389 0 : nscoord gap = 0;
1390 0 : gap = AddInterFrameSpacingToSize(aDesiredSize, this);
1391 0 : if (gap) {
1392 : // Shift our children to account for the correction
1393 0 : nsIFrame* childFrame = mFrames.FirstChild();
1394 0 : while (childFrame) {
1395 0 : childFrame->SetPosition(childFrame->GetPosition() + nsPoint(gap, 0));
1396 0 : childFrame = childFrame->GetNextSibling();
1397 : }
1398 : }
1399 0 : return gap;
1400 : }
1401 :
1402 : /* static */ void
1403 0 : nsMathMLContainerFrame::DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop)
1404 :
1405 : {
1406 0 : if (MOZ_UNLIKELY(!aFirst))
1407 0 : return;
1408 :
1409 0 : for (nsIFrame* frame = aFirst;
1410 0 : frame != aStop;
1411 : frame = frame->GetNextSibling()) {
1412 0 : NS_ASSERTION(frame, "aStop isn't a sibling");
1413 0 : if (frame->GetStateBits() & NS_FRAME_IN_REFLOW) {
1414 : // finish off principal descendants, too
1415 0 : nsIFrame* grandchild = frame->PrincipalChildList().FirstChild();
1416 0 : if (grandchild)
1417 0 : DidReflowChildren(grandchild, nullptr);
1418 :
1419 0 : frame->DidReflow(frame->PresContext(), nullptr,
1420 0 : nsDidReflowStatus::FINISHED);
1421 : }
1422 : }
1423 : }
1424 :
1425 : // helper used by mstyle, mphantom, mpadded and mrow in their implementations
1426 : // of TransmitAutomaticData().
1427 : nsresult
1428 0 : nsMathMLContainerFrame::TransmitAutomaticDataForMrowLikeElement()
1429 : {
1430 : //
1431 : // One loop to check both conditions below:
1432 : //
1433 : // 1) whether all the children of the mrow-like element are space-like.
1434 : //
1435 : // The REC defines the following elements to be "space-like":
1436 : // * an mstyle, mphantom, or mpadded element, all of whose direct
1437 : // sub-expressions are space-like;
1438 : // * an mrow all of whose direct sub-expressions are space-like.
1439 : //
1440 : // 2) whether all but one child of the mrow-like element are space-like and
1441 : // this non-space-like child is an embellished operator.
1442 : //
1443 : // The REC defines the following elements to be embellished operators:
1444 : // * one of the elements mstyle, mphantom, or mpadded, such that an mrow
1445 : // containing the same arguments would be an embellished operator;
1446 : // * an mrow whose arguments consist (in any order) of one embellished
1447 : // operator and zero or more space-like elements.
1448 : //
1449 : nsIFrame *childFrame, *baseFrame;
1450 0 : bool embellishedOpFound = false;
1451 0 : nsEmbellishData embellishData;
1452 :
1453 0 : for (childFrame = PrincipalChildList().FirstChild();
1454 0 : childFrame;
1455 : childFrame = childFrame->GetNextSibling()) {
1456 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
1457 0 : if (!mathMLFrame) break;
1458 0 : if (!mathMLFrame->IsSpaceLike()) {
1459 0 : if (embellishedOpFound) break;
1460 0 : baseFrame = childFrame;
1461 0 : GetEmbellishDataFrom(baseFrame, embellishData);
1462 0 : if (!NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags)) break;
1463 0 : embellishedOpFound = true;
1464 : }
1465 : }
1466 :
1467 0 : if (!childFrame) {
1468 : // we successfully went to the end of the loop. This means that one of
1469 : // condition 1) or 2) holds.
1470 0 : if (!embellishedOpFound) {
1471 : // the mrow-like element is space-like.
1472 0 : mPresentationData.flags |= NS_MATHML_SPACE_LIKE;
1473 : } else {
1474 : // the mrow-like element is an embellished operator.
1475 : // let the state of the embellished operator found bubble to us.
1476 0 : mPresentationData.baseFrame = baseFrame;
1477 0 : mEmbellishData = embellishData;
1478 : }
1479 : }
1480 :
1481 0 : if (childFrame || !embellishedOpFound) {
1482 : // The element is not embellished operator
1483 0 : mPresentationData.baseFrame = nullptr;
1484 0 : mEmbellishData.flags = 0;
1485 0 : mEmbellishData.coreFrame = nullptr;
1486 0 : mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
1487 0 : mEmbellishData.leadingSpace = 0;
1488 0 : mEmbellishData.trailingSpace = 0;
1489 : }
1490 :
1491 0 : if (childFrame || embellishedOpFound) {
1492 : // The element is not space-like
1493 0 : mPresentationData.flags &= ~NS_MATHML_SPACE_LIKE;
1494 : }
1495 :
1496 0 : return NS_OK;
1497 : }
1498 :
1499 : /*static*/ void
1500 0 : nsMathMLContainerFrame::PropagateFrameFlagFor(nsIFrame* aFrame,
1501 : nsFrameState aFlags)
1502 : {
1503 0 : if (!aFrame || !aFlags)
1504 0 : return;
1505 :
1506 0 : aFrame->AddStateBits(aFlags);
1507 0 : for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
1508 0 : PropagateFrameFlagFor(childFrame, aFlags);
1509 : }
1510 : }
1511 :
1512 : nsresult
1513 0 : nsMathMLContainerFrame::ReportErrorToConsole(const char* errorMsgId,
1514 : const char16_t** aParams,
1515 : uint32_t aParamCount)
1516 : {
1517 0 : return nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
1518 0 : NS_LITERAL_CSTRING("Layout: MathML"), mContent->OwnerDoc(),
1519 : nsContentUtils::eMATHML_PROPERTIES,
1520 0 : errorMsgId, aParams, aParamCount);
1521 : }
1522 :
1523 : nsresult
1524 0 : nsMathMLContainerFrame::ReportParseError(const char16_t* aAttribute,
1525 : const char16_t* aValue)
1526 : {
1527 : const char16_t* argv[] =
1528 0 : { aValue, aAttribute, mContent->NodeInfo()->NameAtom()->GetUTF16String() };
1529 0 : return ReportErrorToConsole("AttributeParsingError", argv, 3);
1530 : }
1531 :
1532 : nsresult
1533 0 : nsMathMLContainerFrame::ReportChildCountError()
1534 : {
1535 0 : const char16_t* arg = mContent->NodeInfo()->NameAtom()->GetUTF16String();
1536 0 : return ReportErrorToConsole("ChildCountIncorrect", &arg, 1);
1537 : }
1538 :
1539 : nsresult
1540 0 : nsMathMLContainerFrame::ReportInvalidChildError(nsIAtom* aChildTag)
1541 : {
1542 : const char16_t* argv[] =
1543 0 : { aChildTag->GetUTF16String(),
1544 0 : mContent->NodeInfo()->NameAtom()->GetUTF16String() };
1545 0 : return ReportErrorToConsole("InvalidChild", argv, 2);
1546 : }
1547 :
1548 : //==========================
1549 :
1550 : nsContainerFrame*
1551 0 : NS_NewMathMLmathBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
1552 : {
1553 0 : return new (aPresShell) nsMathMLmathBlockFrame(aContext);
1554 : }
1555 :
1556 0 : NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmathBlockFrame)
1557 :
1558 0 : NS_QUERYFRAME_HEAD(nsMathMLmathBlockFrame)
1559 0 : NS_QUERYFRAME_ENTRY(nsMathMLmathBlockFrame)
1560 0 : NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
1561 :
1562 : nsContainerFrame*
1563 0 : NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
1564 : {
1565 0 : return new (aPresShell) nsMathMLmathInlineFrame(aContext);
1566 : }
1567 :
1568 0 : NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmathInlineFrame)
1569 :
1570 0 : NS_QUERYFRAME_HEAD(nsMathMLmathInlineFrame)
1571 0 : NS_QUERYFRAME_ENTRY(nsIMathMLFrame)
1572 0 : NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame)
|