win32-printing: Implement JPEG support

This commit is contained in:
Adrian Johnson 2008-11-06 00:17:53 +10:30
parent 29621bd399
commit 248dd97075
2 changed files with 85 additions and 9 deletions

View file

@ -1,7 +1,7 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2007 Adrian Johnson
* Copyright © 2007, 2008 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -52,6 +52,7 @@
#include "cairo-win32-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-jpeg-info-private.h"
#include <windows.h>
@ -75,6 +76,10 @@
# define GRADIENT_FILL_RECT_H 0x00
#endif
#if !defined(CHECKJPEGFORMAT)
# define CHECKJPEGFORMAT 0x1017
#endif
#define PELS_72DPI ((LONG)(72. / 0.0254))
static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
@ -99,6 +104,16 @@ _cairo_win32_printing_surface_init_ps_mode (cairo_win32_surface_t *surface)
surface->flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT;
}
static void
_cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface)
{
DWORD word;
word = CHECKJPEGFORMAT;
if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
}
static cairo_int_status_t
analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern)
{
@ -486,6 +501,48 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
return status;
}
static cairo_int_status_t
_cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t *surface,
cairo_surface_t *source,
const unsigned char **jpeg_data,
unsigned int *jpeg_length,
int *jpeg_width,
int *jpeg_height)
{
const unsigned char *mime_data;
unsigned int mime_data_length;
cairo_jpeg_info_t info;
cairo_int_status_t status;
DWORD result;
if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG))
return CAIRO_INT_STATUS_UNSUPPORTED;
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
&mime_data, &mime_data_length);
if (mime_data == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_jpeg_get_info (mime_data, mime_data_length, &info);
if (status)
return status;
result = 0;
if (ExtEscape(surface->dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data,
sizeof(result), (char *) &result) <= 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (result != 1)
return CAIRO_INT_STATUS_UNSUPPORTED;
*jpeg_data = mime_data;
*jpeg_length = mime_data_length;
*jpeg_width = info.width;
*jpeg_height = info.height;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surface,
cairo_surface_pattern_t *pattern)
@ -503,6 +560,10 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
int x_tile, y_tile, left, right, top, bottom;
RECT clip;
const cairo_color_t *background_color;
const unsigned char *jpeg_data;
unsigned int jpeg_size;
int jpeg_width, jpeg_height;
cairo_bool_t use_jpeg;
/* If we can't use StretchDIBits with this surface, we can't do anything
* here.
@ -532,7 +593,18 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
goto CLEANUP_IMAGE;
}
if (image->format != CAIRO_FORMAT_RGB24) {
status = _cairo_win32_printing_surface_check_jpeg (surface,
pattern->surface,
&jpeg_data,
&jpeg_size,
&jpeg_width,
&jpeg_height);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
use_jpeg = (status == CAIRO_STATUS_SUCCESS);
if (!use_jpeg && image->format != CAIRO_FORMAT_RGB24) {
cairo_surface_pattern_t opaque_pattern;
opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
@ -577,14 +649,14 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
}
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = opaque_image->width;
bi.bmiHeader.biHeight = -opaque_image->height;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biWidth = use_jpeg ? jpeg_width : opaque_image->width;
bi.bmiHeader.biHeight = use_jpeg ? - jpeg_height : -opaque_image->height;
bi.bmiHeader.biSizeImage = use_jpeg ? jpeg_size : 0;
bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biCompression = use_jpeg ? BI_JPEG : BI_RGB;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
@ -626,9 +698,9 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
opaque_image->height,
0,
0,
opaque_image->width,
opaque_image->height,
opaque_image->data,
use_jpeg ? jpeg_width : opaque_image->width,
use_jpeg ? jpeg_height : opaque_image->height,
use_jpeg ? jpeg_data : opaque_image->data,
&bi,
DIB_RGB_COLORS,
SRCCOPY))
@ -1594,6 +1666,7 @@ cairo_win32_printing_surface_create (HDC hdc)
surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
_cairo_win32_printing_surface_init_ps_mode (surface);
_cairo_win32_printing_surface_init_image_support (surface);
_cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);

View file

@ -117,6 +117,9 @@ enum {
/* Whether we can use GradientFill rectangles with this surface */
CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
/* Whether we can use the CHECKJPEGFORMAT escape function */
CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
};
cairo_status_t