[win32] Add win32 printing surface

Add win32 surface intended for use with printer DCs; GDI will be used
as much as possible, and the surface will be a paginated surface
that supports fine-grained fallback.

(Original work from Adrian Johnson; additional fixes by me.)
This commit is contained in:
Vladimir Vukicevic 2007-08-29 16:25:58 -07:00
parent 284ed91ee4
commit ffc16c4be2
8 changed files with 1376 additions and 41 deletions

View file

@ -81,7 +81,7 @@ endif
libcairo_win32_sources =
if CAIRO_HAS_WIN32_SURFACE
libcairo_win32_headers = cairo-win32.h
libcairo_win32_sources += cairo-win32-surface.c cairo-win32-private.h
libcairo_win32_sources += cairo-win32-surface.c cairo-win32-printing-surface.c cairo-win32-private.h
backend_pkgconfigs += cairo-win32.pc
endif
# This is not really a separate conditional. Is TRUE iff the previous one is.

View file

@ -300,22 +300,27 @@ _paint_page (cairo_paginated_surface_t *surface)
return status;
}
/* Finer grained fallbacks are currently only supported for PDF
* and PostScript surfaces */
if (surface->target->type == CAIRO_SURFACE_TYPE_PDF ||
surface->target->type == CAIRO_SURFACE_TYPE_PS) {
has_supported = _cairo_analysis_surface_has_supported (analysis);
has_page_fallback = FALSE;
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
} else {
if (_cairo_analysis_surface_has_unsupported (analysis)) {
has_supported = FALSE;
has_page_fallback = TRUE;
} else {
has_supported = TRUE;
has_page_fallback = FALSE;
}
has_finegrained_fallback = FALSE;
/* Finer grained fallbacks are currently only supported for some
* surface types */
switch (surface->target->type) {
case CAIRO_SURFACE_TYPE_PDF:
case CAIRO_SURFACE_TYPE_PS:
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
has_supported = _cairo_analysis_surface_has_supported (analysis);
has_page_fallback = FALSE;
has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
break;
default:
if (_cairo_analysis_surface_has_unsupported (analysis)) {
has_supported = FALSE;
has_page_fallback = TRUE;
} else {
has_supported = TRUE;
has_page_fallback = FALSE;
}
has_finegrained_fallback = FALSE;
break;
}
if (has_supported) {

View file

@ -326,12 +326,7 @@ _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font,
{
XFORM xform;
xform.eM11 = scaled_font->logical_to_device.xx;
xform.eM21 = scaled_font->logical_to_device.xy;
xform.eM12 = scaled_font->logical_to_device.yx;
xform.eM22 = scaled_font->logical_to_device.yy;
xform.eDx = scaled_font->logical_to_device.x0;
xform.eDy = scaled_font->logical_to_device.y0;
_cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform);
if (!SetWorldTransform (hdc, &xform))
return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform");

File diff suppressed because it is too large Load diff

View file

@ -79,10 +79,18 @@ typedef struct _cairo_win32_surface {
/* Surface DC flags */
uint32_t flags;
/* printing surface bits */
cairo_paginated_mode_t paginated_mode;
int clip_saved_dc;
HBRUSH brush, old_brush;
} cairo_win32_surface_t;
/* Surface DC flag values */
enum {
/* If this is a surface created for printing or not */
CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0),
/* Whether the DC is a display DC or not */
CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1),
@ -96,7 +104,15 @@ enum {
CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
/* Whether we can use StretchDIBits with this surface */
CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5)
CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5),
/* Whether we can use GradientFill rectangles with this surface */
CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6),
/* If we should treat all operators other than CLEAR and OVER
* like SOURCE to avoid hitting fallback. Ignored except
* for printing. */
CAIRO_WIN32_SURFACE_IGNORE_OPERATORS = (1<<7)
};
cairo_status_t
@ -105,4 +121,52 @@ _cairo_win32_print_gdi_error (const char *context);
cairo_bool_t
_cairo_surface_is_win32 (cairo_surface_t *surface);
cairo_bool_t
_cairo_surface_is_win32_printing (cairo_surface_t *surface);
cairo_status_t
_cairo_win32_surface_finish (void *abstract_surface);
cairo_int_status_t
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle);
uint32_t
_cairo_win32_flags_for_dc (HDC dc);
cairo_int_status_t
_cairo_win32_surface_show_glyphs (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
cairo_surface_t *
_cairo_win32_surface_create_similar (void *abstract_src,
cairo_content_t content,
int width,
int height);
cairo_status_t
_cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out);
static inline void
_cairo_matrix_to_win32_xform (const cairo_matrix_t *m,
XFORM *xform)
{
xform->eM11 = (FLOAT) m->xx;
xform->eM21 = (FLOAT) m->xy;
xform->eM12 = (FLOAT) m->yx;
xform->eM22 = (FLOAT) m->yy;
xform->eDx = (FLOAT) m->x0;
xform->eDy = (FLOAT) m->y0;
}
#endif /* CAIRO_WIN32_PRIVATE_H */

View file

@ -108,7 +108,7 @@ _cairo_win32_print_gdi_error (const char *context)
return CAIRO_STATUS_NO_MEMORY;
}
static uint32_t
uint32_t
_cairo_win32_flags_for_dc (HDC dc)
{
uint32_t flags = 0;
@ -426,7 +426,7 @@ _cairo_win32_surface_create_similar_internal (void *abstract_src,
return (cairo_surface_t*) new_surf;
}
static cairo_surface_t *
cairo_surface_t *
_cairo_win32_surface_create_similar (void *abstract_src,
cairo_content_t content,
int width,
@ -435,7 +435,50 @@ _cairo_win32_surface_create_similar (void *abstract_src,
return _cairo_win32_surface_create_similar_internal (abstract_src, content, width, height, FALSE);
}
static cairo_status_t
cairo_status_t
_cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
cairo_content_t src_content;
cairo_surface_t *new_surface;
cairo_status_t status;
cairo_pattern_union_t pattern;
src_content = cairo_surface_get_content(src);
new_surface =
_cairo_win32_surface_create_similar_internal (abstract_surface, src_content, width, height, FALSE);
if (cairo_surface_status(new_surface))
return cairo_surface_status(new_surface);
_cairo_pattern_init_for_surface (&pattern.surface, src);
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL,
new_surface,
src_x, src_y,
0, 0,
0, 0,
width, height);
_cairo_pattern_fini (&pattern.base);
if (status == CAIRO_STATUS_SUCCESS)
*clone_out = new_surface;
else
cairo_surface_destroy (new_surface);
return status;
}
cairo_status_t
_cairo_win32_surface_finish (void *abstract_surface)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -476,9 +519,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* We are blitting -from- surface, so we need to check if it
* supports BitBlt. I believe any surface can be used as a
* BitBlt destination. */
/* Only BitBlt if the source surface supports it. */
if ((surface->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
BitBlt (local->dc,
0, 0,
@ -1474,7 +1515,7 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
}
}
static cairo_int_status_t
cairo_int_status_t
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
{
@ -1493,7 +1534,7 @@ _cairo_win32_surface_flush (void *abstract_surface)
#define STACK_GLYPH_SIZE 256
static cairo_int_status_t
cairo_int_status_t
_cairo_win32_surface_show_glyphs (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
@ -1536,8 +1577,10 @@ _cairo_win32_surface_show_glyphs (void *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
/* If we have a fallback mask clip set on the dst, we have
* to go through the fallback path */
if (dst->base.clip &&
* to go through the fallback path, but only if we're not
* doing this for printing */
if (dst->base.clip &&
!(dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) &&
(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
dst->base.clip->surface != NULL))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1692,6 +1735,8 @@ cairo_win32_surface_create (HDC hdc)
surface->bitmap = NULL;
surface->is_dib = FALSE;
surface->saved_dc_bitmap = NULL;
surface->brush = NULL;
surface->old_brush = NULL;
surface->clip_rect.x = (int16_t) rect.left;
surface->clip_rect.y = (int16_t) rect.top;
@ -1713,6 +1758,7 @@ cairo_win32_surface_create (HDC hdc)
surface->extents = surface->clip_rect;
surface->flags = _cairo_win32_flags_for_dc (surface->dc);
surface->clip_saved_dc = 0;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
_cairo_content_from_format (format));
@ -1807,7 +1853,9 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
* _cairo_surface_is_win32:
* @surface: a #cairo_surface_t
*
* Checks if a surface is an #cairo_win32_surface_t
* Checks if a surface is a win32 surface. This will
* return False if this is a win32 printing surface; use
* _cairo_surface_is_win32_printing() to check for that.
*
* Return value: True if the surface is an win32 surface
**/
@ -1833,10 +1881,8 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
{
cairo_win32_surface_t *winsurf;
if (surface == NULL)
return NULL;
if (!_cairo_surface_is_win32(surface))
if (!_cairo_surface_is_win32(surface) &&
!_cairo_surface_is_win32_printing(surface))
return NULL;
winsurf = (cairo_win32_surface_t *) surface;
@ -1898,7 +1944,7 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
_cairo_win32_surface_release_source_image,
_cairo_win32_surface_acquire_dest_image,
_cairo_win32_surface_release_dest_image,
NULL, /* clone_similar */
_cairo_win32_surface_clone_similar,
_cairo_win32_surface_composite,
_cairo_win32_surface_fill_rectangles,
NULL, /* composite_trapezoids */

View file

@ -47,6 +47,9 @@ CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_win32_surface_create (HDC hdc);
cairo_public cairo_surface_t *
cairo_win32_printing_surface_create (HDC hdc, cairo_bool_t ignore_operators);
cairo_public cairo_surface_t *
cairo_win32_surface_create_with_ddb (HDC hdc,
cairo_format_t format,

View file

@ -1435,6 +1435,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb
* @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg
* @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2
* @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
*
* #cairo_surface_type_t is used to describe the type of a given
* surface. The surface types are also known as "backends" or "surface
@ -1471,7 +1472,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_BEOS,
CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG,
CAIRO_SURFACE_TYPE_OS2
CAIRO_SURFACE_TYPE_OS2,
CAIRO_SURFACE_TYPE_WIN32_PRINTING
} cairo_surface_type_t;
cairo_public cairo_surface_type_t