1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla MathML Project.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * The University Of Queensland.
19 : * Portions created by the Initial Developer are Copyright (C) 1999
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Roger B. Sidje <rbs@maths.uq.edu.au>
24 : * Frederic Wang <fred.wang@free.fr>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsINameSpaceManager.h"
41 : #include "nsMathMLFrame.h"
42 : #include "nsMathMLChar.h"
43 : #include "nsCSSPseudoElements.h"
44 :
45 : // used to map attributes into CSS rules
46 : #include "nsStyleSet.h"
47 : #include "nsAutoPtr.h"
48 : #include "nsDisplayList.h"
49 : #include "nsRenderingContext.h"
50 :
51 : eMathMLFrameType
52 0 : nsMathMLFrame::GetMathMLFrameType()
53 : {
54 : // see if it is an embellished operator (mapped to 'Op' in TeX)
55 0 : if (mEmbellishData.coreFrame)
56 0 : return GetMathMLFrameTypeFor(mEmbellishData.coreFrame);
57 :
58 : // if it has a prescribed base, fetch the type from there
59 0 : if (mPresentationData.baseFrame)
60 0 : return GetMathMLFrameTypeFor(mPresentationData.baseFrame);
61 :
62 : // everything else is treated as ordinary (mapped to 'Ord' in TeX)
63 0 : return eMathMLFrameType_Ordinary;
64 : }
65 :
66 : // snippet of code used by <mstyle>, <mtable> and <math> which are the only
67 : // three tags where the displaystyle attribute is allowed by the spec.
68 : /* static */ void
69 0 : nsMathMLFrame::FindAttrDisplaystyle(nsIContent* aContent,
70 : nsPresentationData& aPresentationData)
71 : {
72 0 : NS_ASSERTION(aContent->Tag() == nsGkAtoms::mstyle_ ||
73 : aContent->Tag() == nsGkAtoms::mtable_ ||
74 : aContent->Tag() == nsGkAtoms::math, "bad caller");
75 : static nsIContent::AttrValuesArray strings[] =
76 : {&nsGkAtoms::_false, &nsGkAtoms::_true, nsnull};
77 : // see if the explicit displaystyle attribute is there
78 0 : switch (aContent->FindAttrValueIn(kNameSpaceID_None,
79 0 : nsGkAtoms::displaystyle_, strings, eCaseMatters)) {
80 : case 0:
81 0 : aPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE;
82 0 : aPresentationData.flags |= NS_MATHML_EXPLICIT_DISPLAYSTYLE;
83 0 : break;
84 : case 1:
85 0 : aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
86 0 : aPresentationData.flags |= NS_MATHML_EXPLICIT_DISPLAYSTYLE;
87 0 : break;
88 : }
89 : // no reset if the attr isn't found. so be sure to call it on inherited flags
90 0 : }
91 :
92 : // snippet of code used by the tags where the dir attribute is allowed.
93 : /* static */ void
94 0 : nsMathMLFrame::FindAttrDirectionality(nsIContent* aContent,
95 : nsPresentationData& aPresentationData)
96 : {
97 0 : NS_ASSERTION(aContent->Tag() == nsGkAtoms::math ||
98 : aContent->Tag() == nsGkAtoms::mrow_ ||
99 : aContent->Tag() == nsGkAtoms::mstyle_ ||
100 : aContent->Tag() == nsGkAtoms::mi_ ||
101 : aContent->Tag() == nsGkAtoms::mn_ ||
102 : aContent->Tag() == nsGkAtoms::mo_ ||
103 : aContent->Tag() == nsGkAtoms::mtext_ ||
104 : aContent->Tag() == nsGkAtoms::ms_, "bad caller");
105 :
106 : static nsIContent::AttrValuesArray strings[] =
107 : {&nsGkAtoms::ltr, &nsGkAtoms::rtl, nsnull};
108 :
109 : // see if the explicit dir attribute is there
110 0 : switch (aContent->FindAttrValueIn(kNameSpaceID_None,
111 0 : nsGkAtoms::dir, strings, eCaseMatters))
112 : {
113 : case 0:
114 0 : aPresentationData.flags &= ~NS_MATHML_RTL;
115 0 : break;
116 : case 1:
117 0 : aPresentationData.flags |= NS_MATHML_RTL;
118 0 : break;
119 : }
120 : // no reset if the attr isn't found. so be sure to call it on inherited flags
121 0 : }
122 :
123 : NS_IMETHODIMP
124 0 : nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent)
125 : {
126 0 : mEmbellishData.flags = 0;
127 0 : mEmbellishData.coreFrame = nsnull;
128 0 : mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
129 0 : mEmbellishData.leadingSpace = 0;
130 0 : mEmbellishData.trailingSpace = 0;
131 :
132 0 : mPresentationData.flags = 0;
133 0 : mPresentationData.baseFrame = nsnull;
134 0 : mPresentationData.mstyle = nsnull;
135 :
136 : // by default, just inherit the display of our parent
137 0 : nsPresentationData parentData;
138 0 : GetPresentationDataFrom(aParent, parentData);
139 0 : mPresentationData.mstyle = parentData.mstyle;
140 0 : if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) {
141 0 : mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
142 : }
143 0 : if (NS_MATHML_IS_RTL(parentData.flags)) {
144 0 : mPresentationData.flags |= NS_MATHML_RTL;
145 : }
146 :
147 : #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
148 : mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
149 : #endif
150 :
151 0 : return NS_OK;
152 : }
153 :
154 : NS_IMETHODIMP
155 0 : nsMathMLFrame::UpdatePresentationData(PRUint32 aFlagsValues,
156 : PRUint32 aWhichFlags)
157 : {
158 0 : NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags) ||
159 : NS_MATHML_IS_COMPRESSED(aWhichFlags),
160 : "aWhichFlags should only be displaystyle or compression flag");
161 :
162 : // update flags that are relevant to this call
163 0 : if (NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags)) {
164 : // updating the displaystyle flag is allowed
165 0 : if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
166 0 : mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
167 : }
168 : else {
169 0 : mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE;
170 : }
171 : }
172 0 : if (NS_MATHML_IS_COMPRESSED(aWhichFlags)) {
173 : // updating the compression flag is allowed
174 0 : if (NS_MATHML_IS_COMPRESSED(aFlagsValues)) {
175 : // 'compressed' means 'prime' style in App. G, TeXbook
176 0 : mPresentationData.flags |= NS_MATHML_COMPRESSED;
177 : }
178 : // no else. the flag is sticky. it retains its value once it is set
179 : }
180 0 : return NS_OK;
181 : }
182 :
183 : // Helper to give a style context suitable for doing the stretching of
184 : // a MathMLChar. Frame classes that use this should ensure that the
185 : // extra leaf style contexts given to the MathMLChars are accessible to
186 : // the Style System via the Get/Set AdditionalStyleContext() APIs.
187 : /* static */ void
188 0 : nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext* aPresContext,
189 : nsIContent* aContent,
190 : nsStyleContext* aParentStyleContext,
191 : nsMathMLChar* aMathMLChar,
192 : bool aIsMutableChar)
193 : {
194 : nsCSSPseudoElements::Type pseudoType = (aIsMutableChar) ?
195 : nsCSSPseudoElements::ePseudo_mozMathStretchy :
196 0 : nsCSSPseudoElements::ePseudo_mozMathAnonymous; // savings
197 0 : nsRefPtr<nsStyleContext> newStyleContext;
198 : newStyleContext = aPresContext->StyleSet()->
199 : ResolvePseudoElementStyle(aContent->AsElement(), pseudoType,
200 0 : aParentStyleContext);
201 :
202 0 : if (newStyleContext)
203 0 : aMathMLChar->SetStyleContext(newStyleContext);
204 0 : }
205 :
206 : /* static */ void
207 0 : nsMathMLFrame::GetEmbellishDataFrom(nsIFrame* aFrame,
208 : nsEmbellishData& aEmbellishData)
209 : {
210 : // initialize OUT params
211 0 : aEmbellishData.flags = 0;
212 0 : aEmbellishData.coreFrame = nsnull;
213 0 : aEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
214 0 : aEmbellishData.leadingSpace = 0;
215 0 : aEmbellishData.trailingSpace = 0;
216 :
217 0 : if (aFrame && aFrame->IsFrameOfType(nsIFrame::eMathML)) {
218 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
219 0 : if (mathMLFrame) {
220 0 : mathMLFrame->GetEmbellishData(aEmbellishData);
221 : }
222 : }
223 0 : }
224 :
225 : // helper to get the presentation data of a frame, by possibly walking up
226 : // the frame hierarchy if we happen to be surrounded by non-MathML frames.
227 : /* static */ void
228 0 : nsMathMLFrame::GetPresentationDataFrom(nsIFrame* aFrame,
229 : nsPresentationData& aPresentationData,
230 : bool aClimbTree)
231 : {
232 : // initialize OUT params
233 0 : aPresentationData.flags = 0;
234 0 : aPresentationData.baseFrame = nsnull;
235 0 : aPresentationData.mstyle = nsnull;
236 :
237 0 : nsIFrame* frame = aFrame;
238 0 : while (frame) {
239 0 : if (frame->IsFrameOfType(nsIFrame::eMathML)) {
240 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(frame);
241 0 : if (mathMLFrame) {
242 0 : mathMLFrame->GetPresentationData(aPresentationData);
243 0 : break;
244 : }
245 : }
246 : // stop if the caller doesn't want to lookup beyond the frame
247 0 : if (!aClimbTree) {
248 0 : break;
249 : }
250 : // stop if we reach the root <math> tag
251 0 : nsIContent* content = frame->GetContent();
252 0 : NS_ASSERTION(content || !frame->GetParent(), // no assert for the root
253 : "dangling frame without a content node");
254 0 : if (!content)
255 0 : break;
256 :
257 0 : if (content->Tag() == nsGkAtoms::math) {
258 0 : const nsStyleDisplay* display = frame->GetStyleDisplay();
259 0 : if (display->mDisplay == NS_STYLE_DISPLAY_BLOCK) {
260 0 : aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
261 : }
262 0 : FindAttrDisplaystyle(content, aPresentationData);
263 0 : FindAttrDirectionality(content, aPresentationData);
264 0 : aPresentationData.mstyle = frame->GetFirstContinuation();
265 0 : break;
266 : }
267 0 : frame = frame->GetParent();
268 : }
269 0 : NS_WARN_IF_FALSE(frame && frame->GetContent(),
270 : "bad MathML markup - could not find the top <math> element");
271 0 : }
272 :
273 : // helper to get an attribute from the content or the surrounding <mstyle> hierarchy
274 : /* static */ bool
275 0 : nsMathMLFrame::GetAttribute(nsIContent* aContent,
276 : nsIFrame* aMathMLmstyleFrame,
277 : nsIAtom* aAttributeAtom,
278 : nsString& aValue)
279 : {
280 : // see if we can get the attribute from the content
281 0 : if (aContent && aContent->GetAttr(kNameSpaceID_None, aAttributeAtom,
282 0 : aValue)) {
283 0 : return true;
284 : }
285 :
286 : // see if we can get the attribute from the mstyle frame
287 0 : if (!aMathMLmstyleFrame) {
288 0 : return false;
289 : }
290 :
291 0 : nsIFrame* mstyleParent = aMathMLmstyleFrame->GetParent();
292 :
293 0 : nsPresentationData mstyleParentData;
294 0 : mstyleParentData.mstyle = nsnull;
295 :
296 0 : if (mstyleParent) {
297 0 : nsIMathMLFrame* mathMLFrame = do_QueryFrame(mstyleParent);
298 0 : if (mathMLFrame) {
299 0 : mathMLFrame->GetPresentationData(mstyleParentData);
300 : }
301 : }
302 :
303 : // recurse all the way up into the <mstyle> hierarchy
304 : return GetAttribute(aMathMLmstyleFrame->GetContent(),
305 0 : mstyleParentData.mstyle, aAttributeAtom, aValue);
306 : }
307 :
308 : /* static */ void
309 0 : nsMathMLFrame::GetRuleThickness(nsRenderingContext& aRenderingContext,
310 : nsFontMetrics* aFontMetrics,
311 : nscoord& aRuleThickness)
312 : {
313 : // get the bounding metrics of the overbar char, the rendering context
314 : // is assumed to have been set with the font of the current style context
315 0 : NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
316 : Equals(aFontMetrics->Font()),
317 : "unexpected state");
318 :
319 0 : nscoord xHeight = aFontMetrics->XHeight();
320 0 : PRUnichar overBar = 0x00AF;
321 0 : nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&overBar, 1);
322 0 : aRuleThickness = bm.ascent + bm.descent;
323 0 : if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
324 : // fall-back to the other version
325 0 : GetRuleThickness(aFontMetrics, aRuleThickness);
326 : }
327 0 : }
328 :
329 : /* static */ void
330 0 : nsMathMLFrame::GetAxisHeight(nsRenderingContext& aRenderingContext,
331 : nsFontMetrics* aFontMetrics,
332 : nscoord& aAxisHeight)
333 : {
334 : // get the bounding metrics of the minus sign, the rendering context
335 : // is assumed to have been set with the font of the current style context
336 0 : NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
337 : Equals(aFontMetrics->Font()),
338 : "unexpected state");
339 :
340 0 : nscoord xHeight = aFontMetrics->XHeight();
341 0 : PRUnichar minus = 0x2212; // not '-', but official Unicode minus sign
342 0 : nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&minus, 1);
343 0 : aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
344 0 : if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
345 : // fall-back to the other version
346 0 : GetAxisHeight(aFontMetrics, aAxisHeight);
347 : }
348 0 : }
349 :
350 : /* static */ nscoord
351 0 : nsMathMLFrame::CalcLength(nsPresContext* aPresContext,
352 : nsStyleContext* aStyleContext,
353 : const nsCSSValue& aCSSValue)
354 : {
355 0 : NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit");
356 :
357 0 : if (aCSSValue.IsFixedLengthUnit()) {
358 0 : return aCSSValue.GetFixedLength(aPresContext);
359 : }
360 0 : if (aCSSValue.IsPixelLengthUnit()) {
361 0 : return aCSSValue.GetPixelLength();
362 : }
363 :
364 0 : nsCSSUnit unit = aCSSValue.GetUnit();
365 :
366 0 : if (eCSSUnit_EM == unit) {
367 0 : const nsStyleFont* font = aStyleContext->GetStyleFont();
368 0 : return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size);
369 : }
370 0 : else if (eCSSUnit_XHeight == unit) {
371 0 : nsRefPtr<nsFontMetrics> fm;
372 : nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
373 0 : getter_AddRefs(fm));
374 0 : nscoord xHeight = fm->XHeight();
375 0 : return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight);
376 : }
377 :
378 : // MathML doesn't specify other CSS units such as rem or ch
379 0 : NS_ERROR("Unsupported unit");
380 0 : return 0;
381 : }
382 :
383 : /* static */ bool
384 0 : nsMathMLFrame::ParseNamedSpaceValue(nsIFrame* aMathMLmstyleFrame,
385 : nsString& aString,
386 : nsCSSValue& aCSSValue)
387 : {
388 0 : aCSSValue.Reset();
389 0 : aString.CompressWhitespace(); // aString is not a const in this code...
390 0 : if (!aString.Length()) return false;
391 :
392 : // See if it is one of the 'namedspace' (ranging 1/18em...7/18em)
393 0 : PRInt32 i = 0;
394 0 : nsIAtom* namedspaceAtom = nsnull;
395 0 : if (aString.EqualsLiteral("veryverythinmathspace")) {
396 0 : i = 1;
397 0 : namedspaceAtom = nsGkAtoms::veryverythinmathspace_;
398 : }
399 0 : else if (aString.EqualsLiteral("verythinmathspace")) {
400 0 : i = 2;
401 0 : namedspaceAtom = nsGkAtoms::verythinmathspace_;
402 : }
403 0 : else if (aString.EqualsLiteral("thinmathspace")) {
404 0 : i = 3;
405 0 : namedspaceAtom = nsGkAtoms::thinmathspace_;
406 : }
407 0 : else if (aString.EqualsLiteral("mediummathspace")) {
408 0 : i = 4;
409 0 : namedspaceAtom = nsGkAtoms::mediummathspace_;
410 : }
411 0 : else if (aString.EqualsLiteral("thickmathspace")) {
412 0 : i = 5;
413 0 : namedspaceAtom = nsGkAtoms::thickmathspace_;
414 : }
415 0 : else if (aString.EqualsLiteral("verythickmathspace")) {
416 0 : i = 6;
417 0 : namedspaceAtom = nsGkAtoms::verythickmathspace_;
418 : }
419 0 : else if (aString.EqualsLiteral("veryverythickmathspace")) {
420 0 : i = 7;
421 0 : namedspaceAtom = nsGkAtoms::veryverythickmathspace_;
422 : }
423 0 : else if (aString.EqualsLiteral("negativeveryverythinmathspace")) {
424 0 : i = -1;
425 0 : namedspaceAtom = nsGkAtoms::negativeveryverythinmathspace_;
426 : }
427 0 : else if (aString.EqualsLiteral("negativeverythinmathspace")) {
428 0 : i = -2;
429 0 : namedspaceAtom = nsGkAtoms::negativeverythinmathspace_;
430 : }
431 0 : else if (aString.EqualsLiteral("negativethinmathspace")) {
432 0 : i = -3;
433 0 : namedspaceAtom = nsGkAtoms::negativethinmathspace_;
434 : }
435 0 : else if (aString.EqualsLiteral("negativemediummathspace")) {
436 0 : i = -4;
437 0 : namedspaceAtom = nsGkAtoms::negativemediummathspace_;
438 : }
439 0 : else if (aString.EqualsLiteral("negativethickmathspace")) {
440 0 : i = -5;
441 0 : namedspaceAtom = nsGkAtoms::negativethickmathspace_;
442 : }
443 0 : else if (aString.EqualsLiteral("negativeverythickmathspace")) {
444 0 : i = -6;
445 0 : namedspaceAtom = nsGkAtoms::negativeverythickmathspace_;
446 : }
447 0 : else if (aString.EqualsLiteral("negativeveryverythickmathspace")) {
448 0 : i = -7;
449 0 : namedspaceAtom = nsGkAtoms::negativeveryverythickmathspace_;
450 : }
451 :
452 0 : if (0 != i) {
453 0 : if (aMathMLmstyleFrame) {
454 : // see if there is a <mstyle> that has overriden the default value
455 : // GetAttribute() will recurse all the way up into the <mstyle> hierarchy
456 0 : nsAutoString value;
457 0 : GetAttribute(nsnull, aMathMLmstyleFrame, namedspaceAtom, value);
458 0 : if (!value.IsEmpty()) {
459 0 : if (ParseNumericValue(value, aCSSValue) &&
460 0 : aCSSValue.IsLengthUnit()) {
461 0 : return true;
462 : }
463 : }
464 : }
465 :
466 : // fall back to the default value
467 0 : aCSSValue.SetFloatValue(float(i)/float(18), eCSSUnit_EM);
468 0 : return true;
469 : }
470 :
471 0 : return false;
472 : }
473 :
474 : // ================
475 : // Utils to map attributes into CSS rules (work-around to bug 69409 which
476 : // is not scheduled to be fixed anytime soon)
477 : //
478 :
479 : static const PRInt32 kMathMLversion1 = 1;
480 : static const PRInt32 kMathMLversion2 = 2;
481 :
482 : struct
483 : nsCSSMapping {
484 : PRInt32 compatibility;
485 : const nsIAtom* attrAtom;
486 : const char* cssProperty;
487 : };
488 :
489 : #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
490 : class nsDisplayMathMLBoundingMetrics : public nsDisplayItem {
491 : public:
492 : nsDisplayMathMLBoundingMetrics(nsDisplayListBuilder* aBuilder,
493 : nsIFrame* aFrame, const nsRect& aRect)
494 : : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
495 : MOZ_COUNT_CTOR(nsDisplayMathMLBoundingMetrics);
496 : }
497 : #ifdef NS_BUILD_REFCNT_LOGGING
498 : virtual ~nsDisplayMathMLBoundingMetrics() {
499 : MOZ_COUNT_DTOR(nsDisplayMathMLBoundingMetrics);
500 : }
501 : #endif
502 :
503 : virtual void Paint(nsDisplayListBuilder* aBuilder,
504 : nsRenderingContext* aCtx);
505 : NS_DISPLAY_DECL_NAME("MathMLBoundingMetrics", TYPE_MATHML_BOUNDING_METRICS)
506 : private:
507 : nsRect mRect;
508 : };
509 :
510 : void nsDisplayMathMLBoundingMetrics::Paint(nsDisplayListBuilder* aBuilder,
511 : nsRenderingContext* aCtx)
512 : {
513 : aCtx->SetColor(NS_RGB(0,0,255));
514 : aCtx->DrawRect(mRect + ToReferenceFrame());
515 : }
516 :
517 : nsresult
518 : nsMathMLFrame::DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
519 : nsIFrame* aFrame, const nsPoint& aPt,
520 : const nsBoundingMetrics& aMetrics,
521 : const nsDisplayListSet& aLists) {
522 : if (!NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
523 : return NS_OK;
524 :
525 : nscoord x = aPt.x + aMetrics.leftBearing;
526 : nscoord y = aPt.y - aMetrics.ascent;
527 : nscoord w = aMetrics.rightBearing - aMetrics.leftBearing;
528 : nscoord h = aMetrics.ascent + aMetrics.descent;
529 :
530 : return aLists.Content()->AppendNewToTop(new (aBuilder)
531 : nsDisplayMathMLBoundingMetrics(aBuilder, this, nsRect(x,y,w,h)));
532 : }
533 : #endif
534 :
535 : class nsDisplayMathMLBar : public nsDisplayItem {
536 : public:
537 0 : nsDisplayMathMLBar(nsDisplayListBuilder* aBuilder,
538 : nsIFrame* aFrame, const nsRect& aRect)
539 0 : : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
540 0 : MOZ_COUNT_CTOR(nsDisplayMathMLBar);
541 0 : }
542 : #ifdef NS_BUILD_REFCNT_LOGGING
543 0 : virtual ~nsDisplayMathMLBar() {
544 0 : MOZ_COUNT_DTOR(nsDisplayMathMLBar);
545 0 : }
546 : #endif
547 :
548 : virtual void Paint(nsDisplayListBuilder* aBuilder,
549 : nsRenderingContext* aCtx);
550 0 : NS_DISPLAY_DECL_NAME("MathMLBar", TYPE_MATHML_BAR)
551 : private:
552 : nsRect mRect;
553 : };
554 :
555 0 : void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
556 : nsRenderingContext* aCtx)
557 : {
558 : // paint the bar with the current text color
559 0 : aCtx->SetColor(mFrame->GetVisitedDependentColor(eCSSProperty_color));
560 0 : aCtx->FillRect(mRect + ToReferenceFrame());
561 0 : }
562 :
563 : nsresult
564 0 : nsMathMLFrame::DisplayBar(nsDisplayListBuilder* aBuilder,
565 : nsIFrame* aFrame, const nsRect& aRect,
566 : const nsDisplayListSet& aLists) {
567 0 : if (!aFrame->GetStyleVisibility()->IsVisible() || aRect.IsEmpty())
568 0 : return NS_OK;
569 :
570 : return aLists.Content()->AppendNewToTop(new (aBuilder)
571 0 : nsDisplayMathMLBar(aBuilder, aFrame, aRect));
572 : }
|