summaryrefslogtreecommitdiff
path: root/src/cairo-win32-printing-surface.c
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2008-11-06 00:17:53 +1030
committerAdrian Johnson <ajohnson@redneon.com>2008-11-06 00:21:35 +1030
commit248dd97075b50cd91619022098ed5dd35a66b5df (patch)
tree73496f28868ab0b190e72491650e706f79e44789 /src/cairo-win32-printing-surface.c
parent29621bd3995c5269fd6f73ab501383433bd29768 (diff)
win32-printing: Implement JPEG support
Diffstat (limited to 'src/cairo-win32-printing-surface.c')
-rw-r--r--src/cairo-win32-printing-surface.c91
1 files changed, 82 insertions, 9 deletions
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 94bbc28a..34b31c7d 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -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);