зеркало из https://github.com/mozilla/gecko-dev.git
bug 686497 - avoid passing excessively long wavy-underline path to cairo for stroking. r=roc
This commit is contained in:
Родитель
44e05fde0e
Коммит
ee56ede693
|
@ -3367,6 +3367,7 @@ nsCSSRendering::DrawTableBorderSegment(nsRenderingContext& aContext,
|
|||
|
||||
void
|
||||
nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
|
||||
const gfxRect& aDirtyRect,
|
||||
const nscolor aColor,
|
||||
const gfxPoint& aPt,
|
||||
const gfxSize& aLineSize,
|
||||
|
@ -3381,8 +3382,9 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
|
|||
gfxRect rect =
|
||||
GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
|
||||
aDecoration, aStyle, aDescentLimit);
|
||||
if (rect.IsEmpty())
|
||||
if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE &&
|
||||
aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE &&
|
||||
|
@ -3524,14 +3526,30 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
|
|||
* 7. Repeat from 2 until reached to right-most edge of the area.
|
||||
*/
|
||||
|
||||
rect.x += lineHeight / 2.0;
|
||||
aGfxContext->NewPath();
|
||||
|
||||
gfxPoint pt(rect.TopLeft());
|
||||
gfxFloat rightMost = pt.x + rect.Width() + lineHeight;
|
||||
gfxFloat adv = rect.Height() - lineHeight;
|
||||
gfxFloat flatLengthAtVertex = NS_MAX((lineHeight - 1.0) * 2.0, 1.0);
|
||||
|
||||
// figure out if we can trim whole cycles from the left and right edges
|
||||
// of the line, to try and avoid creating an unnecessarily long and
|
||||
// complex path
|
||||
gfxFloat cycleLength = 2 * (adv + flatLengthAtVertex);
|
||||
PRInt32 skipCycles = floor((aDirtyRect.x - rect.x) / cycleLength);
|
||||
if (skipCycles > 0) {
|
||||
rect.x += skipCycles * cycleLength;
|
||||
rect.width -= skipCycles * cycleLength;
|
||||
}
|
||||
|
||||
rect.x += lineHeight / 2.0;
|
||||
gfxPoint pt(rect.TopLeft());
|
||||
gfxFloat rightMost = pt.x + rect.Width() + lineHeight;
|
||||
|
||||
skipCycles = floor((rightMost - aDirtyRect.XMost()) / cycleLength);
|
||||
if (skipCycles > 0) {
|
||||
rightMost -= skipCycles * cycleLength;
|
||||
}
|
||||
|
||||
aGfxContext->NewPath();
|
||||
|
||||
pt.x -= lineHeight;
|
||||
aGfxContext->MoveTo(pt); // 1
|
||||
|
||||
|
@ -3539,7 +3557,16 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
|
|||
aGfxContext->LineTo(pt); // 2
|
||||
|
||||
PRBool goDown = PR_TRUE;
|
||||
PRUint32 iter = 0;
|
||||
while (pt.x < rightMost) {
|
||||
if (++iter > 1000) {
|
||||
// stroke the current path and start again, to avoid pathological
|
||||
// behavior in cairo with huge numbers of path segments
|
||||
aGfxContext->Stroke();
|
||||
aGfxContext->NewPath();
|
||||
aGfxContext->MoveTo(pt);
|
||||
iter = 0;
|
||||
}
|
||||
pt.x += adv;
|
||||
pt.y += goDown ? adv : -adv;
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ struct nsCSSRendering {
|
|||
* not app units.
|
||||
* input:
|
||||
* @param aGfxContext
|
||||
* @param aDirtyRect no need to paint outside this rect
|
||||
* @param aColor the color of the decoration line
|
||||
* @param aPt the top/left edge of the text
|
||||
* @param aLineSize the width and the height of the decoration
|
||||
|
@ -319,6 +320,7 @@ struct nsCSSRendering {
|
|||
* used for strikeout line and overline too.
|
||||
*/
|
||||
static void PaintDecorationLine(gfxContext* aGfxContext,
|
||||
const gfxRect& aDirtyRect,
|
||||
const nscolor aColor,
|
||||
const gfxPoint& aPt,
|
||||
const gfxSize& aLineSize,
|
||||
|
|
|
@ -514,6 +514,7 @@ protected:
|
|||
PRBool aDrawSoftHyphen);
|
||||
|
||||
void DrawTextRunAndDecorations(gfxContext* const aCtx,
|
||||
const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
PRUint32 aOffset,
|
||||
|
@ -527,6 +528,7 @@ protected:
|
|||
const nscolor* const aDecorationOverrideColor);
|
||||
|
||||
void DrawText(gfxContext* const aCtx,
|
||||
const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
PRUint32 aOffset,
|
||||
|
|
|
@ -4526,7 +4526,9 @@ ComputeSelectionUnderlineHeight(nsPresContext* aPresContext,
|
|||
* This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
|
||||
* drawing text decoration for selections.
|
||||
*/
|
||||
static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
|
||||
static void DrawSelectionDecorations(gfxContext* aContext,
|
||||
const gfxRect& aDirtyRect,
|
||||
SelectionType aType,
|
||||
nsTextFrame* aFrame,
|
||||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsTextRangeStyle &aRangeStyle,
|
||||
|
@ -4608,7 +4610,7 @@ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
|
|||
}
|
||||
size.height *= relativeSize;
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aContext, color, pt, size, aAscent, aFontMetrics.underlineOffset,
|
||||
aContext, aDirtyRect, color, pt, size, aAscent, aFontMetrics.underlineOffset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, style, descentLimit);
|
||||
}
|
||||
|
||||
|
@ -4844,7 +4846,9 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
|||
// Remember that the box blur context has a device offset on it, so we don't need to
|
||||
// translate any coordinates to fit on the surface.
|
||||
gfxFloat advanceWidth;
|
||||
DrawText(shadowContext, aFramePt + shadowOffset,
|
||||
gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
|
||||
aDirtyRect.width, aDirtyRect.height);
|
||||
DrawText(shadowContext, dirtyRect, aFramePt + shadowOffset,
|
||||
aTextBaselinePt + shadowOffset, aOffset, aLength, *aProvider,
|
||||
nsTextPaintStyle(this), aClipEdges, advanceWidth,
|
||||
(GetStateBits() & TEXT_HYPHEN_BREAK) != 0, decorationOverrideColor);
|
||||
|
@ -4955,7 +4959,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
|||
aCtx->SetColor(gfxRGBA(foreground));
|
||||
gfxFloat advance;
|
||||
|
||||
DrawText(aCtx, aFramePt, gfxPoint(aFramePt.x + xOffset, aTextBaselinePt.y),
|
||||
DrawText(aCtx, aDirtyRect, aFramePt, gfxPoint(aFramePt.x + xOffset, aTextBaselinePt.y),
|
||||
offset, length, aProvider, aTextPaintStyle, aClipEdges, advance,
|
||||
hyphenWidth > 0);
|
||||
if (hyphenWidth) {
|
||||
|
@ -5016,6 +5020,8 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
|||
PRInt32 app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
|
||||
// XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint?
|
||||
gfxPoint pt(0.0, (aTextBaselinePt.y - mAscent) / app);
|
||||
gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app,
|
||||
aDirtyRect.width / app, aDirtyRect.height / app);
|
||||
SelectionType type;
|
||||
nsTextRangeStyle selectedStyle;
|
||||
while (iterator.GetNextSegment(&xOffset, &offset, &length, &hyphenWidth,
|
||||
|
@ -5026,7 +5032,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
|
|||
pt.x = (aFramePt.x + xOffset -
|
||||
(mTextRun->IsRightToLeft() ? advance : 0)) / app;
|
||||
gfxFloat width = NS_ABS(advance) / app;
|
||||
DrawSelectionDecorations(aCtx, aSelectionType, this, aTextPaintStyle,
|
||||
DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType, this, aTextPaintStyle,
|
||||
selectedStyle,
|
||||
pt, width, mAscent / app, decorationMetrics);
|
||||
}
|
||||
|
@ -5306,7 +5312,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
|||
ctx->SetColor(gfxRGBA(foregroundColor));
|
||||
|
||||
gfxFloat advanceWidth;
|
||||
DrawText(ctx, framePt, textBaselinePt, startOffset, maxLength, provider,
|
||||
DrawText(ctx, dirtyRect, framePt, textBaselinePt, startOffset, maxLength, provider,
|
||||
textPaintStyle, clipEdges, advanceWidth,
|
||||
(GetStateBits() & TEXT_HYPHEN_BREAK) != 0);
|
||||
}
|
||||
|
@ -5339,7 +5345,7 @@ nsTextFrame::DrawTextRun(gfxContext* const aCtx,
|
|||
|
||||
void
|
||||
nsTextFrame::DrawTextRunAndDecorations(
|
||||
gfxContext* const aCtx,
|
||||
gfxContext* const aCtx, const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
|
||||
PRUint32 aOffset, PRUint32 aLength,
|
||||
PropertyProvider& aProvider,
|
||||
|
@ -5362,6 +5368,9 @@ nsTextFrame::DrawTextRunAndDecorations(
|
|||
const gfxFloat ascent = gfxFloat(mAscent) / app;
|
||||
const gfxFloat frameTop = aFramePt.y;
|
||||
|
||||
gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app,
|
||||
aDirtyRect.Width() / app, aDirtyRect.Height() / app);
|
||||
|
||||
// Underlines
|
||||
for (PRUint32 i = aDecorations.mUnderlines.Length(); i-- > 0; ) {
|
||||
const LineDecoration& dec = aDecorations.mUnderlines[i];
|
||||
|
@ -5373,7 +5382,7 @@ nsTextFrame::DrawTextRunAndDecorations(
|
|||
decPt.y = (frameTop - dec.mBaselineOffset) / app;
|
||||
|
||||
const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, decPt, decSize, ascent,
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, dirtyRect, lineColor, decPt, decSize, ascent,
|
||||
metrics.underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
|
||||
dec.mStyle);
|
||||
}
|
||||
|
@ -5388,7 +5397,7 @@ nsTextFrame::DrawTextRunAndDecorations(
|
|||
decPt.y = (frameTop - dec.mBaselineOffset) / app;
|
||||
|
||||
const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, decPt, decSize, ascent,
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, dirtyRect, lineColor, decPt, decSize, ascent,
|
||||
metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle);
|
||||
}
|
||||
|
||||
|
@ -5408,7 +5417,7 @@ nsTextFrame::DrawTextRunAndDecorations(
|
|||
decPt.y = (frameTop - dec.mBaselineOffset) / app;
|
||||
|
||||
const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, decPt, decSize, ascent,
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, dirtyRect, lineColor, decPt, decSize, ascent,
|
||||
metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
|
||||
dec.mStyle);
|
||||
}
|
||||
|
@ -5416,7 +5425,7 @@ nsTextFrame::DrawTextRunAndDecorations(
|
|||
|
||||
void
|
||||
nsTextFrame::DrawText(
|
||||
gfxContext* const aCtx,
|
||||
gfxContext* const aCtx, const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
|
||||
PRUint32 aOffset, PRUint32 aLength,
|
||||
PropertyProvider& aProvider,
|
||||
|
@ -5433,7 +5442,7 @@ nsTextFrame::DrawText(
|
|||
const bool drawDecorations = !aProvider.GetFontGroup()->ShouldSkipDrawing() &&
|
||||
decorations.HasDecorationLines();
|
||||
if (drawDecorations) {
|
||||
DrawTextRunAndDecorations(aCtx, aFramePt, aTextBaselinePt, aOffset, aLength,
|
||||
DrawTextRunAndDecorations(aCtx, aDirtyRect, aFramePt, aTextBaselinePt, aOffset, aLength,
|
||||
aProvider, aTextStyle, aClipEdges, aAdvanceWidth,
|
||||
aDrawSoftHyphen, decorations,
|
||||
aDecorationOverrideColor);
|
||||
|
|
|
@ -413,13 +413,14 @@ nsTextBoxFrame::PaintTitle(nsRenderingContext& aRenderingContext,
|
|||
if (mTitle.IsEmpty())
|
||||
return;
|
||||
|
||||
DrawText(aRenderingContext, mTextDrawRect + aPt, aOverrideColor);
|
||||
DrawText(aRenderingContext, aDirtyRect, mTextDrawRect + aPt, aOverrideColor);
|
||||
}
|
||||
|
||||
void
|
||||
nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aTextRect,
|
||||
const nscolor* aOverrideColor)
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aTextRect,
|
||||
const nscolor* aOverrideColor)
|
||||
{
|
||||
nsPresContext* presContext = PresContext();
|
||||
|
||||
|
@ -497,6 +498,7 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
|||
presContext->AppUnitsToGfxUnits(aTextRect.y));
|
||||
gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width);
|
||||
gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
|
||||
gfxRect dirtyRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
|
||||
|
||||
// Underlines are drawn before overlines, and both before the text
|
||||
// itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
|
||||
|
@ -510,14 +512,14 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
|||
gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
|
||||
if ((decorations & NS_FONT_DECORATION_UNDERLINE) &&
|
||||
underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
|
||||
nsCSSRendering::PaintDecorationLine(ctx, underColor,
|
||||
nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, underColor,
|
||||
pt, gfxSize(width, sizePixel),
|
||||
ascentPixel, offsetPixel,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle);
|
||||
}
|
||||
if ((decorations & NS_FONT_DECORATION_OVERLINE) &&
|
||||
overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
|
||||
nsCSSRendering::PaintDecorationLine(ctx, overColor,
|
||||
nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, overColor,
|
||||
pt, gfxSize(width, sizePixel),
|
||||
ascentPixel, ascentPixel,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle);
|
||||
|
@ -599,7 +601,7 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
|||
fontMet->GetStrikeout(offset, size);
|
||||
gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
|
||||
gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
|
||||
nsCSSRendering::PaintDecorationLine(ctx, strikeColor,
|
||||
nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, strikeColor,
|
||||
pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
|
||||
strikeStyle);
|
||||
|
|
|
@ -133,8 +133,9 @@ private:
|
|||
PRBool InsertSeparatorBeforeAccessKey();
|
||||
|
||||
void DrawText(nsRenderingContext& aRenderingContext,
|
||||
const nsRect& aTextRect,
|
||||
const nscolor* aOverrideColor);
|
||||
const nsRect& aDirtyRect,
|
||||
const nsRect& aTextRect,
|
||||
const nscolor* aOverrideColor);
|
||||
|
||||
nsString mTitle;
|
||||
nsString mCroppedTitle;
|
||||
|
|
Загрузка…
Ссылка в новой задаче