[Spice-devel] [PATCH 26/30] Covert cairo canvas put_image() to pixman

Alexander Larsson alexl at redhat.com
Thu Feb 18 12:58:52 PST 2010


---
 common/cairo_canvas.c |  119 +++++++++++++++---------------------------------
 1 files changed, 37 insertions(+), 82 deletions(-)

diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
index 9e61a4f..46956aa 100644
--- a/common/cairo_canvas.c
+++ b/common/cairo_canvas.c
@@ -1051,106 +1051,61 @@ void canvas_draw_copy(CairoCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, Spi
 }
 
 #ifdef WIN32
-void canvas_put_image(CairoCanvas *canvas, HDC dc, const SpiceRect *dest, const uint8_t *_src_data,
+void canvas_put_image(CairoCanvas *canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data,
                       uint32_t src_width, uint32_t src_height, int src_stride,
                       const QRegion *clip)
 #else
-void canvas_put_image(CairoCanvas *canvas, const SpiceRect *dest, const uint8_t *_src_data,
+void canvas_put_image(CairoCanvas *canvas, const SpiceRect *dest, const uint8_t *src_data,
                       uint32_t src_width, uint32_t src_height, int src_stride,
                       const QRegion *clip)
 #endif
 {
-    cairo_t *cairo = canvas->cairo;
-    cairo_surface_t* surf = NULL;
+    pixman_image_t *src;
     int dest_width;
     int dest_height;
-    uint8_t *src_data = (uint8_t *)_src_data;
-    uint32_t *data;
-    int nstride;
-
-    cairo_save(cairo);
-
-    if (clip) {
-        int num_rects;
-        pixman_box32_t *rects = pixman_region32_rectangles((pixman_region32_t *)clip,
-                                                           &num_rects);
-        const pixman_box32_t *now = rects;
-        const pixman_box32_t *end = rects + num_rects;
-        for (; now < end; now++) {
-            cairo_rectangle(cairo, now->x1, now->y1, now->x2 - now->x1,
-                            now->y2 - now->y1);
-        }
-        cairo_clip(cairo);
-    }
+    double sx, sy;
+    pixman_transform_t transform;
+
+    src = pixman_image_create_bits(PIXMAN_x8r8g8b8,
+                                   src_width,
+                                   src_height,
+                                   (uint32_t*)src_data,
+                                   src_stride);
 
 
+    if (clip)
+        pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip);
+
     dest_width = dest->right - dest->left;
     dest_height = dest->bottom - dest->top;
 
     if (dest_width != src_width || dest_height != src_height) {
-        int x, y;
-        int x_mul = (uint32_t)((src_width << 16) / dest_width);
-        int y_mul = (uint32_t)((src_height << 16) / dest_height);
-        int new_y;
-        int set_y;
-        int nsrc_stride;
-
-        if (src_stride < 0) {
-            nsrc_stride = -src_stride;
-            src_data = src_data - (src_height - 1) * nsrc_stride;
-            nsrc_stride = nsrc_stride / 4;
-        } else {
-            nsrc_stride = src_stride / 4;
-        }
-        if ((dest_width * dest_height) > canvas->private_data_size) {
-            if (canvas->private_data) {
-                free(canvas->private_data);
-                canvas->private_data = NULL;
-                canvas->private_data_size = 0;
-            }
-            canvas->private_data = (uint32_t *)malloc(4 * dest_width * dest_height);
-            if (!canvas->private_data) {
-                return;
-            }
-            canvas->private_data_size = dest_width * dest_height;
-        }
-        if (!clip) {
-            surf = cairo_get_target(cairo);
-            data = (uint32_t *)cairo_image_surface_get_data(surf);
-            nstride = cairo_image_surface_get_stride(surf) / 4;
-            data += dest->top * nstride + dest->left + (dest_height - 1) * nstride;
-        } else {
-            data = (uint32_t *)canvas->private_data;
-            nstride = dest_width;
-            data += (dest_height - 1) * nstride;
-        }
-
-        for (y = 0; y < dest_height; ++y) {
-            int y_mul_stride = -y * nstride;
-            new_y = ((y * y_mul) >> 16);
-            set_y = (new_y * nsrc_stride);
-            for (x = 0; x < dest_width; ++x) {
-                data[y_mul_stride + x] = ((uint32_t *)src_data)[set_y + ((x * x_mul) >> 16)];
-            }
-        }
-        if (clip) {
-            surf = cairo_image_surface_create_for_data((uint8_t *)canvas->private_data,
-                                                       CAIRO_FORMAT_RGB24, dest_width,
-                                                       dest_height, 4 * dest_width);
-        }
-    } else {
-        surf = cairo_image_surface_create_for_data((uint8_t *)src_data, CAIRO_FORMAT_RGB24,
-                                                   src_width, src_height, src_stride);
+        sx = (double)(src_width) / (dest_width);
+        sy = (double)(src_height) / (dest_height);
+
+        pixman_transform_init_scale(&transform,
+                                    pixman_double_to_fixed(sx),
+                                    pixman_double_to_fixed(sy));
+        pixman_image_set_transform (src, &transform);
+        pixman_image_set_filter (src,
+                                 PIXMAN_FILTER_NEAREST,
+                                 NULL, 0);
     }
 
-    if (clip || !(dest_width != src_width || dest_height != src_height)) {
-        cairo_set_source_surface(cairo, surf, dest->left, dest->top);
-        cairo_surface_destroy(surf);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_source_clipping(src, TRUE);
 
-        cairo_rectangle(cairo, dest->left, dest->top, dest_width, dest_height);
-        cairo_fill(cairo);
-    }
-    cairo_restore(cairo);
+    pixman_image_composite32 (PIXMAN_OP_SRC,
+                              src, NULL, canvas->image,
+                              0, 0, /* src */
+                              0, 0, /* mask */
+                              dest->left, dest->top, /* dst */
+                              dest_width, dest_height);
+
+
+    if (clip)
+        pixman_image_set_clip_region32 (canvas->image, NULL);
+    pixman_image_unref (src);
 }
 
 void canvas_draw_transparent(CairoCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent)
-- 
1.6.6



More information about the Spice-devel mailing list