sp-image.cpp revision 9bd721c03812c9534acfd60e07d011d6981f795b
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * SVG <image> implementation
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Lauris Kaplinski <lauris@kaplinski.com>
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Edward Flick (EAF)
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Abhishek Sharma
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Jon A. Cruz <jon@joncruz.org>
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Copyright (C) 1999-2005 Authors
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Copyright (C) 2000-2001 Ximian, Inc.
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki * Released under GNU GPL, read the file 'COPYING' for more information
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki//Added for preserveAspectRatio support -- EAF
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki#include "brokenimage.xpm"
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki#endif // HAVE_LIBLCMS2
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki//#define DEBUG_LCMS
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki#endif // DEBUG_LCMS
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki// TODO: give these constants better names:
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki// TODO: also check if it is correct to be using two different epsilon values
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_class_init (SPImageClass * klass);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_set (SPObject *object, unsigned int key, const gchar *value);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_modified (SPObject *object, unsigned int flags);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic Geom::OptRect sp_image_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_print (SPItem * item, SPPrintContext *ctx);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic Inkscape::DrawingItem *sp_image_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic Geom::Affine sp_image_set_transform (SPItem *item, Geom::Affine const &xform);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic GdkPixbuf *sp_image_repr_read_image( time_t& modTime, gchar*& pixPath, const gchar *href, const gchar *absref, const gchar *base );
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic GdkPixbuf *sp_image_pixbuf_force_rgba (GdkPixbuf * pixbuf);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic void sp_image_update_canvas_image (SPImage *image);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic GdkPixbuf * sp_image_repr_read_dataURI (const gchar * uri_data);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkistatic GdkPixbuf * sp_image_repr_read_b64 (const gchar * uri_data);
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length );
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki void user_write_data( png_structp png_ptr, png_bytep data, png_size_t length );
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki Inkscape::Preferences *prefs = Inkscape::Preferences::get();\
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki bool dump = prefs->getBool("/options/scislac/" #key);\
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki bool dumpD = prefs->getBool("/options/scislac/" #key "D");\
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki bool dumpD2 = prefs->getBool("/options/scislac/" #key "D2");\
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenki#endif // DEBUG_LCMS
0d63ce2b32a9e1cc8ed71d4d92536c44d66a530avenkinamespace IO {
fp(0),
scratch(0),
size(0),
used(0),
offset(0),
loader(0) {};
if ( offset )
offset = 0;
if ( got )
if ( loader )
return good;
offset = 0;
used = 0;
return giving;
void clear()
offset = 0;
used = 0;
bool good = true;
if ( isPng ) {
good = false;
if (good) {
int unit_type = 0;
#if defined(PNG_sRGB_SUPPORTED)
int intent = 0;
#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 defined(PNG_gAMA_SUPPORTED)
double file_gamma = 0;
#if defined(PNG_iCCP_SUPPORTED)
int compression_type = 0;
// g_message("Found an iCCP chunk named [%s] with %d bytes and comp %d", name, proflen, compression_type);
pngPtr = 0;
infoPtr = 0;
} else if (pngPtr) {
pngPtr = 0;
return good;
GdkPixbuf* pixbuf_new_from_file( const char *filename, time_t &modTime, gchar*& pixPath, GError **/*error*/ )
modTime = 0;
if ( pixPath ) {
//filename is not correct: it is a directory name and hence further code can not return valid results
return NULL;
if ( fp )
if ( !val ) {
if ( loader )
} else if ( !latter ) {
if ( ok ) {
if ( buf ) {
fp = 0;
return buf;
if (pixPath) {
return result;
if (!image_type) {
sizeof (SPImageClass),
sizeof (SPImage),
return image_type;
switch (key) {
case SP_ATTR_XLINK_HREF:
case SP_ATTR_X:
case SP_ATTR_Y:
case SP_ATTR_WIDTH:
case SP_ATTR_HEIGHT:
if (value) {
int len;
const gchar *p, *e;
p = value;
len = e - p;
c[len] = 0;
case SP_PROP_COLOR_PROFILE:
#ifdef DEBUG_LCMS
if ( value ) {
if (pixbuf) {
if ( px ) {
#ifdef DEBUG_LCMS
if ( prof ) {
switch ( profIntent ) {
intent, 0 );
if ( transf ) {
for ( int y = 0; y < imageheight; y++ ) {
#ifdef DEBUG_LCMS
#ifdef DEBUG_LCMS
DEBUG_MESSAGE( lcmsSeven, "in <image>'s sp_image_update. Profile type is named color. Can't transform." );
#ifdef DEBUG_LCMS
case SP_ASPECT_XMIN_YMIN:
case SP_ASPECT_XMID_YMIN:
case SP_ASPECT_XMAX_YMIN:
case SP_ASPECT_XMIN_YMID:
case SP_ASPECT_XMID_YMID:
case SP_ASPECT_XMAX_YMID:
case SP_ASPECT_XMIN_YMAX:
case SP_ASPECT_XMID_YMAX:
case SP_ASPECT_XMAX_YMAX:
static Inkscape::XML::Node *sp_image_write( SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags )
return repr;
static Geom::OptRect sp_image_bbox( SPItem const *item,Geom::Affine const &transform, SPItem::BBoxType /*type*/ )
bbox = Geom::Rect::from_xywh(image.x.computed, image.y.computed, image.width.computed, image.height.computed);
return bbox;
t = s * tp;
t = ti * t;
t = s * tp;
t = ti * t;
sp_print_image_R8G8B8A8_N(ctx, px + trimx*pixskip + trimy*rs, trimwidth, trimheight, rs, t, item->style);
char *href_desc;
href_desc) );
return ret;
static Inkscape::DrawingItem *sp_image_show( SPItem *item, Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/ )
return ai;
GdkPixbuf *sp_image_repr_read_image( time_t& modTime, char*& pixPath, const gchar *href, const gchar *absref, const gchar *base )
modTime = 0;
if ( pixPath ) {
pixPath = 0;
if (fullname) {
return pixbuf;
return pixbuf;
if (!docbase) {
return pixbuf;
return pixbuf;
g_warning ("<image xlink:href=\"%s\"> did not resolve to a valid image file (base dir is %s), now trying sodipodi:absref=\"%s\"", href, base, absref);
g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref);
return pixbuf;
return pixbuf;
return result;
static void sp_image_snappoints( SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs )
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER));
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER));
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER));
p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y0) * i2d, Inkscape::SNAPSOURCE_IMG_CORNER, Inkscape::SNAPTARGET_IMG_CORNER));
return ret;
while (*data) {
data_is_image = 1; // Illustrator produces embedded images without MIME type, so we assume it's image no matter what
while (*data) {
data++;
data++;
data++;
return pixbuf;
if (loader) {
bool eos = false;
bool failed = false;
while (!eos) {
btr++;
if (eos) {
ud[k] = 0;
eos = true;
ud[k] = 0;
eos = true;
ud[k] = 0;
btr++;
len++;
failed = true;
if (!failed) {
return pixbuf;
if ((image->height.computed < MAGIC_EPSILON_TOO) || (image->width.computed < MAGIC_EPSILON_TOO) || (image->clip_ref->getObject())) {
c->unref();
return result;
if ( !val ) {