Bug 1381453 - Support SVG context paint on ::-moz-tree-twisty list-style-image. r=dholbert
MozReview-Commit-ID: E9966Bwog5W
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -7007,16 +7007,17 @@ DrawImageInternal(gfxContext&
/* static */ ImgDrawResult
nsLayoutUtils::DrawSingleUnscaledImage(gfxContext& aContext,
nsPresContext* aPresContext,
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsPoint& aDest,
const nsRect* aDirty,
+ const Maybe<SVGImageContext>& aSVGContext,
uint32_t aImageFlags,
const nsRect* aSourceArea)
{
CSSIntSize imageSize;
aImage->GetWidth(&imageSize.width);
aImage->GetHeight(&imageSize.height);
if (imageSize.width < 1 || imageSize.height < 1) {
NS_WARNING("Image width or height is non-positive");
@@ -7035,17 +7036,17 @@ nsLayoutUtils::DrawSingleUnscaledImage(g
nsRect fill(aDest, source.Size());
// Ensure that only a single image tile is drawn. If aSourceArea extends
// outside the image bounds, we want to honor the aSourceArea-to-aDest
// translation but we don't want to actually tile the image.
fill.IntersectRect(fill, dest);
return DrawImageInternal(aContext, aPresContext,
aImage, aSamplingFilter,
dest, fill, aDest, aDirty ? *aDirty : dest,
- /* no SVGImageContext */ Nothing(), aImageFlags);
+ aSVGContext, aImageFlags);
}
/* static */ ImgDrawResult
nsLayoutUtils::DrawSingleImage(gfxContext& aContext,
nsPresContext* aPresContext,
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsRect& aDest,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1864,28 +1864,37 @@ public:
*
* @param aRenderingContext Where to draw the image, set up with an
* appropriate scale and transform for drawing in
* app units.
* @param aImage The image.
* @param aDest The top-left where the image should be drawn.
* @param aDirty If non-null, then pixels outside this area may
* be skipped.
+ * @param aSVGContext Optionally provides an SVGImageContext.
+ * Callers should pass an SVGImageContext with at
+ * least the viewport size set if aImage may be of
+ * type imgIContainer::TYPE_VECTOR, or pass
+ * Nothing() if it is of type
+ * imgIContainer::TYPE_RASTER (to save cycles
+ * constructing an SVGImageContext, since this
+ * argument will be ignored for raster images).
* @param aImageFlags Image flags of the imgIContainer::FLAG_* variety
* @param aSourceArea If non-null, this area is extracted from
* the image and drawn at aDest. It's
* in appunits. For best results it should
* be aligned with image pixels.
*/
static ImgDrawResult DrawSingleUnscaledImage(gfxContext& aContext,
nsPresContext* aPresContext,
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsPoint& aDest,
const nsRect* aDirty,
+ const mozilla::Maybe<SVGImageContext>& aSVGContext,
uint32_t aImageFlags,
const nsRect* aSourceArea = nullptr);
/**
* Draw a whole image without tiling.
*
* @param aRenderingContext Where to draw the image, set up with an
* appropriate scale and transform for drawing in
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -70,8 +70,9 @@ fails == object-fit-fill-svg-006.xul obj
# Tests for rendering SVG images in a XUL <treecell>:
# XXXdholbert: These are marked as "random" right now, since they might not
# render the images they trying to test in time for the reftest snapshot, per
# bug 1218954.
skip == treecell-image-svg-1a.xul treecell-image-svg-1-ref.xul # bug 1218954
skip == treecell-image-svg-1b.xul treecell-image-svg-1-ref.xul # bug 1218954
== treechildren-padding-percent-1.xul treechildren-padding-percent-1-ref.xul
+test-pref(svg.context-properties.content.enabled,true) == treetwisty-svg-context-paint-1.xul treetwisty-svg-context-paint-1-ref.xul
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/treetwisty-context-paint.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"
+ fill="context-fill" stroke="context-stroke" fill-opacity="context-fill-opacity" stroke-opacity="context-stroke-opacity">
+ <circle cx="8" cy="8" r="7"/>
+</svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/treetwisty-no-context-paint.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"
+ fill="green" stroke="purple" fill-opacity="0.5" stroke-opacity="0.2">
+ <circle cx="8" cy="8" r="7"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/treetwisty-svg-context-paint-1-ref.xul
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml">
+ <html:style>
+ treechildren::-moz-tree-twisty {
+ -moz-appearance: none !important;
+ -moz-context-properties: none !important;
+ list-style-image: url(treetwisty-no-context-paint.svg);
+ }
+ </html:style>
+ <tree seltype="single" flex="1">
+ <treecols>
+ <treecol flex="1" primary="true"/>
+ </treecols>
+ <treechildren>
+ <treeitem>
+ <treerow>
+ <treecell label="I am a treecell"></treecell>
+ </treerow>
+ </treeitem>
+ <treeitem container="true" open="true">
+ <treerow>
+ <treecell label="Folder"></treecell>
+ </treerow>
+ <treechildren>
+ <treeitem>
+ <treerow>
+ <treecell label="I am a treecell"></treecell>
+ </treerow>
+ </treeitem>
+ </treechildren>
+ </treeitem>
+ </treechildren>
+ </tree>
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/treetwisty-svg-context-paint-1.xul
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml">
+ <html:style>
+ treechildren::-moz-tree-twisty {
+ -moz-appearance: none !important;
+ -moz-context-properties: fill, fill-opacity, stroke, stroke-opacity !important;
+ fill: green;
+ fill-opacity: 0.5;
+ stroke: purple;
+ stroke-opacity: 0.2;
+ list-style-image: url(treetwisty-context-paint.svg);
+ }
+ </html:style>
+ <tree seltype="single" flex="1">
+ <treecols>
+ <treecol flex="1" primary="true"/>
+ </treecols>
+ <treechildren>
+ <treeitem>
+ <treerow>
+ <treecell label="I am a treecell"></treecell>
+ </treerow>
+ </treeitem>
+ <treeitem container="true" open="true">
+ <treerow>
+ <treecell label="Folder"></treecell>
+ </treerow>
+ <treechildren>
+ <treeitem>
+ <treerow>
+ <treecell label="I am a treecell"></treecell>
+ </treerow>
+ </treeitem>
+ </treechildren>
+ </treeitem>
+ </treechildren>
+ </tree>
+</window>
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -351,16 +351,17 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
} else { // mImageContainer->GetType() == TYPE_RASTER
aImgParams.result &= nsLayoutUtils::DrawSingleUnscaledImage(
aContext,
PresContext(),
mImageContainer,
nsLayoutUtils::GetSamplingFilterForFrame(this),
nsPoint(0, 0),
aDirtyRect ? &dirtyRect : nullptr,
+ Nothing(),
flags);
}
if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aContext.PopGroupAndBlend();
}
// gfxContextAutoSaveRestore goes out of scope & cleans up our gfxContext
}
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -3489,29 +3489,34 @@ nsTreeBodyFrame::PaintTwisty(int32_t
twistyRect.x = rightEdge - twistyRect.width;
imageSize.Deflate(bp);
// Get the image for drawing.
nsCOMPtr<imgIContainer> image;
bool useImageRegion = true;
GetImage(aRowIndex, aColumn, true, twistyContext, useImageRegion, getter_AddRefs(image));
if (image) {
- nsPoint pt = twistyRect.TopLeft();
+ nsPoint anchorPoint = twistyRect.TopLeft();
// Center the image. XXX Obey vertical-align style prop?
if (imageSize.height < twistyRect.height) {
- pt.y += (twistyRect.height - imageSize.height)/2;
+ anchorPoint.y += (twistyRect.height - imageSize.height)/2;
}
+ // Apply context paint if applicable
+ Maybe<SVGImageContext> svgContext;
+ SVGImageContext::MaybeStoreContextPaint(svgContext, twistyContext,
+ image);
+
// Paint the image.
result &=
nsLayoutUtils::DrawSingleUnscaledImage(
aRenderingContext, aPresContext, image,
- SamplingFilter::POINT, pt, &aDirtyRect,
- imgIContainer::FLAG_NONE, &imageSize);
+ SamplingFilter::POINT, anchorPoint, &aDirtyRect,
+ svgContext, imgIContainer::FLAG_NONE, &imageSize);
}
}
}
return result;
}
ImgDrawResult
@@ -3876,22 +3881,26 @@ nsTreeBodyFrame::PaintCheckbox(int32_t
if (imageSize.height < checkboxRect.height) {
pt.y += (checkboxRect.height - imageSize.height)/2;
}
if (imageSize.width < checkboxRect.width) {
pt.x += (checkboxRect.width - imageSize.width)/2;
}
+ // Apply context paint if applicable
+ Maybe<SVGImageContext> svgContext;
+ SVGImageContext::MaybeStoreContextPaint(svgContext, checkboxContext,
+ image);
// Paint the image.
result &=
nsLayoutUtils::DrawSingleUnscaledImage(aRenderingContext,
aPresContext,
image, SamplingFilter::POINT, pt, &aDirtyRect,
- imgIContainer::FLAG_NONE, &imageSize);
+ svgContext, imgIContainer::FLAG_NONE, &imageSize);
}
return result;
}
ImgDrawResult
nsTreeBodyFrame::PaintDropFeedback(const nsRect& aDropFeedbackRect,
nsPresContext* aPresContext,