mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 572680 - Create gfxDrawable interface and implementations for surfaces, patterns and drawing callbacks. r=joe
This commit is contained in:
parent
ac97761cb7
commit
9a0597fca0
@ -19,6 +19,7 @@ EXPORTS = \
|
||||
gfxCachedTempSurface.h \
|
||||
gfxColor.h \
|
||||
gfxContext.h \
|
||||
gfxDrawable.h \
|
||||
gfxFont.h \
|
||||
gfxFontConstants.h \
|
||||
gfxFontUtils.h \
|
||||
@ -166,6 +167,7 @@ CPPSRCS = \
|
||||
gfxBlur.cpp \
|
||||
gfxCachedTempSurface.cpp \
|
||||
gfxContext.cpp \
|
||||
gfxDrawable.cpp \
|
||||
gfxImageSurface.cpp \
|
||||
gfxFont.cpp \
|
||||
gfxFontMissingGlyphs.cpp \
|
||||
|
254
gfx/thebes/gfxDrawable.cpp
Normal file
254
gfx/thebes/gfxDrawable.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Markus Stange.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "gfxDrawable.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
gfxSurfaceDrawable::gfxSurfaceDrawable(gfxASurface* aSurface,
|
||||
const gfxIntSize aSize,
|
||||
const gfxMatrix aTransform)
|
||||
: gfxDrawable(aSize)
|
||||
, mSurface(aSurface)
|
||||
, mTransform(aTransform)
|
||||
{
|
||||
}
|
||||
|
||||
static gfxMatrix
|
||||
DeviceToImageTransform(gfxContext* aContext,
|
||||
const gfxMatrix& aUserSpaceToImageSpace)
|
||||
{
|
||||
gfxFloat deviceX, deviceY;
|
||||
nsRefPtr<gfxASurface> currentTarget =
|
||||
aContext->CurrentSurface(&deviceX, &deviceY);
|
||||
gfxMatrix currentMatrix = aContext->CurrentMatrix();
|
||||
gfxMatrix deviceToUser = gfxMatrix(currentMatrix).Invert();
|
||||
deviceToUser.Translate(-gfxPoint(-deviceX, -deviceY));
|
||||
return gfxMatrix(deviceToUser).Multiply(aUserSpaceToImageSpace);
|
||||
}
|
||||
|
||||
static void
|
||||
PreparePatternForUntiledDrawing(gfxPattern* aPattern,
|
||||
const gfxMatrix& aDeviceToImage,
|
||||
gfxASurface::gfxSurfaceType aSurfaceType,
|
||||
const gfxPattern::GraphicsFilter aDefaultFilter)
|
||||
{
|
||||
// In theory we can handle this using cairo's EXTEND_PAD,
|
||||
// but implementation limitations mean we have to consult
|
||||
// the surface type.
|
||||
switch (aSurfaceType) {
|
||||
case gfxASurface::SurfaceTypeXlib:
|
||||
case gfxASurface::SurfaceTypeXcb:
|
||||
{
|
||||
// See bug 324698. This is a workaround for EXTEND_PAD not being
|
||||
// implemented correctly on linux in the X server.
|
||||
//
|
||||
// Set the filter to CAIRO_FILTER_FAST --- otherwise,
|
||||
// pixman's sampling will sample transparency for the outside edges
|
||||
// and we'll get blurry edges. CAIRO_EXTEND_PAD would also work
|
||||
// here, if available
|
||||
//
|
||||
// But don't do this for simple downscales because it's horrible.
|
||||
// Downscaling means that device-space coordinates are
|
||||
// scaled *up* to find the image pixel coordinates.
|
||||
PRBool isDownscale =
|
||||
aDeviceToImage.xx >= 1.0 && aDeviceToImage.yy >= 1.0 &&
|
||||
aDeviceToImage.xy == 0.0 && aDeviceToImage.yx == 0.0;
|
||||
if (!isDownscale) {
|
||||
aPattern->SetFilter(gfxPattern::FILTER_FAST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case gfxASurface::SurfaceTypeQuartz:
|
||||
case gfxASurface::SurfaceTypeQuartzImage:
|
||||
// Don't set EXTEND_PAD, Mac seems to be OK. Really?
|
||||
aPattern->SetFilter(aDefaultFilter);
|
||||
break;
|
||||
|
||||
default:
|
||||
// turn on EXTEND_PAD.
|
||||
// This is what we really want for all surface types, if the
|
||||
// implementation was universally good.
|
||||
aPattern->SetExtend(gfxPattern::EXTEND_PAD);
|
||||
aPattern->SetFilter(aDefaultFilter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxSurfaceDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
nsRefPtr<gfxPattern> pattern = new gfxPattern(mSurface);
|
||||
if (aRepeat) {
|
||||
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
|
||||
pattern->SetFilter(aFilter);
|
||||
} else {
|
||||
nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface();
|
||||
gfxASurface::gfxSurfaceType surfaceType = currentTarget->GetType();
|
||||
gfxMatrix deviceSpaceToImageSpace =
|
||||
DeviceToImageTransform(aContext, aTransform);
|
||||
PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace,
|
||||
surfaceType, aFilter);
|
||||
}
|
||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
pattern->SetFilter(gfxPattern::FILTER_FAST);
|
||||
#endif
|
||||
pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform));
|
||||
aContext->NewPath();
|
||||
aContext->SetPattern(pattern);
|
||||
aContext->Rectangle(aFillRect);
|
||||
aContext->Fill();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback,
|
||||
const gfxIntSize aSize)
|
||||
: gfxDrawable(aSize)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<gfxSurfaceDrawable>
|
||||
gfxCallbackDrawable::MakeSurfaceDrawable(const gfxPattern::GraphicsFilter aFilter)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surface =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenSurface(mSize, gfxASurface::ImageFormatARGB32);
|
||||
if (!surface || surface->CairoStatus() != 0)
|
||||
return nsnull;
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
|
||||
Draw(ctx, gfxRect(0, 0, mSize.width, mSize.height), PR_FALSE, aFilter);
|
||||
nsRefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, mSize);
|
||||
return drawable.forget();
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxCallbackDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
if (aRepeat && !mSurfaceDrawable) {
|
||||
mSurfaceDrawable = MakeSurfaceDrawable(aFilter);
|
||||
}
|
||||
|
||||
if (mSurfaceDrawable)
|
||||
return mSurfaceDrawable->Draw(aContext, aFillRect, aRepeat, aFilter,
|
||||
aTransform);
|
||||
|
||||
if (mCallback)
|
||||
return (*mCallback)(aContext, aFillRect, aFilter, aTransform);
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
gfxPatternDrawable::gfxPatternDrawable(gfxPattern* aPattern,
|
||||
const gfxIntSize aSize)
|
||||
: gfxDrawable(aSize)
|
||||
, mPattern(aPattern)
|
||||
{
|
||||
}
|
||||
|
||||
class DrawingCallbackFromDrawable : public gfxDrawingCallback {
|
||||
public:
|
||||
DrawingCallbackFromDrawable(gfxDrawable* aDrawable)
|
||||
: mDrawable(aDrawable) {
|
||||
NS_ASSERTION(aDrawable, "aDrawable is null!");
|
||||
}
|
||||
|
||||
virtual ~DrawingCallbackFromDrawable() {}
|
||||
|
||||
virtual PRBool operator()(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix())
|
||||
{
|
||||
return mDrawable->Draw(aContext, aFillRect, PR_FALSE, aFilter,
|
||||
aTransform);
|
||||
}
|
||||
private:
|
||||
nsRefPtr<gfxDrawable> mDrawable;
|
||||
};
|
||||
|
||||
already_AddRefed<gfxCallbackDrawable>
|
||||
gfxPatternDrawable::MakeCallbackDrawable()
|
||||
{
|
||||
nsRefPtr<gfxDrawingCallback> callback =
|
||||
new DrawingCallbackFromDrawable(this);
|
||||
nsRefPtr<gfxCallbackDrawable> callbackDrawable =
|
||||
new gfxCallbackDrawable(callback, mSize);
|
||||
return callbackDrawable.forget();
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxPatternDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
if (!mPattern)
|
||||
return PR_FALSE;
|
||||
|
||||
if (aRepeat) {
|
||||
// We can't use mPattern directly: We want our repeated tiles to have
|
||||
// the size mSize, which might not be the case in mPattern.
|
||||
// So we need to draw mPattern into a surface of size mSize, create
|
||||
// a pattern from the surface and draw that pattern.
|
||||
// gfxCallbackDrawable and gfxSurfaceDrawable already know how to do
|
||||
// those things, so we use them here. Drawing mPattern into the surface
|
||||
// will happen through this Draw() method with aRepeat = PR_FALSE.
|
||||
nsRefPtr<gfxCallbackDrawable> callbackDrawable = MakeCallbackDrawable();
|
||||
return callbackDrawable->Draw(aContext, aFillRect, PR_TRUE, aFilter,
|
||||
aTransform);
|
||||
}
|
||||
|
||||
aContext->NewPath();
|
||||
gfxMatrix oldMatrix = mPattern->GetMatrix();
|
||||
mPattern->SetMatrix(gfxMatrix(aTransform).Multiply(oldMatrix));
|
||||
aContext->SetPattern(mPattern);
|
||||
aContext->Rectangle(aFillRect);
|
||||
aContext->Fill();
|
||||
mPattern->SetMatrix(oldMatrix);
|
||||
return PR_TRUE;
|
||||
}
|
169
gfx/thebes/gfxDrawable.h
Normal file
169
gfx/thebes/gfxDrawable.h
Normal file
@ -0,0 +1,169 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Markus Stange.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_DRAWABLE_H
|
||||
#define GFX_DRAWABLE_H
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxColor.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxPattern.h"
|
||||
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
|
||||
/**
|
||||
* gfxDrawable
|
||||
* An Interface representing something that has an intrinsic size and can draw
|
||||
* itself repeatedly.
|
||||
*/
|
||||
class THEBES_API gfxDrawable {
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxDrawable)
|
||||
public:
|
||||
gfxDrawable(const gfxIntSize aSize)
|
||||
: mSize(aSize) {}
|
||||
virtual ~gfxDrawable() {}
|
||||
|
||||
/**
|
||||
* Draw into aContext filling aFillRect, possibly repeating, using aFilter.
|
||||
* aTransform is a userspace to "image"space matrix. For example, if Draw
|
||||
* draws using a gfxPattern, this is the matrix that should be set on the
|
||||
* pattern prior to rendering it.
|
||||
* @return whether drawing was successful
|
||||
*/
|
||||
virtual PRBool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix()) = 0;
|
||||
virtual gfxIntSize Size() { return mSize; }
|
||||
|
||||
protected:
|
||||
const gfxIntSize mSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* gfxSurfaceDrawable
|
||||
* A convenience implementation of gfxDrawable for surfaces.
|
||||
*/
|
||||
class THEBES_API gfxSurfaceDrawable : public gfxDrawable {
|
||||
public:
|
||||
gfxSurfaceDrawable(gfxASurface* aSurface, const gfxIntSize aSize,
|
||||
const gfxMatrix aTransform = gfxMatrix());
|
||||
virtual ~gfxSurfaceDrawable() {}
|
||||
|
||||
virtual PRBool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
protected:
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
const gfxMatrix mTransform;
|
||||
};
|
||||
|
||||
/**
|
||||
* gfxDrawingCallback
|
||||
* A simple drawing functor.
|
||||
*/
|
||||
class THEBES_API gfxDrawingCallback {
|
||||
NS_INLINE_DECL_REFCOUNTING(gfxDrawingCallback)
|
||||
public:
|
||||
virtual ~gfxDrawingCallback() {}
|
||||
|
||||
/**
|
||||
* Draw into aContext filling aFillRect using aFilter.
|
||||
* aTransform is a userspace to "image"space matrix. For example, if Draw
|
||||
* draws using a gfxPattern, this is the matrix that should be set on the
|
||||
* pattern prior to rendering it.
|
||||
* @return whether drawing was successful
|
||||
*/
|
||||
virtual PRBool operator()(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix()) = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* gfxSurfaceDrawable
|
||||
* A convenience implementation of gfxDrawable for callbacks.
|
||||
*/
|
||||
class THEBES_API gfxCallbackDrawable : public gfxDrawable {
|
||||
public:
|
||||
gfxCallbackDrawable(gfxDrawingCallback* aCallback, const gfxIntSize aSize);
|
||||
virtual ~gfxCallbackDrawable() {}
|
||||
|
||||
virtual PRBool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
protected:
|
||||
already_AddRefed<gfxSurfaceDrawable> MakeSurfaceDrawable(const gfxPattern::GraphicsFilter aFilter = gfxPattern::FILTER_FAST);
|
||||
|
||||
nsRefPtr<gfxDrawingCallback> mCallback;
|
||||
nsRefPtr<gfxSurfaceDrawable> mSurfaceDrawable;
|
||||
};
|
||||
|
||||
/**
|
||||
* gfxPatternDrawable
|
||||
* A convenience implementation of gfxDrawable for patterns.
|
||||
*/
|
||||
class THEBES_API gfxPatternDrawable : public gfxDrawable {
|
||||
public:
|
||||
gfxPatternDrawable(gfxPattern* aPattern,
|
||||
const gfxIntSize aSize);
|
||||
virtual ~gfxPatternDrawable() {}
|
||||
|
||||
virtual PRBool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
PRBool aRepeat,
|
||||
const gfxPattern::GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
protected:
|
||||
already_AddRefed<gfxCallbackDrawable> MakeCallbackDrawable();
|
||||
|
||||
nsRefPtr<gfxPattern> mPattern;
|
||||
};
|
||||
|
||||
#endif /* GFX_DRAWABLE_H */
|
Loading…
Reference in New Issue
Block a user