summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthew Petroff <matthew@mpetroff.net>2013-09-15 19:26:40 +0000
committerMatthew Petroff <matthew@mpetroff.net>2013-09-15 19:26:40 +0000
commitd0f046b0aff8b4404c852990886f9afeca6d5c0f (patch)
tree9f03e5af0f2126a7d9cd7a7d11d61b5b99e16a3a /src
parentFix document unit change for disconnected connectors. (diff)
parentDutch translation update (diff)
downloadinkscape-d0f046b0aff8b4404c852990886f9afeca6d5c0f.tar.gz
inkscape-d0f046b0aff8b4404c852990886f9afeca6d5c0f.zip
Merge from trunk.
(bzr r12475.1.20)
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-utils.cpp143
-rw-r--r--src/display/cairo-utils.h20
-rw-r--r--src/display/drawing-image.cpp9
-rw-r--r--src/display/nr-filter-image.cpp18
-rw-r--r--src/display/nr-filter-image.h1
-rw-r--r--src/extension/internal/cairo-ps-out.cpp2
-rw-r--r--src/extension/internal/cairo-render-context.cpp47
-rw-r--r--src/extension/internal/cairo-renderer.cpp11
-rw-r--r--src/extension/internal/gdkpixbuf-input.cpp81
-rw-r--r--src/extension/internal/image-resolution.cpp18
-rw-r--r--src/helper/pixbuf-ops.cpp7
-rw-r--r--src/livarot/PathStroke.cpp34
-rw-r--r--src/livarot/ShapeSweep.cpp3
-rw-r--r--src/selection-chemistry.cpp3
-rw-r--r--src/sp-image.cpp611
-rw-r--r--src/sp-image.h2
-rw-r--r--src/sp-pattern.cpp10
-rw-r--r--src/ui/cache/svg_preview_cache.cpp19
-rw-r--r--src/ui/dialog/color-item.cpp12
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp2
-rw-r--r--src/ui/dialog/symbols.cpp118
-rw-r--r--src/ui/widget/color-preview.cpp11
-rw-r--r--src/widgets/dash-selector.cpp78
-rw-r--r--src/widgets/gradient-image.cpp184
-rw-r--r--src/widgets/stroke-marker-selector.cpp10
-rw-r--r--src/xml/repr-io.cpp82
26 files changed, 634 insertions, 902 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index fc56c7b26..755553033 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -28,16 +28,13 @@
#include "helper/geom-curves.h"
#include "display/cairo-templates.h"
-namespace {
-
/**
* Key for cairo_surface_t to keep track of current color interpolation value
* Only the address of the structure is used, it is never initialized. See:
* http://www.cairographics.org/manual/cairo-Types.html#cairo-user-data-key-t
*/
-cairo_user_data_key_t ci_key;
-
-} // namespace
+cairo_user_data_key_t ink_color_interpolation_key;
+cairo_user_data_key_t ink_pixbuf_key;
namespace Inkscape {
@@ -291,7 +288,7 @@ feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv)
SPColorInterpolation
get_cairo_surface_ci(cairo_surface_t *surface) {
- void* data = cairo_surface_get_user_data( surface, &ci_key );
+ void* data = cairo_surface_get_user_data( surface, &ink_color_interpolation_key );
if( data != NULL ) {
return (SPColorInterpolation)GPOINTER_TO_INT( data );
} else {
@@ -317,13 +314,13 @@ set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation ci) {
ink_cairo_surface_linear_to_srgb( surface );
}
- cairo_surface_set_user_data(surface, &ci_key, GINT_TO_POINTER (ci), NULL);
+ cairo_surface_set_user_data(surface, &ink_color_interpolation_key, GINT_TO_POINTER (ci), NULL);
}
}
void
copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out) {
- cairo_surface_set_user_data(out, &ci_key, cairo_surface_get_user_data(in, &ci_key), NULL);
+ cairo_surface_set_user_data(out, &ink_color_interpolation_key, cairo_surface_get_user_data(in, &ink_color_interpolation_key), NULL);
}
void
@@ -375,27 +372,117 @@ ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m)
}
void
-ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y)
+ink_cairo_set_source_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y)
{
- cairo_surface_t *pbs = ink_cairo_surface_create_for_argb32_pixbuf(pb);
+ cairo_surface_t *pbs = ink_cairo_surface_get_for_pixbuf(pb);
cairo_set_source_surface(ct, pbs, x, y);
- cairo_surface_destroy(pbs);
}
+/* The functions below implement the following hack:
+ *
+ * The pixels formats of Cairo and GdkPixbuf are different.
+ * GdkPixbuf accesses pixels as bytes, alpha is not premultiplied,
+ * and successive bytes of a single pixel contain R, G, B and A components.
+ * Cairo accesses pixels as 32-bit ints, alpha is premultiplied,
+ * and each int contains as 0xAARRGGBB, accessed with bitwise operations.
+ *
+ * In other words, on a little endian system, a GdkPixbuf will contain:
+ * char *data = "rgbargbargba...."
+ * int *data = { 0xAABBGGRR, 0xAABBGGRR, 0xAABBGGRR, ... }
+ * while a Cairo image surface will contain:
+ * char *data = "bgrabgrabgra...."
+ * int *data = { 0xAARRGGBB, 0xAARRGGBB, 0xAARRGGBB, ... }
+ *
+ * It is possible to convert between these two formats (almost) losslessly.
+ * Some color information from partially transparent regions of the image
+ * is lost, but the result when displaying this image will remain the same.
+ *
+ * The functions below allow interoperation between GdkPixbuf
+ * and Cairo surfaces, allowing pixbufs to be used as Cairo sources,
+ * and saving Cairo surfaces using GdkPixbuf APIs.
+ * This is implemented by creating a GdkPixbuf and a Cairo image surface
+ * which share their data. Depending on what is needed at a given time,
+ * the pixels are converted in place to the Cairo or the GdkPixbuf format.
+ * In this way, only one copy of the image data is needed.
+ *
+ * Given either a GdkPixbuf or a Cairo surface, these functions create
+ * the other object and convert to its format. The returned object should be
+ * freed using cairo_surface_destroy or g_object_unref when it's no longer
+ * needed.
+ *
+ * Memory ownership semantics:
+ * Regardless of whether the pixels are stored in memory originally belonging
+ * to Cairo surface or to GdkPixbuf, the GdkPixbuf is the master object.
+ * To free the memory, unref the GdkPixbuf ONLY.
+ */
+
+/**
+ * Converts the pixbuf to Cairo pixel format and returns an image surface
+ * which can be used as a source.
+ *
+ * The returned surface is owned by the GdkPixbuf and should not be freed.
+ * Calling this function causes the pixbuf to be unsuitable for use
+ * with GTK drawing functions until ink_pixbuf_ensure_normal() is called.
+ *
+ * @bug You have to call g_object_set_data(G_OBJECT(pb), "cairo_surface", NULL)
+ * when unrefing the last reference to the pixbuf. Otherwise there will be
+ * crashes, because cairo_surface_destroy is called after the pixbuf data
+ * is already freed.
+ */
cairo_surface_t *
-ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb)
+ink_cairo_surface_get_for_pixbuf(GdkPixbuf *pb)
{
- guchar *data = gdk_pixbuf_get_pixels(pb);
- int w = gdk_pixbuf_get_width(pb);
- int h = gdk_pixbuf_get_height(pb);
- int stride = gdk_pixbuf_get_rowstride(pb);
+ cairo_surface_t *pbs =
+ reinterpret_cast<cairo_surface_t*>(g_object_get_data(G_OBJECT(pb), "cairo_surface"));
+
+ ink_pixbuf_ensure_argb32(pb);
+
+ if (pbs == NULL) {
+ guchar *data = gdk_pixbuf_get_pixels(pb);
+ int w = gdk_pixbuf_get_width(pb);
+ int h = gdk_pixbuf_get_height(pb);
+ int stride = gdk_pixbuf_get_rowstride(pb);
+
+ // create a surface that stores the data
+ pbs = cairo_image_surface_create_for_data(
+ data, CAIRO_FORMAT_ARGB32, w, h, stride);
+
+ g_object_set_data_full(G_OBJECT(pb), "cairo_surface", pbs, (GDestroyNotify) cairo_surface_destroy);
+ cairo_surface_set_user_data(pbs, &ink_pixbuf_key, pb, NULL);
+ }
- cairo_surface_t *pbs = cairo_image_surface_create_for_data(
- data, CAIRO_FORMAT_ARGB32, w, h, stride);
return pbs;
}
/**
+ * Converts the Cairo surface to GdkPixbuf pixel format.
+ * GdkPixbuf takes ownership of the passed surface reference,
+ * so it should NOT be freed after calling this function.
+ */
+GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s)
+{
+ GdkPixbuf *pb = reinterpret_cast<GdkPixbuf*>(cairo_surface_get_user_data(s, &ink_pixbuf_key));
+ if (pb == NULL) {
+ pb = gdk_pixbuf_new_from_data(
+ cairo_image_surface_get_data(s), GDK_COLORSPACE_RGB, TRUE, 8,
+ cairo_image_surface_get_width(s), cairo_image_surface_get_height(s),
+ cairo_image_surface_get_stride(s), NULL, NULL);
+
+ g_object_set_data_full(G_OBJECT(pb), "pixel_format", g_strdup("argb32"), g_free);
+ g_object_set_data_full(G_OBJECT(pb), "cairo_surface", s, (GDestroyNotify) cairo_surface_destroy);
+
+ cairo_surface_set_user_data(s, &ink_pixbuf_key, pb, NULL);
+ } else {
+ g_warning("Received surface which is already owned by GdkPixbuf");
+ g_object_ref(pb);
+ }
+
+ ink_pixbuf_ensure_normal(pb);
+
+ return pb;
+}
+
+/**
* Cleanup function for GdkPixbuf.
* This function should be passed as the GdkPixbufDestroyNotify parameter
* to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by
@@ -445,7 +532,7 @@ cairo_surface_t *
ink_cairo_surface_create_identical(cairo_surface_t *s)
{
cairo_surface_t *ns = ink_cairo_surface_create_same_size(s, cairo_surface_get_content(s));
- cairo_surface_set_user_data(ns, &ci_key, cairo_surface_get_user_data(s, &ci_key), NULL);
+ cairo_surface_set_user_data(ns, &ink_color_interpolation_key, cairo_surface_get_user_data(s, &ink_color_interpolation_key), NULL);
return ns;
}
@@ -845,13 +932,20 @@ convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int stride)
* using it with GTK will result in corrupted drawings.
*/
void
-convert_pixbuf_normal_to_argb32(GdkPixbuf *pb)
+ink_pixbuf_ensure_argb32(GdkPixbuf *pb)
{
+ gchar *pixel_format = reinterpret_cast<gchar*>(g_object_get_data(G_OBJECT(pb), "pixel_format"));
+ if (pixel_format != NULL && strcmp(pixel_format, "argb32") == 0) {
+ // nothing to do
+ return;
+ }
+
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));
+ g_object_set_data_full(G_OBJECT(pb), "pixel_format", g_strdup("argb32"), g_free);
}
/**
@@ -859,13 +953,20 @@ convert_pixbuf_normal_to_argb32(GdkPixbuf *pb)
* Once this is done, the pixbuf can be used with GTK again.
*/
void
-convert_pixbuf_argb32_to_normal(GdkPixbuf *pb)
+ink_pixbuf_ensure_normal(GdkPixbuf *pb)
{
+ gchar *pixel_format = reinterpret_cast<gchar*>(g_object_get_data(G_OBJECT(pb), "pixel_format"));
+ if (pixel_format == NULL || strcmp(pixel_format, "pixbuf") == 0) {
+ // nothing to do
+ return;
+ }
+
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));
+ g_object_set_data_full(G_OBJECT(pb), "pixel_format", g_strdup("pixbuf"), g_free);
}
guint32 argb32_from_rgba(guint32 in)
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 016f72d00..289d4e01f 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -82,6 +82,17 @@ public:
} // namespace Inkscape
+enum InkPixelFormat {
+ INK_PIXEL_FORMAT_NONE,
+ INK_PIXEL_FORMAT_CAIRO,
+ INK_PIXEL_FORMAT_PIXBUF,
+ INK_PIXEL_FORMAT_LAST
+};
+
+// TODO: these declarations may not be needed in the header
+extern cairo_user_data_key_t ink_color_interpolation_key;
+extern cairo_user_data_key_t ink_pixbuf_key;
+
SPColorInterpolation get_cairo_surface_ci(cairo_surface_t *surface);
void set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation cif);
void copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out);
@@ -91,7 +102,7 @@ void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacit
void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m);
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m);
-void ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
+void ink_cairo_set_source_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
void ink_matrix_to_2geom(Geom::Affine &, cairo_matrix_t const &);
void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Affine const &);
@@ -116,9 +127,10 @@ cairo_pattern_t *ink_cairo_pattern_create_checkerboard();
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 *);
-cairo_surface_t *ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb);
+void ink_pixbuf_ensure_argb32(GdkPixbuf *);
+void ink_pixbuf_ensure_normal(GdkPixbuf *);
+cairo_surface_t *ink_cairo_surface_get_for_pixbuf(GdkPixbuf *pb);
+GdkPixbuf *ink_pixbuf_create_from_cairo_surface(cairo_surface_t *s);
void ink_cairo_pixbuf_cleanup(guchar *pixels, void *surface);
G_GNUC_CONST guint32 argb32_from_pixbuf(guint32 in);
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
index bdb7c15b0..46f066b8e 100644
--- a/src/display/drawing-image.cpp
+++ b/src/display/drawing-image.cpp
@@ -22,7 +22,7 @@ namespace Inkscape {
DrawingImage::DrawingImage(Drawing &drawing)
: DrawingItem(drawing)
, _pixbuf(NULL)
- , _surface(NULL)
+ , _surface(NULL) // this is owned by _pixbuf!
, _style(NULL)
, _new_surface(NULL)
{}
@@ -33,7 +33,6 @@ DrawingImage::~DrawingImage()
sp_style_unref(_style);
if (_pixbuf) {
if (_new_surface) cairo_surface_destroy(_new_surface);
- cairo_surface_destroy(_surface);
g_object_unref(_pixbuf);
}
}
@@ -47,10 +46,10 @@ DrawingImage::setARGB32Pixbuf(GdkPixbuf *pb)
}
if (_pixbuf != NULL) {
g_object_unref(_pixbuf);
- cairo_surface_destroy(_surface);
+ // unrefing the pixbuf also destroys surface
}
_pixbuf = pb;
- _surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
+ _surface = pb ? ink_cairo_surface_get_for_pixbuf(pb) : NULL;
_markForUpdate(STATE_ALL, false);
}
@@ -207,7 +206,7 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
int orgstride = cairo_image_surface_get_stride(_surface);
int newstride = cairo_image_surface_get_stride(_new_surface);
- cairo_surface_flush(_surface);
+ //cairo_surface_flush(_surface);
cairo_surface_flush(_new_surface);
for(int y=0; y<newheight; y++) {
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 7a27d857e..b9d73f0ad 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -30,7 +30,6 @@ FilterImage::FilterImage()
: SVGElem(0)
, document(0)
, feImageHref(0)
- , image_surface(0)
, broken_ref(false)
{ }
@@ -42,6 +41,7 @@ FilterImage::~FilterImage()
{
if (feImageHref)
g_free(feImageHref);
+ g_object_set_data(G_OBJECT(image->gobj()), "cairo_surface", NULL);
}
void FilterImage::render_cairo(FilterSlot &slot)
@@ -172,18 +172,10 @@ void FilterImage::render_cairo(FilterSlot &slot)
if (!has_alpha) {
image = image->add_alpha(false, 0, 0, 0);
}
-
- // Native size of image
- // width = image->get_width();
- // height = image->get_height();
- // rowstride = image->get_rowstride();
-
- convert_pixbuf_normal_to_argb32(image->gobj());
-
- image_surface = cairo_image_surface_create_for_data(image->get_pixels(),
- CAIRO_FORMAT_ARGB32, image->get_width(), image->get_height(), image->get_rowstride());
}
+ cairo_surface_t *image_surface = ink_cairo_surface_get_for_pixbuf(image->gobj());
+
Geom::Rect sa = slot.get_slot_area();
cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
sa.width(), sa.height());
@@ -310,9 +302,7 @@ void FilterImage::set_href(const gchar *href){
if (feImageHref) g_free (feImageHref);
feImageHref = (href) ? g_strdup (href) : NULL;
- if (image_surface) {
- cairo_surface_destroy(image_surface);
- }
+ g_object_set_data(G_OBJECT(image->gobj()), "cairo_surface", NULL);
image.reset();
broken_ref = false;
}
diff --git a/src/display/nr-filter-image.h b/src/display/nr-filter-image.h
index 05b7d65a8..f45f42265 100644
--- a/src/display/nr-filter-image.h
+++ b/src/display/nr-filter-image.h
@@ -44,7 +44,6 @@ private:
SPDocument *document;
gchar *feImageHref;
Glib::RefPtr<Gdk::Pixbuf> image;
- cairo_surface_t *image_surface;
float feImageX, feImageY, feImageWidth, feImageHeight;
unsigned int aspect_align, aspect_clip;
bool broken_ref;
diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp
index e06c9f30d..5f535dc64 100644
--- a/src/extension/internal/cairo-ps-out.cpp
+++ b/src/extension/internal/cairo-ps-out.cpp
@@ -340,7 +340,7 @@ CairoPsOutput::init (void)
"<_option value=\"page\">" N_("Use document's page size") "</_option>"
"<_option value=\"drawing\">" N_("Use exported object's size") "</_option>"
"</param>"
- "<param name=\"bleed\" gui-text=\"" N_("Bleed/margin (mm)") "\" type=\"float\" min=\"-10000\" max=\"10000\">0</param>\n"
+ "<param name=\"bleed\" gui-text=\"" N_("Bleed/margin (mm):") "\" type=\"float\" min=\"-10000\" max=\"10000\">0</param>\n"
"<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID:") "\" type=\"string\"></param>\n"
"<output>\n"
"<extension>.ps</extension>\n"
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index 3c222bd9e..a950fa177 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -1306,7 +1306,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p
{
cairo_set_dash(_cr, style->stroke_dash.dash, style->stroke_dash.n_dash, style->stroke_dash.offset);
} else {
- cairo_set_dash(_cr, NULL, 0, 0.0); // disable dashing
+ cairo_set_dash(_cr, NULL, 0, 0.0); // disable dashing
}
cairo_set_line_width(_cr, style->stroke_width.computed);
@@ -1314,30 +1314,30 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p
// set line join type
cairo_line_join_t join = CAIRO_LINE_JOIN_MITER;
switch (style->stroke_linejoin.computed) {
- case SP_STROKE_LINEJOIN_MITER:
- join = CAIRO_LINE_JOIN_MITER;
- break;
- case SP_STROKE_LINEJOIN_ROUND:
- join = CAIRO_LINE_JOIN_ROUND;
- break;
- case SP_STROKE_LINEJOIN_BEVEL:
- join = CAIRO_LINE_JOIN_BEVEL;
- break;
+ case SP_STROKE_LINEJOIN_MITER:
+ join = CAIRO_LINE_JOIN_MITER;
+ break;
+ case SP_STROKE_LINEJOIN_ROUND:
+ join = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case SP_STROKE_LINEJOIN_BEVEL:
+ join = CAIRO_LINE_JOIN_BEVEL;
+ break;
}
cairo_set_line_join(_cr, join);
// set line cap type
cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
switch (style->stroke_linecap.computed) {
- case SP_STROKE_LINECAP_BUTT:
- cap = CAIRO_LINE_CAP_BUTT;
- break;
- case SP_STROKE_LINECAP_ROUND:
- cap = CAIRO_LINE_CAP_ROUND;
- break;
- case SP_STROKE_LINECAP_SQUARE:
- cap = CAIRO_LINE_CAP_SQUARE;
- break;
+ case SP_STROKE_LINECAP_BUTT:
+ cap = CAIRO_LINE_CAP_BUTT;
+ break;
+ case SP_STROKE_LINECAP_ROUND:
+ cap = CAIRO_LINE_CAP_ROUND;
+ break;
+ case SP_STROKE_LINECAP_SQUARE:
+ cap = CAIRO_LINE_CAP_SQUARE;
+ break;
}
cairo_set_line_cap(_cr, cap);
cairo_set_miter_limit(_cr, MAX(1, style->stroke_miterlimit.value));
@@ -1453,10 +1453,10 @@ bool CairoRenderContext::renderImage(GdkPixbuf *pb,
// TODO: reenable merge_opacity if useful
float opacity = _state->opacity;
- cairo_surface_t *image_surface = ink_cairo_surface_create_for_argb32_pixbuf(pb);
+ cairo_surface_t *image_surface = ink_cairo_surface_get_for_pixbuf(pb);
if (cairo_surface_status(image_surface)) {
TRACE(("Image surface creation failed:\n%s\n", cairo_status_to_string(cairo_surface_status(image_surface))));
- return false;
+ return false;
}
cairo_save(_cr);
@@ -1475,7 +1475,6 @@ bool CairoRenderContext::renderImage(GdkPixbuf *pb,
cairo_paint_with_alpha(_cr, opacity);
cairo_restore(_cr);
- cairo_surface_destroy(image_surface);
return true;
}
@@ -1676,9 +1675,9 @@ _write_callback(void *closure, const unsigned char *data, unsigned int length)
written = fwrite (data, 1, length, file);
if (written == length)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_STATUS_SUCCESS;
else
- return CAIRO_STATUS_WRITE_ERROR;
+ return CAIRO_STATUS_WRITE_ERROR;
}
#include "clear-n_.h"
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 3ffd6b2ed..ac2fe5ba3 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -449,7 +449,7 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx)
Geom::OptRect bbox = item->desktopVisualBounds();
// no bbox, e.g. empty group
- if (!bbox) {
+ if (!bbox) {
return;
}
@@ -503,8 +503,13 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx)
if (pb) {
TEST(gdk_pixbuf_save( pb, "bitmap.png", "png", NULL, NULL ));
- // TODO this is stupid - we just converted to pixbuf format when generating the bitmap!
- convert_pixbuf_normal_to_argb32(pb);
+
+ /* TODO: find a way to avoid a duplicate conversion between
+ * Cairo and GdkPixbuf pixel formats here.
+ * Internally, generate_internal_bitmap creates a Cairo surface,
+ * but then converts it to pixbuf format. In turn, renderImage()
+ * below converts back to Cairo format.
+ */
ctx->renderImage(pb, t, item->style);
g_object_unref(pb);
pb = 0;
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp
index 994258ccc..117c2fe39 100644
--- a/src/extension/internal/gdkpixbuf-input.cpp
+++ b/src/extension/internal/gdkpixbuf-input.cpp
@@ -19,23 +19,18 @@
namespace Inkscape {
namespace IO {
-GdkPixbuf* pixbuf_new_from_file( char const *utf8name, GError **error );
+// this is defined in sp-image.cpp
+GdkPixbuf* pixbuf_new_from_file(char const *filename, time_t &modTime, gchar*& pixPath);
}
namespace Extension {
namespace Internal {
-static std::set<Glib::ustring> create_lossy_set()
-{
- std::set<Glib::ustring> lossy;
- lossy.insert(".jpg");
- lossy.insert(".jpeg");
- return lossy;
-}
-
SPDocument *
GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
{
+ // determine whether the image should be embedded
+ // TODO: this logic seems very wrong
bool embed = false;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
Glib::ustring attr = prefs->getString("/dialogs/import/link");
@@ -52,27 +47,14 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
}
SPDocument *doc = NULL;
- GdkPixbuf *pb = Inkscape::IO::pixbuf_new_from_file( uri, NULL );
- static std::set<Glib::ustring> lossy = create_lossy_set();
-
- if (pb) { /* We are readable */
- // TODO revisit: bool is_lossy;
- Glib::ustring mime_type, ext;
- Glib::ustring u = uri;
- std::size_t dotpos = u.rfind('.');
- if (dotpos != Glib::ustring::npos) {
- ext = u.substr(dotpos, Glib::ustring::npos);
- }
+ gchar *pixpath = NULL;
+ time_t dummy;
+ GdkPixbuf *pb = Inkscape::IO::pixbuf_new_from_file(uri, dummy, pixpath);
- // HACK: replace with something better based on GIO
- if (!ext.empty() && lossy.find(ext) != lossy.end()) {
- // TODO revisit: is_lossy = true;
- mime_type = "image/jpeg";
- } else {
- // TODO revisit: is_lossy = false;
- mime_type = "image/png";
- }
+ // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage.
+ // Find a way to create the pixbuf only once.
+ if (pb) {
doc = SPDocument::createNewDoc(NULL, TRUE, TRUE);
bool saved = DocumentUndo::getUndoSensitive(doc);
DocumentUndo::setUndoSensitive(doc, false); // no need to undo in this temporary document
@@ -85,40 +67,22 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
double xscale = 1;
double yscale = 1;
- gchar const *str = gdk_pixbuf_get_option( pb, "Inkscape::DpiX" );
- if ( str ) {
- gint dpi = atoi(str);
- if ( dpi > 0 && dpi != 72 ) {
- xscale = 72.0 / (double)dpi;
- }
- } else {
- if (!ir && !forcexdpi)
- ir = new ImageResolution(uri);
- if (ir && ir->ok())
- xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi
- else
- xscale = 90.0 / defaultxdpi;
- }
- width *= xscale;
- str = gdk_pixbuf_get_option( pb, "Inkscape::DpiY" );
- if ( str ) {
- gint dpi = atoi(str);
- if ( dpi > 0 && dpi != 72 ) {
- yscale = 72.0 / (double)dpi;
- }
+ if (!ir && !forcexdpi) {
+ ir = new ImageResolution(uri);
+ }
+ if (ir && ir->ok()) {
+ xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi
+ yscale = 900.0 / floor(10.*ir->y() + .5);
} else {
- if (!ir && !forcexdpi)
- ir = new ImageResolution(uri);
- if (ir && ir->ok())
- yscale = 900.0 / floor(10.*ir->y() + .5); // round-off to 0.1 dpi
- else
- yscale = 90.0 / defaultxdpi;
+ xscale = 90.0 / defaultxdpi;
+ yscale = 90.0 / defaultxdpi;
}
+
+ width *= xscale;
height *= yscale;
- if (ir)
- delete ir;
+ delete ir; // deleting NULL is safe
// Create image node
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -127,7 +91,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
sp_repr_set_svg_double(image_node, "height", height);
if (embed) {
- sp_embed_image(image_node, pb, mime_type);
+ sp_embed_image(image_node, pb);
} else {
// convert filename to uri
gchar* _uri = g_filename_to_uri(uri, NULL, NULL);
@@ -139,6 +103,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
}
}
+ g_object_set_data(G_OBJECT(pb), "cairo_surface", NULL);
g_object_unref(pb);
// Add it to the current layer
diff --git a/src/extension/internal/image-resolution.cpp b/src/extension/internal/image-resolution.cpp
index 3c254a59c..a9d33e831 100644
--- a/src/extension/internal/image-resolution.cpp
+++ b/src/extension/internal/image-resolution.cpp
@@ -14,13 +14,21 @@
#include "image-resolution.h"
#define IR_TRY_PNG 1
+#include <png.h>
+
#ifdef HAVE_EXIF
-#define IR_TRY_EXIF 1
+#include <math.h>
+#include <libexif/exif-data.h>
#endif
+
#define IR_TRY_EXIV 0
+
#ifdef HAVE_JPEG
#define IR_TRY_JFIF 1
+#include <jpeglib.h>
+#include <setjmp.h>
#endif
+
#ifdef WITH_IMAGE_MAGICK
#include <Magick++.h>
#endif
@@ -62,8 +70,6 @@ double ImageResolution::y() const {
#if IR_TRY_PNG
-
-#include <png.h>
static bool haspngheader(FILE *fp) {
unsigned char header[8];
@@ -133,9 +139,6 @@ void ImageResolution::readpng(char const *) {
#if IR_TRY_EXIF
-#include <math.h>
-#include <libexif/exif-data.h>
-
static double exifDouble(ExifEntry *entry, ExifByteOrder byte_order) {
switch (entry->format) {
case EXIF_FORMAT_BYTE: {
@@ -264,9 +267,6 @@ void ImageResolution::readexiv(char const *) {
#if IR_TRY_JFIF
-#include <jpeglib.h>
-#include <setjmp.h>
-
static void irjfif_error_exit(j_common_ptr cinfo) {
longjmp(*(jmp_buf*)cinfo->client_data, 1);
}
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index a53da5bba..6a8897b71 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -146,12 +146,7 @@ GdkPixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*
// render items
drawing.render(ct, final_bbox, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
- pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(surface),
- GDK_COLORSPACE_RGB, TRUE,
- 8, width, height, cairo_image_surface_get_stride(surface),
- ink_cairo_pixbuf_cleanup,
- surface);
- convert_pixbuf_argb32_to_normal(pixbuf);
+ pixbuf = ink_pixbuf_create_from_cairo_surface(surface);
}
else
{
diff --git a/src/livarot/PathStroke.cpp b/src/livarot/PathStroke.cpp
index cdd5cae6d..50c335176 100644
--- a/src/livarot/PathStroke.cpp
+++ b/src/livarot/PathStroke.cpp
@@ -456,19 +456,20 @@ Path::DoLeftJoin (Shape * dest, double width, JoinType join, Geom::Point pos,
} else {*/
leftStNo = dest->AddPoint (pos + width * pnor);
leftEnNo = dest->AddPoint (pos + width * nnor);
- int midNo = dest->AddPoint (pos);
- int nEdge=dest->AddEdge (leftEnNo, midNo);
- if ( dest->hasBackData() ) {
- dest->ebData[nEdge].pathID=pathID;
- dest->ebData[nEdge].pieceID=pieceID;
- dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
- }
- nEdge=dest->AddEdge (midNo, leftStNo);
+// int midNo = dest->AddPoint (pos);
+// int nEdge=dest->AddEdge (leftEnNo, midNo);
+ int nEdge=dest->AddEdge (leftEnNo, leftStNo);
if ( dest->hasBackData() ) {
dest->ebData[nEdge].pathID=pathID;
dest->ebData[nEdge].pieceID=pieceID;
dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
}
+// nEdge=dest->AddEdge (midNo, leftStNo);
+// if ( dest->hasBackData() ) {
+// dest->ebData[nEdge].pathID=pathID;
+// dest->ebData[nEdge].pieceID=pieceID;
+// dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
+// }
// }
}
else
@@ -678,19 +679,20 @@ Path::DoRightJoin (Shape * dest, double width, JoinType join, Geom::Point pos,
} else {*/
rightStNo = dest->AddPoint (pos - width*pnor);
rightEnNo = dest->AddPoint (pos - width*nnor);
- int midNo = dest->AddPoint (pos);
- int nEdge=dest->AddEdge (rightStNo, midNo);
+// int midNo = dest->AddPoint (pos);
+// int nEdge=dest->AddEdge (rightStNo, midNo);
+ int nEdge=dest->AddEdge (rightStNo, rightEnNo);
if ( dest->hasBackData() ) {
dest->ebData[nEdge].pathID=pathID;
dest->ebData[nEdge].pieceID=pieceID;
dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
}
- nEdge=dest->AddEdge (midNo, rightEnNo);
- if ( dest->hasBackData() ) {
- dest->ebData[nEdge].pathID=pathID;
- dest->ebData[nEdge].pieceID=pieceID;
- dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
- }
+// nEdge=dest->AddEdge (midNo, rightEnNo);
+// if ( dest->hasBackData() ) {
+// dest->ebData[nEdge].pathID=pathID;
+// dest->ebData[nEdge].pieceID=pieceID;
+// dest->ebData[nEdge].tSt=dest->ebData[nEdge].tEn=tID;
+// }
// }
}
}
diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp
index ff58b4a71..1954139fa 100644
--- a/src/livarot/ShapeSweep.cpp
+++ b/src/livarot/ShapeSweep.cpp
@@ -2672,7 +2672,8 @@ Shape::TesteAdjacency (Shape * a, int no, const Geom::Point atx, int nPt,
double e = IHalfRound ((cross (diff,adir)) * a->eData[no].isqlength);
if (-3 < e && e < 3)
{
- double rad = HalfRound (0.501); // when using single precision, 0.505 is better (0.5 would be the correct value,
+ double rad = HalfRound (1);
+// double rad = HalfRound (0.501); // when using single precision, 0.505 is better (0.5 would be the correct value,
// but it produces lots of bugs)
diff1[0] = diff[0] - rad;
diff1[1] = diff[1] - rad;
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 14e3462d7..552fc5218 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -3457,6 +3457,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
}
t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse(); /// @fixme hardcoded doc2dt transform?
+ // TODO: avoid roundtrip via file
// Do the export
sp_export_png_file(document, filepath,
bbox->min()[Geom::X], bbox->min()[Geom::Y],
@@ -3483,7 +3484,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop)
if (pb) {
// Create the repr for the image
Inkscape::XML::Node * repr = xml_doc->createElement("svg:image");
- sp_embed_image(repr, pb, "image/png");
+ sp_embed_image(repr, pb);
if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 90 dpi, snap it to pixel grid
sp_repr_set_svg_double(repr, "width", width);
sp_repr_set_svg_double(repr, "height", height);
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index 10d294d5c..0e692eb40 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -57,15 +57,13 @@
//#define DEBUG_LCMS
#ifdef DEBUG_LCMS
-
-
#define DEBUG_MESSAGE(key, ...)\
{\
g_message( __VA_ARGS__ );\
}
-
-
#include <gtk/gtk.h>
+#else
+#define DEBUG_MESSAGE(key, ...)
#endif // DEBUG_LCMS
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
/*
@@ -98,12 +96,7 @@ static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai)
static void sp_image_update_canvas_image (SPImage *image);
static GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
static GdkPixbuf * sp_image_repr_read_b64 (const gchar * uri_data);
-
-extern "C"
-{
- void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length );
-}
-
+static void pixbuf_set_mime_data(GdkPixbuf *pb, guchar *data, gsize len, GdkPixbufFormat *fmt);
#ifdef DEBUG_LCMS
extern guint update_in_progress;
@@ -133,291 +126,22 @@ extern guint update_in_progress;
gtk_widget_show_all( dialog );\
}\
}
+#else // DEBUG_LCMS
+#define DEBUG_MESSAGE_SCISLAC(key, ...)
#endif // DEBUG_LCMS
namespace Inkscape {
namespace IO {
-class PushPull
-{
-public:
- gboolean first;
- FILE* fp;
- guchar* scratch;
- gsize size;
- gsize used;
- gsize offset;
- GdkPixbufLoader *loader;
-
- PushPull() : first(TRUE),
- fp(0),
- scratch(0),
- size(0),
- used(0),
- offset(0),
- loader(0) {};
-
- gboolean readMore()
- {
- gboolean good = FALSE;
- if ( offset )
- {
- g_memmove( scratch, scratch + offset, used - offset );
- used -= offset;
- offset = 0;
- }
- if ( used < size )
- {
- gsize space = size - used;
- gsize got = fread( scratch + used, 1, space, fp );
- if ( got )
- {
- if ( loader )
- {
- GError *err = NULL;
- //g_message( " __read %d bytes", (int)got );
- if ( !gdk_pixbuf_loader_write( loader, scratch + used, got, &err ) )
- {
- //g_message("_error writing pixbuf data");
- }
- }
-
- used += got;
- good = TRUE;
- }
- else
- {
- good = FALSE;
- }
- }
- return good;
- }
-
- gsize available() const
- {
- return (used - offset);
- }
-
- gsize readOut( gpointer data, gsize length )
- {
- gsize giving = available();
- if ( length < giving )
- {
- giving = length;
- }
- g_memmove( data, scratch + offset, giving );
- offset += giving;
- if ( offset >= used )
- {
- offset = 0;
- used = 0;
- }
- return giving;
- }
-
- void clear()
- {
- offset = 0;
- used = 0;
- }
-
-private:
- PushPull& operator = (const PushPull& other);
- PushPull(const PushPull& other);
-};
-
-static void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length )
-{
-// g_message( "user_read_data(%d)", length );
-
- PushPull* youme = (PushPull*)png_get_io_ptr(png_ptr);
-
- gsize filled = 0;
- gboolean canRead = TRUE;
-
- while ( filled < length && canRead )
- {
- gsize some = youme->readOut( data + filled, length - filled );
- filled += some;
- if ( filled < length )
- {
- canRead &= youme->readMore();
- }
- }
-// g_message("things out");
-}
-
-
-static bool readPngAndHeaders( PushPull &youme, gint & dpiX, gint & dpiY )
-{
- bool good = true;
-
- gboolean isPng = !png_sig_cmp( youme.scratch + youme.offset, 0, youme.available() );
- //g_message( " png? %s", (isPng ? "Yes":"No") );
- if ( isPng ) {
- png_structp pngPtr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
- 0, //(png_voidp)user_error_ptr,
- 0, //user_error_fn,
- 0 //user_warning_fn
- );
- png_infop infoPtr = pngPtr ? png_create_info_struct( pngPtr ) : 0;
-
- if ( pngPtr && infoPtr ) {
- if ( setjmp(png_jmpbuf(pngPtr)) ) {
- // libpng calls longjmp to return here if an error occurs.
- good = false;
- }
-
- if (good) {
- png_set_read_fn( pngPtr, &youme, user_read_data );
- //g_message( "In" );
-
- //png_read_info( pngPtr, infoPtr );
- png_read_png( pngPtr, infoPtr, PNG_TRANSFORM_IDENTITY, 0 );
-
- //g_message("out");
-
- /*
- if ( png_get_valid( pngPtr, infoPtr, PNG_INFO_pHYs ) )
- {
- g_message("pHYs chunk now valid" );
- }
- if ( png_get_valid( pngPtr, infoPtr, PNG_INFO_sCAL ) )
- {
- g_message("sCAL chunk now valid" );
- }
- */
-
- png_uint_32 res_x = 0;
- png_uint_32 res_y = 0;
- int unit_type = 0;
- if ( png_get_pHYs( pngPtr, infoPtr, &res_x, &res_y, &unit_type) ) {
-// g_message( "pHYs yes (%d, %d) %d (%s)", (int)res_x, (int)res_y, unit_type,
-// (unit_type == 1? "per meter" : "unknown")
-// );
-
-// g_message( " dpi: (%d, %d)",
-// (int)(0.5 + ((double)res_x)/39.37),
-// (int)(0.5 + ((double)res_y)/39.37) );
- if ( unit_type == PNG_RESOLUTION_METER )
- {
- // TODO come up with a more accurate DPI setting
- dpiX = (int)(0.5 + ((double)res_x)/39.37);
- dpiY = (int)(0.5 + ((double)res_y)/39.37);
- }
- } else {
-// g_message( "pHYs no" );
- }
-
-/*
- double width = 0;
- double height = 0;
- int unit = 0;
- if ( png_get_sCAL(pngPtr, infoPtr, &unit, &width, &height) )
- {
- gchar* vals[] = {
- "unknown", // PNG_SCALE_UNKNOWN
- "meter", // PNG_SCALE_METER
- "radian", // PNG_SCALE_RADIAN
- "last", //
- NULL
- };
-
- g_message( "sCAL: (%f, %f) %d (%s)",
- width, height, unit,
- ((unit >= 0 && unit < 3) ? vals[unit]:"???")
- );
- }
-*/
-
-#if defined(PNG_sRGB_SUPPORTED)
- {
- int intent = 0;
- if ( png_get_sRGB(pngPtr, infoPtr, &intent) ) {
-// g_message("Found an sRGB png chunk");
- }
- }
-#endif // defined(PNG_sRGB_SUPPORTED)
-
-#if defined(PNG_cHRM_SUPPORTED)
- {
- double white_x = 0;
- double white_y = 0;
- double red_x = 0;
- double red_y = 0;
- double green_x = 0;
- double green_y = 0;
- double blue_x = 0;
- double blue_y = 0;
-
- if ( png_get_cHRM(pngPtr, infoPtr,
- &white_x, &white_y,
- &red_x, &red_y,
- &green_x, &green_y,
- &blue_x, &blue_y) ) {
-// g_message("Found a cHRM png chunk");
- }
- }
-#endif // defined(PNG_cHRM_SUPPORTED)
-
-#if defined(PNG_gAMA_SUPPORTED)
- {
- double file_gamma = 0;
- if ( png_get_gAMA(pngPtr, infoPtr, &file_gamma) ) {
-// g_message("Found a gAMA png chunk");
- }
- }
-#endif // defined(PNG_gAMA_SUPPORTED)
-
-#if defined(PNG_iCCP_SUPPORTED)
- {
- png_charp name = 0;
- int compression_type = 0;
-#if (PNG_LIBPNG_VER < 10500)
- png_charp profile = 0;
-#else
- png_bytep profile = 0;
-#endif
- png_uint_32 proflen = 0;
- if ( png_get_iCCP(pngPtr, infoPtr, &name, &compression_type, &profile, &proflen) ) {
-// g_message("Found an iCCP chunk named [%s] with %d bytes and comp %d", name, proflen, compression_type);
- }
- }
-#endif // defined(PNG_iCCP_SUPPORTED)
-
- }
- } else {
- g_message("Error when creating PNG read struct");
- }
-
- // now clean it up.
- if (pngPtr && infoPtr) {
- png_destroy_read_struct( &pngPtr, &infoPtr, 0 );
- pngPtr = 0;
- infoPtr = 0;
- } else if (pngPtr) {
- png_destroy_read_struct( &pngPtr, 0, 0 );
- pngPtr = 0;
- }
- } else {
- good = false; // Was not a png file
- }
-
- return good;
-}
-
-GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, gchar*& pixPath, GError **/*error*/ )
+GdkPixbuf* pixbuf_new_from_file(const char *filename, time_t &modTime, gchar*& pixPath)
{
GdkPixbuf* buf = NULL;
- PushPull youme;
- gint dpiX = 0;
- gint dpiY = 0;
modTime = 0;
if ( pixPath ) {
g_free(pixPath);
pixPath = NULL;
}
-
+
//test correctness of filename
if (!g_file_test (filename, G_FILE_TEST_EXISTS)){
return NULL;
@@ -425,95 +149,43 @@ GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, gchar*&
struct stat stdir;
int val = g_stat(filename, &stdir);
if (stdir.st_mode & S_IFDIR){
- //filename is not correct: it is a directory name and hence further code can not return valid results
+ g_warning("Linked image file %s is a directory", filename);
return NULL;
}
- dump_fopen_call( filename, "pixbuf_new_from_file" );
- FILE* fp = fopen_utf8name( filename, "r" );
- if ( fp )
- {
- {
- // struct stat st;
- // memset(&st, 0, sizeof(st));
- // int val = g_stat(filename, &st);
- if ( !val ) {
- modTime = stdir.st_mtime;//st.st_mtime;
- pixPath = g_strdup(filename);
- }
+ // we need to load the entire pixbuf into memory
+ gchar *data = NULL;
+ gsize len = 0;
+
+ if (g_file_get_contents(filename, &data, &len, NULL)) {
+ if (!val) {
+ modTime = stdir.st_mtime;
+ pixPath = g_strdup(filename);
}
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
- if ( loader )
- {
- GError *err = NULL;
-
- // short buffer
- guchar scratch[1024];
- gboolean latter = FALSE;
-
- youme.fp = fp;
- youme.scratch = scratch;
- youme.size = sizeof(scratch);
- youme.used = 0;
- youme.offset = 0;
- youme.loader = loader;
-
- while ( !feof(fp) )
- {
- if ( youme.readMore() ) {
- if ( youme.first ) {
- //g_message( "First data chunk" );
- youme.first = FALSE;
- if (readPngAndHeaders(youme, dpiX, dpiY))
- {
- // TODO set the dpi to be read elsewhere
- }
- } else if ( !latter ) {
- latter = TRUE;
- }
- // Now clear out the buffer so we can read more.
- // (dumping out unused)
- youme.clear();
- }
- }
-
- gboolean ok = gdk_pixbuf_loader_close(loader, &err);
- if ( ok ) {
- buf = gdk_pixbuf_loader_get_pixbuf( loader );
- if ( buf ) {
- g_object_ref(buf);
- }
- } else {
- // do something
- g_message("error loading pixbuf at close");
- }
-
- g_object_unref(loader);
+ gdk_pixbuf_loader_write(loader, (guchar *) data, len, NULL);
+ gdk_pixbuf_loader_close(loader, NULL);
+
+ buf = gdk_pixbuf_loader_get_pixbuf(loader);
+ if (buf) {
+ g_object_ref(buf);
+ buf = sp_image_pixbuf_force_rgba(buf);
+ pixbuf_set_mime_data(buf, (guchar *) data, len, gdk_pixbuf_loader_get_format(loader));
} else {
- g_message("error when creating pixbuf loader");
+ g_free(data);
+ g_warning("Error loading pixbuf");
}
- fclose( fp );
- fp = 0;
+
+ // TODO: we could also read DPI, ICC profile, gamma correction, and other information
+ // from the file. This can be done by using format-specific libraries e.g. libpng.
} else {
- g_warning ("Unable to open linked file: %s", filename);
+ g_warning("Unable to open linked file: %s", filename);
}
return buf;
}
-GdkPixbuf* pixbuf_new_from_file( const char *filename, GError **error )
-{
- time_t modTime = 0;
- gchar* pixPath = 0;
- GdkPixbuf* result = pixbuf_new_from_file( filename, modTime, pixPath, error );
- if (pixPath) {
- g_free(pixPath);
- }
- return result;
-}
-
-
}
}
@@ -594,6 +266,7 @@ static void sp_image_release( SPObject *object )
}
if (image->pixbuf) {
+ g_object_set_data(G_OBJECT(image->pixbuf), "cairo_surface", NULL);
g_object_unref (image->pixbuf);
image->pixbuf = NULL;
}
@@ -715,23 +388,25 @@ static void sp_image_set( SPObject *object, unsigned int key, const gchar *value
image->aspect_clip = clip;
}
break;
+
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
case SP_PROP_COLOR_PROFILE:
if ( image->color_profile ) {
g_free (image->color_profile);
}
image->color_profile = (value) ? g_strdup (value) : NULL;
-#ifdef DEBUG_LCMS
+
if ( value ) {
DEBUG_MESSAGE( lcmsFour, "<image> color-profile set to '%s'", value );
} else {
DEBUG_MESSAGE( lcmsFour, "<image> color-profile cleared" );
}
-#endif // DEBUG_LCMS
+
// TODO check on this HREF_MODIFIED flag
object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_IMAGE_HREF_MODIFIED_FLAG);
break;
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
default:
if (((SPObjectClass *) (sp_image_parent_class))->set)
((SPObjectClass *) (sp_image_parent_class))->set (object, key, value);
@@ -773,7 +448,6 @@ static void sp_image_update( SPObject *object, SPCtx *ctx, unsigned int flags )
object->getRepr()->attribute("sodipodi:absref"),
doc->getBase());
if (pixbuf) {
- pixbuf = sp_image_pixbuf_force_rgba (pixbuf);
// BLIP
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
if ( image->color_profile )
@@ -784,9 +458,8 @@ static void sp_image_update( SPObject *object, SPCtx *ctx, unsigned int flags )
guchar* px = gdk_pixbuf_get_pixels( pixbuf );
if ( px ) {
-#ifdef DEBUG_LCMS
DEBUG_MESSAGE( lcmsFive, "in <image>'s sp_image_update. About to call colorprofile_get_handle()" );
-#endif // DEBUG_LCMS
+
guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN;
cmsHPROFILE prof = Inkscape::CMSSystem::getHandle( object->document,
&profIntent,
@@ -826,34 +499,22 @@ static void sp_image_update( SPObject *object, SPCtx *ctx, unsigned int flags )
}
cmsDeleteTransform( transf );
- }
-#ifdef DEBUG_LCMS
- else
- {
+ } else {
DEBUG_MESSAGE( lcmsSix, "in <image>'s sp_image_update. Unable to create LCMS transform." );
}
-#endif // DEBUG_LCMS
+
cmsCloseProfile( destProf );
- }
-#ifdef DEBUG_LCMS
- else
- {
+ } else {
DEBUG_MESSAGE( lcmsSeven, "in <image>'s sp_image_update. Profile type is named color. Can't transform." );
}
-#endif // DEBUG_LCMS
- }
-#ifdef DEBUG_LCMS
- else
- {
+ } else {
DEBUG_MESSAGE( lcmsEight, "in <image>'s sp_image_update. No profile found." );
}
-#endif // DEBUG_LCMS
}
}
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+
image->pixbuf = pixbuf;
- // convert to premultiplied native-endian ARGB for display with Cairo
- convert_pixbuf_normal_to_argb32(image->pixbuf);
}
}
}
@@ -1018,7 +679,9 @@ static void sp_image_print( SPItem *item, SPPrintContext *ctx )
if (image->pixbuf && (image->width.computed > 0.0) && (image->height.computed > 0.0) ) {
GdkPixbuf *pb = gdk_pixbuf_copy(image->pixbuf);
- convert_pixbuf_argb32_to_normal(pb);
+ // GObject data is not copied, so we have to set the pixel format explicitly
+ g_object_set_data_full(G_OBJECT(pb), "pixel_format", g_strdup("argb32"), g_free);
+ ink_pixbuf_ensure_normal(pb);
guchar *px = gdk_pixbuf_get_pixels(pb);
int w = gdk_pixbuf_get_width(pb);
@@ -1056,7 +719,7 @@ static void sp_image_print( SPItem *item, SPPrintContext *ctx )
t = ti * t;
sp_print_image_R8G8B8A8_N(ctx, px + trimx*pixskip + trimy*rs, trimwidth, trimheight, rs, t, item->style);
}
- free(px); // else big memory leak on each image print!
+ g_object_unref(pb);
}
}
@@ -1110,13 +773,14 @@ GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gcha
pixPath = 0;
}
- const gchar *filename = href;
+ gchar const *filename = href;
+
if (filename != NULL) {
if (strncmp (filename,"file:",5) == 0) {
gchar *fullname = g_filename_from_uri(filename, NULL, NULL);
if (fullname) {
- // TODO check this. Was doing a UTF-8 to filename conversion here.
- pixbuf = Inkscape::IO::pixbuf_new_from_file (fullname, modTime, pixPath, NULL);
+ pixbuf = Inkscape::IO::pixbuf_new_from_file(fullname, modTime, pixPath);
+ g_free(fullname);
if (pixbuf != NULL) {
return pixbuf;
}
@@ -1142,7 +806,7 @@ GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gcha
// different dir) or unset (when doc is not saved yet), so we check for base+href existence first,
// and if it fails, we also try to use bare href regardless of its g_path_is_absolute
if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) {
- pixbuf = Inkscape::IO::pixbuf_new_from_file( fullname, modTime, pixPath, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file(fullname, modTime, pixPath);
g_free (fullname);
if (pixbuf != NULL) {
return pixbuf;
@@ -1152,7 +816,7 @@ GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gcha
/* try filename as absolute */
if (g_file_test (filename, G_FILE_TEST_EXISTS) && !g_file_test (filename, G_FILE_TEST_IS_DIR)) {
- pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, modTime, pixPath, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file(filename, modTime, pixPath);
if (pixbuf != NULL) {
return pixbuf;
}
@@ -1170,13 +834,13 @@ GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gcha
g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref);
}
- pixbuf = Inkscape::IO::pixbuf_new_from_file( filename, modTime, pixPath, NULL );
+ pixbuf = Inkscape::IO::pixbuf_new_from_file(filename, modTime, pixPath);
if (pixbuf != NULL) {
return pixbuf;
}
}
/* Nope: We do not find any valid pixmap file :-( */
- pixbuf = gdk_pixbuf_new_from_xpm_data ((const gchar **) brokenimage_xpm);
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **) brokenimage_xpm);
/* It should be included xpm, so if it still does not does load, */
/* our libraries are broken */
@@ -1349,82 +1013,57 @@ static GdkPixbuf *sp_image_repr_read_dataURI( const gchar * uri_data )
return pixbuf;
}
-static GdkPixbuf *sp_image_repr_read_b64( const gchar * uri_data )
+static GdkPixbuf *sp_image_repr_read_b64(gchar const *uri_data)
{
- GdkPixbuf * pixbuf = NULL;
-
- static const gchar B64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
+ GdkPixbuf *pixbuf = NULL;
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
- if (loader) {
- bool eos = false;
- bool failed = false;
- const gchar* btr = uri_data;
- gchar ud[4];
- guchar bd[57];
-
- while (!eos) {
- gint ell = 0;
- for (gint j = 0; j < 19; j++) {
- gint len = 0;
- for (gint k = 0; k < 4; k++) {
- while (isspace ((int) (*btr))) {
- if ((*btr) == '\0') break;
- btr++;
- }
- if (eos) {
- ud[k] = 0;
- continue;
- }
- if (((*btr) == '\0') || ((*btr) == '=')) {
- eos = true;
- ud[k] = 0;
- continue;
- }
- ud[k] = 64;
- for (gint b = 0; b < 64; b++) { /* There must a faster way to do this... ?? */
- if (B64[b] == (*btr)) {
- ud[k] = (gchar) b;
- break;
- }
- }
- if (ud[k] == 64) { /* data corruption ?? */
- eos = true;
- ud[k] = 0;
- continue;
- }
- btr++;
- len++;
- }
- guint32 bits = (guint32) ud[0];
- bits = (bits << 6) | (guint32) ud[1];
- bits = (bits << 6) | (guint32) ud[2];
- bits = (bits << 6) | (guint32) ud[3];
- bd[ell++] = (guchar) ((bits & 0xff0000) >> 16);
- if (len > 2) {
- bd[ell++] = (guchar) ((bits & 0xff00) >> 8);
- }
- if (len > 3) {
- bd[ell++] = (guchar) (bits & 0xff);
- }
- }
- if (!gdk_pixbuf_loader_write (loader, (const guchar *) bd, (size_t) ell, NULL)) {
- failed = true;
- break;
- }
- }
+ if (!loader) return NULL;
- gdk_pixbuf_loader_close (loader, NULL);
+ gsize decoded_len = 0;
+ guchar *decoded = g_base64_decode(uri_data, &decoded_len);
- if (!failed) {
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
- }
+ if (gdk_pixbuf_loader_write(loader, decoded, decoded_len, NULL)) {
+ gdk_pixbuf_loader_close(loader, NULL);
+ pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+ g_object_ref(pixbuf);
+ pixbuf = sp_image_pixbuf_force_rgba(pixbuf);
+ pixbuf_set_mime_data(pixbuf, decoded, decoded_len, gdk_pixbuf_loader_get_format(loader));
+ } else {
+ g_free(decoded);
}
+ g_object_unref(loader);
return pixbuf;
}
+// takes ownership of passed data
+static void pixbuf_set_mime_data(GdkPixbuf *pb, guchar *data, gsize len, GdkPixbufFormat *fmt)
+{
+ cairo_surface_t *s = ink_cairo_surface_get_for_pixbuf(pb);
+
+ gchar const *mimetype = NULL;
+ gchar *fmt_name = gdk_pixbuf_format_get_name(fmt);
+ Glib::ustring name = fmt_name;
+ g_free(fmt_name);
+
+ if (name == "jpeg") {
+ mimetype = CAIRO_MIME_TYPE_JPEG;
+ } else if (name == "jpeg2000") {
+ mimetype = CAIRO_MIME_TYPE_JP2;
+ } else if (name == "png") {
+ mimetype = CAIRO_MIME_TYPE_PNG;
+ }
+
+ if (mimetype != NULL) {
+ cairo_surface_set_mime_data(s, mimetype, data, len, g_free, data);
+ //g_message("Setting Cairo MIME data: %s", mimetype);
+ } else {
+ g_free(data);
+ //g_message("Not setting Cairo MIME data: unknown format %s", name.c_str());
+ }
+}
+
static void sp_image_set_curve( SPImage *image )
{
//create a curve at the image's boundary for snapping
@@ -1460,41 +1099,67 @@ SPCurve *sp_image_get_curve( SPImage *image )
return result;
}
-void sp_embed_image( Inkscape::XML::Node *image_node, GdkPixbuf *pb, Glib::ustring const &mime_in )
+void sp_embed_image(Inkscape::XML::Node *image_node, GdkPixbuf *pb)
{
- Glib::ustring format, mime;
- if (mime_in == "image/jpeg") {
- mime = mime_in;
- format = "jpeg";
- } else {
- mime = "image/png";
- format = "png";
+ static gchar const *mimetypes[] = {
+ CAIRO_MIME_TYPE_JPEG, CAIRO_MIME_TYPE_JP2, CAIRO_MIME_TYPE_PNG, NULL };
+ static guint mimetypes_len = g_strv_length(const_cast<gchar**>(mimetypes));
+
+ bool free_data = false;
+
+ // check whether the pixbuf has MIME data
+ guchar *data = NULL;
+ gsize len = 0;
+ gchar const *data_mimetype = NULL;
+
+ cairo_surface_t *s = reinterpret_cast<cairo_surface_t*>(g_object_get_data(G_OBJECT(pb), "cairo_surface"));
+ if (s) {
+ for (guint i = 0; i < mimetypes_len; ++i) {
+ unsigned long len_long = 0;
+ cairo_surface_get_mime_data(s, mimetypes[i], const_cast<unsigned char const **>(&data), &len_long);
+ len = len_long; // this assumes that the added range of long is not needed. the code below assumes gsize range of values is sufficient.
+ if (data != NULL) {
+ data_mimetype = mimetypes[i];
+ break;
+ }
+ }
}
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring quality = Glib::ustring::format(prefs->getInt("/dialogs/import/quality", 100));
+ if (data == NULL) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Glib::ustring quality = Glib::ustring::format(prefs->getInt("/dialogs/import/quality", 100));
- gchar *data = 0;
- gsize length = 0;
- gdk_pixbuf_save_to_buffer(pb, &data, &length, format.data(), NULL, "quality", quality.c_str(), NULL);
+ // if there is no supported MIME data, embed as PNG
+ data_mimetype = "image/png";
+ ink_pixbuf_ensure_normal(pb);
+ gdk_pixbuf_save_to_buffer(pb, reinterpret_cast<gchar**>(&data), &len, "png", NULL,
+ "quality", quality.c_str(), NULL);
+ free_data = true;
+ }
// Save base64 encoded data in image node
// this formula taken from Glib docs
- guint needed_size = length * 4 / 3 + length * 4 / (3 * 72) + 7;
- needed_size += 5 + 8 + mime.size(); // 5 bytes for data:, 8 for ;base64,
+ gsize needed_size = len * 4 / 3 + len * 4 / (3 * 72) + 7;
+ needed_size += 5 + 8 + strlen(data_mimetype); // 5 bytes for data: + 8 for ;base64,
- gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
- buf_work += g_sprintf(buffer, "data:%s;base64,", mime.data());
+ gchar *buffer = (gchar *) g_malloc(needed_size);
+ gchar *buf_work = buffer;
+ buf_work += g_sprintf(buffer, "data:%s;base64,", data_mimetype);
gint state = 0;
gint save = 0;
gsize written = 0;
- written += g_base64_encode_step((guchar*) data, length, TRUE, buf_work, &state, &save);
+ written += g_base64_encode_step(data, len, TRUE, buf_work, &state, &save);
written += g_base64_encode_close(TRUE, buf_work + written, &state, &save);
buf_work[written] = 0; // null terminate
+ // TODO: this is very wasteful memory-wise.
+ // It would be better to only keep the binary data around,
+ // and base64 encode on the fly when saving the XML.
image_node->setAttribute("xlink:href", buffer);
+
g_free(buffer);
+ if (free_data) g_free(data);
}
void sp_image_refresh_if_outdated( SPImage* image )
diff --git a/src/sp-image.h b/src/sp-image.h
index d6fc82a59..c197f6473 100644
--- a/src/sp-image.h
+++ b/src/sp-image.h
@@ -66,7 +66,7 @@ GType sp_image_get_type (void);
/* Return duplicate of curve or NULL */
SPCurve *sp_image_get_curve (SPImage *image);
-void sp_embed_image(Inkscape::XML::Node *imgnode, GdkPixbuf *pb, Glib::ustring const &mime);
+void sp_embed_image(Inkscape::XML::Node *imgnode, GdkPixbuf *pb);
void sp_image_refresh_if_outdated( SPImage* image );
#endif
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index 62811d51a..b8368a416 100644
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
@@ -616,13 +616,13 @@ sp_pattern_create_pattern(SPPaintServer *ps,
// viewBox to pattern server
Geom::Affine vb2ps = Geom::identity();
- if (pat->viewBox_set) {
- Geom::Rect vb = *pattern_viewBox(pat);
- gdouble tmp_x = pattern_width (pat) / vb.width();
- gdouble tmp_y = pattern_height (pat) / vb.height();
+ if (shown->viewBox_set) {
+ Geom::Rect vb = *pattern_viewBox(shown);
+ gdouble tmp_x = pattern_width (shown) / vb.width();
+ gdouble tmp_y = pattern_height (shown) / vb.height();
// FIXME: preserveAspectRatio must be taken into account here too!
- vb2ps = Geom::Affine(tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - vb.left() * tmp_x, pattern_y(pat) - vb.top() * tmp_y);
+ vb2ps = Geom::Affine(tmp_x, 0.0, 0.0, tmp_y, pattern_x(shown) - vb.left() * tmp_x, pattern_y(shown) - vb.top() * tmp_y);
}
// We must determine the size and scaling of the pattern at the time it is displayed and render
diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp
index 74e94b827..a09489f6d 100644
--- a/src/ui/cache/svg_preview_cache.cpp
+++ b/src/ui/cache/svg_preview_cache.cpp
@@ -33,7 +33,7 @@
#include "ui/cache/svg_preview_cache.h"
-GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const Geom::Rect& dbox, unsigned psize)
+GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, Geom::Rect const &dbox, unsigned psize)
{
Geom::Affine t(Geom::Scale(scale_factor, scale_factor));
drawing.root()->setTransform(Geom::Scale(scale_factor));
@@ -61,13 +61,7 @@ GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const
drawing.render(ct, area, Inkscape::DrawingItem::RENDER_BYPASS_CACHE);
cairo_surface_flush(s);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB,
- TRUE,
- 8, psize, psize, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
-
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
return pixbuf;
}
@@ -81,6 +75,12 @@ SvgPreview::SvgPreview()
SvgPreview::~SvgPreview()
{
+ for (std::map<Glib::ustring, GdkPixbuf *>::iterator i = _pixmap_cache.begin();
+ i != _pixmap_cache.end(); ++i)
+ {
+ g_object_unref(i->second);
+ i->second = NULL;
+ }
}
Glib::ustring SvgPreview::cache_key(gchar const *uri, gchar const *name, unsigned psize) const {
@@ -102,6 +102,7 @@ GdkPixbuf* SvgPreview::get_preview_from_cache(const Glib::ustring& key) {
}
void SvgPreview::set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px) {
+ g_object_ref(px);
_pixmap_cache[key] = px;
}
@@ -123,6 +124,8 @@ GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, Inkscape::
void SvgPreview::remove_preview_from_cache(const Glib::ustring& key) {
std::map<Glib::ustring, GdkPixbuf *>::iterator found = _pixmap_cache.find(key);
if ( found != _pixmap_cache.end() ) {
+ g_object_unref(found->second);
+ found->second = NULL;
_pixmap_cache.erase(key);
}
}
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index 2292b66fc..7940c28ae 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -235,11 +235,7 @@ static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpoin
cairo_pattern_destroy(gradient);
cairo_surface_flush(s);
- pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- width, height, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
+ pixbuf = ink_pixbuf_create_from_cairo_surface(s);
} else {
Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height );
guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
@@ -561,11 +557,7 @@ void ColorItem::_regenPreview(EekPreview * preview)
cairo_destroy(ct);
cairo_surface_flush(s);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- w, h, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
eek_preview_set_pixbuf( preview, pixbuf );
}
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index b06c1fd1f..e9cf2e753 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -884,7 +884,7 @@ void InkscapePreferences::initPageIO()
int pathstringFormatValues[numPathstringFormat] = {0, 1, 2};
_svgoutput_pathformat.init("/options/svgoutput/pathstring_format", pathstringFormatLabels, pathstringFormatValues, numPathstringFormat, 2);
- _page_svgoutput.add_line( true, _("Path string format"), _svgoutput_pathformat, "", _("Path data should be written: only with absolute coordinates, only with relative coordinates, or optimized for string length (mixed absolute and relative coordinates)"), false);
+ _page_svgoutput.add_line( true, _("Path string format:"), _svgoutput_pathformat, "", _("Path data should be written: only with absolute coordinates, only with relative coordinates, or optimized for string length (mixed absolute and relative coordinates)"), false);
_svgoutput_forcerepeatcommands.init( _("Force repeat commands"), "/options/svgoutput/forcerepeatcommands", false);
_page_svgoutput.add_line( true, "", _svgoutput_forcerepeatcommands, "", _("Force repeating of the same path command (for example, 'L 1,2 L 3,4' instead of 'L 1,2 3,4')"), false);
diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp
index 26bc52947..6427eb9cc 100644
--- a/src/ui/dialog/symbols.cpp
+++ b/src/ui/dialog/symbols.cpp
@@ -420,12 +420,12 @@ void SymbolsDialog::iconChanged() {
// First look for default style stored in <symbol>
gchar const* style = symbol->getAttribute("inkscape:symbol-style");
if( !style ) {
- // If no default style in <symbol>, look in documents.
- if( symbolDocument == currentDocument ) {
- style = style_from_use( symbol_id.c_str(), currentDocument );
- } else {
- style = symbolDocument->getReprRoot()->attribute("style");
- }
+ // If no default style in <symbol>, look in documents.
+ if( symbolDocument == currentDocument ) {
+ style = style_from_use( symbol_id.c_str(), currentDocument );
+ } else {
+ style = symbolDocument->getReprRoot()->attribute("style");
+ }
}
ClipboardManager *cm = ClipboardManager::get();
@@ -489,8 +489,8 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) {
while( std::getline( iss, line ) ) {
// std::cout << line << std::endl;
if( line.find( "svg:svg" ) == std::string::npos ) {
- tmpSVGOutput += line;
- tmpSVGOutput += "\n";
+ tmpSVGOutput += line;
+ tmpSVGOutput += "\n";
}
}
@@ -499,23 +499,23 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) {
tmpSVGOutput += " </defs>\n";
tmpSVGOutput += "</svg>\n";
-
+
return SPDocument::createNewDocFromMem( tmpSVGOutput.c_str(), strlen( tmpSVGOutput.c_str()), 0 );
}
#endif
-
+
/* Hunts preference directories for symbol files */
void SymbolsDialog::get_symbols() {
std::list<Glib::ustring> directories;
if( Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_EXISTS ) &&
- Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) {
+ Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) {
directories.push_back( INKSCAPE_SYMBOLSDIR );
}
if( Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_EXISTS ) &&
- Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) {
+ Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) {
directories.push_back( profile_path("symbols") );
}
@@ -526,46 +526,46 @@ void SymbolsDialog::get_symbols() {
GDir *dir = g_dir_open( (*it).c_str(), 0, &err );
if( dir ) {
- gchar *filename = 0;
- while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) {
+ gchar *filename = 0;
+ while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) {
- gchar *fullname = g_build_filename((*it).c_str(), filename, NULL);
+ gchar *fullname = g_build_filename((*it).c_str(), filename, NULL);
- if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) {
+ if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) {
- Glib::ustring fn( filename );
- Glib::ustring tag = fn.substr( fn.find_last_of(".") + 1 );
+ Glib::ustring fn( filename );
+ Glib::ustring tag = fn.substr( fn.find_last_of(".") + 1 );
- SPDocument* symbol_doc = NULL;
+ SPDocument* symbol_doc = NULL;
#ifdef WITH_LIBVISIO
- if( tag.compare( "vss" ) == 0 ) {
-
- symbol_doc = read_vss( fullname, filename );
- if( symbol_doc ) {
- symbolSets[Glib::ustring(filename)]= symbol_doc;
- symbolSet->append(filename);
- }
- }
+ if( tag.compare( "vss" ) == 0 ) {
+
+ symbol_doc = read_vss( fullname, filename );
+ if( symbol_doc ) {
+ symbolSets[Glib::ustring(filename)]= symbol_doc;
+ symbolSet->append(filename);
+ }
+ }
#endif
- // Try to read all remaining files as SVG
- if( !symbol_doc ) {
+ // Try to read all remaining files as SVG
+ if( !symbol_doc ) {
- symbol_doc = SPDocument::createNewDoc( fullname, FALSE );
- if( symbol_doc ) {
+ symbol_doc = SPDocument::createNewDoc( fullname, FALSE );
+ if( symbol_doc ) {
gchar *title = symbol_doc->getRoot()->title();
if( title == NULL ) {
title = _("Unnamed Symbols");
}
- symbolSets[Glib::ustring(title)] = symbol_doc;
- symbolSet->append(title);
- }
- }
-
- }
- g_free( fullname );
- }
- g_dir_close( dir );
+ symbolSets[Glib::ustring(title)] = symbol_doc;
+ symbolSet->append(title);
+ }
+ }
+
+ }
+ g_free( fullname );
+ }
+ g_dir_close( dir );
}
}
}
@@ -627,16 +627,16 @@ gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* documen
for( ; l != NULL; l = l->next ) {
SPObject* use = SP_OBJECT(l->data);
if( SP_IS_USE( use ) ) {
- gchar const *href = use->getRepr()->attribute("xlink:href");
- if( href ) {
- Glib::ustring href2(href);
- Glib::ustring id2(id);
- id2 = "#" + id2;
- if( !href2.compare(id2) ) {
- style = use->getRepr()->attribute("style");
- break;
- }
- }
+ gchar const *href = use->getRepr()->attribute("xlink:href");
+ if( href ) {
+ Glib::ustring href2(href);
+ Glib::ustring id2(id);
+ id2 = "#" + id2;
+ if( !href2.compare(id2) ) {
+ style = use->getRepr()->attribute("style");
+ break;
+ }
+ }
}
}
return style;
@@ -749,9 +749,13 @@ SymbolsDialog::create_symbol_image(gchar const *symbol_id, SPObject *symbol)
/* Update to renderable state */
Glib::ustring key = svg_preview_cache.cache_key(previewDocument->getURI(), symbol_id, psize);
//std::cout << " Key: " << key << std::endl;
- // FIX ME
- //Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
- Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::RefPtr<Gdk::Pixbuf>(0);
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf(NULL);
+ GdkPixbuf *pixbuf_gobj = svg_preview_cache.get_preview_from_cache(key);
+ if (pixbuf_gobj) {
+ g_object_ref(pixbuf_gobj); // the reference in svg_preview_cache will get destroyed when it's freed
+ pixbuf = Glib::wrap(pixbuf_gobj);
+ }
// Find object's bbox in document.
// Note symbols can have own viewport... ignore for now.
@@ -776,8 +780,8 @@ SymbolsDialog::create_symbol_image(gchar const *symbol_id, SPObject *symbol)
}
if( fitSymbol->get_active() ) {
- /* Fit */
- scale = psize/std::max(width,height);
+ /* Fit */
+ scale = psize/std::max(width,height);
}
pixbuf = Glib::wrap(render_pixbuf(renderDrawing, scale, *dbox, psize));
@@ -814,8 +818,8 @@ void SymbolsDialog::setTargetDesktop(SPDesktop *desktop)
if (this->currentDesktop != desktop) {
this->currentDesktop = desktop;
if( !symbolSets[symbolSet->get_active_text()] ) {
- // Symbol set is from Current document, update
- rebuild();
+ // Symbol set is from Current document, update
+ rebuild();
}
}
}
diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp
index 4b4a7b738..5bcd16528 100644
--- a/src/ui/widget/color-preview.cpp
+++ b/src/ui/widget/color-preview.cpp
@@ -73,9 +73,9 @@ ColorPreview::on_expose_event (GdkEventExpose *event)
if (get_is_drawable())
{
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
- cr->rectangle(event->area.x, event->area.y,
+ cr->rectangle(event->area.x, event->area.y,
event->area.width, event->area.height);
- cr->clip();
+ cr->clip();
result = on_draw(cr);
}
@@ -176,12 +176,7 @@ ColorPreview::toPixbuf (int width, int height)
cairo_destroy(ct);
cairo_surface_flush(s);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- width, height, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
-
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
return pixbuf;
}
diff --git a/src/widgets/dash-selector.cpp b/src/widgets/dash-selector.cpp
index 51483a9c4..afc81e574 100644
--- a/src/widgets/dash-selector.cpp
+++ b/src/widgets/dash-selector.cpp
@@ -238,58 +238,50 @@ void SPDashSelector::get_dash(int *ndash, double **dash, double *off)
/**
* Fill a pixbuf with the dash pattern using standard cairo drawing
*/
-GdkPixbuf* SPDashSelector::sp_dash_to_pixbuf(double *pattern) {
-
- int n_dashes;
- for (n_dashes = 0; pattern[n_dashes] >= 0.0; n_dashes ++) ;
-
- cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
- cairo_t *ct = cairo_create(s);
-
- cairo_set_line_width (ct, preview_lineheight);
- cairo_scale (ct, preview_lineheight, 1);
- //cairo_set_source_rgb (ct, 0, 0, 0);
- cairo_move_to (ct, 0, preview_height/2);
- cairo_line_to (ct, preview_width, preview_height/2);
- cairo_set_dash(ct, pattern, n_dashes, 0);
- cairo_stroke (ct);
-
- cairo_destroy(ct);
- cairo_surface_flush(s);
-
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- preview_width, preview_height, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
- return pixbuf;
+GdkPixbuf* SPDashSelector::sp_dash_to_pixbuf(double *pattern)
+{
+ int n_dashes;
+ for (n_dashes = 0; pattern[n_dashes] >= 0.0; n_dashes ++) ;
+
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
+ cairo_t *ct = cairo_create(s);
+
+ cairo_set_line_width (ct, preview_lineheight);
+ cairo_scale (ct, preview_lineheight, 1);
+ //cairo_set_source_rgb (ct, 0, 0, 0);
+ cairo_move_to (ct, 0, preview_height/2);
+ cairo_line_to (ct, preview_width, preview_height/2);
+ cairo_set_dash(ct, pattern, n_dashes, 0);
+ cairo_stroke (ct);
+
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
+
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
+ return pixbuf;
}
/**
* Fill a pixbuf with a text label using standard cairo drawing
*/
-GdkPixbuf* SPDashSelector::sp_text_to_pixbuf(char *text) {
-
- cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
- cairo_t *ct = cairo_create(s);
+GdkPixbuf* SPDashSelector::sp_text_to_pixbuf(char *text)
+{
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, preview_width, preview_height);
+ cairo_t *ct = cairo_create(s);
- cairo_select_font_face (ct, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
- cairo_set_font_size (ct, 12.0);
- cairo_set_source_rgb (ct, 0.0, 0.0, 0.0);
- cairo_move_to (ct, 16.0, 13.0);
- cairo_show_text (ct, text);
+ cairo_select_font_face (ct, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size (ct, 12.0);
+ cairo_set_source_rgb (ct, 0.0, 0.0, 0.0);
+ cairo_move_to (ct, 16.0, 13.0);
+ cairo_show_text (ct, text);
- cairo_stroke (ct);
+ cairo_stroke (ct);
- cairo_destroy(ct);
- cairo_surface_flush(s);
+ cairo_destroy(ct);
+ cairo_surface_flush(s);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- preview_width, preview_height, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
- return pixbuf;
+ GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s);
+ return pixbuf;
}
void SPDashSelector::on_selection ()
diff --git a/src/widgets/gradient-image.cpp b/src/widgets/gradient-image.cpp
index 2d58355db..9a5dd4996 100644
--- a/src/widgets/gradient-image.cpp
+++ b/src/widgets/gradient-image.cpp
@@ -31,11 +31,11 @@ static void sp_gradient_image_size_request (GtkWidget *widget, GtkRequisition *r
static void sp_gradient_image_destroy(GtkWidget *object);
static void sp_gradient_image_get_preferred_width(GtkWidget *widget,
gint *minimal_width,
- gint *natural_width);
+ gint *natural_width);
static void sp_gradient_image_get_preferred_height(GtkWidget *widget,
gint *minimal_height,
- gint *natural_height);
+ gint *natural_height);
#else
static void sp_gradient_image_destroy(GtkObject *object);
static gboolean sp_gradient_image_expose(GtkWidget *widget, GdkEventExpose *event);
@@ -50,53 +50,53 @@ static GtkWidgetClass *parent_class;
GType sp_gradient_image_get_type(void)
{
- static GType type = 0;
- if (!type) {
- GTypeInfo info = {
- sizeof (SPGradientImageClass),
- NULL, NULL,
- (GClassInitFunc) sp_gradient_image_class_init,
- NULL, NULL,
- sizeof (SPGradientImage),
- 0,
- (GInstanceInitFunc) sp_gradient_image_init,
- NULL
- };
- type = g_type_register_static (GTK_TYPE_WIDGET, "SPGradientImage", &info, (GTypeFlags)0);
- }
- return type;
+ static GType type = 0;
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (SPGradientImageClass),
+ NULL, NULL,
+ (GClassInitFunc) sp_gradient_image_class_init,
+ NULL, NULL,
+ sizeof (SPGradientImage),
+ 0,
+ (GInstanceInitFunc) sp_gradient_image_init,
+ NULL
+ };
+ type = g_type_register_static (GTK_TYPE_WIDGET, "SPGradientImage", &info, (GTypeFlags)0);
+ }
+ return type;
}
static void sp_gradient_image_class_init(SPGradientImageClass *klass)
{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
- parent_class = GTK_WIDGET_CLASS(g_type_class_peek_parent (klass));
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ parent_class = GTK_WIDGET_CLASS(g_type_class_peek_parent (klass));
#if GTK_CHECK_VERSION(3,0,0)
-// GObjectClass *object_class = G_OBJECT_CLASS(klass);
+// GObjectClass *object_class = G_OBJECT_CLASS(klass);
- widget_class->get_preferred_width = sp_gradient_image_get_preferred_width;
- widget_class->get_preferred_height = sp_gradient_image_get_preferred_height;
- widget_class->draw = sp_gradient_image_draw;
- widget_class->destroy = sp_gradient_image_destroy;
+ widget_class->get_preferred_width = sp_gradient_image_get_preferred_width;
+ widget_class->get_preferred_height = sp_gradient_image_get_preferred_height;
+ widget_class->draw = sp_gradient_image_draw;
+ widget_class->destroy = sp_gradient_image_destroy;
#else
- GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass);
- object_class->destroy = sp_gradient_image_destroy;
- widget_class->size_request = sp_gradient_image_size_request;
- widget_class->expose_event = sp_gradient_image_expose;
+ object_class->destroy = sp_gradient_image_destroy;
+ widget_class->size_request = sp_gradient_image_size_request;
+ widget_class->expose_event = sp_gradient_image_expose;
#endif
}
static void
sp_gradient_image_init (SPGradientImage *image)
{
- gtk_widget_set_has_window (GTK_WIDGET(image), FALSE);
+ gtk_widget_set_has_window (GTK_WIDGET(image), FALSE);
- image->gradient = NULL;
+ image->gradient = NULL;
- new (&image->release_connection) sigc::connection();
- new (&image->modified_connection) sigc::connection();
+ new (&image->release_connection) sigc::connection();
+ new (&image->modified_connection) sigc::connection();
}
#if GTK_CHECK_VERSION(3,0,0)
@@ -105,23 +105,23 @@ static void sp_gradient_image_destroy(GtkWidget *object)
static void sp_gradient_image_destroy(GtkObject *object)
#endif
{
- SPGradientImage *image = SP_GRADIENT_IMAGE (object);
+ SPGradientImage *image = SP_GRADIENT_IMAGE (object);
- if (image->gradient) {
- image->release_connection.disconnect();
- image->modified_connection.disconnect();
- image->gradient = NULL;
- }
+ if (image->gradient) {
+ image->release_connection.disconnect();
+ image->modified_connection.disconnect();
+ image->gradient = NULL;
+ }
- image->release_connection.~connection();
- image->modified_connection.~connection();
+ image->release_connection.~connection();
+ image->modified_connection.~connection();
#if GTK_CHECK_VERSION(3,0,0)
- if (parent_class->destroy)
- (* (parent_class)->destroy) (object);
+ if (parent_class->destroy)
+ (* (parent_class)->destroy) (object);
#else
- if ((GTK_OBJECT_CLASS(parent_class))->destroy)
- (* (GTK_OBJECT_CLASS(parent_class))->destroy) (object);
+ if ((GTK_OBJECT_CLASS(parent_class))->destroy)
+ (* (GTK_OBJECT_CLASS(parent_class))->destroy) (object);
#endif
}
@@ -134,36 +134,36 @@ static void sp_gradient_image_size_request(GtkWidget * /*widget*/, GtkRequisitio
#if GTK_CHECK_VERSION(3,0,0)
static void sp_gradient_image_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width)
{
- GtkRequisition requisition;
- sp_gradient_image_size_request(widget, &requisition);
- *minimal_width = *natural_width = requisition.width;
+ GtkRequisition requisition;
+ sp_gradient_image_size_request(widget, &requisition);
+ *minimal_width = *natural_width = requisition.width;
}
static void sp_gradient_image_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height)
{
- GtkRequisition requisition;
- sp_gradient_image_size_request(widget, &requisition);
- *minimal_height = *natural_height = requisition.height;
+ GtkRequisition requisition;
+ sp_gradient_image_size_request(widget, &requisition);
+ *minimal_height = *natural_height = requisition.height;
}
#endif
#if !GTK_CHECK_VERSION(3,0,0)
static gboolean sp_gradient_image_expose(GtkWidget *widget, GdkEventExpose *event)
{
- gboolean result = TRUE;
- if(gtk_widget_is_drawable(widget)) {
- cairo_t *ct = gdk_cairo_create(gtk_widget_get_window (widget));
- cairo_rectangle(ct, event->area.x, event->area.y,
- event->area.width, event->area.height);
- cairo_clip(ct);
- GtkAllocation allocation;
- gtk_widget_get_allocation(widget, &allocation);
- cairo_translate(ct, allocation.x, allocation.y);
- result = sp_gradient_image_draw(widget, ct);
- cairo_destroy(ct);
- }
-
- return result;
+ gboolean result = TRUE;
+ if(gtk_widget_is_drawable(widget)) {
+ cairo_t *ct = gdk_cairo_create(gtk_widget_get_window (widget));
+ cairo_rectangle(ct, event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_clip(ct);
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ cairo_translate(ct, allocation.x, allocation.y);
+ result = sp_gradient_image_draw(widget, ct);
+ cairo_destroy(ct);
+ }
+
+ return result;
}
#endif
@@ -179,7 +179,7 @@ static gboolean sp_gradient_image_draw(GtkWidget *widget, cairo_t *ct)
cairo_paint(ct);
cairo_pattern_destroy(check);
- if (gr) {
+ if (gr) {
cairo_pattern_t *p = sp_gradient_create_preview_pattern(gr, allocation.width);
cairo_set_source(ct, p);
cairo_paint(ct);
@@ -192,11 +192,11 @@ static gboolean sp_gradient_image_draw(GtkWidget *widget, cairo_t *ct)
GtkWidget *
sp_gradient_image_new (SPGradient *gradient)
{
- SPGradientImage *image = SP_GRADIENT_IMAGE(g_object_new(SP_TYPE_GRADIENT_IMAGE, NULL));
+ SPGradientImage *image = SP_GRADIENT_IMAGE(g_object_new(SP_TYPE_GRADIENT_IMAGE, NULL));
- sp_gradient_image_set_gradient (image, gradient);
+ sp_gradient_image_set_gradient (image, gradient);
- return GTK_WIDGET(image);
+ return GTK_WIDGET(image);
}
GdkPixbuf*
@@ -220,12 +220,8 @@ sp_gradient_to_pixbuf (SPGradient *gr, int width, int height)
cairo_destroy(ct);
cairo_surface_flush(s);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s),
- GDK_COLORSPACE_RGB, TRUE, 8,
- width, height, cairo_image_surface_get_stride(s),
- ink_cairo_pixbuf_cleanup, s);
- convert_pixbuf_argb32_to_normal(pixbuf);
-
+ // no need to free s - the call below takes ownership
+ GdkPixbuf *pixbuf = ink_pixbuf_create_from_cairo_surface(s);
return pixbuf;
}
@@ -233,44 +229,44 @@ sp_gradient_to_pixbuf (SPGradient *gr, int width, int height)
void
sp_gradient_image_set_gradient (SPGradientImage *image, SPGradient *gradient)
{
- if (image->gradient) {
- image->release_connection.disconnect();
- image->modified_connection.disconnect();
- }
+ if (image->gradient) {
+ image->release_connection.disconnect();
+ image->modified_connection.disconnect();
+ }
- image->gradient = gradient;
+ image->gradient = gradient;
- if (gradient) {
- image->release_connection = gradient->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gradient_image_gradient_release), image));
- image->modified_connection = gradient->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_gradient_image_gradient_modified), image));
- }
+ if (gradient) {
+ image->release_connection = gradient->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gradient_image_gradient_release), image));
+ image->modified_connection = gradient->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_gradient_image_gradient_modified), image));
+ }
- sp_gradient_image_update (image);
+ sp_gradient_image_update (image);
}
static void
sp_gradient_image_gradient_release (SPObject *, SPGradientImage *image)
{
- if (image->gradient) {
- image->release_connection.disconnect();
- image->modified_connection.disconnect();
- }
+ if (image->gradient) {
+ image->release_connection.disconnect();
+ image->modified_connection.disconnect();
+ }
- image->gradient = NULL;
+ image->gradient = NULL;
- sp_gradient_image_update (image);
+ sp_gradient_image_update (image);
}
static void
sp_gradient_image_gradient_modified (SPObject *, guint /*flags*/, SPGradientImage *image)
{
- sp_gradient_image_update (image);
+ sp_gradient_image_update (image);
}
static void
sp_gradient_image_update (SPGradientImage *image)
{
- if (gtk_widget_is_drawable (GTK_WIDGET(image))) {
- gtk_widget_queue_draw (GTK_WIDGET (image));
- }
+ if (gtk_widget_is_drawable (GTK_WIDGET(image))) {
+ gtk_widget_queue_draw (GTK_WIDGET (image));
+ }
}
diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp
index 2d1c932d3..00b6b5c91 100644
--- a/src/widgets/stroke-marker-selector.cpp
+++ b/src/widgets/stroke-marker-selector.cpp
@@ -544,16 +544,16 @@ MarkerComboBox::create_marker_image(unsigned psize, gchar const *mname,
gchar *cache_name = g_strconcat(combo_id, mname, NULL);
Glib::ustring key = svg_preview_cache.cache_key(source->getURI(), cache_name, psize);
g_free (cache_name);
- Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key));
+ GdkPixbuf *pixbuf = svg_preview_cache.get_preview_from_cache(key); // no ref created
if (!pixbuf) {
- pixbuf = Glib::wrap(render_pixbuf(drawing, 0.8, *dbox, psize));
- svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj());
+ pixbuf = render_pixbuf(drawing, 0.8, *dbox, psize);
+ svg_preview_cache.set_preview_in_cache(key, pixbuf);
+ g_object_unref(pixbuf); // reference is held by svg_preview_cache
}
// Create widget
- Gtk::Image *pb = new Gtk::Image(pixbuf);
-
+ Gtk::Image *pb = Glib::wrap(GTK_IMAGE(gtk_image_new_from_pixbuf(pixbuf)));
return pb;
}
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index 579c7598c..f7e75a83b 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -98,10 +98,9 @@ public:
}
}
- int setFile( char const * filename );
+ int setFile( char const * filename, bool load_entities );
xmlDocPtr readXml();
- bool SystemCheck; // Checks for SYSTEM Entities
static int readCb( void * context, char * buffer, int len );
static int closeCb( void * context );
@@ -115,16 +114,18 @@ private:
FILE* fp;
unsigned char firstFew[4];
int firstFewLen;
+ bool LoadEntities; // Checks for SYSTEM Entities (requires cached data)
+ std::string cachedData;
+ unsigned int cachedPos;
Inkscape::URI dummy;
Inkscape::IO::UriInputStream* instr;
Inkscape::IO::GzipInputStream* gzin;
};
-int XmlSource::setFile(char const *filename)
+int XmlSource::setFile(char const *filename, bool load_entities=false)
{
int retVal = -1;
- this->SystemCheck = false;
this->filename = filename;
fp = Inkscape::IO::fopen_utf8name(filename, "r");
@@ -178,7 +179,40 @@ int XmlSource::setFile(char const *filename)
retVal = 0; // no error
}
}
+ if(load_entities) {
+ this->cachedData = std::string("");
+ this->cachedPos = 0;
+
+ // First get data from file in typical way (cache it all)
+ char *buffer = new char [4096];
+ while(true) {
+ int len = this->read(buffer, 4096);
+ if(len <= 0) break;
+ buffer[len] = 0;
+ this->cachedData += buffer;
+ }
+ free(buffer);
+
+ // Check for SYSTEM or PUBLIC entities and remove them from the cache
+ GMatchInfo *info;
+ gint start, end;
+
+ GRegex *regex = g_regex_new(
+ "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>",
+ G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL);
+
+ g_regex_match (regex, this->cachedData.c_str(), G_REGEX_MATCH_NEWLINE_ANY, &info);
+ while (g_match_info_matches (info)) {
+ if (g_match_info_fetch_pos (info, 1, &start, &end))
+ this->cachedData.erase(start, end - start);
+ g_match_info_next (info, NULL);
+ }
+ g_match_info_free(info);
+ g_regex_unref(regex);
+ }
+ // Do this after loading cache, so reads don't return cache to fill cache.
+ this->LoadEntities = load_entities;
return retVal;
}
@@ -191,7 +225,7 @@ xmlDocPtr XmlSource::readXml()
if (!allowNetAccess) parse_options |= XML_PARSE_NONET;
// Allow NOENT only if we're filtering out SYSTEM and PUBLIC entities
- if (SystemCheck) parse_options |= XML_PARSE_NOENT;
+ if (LoadEntities) parse_options |= XML_PARSE_NOENT;
return xmlReadIO( readCb, closeCb, this,
filename, getEncoding(), parse_options);
@@ -204,31 +238,6 @@ int XmlSource::readCb( void * context, char * buffer, int len )
if ( context ) {
XmlSource* self = static_cast<XmlSource*>(context);
retVal = self->read( buffer, len );
-
- if(self->SystemCheck) {
- GMatchInfo *info;
- gint start, end;
-
- GRegex *regex = g_regex_new(
- "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>",
- G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL);
-
- // Check for SYSTEM or PUBLIC entities and kill them with spaces
- // Note: g_regex_replace does not modify buffer in place, this
- // logic is used instead because we can just blank out the offending
- // charicters in the right place without hurting the length.
- g_regex_match (regex, buffer, G_REGEX_MATCH_NEWLINE_ANY, &info);
-
- while (g_match_info_matches (info)) {
- if (g_match_info_fetch_pos (info, 1, &start, &end)) {
- for (int x=start; x<end; x++)
- buffer[x] = 0x20;
- }
- g_match_info_next (info, NULL);
- }
- g_match_info_unref(info);
- g_regex_unref(regex);
- }
}
return retVal;
}
@@ -247,7 +256,15 @@ int XmlSource::read( char *buffer, int len )
int retVal = 0;
size_t got = 0;
- if ( firstFewLen > 0 ) {
+ if ( LoadEntities ) {
+ if (cachedPos >= cachedData.length()) {
+ return -1;
+ } else {
+ retVal = cachedData.copy(buffer, len, cachedPos);
+ cachedPos += retVal;
+ return retVal; // Do NOT continue.
+ }
+ } else if ( firstFewLen > 0 ) {
int some = (len < firstFewLen) ? len : firstFewLen;
memcpy( buffer, firstFew, some );
if ( len < firstFewLen ) {
@@ -349,8 +366,7 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
// We try a system check version of load with NOENT for adobe
if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) {
xmlFreeDoc( doc );
- src.setFile(filename);
- src.SystemCheck = true;
+ src.setFile(filename, true);
doc = src.readXml();
rdoc = sp_repr_do_read( doc, default_ns );
}