Code

render text in outline mode via cairo (still no endian-safe); factor out helper functions
authorbuliabyak <buliabyak@users.sourceforge.net>
Thu, 1 Mar 2007 04:15:17 +0000 (04:15 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Thu, 1 Mar 2007 04:15:17 +0000 (04:15 +0000)
src/display/Makefile_insert
src/display/inkscape-cairo.cpp [new file with mode: 0644]
src/display/inkscape-cairo.h [new file with mode: 0644]
src/display/nr-arena-glyphs.cpp
src/display/nr-arena-shape.cpp

index 4d51a789107923f664a5de1fa80c1c2160faf660..ad69c772b0b26a5bda243cbafecc8016720c0a7e 100644 (file)
@@ -75,7 +75,9 @@ display_libspdisplay_a_SOURCES = \
        display/pixblock-scaler.cpp     \
        display/pixblock-scaler.h       \
        display/pixblock-transform.cpp  \
-       display/pixblock-transform.h
+       display/pixblock-transform.h    \
+       display/inkscape-cairo.cpp      \
+       display/inkscape-cairo.h
 
 display_bezier_utils_test_SOURCES = display/bezier-utils-test.cpp
 display_bezier_utils_test_LDADD = libnr/libnr.a -lglib-2.0
diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp
new file mode 100644 (file)
index 0000000..39cd90e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Helper functions to use cairo with inkscape
+ *
+ * Copyright (C) 2007 bulia byak
+ *
+ * Released under GNU GPL
+ *
+ */
+
+#include <cairo.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <libnr/n-art-bpath.h>
+#include <libnr/nr-matrix-ops.h>
+#include <libnr/nr-matrix-fns.h>
+#include <libnr/nr-pixblock.h>
+#include "../style.h"
+#include "nr-arena.h"
+
+
+/** Creates a cairo context to render to the given pixblock on the given area */
+cairo_t *
+nr_create_cairo_context (NRRectL *area, NRPixBlock *pb)
+{
+    if (!nr_rect_l_test_intersect (&pb->area, area)) 
+        return NULL;
+
+    NRRectL clip;
+    nr_rect_l_intersect (&clip, &pb->area, area);
+    unsigned char *dpx = NR_PIXBLOCK_PX (pb) + (clip.y0 - pb->area.y0) * pb->rs + NR_PIXBLOCK_BPP (pb) * (clip.x0 - pb->area.x0);
+    int width = area->x1 - area->x0;
+    int height = area->y1 - area->y0;
+    // even though cairo cannot draw in nonpremul mode, select ARGB32 for R8G8B8A8N as the closest; later eliminate R8G8B8A8N everywhere
+    cairo_surface_t* cst = cairo_image_surface_create_for_data
+        (dpx,
+         ((pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P || pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) ? CAIRO_FORMAT_ARGB32 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_A8)),
+         width,
+         height,
+         pb->rs);
+    cairo_t *ct = cairo_create (cst);
+
+    return ct;
+}
+
+/** Feeds path-creating calls to the cairo context translating them from the SPCurve, with the given transform and shift */
+void
+feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point shift)
+{
+    NR::Point lastX(0,0);
+    bool  closed = false;
+    for (int i = 0; bpath[i].code != NR_END; i++) {
+        switch (bpath[i].code) {
+            case NR_MOVETO_OPEN:
+            case NR_MOVETO:
+                if (closed) cairo_close_path(ct);
+                closed = (bpath[i].code == NR_MOVETO);
+                lastX[NR::X] = bpath[i].x3;
+                lastX[NR::Y] = bpath[i].y3;
+                lastX *= trans;
+                lastX -= shift;
+                cairo_move_to(ct, lastX[NR::X], lastX[NR::Y]);
+                break;
+
+            case NR_LINETO:
+                lastX[NR::X] = bpath[i].x3;
+                lastX[NR::Y] = bpath[i].y3;
+                lastX *= trans;
+                lastX -= shift;
+                cairo_line_to(ct, lastX[NR::X], lastX[NR::Y]);
+                break;
+
+            case NR_CURVETO: {
+                NR::Point  tm1, tm2, tm3;
+                tm1[0]=bpath[i].x1;
+                tm1[1]=bpath[i].y1;
+                tm2[0]=bpath[i].x2;
+                tm2[1]=bpath[i].y2;
+                tm3[0]=bpath[i].x3;
+                tm3[1]=bpath[i].y3;
+                tm1 *= trans;
+                tm2 *= trans;
+                tm3 *= trans;
+                tm1 -= shift;
+                tm2 -= shift;
+                tm3 -= shift;
+                cairo_curve_to (ct, tm1[NR::X], tm1[NR::Y], tm2[NR::X], tm2[NR::Y], tm3[NR::X], tm3[NR::Y]);
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+}
+
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/inkscape-cairo.h b/src/display/inkscape-cairo.h
new file mode 100644 (file)
index 0000000..0692a0d
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __INKSCAPE_CAIRO_H__
+#define __INKSCAPE_CAIRO_H__
+
+/*
+ * Helper functions to use cairo with inkscape
+ *
+ * Copyright (C) 2007 bulia byak
+ *
+ * Released under GNU GPL
+ *
+ */
+
+cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb);
+void feed_curve_to_cairo (cairo_t *ct, NArtBpath *bpath, NR::Matrix trans, NR::Point shift);
+
+#endif
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index b9f962284553fea7eaffe33b98241a5ab08faf2a..a29c44ee14bc6bbb33073faf121c65aacf9b3544 100644 (file)
 #endif
 #include <libnr/nr-blit.h>
 #include <libnr/nr-path.h>
+#include <libnr/n-art-bpath.h>
+#include <libnr/nr-matrix-ops.h>
+#include <libnr/nr-matrix-fns.h>
 #include "../style.h"
 #include "nr-arena.h"
 #include "nr-arena-glyphs.h"
+#include <cairo.h>
+#include "inkscape-cairo.h"
 
 #ifdef test_glyph_liv
 #include "../display/canvas-bpath.h"
@@ -423,7 +428,6 @@ nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint s
     return NR_ARENA_ITEM_STATE_ALL;
 }
 
-/* This sucks - as soon, as we have inheritable renderprops, do something with that opacity */
 
 static unsigned int
 nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
@@ -436,6 +440,40 @@ nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, u
 
     guint ret = item->state;
 
+    if (item->arena->rendermode == RENDERMODE_OUTLINE) {
+
+        cairo_t *ct = nr_create_cairo_context (area, pb);
+
+        if (!ct) 
+            return item->state;
+
+        guint32 rgba = item->arena->outlinecolor;
+        cairo_set_source_rgba(ct, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba));
+        cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
+
+        for (child = group->children; child != NULL; child = child->next) {
+            NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
+
+            NArtBpath *bpath = (NArtBpath *) g->font->ArtBPath(g->glyph);
+
+            cairo_new_path(ct);
+            NR::Matrix g_t(g->g_transform);
+            feed_curve_to_cairo (ct, bpath, g_t * group->ctm, NR::Point(area->x0, area->y0));
+            cairo_fill(ct);
+        }
+
+        cairo_surface_t *cst = cairo_get_target(ct);
+        cairo_destroy (ct);
+        cairo_surface_finish (cst);
+        cairo_surface_destroy (cst);
+
+        pb->empty = FALSE;
+        return ret;
+    }
+
+
+
+
     /* Fill */
     if (style->fill.type != SP_PAINT_TYPE_NONE || item->arena->rendermode == RENDERMODE_OUTLINE) {
         NRPixBlock m;
index 2e15ac5aa902d580bf840c70d0138161007a74a2..d6b3bc73b3262d87a3fdf2799230f926b8214ba9 100644 (file)
@@ -32,6 +32,7 @@
 #include "prefs-utils.h"
 #include "sp-filter.h"
 #include "sp-gaussian-blur.h"
+#include "inkscape-cairo.h"
 
 #include <cairo.h>
 
@@ -725,82 +726,6 @@ nr_arena_shape_add_bboxes(NRArenaShape* shape, NRRect &bbox)
     }
 }
 
-/** Feeds path-creating calls to the cairo context translating them from the SPCurve, with the given transform and shift */
-static void
-feed_curve_to_cairo (cairo_t *ct, SPCurve *curve, NR::Matrix trans, NR::Point shift)
-{
-    NR::Point lastX(0,0);
-    bool  closed = false;
-    NArtBpath *bpath = SP_CURVE_BPATH(curve);
-    for (int i = 0; bpath[i].code != NR_END; i++) {
-        switch (bpath[i].code) {
-            case NR_MOVETO_OPEN:
-            case NR_MOVETO:
-                if (closed) cairo_close_path(ct);
-                closed = (bpath[i].code == NR_MOVETO);
-                lastX[NR::X] = bpath[i].x3;
-                lastX[NR::Y] = bpath[i].y3;
-                lastX *= trans;
-                lastX -= shift;
-                cairo_move_to(ct, lastX[NR::X], lastX[NR::Y]);
-                break;
-
-            case NR_LINETO:
-                lastX[NR::X] = bpath[i].x3;
-                lastX[NR::Y] = bpath[i].y3;
-                lastX *= trans;
-                lastX -= shift;
-                cairo_line_to(ct, lastX[NR::X], lastX[NR::Y]);
-                break;
-
-            case NR_CURVETO: {
-                NR::Point  tm1, tm2, tm3;
-                tm1[0]=bpath[i].x1;
-                tm1[1]=bpath[i].y1;
-                tm2[0]=bpath[i].x2;
-                tm2[1]=bpath[i].y2;
-                tm3[0]=bpath[i].x3;
-                tm3[1]=bpath[i].y3;
-                tm1 *= trans;
-                tm2 *= trans;
-                tm3 *= trans;
-                tm1 -= shift;
-                tm2 -= shift;
-                tm3 -= shift;
-                cairo_curve_to (ct, tm1[NR::X], tm1[NR::Y], tm2[NR::X], tm2[NR::Y], tm3[NR::X], tm3[NR::Y]);
-                break;
-            }
-
-            default:
-                break;
-        }
-    }
-}
-
-/** Creates a cairo context to render to the given pixblock on the given area */
-cairo_t *
-nr_create_cairo_context (NRRectL *area, NRPixBlock *pb)
-{
-    if (!nr_rect_l_test_intersect (&pb->area, area)) 
-        return NULL;
-
-    NRRectL clip;
-    nr_rect_l_intersect (&clip, &pb->area, area);
-    unsigned char *dpx = NR_PIXBLOCK_PX (pb) + (clip.y0 - pb->area.y0) * pb->rs + NR_PIXBLOCK_BPP (pb) * (clip.x0 - pb->area.x0);
-    int width = area->x1 - area->x0;
-    int height = area->y1 - area->y0;
-    // even though cairo cannot draw in nonpremul mode, select ARGB32 for R8G8B8A8N as the closest; later eliminate R8G8B8A8N everywhere
-    cairo_surface_t* cst = cairo_image_surface_create_for_data
-        (dpx,
-         ((pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P || pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) ? CAIRO_FORMAT_ARGB32 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_A8)),
-         width,
-         height,
-         pb->rs);
-    cairo_t *ct = cairo_create (cst);
-
-    return ct;
-}
-
 // cairo outline rendering:
 static unsigned int
 cairo_arena_shape_render_outline(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
@@ -819,7 +744,7 @@ cairo_arena_shape_render_outline(NRArenaItem *item, NRRectL *area, NRPixBlock *p
     cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
     cairo_new_path(ct);
 
-    feed_curve_to_cairo (ct, shape->curve, NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
+    feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
 
     cairo_stroke(ct);
 
@@ -908,7 +833,7 @@ cairo_arena_shape_render_stroke(NRArenaItem *item, NRRectL *area, NRPixBlock *pb
     cairo_set_tolerance(ct, 0.1);
     cairo_new_path(ct);
 
-    feed_curve_to_cairo (ct, shape->curve, NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
+    feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
 
     cairo_stroke(ct);
 
@@ -1080,7 +1005,7 @@ cairo_arena_shape_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
 
         cairo_new_path(ct);
 
-        feed_curve_to_cairo (ct, shape->curve, NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
+        feed_curve_to_cairo (ct, SP_CURVE_BPATH(shape->curve), NR::Matrix(shape->ctm), NR::Point(area->x0, area->y0));
 
         cairo_fill(ct);