/* * A simple image display widget, using Inkscape's own rendering engine * * Authors: * Bob Jamison * Other dudes from The Inkscape Organization * Abhishek Sharma * * Copyright (C) 2004 The Inkscape Organization * * Released under GNU GPL, read the file 'COPYING' for more information */ #include "imageicon.h" #include #include "svg-view-widget.h" #include "document.h" #include "inkscape.h" #include #include namespace Inkscape { namespace UI { namespace Widget { typedef enum { SVG_TYPES, IMPORT_TYPES, EXPORT_TYPES } FileDialogType; /*######################################################################### ### ImageIcon widget #########################################################################*/ /** * Constructor */ ImageIcon::ImageIcon() { init(); } /** * Construct from a file name */ ImageIcon::ImageIcon(const Glib::ustring &fileName) { init(); showSvgFile(fileName); } /** * Copy Constructor */ ImageIcon::ImageIcon(const ImageIcon &other) : sigc::trackable(), Glib::ObjectBase(), Gtk::VBox() { init(); document = other.document; viewerGtkmm = other.viewerGtkmm; showingBrokenImage = other.showingBrokenImage; } /** * Destructor */ ImageIcon::~ImageIcon() { if (document) document->doUnref(); } /** * basic initialization, called by the various constructors */ void ImageIcon::init() { if (!INKSCAPE) inkscape_application_init("",false); document = NULL; viewerGtkmm = NULL; //set_size_request(150,150); showingBrokenImage = false; } bool ImageIcon::showSvgDocument(const SPDocument *docArg) { if (document) document->doUnref(); SPDocument *doc = const_cast(docArg); doc->doRef(); document = doc; //This should remove it from the box, and free resources //if (viewerGtkmm) // viewerGtkmm->destroy(); GtkWidget *viewerGtk = sp_svg_view_widget_new(doc); viewerGtkmm = Glib::wrap(viewerGtk); viewerGtkmm->show(); pack_start(*viewerGtkmm, TRUE, TRUE, 0); //GtkWidget *vbox = (GtkWidget *)gobj(); //gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0); return true; } bool ImageIcon::showSvgFile(const Glib::ustring &theFileName) { Glib::ustring fileName = theFileName; fileName = Glib::filename_to_utf8(fileName); SPDocument *doc = SPDocument::createNewDoc (fileName.c_str(), 0); if (!doc) { g_warning("SVGView: error loading document '%s'\n", fileName.c_str()); return false; } showSvgDocument(doc); doc->doUnref(); return true; } bool ImageIcon::showSvgFromMemory(const char *xmlBuffer) { if (!xmlBuffer) return false; gint len = (gint)strlen(xmlBuffer); SPDocument *doc = SPDocument::createNewDocFromMem(xmlBuffer, len, 0); if (!doc) { g_warning("SVGView: error loading buffer '%s'\n",xmlBuffer); return false; } showSvgDocument(doc); doc->doUnref(); return true; } bool ImageIcon::showBitmap(const Glib::ustring &theFileName) { Glib::ustring fileName = theFileName; /*##################################### # LET'S HAVE SOME FUN WITH SVG! # Instead of just loading an image, why # don't we make a lovely little svg and # display it nicely? #####################################*/ //Arbitrary size of svg doc -- rather 'portrait' shaped gint previewWidth = 400; gint previewHeight = 600; //Get some image info. Smart pointer does not need to be deleted Glib::RefPtr img = Gdk::Pixbuf::create_from_file(fileName); gint imgWidth = img->get_width(); gint imgHeight = img->get_height(); //Find the minimum scale to fit the image inside the preview area double scaleFactorX = (0.9 *(double)previewWidth) / ((double)imgWidth); double scaleFactorY = (0.9 *(double)previewHeight) / ((double)imgHeight); double scaleFactor = scaleFactorX; if (scaleFactorX > scaleFactorY) scaleFactor = scaleFactorY; //Now get the resized values gint scaledImgWidth = (int) (scaleFactor * (double)imgWidth); gint scaledImgHeight = (int) (scaleFactor * (double)imgHeight); //center the image on the area gint imgX = (previewWidth - scaledImgWidth) / 2; gint imgY = (previewHeight - scaledImgHeight) / 2; //wrap a rectangle around the image gint rectX = imgX-1; gint rectY = imgY-1; gint rectWidth = scaledImgWidth +2; gint rectHeight = scaledImgHeight+2; //Our template. Modify to taste gchar const *xformat = "\n" "\n" "\n" "\n" "\n" "\n\n"; //if (!Glib::get_charset()) //If we are not utf8 fileName = Glib::filename_to_utf8(fileName); //Fill in the template /* FIXME: Do proper XML quoting for fileName. */ gchar *xmlBuffer = g_strdup_printf(xformat, previewWidth, previewHeight, imgX, imgY, scaledImgWidth, scaledImgHeight, fileName.c_str(), rectX, rectY, rectWidth, rectHeight); //g_message("%s\n", xmlBuffer); //now show it! showSvgFromMemory(xmlBuffer); g_free(xmlBuffer); return true; } void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage) { //Are we already showing it? if (showingBrokenImage) return; //Our template. Modify to taste gchar const *xformat = "" "" "" " " " " " " " " " " " " " %s" ""; //Fill in the template char *cErrorMessage = (char *)errorMessage.c_str(); gchar *xmlBuffer = g_strdup_printf(xformat, cErrorMessage); //g_message("%s\n", xmlBuffer); //now show it! showSvgFromMemory(xmlBuffer); g_free(xmlBuffer); showingBrokenImage = true; } static bool hasSuffix(const Glib::ustring &str, Glib::ustring &ext) { int strLen = str.length(); int extLen = ext.length(); if (extLen > strLen) { return false; } int strpos = strLen-1; for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--) { Glib::ustring::value_type ch = str[strpos]; if (ch != ext[extpos]) { if ( ((ch & 0xff80) != 0) || static_cast( g_ascii_tolower( static_cast(0x07f & ch) ) ) != ext[extpos] ) { return false; } } } return true; } /** * Return true if the image is loadable by Gdk, else false */ static bool isValidImageIconFile(const Glib::ustring &fileName) { std::vectorformats = Gdk::Pixbuf::get_formats(); for (unsigned int i=0; iextensions = format.get_extensions(); for (unsigned int j=0; j 0x150000L) { Glib::ustring err = "File too large"; showBrokenImage(err); return false; } } Glib::ustring svg = ".svg"; Glib::ustring svgz = ".svgz"; if (hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) ) { if (!showSvgFile(fileName)) { showBrokenImage(bitmapError); return false; } return true; } else if (isValidImageIconFile(fileName)) { if (!showBitmap(fileName)) { showBrokenImage(bitmapError); return false; } return true; } else { showBrokenImage("unsupported file type"); return false; } } } // namespace Widget } // namespace UI } // namespace Inkscape /*######################################################################### ### E N D O F F I L E #########################################################################*/