mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 948265 - [CSS Filters] Change nsSVGFilterProperty to track an nsStyleFilter chain instead of a single nsIURI and nsSVGFilterFrame. r=roc
This commit is contained in:
parent
7af51c65ca
commit
ea7b318066
@ -160,7 +160,7 @@ SVGFilterElement::Invalidate()
|
||||
nsTObserverArray<nsIMutationObserver*>::ForwardIterator iter(*observers);
|
||||
while (iter.HasMore()) {
|
||||
nsCOMPtr<nsIMutationObserver> obs(iter.GetNext());
|
||||
nsCOMPtr<nsISVGFilterProperty> filter = do_QueryInterface(obs);
|
||||
nsCOMPtr<nsISVGFilterReference> filter = do_QueryInterface(obs);
|
||||
if (filter)
|
||||
filter->Invalidate();
|
||||
}
|
||||
|
@ -4971,7 +4971,7 @@ ComputeOutlineAndEffectsRect(nsIFrame* aFrame,
|
||||
// For SVG frames, we only need to account for filters.
|
||||
// TODO: We could also take account of clipPath and mask to reduce the
|
||||
// visual overflow, but that's not essential.
|
||||
if (aFrame->StyleSVGReset()->SingleFilter()) {
|
||||
if (aFrame->StyleSVGReset()->HasFilters()) {
|
||||
if (aStoreRectProperties) {
|
||||
aFrame->Properties().
|
||||
Set(nsIFrame::PreEffectsBBoxProperty(), new nsRect(r));
|
||||
|
@ -2626,13 +2626,8 @@ struct nsStyleSVGReset {
|
||||
nsChangeHint_ClearAncestorIntrinsics);
|
||||
}
|
||||
|
||||
// The backend only supports one SVG reference right now.
|
||||
// Eventually, it will support multiple chained SVG reference filters and CSS
|
||||
// filter functions.
|
||||
nsIURI* SingleFilter() const {
|
||||
return (mFilters.Length() == 1 &&
|
||||
mFilters[0].GetType() == NS_STYLE_FILTER_URL) ?
|
||||
mFilters[0].GetURL() : nullptr;
|
||||
bool HasFilters() const {
|
||||
return mFilters.Length() > 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> mClipPath; // [reset]
|
||||
|
@ -214,12 +214,72 @@ nsSVGRenderingObserver::ContentRemoved(nsIDocument *aDocument,
|
||||
DoUpdate();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterProperty,
|
||||
nsSVGIDRenderingObserver,
|
||||
nsISVGFilterProperty)
|
||||
NS_IMPL_ISUPPORTS1(nsSVGFilterProperty, nsISupports)
|
||||
|
||||
nsSVGFilterProperty::nsSVGFilterProperty(const nsTArray<nsStyleFilter> &aFilters,
|
||||
nsIFrame *aFilteredFrame) :
|
||||
mFilters(aFilters)
|
||||
{
|
||||
for (uint32_t i = 0; i < mFilters.Length(); i++) {
|
||||
if (mFilters[i].GetType() != NS_STYLE_FILTER_URL)
|
||||
continue;
|
||||
|
||||
nsSVGFilterReference *reference =
|
||||
new nsSVGFilterReference(mFilters[i].GetURL(), aFilteredFrame);
|
||||
NS_ADDREF(reference);
|
||||
mReferences.AppendElement(reference);
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGFilterProperty::~nsSVGFilterProperty()
|
||||
{
|
||||
for (uint32_t i = 0; i < mReferences.Length(); i++) {
|
||||
NS_RELEASE(mReferences[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsSVGFilterProperty::ReferencesValidResources()
|
||||
{
|
||||
for (uint32_t i = 0; i < mReferences.Length(); i++) {
|
||||
if (!mReferences[i]->ReferencesValidResource())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSVGFilterProperty::IsInObserverLists() const
|
||||
{
|
||||
for (uint32_t i = 0; i < mReferences.Length(); i++) {
|
||||
if (!mReferences[i]->IsInObserverList())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGFilterProperty::Invalidate()
|
||||
{
|
||||
for (uint32_t i = 0; i < mReferences.Length(); i++) {
|
||||
mReferences[i]->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGFilterFrame *
|
||||
nsSVGFilterProperty::GetFilterFrame()
|
||||
{
|
||||
// Eventually, callers will ask nsSVGFilterProperty for an nsStyleFilter
|
||||
// chain, not a single nsSVGFilterFrame, and this function will go away.
|
||||
return mReferences.Length() > 0 ? mReferences[0]->GetFilterFrame() : nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterReference,
|
||||
nsSVGIDRenderingObserver,
|
||||
nsISVGFilterReference);
|
||||
|
||||
nsSVGFilterFrame *
|
||||
nsSVGFilterReference::GetFilterFrame()
|
||||
{
|
||||
return static_cast<nsSVGFilterFrame *>
|
||||
(GetReferencedFrame(nsGkAtoms::svgFilterFrame, nullptr));
|
||||
@ -235,7 +295,7 @@ InvalidateAllContinuations(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGFilterProperty::DoUpdate()
|
||||
nsSVGFilterReference::DoUpdate()
|
||||
{
|
||||
nsSVGIDRenderingObserver::DoUpdate();
|
||||
if (!mFrame)
|
||||
@ -334,10 +394,6 @@ nsSVGPaintingProperty::DoUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
static nsSVGRenderingObserver *
|
||||
CreateFilterProperty(nsIURI *aURI, nsIFrame *aFrame, bool aReferenceImage)
|
||||
{ return new nsSVGFilterProperty(aURI, aFrame, aReferenceImage); }
|
||||
|
||||
static nsSVGRenderingObserver *
|
||||
CreateMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, bool aReferenceImage)
|
||||
{ return new nsSVGMarkerProperty(aURI, aFrame, aReferenceImage); }
|
||||
@ -371,6 +427,26 @@ GetEffectProperty(nsIURI *aURI, nsIFrame *aFrame,
|
||||
return prop;
|
||||
}
|
||||
|
||||
static nsSVGFilterProperty*
|
||||
GetOrCreateFilterProperty(nsIFrame *aFrame)
|
||||
{
|
||||
const nsStyleSVGReset* style = aFrame->StyleSVGReset();
|
||||
if (!style->HasFilters())
|
||||
return nullptr;
|
||||
|
||||
FrameProperties props = aFrame->Properties();
|
||||
nsSVGFilterProperty *prop =
|
||||
static_cast<nsSVGFilterProperty*>(props.Get(nsSVGEffects::FilterProperty()));
|
||||
if (prop)
|
||||
return prop;
|
||||
prop = new nsSVGFilterProperty(style->mFilters, aFrame);
|
||||
if (!prop)
|
||||
return nullptr;
|
||||
NS_ADDREF(prop);
|
||||
props.Set(nsSVGEffects::FilterProperty(), static_cast<nsISupports*>(prop));
|
||||
return prop;
|
||||
}
|
||||
|
||||
nsSVGMarkerProperty *
|
||||
nsSVGEffects::GetMarkerProperty(nsIURI *aURI, nsIFrame *aFrame,
|
||||
const FramePropertyDescriptor *aProp)
|
||||
@ -438,9 +514,7 @@ nsSVGEffects::GetEffectProperties(nsIFrame *aFrame)
|
||||
|
||||
EffectProperties result;
|
||||
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
|
||||
result.mFilter = static_cast<nsSVGFilterProperty*>
|
||||
(GetEffectProperty(style->SingleFilter(), aFrame, FilterProperty(),
|
||||
CreateFilterProperty));
|
||||
result.mFilter = GetOrCreateFilterProperty(aFrame);
|
||||
result.mClipPath =
|
||||
GetPaintingProperty(style->mClipPath, aFrame, ClipPathProperty());
|
||||
result.mMask =
|
||||
@ -515,8 +589,7 @@ nsSVGEffects::UpdateEffects(nsIFrame *aFrame)
|
||||
|
||||
// Ensure that the filter is repainted correctly
|
||||
// We can't do that in DoUpdate as the referenced frame may not be valid
|
||||
GetEffectProperty(aFrame->StyleSVGReset()->SingleFilter(),
|
||||
aFrame, FilterProperty(), CreateFilterProperty);
|
||||
GetOrCreateFilterProperty(aFrame);
|
||||
|
||||
if (aFrame->GetType() == nsGkAtoms::svgPathGeometryFrame &&
|
||||
static_cast<nsSVGPathGeometryElement*>(aFrame->GetContent())->IsMarkable()) {
|
||||
@ -536,7 +609,7 @@ nsSVGEffects::GetFilterProperty(nsIFrame *aFrame)
|
||||
{
|
||||
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
|
||||
|
||||
if (!aFrame->StyleSVGReset()->SingleFilter())
|
||||
if (!aFrame->StyleSVGReset()->HasFilters())
|
||||
return nullptr;
|
||||
|
||||
return static_cast<nsSVGFilterProperty *>
|
||||
|
@ -150,12 +150,25 @@ protected:
|
||||
nsIPresShell *mFramePresShell;
|
||||
};
|
||||
|
||||
class nsSVGFilterProperty :
|
||||
public nsSVGIDRenderingObserver, public nsISVGFilterProperty {
|
||||
/**
|
||||
* In a filter chain, there can be multiple SVG reference filters.
|
||||
* e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
|
||||
*
|
||||
* This class keeps track of one SVG reference filter in a filter chain.
|
||||
* e.g. url(#svg-filter-1)
|
||||
*
|
||||
* It fires invalidations when the SVG filter element's id changes or when
|
||||
* the SVG filter element's content changes.
|
||||
*
|
||||
* The nsSVGFilterProperty class manages a list of nsSVGFilterReferences.
|
||||
*/
|
||||
class nsSVGFilterReference :
|
||||
public nsSVGIDRenderingObserver, public nsISVGFilterReference {
|
||||
public:
|
||||
nsSVGFilterProperty(nsIURI *aURI, nsIFrame *aFilteredFrame,
|
||||
bool aReferenceImage)
|
||||
: nsSVGIDRenderingObserver(aURI, aFilteredFrame, aReferenceImage) {}
|
||||
nsSVGFilterReference(nsIURI *aURI, nsIFrame *aFilteredFrame)
|
||||
: nsSVGIDRenderingObserver(aURI, aFilteredFrame, false) {}
|
||||
|
||||
bool ReferencesValidResource() { return GetFilterFrame(); }
|
||||
|
||||
/**
|
||||
* @return the filter frame, or null if there is no filter frame
|
||||
@ -165,14 +178,48 @@ public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISVGFilterProperty
|
||||
virtual void Invalidate() MOZ_OVERRIDE { DoUpdate(); }
|
||||
// nsISVGFilterReference
|
||||
virtual void Invalidate() MOZ_OVERRIDE { DoUpdate(); };
|
||||
|
||||
private:
|
||||
// nsSVGRenderingObserver
|
||||
// nsSVGIDRenderingObserver
|
||||
virtual void DoUpdate() MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class manages a list of nsSVGFilterReferences, which represent SVG
|
||||
* reference filters in a filter chain.
|
||||
* e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
|
||||
*
|
||||
* In the above example, the nsSVGFilterProperty will manage two
|
||||
* nsSVGFilterReferences, one for each SVG reference filter. CSS filters like
|
||||
* "blur(10px)" don't reference filter elements, so they don't need an
|
||||
* nsSVGFilterReference. The style system invalidates changes to CSS filters.
|
||||
*/
|
||||
class nsSVGFilterProperty : public nsISupports {
|
||||
public:
|
||||
nsSVGFilterProperty(const nsTArray<nsStyleFilter> &aFilters,
|
||||
nsIFrame *aFilteredFrame);
|
||||
virtual ~nsSVGFilterProperty();
|
||||
|
||||
const nsTArray<nsStyleFilter>& GetFilters() { return mFilters; }
|
||||
bool ReferencesValidResources();
|
||||
bool IsInObserverLists() const;
|
||||
void Invalidate();
|
||||
|
||||
/**
|
||||
* @return the filter frame, or null if there is no filter frame
|
||||
*/
|
||||
nsSVGFilterFrame *GetFilterFrame();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
private:
|
||||
nsTArray<nsSVGFilterReference*> mReferences;
|
||||
nsTArray<nsStyleFilter> mFilters;
|
||||
};
|
||||
|
||||
class nsSVGMarkerProperty : public nsSVGIDRenderingObserver {
|
||||
public:
|
||||
nsSVGMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, bool aReferenceImage)
|
||||
|
@ -152,7 +152,7 @@ nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame)
|
||||
// checking the SDL prefs here, since we don't know if we're being called for
|
||||
// painting or hit-testing anyway.
|
||||
const nsStyleSVGReset *style = aFrame->StyleSVGReset();
|
||||
return (style->SingleFilter() || style->mClipPath || style->mMask);
|
||||
return (style->HasFilters() || style->mClipPath || style->mMask);
|
||||
}
|
||||
|
||||
/* static */ nsPoint
|
||||
@ -302,7 +302,7 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
|
||||
return aInvalidRect;
|
||||
|
||||
nsSVGFilterProperty *prop = nsSVGEffects::GetFilterProperty(firstFrame);
|
||||
if (!prop || !prop->IsInObserverList()) {
|
||||
if (!prop || !prop->IsInObserverLists()) {
|
||||
return aInvalidRect;
|
||||
}
|
||||
|
||||
|
@ -930,7 +930,7 @@ nsSVGUtils::CanOptimizeOpacity(nsIFrame *aFrame)
|
||||
type != nsGkAtoms::svgPathGeometryFrame) {
|
||||
return false;
|
||||
}
|
||||
if (aFrame->StyleSVGReset()->SingleFilter()) {
|
||||
if (aFrame->StyleSVGReset()->HasFilters()) {
|
||||
return false;
|
||||
}
|
||||
// XXX The SVG WG is intending to allow fill, stroke and markers on <image>
|
||||
|
@ -161,18 +161,18 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#define NS_ISVGFILTERPROPERTY_IID \
|
||||
#define NS_ISVGFILTERREFERENCE_IID \
|
||||
{ 0x9744ee20, 0x1bcf, 0x4c62, \
|
||||
{ 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } }
|
||||
|
||||
class nsISVGFilterProperty : public nsISupports
|
||||
class nsISVGFilterReference : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGFILTERPROPERTY_IID)
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGFILTERREFERENCE_IID)
|
||||
virtual void Invalidate() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilterProperty, NS_ISVGFILTERPROPERTY_IID)
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGFilterReference, NS_ISVGFILTERREFERENCE_IID)
|
||||
|
||||
/**
|
||||
* General functions used by all of SVG layout and possibly content code.
|
||||
|
Loading…
Reference in New Issue
Block a user