SVGFEImageFrame.cpp (4864B)
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 "mozilla/PresShell.h" 9 #include "mozilla/SVGObserverUtils.h" 10 #include "mozilla/dom/SVGFEImageElement.h" 11 #include "nsContainerFrame.h" 12 #include "nsGkAtoms.h" 13 #include "nsIFrame.h" 14 #include "nsLiteralString.h" 15 16 using namespace mozilla::dom; 17 18 nsIFrame* NS_NewSVGFEImageFrame(mozilla::PresShell* aPresShell, 19 mozilla::ComputedStyle* aStyle); 20 21 namespace mozilla { 22 23 class SVGFEImageFrame final : public nsIFrame { 24 friend nsIFrame* ::NS_NewSVGFEImageFrame(mozilla::PresShell* aPresShell, 25 ComputedStyle* aStyle); 26 27 protected: 28 explicit SVGFEImageFrame(ComputedStyle* aStyle, nsPresContext* aPresContext) 29 : nsIFrame(aStyle, aPresContext, kClassID) { 30 AddStateBits(NS_FRAME_SVG_LAYOUT | NS_FRAME_IS_NONDISPLAY); 31 32 // This frame isn't actually displayed, but it contains an image and we want 33 // to use the nsImageLoadingContent machinery for managing images, which 34 // requires visibility tracking, so we enable visibility tracking and 35 // forcibly mark it visible below. 36 EnableVisibilityTracking(); 37 } 38 39 public: 40 NS_DECL_FRAMEARENA_HELPERS(SVGFEImageFrame) 41 42 void Init(nsIContent* aContent, nsContainerFrame* aParent, 43 nsIFrame* aPrevInFlow) override; 44 void Destroy(DestroyContext&) override; 45 46 #ifdef DEBUG_FRAME_DUMP 47 nsresult GetFrameName(nsAString& aResult) const override { 48 return MakeFrameName(u"SVGFEImage"_ns, aResult); 49 } 50 #endif 51 52 nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute, 53 AttrModType aModType) override; 54 55 void OnVisibilityChange( 56 Visibility aNewVisibility, 57 const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override; 58 59 bool ComputeCustomOverflow(OverflowAreas& aOverflowAreas) override { 60 // We don't maintain a ink overflow rect 61 return false; 62 } 63 }; 64 65 } // namespace mozilla 66 67 nsIFrame* NS_NewSVGFEImageFrame(mozilla::PresShell* aPresShell, 68 mozilla::ComputedStyle* aStyle) { 69 return new (aPresShell) 70 mozilla::SVGFEImageFrame(aStyle, aPresShell->GetPresContext()); 71 } 72 73 namespace mozilla { 74 75 NS_IMPL_FRAMEARENA_HELPERS(SVGFEImageFrame) 76 77 /* virtual */ 78 void SVGFEImageFrame::Destroy(DestroyContext& aContext) { 79 DecApproximateVisibleCount(); 80 81 nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent); 82 if (imageLoader) { 83 imageLoader->FrameDestroyed(this); 84 } 85 86 nsIFrame::Destroy(aContext); 87 } 88 89 void SVGFEImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, 90 nsIFrame* aPrevInFlow) { 91 NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::feImage), 92 "Trying to construct an SVGFEImageFrame for a " 93 "content element that doesn't support the right interfaces"); 94 95 nsIFrame::Init(aContent, aParent, aPrevInFlow); 96 97 // We assume that feImage's are always visible. 98 // This call must happen before the FrameCreated. This is because the 99 // primary frame pointer on our content node isn't set until after this 100 // function ends, so there is no way for the resulting OnVisibilityChange 101 // notification to get a frame. FrameCreated has a workaround for this in 102 // that it passes our frame around so it can be accessed. OnVisibilityChange 103 // doesn't have that workaround. 104 IncApproximateVisibleCount(); 105 106 nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent); 107 if (imageLoader) { 108 imageLoader->FrameCreated(this); 109 } 110 } 111 112 nsresult SVGFEImageFrame::AttributeChanged(int32_t aNameSpaceID, 113 nsAtom* aAttribute, 114 AttrModType aModType) { 115 SVGFEImageElement* element = static_cast<SVGFEImageElement*>(GetContent()); 116 if (element->AttributeAffectsRendering(aNameSpaceID, aAttribute)) { 117 MOZ_ASSERT( 118 GetParent()->IsSVGFilterFrame(), 119 "Observers observe the filter, so that's what we must invalidate"); 120 SVGObserverUtils::InvalidateRenderingObservers(GetParent()); 121 } 122 123 return nsIFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType); 124 } 125 126 void SVGFEImageFrame::OnVisibilityChange( 127 Visibility aNewVisibility, const Maybe<OnNonvisible>& aNonvisibleAction) { 128 nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent); 129 if (imageLoader) { 130 imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction); 131 } 132 133 nsIFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction); 134 } 135 136 } // namespace mozilla