diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-06-29 22:41:48 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-06-29 22:41:48 +0000 |
| commit | 13b15b7b977eecbededd1734f5ab001f0c44d21f (patch) | |
| tree | f4e1d29f1f5deafa0c5ed2b17c88c1682a378194 /src | |
| parent | Fix icons (diff) | |
| download | inkscape-13b15b7b977eecbededd1734f5ab001f0c44d21f.tar.gz inkscape-13b15b7b977eecbededd1734f5ab001f0c44d21f.zip | |
Consolidate Cairo utils in display/cairo-utils.h. Fix icons harder.
(bzr r9508.1.8)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/Makefile_insert | 2 | ||||
| -rw-r--r-- | src/display/cairo-utils.cpp | 341 | ||||
| -rw-r--r-- | src/display/cairo-utils.h | 17 | ||||
| -rw-r--r-- | src/display/canvas-arena.cpp | 31 | ||||
| -rw-r--r-- | src/display/canvas-bpath.cpp | 7 | ||||
| -rw-r--r-- | src/display/canvas-text.cpp | 2 | ||||
| -rw-r--r-- | src/display/inkscape-cairo.cpp | 283 | ||||
| -rw-r--r-- | src/display/inkscape-cairo.h | 40 | ||||
| -rw-r--r-- | src/display/nr-arena-glyphs.cpp | 16 | ||||
| -rw-r--r-- | src/display/nr-arena-image.cpp | 2 | ||||
| -rw-r--r-- | src/display/nr-arena-shape.cpp | 155 | ||||
| -rw-r--r-- | src/display/nr-svgfonts.cpp | 4 | ||||
| -rw-r--r-- | src/display/sodipodi-ctrl.cpp | 2 | ||||
| -rw-r--r-- | src/display/sodipodi-ctrlrect.cpp | 2 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 2 | ||||
| -rw-r--r-- | src/display/sp-ctrlline.cpp | 12 | ||||
| -rw-r--r-- | src/display/sp-ctrlpoint.cpp | 2 | ||||
| -rw-r--r-- | src/display/sp-ctrlquadr.cpp | 10 | ||||
| -rw-r--r-- | src/extension/internal/cairo-render-context.cpp | 2 | ||||
| -rw-r--r-- | src/sp-gradient.cpp | 2 | ||||
| -rw-r--r-- | src/sp-pattern.cpp | 2 | ||||
| -rw-r--r-- | src/ui/dialog/icon-preview.cpp | 17 | ||||
| -rw-r--r-- | src/widgets/icon.cpp | 65 |
23 files changed, 443 insertions, 575 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index c6cdcbb6d..da5ded824 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -27,8 +27,6 @@ ink_common_sources += \ display/gnome-canvas-acetate.h \ display/guideline.cpp \ display/guideline.h \ - display/inkscape-cairo.cpp \ - display/inkscape-cairo.h \ display/nr-3dutils.cpp \ display/nr-3dutils.h \ display/nr-arena.cpp \ diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index 58db5d551..7bfdd7dd7 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -12,12 +12,19 @@ # include <config.h> #endif +#include "display/cairo-utils.h" + #include <stdexcept> -#include <cairo.h> +#include <2geom/pathvector.h> +#include <2geom/bezier-curve.h> +#include <2geom/hvlinesegment.h> #include <2geom/matrix.h> -#include "display/cairo-utils.h" -#include "display/inkscape-cairo.h" +#include <2geom/point.h> +#include <2geom/path.h> +#include <2geom/transforms.h> +#include <2geom/sbasis-to-bezier.h> #include "color.h" +#include "helper/geom-curves.h" namespace Inkscape { @@ -102,6 +109,334 @@ Cairo::RefPtr<CairoContext> CairoContext::create(Cairo::RefPtr<Cairo::Surface> c } // namespace Inkscape /* + * Can be called recursively. + * If optimize_stroke == false, the view Rect is not used. + */ +static void +feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Matrix const & trans, Geom::Rect view, bool optimize_stroke) +{ + if( is_straight_curve(c) ) + { + Geom::Point end_tr = c.finalPoint() * trans; + if (!optimize_stroke) { + cairo_line_to(cr, end_tr[0], end_tr[1]); + } else { + Geom::Rect swept(c.initialPoint()*trans, end_tr); + if (swept.intersects(view)) { + cairo_line_to(cr, end_tr[0], end_tr[1]); + } else { + cairo_move_to(cr, end_tr[0], end_tr[1]); + } + } + } + else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) { + std::vector<Geom::Point> points = quadratic_bezier->points(); + points[0] *= trans; + points[1] *= trans; + points[2] *= trans; + Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]); + Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]); + if (!optimize_stroke) { + cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]); + } else { + Geom::Rect swept(points[0], points[2]); + swept.expandTo(points[1]); + if (swept.intersects(view)) { + cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]); + } else { + cairo_move_to(cr, points[2][0], points[2][1]); + } + } + } + else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c)) { + std::vector<Geom::Point> points = cubic_bezier->points(); + //points[0] *= trans; // don't do this one here for fun: it is only needed for optimized strokes + points[1] *= trans; + points[2] *= trans; + points[3] *= trans; + if (!optimize_stroke) { + cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]); + } else { + points[0] *= trans; // didn't transform this point yet + Geom::Rect swept(points[0], points[3]); + swept.expandTo(points[1]); + swept.expandTo(points[2]); + if (swept.intersects(view)) { + cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]); + } else { + cairo_move_to(cr, points[3][0], points[3][1]); + } + } + } +// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) { +// //TODO: get at the innards and spit them out to cairo +// } + else { + //this case handles sbasis as well as all other curve types + Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1); + + //recurse to convert the new path resulting from the sbasis to svgd + for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) { + feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke); + } + } +} + + +/** Feeds path-creating calls to the cairo context translating them from the Path */ +static void +feed_path_to_cairo (cairo_t *ct, Geom::Path const &path) +{ + if (path.empty()) + return; + + cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] ); + + for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) { + feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used + } + + if (path.closed()) { + cairo_close_path(ct); + } +} + +/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */ +static void +feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) +{ + if (!area) + return; + if (path.empty()) + return; + + // Transform all coordinates to coords within "area" + Geom::Point shift = area->min(); + Geom::Rect view = *area; + view.expandBy (stroke_width); + view = view * (Geom::Matrix)Geom::Translate(-shift); + // Pass transformation to feed_curve, so that we don't need to create a whole new path. + Geom::Matrix transshift(trans * Geom::Translate(-shift)); + + Geom::Point initial = path.initialPoint() * transshift; + cairo_move_to(ct, initial[0], initial[1] ); + + for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) { + feed_curve_to_cairo(ct, *cit, transshift, view, optimize_stroke); + } + + if (path.closed()) { + if (!optimize_stroke) { + cairo_close_path(ct); + } else { + cairo_line_to(ct, initial[0], initial[1]); + /* We cannot use cairo_close_path(ct) here because some parts of the path may have been + clipped and not drawn (maybe the before last segment was outside view area), which + would result in closing the "subpath" after the last interruption, not the entire path. + + However, according to cairo documentation: + The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate + in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead, + there is a line join connecting the final and initial segments of the sub-path. + + The correct fix will be possible when cairo introduces methods for moving without + ending/starting subpaths, which we will use for skipping invisible segments; then we + will be able to use cairo_close_path here. This issue also affects ps/eps/pdf export, + see bug 168129 + */ + } + } +} + +/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift + * One must have done cairo_new_path(ct); before calling this function. */ +void +feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) +{ + if (!area) + return; + if (pathv.empty()) + return; + + for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) { + feed_path_to_cairo(ct, *it, trans, area, optimize_stroke, stroke_width); + } +} + +/** Feeds path-creating calls to the cairo context translating them from the PathVector + * One must have done cairo_new_path(ct); before calling this function. */ +void +feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv) +{ + if (pathv.empty()) + return; + + for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) { + feed_path_to_cairo(ct, *it); + } +} + +void +ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba) +{ + 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)); +} + +void +ink_cairo_set_source_color(cairo_t *ct, SPColor const &c, double opacity) +{ + cairo_set_source_rgba(ct, c.v.c[0], c.v.c[1], c.v.c[2], opacity); +} + +static void +ink_cairo_convert_matrix(cairo_matrix_t &cm, Geom::Matrix const &m) +{ + cm.xx = m[0]; + cm.xy = m[2]; + cm.x0 = m[4]; + cm.yx = m[1]; + cm.yy = m[3]; + cm.y0 = m[5]; +} + +void +ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m) +{ + cairo_matrix_t cm; + ink_cairo_convert_matrix(cm, m); + cairo_transform(ct, &cm); +} + +void +ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m) +{ + cairo_matrix_t cm; + ink_cairo_convert_matrix(cm, m); + cairo_pattern_set_matrix(cp, &cm); +} + +// taken from Cairo sources +static inline guint32 premul_alpha(guint32 color, guint32 alpha) +{ + guint32 temp = alpha * color + 128; + return (temp + (temp >> 8)) >> 8; +} + +/** + * @brief Convert pixel data from GdkPixbuf format to ARGB. + * This will convert pixel data from GdkPixbuf format to Cairo's native pixel format. + * This involves premultiplying alpha and shuffling around the channels. + * Pixbuf data must have an alpha channel, otherwise the results are undefined + * (usually a segfault). + */ +void +convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int stride) +{ + // TODO: optimize until it squeaks. + guint32 *ipx = reinterpret_cast<guint32*>(data); + + for (int i = 0; i < h; ++i) { + for (int j = 0; j < w; ++j) { + int index = i * stride / 4 + j; + guint32 c = ipx[index]; + guint32 o = 0; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + guint32 a = (c & 0xff000000) >> 24; +#else + guint32 a = (c & 0x000000ff); +#endif + if (a != 0) { + // extract color components +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + guint32 r = (c & 0x000000ff); + guint32 g = (c & 0x0000ff00) >> 8; + guint32 b = (c & 0x00ff0000) >> 16; +#else + guint32 r = (c & 0xff000000) >> 24; + guint32 g = (c & 0x00ff0000) >> 16; + guint32 b = (c & 0x0000ff00) >> 8; +#endif + // premultiply + r = premul_alpha(r, a); + b = premul_alpha(b, a); + g = premul_alpha(g, a); + // combine into output + o = (a << 24) | (r << 16) | (g << 8) | (b); + } + ipx[index] = o; + } + } +} + +/** + * @brief Convert pixel data from ARGB to GdkPixbuf format. + * This will convert pixel data from GdkPixbuf format to Cairo's native pixel format. + * This involves premultiplying alpha and shuffling around the channels. + */ +void +convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int stride) +{ + // TODO: optimize until it squeaks. + guint32 *ipx = reinterpret_cast<guint32*>(data); + for (int i = 0; i < h; ++i) { + for (int j = 0; j < w; ++j) { + int index = i * stride / 4 + j; + guint32 c = ipx[index]; + guint32 o = 0; + guint32 a = (c & 0xff000000) >> 24; + if (a != 0) { + // extract color components + guint32 r = (c & 0x00ff0000) >> 16; + guint32 g = (c & 0x0000ff00) >> 8; + guint32 b = (c & 0x000000ff); + // unpremultiply; adding a/2 gives correct rounding + // (taken from Cairo sources) + r = (r * 255 + a/2) / a; + b = (b * 255 + a/2) / a; + g = (g * 255 + a/2) / a; + // combine into output +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + o = (r) | (g << 8) | (b << 16) | (a << 24); +#else + o = (r << 24) | (g << 16) | (b << 8) | (a); +#endif + } + ipx[index] = o; + } + } +} + +/** + * @brief Converts GdkPixbuf's data to premultiplied ARGB. + * This function will convert a GdkPixbuf in place into Cairo's native pixel format. + * Note that this is a hack intended to save memory. When the pixbuf is Cairo's format, + * using it with GTK will result in corrupted drawings. + */ +void +convert_pixbuf_normal_to_argb32_mutant(GdkPixbuf *pb) +{ + convert_pixels_pixbuf_to_argb32( + gdk_pixbuf_get_pixels(pb), + gdk_pixbuf_get_width(pb), + gdk_pixbuf_get_height(pb), + gdk_pixbuf_get_rowstride(pb)); +} + +/** + * @brief Converts GdkPixbuf's data back to its native format. + * Once this is done, the pixbuf can be used with GTK again. + */ +void +convert_pixbuf_argb32_to_normal(GdkPixbuf *pb) +{ + convert_pixels_argb32_to_pixbuf( + gdk_pixbuf_get_pixels(pb), + gdk_pixbuf_get_width(pb), + gdk_pixbuf_get_height(pb), + gdk_pixbuf_get_rowstride(pb)); +} + +/* Local Variables: mode:c++ c-file-style:"stroustrup" diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index feed987bd..882742d5f 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -13,9 +13,12 @@ #define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H #include <glib.h> +#include <gdk-pixbuf/gdk-pixbuf.h> #include <cairomm/cairomm.h> #include <2geom/forward.h> +struct SPColor; + namespace Inkscape { /** @brief RAII idiom for Cairo groups. @@ -75,6 +78,20 @@ public: } // namespace Inkscape +void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacity); +void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba); +void ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m); +void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m); + +void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs); +void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs); +void convert_pixbuf_normal_to_argb32(GdkPixbuf *); +void convert_pixbuf_argb32_to_normal(GdkPixbuf *); + +// TODO: move those to 2Geom +void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width); +void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv); + #endif /* Local Variables: diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index 86d902be2..086c0a27d 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -12,16 +12,16 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <libnr/nr-blit.h> #include <gtk/gtksignal.h> -#include <display/display-forward.h> -#include <display/sp-canvas-util.h> +#include "libnr/nr-blit.h" +#include "display/display-forward.h" +#include "display/sp-canvas-util.h" #include "helper/sp-marshal.h" -#include <display/nr-arena.h> -#include <display/nr-arena-group.h> -#include <display/canvas-arena.h> -#include <display/inkscape-cairo.h> +#include "display/nr-arena.h" +#include "display/nr-arena-group.h" +#include "display/canvas-arena.h" +#include "display/cairo-utils.h" enum { ARENA_EVENT, @@ -190,7 +190,7 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf) gint bw, bh; SPCanvasArena *arena = SP_CANVAS_ARENA (item); - SPCanvas *canvas = item->canvas; + //SPCanvas *canvas = item->canvas; nr_arena_item_invoke_update (arena->root, NULL, &arena->gc, NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER, @@ -218,23 +218,8 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf) FALSE, FALSE); cb.visible_area = buf->visible_rect; - //cairo_t *ct = nr_create_cairo_context (&area, &cb); - cairo_save(buf->ct); - //cairo_translate(buf->ct, area.x0 - canvas->x0, area.y0 - canvas->y0); nr_arena_item_invoke_render (buf->ct, arena->root, &area, &cb, 0); - cairo_restore(buf->ct); - - //cairo_surface_t *cst = cairo_get_target(ct); - - //cairo_save(buf->ct); - //cairo_set_source_surface(buf->ct, cst, 0, 0); - //cairo_paint(buf->ct); - //cairo_restore(buf->ct); - - //cairo_destroy (ct); - //cairo_surface_finish (cst); - //cairo_surface_destroy (cst); nr_pixblock_release (&cb); } diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index 5726fef02..cf9127352 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -16,12 +16,11 @@ # include "config.h" #endif #include "color.h" -#include "sp-canvas-util.h" -#include "inkscape-cairo.h" -#include "canvas-bpath.h" +#include "display/sp-canvas-util.h" +#include "display/canvas-bpath.h" #include "display/display-forward.h" #include "display/curve.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include <libnr/nr-pixops.h> #include "helper/geom.h" diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp index d32bc20c3..90f7c47c6 100644 --- a/src/display/canvas-text.cpp +++ b/src/display/canvas-text.cpp @@ -16,7 +16,7 @@ #include "display-forward.h" #include "sp-canvas-util.h" #include "canvas-text.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include <sstream> #include <string.h> #include "desktop.h" diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp deleted file mode 100644 index fa5a7cfe2..000000000 --- a/src/display/inkscape-cairo.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Helper functions to use cairo with inkscape - * - * Copyright (C) 2007 bulia byak - * Copyright (C) 2008 Johan Engelen - * - * Released under GNU GPL - * - */ - -#include <cairo.h> - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <libnr/nr-pixblock.h> -#include <libnr/nr-convert2geom.h> -#include "../style.h" -#include "nr-arena.h" -#include "sp-canvas.h" -#include <2geom/pathvector.h> -#include <2geom/bezier-curve.h> -#include <2geom/hvlinesegment.h> -#include <2geom/matrix.h> -#include <2geom/point.h> -#include <2geom/path.h> -#include <2geom/transforms.h> -#include <2geom/sbasis-to-bezier.h> -#include "helper/geom-curves.h" - -/** Creates a cairo context to render to the given pixblock on the given area */ -cairo_t * -nr_create_cairo_context_for_data (NRRectL *area, NRRectL *buf_area, unsigned char *px, unsigned int rowstride) -{ - if (!nr_rect_l_test_intersect_ptr(buf_area, area)) - return NULL; - - NRRectL clip; - nr_rect_l_intersect (&clip, buf_area, area); - unsigned char *dpx = px + (clip.y0 - buf_area->y0) * rowstride + 4 * (clip.x0 - buf_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, - CAIRO_FORMAT_ARGB32, - width, - height, - rowstride); - cairo_t *ct = cairo_create (cst); - - return ct; -} - -#if 0 -/** Creates a cairo context to render to the given SPCanvasBuf on the given area */ -cairo_t * -nr_create_cairo_context_canvasbuf (NRRectL */*area*/, SPCanvasBuf *b) -{ - return nr_create_cairo_context_for_data (&(b->rect), &(b->rect), b->buf, b->buf_rowstride); -} -#endif - - -/** Creates a cairo context to render to the given NRPixBlock on the given area */ -cairo_t * -nr_create_cairo_context (NRRectL *area, NRPixBlock *pb) -{ - return nr_create_cairo_context_for_data (area, &(pb->area), NR_PIXBLOCK_PX (pb), pb->rs); -} - -/* - * Can be called recursively. - * If optimize_stroke == false, the view Rect is not used. - */ -static void -feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Matrix const & trans, Geom::Rect view, bool optimize_stroke) -{ - if( is_straight_curve(c) ) - { - Geom::Point end_tr = c.finalPoint() * trans; - if (!optimize_stroke) { - cairo_line_to(cr, end_tr[0], end_tr[1]); - } else { - Geom::Rect swept(c.initialPoint()*trans, end_tr); - if (swept.intersects(view)) { - cairo_line_to(cr, end_tr[0], end_tr[1]); - } else { - cairo_move_to(cr, end_tr[0], end_tr[1]); - } - } - } - else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) { - std::vector<Geom::Point> points = quadratic_bezier->points(); - points[0] *= trans; - points[1] *= trans; - points[2] *= trans; - Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]); - Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]); - if (!optimize_stroke) { - cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]); - } else { - Geom::Rect swept(points[0], points[2]); - swept.expandTo(points[1]); - if (swept.intersects(view)) { - cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]); - } else { - cairo_move_to(cr, points[2][0], points[2][1]); - } - } - } - else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c)) { - std::vector<Geom::Point> points = cubic_bezier->points(); - //points[0] *= trans; // don't do this one here for fun: it is only needed for optimized strokes - points[1] *= trans; - points[2] *= trans; - points[3] *= trans; - if (!optimize_stroke) { - cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]); - } else { - points[0] *= trans; // didn't transform this point yet - Geom::Rect swept(points[0], points[3]); - swept.expandTo(points[1]); - swept.expandTo(points[2]); - if (swept.intersects(view)) { - cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]); - } else { - cairo_move_to(cr, points[3][0], points[3][1]); - } - } - } -// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) { -// //TODO: get at the innards and spit them out to cairo -// } - else { - //this case handles sbasis as well as all other curve types - Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1); - - //recurse to convert the new path resulting from the sbasis to svgd - for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) { - feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke); - } - } -} - - -/** Feeds path-creating calls to the cairo context translating them from the Path */ -static void -feed_path_to_cairo (cairo_t *ct, Geom::Path const &path) -{ - if (path.empty()) - return; - - cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] ); - - for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) { - feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used - } - - if (path.closed()) { - cairo_close_path(ct); - } -} - -/** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */ -static void -feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) -{ - if (!area) - return; - if (path.empty()) - return; - - // Transform all coordinates to coords within "area" - Geom::Point shift = area->min(); - Geom::Rect view = *area; - view.expandBy (stroke_width); - view = view * (Geom::Matrix)Geom::Translate(-shift); - // Pass transformation to feed_curve, so that we don't need to create a whole new path. - Geom::Matrix transshift(trans * Geom::Translate(-shift)); - - Geom::Point initial = path.initialPoint() * transshift; - cairo_move_to(ct, initial[0], initial[1] ); - - for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) { - feed_curve_to_cairo(ct, *cit, transshift, view, optimize_stroke); - } - - if (path.closed()) { - if (!optimize_stroke) { - cairo_close_path(ct); - } else { - cairo_line_to(ct, initial[0], initial[1]); - /* We cannot use cairo_close_path(ct) here because some parts of the path may have been - clipped and not drawn (maybe the before last segment was outside view area), which - would result in closing the "subpath" after the last interruption, not the entire path. - - However, according to cairo documentation: - The behavior of cairo_close_path() is distinct from simply calling cairo_line_to() with the equivalent coordinate - in the case of stroking. When a closed sub-path is stroked, there are no caps on the ends of the sub-path. Instead, - there is a line join connecting the final and initial segments of the sub-path. - - The correct fix will be possible when cairo introduces methods for moving without - ending/starting subpaths, which we will use for skipping invisible segments; then we - will be able to use cairo_close_path here. This issue also affects ps/eps/pdf export, - see bug 168129 - */ - } - } -} - -/** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift - * One must have done cairo_new_path(ct); before calling this function. */ -void -feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) -{ - if (!area) - return; - if (pathv.empty()) - return; - - for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) { - feed_path_to_cairo(ct, *it, trans, area, optimize_stroke, stroke_width); - } -} - -/** Feeds path-creating calls to the cairo context translating them from the PathVector - * One must have done cairo_new_path(ct); before calling this function. */ -void -feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv) -{ - if (pathv.empty()) - return; - - for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) { - feed_path_to_cairo(ct, *it); - } -} - -void -ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba) -{ - 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)); -} - -static void -ink_cairo_convert_matrix(cairo_matrix_t &cm, Geom::Matrix const &m) -{ - cm.xx = m[0]; - cm.xy = m[2]; - cm.x0 = m[4]; - cm.yx = m[1]; - cm.yy = m[3]; - cm.y0 = m[5]; -} - -void -ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m) -{ - cairo_matrix_t cm; - ink_cairo_convert_matrix(cm, m); - cairo_transform(ct, &cm); -} - -void -ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m) -{ - cairo_matrix_t cm; - ink_cairo_convert_matrix(cm, m); - cairo_pattern_set_matrix(cp, &cm); -} - -/* - 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 deleted file mode 100644 index 74dc10995..000000000 --- a/src/display/inkscape-cairo.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __INKSCAPE_CAIRO_H__ -#define __INKSCAPE_CAIRO_H__ - -/* - * Helper functions to use cairo with inkscape - * - * Copyright (C) 2007 bulia byak - * Copyright (C) 2008 Johan Engelen - * - * Released under GNU GPL - * - */ - -#include <2geom/forward.h> -#include <cairo/cairo.h> -#include <boost/optional.hpp> -#include "libnr/nr-rect.h" - -struct NRPixBlock; -class SPCanvasBuf; - -cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb); -void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width); -void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv); - -void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba); -void ink_cairo_transform(cairo_t *ct, Geom::Matrix const &m); -void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Matrix const &m); - -#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 8e1b659c7..84aa1c231 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -16,21 +16,19 @@ #ifdef HAVE_CONFIG_H # include <config.h> #endif -#include <libnr/nr-blit.h> -#include <libnr/nr-convert2geom.h> +#include "libnr/nr-blit.h" +#include "libnr/nr-convert2geom.h" #include <2geom/matrix.h> -#include "../style.h" -#include "nr-arena.h" -#include "nr-arena-glyphs.h" +#include "style.h" +#include "display/nr-arena.h" +#include "display/nr-arena-glyphs.h" #include <cairo.h> -#include "inkscape-cairo.h" +#include "display/cairo-utils.h" #include "helper/geom.h" #ifdef test_glyph_liv #include "../display/canvas-bpath.h" -#include <libnrtype/font-instance.h> -#include <libnrtype/raster-glyph.h> -#include <libnrtype/RasterFont.h> +#include "libnrtype/font-instance.h" // defined in nr-arena-shape.cpp void nr_pixblock_render_shape_mask_or(NRPixBlock &m, Shape *theS); diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp index 6b71abaa0..ec0a2ab02 100644 --- a/src/display/nr-arena-image.cpp +++ b/src/display/nr-arena-image.cpp @@ -18,7 +18,7 @@ #include "../preferences.h" #include "nr-arena-image.h" #include "style.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "display/nr-arena.h" #include "display/nr-filter.h" #include "display/nr-filter-gaussian.h" diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index f0a621bf0..de9a0c0fd 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -12,38 +12,31 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <cairo.h> +#include <fenv.h> +#include <glib.h> +#include <typeinfo> + +#include <2geom/curves.h> +#include <2geom/pathvector.h> #include <2geom/svg-path.h> #include <2geom/svg-path-parser.h> -#include <display/canvas-arena.h> -#include <display/nr-arena.h> -#include <display/nr-arena-shape.h> +#include "display/cairo-utils.h" +#include "display/canvas-arena.h" #include "display/curve.h" -#include <libnr/nr-pixops.h> -#include <libnr/nr-blit.h> -#include <libnr/nr-convert2geom.h> -#include <2geom/pathvector.h> -#include <2geom/curves.h> -#include <livarot/Shape.h> -#include <livarot/Path.h> -#include <livarot/float-line.h> -#include <livarot/int-line.h> -#include <style.h> -#include "inkscape-cairo.h" -#include "helper/geom.h" +#include "display/nr-arena.h" +#include "display/nr-arena-shape.h" +#include "display/nr-filter.h" #include "helper/geom-curves.h" +#include "helper/geom.h" +#include "libnr/nr-blit.h" +#include "libnr/nr-convert2geom.h" +#include "libnr/nr-pixops.h" +#include "preferences.h" #include "sp-filter.h" #include "sp-filter-reference.h" -#include "display/nr-filter.h" -#include <typeinfo> -#include <cairo.h> -#include "preferences.h" - -#include <glib.h> +#include "style.h" #include "svg/svg.h" -#include <fenv.h> - -//int showRuns=0; -void nr_pixblock_render_shape_mask_or(NRPixBlock &m,Shape* theS); static void nr_arena_shape_class_init(NRArenaShapeClass *klass); static void nr_arena_shape_init(NRArenaShape *shape); @@ -613,118 +606,6 @@ void NRArenaShape::setPaintBox(Geom::Rect const &pbox) nr_arena_item_request_update(this, NR_ARENA_ITEM_STATE_ALL, FALSE); } -static void -shape_run_A8_OR(raster_info &dest,void */*data*/,int st,float vst,int en,float ven) -{ - if ( st >= en ) return; - if ( vst < 0 ) vst=0; - if ( vst > 1 ) vst=1; - if ( ven < 0 ) ven=0; - if ( ven > 1 ) ven=1; - float sv=vst; - float dv=ven-vst; - int len=en-st; - unsigned char* d=(unsigned char*)dest.buffer; - d+=(st-dest.startPix); - if ( fabs(dv) < 0.001 ) { - if ( vst > 0.999 ) { - /* Simple copy */ - while (len > 0) { - d[0] = 255; - d += 1; - len -= 1; - } - } else { - sv*=256; - unsigned int c0_24=(int)sv; - c0_24&=0xFF; - while (len > 0) { - /* Draw */ - d[0] = NR_COMPOSEA_111(c0_24,d[0]); - d += 1; - len -= 1; - } - } - } else { - if ( en <= st+1 ) { - sv=0.5*(vst+ven); - sv*=256; - unsigned int c0_24=(int)sv; - c0_24&=0xFF; - /* Draw */ - d[0] = NR_COMPOSEA_111(c0_24,d[0]); - } else { - dv/=len; - sv+=0.5*dv; // correction trapezoidale - sv*=16777216; - dv*=16777216; - int c0_24 = static_cast<int>(CLAMP(sv, 0, 16777216)); - int s0_24 = static_cast<int>(dv); - while (len > 0) { - unsigned int ca; - /* Draw */ - ca = c0_24 >> 16; - if ( ca > 255 ) ca=255; - d[0] = NR_COMPOSEA_111(ca,d[0]); - d += 1; - c0_24 += s0_24; - c0_24 = CLAMP(c0_24, 0, 16777216); - len -= 1; - } - } - } -} - -void nr_pixblock_render_shape_mask_or(NRPixBlock &m,Shape* theS) -{ - theS->CalcBBox(); - float l = theS->leftX, r = theS->rightX, t = theS->topY, b = theS->bottomY; - int il,ir,it,ib; - il=(int)floor(l); - ir=(int)ceil(r); - it=(int)floor(t); - ib=(int)ceil(b); - - if ( il >= m.area.x1 || ir <= m.area.x0 || it >= m.area.y1 || ib <= m.area.y0 ) return; - if ( il < m.area.x0 ) il=m.area.x0; - if ( it < m.area.y0 ) it=m.area.y0; - if ( ir > m.area.x1 ) ir=m.area.x1; - if ( ib > m.area.y1 ) ib=m.area.y1; - - /* This is the FloatLigne version. See svn (prior to Apr 2006) for versions using BitLigne or direct BitLigne. */ - int curPt; - float curY; - theS->BeginQuickRaster(curY, curPt); - - FloatLigne *theI = new FloatLigne(); - IntLigne *theIL = new IntLigne(); - - theS->DirectQuickScan(curY, curPt, (float) it, true, 1.0); - - char *mdata = (char*)m.data.px; - if ( m.size == NR_PIXBLOCK_SIZE_TINY ) mdata=(char*)m.data.p; - uint32_t *ligStart = ((uint32_t*)(mdata + ((il - m.area.x0) + m.rs * (it - m.area.y0)))); - for (int y = it; y < ib; y++) { - theI->Reset(); - theS->QuickScan(curY, curPt, ((float)(y+1)), theI, 1.0); - theI->Flatten(); - theIL->Copy(theI); - - raster_info dest; - dest.startPix=il; - dest.endPix=ir; - dest.sth=il; - dest.stv=y; - dest.buffer=ligStart; - theIL->Raster(dest, NULL, shape_run_A8_OR); - ligStart=((uint32_t*)(((char*)ligStart)+m.rs)); - } - theS->EndQuickRaster(); - delete theI; - delete theIL; -} - - /* Local Variables: mode:c++ diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 7a0db664a..98b085333 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -18,8 +18,8 @@ #include <cairo.h> #include <vector> #include "svg/svg.h" -#include "inkscape-cairo.h" -#include "nr-svgfonts.h" +#include "display/cairo-utils.h" +#include "display/nr-svgfonts.h" //*************************// // UserFont Implementation // diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp index ed4c91d3b..37685c5da 100644 --- a/src/display/sodipodi-ctrl.cpp +++ b/src/display/sodipodi-ctrl.cpp @@ -13,7 +13,7 @@ #include "display-forward.h" #include "sodipodi-ctrl.h" #include "libnr/nr-pixops.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" enum { ARG_0, diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index 09bfde6fb..2ebf310c7 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -18,7 +18,7 @@ #include "display-forward.h" #include "sp-canvas-util.h" #include "sodipodi-ctrlrect.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" /* * Currently we do not have point method, as it should always be painted diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 31e80d1f9..571b573e1 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -42,7 +42,7 @@ #endif // ENABLE_LCMS #include "display/rendermode.h" #include "libnr/nr-blit.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "debug/gdk-event-latency-tracker.h" #include "desktop.h" #include "sp-namedview.h" diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index 043736d94..7db029dd3 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -19,15 +19,15 @@ * */ -#include "display-forward.h" -#include "sp-canvas-util.h" -#include "sp-ctrlline.h" - #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include <color.h> -#include "display/inkscape-cairo.h" + +#include "display/sp-ctrlline.h" +#include "display/display-forward.h" +#include "display/sp-canvas-util.h" +#include "display/cairo-utils.h" +#include "color.h" static void sp_ctrlline_class_init (SPCtrlLineClass *klass); diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp index 279d3f7f8..9f791676e 100644 --- a/src/display/sp-ctrlpoint.cpp +++ b/src/display/sp-ctrlpoint.cpp @@ -19,7 +19,7 @@ # include "config.h" #endif #include <color.h> -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" static void sp_ctrlpoint_class_init (SPCtrlPointClass *klass); diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp index b307684e5..4372f871c 100644 --- a/src/display/sp-ctrlquadr.cpp +++ b/src/display/sp-ctrlquadr.cpp @@ -11,14 +11,14 @@ * Released under GNU GPL */ -#include "display-forward.h" -#include "sp-canvas-util.h" -#include "sp-ctrlquadr.h" - #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include "display/inkscape-cairo.h" + +#include "display-forward.h" +#include "sp-canvas-util.h" +#include "sp-ctrlquadr.h" +#include "display/cairo-utils.h" #include "color.h" struct SPCtrlQuadr : public SPCanvasItem{ diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index cf3c72432..8b40f60b4 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -37,7 +37,7 @@ #include "display/nr-arena-group.h" #include "display/curve.h" #include "display/canvas-bpath.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "sp-item.h" #include "sp-item-group.h" #include "style.h" diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index f63436e71..ba15f2651 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -31,7 +31,7 @@ #include <sigc++/functors/ptr_fun.h> #include <sigc++/adaptors/bind.h> -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "libnr/nr-gradient.h" #include "libnr/nr-pixops.h" #include "svg/svg.h" diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 8d1e8dab5..5f0c4aebd 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -23,7 +23,7 @@ #include <2geom/transforms.h> #include "macros.h" #include "svg/svg.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "display/nr-arena.h" #include "display/nr-arena-group.h" #include "attributes.h" diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 9a46254ab..c7ed9f92b 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -38,7 +38,7 @@ extern "C" { // takes doc, root, icon, and icon name to produce pixels guchar * sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, - const gchar *name, unsigned int psize ); + const gchar *name, unsigned int psize, unsigned &stride); } namespace Inkscape { @@ -159,10 +159,11 @@ IconPreviewPanel::IconPreviewPanel() : int previous = 0; int avail = 0; for ( int i = numEntries - 1; i >= 0; --i ) { - pixMem[i] = new guchar[4 * sizes[i] * sizes[i]]; - memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] ); + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]); + pixMem[i] = new guchar[sizes[i] * stride]; + memset( pixMem[i], 0x00, sizes[i] * stride ); - GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL ); + GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], stride, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL ); GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) ); images[i] = Glib::wrap(img); Glib::ustring label(*labels[i]); @@ -384,14 +385,16 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) arena, visionkey, SP_ITEM_SHOW_DISPLAY ); for ( int i = 0; i < numEntries; i++ ) { - guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] ); + unsigned unused; + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]); + guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i], unused); // g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") ); if ( px ) { - memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 ); + memcpy( pixMem[i], px, sizes[i] * stride ); g_free( px ); px = 0; } else { - memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 ); + memset( pixMem[i], 0, sizes[i] * stride ); } images[i]->queue_draw(); } diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 51bdfef66..1eb3ef0ab 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -25,6 +25,7 @@ #include "inkscape.h" #include "document.h" #include "sp-item.h" +#include "display/cairo-utils.h" #include "display/nr-arena.h" #include "display/nr-arena-item.h" #include "io/sys.h" @@ -909,11 +910,11 @@ GdkPixbuf *sp_icon_image_load_pixmap(gchar const *name, unsigned /*lsize*/, unsi // takes doc, root, icon, and icon name to produce pixels extern "C" guchar * sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, - gchar const *name, unsigned psize ) + gchar const *name, unsigned psize, + unsigned &stride) { bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); guchar *px = NULL; - int w, h, stride; if (doc) { SPObject *object = doc->getObjectById(name); @@ -1012,25 +1013,23 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.x0, (double)ua.y0, (double)ua.x1, (double)ua.y1 ); } - w = ua.x1 - ua.x0; - h = ua.y1 - ua.y0; - stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); + stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, psize); /* Set up pixblock */ - px = g_new(guchar, stride * h); - memset(px, 0x00, stride * h); + px = g_new(guchar, stride * psize); + memset(px, 0x00, stride * psize); /* Render */ cairo_surface_t *s = cairo_image_surface_create_for_data(px, - CAIRO_FORMAT_ARGB32, w, h, stride); + CAIRO_FORMAT_ARGB32, psize, psize, stride); cairo_t *ct = cairo_create(s); NRPixBlock B; nr_pixblock_setup_extern( &B, NR_PIXBLOCK_MODE_R8G8B8A8N, ua.x0, ua.y0, ua.x1, ua.y1, - px + 4 * psize * (ua.y0 - area.y0) + + px + stride * (ua.y0 - area.y0) + 4 * (ua.x0 - area.x0), - 4 * psize, FALSE, FALSE ); + stride, FALSE, FALSE ); nr_arena_item_invoke_render(ct, root, &ua, &B, NR_ARENA_ITEM_RENDER_NO_CACHE ); nr_pixblock_release(&B); @@ -1038,35 +1037,10 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, cairo_surface_destroy(s); // convert to GdkPixbuf format - guint32 *ipx = reinterpret_cast<guint32*>(px); - for (int i = 0; i < h; ++i) { - for (int j = 0; j < w; ++j) { - int index = i * stride / 4 + j; - guint32 c = ipx[index]; - guint32 o = 0; - guint32 a = (c & 0xff000000) >> 24; - if (a != 0) { - // extract color components - guint32 r = (c & 0x00ff0000) >> 16; - guint32 g = (c & 0x0000ff00) >> 8; - guint32 b = (c & 0x000000ff); - // unpremultiply; adding a/2 gives correct rounding - r = (r * 255 + a/2) / a; - b = (b * 255 + a/2) / a; - g = (g * 255 + a/2) / a; - // combine into output -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - o = (r) | (g << 8) | (b << 16) | (a << 24); -#else - o = (r << 24) | (g << 16) | (b << 8) | (a); -#endif - } - ipx[index] = o; - } - } + convert_pixels_argb32_to_pixbuf(px, psize, psize, stride); if ( Inkscape::Preferences::get()->getBool("/debug/icons/overlaySvg") ) { - sp_icon_overlay_pixels( px, psize, psize, 4 * psize, 0x00, 0x00, 0xff ); + sp_icon_overlay_pixels( px, psize, psize, stride, 0x00, 0x00, 0xff ); } } } @@ -1119,8 +1093,7 @@ static std::list<gchar*> &icons_svg_paths() } // this function renders icons from icons.svg and returns the pixels. -static guchar *load_svg_pixels(gchar const *name, - unsigned /*lsize*/, unsigned psize) +static guchar *load_svg_pixels(gchar const *name, unsigned psize, unsigned &stride) { SPDocument *doc = NULL; NRArenaItem *root = NULL; @@ -1197,7 +1170,7 @@ static guchar *load_svg_pixels(gchar const *name, continue; } - px = sp_icon_doc_icon( doc, root, name, psize ); + px = sp_icon_doc_icon( doc, root, name, psize, stride); // if (px) { // g_message("Found icon %s in %s", name, doc_filename); // } @@ -1251,19 +1224,20 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) if (dump) { g_message("prerender_icon [%s] %d:%d", name, lsize, psize); } - guchar* px = load_svg_pixels(name, lsize, psize); + unsigned stride; + guchar* px = load_svg_pixels(name, psize, stride); if ( !px ) { // check for a fallback name if ( legacyNames.find(name) != legacyNames.end() ) { if ( dump ) { g_message("load_svg_pixels([%s]=%s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize); } - px = load_svg_pixels(legacyNames[name].c_str(), lsize, psize); + px = load_svg_pixels(legacyNames[name].c_str(), psize, stride); } } if (px) { GdkPixbuf* pb = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, TRUE, 8, - psize, psize, psize * 4, + psize, psize, stride, reinterpret_cast<GdkPixbufDestroyNotify>(g_free), NULL ); pb_cache[key] = pb; addToIconSet(pb, name, lsize, psize); @@ -1289,10 +1263,11 @@ static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, u // did we already load this icon at this scale/size? GdkPixbuf* pb = get_cached_pixbuf(key); if (!pb) { - guchar *px = load_svg_pixels(name, lsize, psize); + unsigned stride; + guchar *px = load_svg_pixels(name, psize, stride); if (px) { pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8, - psize, psize, psize * 4, + psize, psize, stride, (GdkPixbufDestroyNotify)g_free, NULL); pb_cache[key] = pb; addToIconSet(pb, name, lsize, psize); |
