All pastes #424328 Raw Edit

Mine

public cpp v1 · immutable
·published 2007-04-04 18:35 UTC
rendered paste body
#define MOZILLA_INTERNAL_API#include <X11/Xlib.h>#include "prmem.h"#include "prlog.h"#include "nsIRenderingContext.h"#include "nsIViewManager.h"#include "compzillaIRenderingContext.h"#include "nsICanvasRenderingContextInternal.h"#include "nsIDOMHTMLCanvasElement.h"#include "compzillaRenderingContext.h"#ifdef MOZ_CAIRO_GFX#include "thebes/gfxContext.h"#include "thebes/gfxASurface.h"#else#include "nsTransform2D.h"#include "cairo-xlib.h"#include <gdk/gdk.h>#include <gdk/gdkx.h>#endif#define DEBUG(format...) printf("   - " format)#define INFO(format...) printf(" *** " format)#define WARNING(format...) printf(" !!! " format)#define ERROR(format...) fprintf(stderr, format)NS_IMPL_ISUPPORTS3_CI (compzillaRenderingContext,		       compzillaIRenderingContext,		       compzillaIRenderingContextInternal,		       nsICanvasRenderingContextInternal)nsresultCZ_NewRenderingContext(compzillaIRenderingContext** aResult){    compzillaIRenderingContext* ctx = new compzillaRenderingContext();    if (!ctx)        return NS_ERROR_OUT_OF_MEMORY;    NS_ADDREF(*aResult = ctx);    return NS_OK;}compzillaRenderingContext::compzillaRenderingContext()  : mWidth(0), mHeight(0), mStride(0), mImageBuffer(nsnull),    mCanvasElement(nsnull),    mCairoImageSurface(nsnull){}compzillaRenderingContext::~compzillaRenderingContext(){}NS_METHODcompzillaRenderingContext::SetCanvasElement (nsICanvasElement* aParentCanvas){    mCanvasElement = aParentCanvas;    DEBUG ("SetCanvasElement: %p\n", mCanvasElement);    return NS_OK;}voidcompzillaRenderingContext::Destroy (){    if (mCairoImageSurface) {      DEBUG ("destroying cairo surface");      cairo_surface_destroy (mCairoImageSurface);      mCairoImageSurface = nsnull;    }}NS_METHOD compzillaRenderingContext::SetDimensions (PRInt32 width, PRInt32 height){    DEBUG ("SetDimensions\n");    if (mWidth == width && mHeight == height)        return NS_OK;    Destroy();    int mStride = (((mWidth*4) + 3) / 4) * 4;    mWidth = width;    mHeight = height;    // allocate surface    return NS_OK;}nsIFrame*compzillaRenderingContext::GetCanvasLayoutFrame(){    if (!mCanvasElement)        return nsnull;    nsIFrame *fr = nsnull;    mCanvasElement->GetPrimaryCanvasFrame(&fr);    return fr;}nsresultcompzillaRenderingContext::Redraw(){    // then invalidate the region and do a sync redraw    // (uh, why sync?)    nsIFrame *frame = GetCanvasLayoutFrame();    if (frame) {        nsRect r = frame->GetRect();        r.x = r.y = 0;        // sync redraw        //frame->Invalidate(r, PR_TRUE);        // nsIFrame::Invalidate is an internal non-virtual method,        // so we basically recreate it here.  I would suggest        // an InvalidateExternal for the trunk.        nsIPresShell *shell = frame->GetPresContext()->GetPresShell();        if (shell) {            PRBool suppressed = PR_FALSE;            shell->IsPaintingSuppressed(&suppressed);            if (suppressed)                return NS_OK;        }        // maybe VMREFRESH_IMMEDIATE in some cases,        // need to think        PRUint32 flags = NS_VMREFRESH_NO_SYNC;        if (frame->HasView()) {            nsIView* view = frame->GetViewExternal();            view->GetViewManager()->UpdateView(view, r, flags);        } else {            nsPoint offset;            nsIView *view;            frame->GetOffsetFromView(offset, &view);            NS_ASSERTION(view, "no view");            r += offset;            view->GetViewManager()->UpdateView(view, r, flags);        }    }    return NS_OK;}/* * This is identical to nsCanvasRenderingContext2D::Render, we just don't * have a good place to put it; though maybe I want a CanvasContextImpl that * all this stuff can derive from? */NS_METHOD compzillaRenderingContext::Render (nsIRenderingContext *rc){   DEBUG ("Render\n");   if (!mCairoImageSurface)     return NS_OK;    nsresult rv = NS_OK;#ifdef MOZ_CAIRO_GFX    DEBUG ("thebes\n");    gfxContext* ctx = (gfxContext*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);    nsRefPtr<gfxASurface> surf = gfxASurface::Wrap(mCairoImageSurface);    nsRefPtr<gfxPattern> pat = new gfxPattern(surf);    // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee    // pixel alignment for this stuff!    ctx->NewPath();    ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);    ctx->Fill();#else    DEBUG ("non-thebes\n");    // non-Thebes; this becomes exciting    cairo_surface_t *dest = nsnull;    cairo_t *dest_cr = nsnull;    GdkDrawable *gdkdraw = nsnull;#ifdef MOZILLA_1_8_BRANCH    rv = rc->RetrieveCurrentNativeGraphicData((void**) &gdkdraw);    if (NS_FAILED(rv) || !gdkdraw)        return NS_ERROR_FAILURE;#else    gdkdraw = (GdkDrawable*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE);    if (!gdkdraw)        return NS_ERROR_FAILURE;#endif    gint w, h;    gdk_drawable_get_size (gdkdraw, &w, &h);    dest = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY(gdkdraw),                                      GDK_DRAWABLE_XID(gdkdraw),                                      GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(gdkdraw)),                                      w, h);    dest_cr = cairo_create (dest);    nsTransform2D *tx = nsnull;    rc->GetCurrentTransform(tx);    nsCOMPtr<nsIDeviceContext> dctx;    rc->GetDeviceContext(*getter_AddRefs(dctx));    float x0 = 0.0, y0 = 0.0;    float sx = 1.0, sy = 1.0;    if (tx->GetType() & MG_2DTRANSLATION) {        tx->Transform(&x0, &y0);    }    if (tx->GetType() & MG_2DSCALE) {        sx = sy = dctx->DevUnitsToTwips();        tx->TransformNoXLate(&sx, &sy);    }    cairo_translate (dest_cr, NSToIntRound(x0), NSToIntRound(y0));    if (sx != 1.0 || sy != 1.0)        cairo_scale (dest_cr, sx, sy);    cairo_rectangle (dest_cr, 0, 0, mWidth, mHeight);    cairo_clip (dest_cr);    cairo_set_source_surface (dest_cr, mCairoImageSurface, 0, 0);    cairo_paint (dest_cr);    if (dest_cr)        cairo_destroy (dest_cr);    if (dest)        cairo_surface_destroy (dest);#endif    return rv;}NS_METHOD compzillaRenderingContext::RenderToSurface (struct _cairo_surface *surf){   return NS_ERROR_NOT_IMPLEMENTED;}NS_METHOD compzillaRenderingContext::GetInputStream (const nsACString& aMimeType,					   const nsAString& aEncoderOptions,					   nsIInputStream **aStream){   return NS_ERROR_NOT_IMPLEMENTED;}NS_IMETHODIMPcompzillaRenderingContext::CopyImageDataFrom (Display *dpy,					      Window drawable,					      PRInt32 src_x, PRInt32 src_y,					      PRUint32 w, PRUint32 h){   // XXX this is wrong, but it'll do for now.  it needs to create a   // (possibly smaller) subimage and composite it into the larger   // mCairoImageSurface.   XImage *image = XGetImage (dpy, drawable, src_x, src_y, w, h, AllPlanes, ZPixmap);   mImageBuffer = (PRUint8*)PR_MALLOC (image->bytes_per_line * image->height);   // XXX we likely need to massage the data..   memcpy (mImageBuffer, image->data, image->bytes_per_line * image->height);   mCairoImageSurface = cairo_image_surface_create_for_data (mImageBuffer,							     CAIRO_FORMAT_ARGB32,							     w,							     h,							     image->bytes_per_line);   XFree (image->data);   XFree (image);   // XXX this redraws the entire canvas element.  we only need to   // force a redraw of the affected rectangle.   return Redraw ();}