mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 757347; Add a cache for image containers. r=roc
This commit is contained in:
parent
91b18c2a91
commit
8c7a60de72
@ -64,6 +64,7 @@ EXPORTS_mozilla = \
|
||||
|
||||
CPPSRCS = \
|
||||
FrameLayerBuilder.cpp \
|
||||
MaskLayerImageCache.cpp \
|
||||
FramePropertyTable.cpp \
|
||||
RestyleTracker.cpp \
|
||||
nsCSSColorUtils.cpp \
|
||||
|
49
layout/base/MaskLayerImageCache.cpp
Normal file
49
layout/base/MaskLayerImageCache.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MaskLayerImageCache.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
MaskLayerImageCache::SweepFunc(MaskLayerImageEntry* aEntry,
|
||||
void* aUserArg)
|
||||
{
|
||||
const MaskLayerImageCache::MaskLayerImageKey* key = aEntry->mKey;
|
||||
|
||||
if (key->mLayerCount == 0) {
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
MaskLayerImageCache::Sweep()
|
||||
{
|
||||
mMaskImageContainers.EnumerateEntries(SweepFunc, nsnull);
|
||||
}
|
||||
|
||||
ImageContainer*
|
||||
MaskLayerImageCache::FindImageFor(const MaskLayerImageKey** aKey)
|
||||
{
|
||||
if (MaskLayerImageEntry* entry = mMaskImageContainers.GetEntry(**aKey)) {
|
||||
*aKey = entry->mKey.get();
|
||||
return entry->mContainer;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
MaskLayerImageCache::PutImage(const MaskLayerImageKey* aKey, ImageContainer* aContainer)
|
||||
{
|
||||
MaskLayerImageEntry* entry = mMaskImageContainers.PutEntry(*aKey);
|
||||
entry->mContainer = aContainer;
|
||||
}
|
||||
|
||||
}
|
215
layout/base/MaskLayerImageCache.h
Normal file
215
layout/base/MaskLayerImageCache.h
Normal file
@ -0,0 +1,215 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MASKLAYERIMAGECACHE_H_
|
||||
#define MASKLAYERIMAGECACHE_H_
|
||||
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "ImageLayers.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Keeps a record of image containers for mask layers, containers are mapped
|
||||
* from the rounded rects used to create them.
|
||||
* The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys.
|
||||
* Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey
|
||||
* (heap-allocated so that a mask layer's userdata can keep a pointer to the
|
||||
* key for its image, in spite of the hashtable moving its entries around).
|
||||
* The key consists of the rounded rects used to create the mask,
|
||||
* an nsRefPtr to the ImageContainer containing the image, and a count
|
||||
* of the number of layers currently using this ImageContainer.
|
||||
* When the key's layer count is zero, the cache
|
||||
* may remove the entry, which deletes the key object.
|
||||
*/
|
||||
class MaskLayerImageCache
|
||||
{
|
||||
typedef mozilla::layers::ImageContainer ImageContainer;
|
||||
public:
|
||||
MaskLayerImageCache()
|
||||
{
|
||||
mMaskImageContainers.Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of a rounded rectangle in device pixel coordinates, in
|
||||
* contrast to FrameLayerBuilder::Clip::RoundedRect, which uses app units.
|
||||
* In particular, our internal representation uses a gfxRect, rather than
|
||||
* an nsRect, so this class is easier to use with transforms.
|
||||
*/
|
||||
struct PixelRoundedRect
|
||||
{
|
||||
PixelRoundedRect(const FrameLayerBuilder::Clip::RoundedRect& aRRect,
|
||||
nsPresContext* aPresContext)
|
||||
: mRect(aPresContext->AppUnitsToGfxUnits(aRRect.mRect.x),
|
||||
aPresContext->AppUnitsToGfxUnits(aRRect.mRect.y),
|
||||
aPresContext->AppUnitsToGfxUnits(aRRect.mRect.width),
|
||||
aPresContext->AppUnitsToGfxUnits(aRRect.mRect.height))
|
||||
{
|
||||
NS_FOR_CSS_HALF_CORNERS(corner) {
|
||||
mRadii[corner] = aPresContext->AppUnitsToGfxUnits(aRRect.mRadii[corner]);
|
||||
}
|
||||
}
|
||||
|
||||
// Applies the scale and translate components of aTransform.
|
||||
// It is an error to pass a matrix which does more than just scale
|
||||
// and translate.
|
||||
void ScaleAndTranslate(const gfxMatrix& aTransform)
|
||||
{
|
||||
NS_ASSERTION(aTransform.xy == 0 && aTransform.yx == 0,
|
||||
"Transform has a component other than scale and translate");
|
||||
|
||||
mRect = aTransform.Transform(mRect);
|
||||
|
||||
for (int i = 0; i < ArrayLength(mRadii); i += 2) {
|
||||
mRadii[i] *= aTransform.xx;
|
||||
mRadii[i + 1] *= aTransform.yy;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const PixelRoundedRect& aOther) const {
|
||||
if (!mRect.IsEqualInterior(aOther.mRect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_FOR_CSS_HALF_CORNERS(corner) {
|
||||
if (mRadii[corner] != aOther.mRadii[corner]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const PixelRoundedRect& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
// Create a hash for this object.
|
||||
PLDHashNumber Hash() const
|
||||
{
|
||||
PLDHashNumber hash = HashBytes(&mRect.x, 4*sizeof(gfxFloat));
|
||||
AddToHash(hash, HashBytes(mRadii, 8*sizeof(gfxFloat)));
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
gfxRect mRect;
|
||||
// Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
|
||||
gfxFloat mRadii[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* A key to identify cached image containers.
|
||||
* The const-ness of this class is with respect to its use as a key into a
|
||||
* hashtable, so anything not used to create the hash is mutable.
|
||||
* mLayerCount counts the number of mask layers which have a reference to
|
||||
* MaskLayerImageEntry::mContainer; it is maintained by MaskLayerUserData,
|
||||
* which keeps a reference to the key. There will usually be mLayerCount + 1
|
||||
* pointers to a key object (the +1 being from the hashtable entry), but this
|
||||
* invariant may be temporarily broken.
|
||||
*/
|
||||
class MaskLayerImageKey
|
||||
{
|
||||
public:
|
||||
MaskLayerImageKey(const nsTArray<PixelRoundedRect>& aRoundedClipRects)
|
||||
: mLayerCount(0)
|
||||
, mRoundedClipRects(aRoundedClipRects)
|
||||
{}
|
||||
|
||||
void AddRef() const { ++mLayerCount; }
|
||||
void Release() const
|
||||
{
|
||||
NS_ASSERTION(mLayerCount > 0, "Inconsistent layer count");
|
||||
--mLayerCount;
|
||||
}
|
||||
|
||||
PLDHashNumber Hash() const
|
||||
{
|
||||
PLDHashNumber hash = 0;
|
||||
|
||||
for (PRUint32 i = 0; i < mRoundedClipRects.Length(); ++i) {
|
||||
AddToHash(hash, mRoundedClipRects[i].Hash());
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool operator==(const MaskLayerImageKey& aOther) const
|
||||
{
|
||||
return mRoundedClipRects == aOther.mRoundedClipRects;
|
||||
}
|
||||
|
||||
mutable PRUint32 mLayerCount;
|
||||
nsTArray<PixelRoundedRect> mRoundedClipRects;
|
||||
};
|
||||
|
||||
|
||||
// Find an image container for aKey, returns nsnull if there is no suitable
|
||||
// cached image. If there is an image, then aKey is set to point at the stored
|
||||
// key for the image.
|
||||
ImageContainer* FindImageFor(const MaskLayerImageKey** aKey);
|
||||
|
||||
// Add an image container with a key to the cache
|
||||
// The image container used will be set as the container in aKey and aKey
|
||||
// itself will be linked from this cache
|
||||
void PutImage(const MaskLayerImageKey* aKey,
|
||||
ImageContainer* aContainer);
|
||||
|
||||
// Sweep the cache for old image containers that can be deleted
|
||||
void Sweep();
|
||||
|
||||
protected:
|
||||
|
||||
class MaskLayerImageEntry : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
typedef const MaskLayerImageKey& KeyType;
|
||||
typedef const MaskLayerImageKey* KeyTypePointer;
|
||||
|
||||
MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey) {}
|
||||
MaskLayerImageEntry(const MaskLayerImageEntry& aOther)
|
||||
: mKey(aOther.mKey.get())
|
||||
{
|
||||
NS_ERROR("ALLOW_MEMMOVE == true, should never be called");
|
||||
}
|
||||
|
||||
// KeyEquals(): does this entry match this key?
|
||||
bool KeyEquals(KeyTypePointer aKey) const
|
||||
{
|
||||
return *mKey == *aKey;
|
||||
}
|
||||
|
||||
// KeyToPointer(): Convert KeyType to KeyTypePointer
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
|
||||
// HashKey(): calculate the hash number
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
return aKey->Hash();
|
||||
}
|
||||
|
||||
// ALLOW_MEMMOVE can we move this class with memmove(), or do we have
|
||||
// to use the copy constructor?
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
bool operator==(const MaskLayerImageEntry& aOther) const
|
||||
{
|
||||
return KeyEquals(aOther.mKey);
|
||||
}
|
||||
|
||||
nsAutoPtr<const MaskLayerImageKey> mKey;
|
||||
nsRefPtr<ImageContainer> mContainer;
|
||||
};
|
||||
|
||||
nsTHashtable<MaskLayerImageEntry> mMaskImageContainers;
|
||||
|
||||
// helper funtion for Sweep(), called for each entry in the hashtable
|
||||
static PLDHashOperator SweepFunc(MaskLayerImageEntry* aEntry, void* aUserArg);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user