Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / layout / mathml / nsMathMLmsupFrame.cpp
blob4b451ea179cd7c97145cb6116f09c28d500a5a92
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> (added TeX rendering rules)
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsCOMPtr.h"
42 #include "nsFrame.h"
43 #include "nsPresContext.h"
44 #include "nsStyleContext.h"
45 #include "nsStyleConsts.h"
46 #include "nsIRenderingContext.h"
47 #include "nsIFontMetrics.h"
49 #include "nsMathMLmsupFrame.h"
52 // <msup> -- attach a superscript to a base - implementation
55 nsIFrame*
56 NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
58 return new (aPresShell) nsMathMLmsupFrame(aContext);
61 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmsupFrame)
63 nsMathMLmsupFrame::~nsMathMLmsupFrame()
67 NS_IMETHODIMP
68 nsMathMLmsupFrame::TransmitAutomaticData()
70 // if our base is an embellished operator, its flags bubble to us
71 mPresentationData.baseFrame = mFrames.FirstChild();
72 GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
74 // 1. The REC says:
75 // The <msup> element increments scriptlevel by 1, and sets displaystyle to
76 // "false", within superscript, but leaves both attributes unchanged within base.
77 // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression,
78 // so we don't set the compression flag. Our parent will propagate its own.
79 UpdatePresentationDataFromChildAt(1, -1,
80 ~NS_MATHML_DISPLAYSTYLE,
81 NS_MATHML_DISPLAYSTYLE);
83 return NS_OK;
86 /* virtual */ nsresult
87 nsMathMLmsupFrame::Place(nsIRenderingContext& aRenderingContext,
88 PRBool aPlaceOrigin,
89 nsHTMLReflowMetrics& aDesiredSize)
91 // extra spacing after sup/subscript
92 nscoord scriptSpace = nsPresContext::CSSPointsToAppUnits(0.5f); // 0.5pt as in plain TeX
94 // check if the superscriptshift attribute is there
95 nsAutoString value;
96 nscoord supScriptShift = 0;
97 GetAttribute(mContent, mPresentationData.mstyle,
98 nsGkAtoms::superscriptshift_, value);
99 if (!value.IsEmpty()) {
100 nsCSSValue cssValue;
101 if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
102 supScriptShift = CalcLength(PresContext(), mStyleContext, cssValue);
106 return nsMathMLmsupFrame::PlaceSuperScript(PresContext(),
107 aRenderingContext,
108 aPlaceOrigin,
109 aDesiredSize,
110 this,
111 supScriptShift,
112 scriptSpace);
115 // exported routine that both mover and msup share.
116 // mover uses this when movablelimits is set.
117 nsresult
118 nsMathMLmsupFrame::PlaceSuperScript(nsPresContext* aPresContext,
119 nsIRenderingContext& aRenderingContext,
120 PRBool aPlaceOrigin,
121 nsHTMLReflowMetrics& aDesiredSize,
122 nsMathMLContainerFrame* aFrame,
123 nscoord aUserSupScriptShift,
124 nscoord aScriptSpace)
126 // force the scriptSpace to be at least 1 pixel
127 nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
128 aScriptSpace = NS_MAX(onePixel, aScriptSpace);
130 ////////////////////////////////////
131 // Get the children's desired sizes
133 nsHTMLReflowMetrics baseSize;
134 nsHTMLReflowMetrics supScriptSize;
135 nsBoundingMetrics bmBase, bmSupScript;
136 nsIFrame* supScriptFrame = nsnull;
137 nsIFrame* baseFrame = aFrame->GetFirstChild(nsnull);
138 if (baseFrame)
139 supScriptFrame = baseFrame->GetNextSibling();
140 if (!baseFrame || !supScriptFrame || supScriptFrame->GetNextSibling()) {
141 // report an error, encourage people to get their markups in order
142 return aFrame->ReflowError(aRenderingContext, aDesiredSize);
144 GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
145 GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
147 // get the supdrop from the supscript font
148 nscoord supDrop;
149 GetSupDropFromChild(supScriptFrame, supDrop);
150 // parameter u, Rule 18a, App. G, TeXbook
151 nscoord minSupScriptShift = bmBase.ascent - supDrop;
153 //////////////////
154 // Place Children
156 // get min supscript shift limit from x-height
157 // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
158 nscoord xHeight = 0;
159 nsCOMPtr<nsIFontMetrics> fm =
160 aPresContext->GetMetricsFor(baseFrame->GetStyleFont()->mFont);
162 fm->GetXHeight (xHeight);
163 nscoord minShiftFromXHeight = (nscoord)
164 (bmSupScript.descent + (1.0f/4.0f) * xHeight);
165 nscoord italicCorrection;
166 GetItalicCorrection(bmBase, italicCorrection);
168 // supScriptShift{1,2,3}
169 // = minimum amount to shift the supscript up
170 // = sup{1,2,3} in TeX
171 // supScriptShift1 = superscriptshift attribute * x-height
172 // Note that there are THREE values for supscript shifts depending
173 // on the current style
174 nscoord supScriptShift1, supScriptShift2, supScriptShift3;
175 // Set supScriptShift{1,2,3} default from font
176 GetSupScriptShifts (fm, supScriptShift1, supScriptShift2, supScriptShift3);
178 if (0 < aUserSupScriptShift) {
179 // the user has set the superscriptshift attribute
180 float scaler2 = ((float) supScriptShift2) / supScriptShift1;
181 float scaler3 = ((float) supScriptShift3) / supScriptShift1;
182 supScriptShift1 =
183 NS_MAX(supScriptShift1, aUserSupScriptShift);
184 supScriptShift2 = NSToCoordRound(scaler2 * supScriptShift1);
185 supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1);
188 // get sup script shift depending on current script level and display style
189 // Rule 18c, App. G, TeXbook
190 nscoord supScriptShift;
191 nsPresentationData presentationData;
192 aFrame->GetPresentationData (presentationData);
193 if ( aFrame->GetStyleFont()->mScriptLevel == 0 &&
194 NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) &&
195 !NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
196 // Style D in TeXbook
197 supScriptShift = supScriptShift1;
199 else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
200 // Style C' in TeXbook = D',T',S',SS'
201 supScriptShift = supScriptShift3;
203 else {
204 // everything else = T,S,SS
205 supScriptShift = supScriptShift2;
208 // get actual supscriptshift to be used
209 // Rule 18c, App. G, TeXbook
210 nscoord actualSupScriptShift =
211 NS_MAX(minSupScriptShift,NS_MAX(supScriptShift,minShiftFromXHeight));
213 // bounding box
214 nsBoundingMetrics boundingMetrics;
215 boundingMetrics.ascent =
216 NS_MAX(bmBase.ascent, (bmSupScript.ascent + actualSupScriptShift));
217 boundingMetrics.descent =
218 NS_MAX(bmBase.descent, (bmSupScript.descent - actualSupScriptShift));
220 // leave aScriptSpace after superscript
221 // add italicCorrection between base and superscript
222 // add "a little to spare" as well (see TeXbook Ch.11, p.64), as we
223 // estimate the italic creation ourselves and it isn't the same as TeX
224 italicCorrection += onePixel;
225 boundingMetrics.width = bmBase.width + italicCorrection +
226 bmSupScript.width + aScriptSpace;
227 boundingMetrics.leftBearing = bmBase.leftBearing;
228 boundingMetrics.rightBearing = bmBase.width + italicCorrection +
229 bmSupScript.rightBearing;
230 aFrame->SetBoundingMetrics(boundingMetrics);
232 // reflow metrics
233 aDesiredSize.ascent =
234 NS_MAX(baseSize.ascent, (supScriptSize.ascent + actualSupScriptShift));
235 aDesiredSize.height = aDesiredSize.ascent +
236 NS_MAX(baseSize.height - baseSize.ascent,
237 (supScriptSize.height - supScriptSize.ascent - actualSupScriptShift));
238 aDesiredSize.width = boundingMetrics.width;
239 aDesiredSize.mBoundingMetrics = boundingMetrics;
241 aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
243 if (aPlaceOrigin) {
244 nscoord dx, dy;
245 // now place the base ...
246 dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
247 FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
248 // ... and supscript
249 dx = bmBase.width + italicCorrection;
250 dy = aDesiredSize.ascent - (supScriptSize.ascent + actualSupScriptShift);
251 FinishReflowChild (supScriptFrame, aPresContext, nsnull, supScriptSize, dx, dy, 0);
254 return NS_OK;