Bug 538266. Part 2: add transform API to layer system. r=jrmuizel,sr=dbaron

This commit is contained in:
Robert O'Callahan 2010-03-02 12:08:28 +13:00
Родитель 4b4c15dbc9
Коммит b0368c5f49
2 изменённых файлов: 41 добавлений и 9 удалений

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsRegion.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "gfx3DMatrix.h"
class gfxContext;
class nsPaintEvent;
@ -228,6 +229,15 @@ public:
}
}
/**
* CONSTRUCTION PHASE ONLY
* Tell this layer what its transform should be. The transformation
* is applied when compositing the layer into its parent container.
* XXX Currently only transformations corresponding to 2D affine transforms
* are supported.
*/
void SetTransform(const gfx3DMatrix& aMatrix) { mTransform = aMatrix; }
// These getters can be used anytime.
float GetOpacity() { return mOpacity; }
const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; }
@ -236,6 +246,7 @@ public:
Layer* GetNextSibling() { return mNextSibling; }
Layer* GetPrevSibling() { return mPrevSibling; }
virtual Layer* GetFirstChild() { return nsnull; }
const gfx3DMatrix& GetTransform() { return mTransform; }
/**
* Only the implementation should call this. This is per-implementation
@ -268,6 +279,7 @@ protected:
Layer* mNextSibling;
Layer* mPrevSibling;
void* mImplData;
gfx3DMatrix mTransform;
float mOpacity;
nsIntRect mClipRect;
PRPackedBool mUseClipRect;

Просмотреть файл

@ -349,7 +349,8 @@ NeedsGroup(Layer* aLayer)
static PRBool
NeedsState(Layer* aLayer)
{
return aLayer->GetClipRect() != nsnull;
return aLayer->GetClipRect() != nsnull ||
!aLayer->GetTransform().IsIdentity();
}
// Returns true if it's OK to save the contents of aLayer in an
@ -379,19 +380,38 @@ BasicLayerManager::BeginPaintingLayer(Layer* aLayer)
{
PRBool needsGroup = NeedsGroup(aLayer);
if ((needsGroup || NeedsState(aLayer)) && mTarget) {
// If we need to call PushGroup, we should clip to the smallest possible
// area first to minimize the size of the temporary surface.
nsIntRect bbox = ToData(aLayer)->GetVisibleRegion().GetBounds();
mTarget->Save();
if (aLayer->GetClipRect()) {
bbox.IntersectRect(bbox, *aLayer->GetClipRect());
const nsIntRect& r = *aLayer->GetClipRect();
mTarget->NewPath();
mTarget->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
mTarget->Clip();
}
mTarget->Save();
mTarget->NewPath();
mTarget->Rectangle(gfxRect(bbox.x, bbox.y, bbox.width, bbox.height));
mTarget->Clip();
gfxMatrix transform;
// XXX we need to add some kind of 3D transform support, possibly
// using pixman?
NS_ASSERTION(aLayer->GetTransform().Is2D(),
"Only 2D transforms supported currently");
aLayer->GetTransform().Is2D(&transform);
mTarget->Multiply(transform);
if (needsGroup) {
// If we need to call PushGroup, we should clip to the smallest possible
// area first to minimize the size of the temporary surface.
nsIntRect bbox = ToData(aLayer)->GetVisibleRegion().GetBounds();
gfxRect deviceRect =
mTarget->UserToDevice(gfxRect(bbox.x, bbox.y, bbox.width, bbox.height));
deviceRect.RoundOut();
gfxMatrix currentMatrix = mTarget->CurrentMatrix();
mTarget->IdentityMatrix();
mTarget->NewPath();
mTarget->Rectangle(deviceRect);
mTarget->Clip();
mTarget->SetMatrix(currentMatrix);
gfxASurface::gfxContentType type = UseOpaqueSurface(aLayer)
? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
mTarget->PushGroup(type);