Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/svg/SVGObserverUtils.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef NSSVGEFFECTS_H_
8
#define NSSVGEFFECTS_H_
9
10
#include "mozilla/Attributes.h"
11
#include "mozilla/dom/IDTracker.h"
12
#include "FrameProperties.h"
13
#include "mozilla/dom/Element.h"
14
#include "nsHashKeys.h"
15
#include "nsID.h"
16
#include "nsIFrame.h"
17
#include "nsIMutationObserver.h"
18
#include "nsInterfaceHashtable.h"
19
#include "nsISupportsBase.h"
20
#include "nsISupportsImpl.h"
21
#include "nsStubMutationObserver.h"
22
#include "nsSVGUtils.h"
23
#include "nsTHashtable.h"
24
#include "nsURIHashKey.h"
25
#include "nsCycleCollectionParticipant.h"
26
27
class nsAtom;
28
class nsIPresShell;
29
class nsIURI;
30
class nsSVGClipPathFrame;
31
class nsSVGMarkerFrame;
32
class nsSVGPaintServerFrame;
33
class nsSVGFilterFrame;
34
class nsSVGMaskFrame;
35
namespace mozilla {
36
class SVGFilterObserverList;
37
namespace dom {
38
class SVGGeometryElement;
39
}
40
}
41
42
namespace mozilla {
43
44
/*
45
 * This class contains URL and referrer information (referrer and referrer
46
 * policy).
47
 * We use it to pass to svg system instead of nsIURI. The object brings referrer
48
 * and referrer policy so we can send correct Referer headers.
49
 */
50
class URLAndReferrerInfo
51
{
52
public:
53
  URLAndReferrerInfo(nsIURI* aURI, nsIURI* aReferrer,
54
                     mozilla::net::ReferrerPolicy aReferrerPolicy)
55
    : mURI(aURI)
56
    , mReferrer(aReferrer)
57
    , mReferrerPolicy(aReferrerPolicy)
58
0
 {
59
0
   MOZ_ASSERT(aURI);
60
0
 }
61
62
  NS_INLINE_DECL_REFCOUNTING(URLAndReferrerInfo)
63
64
0
  nsIURI* GetURI() { return mURI; }
65
0
  nsIURI* GetReferrer() { return mReferrer; }
66
0
  mozilla::net::ReferrerPolicy GetReferrerPolicy() { return mReferrerPolicy; }
67
68
private:
69
0
  ~URLAndReferrerInfo() = default;
70
71
  nsCOMPtr<nsIURI> mURI;
72
  nsCOMPtr<nsIURI> mReferrer;
73
  mozilla::net::ReferrerPolicy mReferrerPolicy;
74
};
75
76
/*
77
 * This interface allows us to be notified when a piece of SVG content is
78
 * re-rendered.
79
 *
80
 * Concrete implementations of this interface need to implement
81
 * "GetTarget()" to specify the piece of SVG content that they'd like to
82
 * monitor, and they need to implement "OnRenderingChange" to specify how
83
 * we'll react when that content gets re-rendered. They also need to implement
84
 * a constructor and destructor, which should call StartObserving and
85
 * StopObserving, respectively.
86
 */
87
class SVGRenderingObserver : public nsStubMutationObserver
88
{
89
90
protected:
91
0
  virtual ~SVGRenderingObserver() = default;
92
93
public:
94
  typedef mozilla::dom::Element Element;
95
96
  SVGRenderingObserver()
97
    : mInObserverList(false)
98
0
  {}
99
100
  // nsIMutationObserver
101
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
102
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
103
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
104
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
105
106
  /**
107
   * Called when non-DOM-mutation changes to the observed element should likely
108
   * cause the rendering of our observer to change.  This includes changes to
109
   * CSS computed values, but also changes to rendering observers that the
110
   * observed element itself may have (for example, when we're being used to
111
   * observe an SVG pattern, and an element in that pattern references and
112
   * observes a gradient that has changed).
113
   */
114
  void OnNonDOMMutationRenderingChange();
115
116
  // When a SVGRenderingObserver list gets forcibly cleared, it uses this
117
  // callback to notify every observer that's cleared from it, so they can
118
  // react.
119
  void NotifyEvictedFromRenderingObserverList();
120
121
0
  bool IsInObserverList() const { return mInObserverList; }
122
123
  nsIFrame* GetReferencedFrame();
124
  /**
125
   * @param aOK this is only for the convenience of callers. We set *aOK to false
126
   * if the frame is the wrong type
127
   */
128
  nsIFrame* GetReferencedFrame(mozilla::LayoutFrameType aFrameType, bool* aOK);
129
130
  Element* GetReferencedElement();
131
132
0
  virtual bool ObservesReflow() { return true; }
133
134
protected:
135
  void StartObserving();
136
  void StopObserving();
137
138
  /**
139
   * Called whenever the rendering of the observed element may have changed.
140
   *
141
   * More specifically, this method is called whenever DOM mutation occurs in
142
   * the observed element's subtree, or whenever
143
   * SVGObserverUtils::InvalidateRenderingObservers or
144
   * SVGObserverUtils::InvalidateDirectRenderingObservers is called for the
145
   * observed element's frame.
146
   *
147
   * Subclasses should override this method to handle rendering changes
148
   * appropriately.
149
   */
150
  virtual void OnRenderingChange() = 0;
151
152
  // This is an internally-used version of GetReferencedElement that doesn't
153
  // forcibly add us as an observer. (whereas GetReferencedElement does)
154
  virtual Element* GetTarget() = 0;
155
156
  // Whether we're in our referenced element's observer list at this time.
157
  bool mInObserverList;
158
};
159
160
161
/*
162
 * SVG elements reference supporting resources by element ID. We need to
163
 * track when those resources change and when the DOM changes in ways
164
 * that affect which element is referenced by a given ID (e.g., when
165
 * element IDs change). The code here is responsible for that.
166
 *
167
 * When a frame references a supporting resource, we create a property
168
 * object derived from SVGIDRenderingObserver to manage the relationship. The
169
 * property object is attached to the referencing frame.
170
 */
171
class SVGIDRenderingObserver : public SVGRenderingObserver
172
{
173
public:
174
  typedef mozilla::dom::Element Element;
175
  typedef mozilla::dom::IDTracker IDTracker;
176
177
  SVGIDRenderingObserver(URLAndReferrerInfo* aURI, nsIContent* aObservingContent,
178
                         bool aReferenceImage);
179
  virtual ~SVGIDRenderingObserver();
180
181
protected:
182
0
  Element* GetTarget() override { return mObservedElementTracker.get(); }
183
184
  void OnRenderingChange() override;
185
186
  /**
187
   * Helper that provides a reference to the element with the ID that our
188
   * observer wants to observe, and that will invalidate our observer if the
189
   * element that that ID identifies changes to a different element (or none).
190
   */
191
  class ElementTracker final : public IDTracker
192
  {
193
  public:
194
    explicit ElementTracker(SVGIDRenderingObserver* aOwningObserver)
195
      : mOwningObserver(aOwningObserver)
196
0
    {}
197
  protected:
198
0
    virtual void ElementChanged(Element* aFrom, Element* aTo) override {
199
0
      mOwningObserver->StopObserving(); // stop observing the old element
200
0
      IDTracker::ElementChanged(aFrom, aTo);
201
0
      mOwningObserver->StartObserving(); // start observing the new element
202
0
      mOwningObserver->OnRenderingChange();
203
0
    }
204
    /**
205
     * Override IsPersistent because we want to keep tracking the element
206
     * for the ID even when it changes.
207
     */
208
0
    virtual bool IsPersistent() override { return true; }
209
  private:
210
    SVGIDRenderingObserver* mOwningObserver;
211
  };
212
213
  ElementTracker mObservedElementTracker;
214
};
215
216
struct nsSVGFrameReferenceFromProperty
217
{
218
  explicit nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
219
    : mFrame(aFrame)
220
    , mFramePresShell(aFrame->PresShell())
221
0
  {}
222
223
  // Clear our reference to the frame.
224
  void Detach();
225
226
  // null if the frame has become invalid
227
  nsIFrame* Get();
228
229
private:
230
  // The frame that this property is attached to, may be null
231
  nsIFrame *mFrame;
232
  // When a presshell is torn down, we don't delete the properties for
233
  // each frame until after the frames are destroyed. So here we remember
234
  // the presshell for the frames we care about and, before we use the frame,
235
  // we test the presshell to see if it's destroying itself. If it is,
236
  // then the frame pointer is not valid and we know the frame has gone away.
237
  // mFramePresShell may be null, but when mFrame is non-null, mFramePresShell
238
  // is guaranteed to be non-null, too.
239
  nsIPresShell *mFramePresShell;
240
};
241
242
/**
243
 * Used for gradient-to-gradient, pattern-to-pattern and filter-to-filter
244
 * references to "template" elements (specified via the 'href' attributes).
245
 *
246
 * This is a special class for the case where we know we only want to call
247
 * InvalidateDirectRenderingObservers (as opposed to
248
 * InvalidateRenderingObservers).
249
 *
250
 * TODO(jwatt): If we added a new NS_FRAME_RENDERING_OBSERVER_CONTAINER state
251
 * bit to clipPath, filter, gradients, marker, mask, pattern and symbol, and
252
 * could have InvalidateRenderingObservers stop on reaching such an element,
253
 * then we would no longer need this class (not to mention improving perf by
254
 * significantly cutting down on ancestor traversal).
255
 */
256
class SVGTemplateElementObserver : public SVGIDRenderingObserver
257
{
258
public:
259
  NS_DECL_ISUPPORTS
260
261
  SVGTemplateElementObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame,
262
                             bool aReferenceImage)
263
    : SVGIDRenderingObserver(aURI, aFrame->GetContent(), aReferenceImage)
264
    , mFrameReference(aFrame)
265
0
  {}
266
267
protected:
268
  virtual ~SVGTemplateElementObserver() = default; // non-public
269
270
  virtual void OnRenderingChange() override;
271
272
  nsSVGFrameReferenceFromProperty mFrameReference;
273
};
274
275
class nsSVGRenderingObserverProperty : public SVGIDRenderingObserver
276
{
277
public:
278
  NS_DECL_ISUPPORTS
279
280
  nsSVGRenderingObserverProperty(URLAndReferrerInfo* aURI, nsIFrame *aFrame,
281
                                 bool aReferenceImage)
282
    : SVGIDRenderingObserver(aURI, aFrame->GetContent(), aReferenceImage)
283
    , mFrameReference(aFrame)
284
0
  {}
285
286
protected:
287
0
  virtual ~nsSVGRenderingObserverProperty() {}
288
289
  virtual void OnRenderingChange() override;
290
291
  nsSVGFrameReferenceFromProperty mFrameReference;
292
};
293
294
#define NS_SVGFILTEROBSERVER_IID \
295
{ 0x9744ee20, 0x1bcf, 0x4c62, \
296
 { 0x86, 0x7d, 0xd3, 0x7a, 0x91, 0x60, 0x3e, 0xef } }
297
298
/**
299
 * In a filter chain, there can be multiple SVG reference filters.
300
 * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
301
 *
302
 * This class keeps track of one SVG reference filter in a filter chain.
303
 * e.g. url(#svg-filter-1)
304
 *
305
 * It fires invalidations when the SVG filter element's id changes or when
306
 * the SVG filter element's content changes.
307
 *
308
 * The SVGFilterObserverList class manages a list of SVGFilterObservers.
309
 */
310
class SVGFilterObserver final : public SVGIDRenderingObserver
311
{
312
public:
313
  SVGFilterObserver(URLAndReferrerInfo* aURI,
314
                    nsIContent* aObservingContent,
315
                    SVGFilterObserverList* aFilterChainObserver)
316
    : SVGIDRenderingObserver(aURI, aObservingContent, false)
317
    , mFilterObserverList(aFilterChainObserver)
318
0
  {
319
0
  }
320
321
0
  bool ReferencesValidResource() { return GetFilterFrame(); }
322
323
0
  void DetachFromChainObserver() { mFilterObserverList = nullptr; }
324
325
  /**
326
   * @return the filter frame, or null if there is no filter frame
327
   */
328
  nsSVGFilterFrame *GetFilterFrame();
329
330
  // nsISupports
331
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVGFILTEROBSERVER_IID)
332
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
333
  NS_DECL_CYCLE_COLLECTION_CLASS(SVGFilterObserver)
334
335
0
  void Invalidate() { OnRenderingChange(); };
336
337
protected:
338
0
  virtual ~SVGFilterObserver() {}
339
340
  // SVGIDRenderingObserver
341
  virtual void OnRenderingChange() override;
342
343
private:
344
  SVGFilterObserverList* mFilterObserverList;
345
};
346
347
NS_DEFINE_STATIC_IID_ACCESSOR(SVGFilterObserver, NS_SVGFILTEROBSERVER_IID)
348
349
/**
350
 * This class manages a list of SVGFilterObservers, which correspond to
351
 * reference to SVG filters in a list of filters in a given 'filter' property.
352
 * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
353
 *
354
 * In the above example, the SVGFilterObserverList will manage two
355
 * SVGFilterObservers, one for each of the references to SVG filters.  CSS
356
 * filters like "blur(10px)" don't reference filter elements, so they don't
357
 * need an SVGFilterObserver.  The style system invalidates changes to CSS
358
 * filters.
359
 */
360
class SVGFilterObserverList : public nsISupports
361
{
362
public:
363
  SVGFilterObserverList(const nsTArray<nsStyleFilter>& aFilters,
364
                        nsIContent* aFilteredElement,
365
                        nsIFrame* aFiltedFrame = nullptr);
366
367
  bool ReferencesValidResources();
368
  bool IsInObserverLists() const;
369
0
  void Invalidate() { OnRenderingChange(); }
370
371
  // nsISupports
372
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
373
  NS_DECL_CYCLE_COLLECTION_CLASS(SVGFilterObserverList)
374
375
protected:
376
  virtual ~SVGFilterObserverList();
377
378
  virtual void OnRenderingChange() = 0;
379
380
private:
381
382
  void DetachObservers()
383
0
  {
384
0
    for (uint32_t i = 0; i < mObservers.Length(); i++) {
385
0
      mObservers[i]->DetachFromChainObserver();
386
0
    }
387
0
  }
388
389
  nsTArray<RefPtr<SVGFilterObserver>> mObservers;
390
};
391
392
class SVGFilterObserverListForCSSProp final : public SVGFilterObserverList
393
{
394
public:
395
  SVGFilterObserverListForCSSProp(const nsTArray<nsStyleFilter>& aFilters,
396
                                  nsIFrame* aFilteredFrame)
397
    : SVGFilterObserverList(aFilters, aFilteredFrame->GetContent(),
398
                            aFilteredFrame)
399
    , mFrameReference(aFilteredFrame)
400
0
  {}
401
402
0
  void DetachFromFrame() { mFrameReference.Detach(); }
403
404
protected:
405
  virtual void OnRenderingChange() override;
406
407
  nsSVGFrameReferenceFromProperty mFrameReference;
408
};
409
410
class SVGMarkerObserver final: public nsSVGRenderingObserverProperty
411
{
412
public:
413
  SVGMarkerObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage)
414
0
    : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage) {}
415
416
protected:
417
  virtual void OnRenderingChange() override;
418
};
419
420
class SVGTextPathObserver final : public nsSVGRenderingObserverProperty
421
{
422
public:
423
  SVGTextPathObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage)
424
    : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage)
425
0
    , mValid(true) {}
426
427
0
  virtual bool ObservesReflow() override { return false; }
428
429
protected:
430
  virtual void OnRenderingChange() override;
431
432
private:
433
  /**
434
   * Returns true if the target of the textPath is the frame of a 'path' element.
435
   */
436
  bool TargetIsValid();
437
438
  bool mValid;
439
};
440
441
class nsSVGPaintingProperty final : public nsSVGRenderingObserverProperty
442
{
443
public:
444
  nsSVGPaintingProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame, bool aReferenceImage)
445
0
    : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage) {}
446
447
protected:
448
  virtual void OnRenderingChange() override;
449
};
450
451
class SVGMaskObserverList final : public nsISupports
452
{
453
public:
454
  explicit SVGMaskObserverList(nsIFrame* aFrame);
455
456
  // nsISupports
457
  NS_DECL_ISUPPORTS
458
459
  const nsTArray<RefPtr<nsSVGPaintingProperty>>& GetObservers() const
460
0
  {
461
0
    return mProperties;
462
0
  }
463
464
  void ResolveImage(uint32_t aIndex);
465
466
private:
467
0
  virtual ~SVGMaskObserverList() {}
468
  nsTArray<RefPtr<nsSVGPaintingProperty>> mProperties;
469
  nsIFrame* mFrame;
470
};
471
472
/**
473
 * A manager for one-shot SVGRenderingObserver tracking.
474
 * nsSVGRenderingObservers can be added or removed. They are not strongly
475
 * referenced so an observer must be removed before it dies.
476
 * When InvalidateAll is called, all outstanding references get
477
 * OnNonDOMMutationRenderingChange()
478
 * called on them and the list is cleared. The intent is that
479
 * the observer will force repainting of whatever part of the document
480
 * is needed, and then at paint time the observer will do a clean lookup
481
 * of the referenced element and [re-]add itself to the element's observer list.
482
 *
483
 * InvalidateAll must be called before this object is destroyed, i.e.
484
 * before the referenced frame is destroyed. This should normally happen
485
 * via nsSVGContainerFrame::RemoveFrame, since only frames in the frame
486
 * tree should be referenced.
487
 */
488
class SVGRenderingObserverList
489
{
490
public:
491
  SVGRenderingObserverList()
492
    : mObservers(4)
493
0
  {
494
0
    MOZ_COUNT_CTOR(SVGRenderingObserverList);
495
0
  }
496
497
0
  ~SVGRenderingObserverList() {
498
0
    InvalidateAll();
499
0
    MOZ_COUNT_DTOR(SVGRenderingObserverList);
500
0
  }
501
502
  void Add(SVGRenderingObserver* aObserver)
503
0
  { mObservers.PutEntry(aObserver); }
504
  void Remove(SVGRenderingObserver* aObserver)
505
0
  { mObservers.RemoveEntry(aObserver); }
506
#ifdef DEBUG
507
  bool Contains(SVGRenderingObserver* aObserver)
508
  { return (mObservers.GetEntry(aObserver) != nullptr); }
509
#endif
510
  bool IsEmpty()
511
0
  { return mObservers.Count() == 0; }
512
513
  /**
514
   * Drop all our observers, and notify them that we have changed and dropped
515
   * our reference to them.
516
   */
517
  void InvalidateAll();
518
519
  /**
520
   * Drop all observers that observe reflow, and notify them that we have changed and dropped
521
   * our reference to them.
522
   */
523
  void InvalidateAllForReflow();
524
525
  /**
526
   * Drop all our observers, and notify them that we have dropped our reference
527
   * to them.
528
   */
529
  void RemoveAll();
530
531
private:
532
  nsTHashtable<nsPtrHashKey<SVGRenderingObserver>> mObservers;
533
};
534
535
class SVGObserverUtils
536
{
537
public:
538
  typedef mozilla::dom::Element Element;
539
  typedef dom::SVGGeometryElement SVGGeometryElement;
540
  typedef nsInterfaceHashtable<nsRefPtrHashKey<URLAndReferrerInfo>,
541
    nsIMutationObserver> URIObserverHashtable;
542
543
  using PaintingPropertyDescriptor =
544
    const mozilla::FramePropertyDescriptor<nsSVGPaintingProperty>*;
545
  using URIObserverHashtablePropertyDescriptor =
546
    const mozilla::FramePropertyDescriptor<URIObserverHashtable>*;
547
548
  static void DestroyFilterProperty(SVGFilterObserverListForCSSProp* aProp)
549
0
  {
550
0
    // SVGFilterObserverListForCSSProp is cycle-collected, so dropping the last
551
0
    // reference doesn't necessarily destroy it. We need to tell it that the
552
0
    // frame has now become invalid.
553
0
    aProp->DetachFromFrame();
554
0
555
0
    aProp->Release();
556
0
  }
557
558
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(HrefToTemplateProperty,
559
                                       SVGTemplateElementObserver)
560
  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(FilterProperty,
561
                                      SVGFilterObserverListForCSSProp,
562
                                      DestroyFilterProperty)
563
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MaskProperty, SVGMaskObserverList)
564
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(ClipPathProperty, nsSVGPaintingProperty)
565
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerStartProperty, SVGMarkerObserver)
566
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerMidProperty, SVGMarkerObserver)
567
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerEndProperty, SVGMarkerObserver)
568
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(FillProperty, nsSVGPaintingProperty)
569
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(StrokeProperty, nsSVGPaintingProperty)
570
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(HrefAsTextPathProperty,
571
                                       SVGTextPathObserver)
572
  NS_DECLARE_FRAME_PROPERTY_DELETABLE(BackgroundImageProperty,
573
                                      URIObserverHashtable)
574
575
  struct EffectProperties {
576
    SVGFilterObserverListForCSSProp* mFilterObservers;
577
    SVGMaskObserverList* mMaskObservers;
578
    nsSVGPaintingProperty* mClipPath;
579
580
    /**
581
     * @return the clip-path frame, or null if there is no clip-path frame
582
     */
583
    nsSVGClipPathFrame* GetClipPathFrame();
584
585
    /**
586
     * @return an array which contains all SVG mask frames.
587
     */
588
    nsTArray<nsSVGMaskFrame*> GetMaskFrames();
589
590
    /*
591
     * @return true if all effects we have are valid or we have no effect
592
     * at all.
593
     */
594
    bool HasNoOrValidEffects();
595
596
    /*
597
     * @return true if we have any invalid effect.
598
     */
599
0
    bool HasInvalidEffects() {
600
0
      return !HasNoOrValidEffects();
601
0
    }
602
603
    /*
604
     * @return true if we either do not have clip-path or have a valid
605
     * clip-path.
606
     */
607
    bool HasNoOrValidClipPath();
608
609
    /*
610
     * @return true if we have an invalid clip-path.
611
     */
612
0
    bool HasInvalidClipPath() {
613
0
      return !HasNoOrValidClipPath();
614
0
    }
615
616
    /*
617
     * @return true if we either do not have mask or all masks we have
618
     * are valid.
619
     */
620
    bool HasNoOrValidMask();
621
622
    /*
623
     * @return true if we have an invalid mask.
624
     */
625
0
    bool HasInvalidMask() {
626
0
      return !HasNoOrValidMask();
627
0
    }
628
629
0
    bool HasValidFilter() {
630
0
      return mFilterObservers && mFilterObservers->ReferencesValidResources();
631
0
    }
632
633
    /*
634
     * @return true if we either do not have filter or all filters we have
635
     * are valid.
636
     */
637
0
    bool HasNoOrValidFilter() {
638
0
      return !mFilterObservers || mFilterObservers->ReferencesValidResources();
639
0
    }
640
641
    /*
642
     * @return true if we have an invalid filter.
643
     */
644
0
    bool HasInvalidFilter() {
645
0
      return !HasNoOrValidFilter();
646
0
    }
647
  };
648
649
  /**
650
   * @param aFrame should be the first continuation
651
   */
652
  static EffectProperties GetEffectProperties(nsIFrame* aFrame);
653
654
  /**
655
   * Called when changes to an element (e.g. CSS property changes) cause its
656
   * frame to start/stop referencing (or reference different) SVG resource
657
   * elements. (_Not_ called for changes to referenced resource elements.)
658
   *
659
   * This function handles such changes by discarding _all_ the frame's SVG
660
   * effects frame properties (causing those properties to stop watching their
661
   * target element). It also synchronously (re)creates the filter and marker
662
   * frame properties (XXX why not the other properties?), which makes it
663
   * useful for initializing those properties during first reflow.
664
   *
665
   * XXX rename to something more meaningful like RefreshResourceReferences?
666
   */
667
  static void UpdateEffects(nsIFrame* aFrame);
668
669
  /**
670
   * @param aFrame should be the first continuation
671
   */
672
  static SVGFilterObserverListForCSSProp* GetFilterObserverList(nsIFrame* aFrame);
673
674
  /**
675
   * @param aFrame must be a first-continuation.
676
   */
677
  static void AddRenderingObserver(Element* aElement,
678
                                   SVGRenderingObserver *aObserver);
679
  /**
680
   * @param aFrame must be a first-continuation.
681
   */
682
  static void RemoveRenderingObserver(Element* aElement,
683
                                      SVGRenderingObserver *aObserver);
684
685
  /**
686
   * Removes all rendering observers from aElement.
687
   */
688
  static void RemoveAllRenderingObservers(Element* aElement);
689
690
  /**
691
   * This can be called on any frame. We invalidate the observers of aFrame's
692
   * element, if any, or else walk up to the nearest observable SVG parent
693
   * frame with observers and invalidate them instead.
694
   *
695
   * Note that this method is very different to e.g.
696
   * nsNodeUtils::AttributeChanged which walks up the content node tree all the
697
   * way to the root node (not stopping if it encounters a non-container SVG
698
   * node) invalidating all mutation observers (not just
699
   * nsSVGRenderingObservers) on all nodes along the way (not just the first
700
   * node it finds with observers). In other words, by doing all the
701
   * things in parentheses in the preceding sentence, this method uses
702
   * knowledge about our implementation and what can be affected by SVG effects
703
   * to make invalidation relatively lightweight when an SVG effect changes.
704
   */
705
  static void InvalidateRenderingObservers(nsIFrame* aFrame);
706
707
  enum {
708
    INVALIDATE_REFLOW = 1
709
  };
710
711
  /**
712
   * This can be called on any element or frame. Only direct observers of this
713
   * (frame's) element, if any, are invalidated.
714
   */
715
  static void InvalidateDirectRenderingObservers(Element* aElement, uint32_t aFlags = 0);
716
  static void InvalidateDirectRenderingObservers(nsIFrame* aFrame, uint32_t aFlags = 0);
717
718
  /**
719
   * Get the paint server for a aTargetFrame.
720
   */
721
  static nsSVGPaintServerFrame *GetPaintServer(nsIFrame* aTargetFrame,
722
                                               nsStyleSVGPaint nsStyleSVG::* aPaint);
723
724
  /**
725
   * Get the start/mid/end-markers for the given frame, and add the frame as
726
   * an observer to those markers.  Returns true if at least one marker type is
727
   * found, false otherwise.
728
   */
729
  static bool
730
  GetMarkerFrames(nsIFrame* aMarkedFrame, nsSVGMarkerFrame*(*aFrames)[3]);
731
732
  /**
733
   * Get the SVGGeometryElement that is referenced by aTextPathFrame, and make
734
   * aTextPathFrame start observing rendering changes to that element.
735
   */
736
  static SVGGeometryElement*
737
  GetTextPathsReferencedPath(nsIFrame* aTextPathFrame);
738
739
  /**
740
   * Make aTextPathFrame stop observing rendering changes to the
741
   * SVGGeometryElement that it references, if any.
742
   */
743
  static void
744
  RemoveTextPathObserver(nsIFrame* aTextPathFrame);
745
746
  static SVGTemplateElementObserver*
747
  GetTemplateElementObserver(URLAndReferrerInfo* aURI, nsIFrame* aFrame,
748
      const mozilla::FramePropertyDescriptor<SVGTemplateElementObserver>* aProperty);
749
750
  /**
751
   * Get an nsSVGPaintingProperty for the frame, creating a fresh one if necessary
752
   */
753
  static nsSVGPaintingProperty*
754
  GetPaintingProperty(URLAndReferrerInfo* aURI, nsIFrame* aFrame,
755
      const mozilla::FramePropertyDescriptor<nsSVGPaintingProperty>* aProperty);
756
  /**
757
   * Get an nsSVGPaintingProperty for the frame for that URI, creating a fresh
758
   * one if necessary
759
   */
760
  static nsSVGPaintingProperty*
761
  GetPaintingPropertyForURI(URLAndReferrerInfo* aURI,
762
                            nsIFrame* aFrame,
763
                            URIObserverHashtablePropertyDescriptor aProp);
764
765
  /**
766
   * A helper function to resolve marker's URL.
767
   */
768
  static already_AddRefed<URLAndReferrerInfo>
769
  GetMarkerURI(nsIFrame* aFrame,
770
               RefPtr<mozilla::css::URLValue> nsStyleSVG::* aMarker);
771
772
  /**
773
   * A helper function to resolve clip-path URL.
774
   */
775
  static already_AddRefed<URLAndReferrerInfo>
776
  GetClipPathURI(nsIFrame* aFrame);
777
778
  /**
779
   * A helper function to resolve filter URL.
780
   */
781
  static already_AddRefed<URLAndReferrerInfo>
782
  GetFilterURI(nsIFrame* aFrame, uint32_t aIndex);
783
784
  /**
785
   * A helper function to resolve filter URL.
786
   */
787
  static already_AddRefed<URLAndReferrerInfo>
788
  GetFilterURI(nsIFrame* aFrame, const nsStyleFilter& aFilter);
789
790
  /**
791
   * A helper function to resolve paint-server URL.
792
   */
793
  static already_AddRefed<URLAndReferrerInfo>
794
  GetPaintURI(nsIFrame* aFrame, nsStyleSVGPaint nsStyleSVG::* aPaint);
795
796
  /**
797
   * A helper function to resolve SVG mask URL.
798
   */
799
  static already_AddRefed<URLAndReferrerInfo>
800
  GetMaskURI(nsIFrame* aFrame, uint32_t aIndex);
801
802
  /**
803
   * Return a baseURL for resolving a local-ref URL.
804
   *
805
   * @param aContent an element which uses a local-ref property. Here are some
806
   *                 examples:
807
   *                   <rect fill=url(#foo)>
808
   *                   <circle clip-path=url(#foo)>
809
   *                   <use xlink:href="#foo">
810
   */
811
  static already_AddRefed<nsIURI>
812
  GetBaseURLForLocalRef(nsIContent* aContent, nsIURI* aDocURI);
813
};
814
815
} // namespace mozilla
816
817
#endif /*NSSVGEFFECTS_H_*/