mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 04:08:13 +02:00
[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:
parent
284ed91ee4
commit
ffc16c4be2
8 changed files with 1376 additions and 41 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
1220
src/cairo-win32-printing-surface.c
Normal file
1220
src/cairo-win32-printing-surface.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue