Bug 577850 - A gradient applied to SVG Text element should render as if the objectBoundingBox spans the entire Text content. r=roc

This commit is contained in:
Robert Longson 2010-08-07 10:38:11 +01:00
parent 7176189879
commit f8e75e6fb6
8 changed files with 70 additions and 24 deletions

View File

@ -149,6 +149,7 @@ fails == inline-in-xul-basic-01.xul pass.svg
random-if(gtk2Widget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713 random-if(gtk2Widget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713
== switch-01.svg pass.svg == switch-01.svg pass.svg
== text-gradient-01.svg text-gradient-01-ref.svg == text-gradient-01.svg text-gradient-01-ref.svg
== text-gradient-02.svg text-gradient-02-ref.svg
== text-in-link-01.svg text-in-link-01-ref.svg == text-in-link-01.svg text-in-link-01-ref.svg
== text-in-link-02.svg text-in-link-02-ref.svg == text-in-link-02.svg text-in-link-02-ref.svg
== text-in-link-03.svg text-in-link-03-ref.svg == text-in-link-03.svg text-in-link-03-ref.svg

View File

@ -0,0 +1,22 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Reference for gradient on text</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=577850 -->
<defs>
<linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="0.0" stop-color="rgb(0, 0, 0)"/>
<stop offset="0.5" stop-color="rgb(255, 255, 255)"/>
<stop offset="1.0" stop-color="rgb(0, 0, 0)"/>
</linearGradient>
</defs>
<text x="0, 30, 60, 0, 40, 70" y="0, 0, 0, 1em, 1em, 1em" fill="url(#gradient)" font-size="60" transform="translate(50, 80)">
FooBar
</text>
</svg>

After

Width:  |  Height:  |  Size: 700 B

View File

@ -0,0 +1,23 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg">
<title>Testcase for gradient on text</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=577850 -->
<defs>
<linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="0.00" stop-color="rgb(0, 0, 0)"/>
<stop offset="0.50" stop-color="rgb(255, 255, 255)"/>
<stop offset="1.00" stop-color="rgb(0, 0, 0)"/>
</linearGradient>
</defs>
<text fill="url(#gradient)" font-size="60" transform="translate(50, 80)">
<tspan x="0, 30, 60" y="0" >Foo</tspan>
<tspan x="0, 40, 70" dy="1em">Bar</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 729 B

View File

@ -270,13 +270,10 @@ nsSVGDisplayContainerFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspac
nsISVGChildFrame* svgKid = do_QueryFrame(kid); nsISVGChildFrame* svgKid = do_QueryFrame(kid);
if (svgKid) { if (svgKid) {
gfxMatrix transform = aToBBoxUserspace; gfxMatrix transform = aToBBoxUserspace;
// nsSVGGlyphFrame's mContent is a nsTextNode! nsIContent *content = kid->GetContent();
if (kid->GetType() != nsGkAtoms::svgGlyphFrame) { if (content->IsSVG() && !content->IsNodeOfType(nsINode::eTEXT)) {
nsIContent *content = kid->GetContent(); transform = static_cast<nsSVGElement*>(content)->
if (content->IsSVG()) { PrependLocalTransformTo(aToBBoxUserspace);
transform = static_cast<nsSVGElement*>(content)->
PrependLocalTransformTo(aToBBoxUserspace);
}
} }
bboxUnion = bboxUnion.Union(svgKid->GetBBoxContribution(transform)); bboxUnion = bboxUnion.Union(svgKid->GetBBoxContribution(transform));
} }

View File

@ -88,7 +88,7 @@ float
nsSVGGeometryFrame::GetStrokeWidth() nsSVGGeometryFrame::GetStrokeWidth()
{ {
nsSVGElement *ctx = static_cast<nsSVGElement*> nsSVGElement *ctx = static_cast<nsSVGElement*>
(GetType() == nsGkAtoms::svgGlyphFrame ? (mContent->IsNodeOfType(nsINode::eTEXT) ?
mContent->GetParent() : mContent); mContent->GetParent() : mContent);
return return
@ -101,7 +101,7 @@ nsresult
nsSVGGeometryFrame::GetStrokeDashArray(gfxFloat **aDashes, PRUint32 *aCount) nsSVGGeometryFrame::GetStrokeDashArray(gfxFloat **aDashes, PRUint32 *aCount)
{ {
nsSVGElement *ctx = static_cast<nsSVGElement*> nsSVGElement *ctx = static_cast<nsSVGElement*>
(GetType() == nsGkAtoms::svgGlyphFrame ? (mContent->IsNodeOfType(nsINode::eTEXT) ?
mContent->GetParent() : mContent); mContent->GetParent() : mContent);
*aDashes = nsnull; *aDashes = nsnull;
*aCount = 0; *aCount = 0;
@ -147,7 +147,7 @@ float
nsSVGGeometryFrame::GetStrokeDashoffset() nsSVGGeometryFrame::GetStrokeDashoffset()
{ {
nsSVGElement *ctx = static_cast<nsSVGElement*> nsSVGElement *ctx = static_cast<nsSVGElement*>
(GetType() == nsGkAtoms::svgGlyphFrame ? (mContent->IsNodeOfType(nsINode::eTEXT) ?
mContent->GetParent() : mContent); mContent->GetParent() : mContent);
return return

View File

@ -164,9 +164,7 @@ nsSVGGradientFrame::GetGradientTransform(nsIFrame *aSource,
"Unknown gradientUnits type"); "Unknown gradientUnits type");
// objectBoundingBox is the default anyway // objectBoundingBox is the default anyway
nsIFrame *frame = aSource->GetContent()->IsNodeOfType(nsINode::eTEXT) ? gfxRect bbox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(aSource);
aSource->GetParent() : aSource;
gfxRect bbox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(frame);
bboxMatrix = gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y()); bboxMatrix = gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y());
} }

View File

@ -614,17 +614,7 @@ nsSVGPatternFrame::GetTargetGeometry(gfxMatrix *aCTM,
nsIFrame *aTarget, nsIFrame *aTarget,
const gfxRect *aOverrideBounds) const gfxRect *aOverrideBounds)
{ {
// If we are attempting to paint a pattern for text, then the content will be *aBBox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(aTarget);
// the #text, so we actually want the parent, which should be the <svg:text>
// or <svg:tspan> element.
if (aTarget->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
*aBBox = nsSVGUtils::GetBBox(aTarget->GetParent());
} else {
*aBBox = nsSVGUtils::GetBBox(aTarget);
}
if (aOverrideBounds) {
*aBBox = *aOverrideBounds;
}
// Sanity check // Sanity check
PRUint16 type = GetPatternUnits(); PRUint16 type = GetPatternUnits();

View File

@ -67,6 +67,7 @@
#include "nsSVGClipPathFrame.h" #include "nsSVGClipPathFrame.h"
#include "nsSVGMaskFrame.h" #include "nsSVGMaskFrame.h"
#include "nsSVGContainerFrame.h" #include "nsSVGContainerFrame.h"
#include "nsSVGTextContainerFrame.h"
#include "nsSVGLength2.h" #include "nsSVGLength2.h"
#include "nsGenericElement.h" #include "nsGenericElement.h"
#include "nsSVGGraphicElement.h" #include "nsSVGGraphicElement.h"
@ -1357,9 +1358,23 @@ nsSVGUtils::ClipToGfxRect(nsIntRect* aRect, const gfxRect& aGfxRect)
gfxRect gfxRect
nsSVGUtils::GetBBox(nsIFrame *aFrame) nsSVGUtils::GetBBox(nsIFrame *aFrame)
{ {
if (aFrame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
aFrame = aFrame->GetParent();
}
gfxRect bbox; gfxRect bbox;
nsISVGChildFrame *svg = do_QueryFrame(aFrame); nsISVGChildFrame *svg = do_QueryFrame(aFrame);
if (svg) { if (svg) {
// It is possible to apply a gradient, pattern, clipping path, mask or
// filter to text. When one of these facilities is applied to text
// the bounding box is the entire text element in all
// cases.
nsSVGTextContainerFrame* metrics = do_QueryFrame(aFrame);
if (metrics) {
while (aFrame->GetType() != nsGkAtoms::svgTextFrame) {
aFrame = aFrame->GetParent();
}
svg = do_QueryFrame(aFrame);
}
bbox = svg->GetBBoxContribution(gfxMatrix()); bbox = svg->GetBBoxContribution(gfxMatrix());
} else { } else {
bbox = nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame); bbox = nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);