b=377336, win32 printing page results in excessive data spooled to printer, for real this time, r=stuart

This commit is contained in:
vladimir@pobox.com 2007-09-24 15:50:44 -07:00
parent 81a069aa59
commit 847a977dc2
13 changed files with 94 additions and 45 deletions

View File

@ -238,8 +238,8 @@ static cairo_int_status_t
_paint_fallback_image (cairo_paginated_surface_t *surface,
cairo_box_int_t *box)
{
double x_scale = surface->base.x_fallback_resolution / surface->base.x_resolution;
double y_scale = surface->base.y_fallback_resolution / surface->base.y_resolution;
double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
cairo_matrix_t matrix;
int x, y, width, height;
cairo_status_t status;

View File

@ -267,6 +267,12 @@ _cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t *su
int x_tile, y_tile, left, right, top, bottom;
RECT clip;
/* If we can't use StretchDIBits with this surface, we can't do anything
* special here.
*/
if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
return CAIRO_INT_STATUS_UNSUPPORTED;
extend = cairo_pattern_get_extend (&pattern->base);
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
(cairo_surface_t *)surface,
@ -284,6 +290,12 @@ _cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t *su
goto FINISH2;
}
if (image->width == 0 || image->height == 0)
{
status = CAIRO_STATUS_SUCCESS;
goto FINISH2;
}
if (image->format != CAIRO_FORMAT_RGB24) {
opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
image->width,
@ -378,7 +390,7 @@ _cairo_win32_printing_surface_paint_surface_pattern (cairo_win32_surface_t *su
&bi,
DIB_RGB_COLORS,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)");
return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_surface_pattern(StretchDIBits)");
}
}
SetStretchBltMode(surface->dc, oldmode);

View File

@ -69,7 +69,6 @@
#include "gfxPSSurface.h"
static nsSystemFontsGTK2 *gSystemFonts = nsnull;
#elif XP_WIN
#include <cairo-win32.h>
#include "nsSystemFontsWin.h"
#include "gfxWindowsSurface.h"
#include "gfxPDFSurface.h"
@ -193,7 +192,7 @@ nsThebesDeviceContext::SetDPI()
#elif defined(XP_OS2)
// get a printer DC if available, otherwise create a new (memory) DC
HDC dc = GetPrintDC();
HDC dc = GetPrintHDC();
PRBool doCloseDC = PR_FALSE;
if (dc <= 0) { // test for NULLHANDLE/DEV_ERROR or HDC_ERROR
// create DC compatible with the screen
@ -333,9 +332,6 @@ nsThebesDeviceContext::CreateRenderingContext(nsIRenderingContext *&aContext)
}
return rv;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
@ -700,6 +696,7 @@ nsThebesDeviceContext::CalcPrintingSize()
#ifdef XP_WIN
case gfxASurface::SurfaceTypeWin32:
case gfxASurface::SurfaceTypeWin32Printing:
{
inPoints = PR_FALSE;
HDC dc = GetPrintHDC();
@ -756,3 +753,30 @@ nsThebesDeviceContext::UpdateScaledAppUnits()
{
mAppUnitsPerDevPixel = PR_MAX(1, PRInt32(float(mAppUnitsPerDevNotScaledPixel) / mPixelScale));
}
#if defined(XP_WIN) || defined(XP_OS2)
HDC
nsThebesDeviceContext::GetPrintHDC()
{
if (mPrintingSurface) {
switch (mPrintingSurface->GetType()) {
#ifdef XP_WIN
case gfxASurface::SurfaceTypeWin32:
case gfxASurface::SurfaceTypeWin32Printing:
return reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
#endif
#ifdef XP_OS2
case gfxASurface::SurfaceTypeOS2:
return GpiQueryDevice(reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetPS());
#endif
default:
NS_ASSERTION(0, "invalid surface type in GetPrintHDC");
break;
}
}
return nsnull;
}
#endif

View File

@ -119,23 +119,8 @@ public:
virtual PRBool SetPixelScale(float aScale);
nsNativeWidget GetWidget() { return mWidget; }
#ifdef XP_WIN
HDC GetPrintHDC() {
if (mPrintingSurface) {
NS_ASSERTION(mPrintingSurface->GetType() == gfxASurface::SurfaceTypeWin32, "invalid surface type");
return reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
}
return nsnull;
}
#elif defined(XP_OS2)
// get the PS from the current surface and from that query the DC
HDC GetPrintDC() {
if (mPrintingSurface) {
NS_ASSERTION(mPrintingSurface->GetType() == gfxASurface::SurfaceTypeOS2, "invalid surface type");
return GpiQueryDevice(reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetPS());
}
return nsnull;
}
#if defined(XP_WIN) || defined(XP_OS2)
HDC GetPrintHDC();
#endif
protected:

View File

@ -80,7 +80,8 @@ public:
SurfaceTypeBeOS,
SurfaceTypeDirectFB,
SurfaceTypeSVG,
SurfaceTypeOS2
SurfaceTypeOS2,
SurfaceTypeWin32Printing
} gfxSurfaceType;
typedef enum {

View File

@ -45,8 +45,13 @@
class THEBES_API gfxWindowsSurface : public gfxASurface {
public:
enum {
FLAG_TAKE_DC = (1 << 0),
FLAG_FOR_PRINTING = (1 << 1)
};
gfxWindowsSurface(HWND wnd);
gfxWindowsSurface(HDC dc, PRBool deleteDC = PR_FALSE);
gfxWindowsSurface(HDC dc, PRUint32 flags = 0);
// Create a DIB surface
gfxWindowsSurface(const gfxIntSize& size,
@ -76,7 +81,9 @@ public:
nsresult EndPage();
private:
PRBool mOwnsDC;
PRPackedBool mOwnsDC;
PRPackedBool mForPrinting;
HDC mDC;
HWND mWnd;
};

View File

@ -147,7 +147,8 @@ gfxASurface::Wrap (cairo_surface_t *csurf)
result = new gfxImageSurface(csurf);
}
#ifdef CAIRO_HAS_WIN32_SURFACE
else if (stype == CAIRO_SURFACE_TYPE_WIN32) {
else if (stype == CAIRO_SURFACE_TYPE_WIN32 ||
stype == CAIRO_SURFACE_TYPE_WIN32_PRINTING) {
result = new gfxWindowsSurface(csurf);
}
#endif

View File

@ -91,9 +91,7 @@ gfxPDFSurface::BeginPage()
nsresult
gfxPDFSurface::EndPage()
{
cairo_t *cx = cairo_create(CairoSurface());
cairo_show_page(cx);
cairo_destroy(cx);
cairo_surface_show_page(CairoSurface());
return NS_OK;
}

View File

@ -91,9 +91,7 @@ gfxPSSurface::BeginPage()
nsresult
gfxPSSurface::EndPage()
{
cairo_t *cx = cairo_create(CairoSurface());
cairo_show_page(cx);
cairo_destroy(cx);
cairo_surface_show_page(CairoSurface());
return NS_OK;
}

View File

@ -81,7 +81,10 @@ struct DCFromContext {
dc = NULL;
nsRefPtr<gfxASurface> aSurface = aContext->CurrentSurface();
NS_ASSERTION(aSurface, "DCFromContext: null surface");
if (aSurface && aSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
if (aSurface &&
(aSurface->GetType() == gfxASurface::SurfaceTypeWin32 ||
aSurface->GetType() == gfxASurface::SurfaceTypeWin32Printing))
{
dc = static_cast<gfxWindowsSurface*>(aSurface.get())->GetDC();
needsRelease = PR_FALSE;
}

View File

@ -83,7 +83,8 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
// if this is a native win32 surface, we don't have to
// redirect rendering to our own HDC; in some cases,
// we may be able to use the HDC from the surface directly.
if (surf->GetType() == gfxASurface::SurfaceTypeWin32 &&
if ((surf->GetType() == gfxASurface::SurfaceTypeWin32 ||
surf->GetType() == gfxASurface::SurfaceTypeWin32Printing) &&
(surf->GetContentType() == gfxASurface::CONTENT_COLOR ||
(surf->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA &&
(mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA))))

View File

@ -45,20 +45,28 @@
#include "nsString.h"
gfxWindowsSurface::gfxWindowsSurface(HWND wnd) :
mOwnsDC(PR_TRUE), mWnd(wnd)
mOwnsDC(PR_TRUE), mForPrinting(PR_FALSE), mWnd(wnd)
{
mDC = ::GetDC(mWnd);
Init(cairo_win32_surface_create(mDC));
}
gfxWindowsSurface::gfxWindowsSurface(HDC dc, PRBool deleteDC) :
mOwnsDC(deleteDC), mDC(dc),mWnd(nsnull)
gfxWindowsSurface::gfxWindowsSurface(HDC dc, PRUint32 flags) :
mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mDC(dc), mWnd(nsnull)
{
Init(cairo_win32_surface_create(mDC));
if (flags & FLAG_TAKE_DC)
mOwnsDC = PR_TRUE;
if (flags & FLAG_FOR_PRINTING) {
Init(cairo_win32_printing_surface_create(mDC, TRUE));
mForPrinting = PR_TRUE;
} else {
Init(cairo_win32_surface_create(mDC));
}
}
gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& size, gfxImageFormat imageFormat) :
mOwnsDC(PR_FALSE), mWnd(nsnull)
mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mWnd(nsnull)
{
if (!CheckSurfaceSize(size))
return;
@ -71,7 +79,7 @@ gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& size, gfxImageFormat imag
}
gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& size, gfxImageFormat imageFormat) :
mOwnsDC(PR_FALSE), mWnd(nsnull)
mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mWnd(nsnull)
{
if (!CheckSurfaceSize(size))
return;
@ -85,10 +93,13 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& size, gfxImageFor
gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
mOwnsDC(PR_FALSE), mWnd(nsnull)
mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mWnd(nsnull)
{
mDC = cairo_win32_surface_get_dc(csurf);
if (cairo_surface_get_type(csurf) == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
mForPrinting = PR_TRUE;
Init(csurf, PR_TRUE);
}
@ -105,6 +116,9 @@ gfxWindowsSurface::~gfxWindowsSurface()
already_AddRefed<gfxImageSurface>
gfxWindowsSurface::GetImageSurface()
{
if (mForPrinting)
return nsnull;
cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
if (!isurf)
return nsnull;
@ -118,6 +132,9 @@ gfxWindowsSurface::GetImageSurface()
already_AddRefed<gfxWindowsSurface>
gfxWindowsSurface::OptimizeToDDB(HDC dc, const gfxIntSize& size, gfxImageFormat format)
{
if (mForPrinting)
return nsnull;
gfxImageFormat realFormat = format;
if (realFormat != ImageFormatRGB24)
@ -204,6 +221,8 @@ nsresult gfxWindowsSurface::BeginPage()
nsresult gfxWindowsSurface::EndPage()
{
if (mForPrinting)
cairo_surface_show_page(CairoSurface());
::EndPage(mDC);
return NS_OK;
}

View File

@ -547,7 +547,7 @@ NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface
HDC dc = ::CreateDC(mDriverName, mDeviceName, NULL, mDevMode);
// have this surface take over ownership of this DC
newSurface = new gfxWindowsSurface(dc, PR_TRUE);
newSurface = new gfxWindowsSurface(dc, gfxWindowsSurface::FLAG_TAKE_DC | gfxWindowsSurface::FLAG_FOR_PRINTING);
}
}