From 9e268605aad18efb0fabff57f4deea18759fec25 Mon Sep 17 00:00:00 2001 From: buliabyak Date: Thu, 1 Mar 2007 04:15:17 +0000 Subject: [PATCH] render text in outline mode via cairo (still no endian-safe); factor out helper functions --- src/display/Makefile_insert | 4 +- src/display/inkscape-cairo.cpp | 108 ++++++++++++++++++++++++++++++++ src/display/inkscape-cairo.h | 26 ++++++++ src/display/nr-arena-glyphs.cpp | 40 +++++++++++- src/display/nr-arena-shape.cpp | 83 ++---------------------- 5 files changed, 180 insertions(+), 81 deletions(-) create mode 100644 src/display/inkscape-cairo.cpp create mode 100644 src/display/inkscape-cairo.h diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 4d51a7891..ad69c772b 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -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 index 000000000..39cd90ed6 --- /dev/null +++ b/src/display/inkscape-cairo.cpp @@ -0,0 +1,108 @@ +/* + * Helper functions to use cairo with inkscape + * + * Copyright (C) 2007 bulia byak + * + * Released under GNU GPL + * + */ + +#include + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#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 index 000000000..0692a0d06 --- /dev/null +++ b/src/display/inkscape-cairo.h @@ -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 : diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index b9f962284..a29c44ee1 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -18,9 +18,14 @@ #endif #include #include +#include +#include +#include #include "../style.h" #include "nr-arena.h" #include "nr-arena-glyphs.h" +#include +#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; diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 2e15ac5aa..d6b3bc73b 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -32,6 +32,7 @@ #include "prefs-utils.h" #include "sp-filter.h" #include "sp-gaussian-blur.h" +#include "inkscape-cairo.h" #include @@ -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); -- 2.30.2