diff --git a/src/main.cpp b/src/main.cpp
index bf1662c3121e06a047d35907be7f04307f9b2fde..f96d99e11e29a8dcffd545131f6364b397ab4ad8 100644 (file)
--- a/src/main.cpp
+++ b/src/main.cpp
#endif
#include "path-prefix.h"
+// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
+#include <png.h>
+
#include <gtk/gtkmessagedialog.h>
#ifdef HAVE_IEEEFP_H
#include <cstring>
#include <string>
#include <locale.h>
+#include <stdlib.h>
#include <popt.h>
#ifndef POPT_TABLEEND
#include <libxml/tree.h>
#include <glib-object.h>
+#include <gtk/gtk.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkwindow.h>
#include "svg/stringstream.h"
#include "inkscape-private.h"
-#include "inkscape-stock.h"
-#include "inkscape_version.h"
+#include "inkscape-version.h"
#include "sp-namedview.h"
#include "sp-guide.h"
#include "debug/log-display-config.h"
#include "helper/png-write.h"
+#include "helper/geom.h"
#include <extension/extension.h>
#include <extension/system.h>
#include <extension/db.h>
#include <extension/output.h>
+#include <extension/input.h>
#ifdef WIN32
//#define REPLACEARGS_ANSI
#endif
#include "application/application.h"
-
#include "main-cmdlineact.h"
+#include "widgets/icon.h"
+#include "ui/widget/panel.h"
-#include <png.h>
#include <errno.h>
enum {
SP_ARG_EXPORT_DPI,
SP_ARG_EXPORT_AREA,
SP_ARG_EXPORT_AREA_DRAWING,
- SP_ARG_EXPORT_AREA_CANVAS,
+ SP_ARG_EXPORT_AREA_PAGE,
SP_ARG_EXPORT_AREA_SNAP,
SP_ARG_EXPORT_WIDTH,
SP_ARG_EXPORT_HEIGHT,
SP_ARG_EXPORT_EMF,
#endif //WIN32
SP_ARG_EXPORT_TEXT_TO_PATH,
- SP_ARG_EXPORT_FONT,
- SP_ARG_EXPORT_BBOX_PAGE,
+ SP_ARG_EXPORT_IGNORE_FILTERS,
SP_ARG_EXTENSIONDIR,
- SP_ARG_FIT_PAGE_TO_DRAWING,
SP_ARG_QUERY_X,
SP_ARG_QUERY_Y,
SP_ARG_QUERY_WIDTH,
SP_ARG_QUERY_HEIGHT,
SP_ARG_QUERY_ALL,
SP_ARG_QUERY_ID,
+ SP_ARG_SHELL,
SP_ARG_VERSION,
SP_ARG_VACUUM_DEFS,
SP_ARG_VERB_LIST,
int sp_main_gui(int argc, char const **argv);
int sp_main_console(int argc, char const **argv);
static void sp_do_export_png(SPDocument *doc);
-static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
-static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime);
+static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const *mime);
#ifdef WIN32
static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
#endif //WIN32
-static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
+static void do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id);
static void do_query_all (SPDocument *doc);
static void do_query_all_recurse (SPObject *o);
static gchar *sp_export_dpi = NULL;
static gchar *sp_export_area = NULL;
static gboolean sp_export_area_drawing = FALSE;
-static gboolean sp_export_area_canvas = FALSE;
+static gboolean sp_export_area_page = FALSE;
static gchar *sp_export_width = NULL;
static gchar *sp_export_height = NULL;
static gchar *sp_export_id = NULL;
static gchar *sp_export_emf = NULL;
#endif //WIN32
static gboolean sp_export_text_to_path = FALSE;
+static gboolean sp_export_ignore_filters = FALSE;
static gboolean sp_export_font = FALSE;
-static gboolean sp_export_bbox_page = FALSE;
static gboolean sp_query_x = FALSE;
static gboolean sp_query_y = FALSE;
static gboolean sp_query_width = FALSE;
static gboolean sp_query_all = FALSE;
static gchar *sp_query_id = NULL;
static int sp_new_gui = FALSE;
+static gboolean sp_shell = FALSE;
static gboolean sp_vacuum_defs = FALSE;
static gchar *sp_export_png_utf8 = NULL;
static gchar *sp_export_svg_utf8 = NULL;
static gchar *sp_global_printer_utf8 = NULL;
+
+/**
+ * Reset variables to default values.
+ */
+static void resetCommandlineGlobals() {
+ sp_global_printer = NULL;
+ sp_export_png = NULL;
+ sp_export_dpi = NULL;
+ sp_export_area = NULL;
+ sp_export_area_drawing = FALSE;
+ sp_export_area_page = FALSE;
+ sp_export_width = NULL;
+ sp_export_height = NULL;
+ sp_export_id = NULL;
+ sp_export_background = NULL;
+ sp_export_background_opacity = NULL;
+ sp_export_area_snap = FALSE;
+ sp_export_use_hints = FALSE;
+ sp_export_id_only = FALSE;
+ sp_export_svg = NULL;
+ sp_export_ps = NULL;
+ sp_export_eps = NULL;
+ sp_export_pdf = NULL;
+#ifdef WIN32
+ sp_export_emf = NULL;
+#endif //WIN32
+ sp_export_text_to_path = FALSE;
+ sp_export_ignore_filters = FALSE;
+ sp_export_font = FALSE;
+ sp_query_x = FALSE;
+ sp_query_y = FALSE;
+ sp_query_width = FALSE;
+ sp_query_height = FALSE;
+ sp_query_all = FALSE;
+ sp_query_id = NULL;
+ sp_vacuum_defs = FALSE;
+
+ sp_export_png_utf8 = NULL;
+ sp_export_svg_utf8 = NULL;
+ sp_global_printer_utf8 = NULL;
+}
+
#ifdef WIN32
static bool replaceArgs( int& argc, char**& argv );
#endif
{"export-dpi", 'd',
POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
- N_("The resolution used for exporting SVG into bitmap (default 90)"),
+ N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"),
N_("DPI")},
{"export-area", 'a',
POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
- N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
+ N_("Exported area in SVG user units (default is the page; 0,0 is lower-left corner)"),
N_("x0:y0:x1:y1")},
{"export-area-drawing", 'D',
POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
- N_("Exported area is the entire drawing (not canvas)"),
+ N_("Exported area is the entire drawing (not page)"),
NULL},
- {"export-area-canvas", 'C',
- POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
- N_("Exported area is the entire canvas"),
+ {"export-area-page", 'C',
+ POPT_ARG_NONE, &sp_export_area_page, SP_ARG_EXPORT_AREA_PAGE,
+ N_("Exported area is the entire page"),
NULL},
{"export-area-snap", 0,
{"export-text-to-path", 'T',
POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
- N_("Convert text object to paths on export (EPS)"),
+ N_("Convert text object to paths on export (PS, EPS, PDF)"),
NULL},
- {"export-embed-fonts", 'F',
- POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT,
- N_("Embed fonts on export (Type 1 only) (EPS)"),
- NULL},
-
- {"export-bbox-page", 'B',
- POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
- N_("Export files with the bounding box set to the page size (EPS)"),
+ {"export-ignore-filters", 0,
+ POPT_ARG_NONE, &sp_export_ignore_filters, SP_ARG_EXPORT_IGNORE_FILTERS,
+ N_("Render filtered objects without filters, instead of rasterizing (PS, EPS, PDF)"),
NULL},
{"query-x", 'X',
N_("Object ID to select when Inkscape opens."),
N_("OBJECT-ID")},
+ {"shell", 0,
+ POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL,
+ N_("Start Inkscape in interactive shell mode."),
+ NULL},
+
POPT_AUTOHELP POPT_TABLEEND
};
static bool needToRecodeParams = true;
-gchar* blankParam = "";
+gchar * blankParam = g_strdup("");
-#ifdef WIN32
-static int _win32_set_inkscape_env(char *argv0)
-{
- CHAR szFullPath[_MAX_PATH];
- CHAR szDrive[_MAX_DRIVE];
- CHAR szDir[_MAX_DIR];
- CHAR szFile[_MAX_FNAME];
- CHAR szExt[_MAX_EXT];
- std::string tmp;
+#ifdef WIN32
- if (GetModuleFileName(NULL, szFullPath, sizeof(szFullPath)) == 0) {
- strcpy(szFullPath, argv0);
+/**
+ * Return the directory of the .exe that is currently running
+ */
+static Glib::ustring _win32_getExePath()
+{
+ char exeName[MAX_PATH+1];
+ // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
+ GetModuleFileName(NULL, exeName, MAX_PATH);
+ char *slashPos = strrchr(exeName, '\\');
+ if (slashPos) {
+ *slashPos = '\0';
}
+ Glib::ustring s = exeName;
+ return s;
+}
- _splitpath(szFullPath, szDrive, szDir, szFile, szExt);
- strcpy(szFullPath, szDrive);
- strcat(szFullPath, szDir);
+/**
+ * Set up the PATH and PYTHONPATH environment variables on
+ * win32
+ */
+static int _win32_set_inkscape_env(const Glib::ustring &exePath)
+{
+ // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
char *oldenv = getenv("PATH");
- tmp = "PATH=";
- tmp += szFullPath;
+ Glib::ustring tmp = "PATH=";
+ tmp += exePath;
tmp += ";";
- tmp += szFullPath;
- tmp += "python;";
- tmp += szFullPath;
- tmp += "perl";
+ tmp += exePath;
+ tmp += "\\python;";
+ tmp += exePath;
+ tmp += "\\python\\Scripts;"; // for uniconv.cmd
+ tmp += exePath;
+ tmp += "\\perl";
if(oldenv != NULL) {
tmp += ";";
tmp += oldenv;
oldenv = getenv("PYTHONPATH");
tmp = "PYTHONPATH=";
- tmp += szFullPath;
- tmp += "python;";
- tmp += szFullPath;
- tmp += "python\\Lib;";
- tmp += szFullPath;
- tmp += "python\\DLLs";
+ tmp += exePath;
+ tmp += "\\python;";
+ tmp += exePath;
+ tmp += "\\python\\Lib;";
+ tmp += exePath;
+ tmp += "\\python\\DLLs";
if(oldenv != NULL) {
tmp += ";";
tmp += oldenv;
}
#endif
+/**
+ * Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home
+ * can find inkex.py et al. (Bug #197475)
+ */
+static int set_extensions_env()
+{
+ char *oldenv = getenv("PYTHONPATH");
+ Glib::ustring tmp = INKSCAPE_EXTENSIONDIR;
+ if (oldenv != NULL) {
+ tmp += G_SEARCHPATH_SEPARATOR;
+ tmp += oldenv;
+ }
+ g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
+
+ return 0;
+}
+
+
+/**
+ * This is the classic main() entry point of the program, though on some
+ * architectures it might be called by something else.
+ */
int
main(int argc, char **argv)
{
fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
#endif
-#ifdef ENABLE_NLS
#ifdef WIN32
- _win32_set_inkscape_env(argv[0]);
+ /*
+ Set the current directory to the directory of the
+ executable. This seems redundant, but is needed for
+ when inkscape.exe is executed from another directory.
+ We use relative paths on win32.
+ HKCR\svgfile\shell\open\command is a good example
+ */
+ Glib::ustring homedir = _win32_getExePath();
+ // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
+ SetCurrentDirectory(homedir.c_str());
+ _win32_set_inkscape_env(homedir);
RegistryTool rt;
rt.setPathInfo();
- gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
- bindtextdomain(GETTEXT_PACKAGE, pathBuf);
- g_free(pathBuf);
+#endif
+
+ // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
+ Gtk::Main::init_gtkmm_internals();
+
+ // Bug #197475
+ set_extensions_env();
+
+ /**
+ * Call bindtextdomain() for various machines's paths
+ */
+#ifdef ENABLE_NLS
+#ifdef WIN32
+ Glib::ustring localePath = homedir;
+ localePath += "\\";
+ localePath += PACKAGE_LOCALE_DIR;
+ bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
#else
#ifdef ENABLE_BINRELOC
bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
Inkscape::Debug::Logger::init();
gboolean use_gui;
+
#ifndef WIN32
+ // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
use_gui = (getenv("DISPLAY") != NULL);
#else
- /*
- Set the current directory to the directory of the
- executable. This seems redundant, but is needed for
- when inkscape.exe is executed from another directory.
- We use relative paths on win32.
- HKCR\svgfile\shell\open\command is a good example
- */
- /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
- char *homedir = g_path_get_dirname(argv[0]);
- SetCurrentDirectory(homedir);
- g_free(homedir);
-
use_gui = TRUE;
#endif
/* Test whether with/without GUI is forced */
|| !strcmp(argv[i], "-e")
|| !strncmp(argv[i], "--export-png", 12)
|| !strcmp(argv[i], "-l")
- || !strncmp(argv[i], "--export-plain-svg", 12)
+ || !strncmp(argv[i], "--export-plain-svg", 18)
|| !strcmp(argv[i], "-i")
|| !strncmp(argv[i], "--export-area-drawing", 21)
|| !strcmp(argv[i], "-D")
- || !strncmp(argv[i], "--export-area-canvas", 20)
+ || !strncmp(argv[i], "--export-area-page", 18)
|| !strcmp(argv[i], "-C")
- || !strncmp(argv[i], "--export-id", 12)
+ || !strncmp(argv[i], "--export-id", 11)
|| !strcmp(argv[i], "-P")
|| !strncmp(argv[i], "--export-ps", 11)
|| !strcmp(argv[i], "-E")
|| !strcmp(argv[i], "-S")
|| !strncmp(argv[i], "--query-all", 11)
|| !strcmp(argv[i], "-X")
- || !strncmp(argv[i], "--query-x", 13)
+ || !strncmp(argv[i], "--query-x", 9)
|| !strcmp(argv[i], "-Y")
- || !strncmp(argv[i], "--query-y", 14)
+ || !strncmp(argv[i], "--query-y", 9)
|| !strcmp(argv[i], "--vacuum-defs")
+ || !strcmp(argv[i], "--shell")
)
{
/* main_console handles any exports -- not the gui */
return app.run();
}
+
+
+
void fixupSingleFilename( gchar **orig, gchar **spare )
{
if ( orig && *orig && **orig ) {
}
}
+
+
GSList *fixupFilenameEncoding( GSList* fl )
{
GSList *newFl = NULL;
static void
snooper(GdkEvent *event, gpointer /*data*/) {
- if(inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
+ if (inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
{
GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
switch (event->type) {
break;
}
}
+
+ if (inkscape_trackalt()) {
+ // MacOS X with X11 has some problem with the default
+ // xmodmapping. A ~/.xmodmap solution does not work reliably due
+ // to the way we package our executable in a .app that can launch
+ // X11 or use an already-running X11. The same problem has been
+ // reported on Linux but there is no .app/X11 to get in the way
+ // of ~/.xmodmap fixes. So we make this a preference.
+ //
+ // For some reason, Gdk senses changes in Alt (Mod1) state for
+ // many message types, but not for keystrokes! So this ugly hack
+ // tracks what the state of Alt-pressing is, and ensures
+ // GDK_MOD1_MASK is in the event->key.state as appropriate.
+ //
+ static gboolean altL_pressed = FALSE;
+ static gboolean altR_pressed = FALSE;
+ static gboolean alt_pressed = FALSE;
+ guint get_group0_keyval(GdkEventKey* event);
+ guint keyval = 0;
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK);
+ break;
+ case GDK_BUTTON_PRESS:
+ alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK);
+ break;
+ case GDK_KEY_PRESS:
+ keyval = get_group0_keyval(&event->key);
+ if (keyval == GDK_Alt_L) altL_pressed = TRUE;
+ if (keyval == GDK_Alt_R) altR_pressed = TRUE;
+ alt_pressed = alt_pressed || altL_pressed || altR_pressed;
+ alt_pressed = alt_pressed || (event->button.state & GDK_MOD1_MASK);
+ if (alt_pressed)
+ event->key.state |= GDK_MOD1_MASK;
+ else
+ event->key.state &= ~GDK_MOD1_MASK;
+ break;
+ case GDK_KEY_RELEASE:
+ keyval = get_group0_keyval(&event->key);
+ if (keyval == GDK_Alt_L) altL_pressed = FALSE;
+ if (keyval == GDK_Alt_R) altR_pressed = FALSE;
+ if (!altL_pressed && !altR_pressed)
+ alt_pressed = FALSE;
+ break;
+ default:
+ break;
+ }
+ //printf("alt_pressed: %s\n", alt_pressed? "+" : "-");
+ }
+
gtk_main_do_event (event);
}
+static std::vector<Glib::ustring> getDirectorySet(const gchar* userDir, const gchar* const * systemDirs) {
+ std::vector<Glib::ustring> listing;
+ listing.push_back(userDir);
+ for ( const char* const* cur = systemDirs; *cur; cur++ )
+ {
+ listing.push_back(*cur);
+ }
+ return listing;
+}
+
int
sp_main_gui(int argc, char const **argv)
{
int retVal = sp_common_main( argc, argv, &fl );
g_return_val_if_fail(retVal == 0, 1);
- inkscape_gtk_stock_init();
+ // Add possible icon entry directories
+ std::vector<Glib::ustring> dataDirs = getDirectorySet( g_get_user_data_dir(),
+ g_get_system_data_dirs() );
+ for (std::vector<Glib::ustring>::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
+ {
+ std::vector<Glib::ustring> listing;
+ listing.push_back(*it);
+ listing.push_back("inkscape");
+ listing.push_back("icons");
+ Glib::ustring dir = Glib::build_filename(listing);
+ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir.c_str());
+ }
- gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
+ // Add our icon directory to the search path for icon theme lookups.
+ gchar *usericondir = profile_path("icons");
+ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), usericondir);
+ gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), INKSCAPE_PIXMAPDIR);
+ g_free(usericondir);
+ gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
Inkscape::Debug::log_display_config();
- /* Set default icon */
- gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
- if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
- gtk_window_set_default_icon_from_file(filename, NULL);
- }
- g_free (filename);
- filename = 0;
+ // Set default window icon. Obeys the theme.
+ gtk_window_set_default_icon_name("inkscape");
+ // Do things that were previously in inkscape_gtk_stock_init().
+ sp_icon_get_phys_size(GTK_ICON_SIZE_MENU);
+ Inkscape::UI::Widget::Panel::prep();
gboolean create_new = TRUE;
return 0;
}
-int
-sp_main_console(int argc, char const **argv)
+/**
+ * Process file list
+ */
+void sp_process_file_list(GSList *fl)
{
- /* We are started in text mode */
-
- /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
- * in a non-Gtk environment. Used in libnrtype's
- * FontInstance.cpp and FontFactory.cpp.
- * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
- */
- g_type_init();
- char **argv2 = const_cast<char **>(argv);
- gtk_init_check( &argc, &argv2 );
- //setlocale(LC_ALL, "");
-
- GSList *fl = NULL;
- int retVal = sp_common_main( argc, argv, &fl );
- g_return_val_if_fail(retVal == 0, 1);
-
- if (fl == NULL) {
- g_print("Nothing to do!\n");
- exit(0);
- }
-
- inkscape_application_init(argv[0], false);
-
while (fl) {
- SPDocument *doc;
+ const gchar *filename = (gchar *)fl->data;
+
+ SPDocument *doc = NULL;
+ try {
+ doc = Inkscape::Extension::open(NULL, filename);
+ } catch (Inkscape::Extension::Input::no_extension_found &e) {
+ doc = NULL;
+ } catch (Inkscape::Extension::Input::open_failed &e) {
+ doc = NULL;
+ }
- doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
if (doc == NULL) {
- doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
+ try {
+ doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename);
+ } catch (Inkscape::Extension::Input::no_extension_found &e) {
+ doc = NULL;
+ } catch (Inkscape::Extension::Input::open_failed &e) {
+ doc = NULL;
+ }
}
if (doc == NULL) {
- g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
+ g_warning("Specified document %s cannot be opened (does not exist or not a valid SVG file)", filename);
} else {
if (sp_vacuum_defs) {
vacuum_document(doc);
}
if (sp_vacuum_defs && !sp_export_svg) {
// save under the name given in the command line
- sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
+ sp_repr_save_file(doc->rdoc, filename, SP_SVG_NS_URI);
}
if (sp_global_printer) {
sp_print_document_to_file(doc, sp_global_printer);
}
- if (sp_export_png) {
+ if (sp_export_png || (sp_export_id && sp_export_use_hints)) {
sp_do_export_png(doc);
}
if (sp_export_svg) {
Inkscape::XML::Node *repr;
rdoc = sp_repr_document_new("svg:svg");
repr = rdoc->root();
- repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
- sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
+ repr = sp_document_root(doc)->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD);
+ sp_repr_save_rebased_file(repr->document(), sp_export_svg, SP_SVG_NS_URI,
+ doc->base, sp_export_svg);
}
if (sp_export_ps) {
- do_export_ps(doc, sp_export_ps, "image/x-postscript");
+ do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
}
if (sp_export_eps) {
- do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
+ do_export_ps_pdf(doc, sp_export_eps, "image/x-e-postscript");
}
if (sp_export_pdf) {
- do_export_pdf(doc, sp_export_pdf, "application/pdf");
+ do_export_ps_pdf(doc, sp_export_pdf, "application/pdf");
}
#ifdef WIN32
if (sp_export_emf) {
if (sp_query_all) {
do_query_all (doc);
} else if (sp_query_width || sp_query_height) {
- do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
+ do_query_dimension (doc, true, sp_query_width? Geom::X : Geom::Y, sp_query_id);
} else if (sp_query_x || sp_query_y) {
- do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
+ do_query_dimension (doc, false, sp_query_x? Geom::X : Geom::Y, sp_query_id);
}
- }
+ delete doc;
+ }
fl = g_slist_remove(fl, fl->data);
}
+}
- inkscape_unref();
+/**
+ * Run the application as an interactive shell, parsing command lines from stdin
+ * Returns -1 on error.
+ */
+int sp_main_shell(char const* command_name)
+{
+ int retval = 0;
+
+ const unsigned int buffer_size = 4096;
+ gchar *command_line = g_strnfill(buffer_size, 0);
+ g_strlcpy(command_line, command_name, buffer_size);
+ gsize offset = g_strlcat(command_line, " ", buffer_size);
+ gsize sizeLeft = buffer_size - offset;
+ gchar *useme = command_line + offset;
+
+ fprintf(stdout, "Inkscape %s interactive shell mode. Type 'quit' to quit.\n", Inkscape::version_string);
+ fflush(stdout);
+ char* linedata = 0;
+ do {
+ fprintf(stdout, ">");
+ fflush(stdout);
+ if ((linedata = fgets(useme, sizeLeft, stdin))) {
+ size_t len = strlen(useme);
+ if ( (len >= sizeLeft - 1) || (useme[len - 1] != '\n') ) {
+ fprintf(stdout, "ERROR: Command line too long\n");
+ // Consume rest of line
+ retval = -1; // If the while loop completes, this remains -1
+ while (fgets(useme, sizeLeft, stdin) && retval) {
+ len = strlen(command_line);
+ if ( (len < buffer_size) && (command_line[len-1] == '\n') ) {
+ retval = 0;
+ }
+ }
+ } else {
+ useme[--len] = '\0'; // Strip newline
+ if (useme[len - 1] == '\r') {
+ useme[--len] = '\0';
+ }
+ if ( strcmp(useme, "quit") == 0 ) {
+ // Time to quit
+ fflush(stdout);
+ linedata = 0; // mark for exit
+ } else if ( len < 1 ) {
+ // blank string. Do nothing.
+ } else {
+ GError* parseError = 0;
+ gchar** argv = 0;
+ gint argc = 0;
+ if ( g_shell_parse_argv(command_line, &argc, &argv, &parseError) ) {
+ poptContext ctx = poptGetContext(NULL, argc, const_cast<const gchar**>(argv), options, 0);
+ poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
+ if ( ctx ) {
+ GSList *fl = sp_process_args(ctx);
+ sp_process_file_list(fl);
+ poptFreeContext(ctx);
+ } else {
+ retval = 1; // not sure why. But this was the previous return value
+ }
+ resetCommandlineGlobals();
+ g_strfreev(argv);
+ } else {
+ g_warning("Cannot parse commandline: %s", useme);
+ }
+ }
+ }
+ } // if (linedata...
+ } while (linedata && (retval == 0));
+
+ g_free(command_line);
+ return retval;
+}
+
+int sp_main_console(int argc, char const **argv)
+{
+ /* We are started in text mode */
+
+ /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
+ * in a non-Gtk environment. Used in libnrtype's
+ * FontInstance.cpp and FontFactory.cpp.
+ * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
+ */
+ g_type_init();
+ char **argv2 = const_cast<char **>(argv);
+ gtk_init_check( &argc, &argv2 );
+ //setlocale(LC_ALL, "");
+
+ GSList *fl = NULL;
+ int retVal = sp_common_main( argc, argv, &fl );
+ g_return_val_if_fail(retVal == 0, 1);
+
+ if (fl == NULL && !sp_shell) {
+ g_print("Nothing to do!\n");
+ exit(0);
+ }
+
+ inkscape_application_init(argv[0], false);
+
+ if (sp_shell) {
+ sp_main_shell(argv[0]); // Run as interactive shell
+ exit(0);
+ } else {
+ sp_process_file_list(fl); // Normal command line invokation
+ }
return 0;
}
static void
-do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
+do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
{
SPObject *o = NULL;
@@ -897,11 +1167,11 @@ do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gch
SPItem *item = ((SPItem *) o);
// "true" SVG bbox for scripting
- NR::Maybe<NR::Rect> area = item->getBounds(sp_item_i2doc_affine(item));
+ Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
if (area) {
Inkscape::SVGOStringStream os;
if (extent) {
- os << area->extent(axis);
+ os << area->dimensions()[axis];
} else {
os << area->min()[axis];
}
{
SPItem *item = ((SPItem *) o);
if (o->id && SP_IS_ITEM(item)) {
- NR::Maybe<NR::Rect> area = item->getBounds(sp_item_i2doc_affine(item));
+ Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
if (area) {
Inkscape::SVGOStringStream os;
os << o->id;
- os << "," << area->min()[NR::X];
- os << "," << area->min()[NR::Y];
- os << "," << area->extent(NR::X);
- os << "," << area->extent(NR::Y);
+ os << "," << area->min()[Geom::X];
+ os << "," << area->min()[Geom::Y];
+ os << "," << area->dimensions()[Geom::X];
+ os << "," << area->dimensions()[Geom::Y];
g_print ("%s\n", os.str().c_str());
}
}
sp_do_export_png(SPDocument *doc)
{
const gchar *filename = NULL;
+ bool filename_from_hint = false;
gdouble dpi = 0.0;
if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
GSList *items = NULL;
- NRRect area;
+ Geom::Rect area;
if (sp_export_id || sp_export_area_drawing) {
SPObject *o = NULL;
filename = sp_export_png;
} else {
filename = fn_hint;
+ filename_from_hint = true;
}
} else {
g_warning ("Export filename hint not found for the object.");
// write object bbox to area
sp_document_ensure_up_to_date (doc);
- sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
+ Geom::OptRect areaMaybe;
+ sp_item_invoke_bbox((SPItem *) o_area, areaMaybe, sp_item_i2d_affine((SPItem *) o_area), TRUE);
+ if (areaMaybe) {
+ area = *areaMaybe;
+ } else {
+ g_warning("Unable to determine a valid bounding box. Nothing exported.");
+ return;
+ }
} else {
g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
return;
if (sp_export_area) {
/* Try to parse area (given in SVG pixels) */
- if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
+ gdouble x0,y0,x1,y1;
+ if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &y1) == 4) {
g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
return;
}
- if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
- g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
- return;
- }
- } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
- /* Export the whole canvas */
+ area = Geom::Rect(Geom::Interval(x0,x1), Geom::Interval(y0,y1));
+ } else if (sp_export_area_page || !(sp_export_id || sp_export_area_drawing)) {
+ /* Export the whole page: note: Inkscape uses 'page' in all menus and dialogs, not 'canvas' */
sp_document_ensure_up_to_date (doc);
- area.x0 = SP_ROOT(doc->root)->x.computed;
- area.y0 = SP_ROOT(doc->root)->y.computed;
- area.x1 = area.x0 + sp_document_width (doc);
- area.y1 = area.y0 + sp_document_height (doc);
+ Geom::Point origin (SP_ROOT(doc->root)->x.computed, SP_ROOT(doc->root)->y.computed);
+ area = Geom::Rect(origin, origin + sp_document_dimensions(doc));
}
// set filename and dpi from options, if not yet set from the hints
}
if (sp_export_area_snap) {
- area.x0 = std::floor (area.x0);
- area.y0 = std::floor (area.y0);
- area.x1 = std::ceil (area.x1);
- area.y1 = std::ceil (area.y1);
+ round_rectangle_outwards(area);
}
// default dpi
- if (dpi == 0.0)
+ if (dpi == 0.0) {
dpi = PX_PER_IN;
+ }
unsigned long int width = 0;
unsigned long int height = 0;
if (sp_export_width) {
+ errno=0;
width = strtoul(sp_export_width, NULL, 0);
if ((width < 1) || (width > PNG_UINT_31_MAX) || (errno == ERANGE) ) {
g_warning("Export width %lu out of range (1 - %lu). Nothing exported.", width, (unsigned long int)PNG_UINT_31_MAX);
return;
}
- dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
+ dpi = (gdouble) width * PX_PER_IN / area.width();
}
if (sp_export_height) {
+ errno=0;
height = strtoul(sp_export_height, NULL, 0);
if ((height < 1) || (height > PNG_UINT_31_MAX)) {
g_warning("Export height %lu out of range (1 - %lu). Nothing exported.", height, (unsigned long int)PNG_UINT_31_MAX);
return;
}
- dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
+ dpi = (gdouble) height * PX_PER_IN / area.height();
}
if (!sp_export_width) {
- width = (unsigned long int) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
+ width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5);
}
if (!sp_export_height) {
- height = (unsigned long int) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
+ height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5);
}
guint32 bgcolor = 0x00000000;
}
}
+ gchar *path = 0;
+ if (filename_from_hint) {
+ //Make relative paths go from the document location, if possible:
+ if (!g_path_is_absolute(filename) && doc->uri) {
+ gchar *dirname = g_path_get_dirname(doc->uri);
+ if (dirname) {
+ path = g_build_filename(dirname, filename, NULL);
+ g_free(dirname);
+ }
+ }
+ if (!path) {
+ path = g_strdup(filename);
+ }
+ } else {
+ path = g_strdup(filename);
+ }
+
g_print("Background RRGGBBAA: %08x\n", bgcolor);
- g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area.x0, area.y0, area.x1, area.y1, width, height, dpi);
+ g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi);
g_print("Bitmap saved as: %s\n", filename);
if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
- sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
+ sp_export_png_file(doc, path, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
} else {
g_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX);
}
+ g_free (path);
g_slist_free (items);
}
/**
- * Perform an export of either PS or EPS.
+ * Perform a PDF/PS/EPS export
*
* \param doc Document to export.
* \param uri URI to export to.
* \param mime MIME type to export as.
*/
-static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
-{
- Inkscape::Extension::DB::OutputList o;
- Inkscape::Extension::db.get_output_list(o);
- Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
- while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
- i++;
- }
-
- if (i == o.end())
- {
- g_warning ("Could not find an extension to export to MIME type %s.", mime);
- return;
- }
-
- bool old_text_to_path = false;
- bool old_font_embedded = false;
- bool old_bbox_page = false;
-
- try {
- old_text_to_path = (*i)->get_param_bool("textToPath");
- (*i)->set_param_bool("textToPath", sp_export_text_to_path);
- }
- catch (...) {
- g_warning ("Could not set export-text-to-path option for this export.");
- }
-
- try {
- old_font_embedded = (*i)->get_param_bool("fontEmbedded");
- (*i)->set_param_bool("fontEmbedded", sp_export_font);
- }
- catch (...) {
- g_warning ("Could not set export-font option for this export.");
- }
-
- try {
- old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
- (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
- }
- catch (...) {
- g_warning ("Could not set export-bbox-page option for this export.");
- }
-
- (*i)->save(doc, uri);
-
- try {
- (*i)->set_param_bool("textToPath", old_text_to_path);
- (*i)->set_param_bool("fontEmbedded", old_font_embedded);
- (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
- }
- catch (...) {
-
- }
-}
-
-/**
- * Perform a PDF export
- *
- * \param doc Document to export.
- * \param uri URI to export to.
- * \param mime MIME type to export as.
- */
-
-static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
+static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
{
Inkscape::Extension::DB::OutputList o;
Inkscape::Extension::db.get_output_list(o);
@@ -1249,16 +1479,56 @@ static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
(*i)->set_param_string ("exportId", "");
}
+ if (sp_export_area_page && sp_export_area_drawing) {
+ g_warning ("You cannot use --export-area-page and --export-area-drawing at the same time; only the former will take effect.");
+ sp_export_area_drawing = false;
+ }
+
if (sp_export_area_drawing) {
- (*i)->set_param_bool ("exportDrawing", TRUE);
+ (*i)->set_param_bool ("areaDrawing", TRUE);
+ } else {
+ (*i)->set_param_bool ("areaDrawing", FALSE);
+ }
+
+ if (sp_export_area_page) {
+ if (sp_export_eps) {
+ g_warning ("EPS cannot have its bounding box extend beyond its content, so if your drawing is smaller than the page, --export-area-page will clip it to drawing.");
+ }
+ (*i)->set_param_bool ("areaPage", TRUE);
+ } else {
+ (*i)->set_param_bool ("areaPage", FALSE);
+ }
+
+ if (!sp_export_area_drawing && !sp_export_area_page && !sp_export_id) {
+ // neither is set, set page as default for ps/pdf and drawing for eps
+ if (sp_export_eps) {
+ try {
+ (*i)->set_param_bool("areaDrawing", TRUE);
+ } catch (...) {}
+ }
+ }
+
+ if (sp_export_text_to_path) {
+ (*i)->set_param_bool("textToPath", TRUE);
} else {
- (*i)->set_param_bool ("exportDrawing", FALSE);
+ (*i)->set_param_bool("textToPath", FALSE);
}
- if (sp_export_area_canvas) {
- (*i)->set_param_bool ("exportCanvas", TRUE);
+ if (sp_export_ignore_filters) {
+ (*i)->set_param_bool("blurToBitmap", FALSE);
} else {
- (*i)->set_param_bool ("exportCanvas", FALSE);
+ (*i)->set_param_bool("blurToBitmap", TRUE);
+
+ gdouble dpi = 90.0;
+ if (sp_export_dpi) {
+ dpi = atof(sp_export_dpi);
+ if ((dpi < 1) || (dpi > 10000.0)) {
+ g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi);
+ dpi = 90;
+ }
+ }
+
+ (*i)->set_param_int("resolution", (int) dpi);
}
(*i)->save(doc, uri);
if ( wildcarded )
{
#ifdef REPLACEARGS_ANSI
- WIN32_FIND_DATAA data = {0};
+ WIN32_FIND_DATAA data;
#else
- WIN32_FIND_DATAW data = {0};
+ WIN32_FIND_DATAW data;
#endif // REPLACEARGS_ANSI
+ memset((void *)&data, 0, sizeof(data));
+
int baseLen = wcslen(parsed[i1]) + 2;
wchar_t* base = new wchar_t[baseLen];
wcsncpy( base, parsed[i1], baseLen );
GSList *fl = NULL;
gint a;
- while ((a = poptGetNextOpt(ctx)) >= 0) {
+ while ((a = poptGetNextOpt(ctx)) != -1) {
switch (a) {
case SP_ARG_FILE: {
gchar const *fn = poptGetOptArg(ctx);
break;
}
case SP_ARG_VERSION: {
- printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
+ printf("Inkscape %s (%s)\n", Inkscape::version_string, __DATE__);
exit(0);
break;
}
}
break;
}
+ case POPT_ERROR_BADOPT: {
+ g_warning ("Invalid option %s", poptBadOption(ctx, 0));
+ exit(1);
+ break;
+ }
default: {
break;
}