1changeset:   29338:f2a10f325734
2tag:         qtip
3tag:         tip
4tag:         win32-raster-mask2.patch
5tag:         qbase
6user:        Jeff Muizelaar <jmuizelaar@mozilla.com>
7date:        Mon Jun 22 14:26:07 2009 -0400
8summary:     imported patch win32-raster-mask2.patch
9
10diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c
11--- a/gfx/cairo/cairo/src/cairo-image-surface.c
12+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
13@@ -1232,27 +1232,27 @@ typedef struct _cairo_image_surface_span
14     cairo_composite_rectangles_t composite_rectangles;
15 } cairo_image_surface_span_renderer_t;
16
17-static cairo_status_t
18-_cairo_image_surface_span_renderer_render_row (
19-    void				*abstract_renderer,
20+void
21+_cairo_image_surface_span_render_row (
22     int					 y,
23     const cairo_half_open_span_t	*spans,
24-    unsigned				 num_spans)
25+    unsigned				 num_spans,
26+    cairo_image_surface_t               *mask,
27+    const cairo_composite_rectangles_t  *rects)
28 {
29-    cairo_image_surface_span_renderer_t *renderer = abstract_renderer;
30-    int xmin = renderer->composite_rectangles.mask.x;
31-    int xmax = xmin + renderer->composite_rectangles.width;
32+    int xmin = rects->mask.x;
33+    int xmax = xmin + rects->width;
34     uint8_t *row;
35     int prev_x = xmin;
36     int prev_alpha = 0;
37     unsigned i;
38
39     /* Make sure we're within y-range. */
40-    y -= renderer->composite_rectangles.mask.y;
41-    if (y < 0 || y >= renderer->composite_rectangles.height)
42+    y -= rects->mask.y;
43+    if (y < 0 || y >= rects->height)
44 	return CAIRO_STATUS_SUCCESS;
45
46-    row = (uint8_t*)(renderer->mask->data) + y*(size_t)renderer->mask->stride - xmin;
47+    row = (uint8_t*)(mask->data) + y*(size_t)mask->stride - xmin;
48
49     /* Find the first span within x-range. */
50     for (i=0; i < num_spans && spans[i].x < xmin; i++) {}
51@@ -1286,7 +1286,17 @@ _cairo_image_surface_span_renderer_rende
52     if (prev_alpha != 0 && prev_x < xmax) {
53 	memset(row + prev_x, prev_alpha, xmax - prev_x);
54     }
55+}
56
57+static cairo_status_t
58+_cairo_image_surface_span_renderer_render_row (
59+    void				*abstract_renderer,
60+    int					 y,
61+    const cairo_half_open_span_t	*spans,
62+    unsigned				 num_spans)
63+{
64+    cairo_image_surface_span_renderer_t *renderer = abstract_renderer;
65+    _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles);
66     return CAIRO_STATUS_SUCCESS;
67 }
68
69diff --git a/gfx/cairo/cairo/src/cairo-tor-scan-converter.c b/gfx/cairo/cairo/src/cairo-tor-scan-converter.c
70--- a/gfx/cairo/cairo/src/cairo-tor-scan-converter.c
71+++ b/gfx/cairo/cairo/src/cairo-tor-scan-converter.c
72@@ -295,9 +295,9 @@ typedef int grid_area_t;
73 #elif GRID_XY == 15
74 #  define  GRID_AREA_TO_ALPHA(c)  (((c) << 4) + (c))
75 #elif GRID_XY == 2*256*15
76-#  define  GRID_AREA_TO_ALPHA(c)  (((c) + ((c)<<4)) >> 9)
77+#  define  GRID_AREA_TO_ALPHA(c)  (((c) + ((c)<<4) + 256) >> 9)
78 #else
79-#  define  GRID_AREA_TO_ALPHA(c)  ((c)*255 / GRID_XY) /* tweak me for rounding */
80+#  define  GRID_AREA_TO_ALPHA(c)  (((c)*255 + GRID_XY/2) / GRID_XY)
81 #endif
82
83 #define UNROLL3(x) x x x
84diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
85--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
86+++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
87@@ -2048,6 +2048,148 @@ _cairo_win32_surface_reset (void *abstra
88     return CAIRO_STATUS_SUCCESS;
89 }
90
91+typedef struct _cairo_win32_surface_span_renderer {
92+    cairo_span_renderer_t base;
93+
94+    cairo_operator_t op;
95+    const cairo_pattern_t *pattern;
96+    cairo_antialias_t antialias;
97+
98+    cairo_image_surface_t *mask;
99+    cairo_win32_surface_t *dst;
100+
101+    cairo_composite_rectangles_t composite_rectangles;
102+} cairo_win32_surface_span_renderer_t;
103+
104+static cairo_status_t
105+_cairo_win32_surface_span_renderer_render_row (
106+    void				*abstract_renderer,
107+    int					 y,
108+    const cairo_half_open_span_t	*spans,
109+    unsigned				 num_spans)
110+{
111+    cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
112+    _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles);
113+    return CAIRO_STATUS_SUCCESS;
114+}
115+
116+static void
117+_cairo_win32_surface_span_renderer_destroy (void *abstract_renderer)
118+{
119+    cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
120+    if (!renderer) return;
121+
122+    if (renderer->mask != NULL)
123+	cairo_surface_destroy (&renderer->mask->base);
124+
125+    free (renderer);
126+}
127+
128+static cairo_status_t
129+_cairo_win32_surface_span_renderer_finish (void *abstract_renderer)
130+{
131+    cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
132+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
133+
134+    if (renderer->pattern == NULL || renderer->mask == NULL)
135+	return CAIRO_STATUS_SUCCESS;
136+
137+    status = cairo_surface_status (&renderer->mask->base);
138+    if (status == CAIRO_STATUS_SUCCESS) {
139+	cairo_composite_rectangles_t *rects = &renderer->composite_rectangles;
140+	cairo_win32_surface_t *dst = renderer->dst;
141+	cairo_pattern_t *mask_pattern = cairo_pattern_create_for_surface (&renderer->mask->base);
142+	/* composite onto the image surface directly if we can */
143+	if (dst->image) {
144+	    GdiFlush();
145+
146+	    status = dst->image->backend->composite (renderer->op,
147+		    renderer->pattern, mask_pattern, dst->image,
148+		    rects->src.x,
149+		    rects->src.y,
150+		    0, 0,		/* mask.x, mask.y */
151+		    rects->dst.x, rects->dst.y,
152+		    rects->width, rects->height);
153+	} else {
154+	    /* otherwise go through the fallback_composite path which
155+	     * will do the appropriate surface acquisition */
156+	    status = _cairo_surface_fallback_composite (
157+		    renderer->op,
158+		    renderer->pattern, mask_pattern, dst,
159+		    rects->src.x,
160+		    rects->src.y,
161+		    0, 0,		/* mask.x, mask.y */
162+		    rects->dst.x, rects->dst.y,
163+		    rects->width, rects->height);
164+	}
165+	cairo_pattern_destroy (mask_pattern);
166+
167+    }
168+    if (status != CAIRO_STATUS_SUCCESS)
169+	return _cairo_span_renderer_set_error (abstract_renderer,
170+					       status);
171+    return CAIRO_STATUS_SUCCESS;
172+}
173+
174+static cairo_bool_t
175+_cairo_win32_surface_check_span_renderer (cairo_operator_t	  op,
176+					  const cairo_pattern_t  *pattern,
177+					  void			 *abstract_dst,
178+					  cairo_antialias_t	  antialias,
179+					  const cairo_composite_rectangles_t *rects)
180+{
181+    (void) op;
182+    (void) pattern;
183+    (void) abstract_dst;
184+    (void) antialias;
185+    (void) rects;
186+    return TRUE;
187+}
188+
189+static cairo_span_renderer_t *
190+_cairo_win32_surface_create_span_renderer (cairo_operator_t	 op,
191+					   const cairo_pattern_t  *pattern,
192+					   void			*abstract_dst,
193+					   cairo_antialias_t	 antialias,
194+					   const cairo_composite_rectangles_t *rects)
195+{
196+    cairo_win32_surface_t *dst = abstract_dst;
197+    cairo_win32_surface_span_renderer_t *renderer
198+	= calloc(1, sizeof(*renderer));
199+    cairo_status_t status;
200+    int width = rects->width;
201+    int height = rects->height;
202+
203+    if (renderer == NULL)
204+	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
205+
206+    renderer->base.destroy = _cairo_win32_surface_span_renderer_destroy;
207+    renderer->base.finish = _cairo_win32_surface_span_renderer_finish;
208+    renderer->base.render_row =
209+	_cairo_win32_surface_span_renderer_render_row;
210+    renderer->op = op;
211+    renderer->pattern = pattern;
212+    renderer->antialias = antialias;
213+    renderer->dst = dst;
214+
215+    renderer->composite_rectangles = *rects;
216+
217+    /* TODO: support rendering to A1 surfaces (or: go add span
218+     * compositing to pixman.) */
219+    renderer->mask = (cairo_image_surface_t *)
220+	cairo_image_surface_create (CAIRO_FORMAT_A8,
221+				    width, height);
222+
223+    status = cairo_surface_status (&renderer->mask->base);
224+
225+    if (status != CAIRO_STATUS_SUCCESS) {
226+	_cairo_win32_surface_span_renderer_destroy (renderer);
227+	return _cairo_span_renderer_create_in_error (status);
228+    }
229+    return &renderer->base;
230+}
231+
232+
233 static const cairo_surface_backend_t cairo_win32_surface_backend = {
234     CAIRO_SURFACE_TYPE_WIN32,
235     _cairo_win32_surface_create_similar,
236@@ -2060,8 +2202,8 @@ static const cairo_surface_backend_t cai
237     _cairo_win32_surface_composite,
238     _cairo_win32_surface_fill_rectangles,
239     NULL, /* composite_trapezoids */
240-    NULL, /* create_span_renderer */
241-    NULL, /* check_span_renderer */
242+    _cairo_win32_surface_create_span_renderer,
243+    _cairo_win32_surface_check_span_renderer,
244     NULL, /* copy_page */
245     NULL, /* show_page */
246     _cairo_win32_surface_set_clip_region,
247diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h
248--- a/gfx/cairo/cairo/src/cairoint.h
249+++ b/gfx/cairo/cairo/src/cairoint.h
250@@ -2193,6 +2193,12 @@ _cairo_image_surface_set_clip_region (vo
251 cairo_private cairo_image_surface_t *
252 _cairo_image_surface_coerce (cairo_image_surface_t	*surface,
253 			     cairo_format_t		 format);
254+cairo_private void
255+_cairo_image_surface_span_render_row (int				 y,
256+				      const cairo_half_open_span_t	 *spans,
257+				      unsigned				 num_spans,
258+				      cairo_image_surface_t              *mask,
259+				      const cairo_composite_rectangles_t *rects);
260
261 cairo_private cairo_image_transparency_t
262 _cairo_image_analyze_transparency (cairo_image_surface_t      *image);
263