[cairo-commit] 5 commits - src/cairo-reference-count-private.h src/cairo-win32.h src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c
Vladimir Vukicevic
vladimir at kemper.freedesktop.org
Tue Oct 9 14:28:33 PDT 2007
src/cairo-reference-count-private.h | 2
src/cairo-win32-printing-surface.c | 16 ---
src/cairo-win32-private.h | 5 -
src/cairo-win32-surface.c | 175 +++++++++++++++++++++---------------
src/cairo-win32.h | 3
5 files changed, 113 insertions(+), 88 deletions(-)
New commits:
diff-tree be7d1f0f8f84ddac9e8c7dda4aa39f88806a5e39 (from 712c3cda44d7023316b93a1241e66aabde15d668)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Oct 9 14:27:53 2007 -0700
Simplify CAIRO_REFERENCE_COUNT_INVALID macro
MSVC doesn't like the previous anonymous structure/cast, so simplify
to just a bare {} structure for use as an initializer.
diff --git a/src/cairo-reference-count-private.h b/src/cairo-reference-count-private.h
index 2d1d81b..aef8a1f 100644
--- a/src/cairo-reference-count-private.h
+++ b/src/cairo-reference-count-private.h
@@ -55,7 +55,7 @@ typedef struct {
#define CAIRO_REFERENCE_COUNT_SET_VALUE(RC, VALUE) _cairo_atomic_int_set (&(RC)->ref_count, (VALUE))
#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1)
-#define CAIRO_REFERENCE_COUNT_INVALID ((cairo_reference_count_t) {CAIRO_REFERENCE_COUNT_INVALID_VALUE})
+#define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE}
#define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE)
diff-tree 712c3cda44d7023316b93a1241e66aabde15d668 (from c99d33b10e84883ade1402c3c1d1efdb4b46f66e)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Oct 9 13:56:51 2007 -0700
[win32] reduce GDI object usage
Only create region objects if they're necessary; this significantly reduces
the number of GDI objects in use by cairo surfaces.
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 2f31697..21336de 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -358,11 +358,7 @@ _cairo_win32_surface_create_for_dc (HDC
surface->clip_rect.width = width;
surface->clip_rect.height = height;
- surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
- if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
- DeleteObject(surface->saved_clip);
- surface->saved_clip = NULL;
- }
+ surface->saved_clip = NULL;
surface->extents = surface->clip_rect;
@@ -409,13 +405,9 @@ _cairo_win32_surface_create_similar_inte
/* otherwise, create a ddb */
HBITMAP ddb = CreateCompatibleBitmap (src->dc, width, height);
HDC ddb_dc = CreateCompatibleDC (src->dc);
- HRGN crgn = CreateRectRgn (0, 0, width, height);
HBITMAP saved_dc_bitmap;
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
- SelectClipRgn (ddb_dc, crgn);
-
- DeleteObject (crgn);
new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
new_surf->bitmap = ddb;
@@ -486,16 +478,33 @@ _cairo_win32_surface_finish (void *abstr
if (surface->image)
cairo_surface_destroy (surface->image);
- if (surface->saved_clip)
- DeleteObject (surface->saved_clip);
-
/* If we created the Bitmap and DC, destroy them */
if (surface->bitmap) {
SelectObject (surface->dc, surface->saved_dc_bitmap);
DeleteObject (surface->bitmap);
DeleteDC (surface->dc);
+ } else {
+ /* otherwise, restore the old clip region on the DC */
+ SelectClipRgn (surface->dc, surface->saved_clip);
+
+ if (surface->saved_clip == NULL) {
+ /* We never had a clip region, so just restore the clip
+ * to the bounds. */
+ if (surface->clip_rect.width != 0 &&
+ surface->clip_rect.height != 0)
+ {
+ IntersectClipRect (surface->dc,
+ surface->clip_rect.x,
+ surface->clip_rect.y,
+ surface->clip_rect.x + surface->clip_rect.width,
+ surface->clip_rect.y + surface->clip_rect.height);
+ }
+ }
}
+ if (surface->saved_clip)
+ DeleteObject (surface->saved_clip);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -1422,7 +1431,7 @@ _cairo_win32_surface_set_clip_region (vo
cairo_region_t *region)
{
cairo_win32_surface_t *surface = abstract_surface;
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
/* If we are in-memory, then we set the clip on the image surface
* as well as on the underlying GDI surface.
@@ -1445,12 +1454,10 @@ _cairo_win32_surface_set_clip_region (vo
if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");
- return CAIRO_STATUS_SUCCESS;
-
+ status = CAIRO_STATUS_SUCCESS;
} else {
cairo_rectangle_int_t extents;
cairo_box_int_t *boxes;
- cairo_status_t status;
int num_boxes;
RGNDATA *data;
size_t data_size;
@@ -1465,56 +1472,72 @@ _cairo_win32_surface_set_clip_region (vo
if (status)
return status;
- data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT);
- data = malloc (data_size);
- if (!data) {
- _cairo_region_boxes_fini (region, boxes);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
- rects = (RECT *)data->Buffer;
+ if (num_boxes == 1 &&
+ boxes[0].p1.x == 0 &&
+ boxes[0].p1.y == 0 &&
+ boxes[0].p2.x == surface->extents.width &&
+ boxes[0].p2.y == surface->extents.height)
+ {
+ gdi_region = NULL;
- data->rdh.dwSize = sizeof (RGNDATAHEADER);
- data->rdh.iType = RDH_RECTANGLES;
- data->rdh.nCount = num_boxes;
- data->rdh.nRgnSize = num_boxes * sizeof (RECT);
- data->rdh.rcBound.left = extents.x;
- data->rdh.rcBound.top = extents.y;
- data->rdh.rcBound.right = extents.x + extents.width;
- data->rdh.rcBound.bottom = extents.y + extents.height;
-
- for (i = 0; i < num_boxes; i++) {
- rects[i].left = boxes[i].p1.x;
- rects[i].top = boxes[i].p1.y;
- rects[i].right = boxes[i].p2.x;
- rects[i].bottom = boxes[i].p2.y;
- }
+ SelectClipRgn (surface->dc, NULL);
+ IntersectClipRect (surface->dc,
+ boxes[0].p1.x,
+ boxes[0].p1.y,
+ boxes[0].p2.x,
+ boxes[0].p2.y);
- _cairo_region_boxes_fini (region, boxes);
+ _cairo_region_boxes_fini (region, boxes);
+ } else {
+ data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT);
+ data = malloc (data_size);
+ if (!data) {
+ _cairo_region_boxes_fini (region, boxes);
+ return _cairo_error(CAIRO_STATUS_NO_MEMORY);
+ }
+ rects = (RECT *)data->Buffer;
- gdi_region = ExtCreateRegion (NULL, data_size, data);
- free (data);
+ data->rdh.dwSize = sizeof (RGNDATAHEADER);
+ data->rdh.iType = RDH_RECTANGLES;
+ data->rdh.nCount = num_boxes;
+ data->rdh.nRgnSize = num_boxes * sizeof (RECT);
+ data->rdh.rcBound.left = extents.x;
+ data->rdh.rcBound.top = extents.y;
+ data->rdh.rcBound.right = extents.x + extents.width;
+ data->rdh.rcBound.bottom = extents.y + extents.height;
+
+ for (i = 0; i < num_boxes; i++) {
+ rects[i].left = boxes[i].p1.x;
+ rects[i].top = boxes[i].p1.y;
+ rects[i].right = boxes[i].p2.x;
+ rects[i].bottom = boxes[i].p2.y;
+ }
- if (!gdi_region)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_region_boxes_fini (region, boxes);
- /* Combine the new region with the original clip */
+ gdi_region = ExtCreateRegion (NULL, data_size, data);
+ free (data);
- if (surface->saved_clip) {
- if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
- goto FAIL;
- }
+ if (!gdi_region)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
- goto FAIL;
+ /* Combine the new region with the original clip */
+ if (surface->saved_clip) {
+ if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
+ status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
+ }
- DeleteObject (gdi_region);
- return CAIRO_STATUS_SUCCESS;
+ /* Then select the new clip region into our surface if everything went ok */
+ if (status == CAIRO_STATUS_SUCCESS) {
+ if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
+ status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
+ }
- FAIL:
- status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
- DeleteObject (gdi_region);
- return status;
+ DeleteObject (gdi_region);
+ }
}
+
+ return status;
}
cairo_int_status_t
@@ -1693,10 +1716,12 @@ cairo_win32_surface_create (HDC hdc)
RECT rect;
int depth;
cairo_format_t format;
+ int clipBoxType;
/* Try to figure out the drawing bounds for the Device context
*/
- if (GetClipBox (hdc, &rect) == ERROR) {
+ clipBoxType = GetClipBox (hdc, &rect);
+ if (clipBoxType == ERROR) {
_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
/* XXX: Can we make a more reasonable guess at the error cause here? */
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1745,16 +1770,15 @@ cairo_win32_surface_create (HDC hdc)
surface->clip_rect.width = (uint16_t) (rect.right - rect.left);
surface->clip_rect.height = (uint16_t) (rect.bottom - rect.top);
- if (surface->clip_rect.width == 0 ||
- surface->clip_rect.height == 0)
- {
- surface->saved_clip = NULL;
- } else {
+ if (clipBoxType == COMPLEXREGION) {
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (GetClipRgn (hdc, surface->saved_clip) == 0) {
+ /* this should never happen */
DeleteObject(surface->saved_clip);
surface->saved_clip = NULL;
}
+ } else {
+ surface->saved_clip = NULL;
}
surface->extents = surface->clip_rect;
@@ -1814,7 +1838,6 @@ cairo_win32_surface_create_with_ddb (HDC
cairo_win32_surface_t *new_surf;
HBITMAP ddb;
HDC screen_dc, ddb_dc;
- HRGN crgn;
HBITMAP saved_dc_bitmap;
if (format != CAIRO_FORMAT_RGB24)
@@ -1834,7 +1857,7 @@ cairo_win32_surface_create_with_ddb (HDC
ddb_dc = CreateCompatibleDC (hdc);
if (ddb_dc == NULL) {
_cairo_win32_print_gdi_error("CreateCompatibleDC");
- new_surf = NIL_SURFACE;
+ new_surf = (cairo_win32_surface_t*) NIL_SURFACE;
goto FINISH;
}
@@ -1847,16 +1870,12 @@ cairo_win32_surface_create_with_ddb (HDC
* video memory is probably exhausted.
*/
_cairo_win32_print_gdi_error("CreateCompatibleBitmap");
- new_surf = NIL_SURFACE;
+ new_surf = (cairo_win32_surface_t*) NIL_SURFACE;
goto FINISH;
}
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
- crgn = CreateRectRgn (0, 0, width, height);
- SelectClipRgn (ddb_dc, crgn);
- DeleteObject (crgn);
-
new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
new_surf->bitmap = ddb;
new_surf->saved_dc_bitmap = saved_dc_bitmap;
diff-tree c99d33b10e84883ade1402c3c1d1efdb4b46f66e (from 4dbf495515d6de933de7f567b935c5fdceed5f6f)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Oct 2 10:54:44 2007 -0700
[win32] return a nil surface, not NULL
Missed an error return
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 9a6e715..2f31697 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1818,7 +1818,7 @@ cairo_win32_surface_create_with_ddb (HDC
HBITMAP saved_dc_bitmap;
if (format != CAIRO_FORMAT_RGB24)
- return NULL;
+ return NIL_SURFACE;
/* XXX handle these eventually
format != CAIRO_FORMAT_A8 ||
format != CAIRO_FORMAT_A1)
diff-tree 4dbf495515d6de933de7f567b935c5fdceed5f6f (from 61ba63f3a0947bc89310f04e9bc1694fb6451c11)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Oct 2 10:48:59 2007 -0700
[win32] report error correctly if CreateCompatibleBitmap fails
These errors were being dropped on the floor, leading to
rendering errors in out of video memory conditions.
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 7b94325..9a6e715 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1831,8 +1831,25 @@ cairo_win32_surface_create_with_ddb (HDC
screen_dc = NULL;
}
- ddb = CreateCompatibleBitmap (hdc, width, height);
ddb_dc = CreateCompatibleDC (hdc);
+ if (ddb_dc == NULL) {
+ _cairo_win32_print_gdi_error("CreateCompatibleDC");
+ new_surf = NIL_SURFACE;
+ goto FINISH;
+ }
+
+ ddb = CreateCompatibleBitmap (hdc, width, height);
+ if (ddb == NULL) {
+ DeleteDC (ddb_dc);
+
+ /* Note that if an app actually does hit this out of memory
+ * condition, it's going to have lots of other issues, as
+ * video memory is probably exhausted.
+ */
+ _cairo_win32_print_gdi_error("CreateCompatibleBitmap");
+ new_surf = NIL_SURFACE;
+ goto FINISH;
+ }
saved_dc_bitmap = SelectObject (ddb_dc, ddb);
@@ -1845,6 +1862,7 @@ cairo_win32_surface_create_with_ddb (HDC
new_surf->saved_dc_bitmap = saved_dc_bitmap;
new_surf->is_dib = FALSE;
+FINISH:
if (screen_dc)
ReleaseDC (NULL, screen_dc);
diff-tree 61ba63f3a0947bc89310f04e9bc1694fb6451c11 (from b12ed375cf7ad02a30324616e121a1e9ab8998cb)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Fri Sep 21 11:18:17 2007 -0700
[win32] remove ignore_operators flag from win32 printing surface
Remove the ignore_operators fallback-avoiding workaround; if apps
want that same behaviour, they'll have to implement it themselves
by taking care when calling cairo_set_operator().
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 839f3cd..fd8efc1 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -147,11 +147,10 @@ _cairo_win32_printing_surface_analyze_op
op == CAIRO_OPERATOR_CLEAR)
return CAIRO_STATUS_SUCCESS;
- /* If IGNORE_OPERATORS was set, then we pretend everything is
- * OVER/SOURCE. Otherwise, we go to fallback.
+ /* If the operation is anything other than CLEAR, SOURCE, or
+ * OVER, we have to go to fallback.
*/
- if (!(surface->flags & CAIRO_WIN32_SURFACE_IGNORE_OPERATORS) &&
- op != CAIRO_OPERATOR_OVER)
+ if (op != CAIRO_OPERATOR_OVER)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
@@ -1084,8 +1083,6 @@ _cairo_win32_printing_surface_set_pagina
/**
* cairo_win32_printing_surface_create:
* @hdc: the DC to create a surface for
- * @ignore_operators: whether operators other than CLEAR and OVER
- * should be treated as SOURCE
*
* Creates a cairo surface that targets the given DC. The DC will be
* queried for its initial clip extents, and this will be used as the
@@ -1097,13 +1094,10 @@ _cairo_win32_printing_surface_set_pagina
* provide correct complex renderinf behaviour; show_page() and
* associated methods must be used for correct output.
*
- * If ignore_operators is TRUE, the rendering may be incorrect;
- * however, the chances of hitting fallback code are much reduced.
- *
* Return value: the newly created surface
**/
cairo_surface_t *
-cairo_win32_printing_surface_create (HDC hdc, cairo_bool_t ignore_operators)
+cairo_win32_printing_surface_create (HDC hdc)
{
cairo_win32_surface_t *surface;
RECT rect;
@@ -1155,8 +1149,6 @@ cairo_win32_printing_surface_create (HDC
surface->flags = _cairo_win32_flags_for_dc (surface->dc);
surface->flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING;
- if (ignore_operators)
- surface->flags |= CAIRO_WIN32_SURFACE_IGNORE_OPERATORS;
surface->clip_saved_dc = 0;
_cairo_win32_printing_surface_init_ps_mode (surface);
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 3410b34..eddde36 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -108,11 +108,6 @@ enum {
/* 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
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 43ddf12..933133f 100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
@@ -48,7 +49,7 @@ 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_win32_printing_surface_create (HDC hdc);
cairo_public cairo_surface_t *
cairo_win32_surface_create_with_ddb (HDC hdc,
More information about the cairo-commit
mailing list