Bug 889235 - Make text-shadow work on SVG text. r=cam

This commit is contained in:
Robert Longson 2014-01-13 12:21:42 +00:00
parent 4f1e358abd
commit 2880ca117f
10 changed files with 75 additions and 34 deletions

View File

@ -2599,7 +2599,7 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
uint32_t aFlags)
{
const nsStyleText* textStyle = aFrame->StyleText();
if (!textStyle->HasTextShadow(aFrame))
if (!textStyle->HasTextShadow())
return aTextAndDecorationsRect;
nsRect resultRect = aTextAndDecorationsRect;
@ -3814,7 +3814,7 @@ nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame,
void* aCallbackData)
{
const nsStyleText* textStyle = aFrame->StyleText();
if (!textStyle->HasTextShadow(aFrame))
if (!textStyle->HasTextShadow())
return;
// Text shadow happens with the last value being painted at the back,

View File

@ -5211,9 +5211,6 @@ static bool GetSelectionTextShadow(nsIFrame* aFrame,
nsTextPaintStyle& aTextPaintStyle,
nsCSSShadowArray** aShadow)
{
if (aFrame->IsSVGText()) {
return false;
}
switch (aType) {
case nsISelectionController::SELECTION_NORMAL:
return aTextPaintStyle.GetSelectionShadow(aShadow);
@ -5511,7 +5508,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
// Determine what shadow, if any, to draw - either from textStyle
// or from the ::-moz-selection pseudo-class if specified there
nsCSSShadowArray *shadow = textStyle->GetTextShadow(this);
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
// Draw shadows, if any
@ -5897,7 +5894,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
nscolor foregroundColor = textPaintStyle.GetTextColor();
if (!aCallbacks) {
const nsStyleText* textStyle = StyleText();
if (textStyle->HasTextShadow(this)) {
if (textStyle->HasTextShadow()) {
// Text shadow happens with the last value being painted at the back,
// ie. it is painted first.
gfxTextRun::Metrics shadowMetrics =

View File

@ -0,0 +1,15 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
<text x="30" y="30" fill="green" style="text-shadow: #cc9900 20px 12px 2px">Hello</text>
<script>
function f() {
document.getElementsByTagName("text")[0].style.textShadow = "grey 3px 3px";
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", f, false);
</script>
</svg>

After

Width:  |  Height:  |  Size: 529 B

View File

@ -1,7 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" width="700" height="200">
<text x="100" y="100" style="font: 16px sans-serif">hello <tspan style="text-shadow: 2px 2px 3px #000">there</tspan> everyone</text>
</svg>

Before

Width:  |  Height:  |  Size: 326 B

View File

@ -127,6 +127,9 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
== textLength-5.svg textLength-5-ref.svg
== textLength-6.svg textLength-6-ref.svg
# text-shadow
== text-shadow.svg text-shadow-ref.svg
# tests for ignoring various properties
== ignore-border.svg ignore-prop-ref.svg
== ignore-display.svg ignore-display-ref.svg
@ -135,7 +138,6 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
== ignore-position.svg ignore-position-ref.svg
== ignore-margin.svg ignore-prop-ref.svg
== ignore-padding.svg ignore-prop-ref.svg
== ignore-text-shadow.svg ignore-prop-ref.svg
== ignore-vertical-align.svg ignore-vertical-align-ref.svg
== ignore-overflow-scroll.svg ignore-prop-ref.svg
== ignore-text-align.svg ignore-prop-ref.svg
@ -163,6 +165,7 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
== dynamic-dominant-baseline.svg dynamic-dominant-baseline-ref.svg
== dynamic-multiple-x.svg dynamic-multiple-x-ref.svg
fuzzy-if(!d2d,14,2) fuzzy-if(azureQuartz,1,6) == dynamic-non-scaling-stroke.svg dynamic-non-scaling-stroke-ref.svg #Bug 885316
== dynamic-text-shadow.svg text-shadow-ref.svg
# text and masks
HTTP(../..) == mask-applied.svg mask-applied-ref.svg

View File

@ -0,0 +1,8 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<text x="33" y="33" fill="grey">Hello</text>
<text x="30" y="30" fill="green">Hello</text>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View File

@ -0,0 +1,7 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<text x="30" y="30" fill="green" style="text-shadow: grey 3px 3px;">Hello</text>
</svg>

After

Width:  |  Height:  |  Size: 249 B

View File

@ -1431,13 +1431,13 @@ struct nsStyleText {
}
// These are defined in nsStyleStructInlines.h.
inline bool HasTextShadow() const;
inline nsCSSShadowArray* GetTextShadow() const;
// The aContextFrame argument on each of these is the frame this
// style struct is for. If the frame is for SVG text, the return
// value will be massaged to be something that makes sense for
// SVG text.
inline bool HasTextShadow(const nsIFrame* aContextFrame) const;
inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aContextFrame) const;
inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
};

View File

@ -57,19 +57,14 @@ nsStyleBorder::GetSubImage(uint8_t aIndex) const
}
bool
nsStyleText::HasTextShadow(const nsIFrame* aContextFrame) const
nsStyleText::HasTextShadow() const
{
NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
return mTextShadow && !aContextFrame->IsSVGText();
return mTextShadow;
}
nsCSSShadowArray*
nsStyleText::GetTextShadow(const nsIFrame* aContextFrame) const
nsStyleText::GetTextShadow() const
{
NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
if (aContextFrame->IsSVGText()) {
return nullptr;
}
return mTextShadow;
}

View File

@ -632,8 +632,10 @@ struct TextRenderedRun
eIncludeFill = 1,
// Includes the stroke geometry of the text in the returned rectangle.
eIncludeStroke = 2,
// Includes any text shadow in the returned rectangle.
eIncludeTextShadow = 4,
// Don't include any horizontal glyph overflow in the returned rectangle.
eNoHorizontalOverflow = 4
eNoHorizontalOverflow = 8
};
/**
@ -910,11 +912,21 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
x = metrics.mBoundingBox.x;
width = metrics.mBoundingBox.width;
}
gfxRect fillInAppUnits(x, baseline - above,
width, metrics.mBoundingBox.height + above + below);
nsRect fillInAppUnits(x, baseline - above,
width, metrics.mBoundingBox.height + above + below);
// Account for text-shadow.
if (aFlags & eIncludeTextShadow) {
fillInAppUnits =
nsLayoutUtils::GetTextShadowRectsUnion(fillInAppUnits, mFrame);
}
// Convert the app units rectangle to user units.
gfxRect fill = AppUnitsToFloatCSSPixels(fillInAppUnits, aContext);
gfxRect fill = AppUnitsToFloatCSSPixels(gfxRect(fillInAppUnits.x,
fillInAppUnits.y,
fillInAppUnits.width,
fillInAppUnits.height),
aContext);
// Scale the rectangle up due to any mFontSizeScaleFactor. We scale
// it around the text's origin.
@ -3738,14 +3750,25 @@ SVGTextFrame::ReflowSVG()
TextRenderedRunIterator it(this, TextRenderedRunIterator::eAllFrames);
for (TextRenderedRun run = it.Current(); run.mFrame; run = it.Next()) {
uint32_t runFlags = 0;
if (run.mFrame->StyleSVG()->mFill.mType != eStyleSVGPaintType_None) {
runFlags |= TextRenderedRun::eIncludeFill |
TextRenderedRun::eIncludeTextShadow;
}
if (nsSVGUtils::HasStroke(run.mFrame)) {
runFlags |= TextRenderedRun::eIncludeFill |
TextRenderedRun::eIncludeTextShadow;
}
// Our "visual" overflow rect needs to be valid for building display lists
// for hit testing, which means that for certain values of 'pointer-events'
// it needs to include the geometry of the fill or stroke even when the fill/
// stroke don't actually render (e.g. when stroke="none" or
// stroke-opacity="0"). GetGeometryHitTestFlags accounts for 'pointer-events'.
// The text-shadow is not part of the hit-test area.
uint16_t hitTestFlags = nsSVGUtils::GetGeometryHitTestFlags(run.mFrame);
if ((hitTestFlags & SVG_HIT_TEST_FILL) ||
run.mFrame->StyleSVG()->mFill.mType != eStyleSVGPaintType_None) {
if (hitTestFlags & SVG_HIT_TEST_FILL) {
runFlags |= TextRenderedRun::eIncludeFill;
}
if ((hitTestFlags & SVG_HIT_TEST_STROKE) ||
nsSVGUtils::HasStroke(run.mFrame)) {
if (hitTestFlags & SVG_HIT_TEST_STROKE) {
runFlags |= TextRenderedRun::eIncludeStroke;
}