Code

New grids are almost ready to fly!
[inkscape.git] / src / display / canvas-arena.cpp
index a7615b3d7c571ca3556c03797fe98585c64fe9e4..bb60cdc938cd32ba481bb923a73d90562add9415 100644 (file)
@@ -21,6 +21,7 @@
 #include <display/nr-arena.h>
 #include <display/nr-arena-group.h>
 #include <display/canvas-arena.h>
+#include <display/inkscape-cairo.h>
 
 enum {
        ARENA_EVENT,
@@ -100,6 +101,7 @@ sp_canvas_arena_init (SPCanvasArena *arena)
        arena->sticky = FALSE;
 
        arena->arena = NRArena::create();
+       arena->arena->canvasarena = arena;
        arena->root = NRArenaGroup::create(arena->arena);
        nr_arena_group_set_transparent (NR_ARENA_GROUP (arena->root), TRUE);
 
@@ -248,9 +250,15 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
                }
        }
 
-/* fixme: RGB transformed bitmap blit is not implemented (Lauris) */
-/* And even if it would be, unless it uses MMX there is little reason to go RGB */
-// CAIRO FIXME: undefine this so that arena renders directly into SPCanvasBuf, without blitting and squishing (32bpp -> 24bpp packed) from a pixblock
+/*
+This define chooses between two modes: When on, arena renders into a temporary 
+32bpp buffer, and the result is then squished into the SPCanvasBuf. When off, arena 
+renders directly to SPCanvasBuf. However currently this gives no speed advantage, 
+perhaps because the lack of squishing is offset by the need for arena items to render 
+to the inconvenient (and probably slower) 24bpp buffer. When SPCanvasBuf is 
+switched to 32bpp and cairo drawing, however, this define should be removed to 
+streamline rendering. 
+*/
 #define STRICT_RGBA
 
        for (y = buf->rect.y0; y < buf->rect.y1; y += sh) {
@@ -268,8 +276,6 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
 
 #ifdef STRICT_RGBA
                        nr_pixblock_setup_fast (&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, area.x0, area.y0, area.x1, area.y1, TRUE);
-                       /* fixme: */
-                       pb.empty = FALSE;
 #endif
 
 // CAIRO FIXME: switch this to R8G8B8A8P and 4 * ...
@@ -279,15 +285,52 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
                                                  FALSE, FALSE);
 
 #ifdef STRICT_RGBA
-            pb.visible_area = buf->visible_rect; 
+                       pb.visible_area = buf->visible_rect;
+
                        if (pb.data.px != NULL) {
-                           nr_arena_item_invoke_render (arena->root, &area, &pb, 0);
-                           nr_blit_pixblock_pixblock (&cb, &pb);
+            cairo_t *ct = nr_create_cairo_context (&area, &pb);
+
+                               nr_arena_item_invoke_render (ct, arena->root, &area, &pb, 0);
+
+                               if (pb.empty == FALSE) {
+
+                                       if (arena->arena->rendermode == RENDERMODE_OUTLINE) {
+                                               // currently we only use cairo in outline mode
+
+                                               // ENDIANNESS FIX
+                                               // Inkscape and GTK use fixed byte order in their buffers: r, g, b, a.
+                                               // Cairo reads/writes buffer values as in32s and therefore depends on the hardware byte order 
+                                               // (little-endian vs big-endian). 
+                                               // Until we move ALL of inkscape rendering and screen display to cairo, 
+                                               // we must reverse the order for big-endian architectures (e.g. PowerPC).
+                                               if (G_BYTE_ORDER == G_BIG_ENDIAN) {
+                                                       unsigned char *start = NR_PIXBLOCK_PX(&pb);
+                                                       unsigned char *end = start + pb.rs * (pb.area.y1 - pb.area.y0);
+                                                       for (unsigned char *i = start; i < end; i += 4) {
+                                                               unsigned char tmp0 = i[0];
+                                                               unsigned char tmp1 = i[1];
+                                                               i[0] = i[3];
+                                                               i[1] = i[2];
+                                                               i[2] = tmp1;
+                                                               i[3] = tmp0;
+                                                       }
+                                               }
+                                       }
+
+                                  // this does the 32->24 squishing, using an assembler routine:
+                             nr_blit_pixblock_pixblock (&cb, &pb);
+                               }
+
+            cairo_surface_t *cst = cairo_get_target(ct);
+            cairo_destroy (ct);
+            cairo_surface_finish (cst);
+            cairo_surface_destroy (cst);
                        }
+
                        nr_pixblock_release (&pb);
 #else
-            cb.visible_area = buf->visible_rect; 
-                       nr_arena_item_invoke_render (arena->root, &area, &cb, 0);
+                       cb.visible_area = buf->visible_rect; 
+                       nr_arena_item_invoke_render (NULL, arena->root, &area, &cb, 0);
 #endif
 
                        nr_pixblock_release (&cb);
@@ -451,6 +494,6 @@ sp_canvas_arena_render_pixblock (SPCanvasArena *ca, NRPixBlock *pb)
        area.x1 = pb->area.x1;
        area.y1 = pb->area.y1;
 
-       nr_arena_item_invoke_render (ca->root, &area, pb, 0);
+       nr_arena_item_invoke_render (NULL, ca->root, &area, pb, 0);
 }