зеркало из https://github.com/mozilla/gecko-dev.git
GetIntrinsicWidth for mroot, mfenced, and mfrac. b=363240, r+sr=roc
This commit is contained in:
Родитель
e387e0eeb1
Коммит
15c6fd9ec5
|
@ -243,6 +243,13 @@ nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext,
|
|||
mOpenChar, mCloseChar, mSeparatorsChar, mSeparatorsCount);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmfencedFrame::GetIntrinsicWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
return doGetIntrinsicWidth(aRenderingContext, this, mOpenChar, mCloseChar,
|
||||
mSeparatorsChar, mSeparatorsCount);
|
||||
}
|
||||
|
||||
// exported routine that both mfenced and mfrac share.
|
||||
// mfrac uses this when its bevelled attribute is set.
|
||||
/*static*/ nsresult
|
||||
|
@ -468,6 +475,32 @@ nsMathMLmfencedFrame::doReflow(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// helper functions to perform the common task of formatting our chars
|
||||
/*static*/ nsresult
|
||||
nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
||||
|
@ -483,20 +516,9 @@ nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
|||
nscoord& aDescent)
|
||||
{
|
||||
if (aMathMLChar && 0 < aMathMLChar->Length()) {
|
||||
nsOperatorFlags flags = 0;
|
||||
float leftSpace = 0.0f;
|
||||
float rightSpace = 0.0f;
|
||||
|
||||
nsAutoString data;
|
||||
aMathMLChar->GetData(data);
|
||||
PRBool found = nsMathMLOperators::LookupOperator(data, aForm,
|
||||
&flags, &leftSpace, &rightSpace);
|
||||
|
||||
// If we don't want extra space when we are a script
|
||||
if (found && aScriptLevel > 0) {
|
||||
leftSpace /= 2.0f;
|
||||
rightSpace /= 2.0f;
|
||||
}
|
||||
nscoord leftSpace;
|
||||
nscoord rightSpace;
|
||||
GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
|
||||
|
||||
// stretch the char to the appropriate height if it is not big enough.
|
||||
nsBoundingMetrics charSize;
|
||||
|
@ -515,6 +537,8 @@ nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
|||
// GetBoundingMetrics failed)
|
||||
leading = 0;
|
||||
if (NS_FAILED(res)) {
|
||||
nsAutoString data;
|
||||
aMathMLChar->GetData(data);
|
||||
nsTextDimensions dimensions;
|
||||
aRenderingContext.GetTextDimensions(data.get(), data.Length(), dimensions);
|
||||
charSize.ascent = dimensions.ascent;
|
||||
|
@ -532,11 +556,11 @@ nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
|
|||
aDescent = charSize.descent + leading;
|
||||
|
||||
// account the spacing
|
||||
charSize.width += NSToCoordRound((leftSpace + rightSpace) * em);
|
||||
charSize.width += leftSpace + rightSpace;
|
||||
|
||||
// x-origin is used to store lspace ...
|
||||
// y-origin is used to stored the ascent ...
|
||||
aMathMLChar->SetRect(nsRect(NSToCoordRound(leftSpace * em),
|
||||
aMathMLChar->SetRect(nsRect(leftSpace,
|
||||
charSize.ascent, charSize.width,
|
||||
charSize.ascent + charSize.descent));
|
||||
}
|
||||
|
@ -553,6 +577,7 @@ nsMathMLmfencedFrame::PlaceChar(nsMathMLChar* aMathMLChar,
|
|||
|
||||
// the char's x-origin was used to store lspace ...
|
||||
// the char's y-origin was used to store the ascent ...
|
||||
// the char's width was used to store the advance with (with spacing) ...
|
||||
nsRect rect;
|
||||
aMathMLChar->GetRect(rect);
|
||||
|
||||
|
@ -574,6 +599,77 @@ nsMathMLmfencedFrame::PlaceChar(nsMathMLChar* aMathMLChar,
|
|||
dx += rect.width;
|
||||
}
|
||||
|
||||
static nscoord
|
||||
GetMaxCharWidth(nsPresContext* aPresContext,
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
nsMathMLChar* aMathMLChar,
|
||||
nsOperatorFlags aForm,
|
||||
PRInt32 aScriptLevel,
|
||||
nscoord em)
|
||||
{
|
||||
nscoord width = aMathMLChar->GetMaxWidth(aPresContext, *aRenderingContext);
|
||||
|
||||
if (0 < aMathMLChar->Length()) {
|
||||
nscoord leftSpace;
|
||||
nscoord rightSpace;
|
||||
GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
|
||||
|
||||
width += leftSpace + rightSpace;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmfencedFrame::doGetIntrinsicWidth(nsIRenderingContext* aRenderingContext,
|
||||
nsMathMLContainerFrame* aForFrame,
|
||||
nsMathMLChar* aOpenChar,
|
||||
nsMathMLChar* aCloseChar,
|
||||
nsMathMLChar* aSeparatorsChar,
|
||||
PRInt32 aSeparatorsCount)
|
||||
{
|
||||
nscoord width = 0;
|
||||
|
||||
nsPresContext* presContext = aForFrame->PresContext();
|
||||
const nsStyleFont* font = aForFrame->GetStyleFont();
|
||||
nsCOMPtr<nsIFontMetrics> fm = presContext->GetMetricsFor(font->mFont);
|
||||
nscoord em;
|
||||
GetEmHeight(fm, em);
|
||||
|
||||
if (aOpenChar) {
|
||||
width +=
|
||||
GetMaxCharWidth(presContext, aRenderingContext, aOpenChar,
|
||||
NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
|
||||
}
|
||||
|
||||
PRInt32 i = 0;
|
||||
nsIFrame* childFrame = aForFrame->GetFirstChild(nsnull);
|
||||
while (childFrame) {
|
||||
// XXX This includes margin while Reflow currently doesn't consider
|
||||
// margin, so we may end up with too much space, but, with stretchy
|
||||
// characters, this is an approximation anyway.
|
||||
width += nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
|
||||
if (i < aSeparatorsCount) {
|
||||
width +=
|
||||
GetMaxCharWidth(presContext, aRenderingContext, &aSeparatorsChar[i],
|
||||
NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, em);
|
||||
}
|
||||
i++;
|
||||
|
||||
childFrame = childFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
if (aCloseChar) {
|
||||
width +=
|
||||
GetMaxCharWidth(presContext, aRenderingContext, aCloseChar,
|
||||
NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmfencedFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,9 @@ public:
|
|||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsIRenderingContext* aRenderingContext);
|
||||
|
||||
NS_IMETHOD
|
||||
AttributeChanged(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
|
@ -87,8 +90,8 @@ public:
|
|||
virtual nscoord
|
||||
FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize);
|
||||
|
||||
// exported routine that both mfenced and mfrac share.
|
||||
// mfrac uses this when its bevelled attribute is set.
|
||||
// exported routines that both mfenced and mfrac share.
|
||||
// mfrac uses these when its bevelled attribute is set.
|
||||
static nsresult
|
||||
doReflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
|
@ -100,6 +103,14 @@ public:
|
|||
nsMathMLChar* aSeparatorsChar,
|
||||
PRInt32 aSeparatorsCount);
|
||||
|
||||
static nscoord
|
||||
doGetIntrinsicWidth(nsIRenderingContext* aRenderingContext,
|
||||
nsMathMLContainerFrame* aForFrame,
|
||||
nsMathMLChar* aOpenChar,
|
||||
nsMathMLChar* aCloseChar,
|
||||
nsMathMLChar* aSeparatorsChar,
|
||||
PRInt32 aSeparatorsCount);
|
||||
|
||||
// helper routines to format the MathMLChars involved here
|
||||
static nsresult
|
||||
ReflowChar(nsPresContext* aPresContext,
|
||||
|
|
|
@ -246,6 +246,20 @@ nsMathMLmfracFrame::Reflow(nsPresContext* aPresContext,
|
|||
aReflowState, aStatus);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmfracFrame::GetIntrinsicWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
if (mSlashChar) {
|
||||
// bevelled rendering
|
||||
return nsMathMLmfencedFrame::doGetIntrinsicWidth(aRenderingContext, this,
|
||||
nsnull, nsnull,
|
||||
mSlashChar, 1);
|
||||
}
|
||||
|
||||
// default rendering
|
||||
return nsMathMLContainerFrame::GetIntrinsicWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsMathMLmfracFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
|
|
|
@ -112,6 +112,9 @@ public:
|
|||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsIRenderingContext* aRenderingContext);
|
||||
|
||||
NS_IMETHOD
|
||||
Place(nsIRenderingContext& aRenderingContext,
|
||||
PRBool aPlaceOrigin,
|
||||
|
|
|
@ -152,6 +152,44 @@ nsMathMLmrootFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
return rv;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
|
@ -314,36 +352,12 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
|||
aDesiredSize.height = aDesiredSize.ascent + descent;
|
||||
}
|
||||
|
||||
// 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, dx, dy;
|
||||
nscoord xHeight = 0;
|
||||
fm->GetXHeight(xHeight);
|
||||
nscoord indexRadicalKern = NSToCoordRound(1.35f * xHeight);
|
||||
if (indexRadicalKern > bmIndex.width) {
|
||||
dxIndex = indexRadicalKern - bmIndex.width;
|
||||
dxSqr = 0;
|
||||
}
|
||||
else {
|
||||
dxIndex = 0;
|
||||
dxSqr = bmIndex.width - indexRadicalKern;
|
||||
}
|
||||
// avoid collision by leaving a minimun space between index and radical
|
||||
nscoord minimumClearance = bmSqr.width/2;
|
||||
if (dxIndex + bmIndex.width + minimumClearance > dxSqr + bmSqr.width) {
|
||||
if (bmIndex.width + minimumClearance < bmSqr.width) {
|
||||
dxIndex = bmSqr.width - (bmIndex.width + minimumClearance);
|
||||
dxSqr = 0;
|
||||
}
|
||||
else {
|
||||
dxIndex = 0;
|
||||
dxSqr = (bmIndex.width + minimumClearance) - bmSqr.width;
|
||||
}
|
||||
}
|
||||
nscoord dxIndex, dxSqr;
|
||||
GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr);
|
||||
|
||||
// place the index
|
||||
dx = dxIndex;
|
||||
dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
|
||||
nscoord dx = dxIndex;
|
||||
nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
|
||||
FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize, dx, dy, 0);
|
||||
|
||||
// place the radical symbol and the radical bar
|
||||
|
@ -375,6 +389,34 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsMathMLmrootFrame::GetIntrinsicWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
nsIFrame* baseFrame = mFrames.FirstChild();
|
||||
nsIFrame* indexFrame = nsnull;
|
||||
if (baseFrame)
|
||||
indexFrame = baseFrame->GetNextSibling();
|
||||
if (!indexFrame || indexFrame->GetNextSibling()) {
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
ReflowError(*aRenderingContext, desiredSize);
|
||||
return desiredSize.width;
|
||||
}
|
||||
|
||||
nscoord baseWidth =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, baseFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
nscoord indexWidth =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, indexFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
nscoord sqrWidth = mSqrChar.GetMaxWidth(PresContext(), *aRenderingContext);
|
||||
|
||||
nsCOMPtr<nsIFontMetrics> fm;
|
||||
aRenderingContext->GetFontMetrics(*getter_AddRefs(fm));
|
||||
nscoord dxSqr;
|
||||
GetRadicalXOffsets(indexWidth, sqrWidth, fm, nsnull, &dxSqr);
|
||||
|
||||
return dxSqr + baseWidth;
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// the Style System will use these to pass the proper style context to our MathMLChar
|
||||
|
|
|
@ -72,6 +72,9 @@ public:
|
|||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
virtual nscoord
|
||||
GetIntrinsicWidth(nsIRenderingContext* aRenderingContext);
|
||||
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
|
Загрузка…
Ссылка в новой задаче