better cairo drawing surface stuff, in progress

This commit is contained in:
vladimir%pobox.com 2004-08-16 00:37:37 +00:00
Родитель b248c2e374
Коммит 81c940994c
4 изменённых файлов: 185 добавлений и 56 удалений

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

@ -392,3 +392,31 @@ nsCairoDeviceContext::SetUseAltDC(PRUint8 aValue, PRBool aOn)
return NS_OK;
}
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Display *
nsCairoDeviceContext::GetXDisplay()
{
#ifdef MOZ_ENABLE_GTK2
return gdk_x11_get_default_xdisplay();
#endif
}
Visual *
nsCairoDeviceContext::GetXVisual()
{
return DefaultVisual(GetXDisplay(),DefaultScreen(GetXDisplay()));
}
Colormap
nsCairoDeviceContext::GetXColormap()
{
return DefaultColormap(GetXDisplay(),DefaultScreen(GetXDisplay()));
}
Drawable
nsCairoDeviceContext::GetXPixmapParentDrawable()
{
return RootWindow(GetXDisplay(),DefaultScreen(GetXDisplay()));
}
#endif

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

@ -97,15 +97,25 @@ public:
NS_IMETHOD GetAltDevice(nsIDeviceContext** aAltDC);
NS_IMETHOD SetUseAltDC(PRUint8 aValue, PRBool aOn);
// local methods
NS_IMETHOD CreateCairoFor(nsNativeWidget aNativeWidget, cairo_t **aCairo);
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Display *GetXDisplay();
Visual *GetXVisual();
Colormap GetXColormap();
Drawable GetXPixmapParentDrawable();
#endif
private:
cairo_t *mCairo;
cairo_surface_t *mSurface;
nsNativeWidget mWidget;
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Drawable mPixmapParentDrawable;
#endif
#ifdef MOZ_ENABLE_XLIB
XlibRgbHandle *mXlibRgbHandle;
#endif

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

@ -43,63 +43,102 @@
NS_IMPL_ISUPPORTS1(nsCairoDrawingSurface, nsIDrawingSurface)
nsCairoDrawingSurface::nsCairoDrawingSurface()
: mSurface(nsnull), mSurfaceData(nsnull), mOwnsData(PR_FALSE)
: mSurface(nsnull), mImageSurface(nsnull), mSurfaceData(nsnull), mOwnsData(PR_FALSE)
{
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
mPixmap = 0;
#endif
}
nsCairoDrawingSurface::~nsCairoDrawingSurface()
{
if (mSurface)
cairo_surface_destroy (mSurface);
if (mOwnsData && mSurfaceData)
nsMemory::Free(mSurfaceData);
if (mImageSurface && !mFastAccess) // otherwise, mImageSurface == mSurface
cairo_surface_destroy (mImageSurface);
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
if (mPixmap != 0)
XFreePixmap(mXDisplay, mPixmap)
#endif
}
nsresult
nsCairoDrawingSurface::Init(PRUint32 aWidth, PRUint32 aHeight)
nsCairoDrawingSurface::Init(nsCairoDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess)
{
NS_ASSERTION(mSurface == nsnull, "Surface already initialized!");
NS_ASSERTION(aWidth > 0 && aHeight > 0, "Invalid surface dimensions!");
mSurfaceData = (PRUint8*) nsMemory::Alloc(aWidth * aHeight * 4);
mSurface = cairo_image_surface_create_for_data ((char*) mSurfaceData, CAIRO_FORMAT_ARGB32,
aWidth, aHeight, aWidth * 4);
mWidth = aWidth;
mHeight = aHeight;
mStride = mWidth * 4;
mDepth = 32;
mOwnsData = PR_TRUE;
if (aFastAccess) {
mSurface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, aWidth, aHeight);
mDepth = 32;
mFastAccess = PR_TRUE;
} else {
// otherwise, we need to do toolkit-specific stuff
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
mXDisplay = aDC->GetXDisplay();
mPixmap = XCreatePixmap(mXDisplay,
aDC->GetXPixmapParentDrawable(),
aWidth, aHeight, 32);
mSurface = cairo_xlib_surface_create (aDC->GetXDisplay(),
mPixmap,
aDC->GetXVisual(),
CAIRO_FORMAT_ARGB32,
aDC->GetXColormap());
mDepth = 32;
mFastAccess = PR_FALSE;
#else
#error write me
#endif
}
mLockFlags = 0;
return NS_OK;
}
nsresult
nsCairoDrawingSurface::Init (cairo_surface_t *aSurface, PRBool aIsOffscreen,
PRUint32 aWidth, PRUint32 aHeight)
nsCairoDrawingSurface::Init (nsCairoDeviceContext *aDC, nsIWidget *aWidget)
{
mSurface = aSurface;
cairo_surface_reference (mSurface);
if (aIsOffscreen) {
char *data;
int width, height, depth, stride;
if (cairo_image_surface_get_data (mSurface, &data, &width, &height, &stride, &depth) == 0) {
mSurfaceData = (PRUint8*) data;
mWidth = width;
mHeight = height;
mStride = stride;
mDepth = depth;
mOwnsData = PR_FALSE;
mIsOffscreen = PR_TRUE;
} else {
NS_WARNING("nsCairoDrawingSurface::Init with non-image offscreen surface");
}
} else {
mWidth = aWidth;
mHeight = aHeight;
mOwnsData = PR_FALSE;
mIsOffscreen = PR_FALSE;
}
nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET);
#ifdef MOZ_ENABLE_GTK2
NS_ASSERTION (GDK_IS_WINDOW(aNativeWidget), "unsupported native widget type!");
mSurface = cairo_xlib_surface_create
(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(nativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(nativeWidget)),
GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(GDK_DRAWABLE(nativeWidget))),
CAIRO_FORMAT_ARGB32, // I hope!
GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(GDK_DRAWABLE(nativeWidget))));
Window root_ignore;
int x_ignore, y_ignore, bwidth_ignore;
int width, height, depth;
XGetGeometry(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(nativeWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(nativeWidget)),
&root_ignore, &x_ignore, &y_ignore,
&width, &height,
&bwidth_ignore, &depth);
if (depth != 32)
fprintf (stderr, "**** nsCairoDrawingSurface::Init with Widget: depth is %d!\n", depth);
mWidth = width;
mHeight = height;
mFastAccess = PR_FALSE;
#else
#error write me
#endif
mPixmap = 0;
mLockFlags = 0;
}
NS_IMETHODIMP
@ -108,22 +147,56 @@ nsCairoDrawingSurface::Lock (PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 a
PRUint32 aFlags)
{
NS_ASSERTION(aX + aWidth <= mWidth, "Invalid aX/aWidth");
NS_ASSERTION(aY + aHeight <= mHeight, "Inavlid aY/aHeight");
NS_ASSERTION(aY + aHeight <= mHeight, "Invalid aY/aHeight");
NS_ASSERTION(mLockFlags == 0, "nsCairoDrawingSurface::Lock while surface is already locked!");
if (mIsOffscreen) {
*aBits = mSurfaceData + ((aWidth * 4) * aY) + (aX * 4);
*aStride = mStride;
*aWidthBytes = mWidth * 4;
} else {
NS_WARNING("nsCairoDrawingSurface::Lock with non-offscreen surface!");
if (!mFastAccess) {
mImageSurface = cairo_surface_get_image (mSurface);
}
char *data;
int width, height, stride, depth;
if (cairo_image_surface_get_data (mImageSurface,
&data, &width, &height, &stride, &depth)
!= 0)
{
/* Something went wrong */
if (!mFastAccess) {
cairo_surface_destroy(mImageSurface);
mImageSurface = nsnull;
}
return NS_ERROR_FAILURE;
}
*aBits = data + (stride * aY) + (aX * (depth / 8));
*aStride = stride;
*aWidthBytes = width * (depth / 8);
mLockFlags = 0;
return NS_OK;
}
NS_IMETHODIMP
nsCairoDrawingSurface::Unlock (void)
{
NS_ASSERT(mLockFlags != 0, "nsCairoDrawingSurface::Unlock on non-locked surface!");
if (mFastAccess) {
mLockFlags = 0;
return NS_OK;
}
if (mLockFlags & NS_LOCK_SURFACE_WRITE_ONLY) {
/* need to copy back */
cairo_surface_set_image (mImageSurface);
}
cairo_surface_destroy (mImageSurface);
mImageSurface = nsnull;
mLockFlags = 0;
return NS_OK;
}
@ -138,14 +211,22 @@ nsCairoDrawingSurface::GetDimensions (PRUint32 *aWidth, PRUint32 *aHeight)
NS_IMETHODIMP
nsCairoDrawingSurface::IsOffscreen(PRBool *aOffScreen)
{
*aOffScreen = mIsOffscreen;
*aOffScreen = PR_FALSE;
if (mFastAccess)
*aOffScreen = PR_TRUE;
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
else if (mPixmap)
*aOffScreen = PR_TRUE;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsCairoDrawingSurface::IsPixelAddressable(PRBool *aAddressable)
{
*aAddressable = mIsOffscreen;
*aAddressable = mFastAccess;
return NS_OK;
}

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

@ -43,21 +43,26 @@
#include <cairo.h>
class nsIWidget;
class nsCairoDeviceContext;
class nsCairoDrawingSurface : public nsIDrawingSurface
{
public:
nsCairoDrawingSurface ();
virtual ~nsCairoDrawingSurface ();
// create a new image surface
nsresult Init (PRUint32 aWidth, PRUint32 aHeight);
// create a DrawingSurface based on the existing cairo surface
nsresult Init (cairo_surface_t *aSurface, PRBool aIsOffscreen,
PRUint32 aWidth, PRUint32 aHeight);
// create a image surface if aFastAccess == TRUE, otherwise create
// a fast server pixmap
nsresult Init (nsCairoDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess);
// create a fast drawing surface for a native widget
nsresult Init (nsCairoDevicecontext *aDC, nsIWidget *aWidget);
// nsISupports interface
NS_DECL_ISUPPORTS
//nsIDrawingSurface interface
// nsIDrawingSurface interface
NS_IMETHOD Lock(PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 aHeight,
void **aBits, PRInt32 *aStride, PRInt32 *aWidthBytes,
@ -72,11 +77,16 @@ public:
cairo_surface_t *GetCairoSurface(void) { return mSurface; }
PRInt32 GetDepth() { return mDepth; }
private:
cairo_surface_t *mSurface;
PRUint8 *mSurfaceData;
PRUint32 mWidth, mHeight, mStride, mDepth;
PRBool mOwnsData, mIsOffscreen;
cairo_surface_t *mSurface, *mImageSurface;
#if defined(MOZ_ENABLE_GTK2) || defined(MOZ_ENABLE_XLIB)
Display *mXDisplay;
Pixmap mPixmap;
#endif
PRUint32 mLockFlags;
PRBool mFastAccess;
PRUint32 mWidth, mHeight;
};
#endif /* NSCAIRODRAWINGSURFACE__H__ */