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 MOZILLA_SVGCONTEXT_H_
8 #define MOZILLA_SVGCONTEXT_H_
9 
10 #include "mozilla/Maybe.h"
11 #include "mozilla/SVGContextPaint.h"
12 #include "SVGPreserveAspectRatio.h"
13 #include "Units.h"
14 
15 class nsIFrame;
16 class nsStyleContext;
17 
18 namespace mozilla {
19 
20 // SVG image-specific rendering context. For imgIContainer::Draw.
21 // Used to pass information such as
22 //  - viewport information from CSS, and
23 //  - overridden attributes from an SVG <image> element
24 // to the image's internal SVG document when it's drawn.
25 class SVGImageContext {
26  public:
SVGImageContext()27   SVGImageContext() {}
28 
29   /**
30    * Currently it seems that the aViewportSize parameter ends up being used
31    * for different things by different pieces of code, and probably in some
32    * cases being used incorrectly (specifically in the case of pixel snapping
33    * under the nsLayoutUtils::Draw*Image() methods).  An unfortunate result of
34    * the messy code is that aViewportSize is currently a Maybe<T> since it
35    * is difficult to create a utility function that consumers can use up
36    * front to get the "correct" viewport size (i.e. which for compatibility
37    * with the current code (bugs and all) would mean the size including all
38    * the snapping and resizing magic that happens in various places under the
39    * nsLayoutUtils::Draw*Image() methods on the way to DrawImageInternal
40    * creating |fallbackContext|).  Using Maybe<T> allows code to pass Nothing()
41    * in order to get the size that's created for |fallbackContext|.  At some
42    * point we need to clean this code up, make our abstractions clear, create
43    * that utility and stop using Maybe for this parameter.
44    */
45   explicit SVGImageContext(
46       const Maybe<CSSIntSize>& aViewportSize,
47       const Maybe<SVGPreserveAspectRatio>& aPreserveAspectRatio = Nothing())
mViewportSize(aViewportSize)48       : mViewportSize(aViewportSize),
49         mPreserveAspectRatio(aPreserveAspectRatio) {}
50 
51   static void MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
52                                      nsIFrame* aFromFrame,
53                                      imgIContainer* aImgContainer);
54 
55   static void MaybeStoreContextPaint(Maybe<SVGImageContext>& aContext,
56                                      nsStyleContext* aFromStyleContext,
57                                      imgIContainer* aImgContainer);
58 
GetViewportSize()59   const Maybe<CSSIntSize>& GetViewportSize() const { return mViewportSize; }
60 
SetViewportSize(const Maybe<CSSIntSize> & aSize)61   void SetViewportSize(const Maybe<CSSIntSize>& aSize) {
62     mViewportSize = aSize;
63   }
64 
GetPreserveAspectRatio()65   const Maybe<SVGPreserveAspectRatio>& GetPreserveAspectRatio() const {
66     return mPreserveAspectRatio;
67   }
68 
SetPreserveAspectRatio(const Maybe<SVGPreserveAspectRatio> & aPAR)69   void SetPreserveAspectRatio(const Maybe<SVGPreserveAspectRatio>& aPAR) {
70     mPreserveAspectRatio = aPAR;
71   }
72 
GetContextPaint()73   const SVGEmbeddingContextPaint* GetContextPaint() const {
74     return mContextPaint.get();
75   }
76 
ClearContextPaint()77   void ClearContextPaint() { mContextPaint = nullptr; }
78 
79   bool operator==(const SVGImageContext& aOther) const {
80     bool contextPaintIsEqual =
81         // neither have context paint, or they have the same object:
82         (mContextPaint == aOther.mContextPaint) ||
83         // or both have context paint that are different but equivalent objects:
84         (mContextPaint && aOther.mContextPaint &&
85          *mContextPaint == *aOther.mContextPaint);
86 
87     return contextPaintIsEqual && mViewportSize == aOther.mViewportSize &&
88            mPreserveAspectRatio == aOther.mPreserveAspectRatio;
89   }
90 
91   bool operator!=(const SVGImageContext& aOther) const {
92     return !(*this == aOther);
93   }
94 
Hash()95   PLDHashNumber Hash() const {
96     PLDHashNumber hash = 0;
97     if (mContextPaint) {
98       hash = HashGeneric(hash, mContextPaint->Hash());
99     }
100     return HashGeneric(hash, mViewportSize.map(HashSize).valueOr(0),
101                        mPreserveAspectRatio.map(HashPAR).valueOr(0));
102   }
103 
104  private:
HashSize(const CSSIntSize & aSize)105   static PLDHashNumber HashSize(const CSSIntSize& aSize) {
106     return HashGeneric(aSize.width, aSize.height);
107   }
HashPAR(const SVGPreserveAspectRatio & aPAR)108   static PLDHashNumber HashPAR(const SVGPreserveAspectRatio& aPAR) {
109     return aPAR.Hash();
110   }
111 
112   // NOTE: When adding new member-vars, remember to update Hash() & operator==.
113   RefPtr<SVGEmbeddingContextPaint> mContextPaint;
114   Maybe<CSSIntSize> mViewportSize;
115   Maybe<SVGPreserveAspectRatio> mPreserveAspectRatio;
116 };
117 
118 }  // namespace mozilla
119 
120 #endif  // MOZILLA_SVGCONTEXT_H_
121