mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 512988 - Text-shadow blur and underline messes up with padding-left. r+sr=roc
This commit is contained in:
parent
debf92ce03
commit
7b53709720
@ -1167,35 +1167,32 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
|
||||
gfxRect frameGfxRect = RectToGfxRect(aFrameArea, twipsPerPixel);
|
||||
frameGfxRect.Round();
|
||||
gfxRect dirtyGfxRect = RectToGfxRect(aDirtyRect, twipsPerPixel);
|
||||
|
||||
for (PRUint32 i = shadows->Length(); i > 0; --i) {
|
||||
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
||||
if (shadowItem->mInset)
|
||||
continue;
|
||||
|
||||
gfxRect shadowRect(aFrameArea.x, aFrameArea.y, aFrameArea.width, aFrameArea.height);
|
||||
shadowRect.MoveBy(gfxPoint(shadowItem->mXOffset, shadowItem->mYOffset));
|
||||
shadowRect.Outset(shadowItem->mSpread);
|
||||
|
||||
gfxRect shadowRectPlusBlur = shadowRect;
|
||||
shadowRect.ScaleInverse(twipsPerPixel);
|
||||
shadowRect.Round();
|
||||
nsRect shadowRect = aFrameArea;
|
||||
shadowRect.MoveBy(shadowItem->mXOffset, shadowItem->mYOffset);
|
||||
shadowRect.Inflate(shadowItem->mSpread, shadowItem->mSpread);
|
||||
|
||||
// shadowRect won't include the blur, so make an extra rect here that includes the blur
|
||||
// for use in the even-odd rule below.
|
||||
nsRect shadowRectPlusBlur = shadowRect;
|
||||
nscoord blurRadius = shadowItem->mRadius;
|
||||
shadowRectPlusBlur.Outset(blurRadius);
|
||||
shadowRectPlusBlur.ScaleInverse(twipsPerPixel);
|
||||
shadowRectPlusBlur.RoundOut();
|
||||
shadowRectPlusBlur.Inflate(blurRadius, blurRadius);
|
||||
|
||||
gfxRect shadowGfxRect = RectToGfxRect(shadowRect, twipsPerPixel);
|
||||
gfxRect shadowGfxRectPlusBlur = RectToGfxRect(shadowRectPlusBlur, twipsPerPixel);
|
||||
shadowGfxRect.Round();
|
||||
shadowGfxRectPlusBlur.RoundOut();
|
||||
|
||||
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
||||
nsRefPtr<gfxContext> shadowContext;
|
||||
nsContextBoxBlur blurringArea;
|
||||
|
||||
// shadowRect is already in device pixels, pass 1 as the appunits/pixel value
|
||||
blurRadius /= twipsPerPixel;
|
||||
shadowContext = blurringArea.Init(shadowRect, blurRadius, 1, renderContext, dirtyGfxRect);
|
||||
shadowContext = blurringArea.Init(shadowRect, blurRadius, twipsPerPixel, renderContext, aDirtyRect);
|
||||
if (!shadowContext)
|
||||
continue;
|
||||
|
||||
@ -1212,7 +1209,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
// Clip out the area of the actual frame so the shadow is not shown within
|
||||
// the frame
|
||||
renderContext->NewPath();
|
||||
renderContext->Rectangle(shadowRectPlusBlur);
|
||||
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
||||
if (hasBorderRadius)
|
||||
renderContext->RoundedRectangle(frameGfxRect, borderRadii);
|
||||
else
|
||||
@ -1235,9 +1232,9 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
};
|
||||
nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
|
||||
&clipRectRadii);
|
||||
shadowContext->RoundedRectangle(shadowRect, clipRectRadii);
|
||||
shadowContext->RoundedRectangle(shadowGfxRect, clipRectRadii);
|
||||
} else {
|
||||
shadowContext->Rectangle(shadowRect);
|
||||
shadowContext->Rectangle(shadowGfxRect);
|
||||
}
|
||||
shadowContext->Fill();
|
||||
|
||||
@ -1284,7 +1281,6 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||
&innerRadii);
|
||||
}
|
||||
|
||||
gfxRect dirtyGfxRect = RectToGfxRect(aDirtyRect, twipsPerPixel);
|
||||
for (PRUint32 i = shadows->Length(); i > 0; --i) {
|
||||
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
||||
if (!shadowItem->mInset)
|
||||
@ -1298,28 +1294,18 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||
* that we will NOT paint in
|
||||
*/
|
||||
nscoord blurRadius = shadowItem->mRadius;
|
||||
gfxRect shadowRect(paddingRect.x, paddingRect.y, paddingRect.width, paddingRect.height);
|
||||
gfxRect shadowPaintRect = shadowRect;
|
||||
shadowPaintRect.Outset(blurRadius);
|
||||
nsRect shadowPaintRect = paddingRect;
|
||||
shadowPaintRect.Inflate(blurRadius, blurRadius);
|
||||
|
||||
gfxRect shadowClipRect = shadowRect;
|
||||
shadowClipRect.MoveBy(gfxPoint(shadowItem->mXOffset, shadowItem->mYOffset));
|
||||
shadowClipRect.Inset(shadowItem->mSpread);
|
||||
|
||||
shadowRect.ScaleInverse(twipsPerPixel);
|
||||
shadowRect.Round();
|
||||
shadowPaintRect.ScaleInverse(twipsPerPixel);
|
||||
shadowPaintRect.RoundOut();
|
||||
shadowClipRect.ScaleInverse(twipsPerPixel);
|
||||
shadowClipRect.Round();
|
||||
nsRect shadowClipRect = paddingRect;
|
||||
shadowClipRect.MoveBy(shadowItem->mXOffset, shadowItem->mYOffset);
|
||||
shadowClipRect.Deflate(shadowItem->mSpread, shadowItem->mSpread);
|
||||
|
||||
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
||||
nsRefPtr<gfxContext> shadowContext;
|
||||
nsContextBoxBlur blurringArea;
|
||||
|
||||
// shadowPaintRect is already in device pixels, pass 1 as the appunits/pixel value
|
||||
blurRadius /= twipsPerPixel;
|
||||
shadowContext = blurringArea.Init(shadowPaintRect, blurRadius, 1, renderContext, dirtyGfxRect);
|
||||
shadowContext = blurringArea.Init(shadowPaintRect, blurRadius, twipsPerPixel, renderContext, aDirtyRect);
|
||||
if (!shadowContext)
|
||||
continue;
|
||||
|
||||
@ -1335,17 +1321,23 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||
|
||||
// Clip the context to the area of the frame's padding rect, so no part of the
|
||||
// shadow is painted outside
|
||||
gfxRect shadowGfxRect = RectToGfxRect(paddingRect, twipsPerPixel);
|
||||
shadowGfxRect.Round();
|
||||
renderContext->NewPath();
|
||||
if (hasBorderRadius)
|
||||
renderContext->RoundedRectangle(shadowRect, innerRadii, PR_FALSE);
|
||||
renderContext->RoundedRectangle(shadowGfxRect, innerRadii, PR_FALSE);
|
||||
else
|
||||
renderContext->Rectangle(shadowRect);
|
||||
renderContext->Rectangle(shadowGfxRect);
|
||||
renderContext->Clip();
|
||||
|
||||
// Fill the temporary surface minus the area within the frame that we should
|
||||
// not paint in, and blur and apply it
|
||||
gfxRect shadowPaintGfxRect = RectToGfxRect(shadowPaintRect, twipsPerPixel);
|
||||
gfxRect shadowClipGfxRect = RectToGfxRect(shadowClipRect, twipsPerPixel);
|
||||
shadowPaintGfxRect.RoundOut();
|
||||
shadowClipGfxRect.Round();
|
||||
shadowContext->NewPath();
|
||||
shadowContext->Rectangle(shadowPaintRect);
|
||||
shadowContext->Rectangle(shadowPaintGfxRect);
|
||||
if (hasBorderRadius) {
|
||||
// Calculate the radii the inner clipping rect will have
|
||||
gfxCornerSizes clipRectRadii;
|
||||
@ -1356,9 +1348,9 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||
};
|
||||
nsCSSBorderRenderer::ComputeInnerRadii(innerRadii, borderSizes,
|
||||
&clipRectRadii);
|
||||
shadowContext->RoundedRectangle(shadowClipRect, clipRectRadii, PR_FALSE);
|
||||
shadowContext->RoundedRectangle(shadowClipGfxRect, clipRectRadii, PR_FALSE);
|
||||
} else {
|
||||
shadowContext->Rectangle(shadowClipRect);
|
||||
shadowContext->Rectangle(shadowClipGfxRect);
|
||||
}
|
||||
shadowContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
|
||||
shadowContext->Fill();
|
||||
@ -3239,14 +3231,13 @@ ImageRenderer::Draw(nsPresContext* aPresContext,
|
||||
// nsContextBoxBlur
|
||||
// -----
|
||||
gfxContext*
|
||||
nsContextBoxBlur::Init(const gfxRect& aRect, nscoord aBlurRadius,
|
||||
nsContextBoxBlur::Init(const nsRect& aRect, nscoord aBlurRadius,
|
||||
PRInt32 aAppUnitsPerDevPixel,
|
||||
gfxContext* aDestinationCtx,
|
||||
const gfxRect& aDirtyRect)
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
mDestinationCtx = aDestinationCtx;
|
||||
|
||||
PRInt32 blurRadius = static_cast<PRInt32>(aBlurRadius / aAppUnitsPerDevPixel);
|
||||
mDestinationCtx = aDestinationCtx;
|
||||
|
||||
// if not blurring, draw directly onto the destination device
|
||||
if (blurRadius <= 0) {
|
||||
@ -3255,18 +3246,15 @@ nsContextBoxBlur::Init(const gfxRect& aRect, nscoord aBlurRadius,
|
||||
}
|
||||
|
||||
// Convert from app units to device pixels
|
||||
gfxRect rect = aRect;
|
||||
rect.ScaleInverse(aAppUnitsPerDevPixel);
|
||||
gfxRect rect = RectToGfxRect(aRect, aAppUnitsPerDevPixel);
|
||||
rect.RoundOut();
|
||||
|
||||
if (rect.IsEmpty()) {
|
||||
mContext = aDestinationCtx;
|
||||
return mContext;
|
||||
}
|
||||
|
||||
gfxRect dirtyRect = aDirtyRect;
|
||||
dirtyRect.ScaleInverse(aAppUnitsPerDevPixel);
|
||||
|
||||
mDestinationCtx = aDestinationCtx;
|
||||
gfxRect dirtyRect = RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
|
||||
|
||||
// Create the temporary surface for blurring
|
||||
mContext = blur.Init(rect, gfxIntSize(blurRadius, blurRadius), &dirtyRect);
|
||||
|
@ -403,9 +403,9 @@ public:
|
||||
* should prepare the destination context as if you were going to draw
|
||||
* directly on it instead of any temporary surface created in this class.
|
||||
*/
|
||||
gfxContext* Init(const gfxRect& aRect, nscoord aBlurRadius,
|
||||
gfxContext* Init(const nsRect& aRect, nscoord aBlurRadius,
|
||||
PRInt32 aAppUnitsPerDevPixel, gfxContext* aDestinationCtx,
|
||||
const gfxRect& aDirtyRect);
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
/**
|
||||
* Does the actual blurring and mask applying. Users of this object *must*
|
||||
|
@ -5860,6 +5860,25 @@ nsBlockFrame::PaintTextDecorationLine(gfxContext* aCtx,
|
||||
nscoord start = aLine->mBounds.x;
|
||||
nscoord width = aLine->mBounds.width;
|
||||
|
||||
AdjustForTextIndent(aLine, start, width);
|
||||
|
||||
// Only paint if we have a positive width
|
||||
if (width > 0) {
|
||||
gfxPoint pt(PresContext()->AppUnitsToGfxUnits(start + aPt.x),
|
||||
PresContext()->AppUnitsToGfxUnits(aLine->mBounds.y + aPt.y));
|
||||
gfxSize size(PresContext()->AppUnitsToGfxUnits(width), aSize);
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aCtx, aColor, pt, size,
|
||||
PresContext()->AppUnitsToGfxUnits(aLine->GetAscent()),
|
||||
aOffset, aDecoration, nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ void
|
||||
nsBlockFrame::AdjustForTextIndent(const nsLineBox* aLine,
|
||||
nscoord& start,
|
||||
nscoord& width)
|
||||
{
|
||||
if (!GetPrevContinuation() && aLine == begin_lines().get()) {
|
||||
// Adjust for the text-indent. See similar code in
|
||||
// nsLineLayout::BeginLineReflow.
|
||||
@ -5884,17 +5903,6 @@ nsBlockFrame::PaintTextDecorationLine(gfxContext* aCtx,
|
||||
start += indent;
|
||||
width -= indent;
|
||||
}
|
||||
|
||||
// Only paint if we have a positive width
|
||||
if (width > 0) {
|
||||
gfxPoint pt(PresContext()->AppUnitsToGfxUnits(start + aPt.x),
|
||||
PresContext()->AppUnitsToGfxUnits(aLine->mBounds.y + aPt.y));
|
||||
gfxSize size(PresContext()->AppUnitsToGfxUnits(width), aSize);
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aCtx, aColor, pt, size,
|
||||
PresContext()->AppUnitsToGfxUnits(aLine->GetAscent()),
|
||||
aOffset, aDecoration, nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -355,6 +355,10 @@ protected:
|
||||
gfxFloat aSize,
|
||||
const PRUint8 aDecoration);
|
||||
|
||||
virtual void AdjustForTextIndent(const nsLineBox* aLine,
|
||||
nscoord& start,
|
||||
nscoord& width);
|
||||
|
||||
void TryAllLines(nsLineList::iterator* aIterator,
|
||||
nsLineList::iterator* aStartIterator,
|
||||
nsLineList::iterator* aEndIterator,
|
||||
|
@ -155,7 +155,7 @@ class nsDisplayTextShadow : public nsDisplayItem {
|
||||
public:
|
||||
nsDisplayTextShadow(nsHTMLContainerFrame* aFrame, const PRUint8 aDecoration,
|
||||
const nscolor& aColor, nsLineBox* aLine,
|
||||
const nscoord& aBlurRadius, const gfxPoint& aOffset)
|
||||
const nscoord& aBlurRadius, const nsPoint& aOffset)
|
||||
: nsDisplayItem(aFrame), mLine(aLine), mColor(aColor),
|
||||
mDecorationFlags(aDecoration),
|
||||
mBlurRadius(aBlurRadius), mOffset(aOffset) {
|
||||
@ -173,8 +173,8 @@ private:
|
||||
nsLineBox* mLine;
|
||||
nscolor mColor;
|
||||
PRUint8 mDecorationFlags;
|
||||
nscoord mBlurRadius; // App units
|
||||
gfxPoint mOffset; // App units
|
||||
nscoord mBlurRadius;
|
||||
nsPoint mOffset;
|
||||
};
|
||||
|
||||
void
|
||||
@ -191,22 +191,83 @@ nsDisplayTextShadow::Paint(nsDisplayListBuilder* aBuilder,
|
||||
gfxFont* firstFont = fontGroup->GetFontAt(0);
|
||||
if (!firstFont)
|
||||
return; // OOM
|
||||
|
||||
const gfxFont::Metrics& metrics = firstFont->GetMetrics();
|
||||
nsPoint pt = aBuilder->ToReferenceFrame(mFrame) + nsPoint(mOffset.x, mOffset.y);
|
||||
gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
|
||||
|
||||
nsHTMLContainerFrame* f = static_cast<nsHTMLContainerFrame*>(mFrame);
|
||||
nsMargin bp = f->GetUsedBorderAndPadding();
|
||||
nscoord innerWidthInAppUnits = (mFrame->GetSize().width - bp.LeftRight());
|
||||
nsPoint pt = aBuilder->ToReferenceFrame(mFrame) + mOffset;
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
||||
gfxFloat lineWidth;
|
||||
nsPoint linePt;
|
||||
gfxFloat ascent;
|
||||
if (mLine) {
|
||||
// Block frames give us an nsLineBox, so we must use that
|
||||
nscoord start = mLine->mBounds.x;
|
||||
nscoord width = mLine->mBounds.width;
|
||||
f->AdjustForTextIndent(mLine, start, width);
|
||||
if (width <= 0)
|
||||
return;
|
||||
|
||||
lineWidth = presContext->AppUnitsToGfxUnits(width);
|
||||
linePt = nsPoint(start + pt.x, mLine->mBounds.y + pt.y);
|
||||
ascent = presContext->AppUnitsToGfxUnits(mLine->GetAscent());
|
||||
} else {
|
||||
// For inline frames, we must use the frame's geometry
|
||||
nsRect contentRect = mFrame->GetContentRect() - mFrame->GetPosition() + pt;
|
||||
|
||||
lineWidth = presContext->AppUnitsToGfxUnits(contentRect.width);
|
||||
linePt = contentRect.TopLeft();
|
||||
|
||||
// The ascent of :first-letter frame's text may not be the same as the ascent
|
||||
// of the font metrics, because it may use the tight box of the actual
|
||||
// glyph.
|
||||
if (mFrame->GetType() == nsGkAtoms::letterFrame) {
|
||||
// Note that nsFirstLetterFrame::GetFirstLetterBaseline() returns
|
||||
// |border-top + padding-top + ascent|. But we only need the ascent value,
|
||||
// because those will be added in PaintTextDecorationLine.
|
||||
nsFirstLetterFrame* letterFrame = static_cast<nsFirstLetterFrame*>(mFrame);
|
||||
nscoord tmp = letterFrame->GetFirstLetterBaseline();
|
||||
tmp -= letterFrame->GetUsedBorderAndPadding().top;
|
||||
ascent = presContext->AppUnitsToGfxUnits(tmp);
|
||||
} else {
|
||||
ascent = metrics.maxAscent;
|
||||
}
|
||||
}
|
||||
|
||||
gfxRect shadowRect = gfxRect(pt.x, pt.y, innerWidthInAppUnits, mFrame->GetSize().height);
|
||||
gfxContext* thebesCtx = aCtx->ThebesContext();
|
||||
nsRect shadowRect(0, 0, 0, 0);
|
||||
|
||||
gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
// Get the rects for each text decoration line, and union them together so we
|
||||
// know the minimum size we can make our shadow-painting surface.
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
|
||||
gfxSize size(lineWidth, metrics.underlineSize);
|
||||
nsRect rect = nsCSSRendering::GetTextDecorationRect(presContext, size,
|
||||
ascent, underlineOffset, NS_STYLE_TEXT_DECORATION_UNDERLINE,
|
||||
nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
shadowRect.UnionRect(shadowRect, rect + linePt);
|
||||
}
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_OVERLINE) {
|
||||
gfxSize size(lineWidth, metrics.underlineSize);
|
||||
nsRect rect = nsCSSRendering::GetTextDecorationRect(presContext, size,
|
||||
ascent, metrics.maxAscent, NS_STYLE_TEXT_DECORATION_OVERLINE,
|
||||
nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
shadowRect.UnionRect(shadowRect, rect + linePt);
|
||||
}
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
|
||||
gfxSize size(lineWidth, metrics.strikeoutSize);
|
||||
nsRect rect = nsCSSRendering::GetTextDecorationRect(presContext, size,
|
||||
ascent, metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
|
||||
nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
shadowRect.UnionRect(shadowRect, rect + linePt);
|
||||
}
|
||||
|
||||
// Create our shadow surface, then paint the text decorations onto it
|
||||
nsContextBoxBlur contextBoxBlur;
|
||||
gfxContext* shadowCtx = contextBoxBlur.Init(shadowRect, mBlurRadius,
|
||||
mFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
thebesCtx, dirtyRect);
|
||||
presContext->AppUnitsPerDevPixel(),
|
||||
thebesCtx, aDirtyRect);
|
||||
if (!shadowCtx)
|
||||
return;
|
||||
|
||||
@ -215,19 +276,18 @@ nsDisplayTextShadow::Paint(nsDisplayListBuilder* aBuilder,
|
||||
thebesCtx->SetColor(gfxRGBA(mColor));
|
||||
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
|
||||
gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
|
||||
f->PaintTextDecorationLine(shadowCtx, pt, mLine, mColor,
|
||||
underlineOffset, metrics.maxAscent,
|
||||
underlineOffset, ascent,
|
||||
metrics.underlineSize, NS_STYLE_TEXT_DECORATION_UNDERLINE);
|
||||
}
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_OVERLINE) {
|
||||
f->PaintTextDecorationLine(shadowCtx, pt, mLine, mColor,
|
||||
metrics.maxAscent, metrics.maxAscent,
|
||||
metrics.maxAscent, ascent,
|
||||
metrics.underlineSize, NS_STYLE_TEXT_DECORATION_OVERLINE);
|
||||
}
|
||||
if (mDecorationFlags & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
|
||||
f->PaintTextDecorationLine(shadowCtx, pt, mLine, mColor,
|
||||
metrics.strikeoutOffset, metrics.maxAscent,
|
||||
metrics.strikeoutOffset, ascent,
|
||||
metrics.strikeoutSize, NS_STYLE_TEXT_DECORATION_LINE_THROUGH);
|
||||
}
|
||||
|
||||
@ -279,7 +339,7 @@ nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
|
||||
else
|
||||
shadowColor = GetStyleColor()->mColor;
|
||||
|
||||
gfxPoint offset = gfxPoint(shadow->mXOffset, shadow->mYOffset);
|
||||
nsPoint offset(shadow->mXOffset, shadow->mYOffset);
|
||||
|
||||
// Add it to the display list so it is painted underneath the text and all decorations
|
||||
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
|
||||
@ -364,6 +424,16 @@ nsHTMLContainerFrame::PaintTextDecorationLine(
|
||||
aDecoration, nsCSSRendering::DECORATION_STYLE_SOLID);
|
||||
}
|
||||
|
||||
/*virtual*/ void
|
||||
nsHTMLContainerFrame::AdjustForTextIndent(const nsLineBox* aLine,
|
||||
nscoord& start,
|
||||
nscoord& width)
|
||||
{
|
||||
// This function is not for us.
|
||||
// It allows nsBlockFrame to adjust the width/X position of its
|
||||
// shadowed decorations if a text-indent rule is in effect.
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLContainerFrame::GetTextDecorations(nsPresContext* aPresContext,
|
||||
PRBool aIsBlock,
|
||||
|
@ -182,6 +182,10 @@ protected:
|
||||
gfxFloat aSize,
|
||||
const PRUint8 aDecoration);
|
||||
|
||||
virtual void AdjustForTextIndent(const nsLineBox* aLine,
|
||||
nscoord& start,
|
||||
nscoord& width);
|
||||
|
||||
friend class nsDisplayTextDecoration;
|
||||
friend class nsDisplayTextShadow;
|
||||
};
|
||||
|
@ -420,7 +420,7 @@ protected:
|
||||
PRUint32 aLength,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
PropertyProvider* aProvider,
|
||||
const gfxRect& aDirtyRect,
|
||||
const nsRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
gfxContext* aCtx,
|
||||
|
@ -4428,7 +4428,7 @@ AddHyphenToMetrics(nsTextFrame* aTextFrame, gfxTextRun* aBaseTextRun,
|
||||
void
|
||||
nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
PropertyProvider* aProvider, const gfxRect& aDirtyRect,
|
||||
PropertyProvider* aProvider, const nsRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
|
||||
gfxContext* aCtx, const nscolor& aForegroundColor)
|
||||
{
|
||||
@ -4445,8 +4445,10 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
||||
// This rect is the box which is equivalent to where the shadow will be painted.
|
||||
// The origin of mBoundingBox is the text baseline left, so we must translate it by
|
||||
// that much in order to make the origin the top-left corner of the text bounding box.
|
||||
gfxRect shadowRect = shadowMetrics.mBoundingBox +
|
||||
gfxPoint(aFramePt.x, aTextBaselinePt.y) + shadowOffset;
|
||||
gfxRect shadowGfxRect = shadowMetrics.mBoundingBox +
|
||||
gfxPoint(aFramePt.x, aTextBaselinePt.y) + shadowOffset;
|
||||
nsRect shadowRect(shadowGfxRect.X(), shadowGfxRect.Y(),
|
||||
shadowGfxRect.Width(), shadowGfxRect.Height());;
|
||||
|
||||
nsContextBoxBlur contextBoxBlur;
|
||||
gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, blurRadius,
|
||||
@ -4468,17 +4470,18 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
||||
// Draw the text onto our alpha-only surface to capture the alpha values.
|
||||
// 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.
|
||||
gfxRect dirtyGfxRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
gfxFloat advanceWidth;
|
||||
DrawText(shadowContext,
|
||||
aTextBaselinePt + shadowOffset,
|
||||
aOffset, aLength, &aDirtyRect, aProvider, advanceWidth,
|
||||
aOffset, aLength, &dirtyGfxRect, aProvider, advanceWidth,
|
||||
(GetStateBits() & TEXT_HYPHEN_BREAK) != 0);
|
||||
|
||||
// This will only have an effect in quirks mode. Standards mode text-decoration shadow painting
|
||||
// is handled in nsHTMLContainerFrame.cpp, so you must remember to consider that if you change
|
||||
// any code behaviour here.
|
||||
nsTextPaintStyle textPaintStyle(this);
|
||||
PaintTextDecorations(shadowContext, aDirtyRect, aFramePt + shadowOffset,
|
||||
PaintTextDecorations(shadowContext, dirtyGfxRect, aFramePt + shadowOffset,
|
||||
aTextBaselinePt + shadowOffset,
|
||||
textPaintStyle, *aProvider, &shadowColor);
|
||||
|
||||
@ -4744,7 +4747,7 @@ nsTextFrame::PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
PaintOneShadow(provider.GetStart().GetSkippedOffset(),
|
||||
ComputeTransformedLength(provider),
|
||||
textStyle->mTextShadow->ShadowAt(i - 1), &provider,
|
||||
dirtyRect, framePt, textBaselinePt, ctx,
|
||||
aDirtyRect, framePt, textBaselinePt, ctx,
|
||||
textPaintStyle.GetTextColor());
|
||||
}
|
||||
}
|
||||
|
3
layout/reftests/text-shadow/lineoverflow-ref.html
Normal file
3
layout/reftests/text-shadow/lineoverflow-ref.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<div style="position: absolute; top: 20px; left: 20px;"><span style="text-decoration: underline; text-shadow: 3px 3px 3px red; font-size: 40px;">Testingtestingtestingtesting</span></div>
|
3
layout/reftests/text-shadow/lineoverflow.html
Normal file
3
layout/reftests/text-shadow/lineoverflow.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<div style="position: absolute; top: 20px; left: 20px; width: 50px; text-decoration: underline; text-shadow: 3px 3px 3px red; font-size: 40px;">Testingtestingtestingtesting</div>
|
1
layout/reftests/text-shadow/padding-decoration-ref.html
Normal file
1
layout/reftests/text-shadow/padding-decoration-ref.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE HTML><div><a href="http://test" style="margin-left: 20px; text-shadow: 2px 2px 3px blue;">Hello world hello world</a></div>
|
1
layout/reftests/text-shadow/padding-decoration.html
Normal file
1
layout/reftests/text-shadow/padding-decoration.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE HTML><div><a href="http://test" style="padding-left: 20px; text-shadow: 2px 2px 3px blue;">Hello world hello world</a></div>
|
@ -13,4 +13,7 @@
|
||||
== multiple-noblur.html multiple-noblur-ref.html
|
||||
== quirks-decor-noblur.html quirks-decor-noblur-ref.html
|
||||
== standards-decor-noblur.html standards-decor-noblur-ref.html
|
||||
== padding-decoration.html padding-decoration-ref.html
|
||||
== textindent.html textindent-ref.html
|
||||
== lineoverflow.html lineoverflow-ref.html
|
||||
|
||||
|
3
layout/reftests/text-shadow/textindent-ref.html
Normal file
3
layout/reftests/text-shadow/textindent-ref.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<div style="position:absolute; top: 20px; left: 60px; text-decoration: underline; text-shadow: 5px 5px 3px blue; font-size: 40px;">M</div>
|
3
layout/reftests/text-shadow/textindent.html
Normal file
3
layout/reftests/text-shadow/textindent.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE HTML>
|
||||
|
||||
<div style="position:absolute; top: 20px; left: 120px; text-indent: -60px; text-decoration: underline; text-shadow: 5px 5px 3px blue; font-size: 40px;">M</div>
|
@ -576,13 +576,10 @@ void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
|
||||
nsRect shadowRect(aTextRect);
|
||||
shadowRect.MoveBy(shadowOffset);
|
||||
|
||||
gfxRect shadowRectGFX(shadowRect.x, shadowRect.y, shadowRect.width, shadowRect.height);
|
||||
gfxRect dirtyRectGFX(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
|
||||
nsContextBoxBlur contextBoxBlur;
|
||||
gfxContext* shadowContext = contextBoxBlur.Init(shadowRectGFX, blurRadius,
|
||||
gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, blurRadius,
|
||||
PresContext()->AppUnitsPerDevPixel(),
|
||||
aCtx, dirtyRectGFX);
|
||||
aCtx, aDirtyRect);
|
||||
|
||||
if (!shadowContext)
|
||||
return;
|
||||
@ -597,7 +594,8 @@ void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
|
||||
nsCOMPtr<nsIRenderingContext> renderingContext = nsnull;
|
||||
nsIDeviceContext* devCtx = PresContext()->DeviceContext();
|
||||
devCtx->CreateRenderingContextInstance(*getter_AddRefs(renderingContext));
|
||||
if (!renderingContext) return;
|
||||
if (!renderingContext)
|
||||
return;
|
||||
renderingContext->Init(devCtx, shadowContext);
|
||||
|
||||
aCtx->Save();
|
||||
|
Loading…
Reference in New Issue
Block a user