gecko-dev/layout/svg/nsSVGGradientFrame.h
cku 148bb081ca Bug 1345853 - Part 1. Pass DrawResult from nsSVGPatternFrame::PaintPattern back to nsDisplaySVGGeometry::Paint. r=mstange,tnikkel
I did many change in many files in this patch. But the goal is pretty simple: To
pass the return value of nsSVGPatternFrame::PaintPattern back to the caller
(nsDisplaySVGGeometry). My suggestion is to review this patch right from
nsSVGPatternFrame.cpp.

I made two mistakes in bug 1258510
1. We should not return directly at [1]. RemoveStateBits at l418 will be skip.
2. nsSVGPatternFrame::PaintPattern should return both SourceSurface and draw
result, so that we can update UpdateDrawResult in display item.

All the other changes are to
1. make sure the return value of nsSVGPatternFrame::PaintPattern goes back to
nsDisplaySVGGeometry::Paint correctly.
2. Since the return value of nsSVGPatternFrame::PaintPattern change, we need
modify all existed callers.

I also filed bug 1346124 for handle the returning value of PaintMarkers.

[1] https://hg.mozilla.org/mozilla-central/file/c0700bedb4f7/layout/svg/nsSVGPatternFrame.cpp#l415

MozReview-Commit-ID: Iq9RPQ6Omz0

--HG--
extra : rebase_source : ca7a35bb9f5e27880d5dc62e03feb91b6ac3435d
2017-03-21 10:12:23 +08:00

210 lines
7.3 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __NS_SVGGRADIENTFRAME_H__
#define __NS_SVGGRADIENTFRAME_H__
#include "mozilla/Attributes.h"
#include "gfxMatrix.h"
#include "nsCOMPtr.h"
#include "nsFrame.h"
#include "nsLiteralString.h"
#include "nsSVGPaintServerFrame.h"
class gfxPattern;
class nsIAtom;
class nsIContent;
class nsIFrame;
class nsIPresShell;
class nsStyleContext;
struct gfxRect;
namespace mozilla {
class nsSVGAnimatedTransformList;
namespace dom {
class SVGLinearGradientElement;
class SVGRadialGradientElement;
} // namespace dom
} // namespace mozilla
/**
* Gradients can refer to other gradients. We create an nsSVGPaintingProperty
* with property type nsGkAtoms::href to track the referenced gradient.
*/
class nsSVGGradientFrame : public nsSVGPaintServerFrame
{
typedef mozilla::gfx::ExtendMode ExtendMode;
protected:
explicit nsSVGGradientFrame(nsStyleContext* aContext);
public:
NS_DECL_ABSTRACT_FRAME(nsSVGGradientFrame)
// nsSVGPaintServerFrame methods:
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:
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override
{
return MakeFrameName(NS_LITERAL_STRING("SVGGradient"), aResult);
}
#endif // DEBUG
private:
// Parse our xlink:href and set up our nsSVGPaintingProperty if we
// reference another gradient and we don't have a property. Return
// the referenced gradient's frame if available, null otherwise.
nsSVGGradientFrame* GetReferencedGradient();
// Optionally get a stop frame (returns stop index/count)
void GetStopFrames(nsTArray<nsIFrame*>* aStopFrames);
const mozilla::nsSVGAnimatedTransformList* GetGradientTransformList(
nsIContent* aDefault);
// Will be singular for gradientUnits="objectBoundingBox" with an empty bbox.
gfxMatrix GetGradientTransform(nsIFrame *aSource,
const gfxRect *aOverrideBounds);
protected:
virtual bool GradientVectorLengthIsZero() = 0;
virtual already_AddRefed<gfxPattern> CreateGradient() = 0;
// Accessors to lookup gradient attributes
uint16_t GetEnumValue(uint32_t aIndex, nsIContent *aDefault);
uint16_t GetEnumValue(uint32_t aIndex)
{
return GetEnumValue(aIndex, mContent);
}
uint16_t GetGradientUnits();
uint16_t GetSpreadMethod();
// Gradient-type-specific lookups since the length values differ between
// linear and radial gradients
virtual mozilla::dom::SVGLinearGradientElement * GetLinearGradientWithLength(
uint32_t aIndex, mozilla::dom::SVGLinearGradientElement* aDefault);
virtual mozilla::dom::SVGRadialGradientElement * GetRadialGradientWithLength(
uint32_t aIndex, mozilla::dom::SVGRadialGradientElement* aDefault);
// The frame our gradient is (currently) being applied to
nsIFrame* mSource;
private:
// Flag to mark this frame as "in use" during recursive calls along our
// gradient's reference chain so we can detect reference loops. See:
// http://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute
bool mLoopFlag;
// Gradients often don't reference other gradients, so here we cache
// the fact that that isn't happening.
bool mNoHRefURI;
};
// -------------------------------------------------------------------------
// Linear Gradients
// -------------------------------------------------------------------------
class nsSVGLinearGradientFrame : public nsSVGGradientFrame
{
friend nsIFrame* NS_NewSVGLinearGradientFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
protected:
explicit nsSVGLinearGradientFrame(nsStyleContext* aContext)
: nsSVGGradientFrame(aContext) {}
public:
NS_DECL_FRAMEARENA_HELPERS
// nsIFrame interface:
#ifdef DEBUG
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
#endif
virtual nsIAtom* GetType() const override; // frame type: nsGkAtoms::svgLinearGradientFrame
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override
{
return MakeFrameName(NS_LITERAL_STRING("SVGLinearGradient"), aResult);
}
#endif // DEBUG
protected:
float GetLengthValue(uint32_t aIndex);
virtual mozilla::dom::SVGLinearGradientElement* GetLinearGradientWithLength(
uint32_t aIndex, mozilla::dom::SVGLinearGradientElement* aDefault) override;
virtual bool GradientVectorLengthIsZero() override;
virtual already_AddRefed<gfxPattern> CreateGradient() override;
};
// -------------------------------------------------------------------------
// Radial Gradients
// -------------------------------------------------------------------------
class nsSVGRadialGradientFrame : public nsSVGGradientFrame
{
friend nsIFrame* NS_NewSVGRadialGradientFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
protected:
explicit nsSVGRadialGradientFrame(nsStyleContext* aContext)
: nsSVGGradientFrame(aContext) {}
public:
NS_DECL_FRAMEARENA_HELPERS
// nsIFrame interface:
#ifdef DEBUG
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
#endif
virtual nsIAtom* GetType() const override; // frame type: nsGkAtoms::svgRadialGradientFrame
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override
{
return MakeFrameName(NS_LITERAL_STRING("SVGRadialGradient"), aResult);
}
#endif // DEBUG
protected:
float GetLengthValue(uint32_t aIndex);
float GetLengthValue(uint32_t aIndex, float aDefaultValue);
float GetLengthValueFromElement(uint32_t aIndex,
mozilla::dom::SVGRadialGradientElement& aElement);
virtual mozilla::dom::SVGRadialGradientElement* GetRadialGradientWithLength(
uint32_t aIndex, mozilla::dom::SVGRadialGradientElement* aDefault) override;
virtual bool GradientVectorLengthIsZero() override;
virtual already_AddRefed<gfxPattern> CreateGradient() override;
};
#endif // __NS_SVGGRADIENTFRAME_H__