--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1618,20 +1618,26 @@ private:
buf.mNumGlyphs = mNumGlyphs;
gfxContext::AzureState state = mRunParams.context->CurrentState();
if (mRunParams.drawMode & DrawMode::GLYPH_FILL) {
if (state.pattern || mFontParams.contextPaint) {
Pattern *pat;
RefPtr<gfxPattern> fillPattern;
- if (!mFontParams.contextPaint ||
- !(fillPattern = mFontParams.contextPaint->GetFillPattern(
- mRunParams.context->GetDrawTarget(),
- mRunParams.context->CurrentMatrix()))) {
+ if (mFontParams.contextPaint) {
+ mozilla::image::DrawResult result = mozilla::image::DrawResult::SUCCESS;
+ Tie(result, fillPattern) =
+ mFontParams.contextPaint->GetFillPattern(
+ mRunParams.context->GetDrawTarget(),
+ mRunParams.context->CurrentMatrix());
+ // XXX cku Flush should return result to the caller?
+ Unused << result;
+ }
+ if (!fillPattern) {
if (state.pattern) {
pat = state.pattern->GetPattern(mRunParams.dt,
state.patternTransformChanged ?
&state.patternTransform : nullptr);
} else {
pat = nullptr;
}
} else {
--- a/gfx/thebes/gfxSVGGlyphs.h
+++ b/gfx/thebes/gfxSVGGlyphs.h
@@ -197,34 +197,36 @@ public:
const gfxMatrix& aCTM) :
mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
{
mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
}
- already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) {
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetFillPattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) {
if (mFillPattern) {
mFillPattern->SetMatrix(aCTM * mFillMatrix);
}
RefPtr<gfxPattern> fillPattern = mFillPattern;
- return fillPattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(fillPattern));
}
- already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) {
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetStrokePattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) {
if (mStrokePattern) {
mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
}
RefPtr<gfxPattern> strokePattern = mStrokePattern;
- return strokePattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(strokePattern));
}
float GetFillOpacity() const {
return mFillPattern ? 1.0f : 0.0f;
}
float GetStrokeOpacity() const {
return mStrokePattern ? 1.0f : 0.0f;
--- a/layout/svg/SVGContextPaint.cpp
+++ b/layout/svg/SVGContextPaint.cpp
@@ -8,123 +8,134 @@
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "nsIDocument.h"
#include "nsSVGPaintServerFrame.h"
#include "nsSVGEffects.h"
#include "nsSVGPaintServerFrame.h"
using namespace mozilla::gfx;
+using namespace mozilla::image;
namespace mozilla {
/**
* Stores in |aTargetPaint| information on how to reconstruct the current
* fill or stroke pattern. Will also set the paint opacity to transparent if
* the paint is set to "none".
* @param aOuterContextPaint pattern information from the outer text context
* @param aTargetPaint where to store the current pattern information
* @param aFillOrStroke member pointer to the paint we are setting up
* @param aProperty the frame property descriptor of the fill or stroke paint
* server frame
*/
-static void
+static DrawResult
SetupInheritablePaint(const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsIFrame* aFrame,
float& aOpacity,
SVGContextPaint* aOuterContextPaint,
SVGContextPaintImpl::Paint& aTargetPaint,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
nsSVGEffects::PaintingPropertyDescriptor aProperty)
{
const nsStyleSVG *style = aFrame->StyleSVG();
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, aFillOrStroke, aProperty);
+ DrawResult result = DrawResult::SUCCESS;
if (ps) {
- RefPtr<gfxPattern> pattern =
+ RefPtr<gfxPattern> pattern;
+ Tie(result, pattern) =
ps->GetPaintServerPattern(aFrame, aDrawTarget, aContextMatrix,
aFillOrStroke, aOpacity);
+
if (pattern) {
aTargetPaint.SetPaintServer(aFrame, aContextMatrix, ps);
- return;
+ return result;
}
}
+
if (aOuterContextPaint) {
RefPtr<gfxPattern> pattern;
switch ((style->*aFillOrStroke).Type()) {
case eStyleSVGPaintType_ContextFill:
- pattern = aOuterContextPaint->GetFillPattern(aDrawTarget, aOpacity,
- aContextMatrix);
+ Tie(result, pattern) =
+ aOuterContextPaint->GetFillPattern(aDrawTarget, aOpacity,
+ aContextMatrix);
break;
case eStyleSVGPaintType_ContextStroke:
- pattern = aOuterContextPaint->GetStrokePattern(aDrawTarget, aOpacity,
- aContextMatrix);
+ Tie(result, pattern) =
+ aOuterContextPaint->GetStrokePattern(aDrawTarget, aOpacity,
+ aContextMatrix);
break;
default:
;
}
if (pattern) {
aTargetPaint.SetContextPaint(aOuterContextPaint, (style->*aFillOrStroke).Type());
- return;
+ return result;
}
}
+
nscolor color =
nsSVGUtils::GetFallbackOrPaintColor(aFrame->StyleContext(), aFillOrStroke);
aTargetPaint.SetColor(color);
+
+ return result;
}
-DrawMode
+mozilla::Pair<DrawResult, DrawMode>
SVGContextPaintImpl::Init(const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsIFrame* aFrame,
SVGContextPaint* aOuterContextPaint)
{
DrawMode toDraw = DrawMode(0);
const nsStyleSVG *style = aFrame->StyleSVG();
+ DrawResult result = DrawResult::SUCCESS;
// fill:
if (style->mFill.Type() == eStyleSVGPaintType_None) {
SetFillOpacity(0.0f);
} else {
float opacity = nsSVGUtils::GetOpacity(style->FillOpacitySource(),
style->mFillOpacity,
aOuterContextPaint);
- SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
- opacity, aOuterContextPaint,
- mFillPaint, &nsStyleSVG::mFill,
- nsSVGEffects::FillProperty());
+ result &= SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
+ opacity, aOuterContextPaint,
+ mFillPaint, &nsStyleSVG::mFill,
+ nsSVGEffects::FillProperty());
SetFillOpacity(opacity);
toDraw |= DrawMode::GLYPH_FILL;
}
// stroke:
if (style->mStroke.Type() == eStyleSVGPaintType_None) {
SetStrokeOpacity(0.0f);
} else {
float opacity = nsSVGUtils::GetOpacity(style->StrokeOpacitySource(),
style->mStrokeOpacity,
aOuterContextPaint);
- SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
- opacity, aOuterContextPaint,
- mStrokePaint, &nsStyleSVG::mStroke,
- nsSVGEffects::StrokeProperty());
+ result &= SetupInheritablePaint(aDrawTarget, aContextMatrix, aFrame,
+ opacity, aOuterContextPaint,
+ mStrokePaint, &nsStyleSVG::mStroke,
+ nsSVGEffects::StrokeProperty());
SetStrokeOpacity(opacity);
toDraw |= DrawMode::GLYPH_STROKE;
}
- return toDraw;
+ return MakePair(result, toDraw);
}
void
SVGContextPaint::InitStrokeGeometry(gfxContext* aContext,
float devUnitsPerSVGUnit)
{
mStrokeWidth = aContext->CurrentLineWidth() / devUnitsPerSVGUnit;
aContext->CurrentDash(mDashes, &mDashOffset);
@@ -153,96 +164,100 @@ SVGContextPaint::GetContextPaint(nsICont
// bit of a headache so for now we punt on that, don't reapply the constness
// to the SVGContextPaint here, and trust that no one will add code that
// actually modifies the object.
return static_cast<SVGContextPaint*>(
ownerDoc->GetProperty(nsGkAtoms::svgContextPaint));
}
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
SVGContextPaintImpl::GetFillPattern(const DrawTarget* aDrawTarget,
float aOpacity,
const gfxMatrix& aCTM)
{
return mFillPaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mFill, aCTM);
}
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
SVGContextPaintImpl::GetStrokePattern(const DrawTarget* aDrawTarget,
float aOpacity,
const gfxMatrix& aCTM)
{
return mStrokePaint.GetPattern(aDrawTarget, aOpacity, &nsStyleSVG::mStroke, aCTM);
}
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
SVGContextPaintImpl::Paint::GetPattern(const DrawTarget* aDrawTarget,
float aOpacity,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
const gfxMatrix& aCTM)
{
RefPtr<gfxPattern> pattern;
if (mPatternCache.Get(aOpacity, getter_AddRefs(pattern))) {
// Set the pattern matrix just in case it was messed with by a previous
// caller. We should get the same matrix each time a pattern is constructed
// so this should be fine.
pattern->SetMatrix(aCTM * mPatternMatrix);
- return pattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(pattern));
}
+ DrawResult result = DrawResult::SUCCESS;
switch (mPaintType) {
case eStyleSVGPaintType_None:
pattern = new gfxPattern(Color());
mPatternMatrix = gfxMatrix();
break;
case eStyleSVGPaintType_Color: {
Color color = Color::FromABGR(mPaintDefinition.mColor);
color.a *= aOpacity;
pattern = new gfxPattern(color);
mPatternMatrix = gfxMatrix();
break;
}
case eStyleSVGPaintType_Server:
- pattern = mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
- aDrawTarget,
- mContextMatrix,
- aFillOrStroke,
- aOpacity);
+ Tie(result, pattern) =
+ mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
+ aDrawTarget,
+ mContextMatrix,
+ aFillOrStroke,
+ aOpacity);
{
// m maps original-user-space to pattern space
gfxMatrix m = pattern->GetMatrix();
gfxMatrix deviceToOriginalUserSpace = mContextMatrix;
if (!deviceToOriginalUserSpace.Invert()) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
}
// mPatternMatrix maps device space to pattern space via original user space
mPatternMatrix = deviceToOriginalUserSpace * m;
}
pattern->SetMatrix(aCTM * mPatternMatrix);
break;
case eStyleSVGPaintType_ContextFill:
- pattern = mPaintDefinition.mContextPaint->GetFillPattern(aDrawTarget,
+ Tie(result, pattern) =
+ mPaintDefinition.mContextPaint->GetFillPattern(aDrawTarget,
aOpacity, aCTM);
// Don't cache this. mContextPaint will have cached it anyway. If we
// cache it, we'll have to compute mPatternMatrix, which is annoying.
- return pattern.forget();
+ return MakePair(result, Move(pattern));
case eStyleSVGPaintType_ContextStroke:
- pattern = mPaintDefinition.mContextPaint->GetStrokePattern(aDrawTarget,
+ Tie(result, pattern) =
+ mPaintDefinition.mContextPaint->GetStrokePattern(aDrawTarget,
aOpacity, aCTM);
// Don't cache this. mContextPaint will have cached it anyway. If we
// cache it, we'll have to compute mPatternMatrix, which is annoying.
- return pattern.forget();
+ return MakePair(result, Move(pattern));
default:
MOZ_ASSERT(false, "invalid paint type");
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
}
mPatternCache.Put(aOpacity, pattern);
- return pattern.forget();
+ return MakePair(result, Move(pattern));
}
AutoSetRestoreSVGContextPaint::AutoSetRestoreSVGContextPaint(
const SVGContextPaint* aContextPaint,
nsIDocument* aSVGDocument)
: mSVGDocument(aSVGDocument)
, mOuterContextPaint(aSVGDocument->GetProperty(nsGkAtoms::svgContextPaint))
{
@@ -274,43 +289,45 @@ AutoSetRestoreSVGContextPaint::~AutoSetR
NS_WARNING_ASSERTION(NS_SUCCEEDED(res), "Failed to restore context paint");
}
}
// SVGEmbeddingContextPaint
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
SVGEmbeddingContextPaint::GetFillPattern(const DrawTarget* aDrawTarget,
float aFillOpacity,
const gfxMatrix& aCTM)
{
if (!mFill) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
}
// The gfxPattern that we create below depends on aFillOpacity, and since
// different elements in the SVG image may pass in different values for
// fill opacities we don't try to cache the gfxPattern that we create.
Color fill = *mFill;
fill.a *= aFillOpacity;
- return do_AddRef(new gfxPattern(fill));
+ RefPtr<gfxPattern> patern = new gfxPattern(fill);
+ return MakePair(DrawResult::SUCCESS, Move(patern));
}
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
SVGEmbeddingContextPaint::GetStrokePattern(const DrawTarget* aDrawTarget,
float aStrokeOpacity,
const gfxMatrix& aCTM)
{
if (!mStroke) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<gfxPattern>());
}
Color stroke = *mStroke;
stroke.a *= aStrokeOpacity;
- return do_AddRef(new gfxPattern(stroke));
+ RefPtr<gfxPattern> patern = new gfxPattern(stroke);
+ return MakePair(DrawResult::SUCCESS, Move(patern));
}
uint32_t
SVGEmbeddingContextPaint::Hash() const
{
uint32_t hash = 0;
if (mFill) {
--- a/layout/svg/SVGContextPaint.h
+++ b/layout/svg/SVGContextPaint.h
@@ -12,16 +12,17 @@
#include "gfxTypes.h"
#include "gfxUtils.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Assertions.h"
#include "mozilla/gfx/2D.h"
#include "nsColor.h"
#include "nsStyleStruct.h"
#include "nsTArray.h"
+#include "DrawResult.h"
class gfxContext;
class nsIDocument;
class nsSVGPaintServerFrame;
namespace mozilla {
/**
@@ -48,36 +49,40 @@ namespace mozilla {
class SVGContextPaint : public RefCounted<SVGContextPaint>
{
protected:
typedef mozilla::gfx::DrawTarget DrawTarget;
SVGContextPaint() {}
public:
+ typedef image::DrawResult DrawResult;
+
MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint)
virtual ~SVGContextPaint() {}
- virtual already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) = 0;
- virtual already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) = 0;
+ virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetFillPattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) = 0;
+ virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetStrokePattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) = 0;
virtual float GetFillOpacity() const = 0;
virtual float GetStrokeOpacity() const = 0;
- already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
- const gfxMatrix& aCTM) {
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetFillPattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM) {
return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM);
}
- already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
- const gfxMatrix& aCTM) {
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetStrokePattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM) {
return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM);
}
static SVGContextPaint* GetContextPaint(nsIContent* aContent);
// XXX This gets the geometry params from the gfxContext. We should get that
// information from the actual paint context!
void InitStrokeGeometry(gfxContext *aContext,
@@ -133,28 +138,34 @@ private:
/**
* This class should be flattened into SVGContextPaint once we get rid of the
* other sub-class (SimpleTextContextPaint).
*/
struct SVGContextPaintImpl : public SVGContextPaint
{
protected:
typedef mozilla::gfx::DrawTarget DrawTarget;
+
public:
- DrawMode Init(const DrawTarget* aDrawTarget,
- const gfxMatrix& aContextMatrix,
- nsIFrame* aFrame,
- SVGContextPaint* aOuterContextPaint);
+ typedef mozilla::image::DrawResult DrawResult;
- already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) override;
- already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- const gfxMatrix& aCTM) override;
+ mozilla::Pair<DrawResult, DrawMode>
+ Init(const DrawTarget* aDrawTarget,
+ const gfxMatrix& aContextMatrix,
+ nsIFrame* aFrame,
+ SVGContextPaint* aOuterContextPaint);
+
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetFillPattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) override;
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetStrokePattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) override;
void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
float GetFillOpacity() const override { return mFillOpacity; }
void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
float GetStrokeOpacity() const override { return mStrokeOpacity; }
struct Paint {
@@ -194,20 +205,21 @@ public:
// CTM defining the user space for the pattern we will use.
gfxMatrix mContextMatrix;
nsStyleSVGPaintType mPaintType;
// Device-space-to-pattern-space
gfxMatrix mPatternMatrix;
nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
- already_AddRefed<gfxPattern> GetPattern(const DrawTarget* aDrawTarget,
- float aOpacity,
- nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
- const gfxMatrix& aCTM);
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetPattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
+ const gfxMatrix& aCTM);
};
Paint mFillPaint;
Paint mStrokePaint;
float mFillOpacity;
float mStrokeOpacity;
};
@@ -216,40 +228,41 @@ public:
* This class is used to pass context paint to an SVG image when an element
* references that image (e.g. via HTML <img> or SVG <image>, or by referencing
* it from a CSS property such as 'background-image'). In this case we only
* support context colors and not paint servers.
*/
class SVGEmbeddingContextPaint : public SVGContextPaint
{
typedef gfx::Color Color;
+ typedef mozilla::image::DrawResult DrawResult;
public:
SVGEmbeddingContextPaint() {}
void SetFill(nscolor aFill) {
mFill.emplace(gfx::ToDeviceColor(aFill));
}
void SetStroke(nscolor aStroke) {
mStroke.emplace(gfx::ToDeviceColor(aStroke));
}
/**
* Returns a pattern of type PatternType::COLOR, or else nullptr.
*/
- already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
- float aFillOpacity,
- const gfxMatrix& aCTM) override;
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetFillPattern(const DrawTarget* aDrawTarget, float aFillOpacity,
+ const gfxMatrix& aCTM) override;
/**
* Returns a pattern of type PatternType::COLOR, or else nullptr.
*/
- already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
- float aStrokeOpacity,
- const gfxMatrix& aCTM) override;
+ mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
+ GetStrokePattern(const DrawTarget* aDrawTarget, float aStrokeOpacity,
+ const gfxMatrix& aCTM) override;
float GetFillOpacity() const override {
// Always 1.0f since we don't currently allow 'context-fill-opacity'
return 1.0f;
};
float GetStrokeOpacity() const override {
// Always 1.0f since we don't currently allow 'context-stroke-opacity'
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -288,39 +288,41 @@ SVGGeometryFrame::PaintSVG(gfxContext& a
// Matrix to the geometry's user space:
gfxMatrix newMatrix =
aContext.CurrentMatrix().PreMultiply(aTransform).NudgeToIntegers();
if (newMatrix.IsSingular()) {
return DrawResult::BAD_ARGS;
}
uint32_t paintOrder = StyleSVG()->mPaintOrder;
+ DrawResult result = DrawResult::SUCCESS;
+
if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
- Render(&aContext, eRenderFill | eRenderStroke, newMatrix);
+ result = Render(&aContext, eRenderFill | eRenderStroke, newMatrix);
PaintMarkers(aContext, aTransform);
} else {
while (paintOrder) {
uint32_t component =
paintOrder & ((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1);
switch (component) {
case NS_STYLE_PAINT_ORDER_FILL:
- Render(&aContext, eRenderFill, newMatrix);
+ result &= Render(&aContext, eRenderFill, newMatrix);
break;
case NS_STYLE_PAINT_ORDER_STROKE:
- Render(&aContext, eRenderStroke, newMatrix);
+ result &= Render(&aContext, eRenderStroke, newMatrix);
break;
case NS_STYLE_PAINT_ORDER_MARKERS:
PaintMarkers(aContext, aTransform);
break;
}
paintOrder >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
}
}
- return DrawResult::SUCCESS;
+ return result;
}
nsIFrame*
SVGGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
{
FillRule fillRule;
uint16_t hitTestFlags;
if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
@@ -744,17 +746,17 @@ nsSVGMarkerFrame *
SVGGeometryFrame::MarkerProperties::GetMarkerEndFrame()
{
if (!mMarkerEnd)
return nullptr;
return static_cast<nsSVGMarkerFrame *>
(mMarkerEnd->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nullptr));
}
-void
+DrawResult
SVGGeometryFrame::Render(gfxContext* aContext,
uint32_t aRenderComponents,
const gfxMatrix& aNewTransform)
{
MOZ_ASSERT(!aNewTransform.IsSingular());
DrawTarget* drawTarget = aContext->GetDrawTarget();
@@ -780,35 +782,38 @@ SVGGeometryFrame::Render(gfxContext* aCo
// We don't complicate this code with GetAsSimplePath since the cost of
// masking will dwarf Path creation overhead anyway.
RefPtr<Path> path = element->GetOrBuildPath(*drawTarget, fillRule);
if (path) {
ColorPattern white(ToDeviceColor(Color(1.0f, 1.0f, 1.0f, 1.0f)));
drawTarget->Fill(path, white,
DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
}
- return;
+ return DrawResult::SUCCESS;
}
SVGGeometryElement::SimplePath simplePath;
RefPtr<Path> path;
element->GetAsSimplePath(&simplePath);
if (!simplePath.IsPath()) {
path = element->GetOrBuildPath(*drawTarget, fillRule);
if (!path) {
- return;
+ return DrawResult::SUCCESS;
}
}
SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(mContent);
+ DrawResult result = DrawResult::SUCCESS;
if (aRenderComponents & eRenderFill) {
GeneralPattern fillPattern;
- nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern, contextPaint);
+ result = nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern,
+ contextPaint);
+
if (fillPattern.GetPattern()) {
DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
if (simplePath.IsRect()) {
drawTarget->FillRect(simplePath.AsRect(), fillPattern, drawOptions);
} else if (path) {
drawTarget->Fill(path, fillPattern, drawOptions);
}
}
@@ -819,53 +824,58 @@ SVGGeometryFrame::Render(gfxContext* aCo
// Account for vector-effect:non-scaling-stroke:
gfxMatrix userToOuterSVG;
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
// A simple Rect can't be transformed with rotate/skew, so let's switch
// to using a real path:
if (!path) {
path = element->GetOrBuildPath(*drawTarget, fillRule);
if (!path) {
- return;
+ return DrawResult::SUCCESS;
}
simplePath.Reset();
}
// We need to transform the path back into the appropriate ancestor
// coordinate system, and paint it it that coordinate system, in order
// for non-scaled stroke to paint correctly.
gfxMatrix outerSVGToUser = userToOuterSVG;
outerSVGToUser.Invert();
aContext->Multiply(outerSVGToUser);
RefPtr<PathBuilder> builder =
path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
path = builder->Finish();
}
GeneralPattern strokePattern;
- nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern, contextPaint);
+ result &=
+ nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern,
+ contextPaint);
+
if (strokePattern.GetPattern()) {
SVGContentUtils::AutoStrokeOptions strokeOptions;
SVGContentUtils::GetStrokeOptions(&strokeOptions,
static_cast<nsSVGElement*>(mContent),
StyleContext(), contextPaint);
// GetStrokeOptions may set the line width to zero as an optimization
if (strokeOptions.mLineWidth <= 0) {
- return;
+ return DrawResult::SUCCESS;
}
DrawOptions drawOptions(1.0f, CompositionOp::OP_OVER, aaMode);
if (simplePath.IsRect()) {
drawTarget->StrokeRect(simplePath.AsRect(), strokePattern,
strokeOptions, drawOptions);
} else if (simplePath.IsLine()) {
drawTarget->StrokeLine(simplePath.Point1(), simplePath.Point2(),
strokePattern, strokeOptions, drawOptions);
} else {
drawTarget->Stroke(path, strokePattern, strokeOptions, drawOptions);
}
}
}
+
+ return result;
}
void
SVGGeometryFrame::PaintMarkers(gfxContext& aContext,
const gfxMatrix& aTransform)
{
SVGContextPaint* contextPaint = SVGContextPaint::GetContextPaint(mContent);
--- a/layout/svg/SVGGeometryFrame.h
+++ b/layout/svg/SVGGeometryFrame.h
@@ -115,18 +115,18 @@ protected:
* This function returns a set of bit flags indicating which parts of the
* element (fill, stroke, bounds) should intercept pointer events. It takes
* into account the type of element and the value of the 'pointer-events'
* property on the element.
*/
virtual uint16_t GetHitTestFlags();
private:
enum { eRenderFill = 1, eRenderStroke = 2 };
- void Render(gfxContext* aContext, uint32_t aRenderComponents,
- const gfxMatrix& aTransform);
+ DrawResult Render(gfxContext* aContext, uint32_t aRenderComponents,
+ const gfxMatrix& aTransform);
/**
* @param aMatrix The transform that must be multiplied onto aContext to
* establish this frame's SVG user space.
*/
void PaintMarkers(gfxContext& aContext, const gfxMatrix& aMatrix);
struct MarkerProperties {
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -2924,17 +2924,17 @@ SVGTextDrawPathCallbacks::HandleTextGeom
}
}
void
SVGTextDrawPathCallbacks::MakeFillPattern(GeneralPattern* aOutPattern)
{
if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
mColor == NS_40PERCENT_FOREGROUND_COLOR) {
- nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern);
+ Unused << nsSVGUtils::MakeFillPatternFor(mFrame, gfx, aOutPattern);
return;
}
if (mColor == NS_TRANSPARENT) {
return;
}
aOutPattern->InitColorPattern(ToDeviceColor(mColor));
@@ -2995,17 +2995,18 @@ SVGTextDrawPathCallbacks::FillGeometry()
void
SVGTextDrawPathCallbacks::StrokeGeometry()
{
// We don't paint the stroke when we are filling with a selection color.
if (mColor == NS_SAME_AS_FOREGROUND_COLOR ||
mColor == NS_40PERCENT_FOREGROUND_COLOR) {
if (nsSVGUtils::HasStroke(mFrame, /*aContextPaint*/ nullptr)) {
GeneralPattern strokePattern;
- nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern, /*aContextPaint*/ nullptr);
+ Unused << nsSVGUtils::MakeStrokePatternFor(mFrame, gfx, &strokePattern,
+ /*aContextPaint*/ nullptr);
if (strokePattern.GetPattern()) {
if (!mFrame->GetParent()->GetContent()->IsSVGElement()) {
// The cast that follows would be unsafe
MOZ_ASSERT(false, "Our nsTextFrame's parent's content should be SVG");
return;
}
nsSVGElement* svgOwner =
static_cast<nsSVGElement*>(mFrame->GetParent()->GetContent());
@@ -3640,33 +3641,35 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
TextRenderedRunIterator it(this, TextRenderedRunIterator::eVisibleFrames);
TextRenderedRun run = it.Current();
SVGContextPaint* outerContextPaint =
SVGContextPaint::GetContextPaint(mContent);
nsRenderingContext rendCtx(&aContext);
-
+ DrawResult finalResult = DrawResult::SUCCESS;
while (run.mFrame) {
nsTextFrame* frame = run.mFrame;
// Determine how much of the left and right edges of the text frame we
// need to ignore.
SVGCharClipDisplayItem item(run);
// Set up the fill and stroke so that SVG glyphs can get painted correctly
// when they use context-fill etc.
aContext.SetMatrix(initialMatrix);
RefPtr<SVGContextPaintImpl> contextPaint = new SVGContextPaintImpl();
- DrawMode drawMode = contextPaint->Init(&aDrawTarget,
- aContext.CurrentMatrix(),
- frame, outerContextPaint);
-
+ DrawMode drawMode;
+ DrawResult result = DrawResult::SUCCESS;
+ Tie(result, drawMode) = contextPaint->Init(&aDrawTarget,
+ aContext.CurrentMatrix(),
+ frame, outerContextPaint);
+ finalResult &= result;
if (drawMode & DrawMode::GLYPH_STROKE) {
// This may change the gfxContext's transform (for non-scaling stroke),
// in which case this needs to happen before we call SetMatrix() below.
nsSVGUtils::SetupCairoStrokeGeometry(frame, &aContext, outerContextPaint);
}
// Set up the transform for painting the text frame for the substring
// indicated by the run.
@@ -3698,17 +3701,17 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
// caret with, rather than using the color property?
caret->PaintCaret(aDrawTarget, frame, nsPoint());
aContext.NewPath();
}
run = it.Next();
}
- return DrawResult::SUCCESS;
+ return finalResult;
}
nsIFrame*
SVGTextFrame::GetFrameForPoint(const gfxPoint& aPoint)
{
NS_ASSERTION(PrincipalChildList().FirstChild(), "must have a child frame");
if (mState & NS_FRAME_IS_NONDISPLAY) {
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -391,31 +391,32 @@ nsFilterInstance::BuildSourcePaint(Sourc
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
MOZ_ASSERT(ctx); // already checked the draw target above
gfxContextAutoSaveRestore saver(ctx);
ctx->SetMatrix(mPaintTransform *
gfxMatrix::Translation(-neededRect.TopLeft()));
GeneralPattern pattern;
+ DrawResult result = DrawResult::SUCCESS;
if (aSource == &mFillPaint) {
- nsSVGUtils::MakeFillPatternFor(mTargetFrame, ctx, &pattern);
+ result = nsSVGUtils::MakeFillPatternFor(mTargetFrame, ctx, &pattern);
} else if (aSource == &mStrokePaint) {
- nsSVGUtils::MakeStrokePatternFor(mTargetFrame, ctx, &pattern);
+ result = nsSVGUtils::MakeStrokePatternFor(mTargetFrame, ctx, &pattern);
}
if (pattern.GetPattern()) {
offscreenDT->FillRect(ToRect(FilterSpaceToUserSpace(ThebesRect(neededRect))),
pattern);
}
aSource->mSourceSurface = offscreenDT->Snapshot();
aSource->mSurfaceRect = neededRect;
- return DrawResult::SUCCESS;
+ return result;
}
DrawResult
nsFilterInstance::BuildSourcePaints()
{
if (!mFillPaint.mNeededBounds.IsEmpty()) {
DrawResult result = BuildSourcePaint(&mFillPaint);
if (result != DrawResult::SUCCESS) {
--- a/layout/svg/nsSVGGradientFrame.cpp
+++ b/layout/svg/nsSVGGradientFrame.cpp
@@ -218,17 +218,17 @@ static void GetStopInformation(nsIFrame*
static_cast<SVGStopElement*>(stopContent)->
GetAnimatedNumberValues(aOffset, nullptr);
*aOffset = mozilla::clamped(*aOffset, 0.0f, 1.0f);
*aStopColor = aStopFrame->StyleSVGReset()->mStopColor;
*aStopOpacity = aStopFrame->StyleSVGReset()->mStopOpacity;
}
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
nsSVGGradientFrame::GetPaintServerPattern(nsIFrame* aSource,
const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aGraphicOpacity,
const gfxRect* aOverrideBounds)
{
uint16_t gradientUnits = GetGradientUnits();
@@ -246,55 +246,56 @@ nsSVGGradientFrame::GetPaintServerPatter
GetStopFrames(&stopFrames);
uint32_t nStops = stopFrames.Length();
// SVG specification says that no stops should be treated like
// the corresponding fill or stroke had "none" specified.
if (nStops == 0) {
RefPtr<gfxPattern> pattern = new gfxPattern(Color());
- return pattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(pattern));
}
if (nStops == 1 || GradientVectorLengthIsZero()) {
// The gradient paints a single colour, using the stop-color of the last
// gradient step if there are more than one.
float stopOpacity = stopFrames[nStops-1]->StyleSVGReset()->mStopOpacity;
nscolor stopColor = stopFrames[nStops-1]->StyleSVGReset()->mStopColor;
Color stopColor2 = Color::FromABGR(stopColor);
stopColor2.a *= stopOpacity * aGraphicOpacity;
RefPtr<gfxPattern> pattern = new gfxPattern(stopColor2);
- return pattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(pattern));
}
// Get the transform list (if there is one). We do this after the returns
// above since this call can be expensive when "gradientUnits" is set to
// "objectBoundingBox" (since that requiring a GetBBox() call).
gfxMatrix patternMatrix = GetGradientTransform(aSource, aOverrideBounds);
if (patternMatrix.IsSingular()) {
- return nullptr;
+ return MakePair(DrawResult::BAD_ARGS, RefPtr<gfxPattern>());
}
// revert any vector effect transform so that the gradient appears unchanged
if (aFillOrStroke == &nsStyleSVG::mStroke) {
gfxMatrix userToOuterSVG;
if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
patternMatrix *= userToOuterSVG;
}
}
if (!patternMatrix.Invert()) {
- return nullptr;
+ return MakePair(DrawResult::BAD_ARGS, RefPtr<gfxPattern>());
}
RefPtr<gfxPattern> gradient = CreateGradient();
- if (!gradient)
- return nullptr;
+ if (!gradient) {
+ return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<gfxPattern>());
+ }
uint16_t aSpread = GetSpreadMethod();
if (aSpread == SVG_SPREADMETHOD_PAD)
gradient->SetExtend(ExtendMode::CLAMP);
else if (aSpread == SVG_SPREADMETHOD_REFLECT)
gradient->SetExtend(ExtendMode::REFLECT);
else if (aSpread == SVG_SPREADMETHOD_REPEAT)
gradient->SetExtend(ExtendMode::REPEAT);
@@ -315,17 +316,17 @@ nsSVGGradientFrame::GetPaintServerPatter
else
lastOffset = offset;
Color stopColor2 = Color::FromABGR(stopColor);
stopColor2.a *= stopOpacity * aGraphicOpacity;
gradient->AddColorStop(offset, stopColor2);
}
- return gradient.forget();
+ return MakePair(DrawResult::SUCCESS, Move(gradient));
}
// Private (helper) methods
nsSVGGradientFrame *
nsSVGGradientFrame::GetReferencedGradient()
{
if (mNoHRefURI)
--- a/layout/svg/nsSVGGradientFrame.h
+++ b/layout/svg/nsSVGGradientFrame.h
@@ -41,17 +41,17 @@ class nsSVGGradientFrame : public nsSVGP
protected:
explicit nsSVGGradientFrame(nsStyleContext* aContext);
public:
NS_DECL_ABSTRACT_FRAME(nsSVGGradientFrame)
// nsSVGPaintServerFrame methods:
- virtual already_AddRefed<gfxPattern>
+ virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
GetPaintServerPattern(nsIFrame* aSource,
const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aGraphicOpacity,
const gfxRect* aOverrideBounds) override;
// nsIFrame interface:
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -920,17 +920,16 @@ nsSVGIntegrationUtils::PaintMaskAndClipP
if (paintResult.transparentBlackMask) {
return paintResult.result;
}
result &= paintResult.result;
maskSurface = paintResult.maskSurface;
if (maskSurface) {
- MOZ_ASSERT(paintResult.result == DrawResult::SUCCESS);
shouldPushMask = true;
maskTransform = paintResult.maskTransform;
opacityApplied = paintResult.opacityApplied;
}
}
if (maskUsage.shouldGenerateClipMaskLayer) {
matSR.Restore();
@@ -1227,20 +1226,22 @@ nsSVGIntegrationUtils::DrawableFromPaint
// frame by default, so aPaintServerSize is the whole target background fill
// area.
nsSVGPaintServerFrame* server =
static_cast<nsSVGPaintServerFrame*>(aFrame);
gfxRect overrideBounds(0, 0,
aPaintServerSize.width, aPaintServerSize.height);
overrideBounds.ScaleInverse(aFrame->PresContext()->AppUnitsPerDevPixel());
- RefPtr<gfxPattern> pattern =
- server->GetPaintServerPattern(aTarget, aDrawTarget,
- aContextMatrix, &nsStyleSVG::mFill, 1.0,
- &overrideBounds);
+ DrawResult result = DrawResult::SUCCESS;
+ RefPtr<gfxPattern> pattern;
+ Tie(result, pattern) =
+ server->GetPaintServerPattern(aTarget, aDrawTarget,
+ aContextMatrix, &nsStyleSVG::mFill, 1.0,
+ &overrideBounds);
if (!pattern)
return nullptr;
// pattern is now set up to fill aPaintServerSize. But we want it to
// fill aRenderSize, so we need to add a scaling transform.
// We couldn't just have set overrideBounds to aRenderSize - it would have
// worked for gradients, but for patterns it would result in a different
--- a/layout/svg/nsSVGMaskFrame.cpp
+++ b/layout/svg/nsSVGMaskFrame.cpp
@@ -248,34 +248,31 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
context->CurrentMatrix() * gfxMatrix::Translation(-maskSurfaceRect.TopLeft());
RefPtr<gfxContext> tmpCtx = gfxContext::CreateOrNull(maskDT);
MOZ_ASSERT(tmpCtx); // already checked the draw target above
tmpCtx->SetMatrix(maskSurfaceMatrix);
mMatrixForChildren = GetMaskTransform(aParams.maskedFrame) *
aParams.toUserSpace;
- DrawResult result;
+ DrawResult result = DrawResult::SUCCESS;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
// The CTM of each frame referencing us can be different
nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
}
gfxMatrix m = mMatrixForChildren;
if (kid->GetContent()->IsSVGElement()) {
m = static_cast<nsSVGElement*>(kid->GetContent())->
PrependLocalTransformsTo(m, eUserSpaceToParent);
}
- result = nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m);
- if (result != DrawResult::SUCCESS) {
- return MakePair(result, RefPtr<SourceSurface>());
- }
+ result &= nsSVGUtils::PaintFrameWithEffects(kid, *tmpCtx, m);
}
RefPtr<SourceSurface> maskSnapshot = maskDT->Snapshot();
if (!maskSnapshot) {
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}
RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
DataSourceSurface::MappedSurface map;
@@ -324,17 +321,17 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(Ma
// Moz2D transforms in the opposite direction to Thebes
if (!maskSurfaceMatrix.Invert()) {
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}
*aParams.maskTransform = ToMatrix(maskSurfaceMatrix);
RefPtr<SourceSurface> surface = destMaskSurface.forget();
- return MakePair(DrawResult::SUCCESS, Move(surface));
+ return MakePair(result, Move(surface));
}
gfxRect
nsSVGMaskFrame::GetMaskArea(nsIFrame* aMaskedFrame)
{
SVGMaskElement *maskElem = static_cast<SVGMaskElement*>(mContent);
uint16_t units =
--- a/layout/svg/nsSVGPaintServerFrame.h
+++ b/layout/svg/nsSVGPaintServerFrame.h
@@ -51,16 +51,17 @@ private:
nsIFrame* mFrame;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class nsSVGPaintServerFrame : public nsSVGContainerFrame
{
protected:
typedef mozilla::gfx::DrawTarget DrawTarget;
+ typedef mozilla::image::DrawResult DrawResult;
explicit nsSVGPaintServerFrame(nsStyleContext* aContext)
: nsSVGContainerFrame(aContext)
{
AddStateBits(NS_FRAME_IS_NONDISPLAY);
}
public:
@@ -69,17 +70,17 @@ public:
/**
* Constructs a gfxPattern of the paint server rendering.
*
* @param aContextMatrix The transform matrix that is currently applied to
* the gfxContext that is being drawn to. This is needed by SVG patterns so
* that surfaces of the correct size can be created. (SVG gradients are
* vector based, so it's not used there.)
*/
- virtual already_AddRefed<gfxPattern>
+ virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
GetPaintServerPattern(nsIFrame *aSource,
const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aOpacity,
const gfxRect *aOverrideBounds = nullptr) = 0;
// nsIFrame methods:
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -206,17 +206,17 @@ GetTargetGeometry(gfxRect *aBBox,
float scale = MaxExpansion(aContextMatrix);
if (scale <= 0) {
return NS_ERROR_FAILURE;
}
aBBox->Scale(scale);
return NS_OK;
}
-already_AddRefed<SourceSurface>
+mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
nsSVGPatternFrame::PaintPattern(const DrawTarget* aDrawTarget,
Matrix* patternMatrix,
const Matrix &aContextMatrix,
nsIFrame *aSource,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aGraphicOpacity,
const gfxRect *aOverrideBounds)
{
@@ -229,17 +229,18 @@ nsSVGPatternFrame::PaintPattern(const Dr
* Calculate the content transformation matrix
* Get our children (we may need to get them from another Pattern)
* Call SVGPaint on all of our children
* Return
*/
nsSVGPatternFrame* patternWithChildren = GetPatternWithChildren();
if (!patternWithChildren) {
- return nullptr; // Either no kids or a bad reference
+ // Either no kids or a bad reference
+ return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
}
nsIFrame* firstKid = patternWithChildren->mFrames.FirstChild();
const nsSVGViewBox& viewBox = GetViewBox();
uint16_t patternContentUnits =
GetEnumValue(SVGPatternElement::PATTERNCONTENTUNITS);
uint16_t patternUnits =
@@ -268,76 +269,76 @@ nsSVGPatternFrame::PaintPattern(const Dr
// the geometry that is being rendered with a pattern
gfxRect callerBBox;
if (NS_FAILED(GetTargetGeometry(&callerBBox,
viewBox,
patternContentUnits, patternUnits,
aSource,
aContextMatrix,
aOverrideBounds))) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
}
// Construct the CTM that we will provide to our children when we
// render them into the tile.
gfxMatrix ctm = ConstructCTM(viewBox, patternContentUnits, patternUnits,
callerBBox, aContextMatrix, aSource);
if (ctm.IsSingular()) {
- return nullptr;
+ return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
}
if (patternWithChildren->mCTM) {
*patternWithChildren->mCTM = ctm;
} else {
patternWithChildren->mCTM = new gfxMatrix(ctm);
}
// Get the bounding box of the pattern. This will be used to determine
// the size of the surface, and will also be used to define the bounding
// box for the pattern tile.
gfxRect bbox = GetPatternRect(patternUnits, callerBBox, aContextMatrix, aSource);
if (bbox.Width() <= 0.0 || bbox.Height() <= 0.0) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
}
// Get the pattern transform
Matrix patternTransform = ToMatrix(GetPatternTransform());
// revert the vector effect transform so that the pattern appears unchanged
if (aFillOrStroke == &nsStyleSVG::mStroke) {
gfxMatrix userToOuterSVG;
if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
patternTransform *= ToMatrix(userToOuterSVG);
if (patternTransform.IsSingular()) {
NS_WARNING("Singular matrix painting non-scaling-stroke");
- return nullptr;
+ return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
}
}
}
// Get the transformation matrix that we will hand to the renderer's pattern
// routine.
*patternMatrix = GetPatternMatrix(patternUnits, patternTransform,
bbox, callerBBox, aContextMatrix);
if (patternMatrix->IsSingular()) {
- return nullptr;
+ return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
}
// Now that we have all of the necessary geometries, we can
// create our surface.
gfxRect transformedBBox = ThebesRect(patternTransform.TransformBounds(ToRect(bbox)));
bool resultOverflows;
IntSize surfaceSize =
nsSVGUtils::ConvertToSurfaceSize(
transformedBBox.Size(), &resultOverflows);
// 0 disables rendering, < 0 is an error
if (surfaceSize.width <= 0 || surfaceSize.height <= 0) {
- return nullptr;
+ return MakePair(DrawResult::SUCCESS, RefPtr<SourceSurface>());
}
gfxFloat patternWidth = bbox.Width();
gfxFloat patternHeight = bbox.Height();
if (resultOverflows ||
patternWidth != surfaceSize.width ||
patternHeight != surfaceSize.height) {
@@ -351,17 +352,17 @@ nsSVGPatternFrame::PaintPattern(const Dr
// and rescale pattern to compensate
patternMatrix->PreScale(patternWidth / surfaceSize.width,
patternHeight / surfaceSize.height);
}
RefPtr<DrawTarget> dt =
aDrawTarget->CreateSimilarDrawTarget(surfaceSize, SurfaceFormat::B8G8R8A8);
if (!dt || !dt->IsValid()) {
- return nullptr;
+ return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}
dt->ClearRect(Rect(0, 0, surfaceSize.width, surfaceSize.height));
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(ctx); // already checked the draw target above
if (aGraphicOpacity != 1.0f) {
ctx->Save();
@@ -374,46 +375,46 @@ nsSVGPatternFrame::PaintPattern(const Dr
if (aSource->IsFrameOfType(nsIFrame::eSVGGeometry)) {
// Set the geometrical parent of the pattern we are rendering
patternWithChildren->mSource = static_cast<SVGGeometryFrame*>(aSource);
}
// Delay checking NS_FRAME_DRAWING_AS_PAINTSERVER bit until here so we can
// give back a clear surface if there's a loop
+ DrawResult result = DrawResult::SUCCESS;
if (!(patternWithChildren->GetStateBits() & NS_FRAME_DRAWING_AS_PAINTSERVER)) {
AutoSetRestorePaintServerState paintServer(patternWithChildren);
for (nsIFrame* kid = firstKid; kid;
kid = kid->GetNextSibling()) {
// The CTM of each frame referencing us can be different
nsSVGDisplayableFrame* SVGFrame = do_QueryFrame(kid);
if (SVGFrame) {
SVGFrame->NotifySVGChanged(nsSVGDisplayableFrame::TRANSFORM_CHANGED);
}
gfxMatrix tm = *(patternWithChildren->mCTM);
if (kid->GetContent()->IsSVGElement()) {
tm = static_cast<nsSVGElement*>(kid->GetContent())->
PrependLocalTransformsTo(tm, eUserSpaceToParent);
}
- DrawResult result = nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm);
- if (result != DrawResult::SUCCESS) {
- return nullptr;
- }
+
+ result &= nsSVGUtils::PaintFrameWithEffects(kid, *ctx, tm);
}
}
patternWithChildren->mSource = nullptr;
if (aGraphicOpacity != 1.0f) {
ctx->PopGroupAndBlend();
ctx->Restore();
}
// caller now owns the surface
- return dt->Snapshot();
+ RefPtr<SourceSurface> surf = dt->Snapshot();
+ return MakePair(result, Move(surf));
}
/* Will probably need something like this... */
// How do we handle the insertion of a new frame?
// We really don't want to rerender this every time,
// do we?
nsSVGPatternFrame*
nsSVGPatternFrame::GetPatternWithChildren()
@@ -716,47 +717,49 @@ nsSVGPatternFrame::ConstructCTM(const ns
viewBoxRect.width, viewBoxRect.height,
GetPreserveAspectRatio());
return ThebesMatrix(tm);
}
//----------------------------------------------------------------------
// nsSVGPaintServerFrame methods:
-
-already_AddRefed<gfxPattern>
+mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
nsSVGPatternFrame::GetPaintServerPattern(nsIFrame *aSource,
const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aGraphicOpacity,
const gfxRect *aOverrideBounds)
{
if (aGraphicOpacity == 0.0f) {
RefPtr<gfxPattern> pattern = new gfxPattern(Color());
- return pattern.forget();
+ return MakePair(DrawResult::SUCCESS, Move(pattern));
}
// Paint it!
Matrix pMatrix;
- RefPtr<SourceSurface> surface =
+ RefPtr<SourceSurface> surface;
+ DrawResult result = DrawResult::SUCCESS;
+ Tie(result, surface) =
PaintPattern(aDrawTarget, &pMatrix, ToMatrix(aContextMatrix), aSource,
aFillOrStroke, aGraphicOpacity, aOverrideBounds);
if (!surface) {
- return nullptr;
+ return MakePair(result, RefPtr<gfxPattern>());
}
RefPtr<gfxPattern> pattern = new gfxPattern(surface, pMatrix);
- if (!pattern)
- return nullptr;
+ if (!pattern) {
+ return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<gfxPattern>());
+ }
pattern->SetExtend(ExtendMode::REPEAT);
- return pattern.forget();
+ return MakePair(result, Move(pattern));
}
// -------------------------------------------------------------------------
// Public functions
// -------------------------------------------------------------------------
nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext)
--- a/layout/svg/nsSVGPatternFrame.h
+++ b/layout/svg/nsSVGPatternFrame.h
@@ -35,17 +35,17 @@ public:
NS_DECL_FRAMEARENA_HELPERS
friend nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsSVGPatternFrame(nsStyleContext* aContext);
// nsSVGPaintServerFrame methods:
- virtual already_AddRefed<gfxPattern>
+ virtual mozilla::Pair<DrawResult, RefPtr<gfxPattern>>
GetPaintServerPattern(nsIFrame *aSource,
const DrawTarget* aDrawTarget,
const gfxMatrix& aContextMatrix,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aOpacity,
const gfxRect *aOverrideBounds) override;
public:
@@ -101,17 +101,17 @@ protected:
return GetPreserveAspectRatio(mContent);
}
const nsSVGLength2 *GetLengthValue(uint32_t aIndex, nsIContent *aDefault);
const nsSVGLength2 *GetLengthValue(uint32_t aIndex)
{
return GetLengthValue(aIndex, mContent);
}
- already_AddRefed<SourceSurface>
+ mozilla::Pair<DrawResult, RefPtr<SourceSurface>>
PaintPattern(const DrawTarget* aDrawTarget,
Matrix *patternMatrix,
const Matrix &aContextMatrix,
nsIFrame *aSource,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aGraphicOpacity,
const gfxRect *aOverrideBounds);
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1474,25 +1474,25 @@ nsSVGUtils::GetFallbackOrPaintColor(nsSt
nscolor colors[2] = { color, paintIfVisited.GetColor() };
return nsStyleContext::CombineVisitedColors(
colors, aStyleContext->RelevantLinkVisited());
}
}
return color;
}
-/* static */ void
+/* static */ DrawResult
nsSVGUtils::MakeFillPatternFor(nsIFrame* aFrame,
gfxContext* aContext,
GeneralPattern* aOutPattern,
SVGContextPaint* aContextPaint)
{
const nsStyleSVG* style = aFrame->StyleSVG();
if (style->mFill.Type() == eStyleSVGPaintType_None) {
- return;
+ return DrawResult::SUCCESS;
}
const float opacity = aFrame->StyleEffects()->mOpacity;
float fillOpacity = GetOpacity(style->FillOpacitySource(),
style->mFillOpacity,
aContextPaint);
if (opacity < 1.0f &&
@@ -1502,65 +1502,71 @@ nsSVGUtils::MakeFillPatternFor(nsIFrame*
fillOpacity *= opacity;
}
const DrawTarget* dt = aContext->GetDrawTarget();
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mFill,
nsSVGEffects::FillProperty());
+ DrawResult result = DrawResult::SUCCESS;
if (ps) {
- RefPtr<gfxPattern> pattern =
+ RefPtr<gfxPattern> pattern;
+ Tie(result, pattern) =
ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
&nsStyleSVG::mFill, fillOpacity);
if (pattern) {
pattern->CacheColorStops(dt);
aOutPattern->Init(*pattern->GetPattern(dt));
- return;
+ return result;
}
}
if (aContextPaint) {
RefPtr<gfxPattern> pattern;
switch (style->mFill.Type()) {
case eStyleSVGPaintType_ContextFill:
- pattern = aContextPaint->GetFillPattern(dt, fillOpacity,
- aContext->CurrentMatrix());
+ Tie(result, pattern) =
+ aContextPaint->GetFillPattern(dt, fillOpacity,
+ aContext->CurrentMatrix());
break;
case eStyleSVGPaintType_ContextStroke:
- pattern = aContextPaint->GetStrokePattern(dt, fillOpacity,
- aContext->CurrentMatrix());
+ Tie(result, pattern) =
+ aContextPaint->GetStrokePattern(dt, fillOpacity,
+ aContext->CurrentMatrix());
break;
default:
;
}
if (pattern) {
aOutPattern->Init(*pattern->GetPattern(dt));
- return;
+ return result;
}
}
// On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
Color color(Color::FromABGR(GetFallbackOrPaintColor(aFrame->StyleContext(),
&nsStyleSVG::mFill)));
color.a *= fillOpacity;
aOutPattern->InitColorPattern(ToDeviceColor(color));
+
+ return result;
}
-/* static */ void
+/* static */ DrawResult
nsSVGUtils::MakeStrokePatternFor(nsIFrame* aFrame,
gfxContext* aContext,
GeneralPattern* aOutPattern,
SVGContextPaint* aContextPaint)
{
const nsStyleSVG* style = aFrame->StyleSVG();
if (style->mStroke.Type() == eStyleSVGPaintType_None) {
- return;
+ return DrawResult::SUCCESS;
}
const float opacity = aFrame->StyleEffects()->mOpacity;
float strokeOpacity = GetOpacity(style->StrokeOpacitySource(),
style->mStrokeOpacity,
aContextPaint);
if (opacity < 1.0f &&
@@ -1570,54 +1576,60 @@ nsSVGUtils::MakeStrokePatternFor(nsIFram
strokeOpacity *= opacity;
}
const DrawTarget* dt = aContext->GetDrawTarget();
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, &nsStyleSVG::mStroke,
nsSVGEffects::StrokeProperty());
+ DrawResult result = DrawResult::SUCCESS;
if (ps) {
- RefPtr<gfxPattern> pattern =
+ RefPtr<gfxPattern> pattern;
+ Tie(result, pattern) =
ps->GetPaintServerPattern(aFrame, dt, aContext->CurrentMatrix(),
&nsStyleSVG::mStroke, strokeOpacity);
if (pattern) {
pattern->CacheColorStops(dt);
aOutPattern->Init(*pattern->GetPattern(dt));
- return;
+ return result;
}
}
if (aContextPaint) {
RefPtr<gfxPattern> pattern;
switch (style->mStroke.Type()) {
case eStyleSVGPaintType_ContextFill:
- pattern = aContextPaint->GetFillPattern(dt, strokeOpacity,
- aContext->CurrentMatrix());
+ Tie(result, pattern) =
+ aContextPaint->GetFillPattern(dt, strokeOpacity,
+ aContext->CurrentMatrix());
break;
case eStyleSVGPaintType_ContextStroke:
- pattern = aContextPaint->GetStrokePattern(dt, strokeOpacity,
- aContext->CurrentMatrix());
+ Tie(result, pattern) =
+ aContextPaint->GetStrokePattern(dt, strokeOpacity,
+ aContext->CurrentMatrix());
break;
default:
;
}
if (pattern) {
aOutPattern->Init(*pattern->GetPattern(dt));
- return;
+ return result;
}
}
// On failure, use the fallback colour in case we have an
// objectBoundingBox where the width or height of the object is zero.
// See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
Color color(Color::FromABGR(GetFallbackOrPaintColor(aFrame->StyleContext(),
&nsStyleSVG::mStroke)));
color.a *= strokeOpacity;
aOutPattern->InitColorPattern(ToDeviceColor(color));
+
+ return DrawResult::SUCCESS;
}
/* static */ float
nsSVGUtils::GetOpacity(nsStyleSVGOpacitySource aOpacityType,
const float& aOpacity,
SVGContextPaint *aContextPaint)
{
float opacity = 1.0f;
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -504,22 +504,22 @@ public:
{
return NS_lround(std::max(double(INT32_MIN),
std::min(double(INT32_MAX), aVal)));
}
static nscolor GetFallbackOrPaintColor(nsStyleContext *aStyleContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke);
- static void MakeFillPatternFor(nsIFrame *aFrame,
- gfxContext* aContext,
- GeneralPattern* aOutPattern,
- SVGContextPaint* aContextPaint = nullptr);
+ static DrawResult MakeFillPatternFor(nsIFrame *aFrame,
+ gfxContext* aContext,
+ GeneralPattern* aOutPattern,
+ SVGContextPaint* aContextPaint = nullptr);
- static void
+ static DrawResult
MakeStrokePatternFor(nsIFrame* aFrame,
gfxContext* aContext,
GeneralPattern* aOutPattern,
SVGContextPaint* aContextPaint = nullptr);
static float GetOpacity(nsStyleSVGOpacitySource aOpacityType,
const float& aOpacity,
SVGContextPaint* aContextPaint);