Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / mathml / base / src / nsMathMLmunderFrame.cpp
blobc7416c4097f7398cd4b2280dbe51bd2a895e11d2
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
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/
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.
15 * The Original Code is Mozilla MathML Project.
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.
22 * Contributor(s):
23 * Roger B. Sidje <rbs@maths.uq.edu.au>
24 * David J. Fiddes <D.J.Fiddes@hw.ac.uk>
25 * Shyjan Mahamud <mahamud@cs.cmu.edu>
26 * Pierre Phaneuf <pp@ludusdesign.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
43 #include "nsCOMPtr.h"
44 #include "nsFrame.h"
45 #include "nsPresContext.h"
46 #include "nsStyleContext.h"
47 #include "nsStyleConsts.h"
48 #include "nsINameSpaceManager.h"
49 #include "nsIRenderingContext.h"
50 #include "nsIFontMetrics.h"
52 #include "nsMathMLmunderFrame.h"
53 #include "nsMathMLmsubFrame.h"
56 // <munder> -- attach an underscript to a base - implementation
59 nsIFrame*
60 NS_NewMathMLmunderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
62 return new (aPresShell) nsMathMLmunderFrame(aContext);
65 nsMathMLmunderFrame::~nsMathMLmunderFrame()
69 NS_IMETHODIMP
70 nsMathMLmunderFrame::AttributeChanged(PRInt32 aNameSpaceID,
71 nsIAtom* aAttribute,
72 PRInt32 aModType)
74 if (nsGkAtoms::accentunder_ == aAttribute) {
75 // When we have automatic data to update within ourselves, we ask our
76 // parent to re-layout its children
77 return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
80 return nsMathMLContainerFrame::
81 AttributeChanged(aNameSpaceID, aAttribute, aModType);
84 NS_IMETHODIMP
85 nsMathMLmunderFrame::UpdatePresentationData(PRUint32 aFlagsValues,
86 PRUint32 aFlagsToUpdate)
88 nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
89 // disable the stretch-all flag if we are going to act like a subscript
90 if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
91 !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
92 mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
94 else {
95 mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
97 return NS_OK;
100 NS_IMETHODIMP
101 nsMathMLmunderFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex,
102 PRInt32 aLastIndex,
103 PRUint32 aFlagsValues,
104 PRUint32 aFlagsToUpdate)
106 // munder is special... The REC says:
107 // Within underscript, <munder> always sets displaystyle to "false",
108 // but increments scriptlevel by 1 only when accentunder is "false".
109 // This means that
110 // 1. don't allow displaystyle to change in the underscript
111 // 2. if the value of the accent is changed, we need to recompute the
112 // scriptlevel of the underscript. The problem is that the accent
113 // can change in the <mo> deep down the embellished hierarchy
115 // Do #1 here, never allow displaystyle to be changed in the underscript
116 PRInt32 index = 0;
117 nsIFrame* childFrame = mFrames.FirstChild();
118 while (childFrame) {
119 if ((index >= aFirstIndex) &&
120 ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) {
121 if (index > 0) {
122 // disable the flag
123 aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
124 aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
126 PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate);
128 index++;
129 childFrame = childFrame->GetNextSibling();
131 return NS_OK;
133 // For #2, changing the accent attribute will trigger a re-build of
134 // all automatic data in the embellished hierarchy
137 NS_IMETHODIMP
138 nsMathMLmunderFrame::InheritAutomaticData(nsIFrame* aParent)
140 // let the base class get the default from our parent
141 nsMathMLContainerFrame::InheritAutomaticData(aParent);
143 mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
145 return NS_OK;
148 NS_IMETHODIMP
149 nsMathMLmunderFrame::TransmitAutomaticData()
151 // At this stage, all our children are in sync and we can fully
152 // resolve our own mEmbellishData struct
153 //---------------------------------------------------------------------
155 /* The REC says:
156 The default value of accentunder is false, unless underscript
157 is an <mo> element or an embellished operator. If underscript is
158 an <mo> element, the value of its accent attribute is used as the
159 default value of accentunder. If underscript is an embellished
160 operator, the accent attribute of the <mo> element at its
161 core is used as the default value. As with all attributes, an
162 explicitly given value overrides the default.
164 XXX The winner is the outermost setting in conflicting settings like these:
165 <munder accent='true'>
166 <mi>...</mi>
167 <mo accent='false'> ... </mo>
168 </munder>
171 nsIFrame* underscriptFrame = nsnull;
172 nsIFrame* baseFrame = mFrames.FirstChild();
173 if (baseFrame)
174 underscriptFrame = baseFrame->GetNextSibling();
176 // if our base is an embellished operator, let its state bubble to us (in particular,
177 // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags
178 // are reset to the default values of false if the base frame isn't embellished.
179 mPresentationData.baseFrame = baseFrame;
180 GetEmbellishDataFrom(baseFrame, mEmbellishData);
182 // The default value of accentunder is false, unless the underscript is embellished
183 // and its core <mo> is an accent
184 nsEmbellishData embellishData;
185 GetEmbellishDataFrom(underscriptFrame, embellishData);
186 if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags))
187 mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER;
188 else
189 mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER;
191 // if we have an accentunder attribute, it overrides what the underscript said
192 static nsIContent::AttrValuesArray strings[] =
193 {&nsGkAtoms::_true, &nsGkAtoms::_false, nsnull};
194 switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::accentunder_,
195 strings, eCaseMatters)) {
196 case 0: mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; break;
197 case 1: mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; break;
200 // disable the stretch-all flag if we are going to act like a superscript
201 if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
202 !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
203 mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
205 // Now transmit any change that we want to our children so that they
206 // can update their mPresentationData structs
207 //---------------------------------------------------------------------
209 /* The REC says:
210 Within underscript, <munder> always sets displaystyle to "false",
211 but increments scriptlevel by 1 only when accentunder is "false".
213 The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a
214 say it should be compressed
216 SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags));
217 PropagatePresentationDataFor(underscriptFrame,
218 ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
219 NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
221 return NS_OK;
225 The REC says:
226 * If the base is an operator with movablelimits="true" (or
227 an embellished operator whose <mo> element core has
228 movablelimits="true"), and displaystyle="false", then
229 underscript is drawn in a subscript position. In this case,
230 the accentunder attribute is ignored. This is often used
231 for limits on symbols such as &sum;.
233 i.e.,:
234 if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
235 !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
236 // place like subscript
238 else {
239 // place like underscript
243 /* virtual */ nsresult
244 nsMathMLmunderFrame::Place(nsIRenderingContext& aRenderingContext,
245 PRBool aPlaceOrigin,
246 nsHTMLReflowMetrics& aDesiredSize)
248 if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
249 !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
250 // place like subscript
251 return nsMathMLmsubFrame::PlaceSubScript(PresContext(),
252 aRenderingContext,
253 aPlaceOrigin,
254 aDesiredSize,
255 this, 0, PresContext()->PointsToAppUnits(0.5f));
258 ////////////////////////////////////
259 // Get the children's desired sizes
261 nsBoundingMetrics bmBase, bmUnder;
262 nsHTMLReflowMetrics baseSize;
263 nsHTMLReflowMetrics underSize;
264 nsIFrame* underFrame = nsnull;
265 nsIFrame* baseFrame = mFrames.FirstChild();
266 if (baseFrame)
267 underFrame = baseFrame->GetNextSibling();
268 if (!baseFrame || !underFrame || underFrame->GetNextSibling()) {
269 // report an error, encourage people to get their markups in order
270 return ReflowError(aRenderingContext, aDesiredSize);
272 GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
273 GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
275 nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
277 ////////////////////
278 // Place Children
280 aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
281 PresContext()->GetUserFontSet());
282 nsCOMPtr<nsIFontMetrics> fm;
283 aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
285 nscoord xHeight = 0;
286 fm->GetXHeight (xHeight);
288 nscoord ruleThickness;
289 GetRuleThickness (aRenderingContext, fm, ruleThickness);
291 // there are 2 different types of placement depending on
292 // whether we want an accented under or not
294 nscoord correction = 0;
295 GetItalicCorrection (bmBase, correction);
297 nscoord delta1 = 0; // gap between base and underscript
298 nscoord delta2 = 0; // extra space beneath underscript
299 if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
300 // Rule 13a, App. G, TeXbook
301 nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy;
302 GetBigOpSpacings (fm,
303 dummy, bigOpSpacing2,
304 dummy, bigOpSpacing4,
305 bigOpSpacing5);
306 delta1 = PR_MAX(bigOpSpacing2, (bigOpSpacing4 - bmUnder.ascent));
307 delta2 = bigOpSpacing5;
309 else {
310 // No corresponding rule in TeXbook - we are on our own here
311 // XXX tune the gap delta between base and underscript
313 // Should we use Rule 10 like \underline does?
314 delta1 = ruleThickness + onePixel/2;
315 delta2 = ruleThickness;
317 // empty under?
318 if (!(bmUnder.ascent + bmUnder.descent)) delta1 = 0;
320 nscoord dxBase, dxUnder = 0;
322 // Width of non-spacing marks is zero so use left and right bearing.
323 nscoord underWidth = bmUnder.width;
324 if (!underWidth) {
325 underWidth = bmUnder.rightBearing - bmUnder.leftBearing;
326 dxUnder = -bmUnder.leftBearing;
329 nscoord maxWidth = PR_MAX(bmBase.width, underWidth);
330 if (NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
331 dxUnder += (maxWidth - underWidth)/2;
333 else {
334 dxUnder += -correction/2 + (maxWidth - underWidth)/2;
336 dxBase = (maxWidth - bmBase.width)/2;
338 mBoundingMetrics.width =
339 PR_MAX(dxBase + bmBase.width, dxUnder + bmUnder.width);
340 mBoundingMetrics.ascent = bmBase.ascent;
341 mBoundingMetrics.descent =
342 bmBase.descent + delta1 + bmUnder.ascent + bmUnder.descent;
343 mBoundingMetrics.leftBearing =
344 PR_MIN(dxBase + bmBase.leftBearing, dxUnder + bmUnder.leftBearing);
345 mBoundingMetrics.rightBearing =
346 PR_MAX(dxBase + bmBase.rightBearing, dxUnder + bmUnder.rightBearing);
348 aDesiredSize.ascent = baseSize.ascent;
349 aDesiredSize.height = aDesiredSize.ascent +
350 PR_MAX(mBoundingMetrics.descent + delta2,
351 bmBase.descent + delta1 + bmUnder.ascent +
352 underSize.height - underSize.ascent);
353 aDesiredSize.width = mBoundingMetrics.width;
354 aDesiredSize.mBoundingMetrics = mBoundingMetrics;
356 mReference.x = 0;
357 mReference.y = aDesiredSize.ascent;
359 if (aPlaceOrigin) {
360 nscoord dy = 0;
361 // place base
362 FinishReflowChild(baseFrame, PresContext(), nsnull, baseSize, dxBase, dy, 0);
363 // place underscript
364 dy = aDesiredSize.ascent + mBoundingMetrics.descent - bmUnder.descent - underSize.ascent;
365 FinishReflowChild(underFrame, PresContext(), nsnull, underSize, dxUnder, dy, 0);
368 return NS_OK;