Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/svg/SVGFEImageFrame.cpp
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
// Keep in (case-insensitive) order:
8
#include "nsContainerFrame.h"
9
#include "nsFrame.h"
10
#include "nsGkAtoms.h"
11
#include "nsLiteralString.h"
12
#include "SVGObserverUtils.h"
13
#include "nsSVGFilters.h"
14
#include "mozilla/dom/SVGFEImageElement.h"
15
#include "mozilla/dom/MutationEventBinding.h"
16
17
using namespace mozilla;
18
using namespace mozilla::dom;
19
20
class SVGFEImageFrame final : public nsFrame
21
{
22
  friend nsIFrame*
23
  NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle);
24
protected:
25
  explicit SVGFEImageFrame(ComputedStyle* aStyle)
26
    : nsFrame(aStyle, kClassID)
27
0
  {
28
0
    AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY);
29
0
30
0
    // This frame isn't actually displayed, but it contains an image and we want
31
0
    // to use the nsImageLoadingContent machinery for managing images, which
32
0
    // requires visibility tracking, so we enable visibility tracking and
33
0
    // forcibly mark it visible below.
34
0
    EnableVisibilityTracking();
35
0
  }
36
37
public:
38
  NS_DECL_FRAMEARENA_HELPERS(SVGFEImageFrame)
39
40
  virtual void Init(nsIContent*       aContent,
41
                    nsContainerFrame* aParent,
42
                    nsIFrame*         aPrevInFlow) override;
43
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
44
45
  virtual bool IsFrameOfType(uint32_t aFlags) const override
46
0
  {
47
0
    if (aFlags & eSupportsContainLayoutAndPaint) {
48
0
      return false;
49
0
    }
50
0
51
0
    return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
52
0
  }
53
54
#ifdef DEBUG_FRAME_DUMP
55
  virtual nsresult GetFrameName(nsAString& aResult) const override
56
  {
57
    return MakeFrameName(NS_LITERAL_STRING("SVGFEImage"), aResult);
58
  }
59
#endif
60
61
  virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
62
                                    nsAtom* aAttribute,
63
                                    int32_t  aModType) override;
64
65
  void OnVisibilityChange(Visibility aNewVisibility,
66
                          const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
67
68
0
  virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
69
0
    // We don't maintain a visual overflow rect
70
0
    return false;
71
0
  }
72
};
73
74
nsIFrame*
75
NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
76
0
{
77
0
  return new (aPresShell) SVGFEImageFrame(aStyle);
78
0
}
79
80
NS_IMPL_FRAMEARENA_HELPERS(SVGFEImageFrame)
81
82
/* virtual */ void
83
SVGFEImageFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
84
0
{
85
0
  DecApproximateVisibleCount();
86
0
87
0
  nsCOMPtr<nsIImageLoadingContent> imageLoader =
88
0
    do_QueryInterface(nsFrame::mContent);
89
0
  if (imageLoader) {
90
0
    imageLoader->FrameDestroyed(this);
91
0
  }
92
0
93
0
  nsFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
94
0
}
95
96
void
97
SVGFEImageFrame::Init(nsIContent*       aContent,
98
                      nsContainerFrame* aParent,
99
                      nsIFrame*         aPrevInFlow)
100
0
{
101
0
  NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::feImage),
102
0
               "Trying to construct an SVGFEImageFrame for a "
103
0
               "content element that doesn't support the right interfaces");
104
0
105
0
  nsFrame::Init(aContent, aParent, aPrevInFlow);
106
0
107
0
  // We assume that feImage's are always visible.
108
0
  // This call must happen before the FrameCreated. This is because the
109
0
  // primary frame pointer on our content node isn't set until after this
110
0
  // function ends, so there is no way for the resulting OnVisibilityChange
111
0
  // notification to get a frame. FrameCreated has a workaround for this in
112
0
  // that it passes our frame around so it can be accessed. OnVisibilityChange
113
0
  // doesn't have that workaround.
114
0
  IncApproximateVisibleCount();
115
0
116
0
  nsCOMPtr<nsIImageLoadingContent> imageLoader =
117
0
    do_QueryInterface(nsFrame::mContent);
118
0
  if (imageLoader) {
119
0
    imageLoader->FrameCreated(this);
120
0
  }
121
0
}
122
123
nsresult
124
SVGFEImageFrame::AttributeChanged(int32_t  aNameSpaceID,
125
                                  nsAtom* aAttribute,
126
                                  int32_t  aModType)
127
0
{
128
0
  SVGFEImageElement* element = static_cast<SVGFEImageElement*>(GetContent());
129
0
  if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) {
130
0
    MOZ_ASSERT(GetParent()->IsSVGFilterFrame(),
131
0
               "Observers observe the filter, so that's what we must invalidate");
132
0
    SVGObserverUtils::InvalidateDirectRenderingObservers(GetParent());
133
0
  }
134
0
135
0
  // Currently our SMIL implementation does not modify the DOM attributes. Once
136
0
  // we implement the SVG 2 SMIL behaviour this can be removed
137
0
  // SVGFEImageElement::AfterSetAttr's implementation will be sufficient.
138
0
  if (aModType == MutationEvent_Binding::SMIL &&
139
0
      aAttribute == nsGkAtoms::href &&
140
0
      (aNameSpaceID == kNameSpaceID_XLink ||
141
0
       aNameSpaceID == kNameSpaceID_None)) {
142
0
    bool hrefIsSet =
143
0
      element->mStringAttributes[SVGFEImageElement::HREF].IsExplicitlySet() ||
144
0
      element->mStringAttributes[SVGFEImageElement::XLINK_HREF]
145
0
        .IsExplicitlySet();
146
0
    if (hrefIsSet) {
147
0
      element->LoadSVGImage(true, true);
148
0
    } else {
149
0
      element->CancelImageRequests(true);
150
0
    }
151
0
  }
152
0
153
0
  return nsFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
154
0
}
155
156
void
157
SVGFEImageFrame::OnVisibilityChange(Visibility aNewVisibility,
158
                                    const Maybe<OnNonvisible>& aNonvisibleAction)
159
0
{
160
0
  nsCOMPtr<nsIImageLoadingContent> imageLoader =
161
0
    do_QueryInterface(nsFrame::mContent);
162
0
  if (!imageLoader) {
163
0
    MOZ_ASSERT_UNREACHABLE("Should have an nsIImageLoadingContent");
164
0
    nsFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
165
0
    return;
166
0
  }
167
0
168
0
  imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
169
0
170
0
  nsFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
171
0
}