This commit is contained in:
Brad Lassey 2008-11-26 10:08:45 -05:00
Родитель 588d9fb6c7 dc77572fbe
Коммит ee3abc1a8f
11 изменённых файлов: 165 добавлений и 159 удалений

Просмотреть файл

@ -285,11 +285,43 @@ inline nscoord NSToCoordFloor(float aValue)
return nscoord(NS_floorf(aValue));
}
inline nscoord NSToCoordFloorClamped(float aValue)
{
#ifndef NS_COORD_IS_FLOAT
// Bounds-check before converting out of float, to avoid overflow
if (aValue >= nscoord_MAX) {
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord");
return nscoord_MAX;
}
if (aValue <= nscoord_MIN) {
NS_WARNING("Overflowed nscoord_MIN in conversion to nscoord");
return nscoord_MIN;
}
#endif
return NSToCoordFloor(aValue);
}
inline nscoord NSToCoordCeil(float aValue)
{
return nscoord(NS_ceilf(aValue));
}
inline nscoord NSToCoordCeilClamped(float aValue)
{
#ifndef NS_COORD_IS_FLOAT
// Bounds-check before converting out of float, to avoid overflow
if (aValue >= nscoord_MAX) {
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord");
return nscoord_MAX;
}
if (aValue <= nscoord_MIN) {
NS_WARNING("Overflowed nscoord_MIN in conversion to nscoord");
return nscoord_MIN;
}
#endif
return NSToCoordCeil(aValue);
}
inline nscoord NSToCoordRound(float aValue)
{
#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
@ -299,6 +331,22 @@ inline nscoord NSToCoordRound(float aValue)
#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
}
inline nscoord NSToCoordRoundWithClamp(float aValue)
{
#ifndef NS_COORD_IS_FLOAT
// Bounds-check before converting out of float, to avoid overflow
if (aValue >= nscoord_MAX) {
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord");
return nscoord_MAX;
}
if (aValue <= nscoord_MIN) {
NS_WARNING("Overflowed nscoord_MIN in conversion to nscoord");
return nscoord_MIN;
}
#endif
return NSToCoordRound(aValue);
}
/*
* Int Rounding Functions
*/
@ -322,27 +370,7 @@ inline PRInt32 NSToIntRound(float aValue)
*/
inline nscoord NSFloatPixelsToAppUnits(float aPixels, float aAppUnitsPerPixel)
{
float product = aPixels * aAppUnitsPerPixel;
nscoord result;
#ifdef NS_COORD_IS_FLOAT
// No need to bounds-check if converting float to float
result = NSToCoordRound(product);
#else
// Bounds-check before converting out of float, to avoid overflow
if (product >= nscoord_MAX) {
NS_WARNING("Overflowed nscoord_MAX in conversion to nscoord");
result = nscoord_MAX;
} else if (product <= nscoord_MIN) {
NS_WARNING("Overflowed nscoord_MIN in conversion to nscoord");
result = nscoord_MIN;
} else {
result = NSToCoordRound(product);
}
#endif
VERIFY_COORD(result);
return result;
return NSToCoordRoundWithClamp(aPixels * aAppUnitsPerPixel);
}
inline nscoord NSIntPixelsToAppUnits(PRInt32 aPixels, PRInt32 aAppUnitsPerPixel)

Просмотреть файл

@ -1425,6 +1425,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
}
// Screen out negative heights --- can happen due to integer overflows :-(
aMetrics.height = PR_MAX(0, aMetrics.height);
#ifdef DEBUG_blocks
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
ListTag(stdout);

Просмотреть файл

@ -714,6 +714,14 @@ public:
aCapitalize, mContext);
}
void Finish() {
if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
nsTransformedTextRun* transformedTextRun =
static_cast<nsTransformedTextRun*>(mTextRun);
transformedTextRun->FinishSettingProperties(mContext);
}
}
gfxTextRun* mTextRun;
gfxContext* mContext;
PRUint32 mOffsetIntoTextRun;
@ -776,10 +784,32 @@ TextContainsLineBreakerWhiteSpace(const void* aText, PRUint32 aLength,
}
struct FrameTextTraversal {
nsIFrame* mFrameToDescendInto;
PRPackedBool mDescendIntoFrameSiblings;
// These fields identify which frames should be recursively scanned
// The first normal frame to scan (or null, if no such frame should be scanned)
nsIFrame* mFrameToScan;
// The first overflow frame to scan (or null, if no such frame should be scanned)
nsIFrame* mOverflowFrameToScan;
// Whether to scan the siblings of mFrameToDescendInto/mOverflowFrameToDescendInto
PRPackedBool mScanSiblings;
// These identify the boundaries of the context required for
// line breaking or textrun construction
PRPackedBool mLineBreakerCanCrossFrameBoundary;
PRPackedBool mTextRunCanCrossFrameBoundary;
nsIFrame* NextFrameToScan() {
nsIFrame* f;
if (mFrameToScan) {
f = mFrameToScan;
mFrameToScan = mScanSiblings ? f->GetNextSibling() : nsnull;
} else if (mOverflowFrameToScan) {
f = mOverflowFrameToScan;
mOverflowFrameToScan = mScanSiblings ? f->GetNextSibling() : nsnull;
} else {
f = nsnull;
}
return f;
}
};
static FrameTextTraversal
@ -794,28 +824,33 @@ CanTextCrossFrameBoundary(nsIFrame* aFrame, nsIAtom* aType)
// placeholders are "invisible", so a text run should be able to span
// across one. But don't descend into the out-of-flow.
result.mLineBreakerCanCrossFrameBoundary = PR_TRUE;
result.mOverflowFrameToScan = nsnull;
if (continuesTextRun) {
// ... Except for first-letter floats, which are really in-flow
// from the point of view of capitalization etc, so we'd better
// descend into them. But we actually need to break the textrun for
// first-letter floats since things look bad if, say, we try to make a
// ligature across the float boundary.
result.mFrameToDescendInto =
result.mFrameToScan =
(static_cast<nsPlaceholderFrame*>(aFrame))->GetOutOfFlowFrame();
result.mDescendIntoFrameSiblings = PR_FALSE;
result.mScanSiblings = PR_FALSE;
result.mTextRunCanCrossFrameBoundary = PR_FALSE;
} else {
result.mFrameToDescendInto = nsnull;
result.mFrameToScan = nsnull;
result.mTextRunCanCrossFrameBoundary = PR_TRUE;
}
} else {
if (continuesTextRun) {
result.mFrameToDescendInto = aFrame->GetFirstChild(nsnull);
result.mDescendIntoFrameSiblings = PR_TRUE;
result.mFrameToScan = aFrame->GetFirstChild(nsnull);
result.mOverflowFrameToScan = aFrame->GetFirstChild(nsGkAtoms::overflowList);
NS_WARN_IF_FALSE(!result.mOverflowFrameToScan,
"Scanning overflow inline frames is something we should avoid");
result.mScanSiblings = PR_TRUE;
result.mTextRunCanCrossFrameBoundary = PR_TRUE;
result.mLineBreakerCanCrossFrameBoundary = PR_TRUE;
} else {
result.mFrameToDescendInto = nsnull;
result.mFrameToScan = nsnull;
result.mOverflowFrameToScan = nsnull;
result.mTextRunCanCrossFrameBoundary = PR_FALSE;
result.mLineBreakerCanCrossFrameBoundary = PR_FALSE;
}
@ -871,13 +906,11 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState
return FB_FOUND_VALID_TEXTRUN_BOUNDARY;
}
for (nsIFrame* f = traversal.mFrameToDescendInto; f;
f = f->GetNextSibling()) {
for (nsIFrame* f = traversal.NextFrameToScan(); f;
f = traversal.NextFrameToScan()) {
FindBoundaryResult result = FindBoundaries(f, aState);
if (result != FB_CONTINUE)
return result;
if (!traversal.mDescendIntoFrameSiblings)
break;
}
if (!traversal.mTextRunCanCrossFrameBoundary) {
@ -1129,6 +1162,7 @@ void BuildTextRunsScanner::FlushFrames(PRBool aFlushLineBreaks, PRBool aSuppress
// TODO cause frames associated with the textrun to be reflowed, if they
// aren't being reflowed already!
}
mBreakSinks[i]->Finish();
}
mBreakSinks.Clear();
}
@ -1285,11 +1319,9 @@ void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
FlushFrames(PR_FALSE, PR_FALSE);
}
for (nsIFrame* f = traversal.mFrameToDescendInto; f;
f = f->GetNextSibling()) {
for (nsIFrame* f = traversal.NextFrameToScan(); f;
f = traversal.NextFrameToScan()) {
ScanFrame(f);
if (!traversal.mDescendIntoFrameSiblings)
break;
}
if (!traversal.mLineBreakerCanCrossFrameBoundary) {
@ -4769,7 +4801,7 @@ nsTextFrame::GetPointFromOffset(PRInt32 inOffset,
mTextRun->GetAdvanceWidth(properties.GetStart().GetSkippedOffset(),
GetSkippedDistance(properties.GetStart(), iter),
&properties);
nscoord width = NSToCoordCeil(advanceWidth);
nscoord width = NSToCoordCeilClamped(advanceWidth);
if (mTextRun->IsRightToLeft()) {
outPoint->x = mRect.width - width;
@ -5292,8 +5324,8 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
if (i > wordStart) {
nscoord width =
NSToCoordCeil(mTextRun->GetAdvanceWidth(wordStart, i - wordStart, &provider));
aData->currentLine += width;
NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(wordStart, i - wordStart, &provider));
aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, width);
aData->atStartOfLine = PR_FALSE;
if (collapseWhitespace) {
@ -5305,7 +5337,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
} else {
// Some non-whitespace so the old trailingWhitespace is no longer trailing
aData->trailingWhitespace =
NSToCoordCeil(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider));
NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider));
}
} else {
aData->trailingWhitespace = 0;
@ -5414,7 +5446,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
if (i > lineStart) {
nscoord width =
NSToCoordCeil(mTextRun->GetAdvanceWidth(lineStart, i - lineStart, &provider));
NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(lineStart, i - lineStart, &provider));
aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, width);
if (collapseWhitespace) {
@ -5426,7 +5458,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext,
} else {
// Some non-whitespace so the old trailingWhitespace is no longer trailing
aData->trailingWhitespace =
NSToCoordCeil(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider));
NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider));
}
} else {
aData->trailingWhitespace = 0;

Просмотреть файл

@ -72,7 +72,7 @@ nsTransformedTextRun::SetCapitalization(PRUint32 aStart, PRUint32 aLength,
memset(mCapitalize.Elements(), 0, GetLength()*sizeof(PRPackedBool));
}
memcpy(mCapitalize.Elements() + aStart, aCapitalization, aLength*sizeof(PRPackedBool));
mFactory->RebuildTextRun(this, aRefContext);
mNeedsRebuild = PR_TRUE;
}
PRBool
@ -82,76 +82,20 @@ nsTransformedTextRun::SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
{
PRBool changed = gfxTextRun::SetPotentialLineBreaks(aStart, aLength,
aBreakBefore, aRefContext);
mFactory->RebuildTextRun(this, aRefContext);
if (changed) {
mNeedsRebuild = PR_TRUE;
}
return changed;
}
PRBool
nsTransformedTextRun::SetLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRBool aLineBreakBefore, PRBool aLineBreakAfter,
gfxFloat* aAdvanceWidthDelta,
gfxContext* aRefContext)
{
nsTArray<PRUint32> newBreaks;
PRUint32 i;
PRBool changed = PR_FALSE;
for (i = 0; i < mLineBreaks.Length(); ++i) {
PRUint32 pos = mLineBreaks[i];
if (pos >= aStart)
break;
newBreaks.AppendElement(pos);
}
if (aLineBreakBefore != (i < mLineBreaks.Length() &&
mLineBreaks[i] == aStart)) {
changed = PR_TRUE;
}
if (aLineBreakBefore) {
nsTextFrameUtils::AppendLineBreakOffset(&newBreaks, aStart);
}
if (aLineBreakAfter != (i + 1 < mLineBreaks.Length() &&
mLineBreaks[i + 1] == aStart + aLength)) {
changed = PR_TRUE;
}
if (aLineBreakAfter) {
nsTextFrameUtils::AppendLineBreakOffset(&newBreaks, aStart + aLength);
}
for (; i < mLineBreaks.Length(); ++i) {
if (mLineBreaks[i] > aStart + aLength)
break;
changed = PR_TRUE;
}
if (!changed) {
if (aAdvanceWidthDelta) {
*aAdvanceWidthDelta = 0;
}
return PR_FALSE;
}
newBreaks.AppendElements(mLineBreaks.Elements() + i, mLineBreaks.Length() - i);
mLineBreaks.SwapElements(newBreaks);
gfxFloat currentAdvance = GetAdvanceWidth(aStart, aLength, nsnull);
mFactory->RebuildTextRun(this, aRefContext);
if (aAdvanceWidthDelta) {
*aAdvanceWidthDelta = GetAdvanceWidth(aStart, aLength, nsnull) - currentAdvance;
}
return PR_TRUE;
}
gfxTextRun*
nsTransformingTextRunFactory::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
const gfxTextRunFactory::Parameters* aParams,
gfxFontGroup* aFontGroup, PRUint32 aFlags,
nsStyleContext** aStyles, PRBool aOwnsFactory)
{
nsTransformedTextRun* textRun =
nsTransformedTextRun::Create(aParams, this, aFontGroup,
aString, aLength, aFlags, aStyles, aOwnsFactory);
if (!textRun)
return nsnull;
RebuildTextRun(textRun, aParams->mContext);
return textRun;
return nsTransformedTextRun::Create(aParams, this, aFontGroup,
aString, aLength, aFlags, aStyles, aOwnsFactory);
}
gfxTextRun*
@ -271,7 +215,7 @@ GetParametersForInner(nsTransformedTextRun* aTextRun, PRUint32* aFlags,
{
gfxTextRunFactory::Parameters params =
{ aRefContext, nsnull, nsnull,
nsnull, nsnull, aTextRun->GetAppUnitsPerDevUnit()
nsnull, 0, aTextRun->GetAppUnitsPerDevUnit()
};
*aFlags = aTextRun->GetFlags() & ~gfxFontGroup::TEXT_IS_PERSISTENT;
return params;
@ -313,17 +257,9 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
PRBool runIsLowercase = PR_FALSE;
nsAutoTArray<nsStyleContext*,50> styleArray;
nsAutoTArray<PRPackedBool,50> canBreakBeforeArray;
nsAutoTArray<PRUint32,10> lineBreakBeforeArray;
PRUint32 nextLineBreak = 0;
PRUint32 i;
for (i = 0; i <= length; ++i) {
if (nextLineBreak < aTextRun->mLineBreaks.Length() &&
aTextRun->mLineBreaks[nextLineBreak] == i) {
lineBreakBeforeArray.AppendElement(i - runStart);
++nextLineBreak;
}
PRBool isLowercase = PR_FALSE;
if (i < length) {
// Characters that aren't the start of a cluster are ignored here. They
@ -346,9 +282,7 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
nsAutoPtr<gfxTextRun> transformedChild;
gfxTextRunCache::AutoTextRun cachedChild;
gfxTextRun* child;
// Setup actual line break data for child (which may affect shaping)
innerParams.mInitialBreaks = lineBreakBeforeArray.Elements();
innerParams.mInitialBreakCount = lineBreakBeforeArray.Length();
if (runIsLowercase) {
transformedChild = uppercaseFactory.MakeTextRun(str + runStart, i - runStart,
&innerParams, smallFont, flags, styleArray.Elements(), PR_FALSE);
@ -372,10 +306,6 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
runStart = i;
styleArray.Clear();
canBreakBeforeArray.Clear();
lineBreakBeforeArray.Clear();
if (nextLineBreak > 0 && aTextRun->mLineBreaks[nextLineBreak - 1] == i) {
lineBreakBeforeArray.AppendElement(0);
}
}
if (i < length) {
@ -384,8 +314,6 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i));
}
}
NS_ASSERTION(nextLineBreak == aTextRun->mLineBreaks.Length(),
"lost track of line breaks somehow");
}
void
@ -404,8 +332,6 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
nsAutoTArray<PRPackedBool,50> charsToMergeArray;
nsAutoTArray<nsStyleContext*,50> styleArray;
nsAutoTArray<PRPackedBool,50> canBreakBeforeArray;
nsAutoTArray<PRUint32,10> lineBreakBeforeArray;
PRUint32 nextLineBreak = 0;
PRUint32 extraCharsCount = 0;
PRUint32 i;
@ -415,11 +341,6 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
charsToMergeArray.AppendElement(PR_FALSE);
styleArray.AppendElement(styles[i]);
canBreakBeforeArray.AppendElement(aTextRun->CanBreakLineBefore(i));
if (nextLineBreak < aTextRun->mLineBreaks.Length() &&
aTextRun->mLineBreaks[nextLineBreak] == i) {
lineBreakBeforeArray.AppendElement(i + extraCharsCount);
++nextLineBreak;
}
PRUint8 style = mAllUppercase ? NS_STYLE_TEXT_TRANSFORM_UPPERCASE
: styles[i]->GetStyleText()->mTextTransform;
@ -461,13 +382,6 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
canBreakBeforeArray.AppendElement(PR_FALSE);
}
}
if (nextLineBreak < aTextRun->mLineBreaks.Length() &&
aTextRun->mLineBreaks[nextLineBreak] == length) {
lineBreakBeforeArray.AppendElement(length + extraCharsCount);
++nextLineBreak;
}
NS_ASSERTION(nextLineBreak == aTextRun->mLineBreaks.Length(),
"lost track of line breaks somehow");
PRUint32 flags;
gfxTextRunFactory::Parameters innerParams =
@ -477,9 +391,7 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
nsAutoPtr<gfxTextRun> transformedChild;
gfxTextRunCache::AutoTextRun cachedChild;
gfxTextRun* child;
// Setup actual line break data for child (which may affect shaping)
innerParams.mInitialBreaks = lineBreakBeforeArray.Elements();
innerParams.mInitialBreakCount = lineBreakBeforeArray.Length();
if (mInnerTransformingTextRunFactory) {
transformedChild = mInnerTransformingTextRunFactory->MakeTextRun(
convertedString.BeginReading(), convertedString.Length(),

Просмотреть файл

@ -113,22 +113,30 @@ public:
}
}
virtual void SetCapitalization(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aCapitalization,
gfxContext* aRefContext);
void SetCapitalization(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aCapitalization,
gfxContext* aRefContext);
virtual PRBool SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aBreakBefore,
gfxContext* aRefContext);
virtual PRBool SetLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRBool aLineBreakBefore, PRBool aLineBreakAfter,
gfxFloat* aAdvanceWidthDelta,
gfxContext* aRefContext);
/**
* Called after SetCapitalization and SetPotentialLineBreaks
* are done and before we request any data from the textrun. Also always
* called after a Create.
*/
void FinishSettingProperties(gfxContext* aRefContext)
{
if (mNeedsRebuild) {
mNeedsRebuild = PR_FALSE;
mFactory->RebuildTextRun(this, aRefContext);
}
}
nsTransformingTextRunFactory *mFactory;
nsTArray<PRUint32> mLineBreaks;
nsTArray<nsRefPtr<nsStyleContext> > mStyles;
nsTArray<PRPackedBool> mCapitalize;
PRPackedBool mOwnsFactory;
PRPackedBool mNeedsRebuild;
private:
nsTransformedTextRun(const gfxTextRunFactory::Parameters* aParams,
@ -138,15 +146,12 @@ private:
const PRUint32 aFlags, nsStyleContext** aStyles,
PRBool aOwnsFactory)
: gfxTextRun(aParams, aString, aLength, aFontGroup, aFlags, sizeof(nsTransformedTextRun)),
mFactory(aFactory), mOwnsFactory(aOwnsFactory)
mFactory(aFactory), mOwnsFactory(aOwnsFactory), mNeedsRebuild(PR_TRUE)
{
PRUint32 i;
for (i = 0; i < aLength; ++i) {
mStyles.AppendElement(aStyles[i]);
}
for (i = 0; i < aParams->mInitialBreakCount; ++i) {
mLineBreaks.AppendElement(aParams->mInitialBreaks[i]);
}
}
};

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body style="font-family: monospace; white-space:pre;">aa
aa
a<b>a a</b></body>
</html>

Просмотреть файл

@ -0,0 +1,4 @@
<!DOCTYPE html>
<html>
<body style="font-family: monospace; width: 4.1ch;">aa aa a<b>a a</b></body>
</html>

Просмотреть файл

@ -946,6 +946,7 @@ fails == 441259-2.html 441259-2-ref.html # bug 441400
== 455105-2.html 455105-ref.html
== 455171-5.html 455171-5-ref.html
== 455280-1.xhtml 455280-1-ref.xhtml
== 455826-1.html 455826-1-ref.html
fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 456147.xul 456147-ref.html # bug 456147, but not caused by it
== 456330-1.gif 456330-1-ref.png
== 456484-1.html 456484-1-ref.html

Просмотреть файл

@ -195,11 +195,11 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
}
switch (unit) {
case eCSSUnit_EM: {
return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize));
return NSToCoordRoundWithClamp(aValue.GetFloatValue() * float(aFontSize));
// XXX scale against font metrics height instead?
}
case eCSSUnit_EN: {
return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
return NSToCoordRoundWithClamp((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
}
case eCSSUnit_XHeight: {
nsFont font = aStyleFont->mFont;
@ -207,12 +207,12 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
nscoord xHeight;
fm->GetXHeight(xHeight);
return NSToCoordRound(aValue.GetFloatValue() * float(xHeight));
return NSToCoordRoundWithClamp(aValue.GetFloatValue() * float(xHeight));
}
case eCSSUnit_CapHeight: {
NS_NOTYETIMPLEMENTED("cap height unit");
nscoord capHeight = ((aFontSize / 3) * 2); // XXX HACK!
return NSToCoordRound(aValue.GetFloatValue() * float(capHeight));
return NSToCoordRoundWithClamp(aValue.GetFloatValue() * float(capHeight));
}
case eCSSUnit_Char: {
nsFont font = aStyleFont->mFont;
@ -222,7 +222,7 @@ static nscoord CalcLengthWith(const nsCSSValue& aValue,
gfxFloat zeroWidth = (tfm->GetThebesFontGroup()->GetFontAt(0)
->GetMetrics().zeroOrAveCharWidth);
return NSToCoordRound(aValue.GetFloatValue() *
return NSToCoordRoundWithClamp(aValue.GetFloatValue() *
NS_ceil(aPresContext->AppUnitsPerDevPixel() *
zeroWidth));
}

Просмотреть файл

@ -336,16 +336,23 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
NS_DISPLAY_DECL_NAME("XULTextBox")
};
void nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
void
nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
static_cast<nsTextBoxFrame*>(mFrame)->
PaintTitle(*aCtx, aDirtyRect, aBuilder->ToReferenceFrame(mFrame));
}
nsRect
nsDisplayXULTextBox::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
}
NS_IMETHODIMP
nsTextBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@ -952,6 +959,12 @@ nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState)
return rv;
}
PRBool
nsTextBoxFrame::ComputesOwnOverflowArea()
{
return PR_TRUE;
}
/* virtual */ void
nsTextBoxFrame::MarkIntrinsicWidthsDirty()
{

Просмотреть файл

@ -87,6 +87,8 @@ public:
const nsRect& aDirtyRect,
nsPoint aPt);
virtual PRBool ComputesOwnOverflowArea();
protected:
friend class nsAsyncAccesskeyUpdate;
// Should be called only by nsAsyncAccesskeyUpdate.