Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MASKLAYERIMAGECACHE_H_
7 #define MASKLAYERIMAGECACHE_H_
9 #include "DisplayItemClip.h"
10 #include "nsPresContext.h"
11 #include "mozilla/gfx/Matrix.h"
13 namespace mozilla {
15 namespace layers {
16 class ImageContainer;
17 }
19 /**
20 * Keeps a record of image containers for mask layers, containers are mapped
21 * from the rounded rects used to create them.
22 * The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys.
23 * Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey
24 * (heap-allocated so that a mask layer's userdata can keep a pointer to the
25 * key for its image, in spite of the hashtable moving its entries around).
26 * The key consists of the rounded rects used to create the mask,
27 * an nsRefPtr to the ImageContainer containing the image, and a count
28 * of the number of layers currently using this ImageContainer.
29 * When the key's layer count is zero, the cache
30 * may remove the entry, which deletes the key object.
31 */
32 class MaskLayerImageCache
33 {
34 typedef mozilla::layers::ImageContainer ImageContainer;
35 public:
36 MaskLayerImageCache();
37 ~MaskLayerImageCache();
39 /**
40 * Representation of a rounded rectangle in device pixel coordinates, in
41 * contrast to DisplayItemClip::RoundedRect, which uses app units.
42 * In particular, our internal representation uses a gfxRect, rather than
43 * an nsRect, so this class is easier to use with transforms.
44 */
45 struct PixelRoundedRect
46 {
47 PixelRoundedRect(const DisplayItemClip::RoundedRect& aRRect,
48 nsPresContext* aPresContext)
49 : mRect(aPresContext->AppUnitsToGfxUnits(aRRect.mRect.x),
50 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.y),
51 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.width),
52 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.height))
53 {
54 MOZ_COUNT_CTOR(PixelRoundedRect);
55 NS_FOR_CSS_HALF_CORNERS(corner) {
56 mRadii[corner] = aPresContext->AppUnitsToGfxUnits(aRRect.mRadii[corner]);
57 }
58 }
59 PixelRoundedRect(const PixelRoundedRect& aPRR)
60 : mRect(aPRR.mRect)
61 {
62 MOZ_COUNT_CTOR(PixelRoundedRect);
63 NS_FOR_CSS_HALF_CORNERS(corner) {
64 mRadii[corner] = aPRR.mRadii[corner];
65 }
66 }
68 ~PixelRoundedRect()
69 {
70 MOZ_COUNT_DTOR(PixelRoundedRect);
71 }
73 // Applies the scale and translate components of aTransform.
74 // It is an error to pass a matrix which does more than just scale
75 // and translate.
76 void ScaleAndTranslate(const gfx::Matrix& aTransform)
77 {
78 NS_ASSERTION(aTransform._12 == 0 && aTransform._21 == 0,
79 "Transform has a component other than scale and translate");
81 mRect = aTransform.TransformBounds(mRect);
83 for (size_t i = 0; i < ArrayLength(mRadii); i += 2) {
84 mRadii[i] *= aTransform._11;
85 mRadii[i + 1] *= aTransform._22;
86 }
87 }
89 bool operator==(const PixelRoundedRect& aOther) const {
90 if (!mRect.IsEqualInterior(aOther.mRect)) {
91 return false;
92 }
94 NS_FOR_CSS_HALF_CORNERS(corner) {
95 if (mRadii[corner] != aOther.mRadii[corner]) {
96 return false;
97 }
98 }
99 return true;
100 }
101 bool operator!=(const PixelRoundedRect& aOther) const {
102 return !(*this == aOther);
103 }
105 // Create a hash for this object.
106 PLDHashNumber Hash() const
107 {
108 PLDHashNumber hash = HashBytes(&mRect.x, 4*sizeof(gfxFloat));
109 hash = AddToHash(hash, HashBytes(mRadii, 8*sizeof(gfxFloat)));
111 return hash;
112 }
114 gfx::Rect mRect;
115 // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
116 gfxFloat mRadii[8];
118 private:
119 PixelRoundedRect() MOZ_DELETE;
120 };
122 /**
123 * A key to identify cached image containers.
124 * The const-ness of this class is with respect to its use as a key into a
125 * hashtable, so anything not used to create the hash is mutable.
126 * mLayerCount counts the number of mask layers which have a reference to
127 * MaskLayerImageEntry::mContainer; it is maintained by MaskLayerUserData,
128 * which keeps a reference to the key. There will usually be mLayerCount + 1
129 * pointers to a key object (the +1 being from the hashtable entry), but this
130 * invariant may be temporarily broken.
131 */
132 struct MaskLayerImageKey
133 {
134 MaskLayerImageKey()
135 : mLayerCount(0)
136 , mRoundedClipRects()
137 {
138 MOZ_COUNT_CTOR(MaskLayerImageKey);
139 }
140 MaskLayerImageKey(const MaskLayerImageKey& aKey)
141 : mLayerCount(aKey.mLayerCount)
142 , mRoundedClipRects(aKey.mRoundedClipRects)
143 {
144 MOZ_COUNT_CTOR(MaskLayerImageKey);
145 }
147 ~MaskLayerImageKey()
148 {
149 MOZ_COUNT_DTOR(MaskLayerImageKey);
150 }
152 void AddRef() const { ++mLayerCount; }
153 void Release() const
154 {
155 NS_ASSERTION(mLayerCount > 0, "Inconsistent layer count");
156 --mLayerCount;
157 }
159 PLDHashNumber Hash() const
160 {
161 PLDHashNumber hash = 0;
163 for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) {
164 hash = AddToHash(hash, mRoundedClipRects[i].Hash());
165 }
167 return hash;
168 }
170 bool operator==(const MaskLayerImageKey& aOther) const
171 {
172 return mRoundedClipRects == aOther.mRoundedClipRects;
173 }
175 mutable uint32_t mLayerCount;
176 nsTArray<PixelRoundedRect> mRoundedClipRects;
177 };
180 // Find an image container for aKey, returns nullptr if there is no suitable
181 // cached image. If there is an image, then aKey is set to point at the stored
182 // key for the image.
183 ImageContainer* FindImageFor(const MaskLayerImageKey** aKey);
185 // Add an image container with a key to the cache
186 // The image container used will be set as the container in aKey and aKey
187 // itself will be linked from this cache
188 void PutImage(const MaskLayerImageKey* aKey,
189 ImageContainer* aContainer);
191 // Sweep the cache for old image containers that can be deleted
192 void Sweep();
194 protected:
196 class MaskLayerImageEntry : public PLDHashEntryHdr
197 {
198 public:
199 typedef const MaskLayerImageKey& KeyType;
200 typedef const MaskLayerImageKey* KeyTypePointer;
202 MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey)
203 {
204 MOZ_COUNT_CTOR(MaskLayerImageEntry);
205 }
206 MaskLayerImageEntry(const MaskLayerImageEntry& aOther)
207 : mKey(aOther.mKey.get())
208 {
209 NS_ERROR("ALLOW_MEMMOVE == true, should never be called");
210 }
211 ~MaskLayerImageEntry()
212 {
213 MOZ_COUNT_DTOR(MaskLayerImageEntry);
214 }
216 // KeyEquals(): does this entry match this key?
217 bool KeyEquals(KeyTypePointer aKey) const
218 {
219 return *mKey == *aKey;
220 }
222 // KeyToPointer(): Convert KeyType to KeyTypePointer
223 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
225 // HashKey(): calculate the hash number
226 static PLDHashNumber HashKey(KeyTypePointer aKey)
227 {
228 return aKey->Hash();
229 }
231 // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
232 // to use the copy constructor?
233 enum { ALLOW_MEMMOVE = true };
235 bool operator==(const MaskLayerImageEntry& aOther) const
236 {
237 return KeyEquals(aOther.mKey);
238 }
240 nsAutoPtr<const MaskLayerImageKey> mKey;
241 nsRefPtr<ImageContainer> mContainer;
242 };
244 nsTHashtable<MaskLayerImageEntry> mMaskImageContainers;
246 // helper funtion for Sweep(), called for each entry in the hashtable
247 static PLDHashOperator SweepFunc(MaskLayerImageEntry* aEntry, void* aUserArg);
248 };
250 }
253 #endif