Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "nsMathMLmrootFrame.h" |
michael@0 | 7 | #include "nsPresContext.h" |
michael@0 | 8 | #include "nsRenderingContext.h" |
michael@0 | 9 | #include <algorithm> |
michael@0 | 10 | |
michael@0 | 11 | // |
michael@0 | 12 | // <msqrt> and <mroot> -- form a radical - implementation |
michael@0 | 13 | // |
michael@0 | 14 | |
michael@0 | 15 | //NOTE: |
michael@0 | 16 | // The code assumes that TeX fonts are picked. |
michael@0 | 17 | // There is no fall-back to draw the branches of the sqrt explicitly |
michael@0 | 18 | // in the case where TeX fonts are not there. In general, there are no |
michael@0 | 19 | // fall-back(s) in MathML when some (freely-downloadable) fonts are missing. |
michael@0 | 20 | // Otherwise, this will add much work and unnecessary complexity to the core |
michael@0 | 21 | // MathML engine. Assuming that authors have the free fonts is part of the |
michael@0 | 22 | // deal. We are not responsible for cases of misconfigurations out there. |
michael@0 | 23 | |
michael@0 | 24 | // additional style context to be used by our MathMLChar. |
michael@0 | 25 | #define NS_SQR_CHAR_STYLE_CONTEXT_INDEX 0 |
michael@0 | 26 | |
michael@0 | 27 | static const char16_t kSqrChar = char16_t(0x221A); |
michael@0 | 28 | |
michael@0 | 29 | nsIFrame* |
michael@0 | 30 | NS_NewMathMLmrootFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) |
michael@0 | 31 | { |
michael@0 | 32 | return new (aPresShell) nsMathMLmrootFrame(aContext); |
michael@0 | 33 | } |
michael@0 | 34 | |
michael@0 | 35 | NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmrootFrame) |
michael@0 | 36 | |
michael@0 | 37 | nsMathMLmrootFrame::nsMathMLmrootFrame(nsStyleContext* aContext) : |
michael@0 | 38 | nsMathMLContainerFrame(aContext), |
michael@0 | 39 | mSqrChar(), |
michael@0 | 40 | mBarRect() |
michael@0 | 41 | { |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | nsMathMLmrootFrame::~nsMathMLmrootFrame() |
michael@0 | 45 | { |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | void |
michael@0 | 49 | nsMathMLmrootFrame::Init(nsIContent* aContent, |
michael@0 | 50 | nsIFrame* aParent, |
michael@0 | 51 | nsIFrame* aPrevInFlow) |
michael@0 | 52 | { |
michael@0 | 53 | nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow); |
michael@0 | 54 | |
michael@0 | 55 | nsPresContext *presContext = PresContext(); |
michael@0 | 56 | |
michael@0 | 57 | // No need to track the style context given to our MathML char. |
michael@0 | 58 | // The Style System will use Get/SetAdditionalStyleContext() to keep it |
michael@0 | 59 | // up-to-date if dynamic changes arise. |
michael@0 | 60 | nsAutoString sqrChar; sqrChar.Assign(kSqrChar); |
michael@0 | 61 | mSqrChar.SetData(presContext, sqrChar); |
michael@0 | 62 | ResolveMathMLCharStyle(presContext, mContent, mStyleContext, &mSqrChar); |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | NS_IMETHODIMP |
michael@0 | 66 | nsMathMLmrootFrame::TransmitAutomaticData() |
michael@0 | 67 | { |
michael@0 | 68 | // 1. The REC says: |
michael@0 | 69 | // The <mroot> element increments scriptlevel by 2, and sets displaystyle to |
michael@0 | 70 | // "false", within index, but leaves both attributes unchanged within base. |
michael@0 | 71 | // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed |
michael@0 | 72 | UpdatePresentationDataFromChildAt(1, 1, |
michael@0 | 73 | NS_MATHML_COMPRESSED, |
michael@0 | 74 | NS_MATHML_COMPRESSED); |
michael@0 | 75 | UpdatePresentationDataFromChildAt(0, 0, |
michael@0 | 76 | NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); |
michael@0 | 77 | |
michael@0 | 78 | PropagateFrameFlagFor(mFrames.LastChild(), |
michael@0 | 79 | NS_FRAME_MATHML_SCRIPT_DESCENDANT); |
michael@0 | 80 | |
michael@0 | 81 | return NS_OK; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | void |
michael@0 | 85 | nsMathMLmrootFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, |
michael@0 | 86 | const nsRect& aDirtyRect, |
michael@0 | 87 | const nsDisplayListSet& aLists) |
michael@0 | 88 | { |
michael@0 | 89 | ///////////// |
michael@0 | 90 | // paint the content we are square-rooting |
michael@0 | 91 | nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); |
michael@0 | 92 | |
michael@0 | 93 | ///////////// |
michael@0 | 94 | // paint the sqrt symbol |
michael@0 | 95 | if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) { |
michael@0 | 96 | mSqrChar.Display(aBuilder, this, aLists, 0); |
michael@0 | 97 | |
michael@0 | 98 | DisplayBar(aBuilder, this, mBarRect, aLists); |
michael@0 | 99 | |
michael@0 | 100 | #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX) |
michael@0 | 101 | // for visual debug |
michael@0 | 102 | nsRect rect; |
michael@0 | 103 | mSqrChar.GetRect(rect); |
michael@0 | 104 | nsBoundingMetrics bm; |
michael@0 | 105 | mSqrChar.GetBoundingMetrics(bm); |
michael@0 | 106 | DisplayBoundingMetrics(aBuilder, this, rect.TopLeft(), bm, aLists); |
michael@0 | 107 | #endif |
michael@0 | 108 | } |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | static void |
michael@0 | 112 | GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth, |
michael@0 | 113 | nsFontMetrics* aFontMetrics, |
michael@0 | 114 | nscoord* aIndexOffset, nscoord* aSqrOffset) |
michael@0 | 115 | { |
michael@0 | 116 | // The index is tucked in closer to the radical while making sure |
michael@0 | 117 | // that the kern does not make the index and radical collide |
michael@0 | 118 | nscoord dxIndex, dxSqr; |
michael@0 | 119 | nscoord xHeight = aFontMetrics->XHeight(); |
michael@0 | 120 | nscoord indexRadicalKern = NSToCoordRound(1.35f * xHeight); |
michael@0 | 121 | if (indexRadicalKern > aIndexWidth) { |
michael@0 | 122 | dxIndex = indexRadicalKern - aIndexWidth; |
michael@0 | 123 | dxSqr = 0; |
michael@0 | 124 | } |
michael@0 | 125 | else { |
michael@0 | 126 | dxIndex = 0; |
michael@0 | 127 | dxSqr = aIndexWidth - indexRadicalKern; |
michael@0 | 128 | } |
michael@0 | 129 | // avoid collision by leaving a minimum space between index and radical |
michael@0 | 130 | nscoord minimumClearance = aSqrWidth/2; |
michael@0 | 131 | if (dxIndex + aIndexWidth + minimumClearance > dxSqr + aSqrWidth) { |
michael@0 | 132 | if (aIndexWidth + minimumClearance < aSqrWidth) { |
michael@0 | 133 | dxIndex = aSqrWidth - (aIndexWidth + minimumClearance); |
michael@0 | 134 | dxSqr = 0; |
michael@0 | 135 | } |
michael@0 | 136 | else { |
michael@0 | 137 | dxIndex = 0; |
michael@0 | 138 | dxSqr = (aIndexWidth + minimumClearance) - aSqrWidth; |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | if (aIndexOffset) |
michael@0 | 143 | *aIndexOffset = dxIndex; |
michael@0 | 144 | if (aSqrOffset) |
michael@0 | 145 | *aSqrOffset = dxSqr; |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | nsresult |
michael@0 | 149 | nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext, |
michael@0 | 150 | nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 151 | const nsHTMLReflowState& aReflowState, |
michael@0 | 152 | nsReflowStatus& aStatus) |
michael@0 | 153 | { |
michael@0 | 154 | nsresult rv = NS_OK; |
michael@0 | 155 | nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); |
michael@0 | 156 | nsReflowStatus childStatus; |
michael@0 | 157 | |
michael@0 | 158 | aDesiredSize.Width() = aDesiredSize.Height() = 0; |
michael@0 | 159 | aDesiredSize.SetTopAscent(0); |
michael@0 | 160 | |
michael@0 | 161 | nsBoundingMetrics bmSqr, bmBase, bmIndex; |
michael@0 | 162 | nsRenderingContext& renderingContext = *aReflowState.rendContext; |
michael@0 | 163 | |
michael@0 | 164 | ////////////////// |
michael@0 | 165 | // Reflow Children |
michael@0 | 166 | |
michael@0 | 167 | int32_t count = 0; |
michael@0 | 168 | nsIFrame* baseFrame = nullptr; |
michael@0 | 169 | nsIFrame* indexFrame = nullptr; |
michael@0 | 170 | nsHTMLReflowMetrics baseSize(aReflowState); |
michael@0 | 171 | nsHTMLReflowMetrics indexSize(aReflowState); |
michael@0 | 172 | nsIFrame* childFrame = mFrames.FirstChild(); |
michael@0 | 173 | while (childFrame) { |
michael@0 | 174 | // ask our children to compute their bounding metrics |
michael@0 | 175 | nsHTMLReflowMetrics childDesiredSize(aReflowState, |
michael@0 | 176 | aDesiredSize.mFlags |
michael@0 | 177 | | NS_REFLOW_CALC_BOUNDING_METRICS); |
michael@0 | 178 | nsHTMLReflowState childReflowState(aPresContext, aReflowState, |
michael@0 | 179 | childFrame, availSize); |
michael@0 | 180 | rv = ReflowChild(childFrame, aPresContext, |
michael@0 | 181 | childDesiredSize, childReflowState, childStatus); |
michael@0 | 182 | //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); |
michael@0 | 183 | if (NS_FAILED(rv)) { |
michael@0 | 184 | // Call DidReflow() for the child frames we successfully did reflow. |
michael@0 | 185 | DidReflowChildren(mFrames.FirstChild(), childFrame); |
michael@0 | 186 | return rv; |
michael@0 | 187 | } |
michael@0 | 188 | if (0 == count) { |
michael@0 | 189 | // base |
michael@0 | 190 | baseFrame = childFrame; |
michael@0 | 191 | baseSize = childDesiredSize; |
michael@0 | 192 | bmBase = childDesiredSize.mBoundingMetrics; |
michael@0 | 193 | } |
michael@0 | 194 | else if (1 == count) { |
michael@0 | 195 | // index |
michael@0 | 196 | indexFrame = childFrame; |
michael@0 | 197 | indexSize = childDesiredSize; |
michael@0 | 198 | bmIndex = childDesiredSize.mBoundingMetrics; |
michael@0 | 199 | } |
michael@0 | 200 | count++; |
michael@0 | 201 | childFrame = childFrame->GetNextSibling(); |
michael@0 | 202 | } |
michael@0 | 203 | if (2 != count) { |
michael@0 | 204 | // report an error, encourage people to get their markups in order |
michael@0 | 205 | ReportChildCountError(); |
michael@0 | 206 | rv = ReflowError(renderingContext, aDesiredSize); |
michael@0 | 207 | aStatus = NS_FRAME_COMPLETE; |
michael@0 | 208 | NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); |
michael@0 | 209 | // Call DidReflow() for the child frames we successfully did reflow. |
michael@0 | 210 | DidReflowChildren(mFrames.FirstChild(), childFrame); |
michael@0 | 211 | return rv; |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | //////////// |
michael@0 | 215 | // Prepare the radical symbol and the overline bar |
michael@0 | 216 | |
michael@0 | 217 | nsRefPtr<nsFontMetrics> fm; |
michael@0 | 218 | nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); |
michael@0 | 219 | renderingContext.SetFont(fm); |
michael@0 | 220 | |
michael@0 | 221 | // For radical glyphs from TeX fonts and some of the radical glyphs from |
michael@0 | 222 | // Mathematica fonts, the thickness of the overline can be obtained from the |
michael@0 | 223 | // ascent of the glyph. Most fonts however have radical glyphs above the |
michael@0 | 224 | // baseline so no assumption can be made about the meaning of the ascent. |
michael@0 | 225 | nscoord ruleThickness, leading, em; |
michael@0 | 226 | GetRuleThickness(renderingContext, fm, ruleThickness); |
michael@0 | 227 | |
michael@0 | 228 | char16_t one = '1'; |
michael@0 | 229 | nsBoundingMetrics bmOne = renderingContext.GetBoundingMetrics(&one, 1); |
michael@0 | 230 | |
michael@0 | 231 | // get the leading to be left at the top of the resulting frame |
michael@0 | 232 | // this seems more reliable than using fm->GetLeading() on suspicious fonts |
michael@0 | 233 | GetEmHeight(fm, em); |
michael@0 | 234 | leading = nscoord(0.2f * em); |
michael@0 | 235 | |
michael@0 | 236 | // Rule 11, App. G, TeXbook |
michael@0 | 237 | // psi = clearance between rule and content |
michael@0 | 238 | nscoord phi = 0, psi = 0; |
michael@0 | 239 | if (StyleFont()->mMathDisplay == NS_MATHML_DISPLAYSTYLE_BLOCK) |
michael@0 | 240 | phi = fm->XHeight(); |
michael@0 | 241 | else |
michael@0 | 242 | phi = ruleThickness; |
michael@0 | 243 | psi = ruleThickness + phi/4; |
michael@0 | 244 | |
michael@0 | 245 | // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131) |
michael@0 | 246 | if (bmOne.ascent > bmBase.ascent) |
michael@0 | 247 | psi += bmOne.ascent - bmBase.ascent; |
michael@0 | 248 | |
michael@0 | 249 | // make sure that the rule appears on on screen |
michael@0 | 250 | nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); |
michael@0 | 251 | if (ruleThickness < onePixel) { |
michael@0 | 252 | ruleThickness = onePixel; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | // adjust clearance psi to get an exact number of pixels -- this |
michael@0 | 256 | // gives a nicer & uniform look on stacked radicals (bug 130282) |
michael@0 | 257 | nscoord delta = psi % onePixel; |
michael@0 | 258 | if (delta) |
michael@0 | 259 | psi += onePixel - delta; // round up |
michael@0 | 260 | |
michael@0 | 261 | // Stretch the radical symbol to the appropriate height if it is not big enough. |
michael@0 | 262 | nsBoundingMetrics contSize = bmBase; |
michael@0 | 263 | contSize.descent = bmBase.ascent + bmBase.descent + psi; |
michael@0 | 264 | contSize.ascent = ruleThickness; |
michael@0 | 265 | |
michael@0 | 266 | // height(radical) should be >= height(base) + psi + ruleThickness |
michael@0 | 267 | nsBoundingMetrics radicalSize; |
michael@0 | 268 | mSqrChar.Stretch(aPresContext, renderingContext, |
michael@0 | 269 | NS_STRETCH_DIRECTION_VERTICAL, |
michael@0 | 270 | contSize, radicalSize, |
michael@0 | 271 | NS_STRETCH_LARGER, |
michael@0 | 272 | StyleVisibility()->mDirection); |
michael@0 | 273 | // radicalSize have changed at this point, and should match with |
michael@0 | 274 | // the bounding metrics of the char |
michael@0 | 275 | mSqrChar.GetBoundingMetrics(bmSqr); |
michael@0 | 276 | |
michael@0 | 277 | // Update the desired size for the container (like msqrt, index is not yet included) |
michael@0 | 278 | // the baseline will be that of the base. |
michael@0 | 279 | mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness; |
michael@0 | 280 | mBoundingMetrics.descent = |
michael@0 | 281 | std::max(bmBase.descent, |
michael@0 | 282 | (bmSqr.ascent + bmSqr.descent - mBoundingMetrics.ascent)); |
michael@0 | 283 | mBoundingMetrics.width = bmSqr.width + bmBase.width; |
michael@0 | 284 | mBoundingMetrics.leftBearing = bmSqr.leftBearing; |
michael@0 | 285 | mBoundingMetrics.rightBearing = bmSqr.width + |
michael@0 | 286 | std::max(bmBase.width, bmBase.rightBearing); // take also care of the rule |
michael@0 | 287 | |
michael@0 | 288 | aDesiredSize.SetTopAscent(mBoundingMetrics.ascent + leading); |
michael@0 | 289 | aDesiredSize.Height() = aDesiredSize.TopAscent() + |
michael@0 | 290 | std::max(baseSize.Height() - baseSize.TopAscent(), |
michael@0 | 291 | mBoundingMetrics.descent + ruleThickness); |
michael@0 | 292 | aDesiredSize.Width() = mBoundingMetrics.width; |
michael@0 | 293 | |
michael@0 | 294 | ///////////// |
michael@0 | 295 | // Re-adjust the desired size to include the index. |
michael@0 | 296 | |
michael@0 | 297 | // the index is raised by some fraction of the height |
michael@0 | 298 | // of the radical, see \mroot macro in App. B, TexBook |
michael@0 | 299 | nscoord raiseIndexDelta = NSToCoordRound(0.6f * (bmSqr.ascent + bmSqr.descent)); |
michael@0 | 300 | nscoord indexRaisedAscent = mBoundingMetrics.ascent // top of radical |
michael@0 | 301 | - (bmSqr.ascent + bmSqr.descent) // to bottom of radical |
michael@0 | 302 | + raiseIndexDelta + bmIndex.ascent + bmIndex.descent; // to top of raised index |
michael@0 | 303 | |
michael@0 | 304 | nscoord indexClearance = 0; |
michael@0 | 305 | if (mBoundingMetrics.ascent < indexRaisedAscent) { |
michael@0 | 306 | indexClearance = |
michael@0 | 307 | indexRaisedAscent - mBoundingMetrics.ascent; // excess gap introduced by a tall index |
michael@0 | 308 | mBoundingMetrics.ascent = indexRaisedAscent; |
michael@0 | 309 | nscoord descent = aDesiredSize.Height() - aDesiredSize.TopAscent(); |
michael@0 | 310 | aDesiredSize.SetTopAscent(mBoundingMetrics.ascent + leading); |
michael@0 | 311 | aDesiredSize.Height() = aDesiredSize.TopAscent() + descent; |
michael@0 | 312 | } |
michael@0 | 313 | |
michael@0 | 314 | nscoord dxIndex, dxSqr; |
michael@0 | 315 | GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr); |
michael@0 | 316 | |
michael@0 | 317 | mBoundingMetrics.width = dxSqr + bmSqr.width + bmBase.width; |
michael@0 | 318 | mBoundingMetrics.leftBearing = |
michael@0 | 319 | std::min(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing); |
michael@0 | 320 | mBoundingMetrics.rightBearing = dxSqr + bmSqr.width + |
michael@0 | 321 | std::max(bmBase.width, bmBase.rightBearing); |
michael@0 | 322 | |
michael@0 | 323 | aDesiredSize.Width() = mBoundingMetrics.width; |
michael@0 | 324 | aDesiredSize.mBoundingMetrics = mBoundingMetrics; |
michael@0 | 325 | GatherAndStoreOverflow(&aDesiredSize); |
michael@0 | 326 | |
michael@0 | 327 | // place the index |
michael@0 | 328 | nscoord dx = dxIndex; |
michael@0 | 329 | nscoord dy = aDesiredSize.TopAscent() - (indexRaisedAscent + indexSize.TopAscent() - bmIndex.ascent); |
michael@0 | 330 | FinishReflowChild(indexFrame, aPresContext, indexSize, nullptr, |
michael@0 | 331 | MirrorIfRTL(aDesiredSize.Width(), indexSize.Width(), dx), |
michael@0 | 332 | dy, 0); |
michael@0 | 333 | |
michael@0 | 334 | // place the radical symbol and the radical bar |
michael@0 | 335 | dx = dxSqr; |
michael@0 | 336 | dy = indexClearance + leading; // leave a leading at the top |
michael@0 | 337 | mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.Width(), bmSqr.width, dx), |
michael@0 | 338 | dy, bmSqr.width, bmSqr.ascent + bmSqr.descent)); |
michael@0 | 339 | dx += bmSqr.width; |
michael@0 | 340 | mBarRect.SetRect(MirrorIfRTL(aDesiredSize.Width(), bmBase.width, dx), |
michael@0 | 341 | dy, bmBase.width, ruleThickness); |
michael@0 | 342 | |
michael@0 | 343 | // place the base |
michael@0 | 344 | dy = aDesiredSize.TopAscent() - baseSize.TopAscent(); |
michael@0 | 345 | FinishReflowChild(baseFrame, aPresContext, baseSize, nullptr, |
michael@0 | 346 | MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx), |
michael@0 | 347 | dy, 0); |
michael@0 | 348 | |
michael@0 | 349 | mReference.x = 0; |
michael@0 | 350 | mReference.y = aDesiredSize.TopAscent(); |
michael@0 | 351 | |
michael@0 | 352 | aStatus = NS_FRAME_COMPLETE; |
michael@0 | 353 | NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); |
michael@0 | 354 | return NS_OK; |
michael@0 | 355 | } |
michael@0 | 356 | |
michael@0 | 357 | /* virtual */ void |
michael@0 | 358 | nsMathMLmrootFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize) |
michael@0 | 359 | { |
michael@0 | 360 | nsIFrame* baseFrame = mFrames.FirstChild(); |
michael@0 | 361 | nsIFrame* indexFrame = nullptr; |
michael@0 | 362 | if (baseFrame) |
michael@0 | 363 | indexFrame = baseFrame->GetNextSibling(); |
michael@0 | 364 | if (!indexFrame || indexFrame->GetNextSibling()) { |
michael@0 | 365 | ReflowError(*aRenderingContext, aDesiredSize); |
michael@0 | 366 | return; |
michael@0 | 367 | } |
michael@0 | 368 | |
michael@0 | 369 | nscoord baseWidth = |
michael@0 | 370 | nsLayoutUtils::IntrinsicForContainer(aRenderingContext, baseFrame, |
michael@0 | 371 | nsLayoutUtils::PREF_WIDTH); |
michael@0 | 372 | nscoord indexWidth = |
michael@0 | 373 | nsLayoutUtils::IntrinsicForContainer(aRenderingContext, indexFrame, |
michael@0 | 374 | nsLayoutUtils::PREF_WIDTH); |
michael@0 | 375 | nscoord sqrWidth = mSqrChar.GetMaxWidth(PresContext(), *aRenderingContext); |
michael@0 | 376 | |
michael@0 | 377 | nscoord dxSqr; |
michael@0 | 378 | nsRefPtr<nsFontMetrics> fm; |
michael@0 | 379 | nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); |
michael@0 | 380 | GetRadicalXOffsets(indexWidth, sqrWidth, fm, nullptr, &dxSqr); |
michael@0 | 381 | |
michael@0 | 382 | nscoord width = dxSqr + sqrWidth + baseWidth; |
michael@0 | 383 | |
michael@0 | 384 | aDesiredSize.Width() = width; |
michael@0 | 385 | aDesiredSize.mBoundingMetrics.width = width; |
michael@0 | 386 | aDesiredSize.mBoundingMetrics.leftBearing = 0; |
michael@0 | 387 | aDesiredSize.mBoundingMetrics.rightBearing = width; |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | // ---------------------- |
michael@0 | 391 | // the Style System will use these to pass the proper style context to our MathMLChar |
michael@0 | 392 | nsStyleContext* |
michael@0 | 393 | nsMathMLmrootFrame::GetAdditionalStyleContext(int32_t aIndex) const |
michael@0 | 394 | { |
michael@0 | 395 | switch (aIndex) { |
michael@0 | 396 | case NS_SQR_CHAR_STYLE_CONTEXT_INDEX: |
michael@0 | 397 | return mSqrChar.GetStyleContext(); |
michael@0 | 398 | break; |
michael@0 | 399 | default: |
michael@0 | 400 | return nullptr; |
michael@0 | 401 | } |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | void |
michael@0 | 405 | nsMathMLmrootFrame::SetAdditionalStyleContext(int32_t aIndex, |
michael@0 | 406 | nsStyleContext* aStyleContext) |
michael@0 | 407 | { |
michael@0 | 408 | switch (aIndex) { |
michael@0 | 409 | case NS_SQR_CHAR_STYLE_CONTEXT_INDEX: |
michael@0 | 410 | mSqrChar.SetStyleContext(aStyleContext); |
michael@0 | 411 | break; |
michael@0 | 412 | } |
michael@0 | 413 | } |