diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index e3f70814269a6b1f1672995bbd927f5a86be4ebd..ad9e79de2ba576a9fec46f9c2538ffdfa44cc722 100644 (file)
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Edward Flick (EAF)
+ * Abhishek Sharma
*
* Copyright (C) 1999-2005 Authors
* Copyright (C) 2000-2001 Ximian, Inc.
#include <glibmm/i18n.h>
#include "xml/quote.h"
#include <xml/repr.h>
-
+#include "snap-candidate.h"
#include "libnr/nr-matrix-fns.h"
#include "io/sys.h"
static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags);
static void sp_image_print (SPItem * item, SPPrintContext *ctx);
static gchar * sp_image_description (SPItem * item);
-static void sp_image_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs);
+static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags);
static Geom::Matrix sp_image_set_transform (SPItem *item, Geom::Matrix const &xform);
static void sp_image_set_curve(SPImage *image);
//g_message( "user_flush_data" );
}
+
+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)
+ {
+ char* name = 0;
+ int compression_type = 0;
+ char* profile = 0;
+ 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;
+}
+
static GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, gchar*& pixPath, GError **/*error*/ )
{
GdkPixbuf* buf = NULL;
@@ -297,10 +453,6 @@ static GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, g
// short buffer
guchar scratch[1024];
gboolean latter = FALSE;
- gboolean isPng = FALSE;
- png_structp pngPtr = NULL;
- png_infop infoPtr = NULL;
- //png_infop endPtr = NULL;
youme.fp = fp;
youme.scratch = scratch;
@@ -311,155 +463,15 @@ static GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, g
while ( !feof(fp) )
{
- if ( youme.readMore() )
- {
- if ( youme.first )
- {
+ if ( youme.readMore() ) {
+ if ( youme.first ) {
//g_message( "First data chunk" );
youme.first = FALSE;
- isPng = !png_sig_cmp( scratch + youme.offset, 0, youme.available() );
- //g_message( " png? %s", (isPng ? "Yes":"No") );
- if ( isPng )
+ if (readPngAndHeaders(youme, dpiX, dpiY))
{
- pngPtr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
- NULL,//(png_voidp)user_error_ptr,
- NULL,//user_error_fn,
- NULL//user_warning_fn
- );
- if ( pngPtr )
- {
- infoPtr = png_create_info_struct( pngPtr );
- //endPtr = png_create_info_struct( pngPtr );
-
- 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, NULL );
-
- //g_message("out");
-
- //png_read_end(pngPtr, endPtr);
-
- /*
- 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)
- {
- char* name = 0;
- int compression_type = 0;
- char* profile = 0;
- 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)
-
-
- // now clean it up.
- png_destroy_read_struct( &pngPtr, &infoPtr, NULL );//&endPtr );
- }
- else
- {
-// g_message("Error when creating PNG read struct");
- }
+ // TODO set the dpi to be read elsewhere
}
- }
- else if ( !latter )
- {
+ } else if ( !latter ) {
latter = TRUE;
//g_message(" READing latter");
}
@@ -470,52 +482,40 @@ static GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, g
}
gboolean ok = gdk_pixbuf_loader_close(loader, &err);
- if ( ok )
- {
+ if ( ok ) {
buf = gdk_pixbuf_loader_get_pixbuf( loader );
- if ( buf )
- {
+ if ( buf ) {
g_object_ref(buf);
- if ( dpiX )
- {
+ if ( dpiX ) {
gchar *tmp = g_strdup_printf( "%d", dpiX );
- if ( tmp )
- {
-// g_message("Need to set DpiX: %s", tmp);
+ if ( tmp ) {
+ //g_message("Need to set DpiX: %s", tmp);
//gdk_pixbuf_set_option( buf, "Inkscape::DpiX", tmp );
g_free( tmp );
}
}
- if ( dpiY )
- {
+ if ( dpiY ) {
gchar *tmp = g_strdup_printf( "%d", dpiY );
- if ( tmp )
- {
-// g_message("Need to set DpiY: %s", tmp);
+ if ( tmp ) {
+ //g_message("Need to set DpiY: %s", tmp);
//gdk_pixbuf_set_option( buf, "Inkscape::DpiY", tmp );
g_free( tmp );
}
}
}
- }
- else
- {
+ } else {
// do something
g_message("error loading pixbuf at close");
}
g_object_unref(loader);
- }
- else
- {
+ } else {
g_message("error when creating pixbuf loader");
}
fclose( fp );
- fp = NULL;
- }
- else
- {
+ fp = 0;
+ } else {
g_warning ("Unable to open linked file: %s", filename);
}
(GInstanceInitFunc) sp_image_init,
NULL, /* value_table */
};
- image_type = g_type_register_static (sp_item_get_type (), "SPImage", &image_info, (GTypeFlags)0);
+ image_type = g_type_register_static (SPItem::getType (), "SPImage", &image_info, (GTypeFlags)0);
}
return image_type;
}
sp_object_class = (SPObjectClass *) klass;
item_class = (SPItemClass *) klass;
- parent_class = (SPItemClass*)g_type_class_ref (sp_item_get_type ());
+ parent_class = (SPItemClass*)g_type_class_ref (SPItem::getType ());
sp_object_class->build = sp_image_build;
sp_object_class->release = sp_image_release;
@@ -638,16 +638,16 @@ sp_image_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
((SPObjectClass *) parent_class)->build (object, document, repr);
}
- sp_object_read_attr (object, "xlink:href");
- sp_object_read_attr (object, "x");
- sp_object_read_attr (object, "y");
- sp_object_read_attr (object, "width");
- sp_object_read_attr (object, "height");
- sp_object_read_attr (object, "preserveAspectRatio");
- sp_object_read_attr (object, "color-profile");
+ object->readAttr( "xlink:href" );
+ object->readAttr( "x" );
+ object->readAttr( "y" );
+ object->readAttr( "width" );
+ object->readAttr( "height" );
+ object->readAttr( "preserveAspectRatio" );
+ object->readAttr( "color-profile" );
/* Register */
- sp_document_add_resource (document, "image", object);
+ document->addResource("image", object);
}
static void
if (SP_OBJECT_DOCUMENT (object)) {
/* Unregister ourselves */
- sp_document_remove_resource (SP_OBJECT_DOCUMENT (object), "image", SP_OBJECT (object));
+ SP_OBJECT_DOCUMENT(object)->removeResource("image", SP_OBJECT(object));
}
if (image->href) {
pixbuf = sp_image_repr_read_image (
image->lastMod,
image->pixPath,
- object->repr->attribute("xlink:href"),
- object->repr->attribute("sodipodi:absref"),
- doc->base);
+
+ //XML Tree being used directly while it shouldn't be.
+ object->getRepr()->attribute("xlink:href"),
+
+ //XML Tree being used directly while it shouldn't be.
+ object->getRepr()->attribute("sodipodi:absref"),
+ doc->getBase());
if (pixbuf) {
pixbuf = sp_image_pixbuf_force_rgba (pixbuf);
// BLIP
@@ -1057,7 +1061,9 @@ sp_image_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XM
if (image->height._set) {
sp_repr_set_svg_double(repr, "height", image->height.computed);
}
- repr->setAttribute("preserveAspectRatio", object->repr->attribute("preserveAspectRatio"));
+
+ //XML Tree being used directly here while it shouldn't be...
+ repr->setAttribute("preserveAspectRatio", object->getRepr()->attribute("preserveAspectRatio"));
#if ENABLE_LCMS
if (image->color_profile) {
repr->setAttribute("color-profile", image->color_profile);
}
}
-static void sp_image_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/)
+static void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const */*snapprefs*/)
{
/* An image doesn't have any nodes to snap, but still we want to be able snap one image
to another. Therefore we will create some snappoints at the corner, similar to a rect. If
@@ -1353,13 +1359,11 @@ static void sp_image_snappoints(SPItem const *item, bool const target, SnapPoint
double const y0 = image.y.computed;
double const x1 = x0 + image.width.computed;
double const y1 = y0 + image.height.computed;
- Geom::Matrix const i2d (sp_item_i2d_affine (item));
- Geom::Point pt;
- int type = target ? int(Inkscape::SNAPTARGET_CORNER) : int(Inkscape::SNAPSOURCE_CORNER);
- p.push_back(std::make_pair(Geom::Point(x0, y0) * i2d, type));
- p.push_back(std::make_pair(Geom::Point(x0, y1) * i2d, type));
- p.push_back(std::make_pair(Geom::Point(x1, y1) * i2d, type));
- p.push_back(std::make_pair(Geom::Point(x1, y0) * i2d, type));
+ Geom::Matrix const i2d (item->i2d_affine ());
+ p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
+ p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
+ p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
+ p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER));
}
}
NRRect rect;
sp_image_bbox(image, &rect, Geom::identity(), 0);
Geom::Rect rect2 = to_2geom(*rect.upgrade());
- SPCurve *c = SPCurve::new_from_rect(rect2);
+ SPCurve *c = SPCurve::new_from_rect(rect2, true);
if (image->curve) {
image->curve = image->curve->unref();
return result;
}
+void
+sp_embed_image(Inkscape::XML::Node *image_node, GdkPixbuf *pb, Glib::ustring const &mime_in)
+{
+ Glib::ustring format, mime;
+ if (mime_in == "image/jpeg") {
+ mime = mime_in;
+ format = "jpeg";
+ } else {
+ mime = "image/png";
+ format = "png";
+ }
+
+ gchar *data;
+ gsize length;
+ gdk_pixbuf_save_to_buffer(pb, &data, &length, format.data(), NULL, NULL);
+
+ // 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,
+
+ gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
+ buf_work += g_sprintf(buffer, "data:%s;base64,", mime.data());
+
+ gint state = 0, save = 0;
+ gsize written = 0;
+ written += g_base64_encode_step((guchar*) data, length, TRUE, buf_work, &state, &save);
+ written += g_base64_encode_close(TRUE, buf_work + written, &state, &save);
+ buf_work[written] = 0; // null terminate
+
+ image_node->setAttribute("xlink:href", buffer);
+ g_free(buffer);
+}
+
void sp_image_refresh_if_outdated( SPImage* image )
{
if ( image->href && image->lastMod ) {