static void GetCharSpacing(nsMathMLChar* aMathMLChar, nsOperatorFlags aForm, PRInt32 aScriptLevel, nscoord em, nscoord& aLeftSpace, nscoord& aRightSpace) { nsAutoString data; aMathMLChar->GetData(data); nsOperatorFlags flags = 0; float lspace = 0.0f; float rspace = 0.0f; PRBool found = nsMathMLOperators::LookupOperator(data, aForm, &flags, &lspace, &rspace); // We don't want extra space when we are a script if (found && aScriptLevel > 0) { lspace /= 2.0f; rspace /= 2.0f; } aLeftSpace = NSToCoordRound(lspace * em); aRightSpace = NSToCoordRound(rspace * em); }
/* static */ nscoord nsMathMLFrame::CalcLength(nsPresContext* aPresContext, nsStyleContext* aStyleContext, const nsCSSValue& aCSSValue) { NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit"); if (aCSSValue.IsFixedLengthUnit()) { return aCSSValue.GetLengthTwips(); } nsCSSUnit unit = aCSSValue.GetUnit(); if (eCSSUnit_Pixel == unit) { return NSFloatPixelsToTwips(aCSSValue.GetFloatValue(), aPresContext->ScaledPixelsToTwips()); } else if (eCSSUnit_EM == unit) { const nsStyleFont* font = aStyleContext->GetStyleFont(); return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size); } else if (eCSSUnit_XHeight == unit) { nscoord xHeight; const nsStyleFont* font = aStyleContext->GetStyleFont(); nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font->mFont); fm->GetXHeight(xHeight); return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight); } return 0; }
/* static */ nscoord nsMathMLFrame::CalcLength(nsPresContext* aPresContext, nsStyleContext* aStyleContext, const nsCSSValue& aCSSValue) { NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit"); if (aCSSValue.IsFixedLengthUnit()) { return aCSSValue.GetFixedLength(aPresContext); } if (aCSSValue.IsPixelLengthUnit()) { return aCSSValue.GetPixelLength(); } nsCSSUnit unit = aCSSValue.GetUnit(); if (eCSSUnit_EM == unit) { const nsStyleFont* font = aStyleContext->GetStyleFont(); return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size); } else if (eCSSUnit_XHeight == unit) { nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext, getter_AddRefs(fm)); nscoord xHeight = fm->XHeight(); return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight); } // MathML doesn't specify other CSS units such as rem or ch NS_ERROR("Unsupported unit"); return 0; }
/* Performs the matrix multiplication necessary to multiply the two matrices, * then hands back a reference to ourself. */ nsStyleTransformMatrix& nsStyleTransformMatrix::operator *= (const nsStyleTransformMatrix &aOther) { /* We'll buffer all of our results into a temporary storage location * during this operation since we don't want to overwrite the values of * the old matrix with the values of the new. */ float newMatrix[4]; nscoord newDelta[2]; float newX[2]; float newY[2]; /* [this] [aOther] * |a1 c1 e1| |a0 c0 e0| |a0a1 + b0c1 c0a1 + d0c1 e0a1 + f0c1 + e1| * |b1 d1 f1|x|b0 d0 f0| = |a0b1 + b0d1 c0b1 + d0d1 e0b1 + f0d1 + f1| * |0 0 1 | | 0 0 1| | 0 0 1| */ newMatrix[0] = aOther.mMain[0] * mMain[0] + aOther.mMain[1] * mMain[2]; newMatrix[1] = aOther.mMain[0] * mMain[1] + aOther.mMain[1] * mMain[3]; newMatrix[2] = aOther.mMain[2] * mMain[0] + aOther.mMain[3] * mMain[2]; newMatrix[3] = aOther.mMain[2] * mMain[1] + aOther.mMain[3] * mMain[3]; newDelta[0] = NSToCoordRound(aOther.mDelta[0] * mMain[0] + aOther.mDelta[1] * mMain[2]) + mDelta[0]; newDelta[1] = NSToCoordRound(aOther.mDelta[0] * mMain[1] + aOther.mDelta[1] * mMain[3]) + mDelta[1]; /* For consistent terminology, let u0, u1, v0, and v1 be the four transform * coordinates from our matrix, and let x0, x1, y0, and y1 be the four * transform coordinates from the other matrix. Then the new transform * coordinates are: * * u0' = a1u0 + c1u1 + x0 * u1' = b1u0 + d1u1 + x1 * v0' = a1v0 + c1v1 + y0 * v1' = b1v0 + d1v1 + y1 */ newX[0] = mMain[0] * aOther.mX[0] + mMain[2] * aOther.mX[1] + mX[0]; newX[1] = mMain[1] * aOther.mX[0] + mMain[3] * aOther.mX[1] + mX[1]; newY[0] = mMain[0] * aOther.mY[0] + mMain[2] * aOther.mY[1] + mY[0]; newY[1] = mMain[1] * aOther.mY[0] + mMain[3] * aOther.mY[1] + mY[1]; /* Now, write everything back in. */ for (PRInt32 index = 0; index < 4; ++index) mMain[index] = newMatrix[index]; for (PRInt32 index = 0; index < 2; ++index) { mDelta[index] = newDelta[index]; mX[index] = newX[index]; mY[index] = newY[index]; } /* As promised, return a reference to ourselves. */ return *this; }
void nsMathMLmpaddedFrame::UpdateValue(int32_t aSign, int32_t aPseudoUnit, const nsCSSValue& aCSSValue, const ReflowOutput& aDesiredSize, nscoord& aValueToUpdate, float aFontSizeInflation) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aDesiredSize.Width(); break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aDesiredSize.BlockStartAscent(); break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aDesiredSize.Height() - aDesiredSize.BlockStartAscent(); break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ERROR("Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue, aFontSizeInflation); if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; } }
void nsMathMLmpaddedFrame::UpdateValue(PRInt32 aSign, PRInt32 aPseudoUnit, const nsCSSValue& aCSSValue, const nsBoundingMetrics& aBoundingMetrics, nscoord& aValueToUpdate) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aBoundingMetrics.width; break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aBoundingMetrics.ascent; break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aBoundingMetrics.descent; break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ERROR("Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue); nscoord oldValue = aValueToUpdate; if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; } }
/* static */ void nsMathMLFrame::ParseNumericValue(const nsString& aString, nscoord* aLengthValue, uint32_t aFlags, nsPresContext* aPresContext, nsStyleContext* aStyleContext) { nsCSSValue cssValue; if (!nsMathMLElement::ParseNumericValue(aString, cssValue, aFlags, aPresContext->Document())) { // Invalid attribute value. aLengthValue remains unchanged, so the default // length value is used. return; } nsCSSUnit unit = cssValue.GetUnit(); if (unit == eCSSUnit_Percent || unit == eCSSUnit_Number) { // Relative units. A multiple of the default length value is used. *aLengthValue = NSToCoordRound(*aLengthValue * (unit == eCSSUnit_Percent ? cssValue.GetPercentValue() : cssValue.GetFloatValue())); return; } // Absolute units. *aLengthValue = CalcLength(aPresContext, aStyleContext, cssValue); }
NS_IMETHODIMP nsRenderingContextQt::GetTextDimensions(const char* aString, PRUint32 aLength, nsTextDimensions& aDimensions) { aDimensions.Clear(); if (aLength == 0) return NS_OK; if (nsnull == aString) return NS_ERROR_FAILURE; QString str = QString::fromLatin1(aString, aLength); QFontMetrics fm(mCurrentFont->font); aDimensions.ascent = NSToCoordRound(fm.ascent()*mP2T); aDimensions.descent = NSToCoordRound(fm.descent()*mP2T); aDimensions.width = NSToCoordRound(fm.width(str)*mP2T); return NS_OK; }
static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM, bool aVertical) { nsPresContext* pc = aFrame->PresContext(); float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() / MM_PER_INCH_FLOAT); return NSToCoordRound(result); }
void nsMeterFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { bool vertical = StyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL; nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame, nsSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE)); nscoord size = vertical ? aReflowState.ComputedHeight() : aReflowState.ComputedWidth(); nscoord xoffset = aReflowState.mComputedBorderPadding.left; nscoord yoffset = aReflowState.mComputedBorderPadding.top; // NOTE: Introduce a new function getPosition in the content part ? double position, max, min, value; nsCOMPtr<nsIDOMHTMLMeterElement> meterElement = do_QueryInterface(mContent); meterElement->GetMax(&max); meterElement->GetMin(&min); meterElement->GetValue(&value); position = max - min; position = position != 0 ? (value - min) / position : 1; size = NSToCoordRound(size * position); if (!vertical && StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { xoffset += aReflowState.ComputedWidth() - size; } // The bar position is *always* constrained. if (vertical) { // We want the bar to begin at the bottom. yoffset += aReflowState.ComputedHeight() - size; size -= reflowState.mComputedMargin.TopBottom() + reflowState.mComputedBorderPadding.TopBottom(); size = std::max(size, 0); reflowState.SetComputedHeight(size); } else { size -= reflowState.mComputedMargin.LeftRight() + reflowState.mComputedBorderPadding.LeftRight(); size = std::max(size, 0); reflowState.SetComputedWidth(size); } xoffset += reflowState.mComputedMargin.left; yoffset += reflowState.mComputedMargin.top; nsHTMLReflowMetrics barDesiredSize; ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, xoffset, yoffset, 0); }
NS_IMETHODIMP nsRenderingContextQt::GetBoundingMetrics(const char *aString,PRUint32 aLength, nsBoundingMetrics &aBoundingMetrics) { aBoundingMetrics.Clear(); if (0 >= aLength || !aString || !mCurrentFont) return(NS_ERROR_FAILURE); QString str = QString::fromLatin1(aString, aLength); QFontMetrics fm(mCurrentFont->font); QRect br = fm.boundingRect(str); aBoundingMetrics.width = NSToCoordRound(br.width() * mP2T); aBoundingMetrics.ascent = NSToCoordRound(-br.y() * mP2T); aBoundingMetrics.descent = NSToCoordRound(br.bottom() * mP2T); aBoundingMetrics.leftBearing = NSToCoordRound(br.x() * mP2T); aBoundingMetrics.rightBearing = NSToCoordRound(fm.rightBearing(str.at(aLength - 1)) * mP2T); return NS_OK; }
static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM, bool aVertical) { nsPresContext* pc = aFrame->PresContext(); nsIPresShell* presShell = pc->PresShell(); float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() / MM_PER_INCH_FLOAT) * (aVertical ? presShell->GetYResolution() : presShell->GetXResolution()); return NSToCoordRound(result); }
static inline nscoord AllocateUnassigned(nscoord aUnassignedSpace, float aShare) { if (aShare == 1.0f) { // This happens when the numbers we're dividing to get aShare // are equal. We want to return unassignedSpace exactly, even // if it can't be precisely round-tripped through float. return aUnassignedSpace; } return NSToCoordRound(float(aUnassignedSpace) * aShare); }
NS_IMETHODIMP nsRenderingContextPh :: GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth ) { PhRect_t extent; /* Check for the very common case of trying to get the width of a single space */ if( aString[0] == ' ' && aLength == 1 ) return mFontMetrics->GetSpaceWidth(aWidth); PfExtent( &extent, NULL, mPhotonFontName, 0L, 0L, aString, aLength, PF_SIMPLE_METRICS, NULL ); aWidth = NSToCoordRound((int) ((extent.lr.x - extent.ul.x + 1) * mP2T)); return NS_OK; }
static nscoord AppUnitsFromMM(nsIFrame* aFrame, uint32_t aMM) { nsPresContext* pc = aFrame->PresContext(); nsIPresShell* presShell = pc->PresShell(); float result = float(aMM) * (pc->DeviceContext()->AppUnitsPerPhysicalInch() / MM_PER_INCH_FLOAT); if (presShell->ScaleToResolution()) { result = result / presShell->GetResolution(); } return NSToCoordRound(result); }
NS_IMETHODIMP nsRenderingContextQt::GetWidth(char aC, nscoord &aWidth) { if (!mFontMetrics) return NS_ERROR_FAILURE; if (aC == ' ') { aWidth = mCurrentFont->mSpaceWidth; } else { QFontMetrics fm(mCurrentFont->font); aWidth = NSToCoordRound(fm.width(aC) * mP2T); } return NS_OK; }
nscoord nsMathMLmfracFrame::CalcLineThickness(nsPresContext* aPresContext, nsStyleContext* aStyleContext, nsString& aThicknessAttribute, nscoord onePixel, nscoord aDefaultRuleThickness) { nscoord defaultThickness = aDefaultRuleThickness; nscoord lineThickness = aDefaultRuleThickness; nscoord minimumThickness = onePixel; if (!aThicknessAttribute.IsEmpty()) { if (aThicknessAttribute.EqualsLiteral("thin")) { lineThickness = NSToCoordFloor(defaultThickness * THIN_FRACTION_LINE); minimumThickness = onePixel * THIN_FRACTION_LINE_MINIMUM_PIXELS; // should visually decrease by at least one pixel, if default is not a pixel if (defaultThickness > onePixel && lineThickness > defaultThickness - onePixel) lineThickness = defaultThickness - onePixel; } else if (aThicknessAttribute.EqualsLiteral("medium")) { lineThickness = NSToCoordRound(defaultThickness * MEDIUM_FRACTION_LINE); minimumThickness = onePixel * MEDIUM_FRACTION_LINE_MINIMUM_PIXELS; // should visually increase by at least one pixel if (lineThickness < defaultThickness + onePixel) lineThickness = defaultThickness + onePixel; } else if (aThicknessAttribute.EqualsLiteral("thick")) { lineThickness = NSToCoordCeil(defaultThickness * THICK_FRACTION_LINE); minimumThickness = onePixel * THICK_FRACTION_LINE_MINIMUM_PIXELS; // should visually increase by at least two pixels if (lineThickness < defaultThickness + 2*onePixel) lineThickness = defaultThickness + 2*onePixel; } else { // see if it is a plain number, or a percentage, or a h/v-unit like 1ex, 2px, 1em nsCSSValue cssValue; if (ParseNumericValue(aThicknessAttribute, cssValue)) { nsCSSUnit unit = cssValue.GetUnit(); if (eCSSUnit_Number == unit) lineThickness = nscoord(float(defaultThickness) * cssValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) lineThickness = nscoord(float(defaultThickness) * cssValue.GetPercentValue()); else if (eCSSUnit_Null != unit) lineThickness = CalcLength(aPresContext, aStyleContext, cssValue); } } } // use minimum if the lineThickness is a non-zero value less than minimun if (lineThickness && lineThickness < minimumThickness) lineThickness = minimumThickness; return lineThickness; }
nscoord nsFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength, nsRenderingContext *aContext) { if (aLength == 0) return 0; if (aLength == 1 && aString[0] == ' ') return SpaceWidth(); StubPropertyProvider provider; AutoTextRun textRun(this, aContext, aString, aLength); return NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)); }
NS_IMETHODIMP nsRenderingContextQt::GetWidth(const char *aString, PRUint32 aLength,nscoord &aWidth) { if (0 == aLength) { aWidth = 0; return NS_OK; } if (nsnull == aString || nsnull == mCurrentFont) return NS_ERROR_FAILURE; QFontMetrics curFontMetrics(mCurrentFont->font); int rawWidth = curFontMetrics.width(QString::fromLatin1(aString, aLength)); aWidth = NSToCoordRound(rawWidth * mP2T); return NS_OK; }
NS_IMETHODIMP nsRenderingContextQt::GetTextDimensions(const PRUnichar *aString, PRUint32 aLength, nsTextDimensions &aDimensions, PRInt32 *aFontID) { aDimensions.Clear(); if (0 == aLength) return NS_OK; if (nsnull == aString) return NS_ERROR_FAILURE; QConstString str((const QChar *)aString, aLength); QFontMetrics fm(mCurrentFont->font); aDimensions.ascent = NSToCoordRound(fm.ascent()*mP2T); aDimensions.descent = NSToCoordRound(fm.descent()*mP2T); aDimensions.width = NSToCoordRound(fm.width(str.string())*mP2T); if (nsnull != aFontID) *aFontID = 0; return NS_OK; }
static void GetTextRunBoundingMetrics(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aLength, nsThebesRenderingContext *aContext, nsBoundingMetrics &aBoundingMetrics) { StubPropertyProvider provider; gfxTextRun::Metrics theMetrics = aTextRun->MeasureText(aStart, aLength, PR_TRUE, aContext->ThebesContext(), &provider); aBoundingMetrics.leftBearing = NSToCoordFloor(theMetrics.mBoundingBox.X()); aBoundingMetrics.rightBearing = NSToCoordCeil(theMetrics.mBoundingBox.XMost()); aBoundingMetrics.width = NSToCoordRound(theMetrics.mAdvanceWidth); aBoundingMetrics.ascent = NSToCoordCeil(- theMetrics.mBoundingBox.Y()); aBoundingMetrics.descent = NSToCoordCeil(theMetrics.mBoundingBox.YMost()); }
nscoord nsFontMetrics::GetWidth(const char16_t* aString, uint32_t aLength, DrawTarget* aDrawTarget) { if (aLength == 0) return 0; if (aLength == 1 && aString[0] == ' ') return SpaceWidth(); StubPropertyProvider provider; AutoTextRun textRun(this, aDrawTarget, aString, aLength); if (textRun.get()) { return NSToCoordRound( textRun->GetAdvanceWidth(Range(0, aLength), &provider)); } return 0; }
NS_IMETHODIMP nsRenderingContextQt::GetWidth(const PRUnichar *aString, PRUint32 aLength,nscoord &aWidth, PRInt32 *aFontID) { if (aFontID) *aFontID = 0; if (0 == aLength) { aWidth = 0; return NS_OK; } if (!aString || !mFontMetrics) return NS_ERROR_FAILURE; QConstString cstr((const QChar *)aString, aLength); QFontMetrics curFontMetrics(mCurrentFont->font); int rawWidth = curFontMetrics.width(cstr.string()); aWidth = NSToCoordRound(rawWidth * mP2T); return NS_OK; }
nsSize nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aCBSize, nscoord aAvailableWidth, nsSize aMargin, nsSize aBorder, nsSize aPadding, bool aShrinkWrap) { nsSize autoSize; autoSize.height = autoSize.width = NSToCoordRound(StyleFont()->mFont.size * nsLayoutUtils::FontSizeInflationFor(this)); // 1em if (StyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL) { autoSize.height *= 10; // 10em } else { autoSize.width *= 10; // 10em } return autoSize; }
nsBoundingMetrics nsFontMetrics::GetBoundingMetrics(const PRUnichar *aString, PRUint32 aLength, nsRenderingContext *aContext) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(this, aContext, aString, aLength); gfxTextRun::Metrics theMetrics = textRun->MeasureText(0, aLength, gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS, aContext->ThebesContext(), &provider); nsBoundingMetrics m; m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); return m; }
nsresult nsThebesFontMetrics::GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth, nsThebesRenderingContext *aContext) { if (aLength == 0) { aWidth = 0; return NS_OK; } // callers that hit this should not be so stupid if ((aLength == 1) && (aString[0] == ' ')) return GetSpaceWidth(aWidth); StubPropertyProvider provider; AutoTextRun textRun(this, aContext, aString, aLength); if (!textRun.get()) return NS_ERROR_FAILURE; aWidth = NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)); return NS_OK; }
static nsBoundingMetrics GetTextBoundingMetrics(nsFontMetrics* aMetrics, const char16_t* aString, uint32_t aLength, mozilla::gfx::DrawTarget* aDrawTarget, gfxFont::BoundingBoxType aType) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(aMetrics, aDrawTarget, aString, aLength); nsBoundingMetrics m; if (textRun.get()) { gfxTextRun::Metrics theMetrics = textRun->MeasureText( gfxTextRun::Range(0, aLength), aType, aDrawTarget, &provider); m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); } return m; }
static void GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth, nsIFontMetrics* aFontMetrics, nscoord* aIndexOffset, nscoord* aSqrOffset) { // The index is tucked in closer to the radical while making sure // that the kern does not make the index and radical collide nscoord dxIndex, dxSqr; nscoord xHeight = 0; aFontMetrics->GetXHeight(xHeight); nscoord indexRadicalKern = NSToCoordRound(1.35f * xHeight); if (indexRadicalKern > aIndexWidth) { dxIndex = indexRadicalKern - aIndexWidth; dxSqr = 0; } else { dxIndex = 0; dxSqr = aIndexWidth - indexRadicalKern; } // avoid collision by leaving a minimum space between index and radical nscoord minimumClearance = aSqrWidth/2; if (dxIndex + aIndexWidth + minimumClearance > dxSqr + aSqrWidth) { if (aIndexWidth + minimumClearance < aSqrWidth) { dxIndex = aSqrWidth - (aIndexWidth + minimumClearance); dxSqr = 0; } else { dxIndex = 0; dxSqr = (aIndexWidth + minimumClearance) - aSqrWidth; } } if (aIndexOffset) *aIndexOffset = dxIndex; if (aSqrOffset) *aSqrOffset = dxSqr; }
static nsBoundingMetrics GetTextBoundingMetrics(nsFontMetrics* aMetrics, const PRUnichar *aString, uint32_t aLength, nsRenderingContext *aContext, gfxFont::BoundingBoxType aType) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(aMetrics, aContext, aString, aLength); nsBoundingMetrics m; if (textRun.get()) { gfxTextRun::Metrics theMetrics = textRun->MeasureText(0, aLength, aType, aContext->ThebesContext(), &provider); m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); } return m; }
NS_IMETHODIMP nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv; aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); PRInt32 i; const nsStyleFont* font = GetStyleFont(); nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); aReflowState.rendContext->SetFont(fm); nscoord axisHeight, em; GetAxisHeight(*aReflowState.rendContext, fm, axisHeight); GetEmHeight(fm, em); // leading to be left at the top and the bottom of stretched chars nscoord leading = NSToCoordRound(0.2f * em); ///////////// // Reflow children // Asking each child to cache its bounding metrics // Note that we don't use the base method nsMathMLContainerFrame::Reflow() // because we want to stretch our fences, separators and stretchy frames using // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base // method here, our stretchy frames will be stretched and placed, and we may // end up stretching our fences/separators with a different aDesiredSize. // XXX The above decision was revisited in bug 121748 and this code can be // refactored to use nsMathMLContainerFrame::Reflow() at some stage. nsReflowStatus childStatus; nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsIFrame* firstChild = GetFirstChild(nsnull); nsIFrame* childFrame = firstChild; nscoord ascent = 0, descent = 0; if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) { // We use the ASCII metrics to get our minimum height. This way, // if we have borders or a background, they will fit better with // other elements on the line. ascent = fm->MaxAscent(); descent = fm->MaxDescent(); } while (childFrame) { nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(firstChild, childFrame); return rv; } SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; childFrame = childFrame->GetNextSibling(); } ///////////// // Ask stretchy children to stretch themselves nsBoundingMetrics containerSize; nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; GetPreferredStretchSize(*aReflowState.rendContext, 0, /* i.e., without embellishments */ stretchDir, containerSize); childFrame = firstChild; while (childFrame) { nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame); if (mathmlChild) { nsHTMLReflowMetrics childDesiredSize; // retrieve the metrics that was stored at the previous pass GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); mathmlChild->Stretch(*aReflowState.rendContext, stretchDir, containerSize, childDesiredSize); // store the updated metrics SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; } childFrame = childFrame->GetNextSibling(); } // bug 121748: for surrounding fences & separators, use a size that covers everything GetPreferredStretchSize(*aReflowState.rendContext, STRETCH_CONSIDER_EMBELLISHMENTS, stretchDir, containerSize); ////////////////////////////////////////// // Prepare the opening fence, separators, and closing fence, and // adjust the origin of children. // we need to center around the axis nscoord delta = NS_MAX(containerSize.ascent - axisHeight, containerSize.descent + axisHeight); containerSize.ascent = delta + axisHeight; containerSize.descent = delta - axisHeight; ///////////////// // opening fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar, NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ///////////////// // separators ... for (i = 0; i < mSeparatorsCount; i++) { ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i], NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); } ///////////////// // closing fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar, NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ////////////////// // Adjust the origins of each child. // and update our bounding metrics i = 0; nscoord dx = 0; nsBoundingMetrics bm; PRBool firstTime = PR_TRUE; if (mOpenChar) { PlaceChar(mOpenChar, ascent, bm, dx); aDesiredSize.mBoundingMetrics = bm; firstTime = PR_FALSE; } childFrame = firstChild; while (childFrame) { nsHTMLReflowMetrics childSize; GetReflowAndBoundingMetricsFor(childFrame, childSize, bm); if (firstTime) { firstTime = PR_FALSE; aDesiredSize.mBoundingMetrics = bm; } else aDesiredSize.mBoundingMetrics += bm; FinishReflowChild(childFrame, aPresContext, nsnull, childSize, dx, ascent - childSize.ascent, 0); dx += childSize.width; if (i < mSeparatorsCount) { PlaceChar(&mSeparatorsChar[i], ascent, bm, dx); aDesiredSize.mBoundingMetrics += bm; } i++; childFrame = childFrame->GetNextSibling(); } if (mCloseChar) { PlaceChar(mCloseChar, ascent, bm, dx); if (firstTime) aDesiredSize.mBoundingMetrics = bm; else aDesiredSize.mBoundingMetrics += bm; } aDesiredSize.width = aDesiredSize.mBoundingMetrics.width; aDesiredSize.height = ascent + descent; aDesiredSize.ascent = ascent; SetBoundingMetrics(aDesiredSize.mBoundingMetrics); SetReference(nsPoint(0, aDesiredSize.ascent)); // see if we should fix the spacing FixInterFrameSpacing(aDesiredSize); // Finished with these: ClearSavedChildMetrics(); // Set our overflow area GatherAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }