diff options
| author | Ted Gould <ted@gould.cx> | 2010-03-26 04:34:25 +0000 |
|---|---|---|
| committer | Ted Gould <ted@gould.cx> | 2010-03-26 04:34:25 +0000 |
| commit | 9e023a3aa964a0d3fa1e31e46d33657367ba68aa (patch) | |
| tree | 33f1392a340737e4eeefca6fd031f96c29befd2b /src/extension | |
| parent | Installing the pkgconfig file (diff) | |
| parent | Adding in shape-record.h (diff) | |
| download | inkscape-9e023a3aa964a0d3fa1e31e46d33657367ba68aa.tar.gz inkscape-9e023a3aa964a0d3fa1e31e46d33657367ba68aa.zip | |
Merge from trunk
(bzr r8254.1.53)
Diffstat (limited to 'src/extension')
30 files changed, 1170 insertions, 214 deletions
diff --git a/src/extension/dxf2svg/entities2elements.cpp b/src/extension/dxf2svg/entities2elements.cpp index ab160e265..f280bb2a8 100644 --- a/src/extension/dxf2svg/entities2elements.cpp +++ b/src/extension/dxf2svg/entities2elements.cpp @@ -20,10 +20,12 @@ SoC 2005 */ -#include"entities2elements.h" -#include"tables2svg_info.h" -#include<iostream> -#include<math.h> +#include "entities2elements.h" +#include "tables2svg_info.h" +#include <iostream> +#include <math.h> +#include <string.h> +#include <stdlib.h> // The names indicate the DXF entitiy first and the SVG element last // Common elements diff --git a/src/extension/dxf2svg/read_dxf.cpp b/src/extension/dxf2svg/read_dxf.cpp index 8a6a6d6ac..ecda343c6 100644 --- a/src/extension/dxf2svg/read_dxf.cpp +++ b/src/extension/dxf2svg/read_dxf.cpp @@ -11,11 +11,13 @@ -#include<fstream> -#include<string> -#include"read_dxf.h" +#include <fstream> +#include <string> +#include "read_dxf.h" -#include<iostream> +#include <iostream> +#include <string.h> +#include <stdlib.h> using namespace std; diff --git a/src/extension/dxf2svg/tables2svg_info.cpp b/src/extension/dxf2svg/tables2svg_info.cpp index 17bc47beb..3b27a9c38 100644 --- a/src/extension/dxf2svg/tables2svg_info.cpp +++ b/src/extension/dxf2svg/tables2svg_info.cpp @@ -10,9 +10,11 @@ */ -#include"tables2svg_info.h" -#include<math.h> -#include<iostream> +#include "tables2svg_info.h" +#include <math.h> +#include <iostream> +#include <stdlib.h> +#include <string.h> char* pattern2dasharray(ltype info, int precision, double scaling, char* out){ std::vector< double > pattern = info.ret_pattern(); diff --git a/src/extension/execution-env.cpp b/src/extension/execution-env.cpp index e8d7c4baf..7ed389195 100644 --- a/src/extension/execution-env.cpp +++ b/src/extension/execution-env.cpp @@ -58,7 +58,7 @@ ExecutionEnv::ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Imp sp_desktop_selection(desktop)->itemList(); while ( selected != NULL ) { Glib::ustring selected_id; - selected_id = SP_OBJECT_ID(*selected); + selected_id = (*selected)->getId(); _selected.insert(_selected.end(), selected_id); //std::cout << "Selected: " << selected_id << std::endl; ++selected; @@ -127,7 +127,7 @@ ExecutionEnv::createWorkingDialog (void) { SPDesktop *desktop = (SPDesktop *)_doc; GtkWidget *toplevel = gtk_widget_get_toplevel(&(desktop->canvas->widget)); - if (!toplevel || !GTK_WIDGET_TOPLEVEL (toplevel)) + if (!toplevel || !GTK_WIDGET_TOPLEVEL (toplevel)) return; Gtk::Window *window = Glib::wrap(GTK_WINDOW(toplevel), false); diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp index 52d5f5148..b4cf06bda 100644 --- a/src/extension/extension.cpp +++ b/src/extension/extension.cpp @@ -57,7 +57,9 @@ Parameter * param_shared (const gchar * name, GSList * list); not related to the module directly. If the Repr does not include a name and an ID the module will be left in an errored state. */ -Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) : _help(NULL) +Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) + : _help(NULL) + , _gui(true) { repr = in_repr; Inkscape::GC::anchor(in_repr); @@ -438,6 +440,14 @@ Extension::get_param_enum (const gchar * name, const SPDocument * doc, const Ink return param->get_enum(doc, node); } + +gchar const *Extension::get_param_optiongroup( gchar const * name, SPDocument const * doc, Inkscape::XML::Node const * node) +{ + Parameter* param = param_shared(name, parameters); + return param->get_optiongroup(doc, node); +} + + /** \return The value of the parameter identified by the name \brief Gets a parameter identified by name with the bool placed @@ -595,6 +605,13 @@ Extension::set_param_string (const gchar * name, const gchar * value, SPDocument return param->set_string(value, doc, node); } +gchar const * Extension::set_param_optiongroup(gchar const * name, gchar const * value, SPDocument * doc, Inkscape::XML::Node * node) +{ + Parameter * param = param_shared(name, parameters); + return param->set_optiongroup(value, doc, node); +} + + /** \return The passed in value \brief Sets a parameter identified by name with the string @@ -673,7 +690,7 @@ public: Gtk::Widget * Extension::autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) { - if (param_visible_count() == 0) return NULL; + if (!_gui || param_visible_count() == 0) return NULL; AutoGUI * agui = Gtk::manage(new AutoGUI()); diff --git a/src/extension/extension.h b/src/extension/extension.h index 48ca86cf7..c71ae59b4 100644 --- a/src/extension/extension.h +++ b/src/extension/extension.h @@ -99,6 +99,7 @@ private: state_t _state; /**< Which state the Extension is currently in */ std::vector<Dependency *> _deps; /**< Dependencies for this extension */ static std::ofstream error_file; /**< This is the place where errors get reported */ + bool _gui; protected: Inkscape::XML::Node *repr; /**< The XML description of the Extension */ @@ -138,8 +139,8 @@ public: g_slist_length(parameters); }; /** \brief A function to get the the number of parameters that are visible to the user that the extension has. - \return The number of visible parameters. - + \return The number of visible parameters. + \note Currently this just calls param_count as visible isn't implemented but in the future it'll do something different. Please call the appropriate function in code so that it'll work in the @@ -152,16 +153,17 @@ public: class param_wrong_type {}; class param_not_color_param {}; class param_not_enum_param {}; + class param_not_optiongroup_param {}; class param_not_string_param {}; class param_not_float_param {}; class param_not_int_param {}; class param_not_bool_param {}; - - /** An error class for when a parameter is looked for that just + + /** An error class for when a parameter is looked for that just * simply doesn't exist */ class param_not_exist {}; - - /** An error class for when a filename already exists, but the user + + /** An error class for when a filename already exists, but the user * doesn't want to overwrite it */ class no_overwrite {}; @@ -175,37 +177,56 @@ public: bool get_param_bool (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + int get_param_int (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + float get_param_float (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + const gchar * get_param_string (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + guint32 get_param_color (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + const gchar * get_param_enum (const gchar * name, const SPDocument * doc = NULL, const Inkscape::XML::Node * node = NULL); + + gchar const *get_param_optiongroup( gchar const * name, + SPDocument const * doc = 0, + Inkscape::XML::Node const * node = 0); + bool set_param_bool (const gchar * name, bool value, SPDocument * doc = NULL, Inkscape::XML::Node * node = NULL); + int set_param_int (const gchar * name, int value, SPDocument * doc = NULL, Inkscape::XML::Node * node = NULL); + float set_param_float (const gchar * name, float value, SPDocument * doc = NULL, Inkscape::XML::Node * node = NULL); + const gchar * set_param_string (const gchar * name, const gchar * value, SPDocument * doc = NULL, Inkscape::XML::Node * node = NULL); + + gchar const * set_param_optiongroup(gchar const * name, + gchar const * value, + SPDocument * doc = 0, + Inkscape::XML::Node * node = 0); + guint32 set_param_color (const gchar * name, guint32 color, SPDocument * doc = NULL, @@ -219,6 +240,7 @@ public: public: Gtk::Widget * autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal = NULL); void paramListString (std::list <std::string> & retlist); + void set_gui(bool s) { _gui = s; } /* Extension editor dialog stuff */ public: diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 5f1bef8d1..60623191f 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -5,6 +5,7 @@ * Authors: * Bryce Harrington <bryce@osdl.org> * Ted Gould <ted@gould.cx> + * Jon A. Cruz <jon@joncruz.org> * * Copyright (C) 2002-2005,2007 Authors * @@ -64,13 +65,13 @@ namespace Implementation { /** \brief Make GTK+ events continue to come through a little bit - This just keeps coming the events through so that we'll make the GUI - update and look pretty. + This just keeps coming the events through so that we'll make the GUI + update and look pretty. */ -void -Script::pump_events (void) { - while( Gtk::Main::events_pending() ) +void Script::pump_events (void) { + while ( Gtk::Main::events_pending() ) { Gtk::Main::iteration(); + } return; } @@ -96,17 +97,15 @@ Script::interpreter_t const Script::interpreterTab[] = { /** \brief Look up an interpreter name, and translate to something that - is executable + is executable \param interpNameArg The name of the interpreter that we're looking - for, should be an entry in interpreterTab + for, should be an entry in interpreterTab */ -Glib::ustring -Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) +Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) { - Glib::ustring interpName = interpNameArg; - interpreter_t const *interp; + interpreter_t const *interp = 0; bool foundInterp = false; for (interp = interpreterTab ; interp->identity ; interp++ ){ if (interpName == interp->identity) { @@ -116,8 +115,9 @@ Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) } // Do we have a supported interpreter type? - if (!foundInterp) + if (!foundInterp) { return ""; + } interpName = interp->defaultval; // 1. Check preferences @@ -137,6 +137,7 @@ Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) Glib::ustring path; Glib::ustring exeName; if (rt.getExeInfo(fullPath, path, exeName)) { +// TODO replace with proper glib/glibmm path building routines: Glib::ustring interpPath = path; interpPath.append("\\"); interpPath.append(interpNameArg); @@ -144,7 +145,7 @@ Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) interpPath.append(interpName); interpPath.append(".exe"); struct stat finfo; - if (stat(interpPath .c_str(), &finfo) ==0) { + if (stat(interpPath .c_str(), &finfo) == 0) { g_message("Found local interpreter, '%s', Size: %d", interpPath .c_str(), (int)finfo.st_size); @@ -153,12 +154,11 @@ Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg) } // 3. Try searching the path - char szExePath[MAX_PATH]; - char szCurrentDir[MAX_PATH]; + char szExePath[MAX_PATH] = {0}; + char szCurrentDir[MAX_PATH] = {0}; GetCurrentDirectory(sizeof(szCurrentDir), szCurrentDir); - unsigned int ret = (unsigned int)FindExecutable( - interpName.c_str(), szCurrentDir, szExePath); - if (ret > 32) { + HINSTANCE ret = FindExecutable(interpName.c_str(), szCurrentDir, szExePath); + if (ret > reinterpret_cast<HINSTANCE>(32)) { interpName = szExePath; return interpName; } @@ -231,9 +231,9 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { Glib::ustring filename = fname; g_free(fname); - if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) + if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) { return filename; - + } } } else { Glib::ustring str = sp_repr_children(reprin)->content(); @@ -261,8 +261,7 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { then a TRUE is returned. If we get all the way through the path then a FALSE is returned, the command could not be found. */ -bool -Script::check_existance(const Glib::ustring &command) +bool Script::check_existance(const Glib::ustring &command) { // Check the simple case first @@ -272,21 +271,23 @@ Script::check_existance(const Glib::ustring &command) //Don't search when it contains a slash. */ if (command.find(G_DIR_SEPARATOR) != command.npos) { - if (Inkscape::IO::file_test(command.c_str(), G_FILE_TEST_EXISTS)) + if (Inkscape::IO::file_test(command.c_str(), G_FILE_TEST_EXISTS)) { return true; - else + } else { return false; + } } Glib::ustring path; gchar *s = (gchar *) g_getenv("PATH"); - if (s) + if (s) { path = s; - else + } else { /* There is no `PATH' in the environment. The default search path is the current directory */ path = G_SEARCHPATH_SEPARATOR_S; + } std::string::size_type pos = 0; std::string::size_type pos2 = 0; @@ -339,11 +340,11 @@ Script::check_existance(const Glib::ustring &command) and should error out at a higher level. */ -bool -Script::load(Inkscape::Extension::Extension *module) +bool Script::load(Inkscape::Extension::Extension *module) { - if (module->loaded()) + if (module->loaded()) { return true; + } helper_extension = ""; @@ -392,8 +393,7 @@ Script::load(Inkscape::Extension::Extension *module) This function just sets the module to unloaded. It free's the command if it has been allocated. */ -void -Script::unload(Inkscape::Extension::Extension */*module*/) +void Script::unload(Inkscape::Extension::Extension */*module*/) { command.clear(); helper_extension = ""; @@ -411,11 +411,11 @@ Script::unload(Inkscape::Extension::Extension */*module*/) bool Script::check(Inkscape::Extension::Extension *module) { - int script_count = 0; + int script_count = 0; Inkscape::XML::Node *child_repr = sp_repr_children(module->get_repr()); while (child_repr != NULL) { if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "script")) { - script_count++; + script_count++; child_repr = sp_repr_children(child_repr); while (child_repr != NULL) { if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "check")) { @@ -443,9 +443,9 @@ Script::check(Inkscape::Extension::Extension *module) child_repr = sp_repr_next(child_repr); } - if (script_count == 0) { - return false; - } + if (script_count == 0) { + return false; + } return true; } @@ -488,8 +488,7 @@ ScriptDocCache::~ScriptDocCache ( ) unlink(_filename.c_str()); } -ImplementationDocumentCache * -Script::newDocCache( Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::View::View * view ) { +ImplementationDocumentCache *Script::newDocCache( Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::View::View * view ) { return new ScriptDocCache(view); } @@ -502,8 +501,7 @@ Script::newDocCache( Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::Vie This function should really do something, right now it doesn't. */ -Gtk::Widget * -Script::prefs_input(Inkscape::Extension::Input *module, +Gtk::Widget *Script::prefs_input(Inkscape::Extension::Input *module, const gchar */*filename*/) { return module->autogui(NULL, NULL); @@ -518,8 +516,7 @@ Script::prefs_input(Inkscape::Extension::Input *module, This function should really do something, right now it doesn't. */ -Gtk::Widget * -Script::prefs_output(Inkscape::Extension::Output *module) +Gtk::Widget *Script::prefs_output(Inkscape::Extension::Output *module) { return module->autogui(NULL, NULL); } @@ -545,8 +542,7 @@ Script::prefs_output(Inkscape::Extension::Output *module) the incoming filename (so that it's not the temporary filename). That document is then returned from this function. */ -SPDocument * -Script::open(Inkscape::Extension::Input *module, +SPDocument *Script::open(Inkscape::Extension::Input *module, const gchar *filenameArg) { std::list<std::string> params; @@ -621,8 +617,7 @@ Script::open(Inkscape::Extension::Input *module, put the output of the script into the final output file. We then delete the temporary file. */ -void -Script::save(Inkscape::Extension::Output *module, +void Script::save(Inkscape::Extension::Output *module, SPDocument *doc, const gchar *filenameArg) { @@ -662,7 +657,7 @@ Script::save(Inkscape::Extension::Output *module, // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name unlink(tempfilename_in.c_str()); - if(success == false) { + if (success == false) { throw Inkscape::Extension::Output::save_failed(); } @@ -699,8 +694,7 @@ Script::save(Inkscape::Extension::Output *module, exists at the time, the other is created by that script). At that point both should be full, and the second one is loaded. */ -void -Script::effect(Inkscape::Extension::Effect *module, +void Script::effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc, ImplementationDocumentCache * docCache) { @@ -745,7 +739,7 @@ Script::effect(Inkscape::Extension::Effect *module, while ( selected != NULL ) { Glib::ustring selected_id; selected_id += "--id="; - selected_id += SP_OBJECT_ID(*selected); + selected_id += (*selected)->getId(); params.insert(params.begin(), selected_id); ++selected; } @@ -801,8 +795,7 @@ Script::effect(Inkscape::Extension::Effect *module, elements and putting them into the old document. The copy is then complete. */ -void -Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) +void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) { std::vector<Inkscape::XML::Node *> delete_list; Inkscape::XML::Node * oldroot_namedview = NULL; @@ -821,8 +814,9 @@ Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) delete_list.push_back(child); } } - for (unsigned int i = 0; i < delete_list.size(); i++) + for (unsigned int i = 0; i < delete_list.size(); i++) { sp_repr_unparent(delete_list[i]); + } for (Inkscape::XML::Node * child = newroot->firstChild(); child != NULL; @@ -851,8 +845,9 @@ Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) } // Delete the attributes of the old root nodes. - for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); it++) + for (std::vector<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); it++) { oldroot->setAttribute(*it, NULL); + } // Set the new attributes. for (List<AttributeRecord const> iter = newroot->attributeList(); iter; ++iter) { @@ -869,8 +864,7 @@ Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) shows it in a warning dialog to the user \param filename Filename of the stderr file */ -void -Script::checkStderr (const Glib::ustring &data, +void Script::checkStderr (const Glib::ustring &data, Gtk::MessageType type, const Glib::ustring &message) { @@ -902,8 +896,7 @@ Script::checkStderr (const Glib::ustring &data, return; } -bool -Script::cancelProcessing (void) { +bool Script::cancelProcessing (void) { _canceled = true; _main_loop->quit(); Glib::spawn_close_pid(_pid); @@ -939,8 +932,7 @@ Script::cancelProcessing (void) { At the very end (after the data has been copied) both of the files are closed, and we return to what we were doing. */ -int -Script::execute (const std::list<std::string> &in_command, +int Script::execute (const std::list<std::string> &in_command, const std::list<std::string> &in_params, const Glib::ustring &filein, file_listener &fileout) @@ -968,52 +960,51 @@ Script::execute (const std::list<std::string> &in_command, //std::cout << "first space " << first_space << std::endl; //std::cout << "first quote " << first_quote << std::endl; - if((first_quote != std::string::npos) && (first_quote == 0)) { + if ((first_quote != std::string::npos) && (first_quote == 0)) { size_t next_quote = param_str.find_first_of('"', first_quote + 1); //std::cout << "next quote " << next_quote << std::endl; - if(next_quote != std::string::npos) { + if (next_quote != std::string::npos) { //std::cout << "now split " << next_quote << std::endl; //std::cout << "now split " << param_str.substr(1, next_quote - 1) << std::endl; //std::cout << "now split " << param_str.substr(next_quote + 1) << std::endl; std::string part_str = param_str.substr(1, next_quote - 1); - if(part_str.size() > 0) + if (part_str.size() > 0) argv.push_back(part_str); param_str = param_str.substr(next_quote + 1); - } - else { - if(param_str.size() > 0) + } else { + if (param_str.size() > 0) argv.push_back(param_str); param_str = ""; } - } - else if(first_space != std::string::npos) { + } else if (first_space != std::string::npos) { //std::cout << "now split " << first_space << std::endl; //std::cout << "now split " << param_str.substr(0, first_space) << std::endl; //std::cout << "now split " << param_str.substr(first_space + 1) << std::endl; std::string part_str = param_str.substr(0, first_space); - if(part_str.size() > 0) + if (part_str.size() > 0) { argv.push_back(part_str); + } param_str = param_str.substr(first_space + 1); - } - else { - if(param_str.size() > 0) + } else { + if (param_str.size() > 0) { argv.push_back(param_str); + } param_str = ""; } - } while(param_str.size() > 0); + } while (param_str.size() > 0); } for (std::list<std::string>::const_iterator i = in_params.begin(); i != in_params.end(); i++) { - //g_message("Script parameter: %s",(*i)g.c_str()); + //g_message("Script parameter: %s",(*i)g.c_str()); argv.push_back(*i); } if (!(filein.empty())) { - argv.push_back(filein); + argv.push_back(filein); } int stdout_pipe, stderr_pipe; @@ -1042,10 +1033,12 @@ Script::execute (const std::list<std::string> &in_command, _main_loop->run(); // Ensure all the data is out of the pipe - while (!fileout.isDead()) + while (!fileout.isDead()) { fileout.read(Glib::IO_IN); - while (!fileerr.isDead()) + } + while (!fileerr.isDead()) { fileerr.read(Glib::IO_IN); + } if (_canceled) { // std::cout << "Script Canceled" << std::endl; diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h index 8e25fb351..e0b6701bf 100644 --- a/src/extension/implementation/script.h +++ b/src/extension/implementation/script.h @@ -10,8 +10,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifndef __INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H__ -#define __INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H__ +#ifndef INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H_SEEN +#define INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H_SEEN #include "implementation.h" #include <gtkmm/messagedialog.h> @@ -62,7 +62,7 @@ public: */ virtual bool check(Inkscape::Extension::Extension *module); - ImplementationDocumentCache * newDocCache (Inkscape::Extension::Extension * ext, Inkscape::UI::View::View * view); + ImplementationDocumentCache * newDocCache(Inkscape::Extension::Extension * ext, Inkscape::UI::View::View * view); /** * @@ -93,7 +93,7 @@ public: */ virtual void effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc, - ImplementationDocumentCache * docCache); + ImplementationDocumentCache * docCache); virtual bool cancelProcessing (void); @@ -204,18 +204,18 @@ private: const Glib::ustring &filein, file_listener &fileout); - void pump_events (void); + void pump_events(void); - /** \brief A definition of an interpreter, which can be specified - in the INX file, but we need to know what to call */ - struct interpreter_t { - gchar const *identity; /**< The ID that is in the INX file */ - gchar const *prefstring; /**< The preferences key that can override the default */ - gchar const *defaultval; /**< The default value if there are no preferences */ - }; + /** \brief A definition of an interpreter, which can be specified + in the INX file, but we need to know what to call */ + struct interpreter_t { + gchar const *identity; /**< The ID that is in the INX file */ + gchar const *prefstring; /**< The preferences key that can override the default */ + gchar const *defaultval; /**< The default value if there are no preferences */ + }; static interpreter_t const interpreterTab[]; - Glib::ustring resolveInterpreterExecutable(const Glib::ustring &interpNameArg); + Glib::ustring resolveInterpreterExecutable(const Glib::ustring &interpNameArg); }; // class Script @@ -227,7 +227,7 @@ private: } // namespace Extension } // namespace Inkscape -#endif /* __INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H__ */ +#endif // INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H_SEEN /* Local Variables: diff --git a/src/extension/init.cpp b/src/extension/init.cpp index dc39ea430..f58c8cbe6 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -127,10 +127,10 @@ update_pref(Glib::ustring const &pref_path, /* gboolean missing=TRUE; for (GSList *list = extension_family; list; list = g_slist_next(list)) { - g_assert( list->data ); + g_assert( list->data ); - Inkscape::Extension *extension; - extension = reinterpret_cast<Inkscape::Extension *>(list->data); + Inkscape::Extension *extension; + extension = reinterpret_cast<Inkscape::Extension *>(list->data); if (!strcmp(extension->get_id(),pref)) missing=FALSE; } @@ -231,14 +231,14 @@ init() Internal::Bitmap::Wave::init(); #endif /* WITH_IMAGE_MAGICK */ - Internal::Filter::Filter::filters_all(); + Internal::Filter::Filter::filters_all(); /* Load search path for extensions */ if (Inkscape::Extension::Extension::search_path.size() == 0) { - Inkscape::Extension::Extension::search_path.push_back(profile_path("extensions")); - - Inkscape::Extension::Extension::search_path.push_back(g_strdup(INKSCAPE_EXTENSIONDIR)); + Inkscape::Extension::Extension::search_path.push_back(profile_path("extensions")); + + Inkscape::Extension::Extension::search_path.push_back(g_strdup(INKSCAPE_EXTENSIONDIR)); } diff --git a/src/extension/input.h b/src/extension/input.h index 55d807ce2..24cbc4896 100644 --- a/src/extension/input.h +++ b/src/extension/input.h @@ -11,6 +11,7 @@ #ifndef INKSCAPE_EXTENSION_INPUT_H__ #define INKSCAPE_EXTENSION_INPUT_H__ +#include <exception> #include <glib.h> #include "extension.h" #include "xml/repr.h" @@ -30,8 +31,14 @@ public: /* this is a hack for this release, this will be private shortly */ gchar *output_extension; /**< Setting of what output extension should be used */ public: - class open_failed {}; /**< Generic failure for an undescribed reason */ - class no_extension_found {}; /**< Failed because we couldn't find an extension to match the filename */ + struct open_failed : public std::exception { + virtual ~open_failed() throw() {} + const char *what() const throw() { return "Open failed"; } + }; + struct no_extension_found : public std::exception { + virtual ~no_extension_found() throw() {} + const char *what() const throw() { return "No suitable input extension found"; } + }; Input (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp); diff --git a/src/extension/internal/CMakeLists.txt b/src/extension/internal/CMakeLists.txt index c9c00e05b..8b23cb0ac 100644 --- a/src/extension/internal/CMakeLists.txt +++ b/src/extension/internal/CMakeLists.txt @@ -20,6 +20,7 @@ latex-pstricks.cpp latex-pstricks-out.cpp odf.cpp pdfinput +latex-text-renderer.cpp pdf-input-cairo.cpp pov-out.cpp javafx-out.cpp diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert index d2ba9b3eb..3c1ce7f43 100644 --- a/src/extension/internal/Makefile_insert +++ b/src/extension/internal/Makefile_insert @@ -109,6 +109,8 @@ ink_common_sources += \ extension/internal/javafx-out.h \ extension/internal/gdkpixbuf-input.h \ extension/internal/gdkpixbuf-input.cpp \ + extension/internal/latex-text-renderer.h \ + extension/internal/latex-text-renderer.cpp \ extension/internal/pdfinput/svg-builder.h \ extension/internal/pdfinput/svg-builder.cpp \ extension/internal/pdfinput/pdf-parser.h \ diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp index 737bb2885..61760e9d9 100644 --- a/src/extension/internal/cairo-ps-out.cpp +++ b/src/extension/internal/cairo-ps-out.cpp @@ -21,6 +21,7 @@ #include "cairo-ps-out.h" #include "cairo-render-context.h" #include "cairo-renderer.h" +#include "latex-text-renderer.h" #include <print.h> #include "extension/system.h" #include "extension/print.h" @@ -61,7 +62,8 @@ bool CairoEpsOutput::check (Inkscape::Extension::Extension * /*module*/) } static bool -ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false) +ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool omittext, + bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false) { sp_document_ensure_up_to_date(doc); @@ -93,6 +95,7 @@ ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int l ctx->setPSLevel(level); ctx->setEPS(eps); ctx->setTextToPath(texttopath); + renderer->_omitText = omittext; ctx->setFilterToBitmap(filtertobitmap); ctx->setBitmapResolution(resolution); @@ -146,6 +149,14 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con new_textToPath = mod->get_param_bool("textToPath"); } catch(...) {} + bool new_textToLaTeX = FALSE; + try { + new_textToLaTeX = mod->get_param_bool("textToLaTeX"); + } + catch(...) { + g_warning("Parameter <textToLaTeX> might not exist"); + } + bool new_blurToBitmap = FALSE; try { new_blurToBitmap = mod->get_param_bool("blurToBitmap"); @@ -171,13 +182,29 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con new_exportId = mod->get_param_string("exportId"); } catch(...) {} - gchar * final_name; - final_name = g_strdup_printf("> %s", filename); - ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage); - g_free(final_name); + // Create PS + { + gchar * final_name; + final_name = g_strdup_printf("> %s", filename); + ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage); + g_free(final_name); - if (!ret) - throw Inkscape::Extension::Output::save_failed(); + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } + + // Create LaTeX file (if requested) + if (new_textToLaTeX) { + gchar * tex_filename; + //strip filename of ".ps", do not add ".tex" here. + gsize n = g_str_has_suffix(filename, ".ps") ? strlen(filename)-3 : strlen(filename); + tex_filename = g_strndup(filename, n); + ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage, false); + g_free(tex_filename); + + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } } @@ -210,6 +237,14 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co new_textToPath = mod->get_param_bool("textToPath"); } catch(...) {} + bool new_textToLaTeX = FALSE; + try { + new_textToLaTeX = mod->get_param_bool("textToLaTeX"); + } + catch(...) { + g_warning("Parameter <textToLaTeX> might not exist"); + } + bool new_blurToBitmap = FALSE; try { new_blurToBitmap = mod->get_param_bool("blurToBitmap"); @@ -235,13 +270,29 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co new_exportId = mod->get_param_string("exportId"); } catch(...) {} - gchar * final_name; - final_name = g_strdup_printf("> %s", filename); - ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage, true); - g_free(final_name); + // Create EPS + { + gchar * final_name; + final_name = g_strdup_printf("> %s", filename); + ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage, true); + g_free(final_name); - if (!ret) - throw Inkscape::Extension::Output::save_failed(); + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } + + // Create LaTeX file (if requested) + if (new_textToLaTeX) { + gchar * tex_filename; + //strip filename of ".eps", do not add ".tex" here. + gsize n = g_str_has_suffix(filename, ".eps") ? strlen(filename)-4 : strlen(filename); + tex_filename = g_strndup(filename, n); + ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage, false); + g_free(tex_filename); + + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } } @@ -280,6 +331,7 @@ CairoPsOutput::init (void) #endif "</param>\n" "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" + "<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n" @@ -317,6 +369,7 @@ CairoEpsOutput::init (void) #endif "</param>\n" "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" + "<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n" diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index c33beab8a..877bdb952 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -80,7 +80,7 @@ #include <pango/pangofc-fontmap.h> //#define TRACE(_args) g_printf _args -#define TRACE(_args) +#define TRACE(_args) g_message _args //#define TEST(_args) _args #define TEST(_args) @@ -662,7 +662,11 @@ CairoRenderContext::popLayer(void) surface_width *= 1.25; surface_height *= 1.25; } - mask_ctx->setupSurface( surface_width, surface_height ); + if (!mask_ctx->setupSurface( surface_width, surface_height )) { + TRACE(("mask: setupSurface failed\n")); + _renderer->destroyContext(mask_ctx); + return; + } TRACE(("mask surface: %f x %f at %i dpi\n", surface_width, surface_height, _dpi )); // set rendering mode to normal @@ -815,6 +819,7 @@ CairoRenderContext::setSurfaceTarget(cairo_surface_t *surface, bool is_vector, c bool CairoRenderContext::_finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t *ctm) { +g_message("enter"); if(surface == NULL) { return false; } @@ -841,7 +846,7 @@ CairoRenderContext::_finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t } _is_valid = TRUE; - +g_message("leave"); return true; } diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index 0598c388a..808590e04 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -5,8 +5,9 @@ * Authors: * Ted Gould <ted@gould.cx> * Ulf Erikson <ulferikson@users.sf.net> + * Johan Engelen <goejendaagh@zonnet.nl> * - * Copyright (C) 2004-2006 Authors + * Copyright (C) 2004-2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -20,6 +21,7 @@ #include "cairo-renderer-pdf-out.h" #include "cairo-render-context.h" #include "cairo-renderer.h" +#include "latex-text-renderer.h" #include <print.h> #include "extension/system.h" #include "extension/print.h" @@ -33,6 +35,8 @@ #include "sp-item.h" #include "sp-root.h" +#include <2geom/matrix.h> + namespace Inkscape { namespace Extension { namespace Internal { @@ -48,7 +52,7 @@ CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module) static bool pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, - bool texttopath, bool filtertobitmap, int resolution, + bool texttopath, bool omittext, bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas) { sp_document_ensure_up_to_date(doc); @@ -83,6 +87,7 @@ pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int CairoRenderContext *ctx = renderer->createContext(); ctx->setPDFLevel(level); ctx->setTextToPath(texttopath); + renderer->_omitText = omittext; ctx->setFilterToBitmap(filtertobitmap); ctx->setBitmapResolution(resolution); @@ -106,7 +111,6 @@ pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int return ret; } - /** \brief This function calls the output module with the filename \param mod unused @@ -146,6 +150,14 @@ CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, g_warning("Parameter <textToPath> might not exist"); } + bool new_textToLaTeX = FALSE; + try { + new_textToLaTeX = mod->get_param_bool("textToLaTeX"); + } + catch(...) { + g_warning("Parameter <textToLaTeX> might not exist"); + } + bool new_blurToBitmap = FALSE; try { new_blurToBitmap = mod->get_param_bool("blurToBitmap"); @@ -186,15 +198,31 @@ CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, g_warning("Parameter <exportCanvas> might not exist"); } - gchar * final_name; - final_name = g_strdup_printf("> %s", filename); - ret = pdf_render_document_to_file(doc, final_name, level, - new_textToPath, new_blurToBitmap, new_bitmapResolution, - new_exportId, new_exportDrawing, new_exportCanvas); - g_free(final_name); + // Create PDF file + { + gchar * final_name; + final_name = g_strdup_printf("> %s", filename); + ret = pdf_render_document_to_file(doc, final_name, level, + new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, + new_exportId, new_exportDrawing, new_exportCanvas); + g_free(final_name); + + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } - if (!ret) - throw Inkscape::Extension::Output::save_failed(); + // Create LaTeX file (if requested) + if (new_textToLaTeX) { + gchar * tex_filename; + //strip filename of ".pdf", do not add ".tex" here. + gsize n = g_str_has_suffix(filename, ".pdf") ? strlen(filename)-4 : strlen(filename); + tex_filename = g_strndup(filename, n); + ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_exportDrawing, new_exportCanvas, true); + g_free(tex_filename); + + if (!ret) + throw Inkscape::Extension::Output::save_failed(); + } } #include "clear-n_.h" @@ -217,6 +245,7 @@ CairoRendererPdfOutput::init (void) "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n" "</param>\n" "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n" + "<param name=\"textToLaTeX\" gui-text=\"" N_("PDF+LaTeX: Omit text in PDF, and create LaTeX file") "\" type=\"boolean\">false</param>\n" "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n" "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n" "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n" diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 8cc386135..6e4bb3b7e 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -29,6 +29,7 @@ #include <errno.h> #include "libnr/nr-rect.h" +#include "libnrtype/Layout-TNG.h" #include <2geom/transforms.h> #include <2geom/pathvector.h> @@ -102,6 +103,7 @@ namespace Extension { namespace Internal { CairoRenderer::CairoRenderer(void) + : _omitText(false) {} CairoRenderer::~CairoRenderer(void) @@ -567,6 +569,11 @@ CairoRenderer::setStateForItem(CairoRenderContext *ctx, SPItem const *item) void CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) { + if ( _omitText && (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) ) { + // skip text if _omitText is true + return; + } + ctx->pushState(); setStateForItem(ctx, item); @@ -591,6 +598,8 @@ CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) bool CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool pageBoundingBox, SPItem *base) { +// PLEASE note when making changes to the boundingbox and transform calculation, corresponding changes should be made to PDFLaTeXRenderer::setupDocument !!! + g_assert( ctx != NULL ); if (!base) diff --git a/src/extension/internal/cairo-renderer.h b/src/extension/internal/cairo-renderer.h index ab5d4cf58..d69a60753 100644 --- a/src/extension/internal/cairo-renderer.h +++ b/src/extension/internal/cairo-renderer.h @@ -56,6 +56,10 @@ public: /** Traverses the object tree and invokes the render methods. */ void renderItem(CairoRenderContext *ctx, SPItem *item); + + /** If _omitText is true, no text will be output to the PDF document. + The PDF will be exactly the same as if the text was written to it and then erased. */ + bool _omitText; }; // FIXME: this should be a static method of CairoRenderer diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp index d98f8e9a2..30e622507 100644 --- a/src/extension/internal/filter/filter.cpp +++ b/src/extension/internal/filter/filter.cpp @@ -71,7 +71,9 @@ Filter::get_filter (Inkscape::Extension::Extension * ext) { } void -Filter::merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar * srcGraphic, gchar * srcGraphicAlpha) +Filter::merge_filters( Inkscape::XML::Node * to, Inkscape::XML::Node * from, + Inkscape::XML::Document * doc, + gchar const * srcGraphic, gchar const * srcGraphicAlpha) { if (from == NULL) return; diff --git a/src/extension/internal/filter/filter.h b/src/extension/internal/filter/filter.h index fe6b678d9..a5d5d9d4e 100644 --- a/src/extension/internal/filter/filter.h +++ b/src/extension/internal/filter/filter.h @@ -25,7 +25,7 @@ protected: private: Inkscape::XML::Document * get_filter (Inkscape::Extension::Extension * ext); - void merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar * srcGraphic = NULL, gchar * srcGraphicAlpha = NULL); + void merge_filters (Inkscape::XML::Node * to, Inkscape::XML::Node * from, Inkscape::XML::Document * doc, gchar const * srcGraphic = NULL, gchar const * srcGraphicAlpha = NULL); public: Filter(); diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index 64a099c8a..a1295406c 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -1,11 +1,14 @@ #ifdef HAVE_CONFIG_H # include <config.h> #endif +#include <glib/gprintf.h> #include "document-private.h" #include <dir-util.h> +#include "extension/input.h" #include "extension/system.h" #include "gdkpixbuf-input.h" #include "selection-chemistry.h" +#include "sp-image.h" namespace Inkscape { @@ -16,69 +19,88 @@ GdkPixbuf* pixbuf_new_from_file( char const *utf8name, GError **error ); 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) +GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) { + bool embed = (strcmp(mod->get_param_optiongroup("link"), "embed") == 0); + 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 */ + 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); + } + + // HACK: replace with something better based on GIO + if (!ext.empty() && lossy.find(ext) != lossy.end()) { + is_lossy = true; + mime_type = "image/jpeg"; + } else { + is_lossy = false; + mime_type = "image/png"; + } + doc = sp_document_new(NULL, TRUE, TRUE); bool saved = sp_document_get_undo_sensitive(doc); sp_document_set_undo_sensitive(doc, false); // no need to undo in this temporary document - Inkscape::XML::Node *repr = NULL; - double width = gdk_pixbuf_get_width(pb); double height = gdk_pixbuf_get_height(pb); gchar const *str = gdk_pixbuf_get_option( pb, "Inkscape::DpiX" ); - if ( str ) - { + if ( str ) { gint dpi = atoi(str); - if ( dpi > 0 && dpi != 72 ) - { + if ( dpi > 0 && dpi != 72 ) { double scale = 72.0 / (double)dpi; width *= scale; } } str = gdk_pixbuf_get_option( pb, "Inkscape::DpiY" ); - if ( str ) - { + if ( str ) { gint dpi = atoi(str); - if ( dpi > 0 && dpi != 72 ) - { + if ( dpi > 0 && dpi != 72 ) { double scale = 72.0 / (double)dpi; height *= scale; } } + // Create image node Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); - // import as <image> - repr = xml_doc->createElement("svg:image"); - - // convert filename to uri - gchar* _uri = g_filename_to_uri(uri, NULL, NULL); - if(_uri) { - repr->setAttribute("xlink:href", _uri); - g_free(_uri); + Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); + sp_repr_set_svg_double(image_node, "width", width); + sp_repr_set_svg_double(image_node, "height", height); + + if (embed) { + sp_embed_image(image_node, pb, mime_type); } else { - repr->setAttribute("xlink:href", uri); + // convert filename to uri + gchar* _uri = g_filename_to_uri(uri, NULL, NULL); + if(_uri) { + image_node->setAttribute("xlink:href", _uri); + g_free(_uri); + } else { + image_node->setAttribute("xlink:href", uri); + } } - /* impl: doc->base is currently NULL, so we can use uri for href whether it's absolute - * or relative. The href will get rewritten by rebase_hrefs if by chance uri is relative - * and doc gets saved to a different directory. - * - * We don't bother setting sodipodi:absref, as we assume it's never useful to have - * sodipodi:absref with the same value as xlink:href, and rebase_hrefs will provide - * sodipodi:absref values where necessary. */ - - sp_repr_set_svg_double(repr, "width", width); - sp_repr_set_svg_double(repr, "height", height); - - SP_DOCUMENT_ROOT(doc)->appendChildRepr(repr); - Inkscape::GC::release(repr); - gdk_pixbuf_unref(pb); - //alter the canvas size to fit the image size + + g_object_unref(pb); + + // Add it to the current layer + SP_DOCUMENT_ROOT(doc)->appendChildRepr(image_node); + Inkscape::GC::release(image_node); fit_canvas_to_drawing(doc); // restore undo, as now this document may be shown to the user if a bitmap was opened sp_document_set_undo_sensitive(doc, saved); @@ -126,6 +148,11 @@ GdkpixbufInput::init(void) "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" "<name>" N_("%s GDK pixbuf Input") "</name>\n" "<id>org.inkscape.input.gdkpixbuf.%s</id>\n" + "<param name='link' type='optiongroup' appearance='full' _gui-text='" N_("Link or embed image:") "' >\n" + "<_option value='embed'>" N_("embed") "</_option>\n" + "<_option value='link'>" N_("link") "</_option>\n" + "</param>\n" + "<_param name='help' type='description'>" N_("Embed results in stand-alone, larger SVG files. Link references a file outside this SVG document and all files must be moved together.") "</_param>\n" "<input>\n" "<extension>.%s</extension>\n" "<mimetype>%s</mimetype>\n" diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index a2f387406..ca061a63a 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -707,7 +707,7 @@ bool JavaFXOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) * Check the type of node and process */ String id; - if (!obj->id) + if (!obj->getId()) { char buf[16]; sprintf(buf, "id%d", idindex++); @@ -715,7 +715,7 @@ bool JavaFXOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) } else { - id = obj->id; + id = obj->getId(); } if (SP_IS_ITEM(obj)) { @@ -773,7 +773,7 @@ bool JavaFXOutput::doBody(SPDocument *doc, SPObject *obj) * Check the type of node and process */ String id; - if (!obj->id) + if (!obj->getId()) { char buf[16]; sprintf(buf, "id%d", idindex++); @@ -781,7 +781,7 @@ bool JavaFXOutput::doBody(SPDocument *doc, SPObject *obj) } else { - id = obj->id; + id = obj->getId(); } if (SP_IS_ITEM(obj)) { diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp index 789e5ea34..34b7532ce 100644 --- a/src/extension/internal/latex-pstricks.cpp +++ b/src/extension/internal/latex-pstricks.cpp @@ -203,13 +203,19 @@ PrintLatex::fill(Inkscape::Extension::Print *mod, if (style->fill.isColor()) { Inkscape::SVGOStringStream os; float rgb[3]; + float fill_opacity; os.setf(std::ios::fixed); + fill_opacity=SP_SCALE24_TO_FLOAT(style->fill_opacity.value); sp_color_get_rgb_floatv(&style->fill.value.color, rgb); os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n"; + os << "\\pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor"; + if (fill_opacity!=1.0) { + os << ",opacity="<<fill_opacity; + } - os << "\\pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor]\n{\n"; + os << "]\n{\n"; print_pathvector(os, pathv, transform); @@ -230,14 +236,20 @@ PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pat if (style->stroke.isColor()) { Inkscape::SVGOStringStream os; float rgb[3]; + float stroke_opacity; Geom::Matrix tr_stack = m_tr_stack.top(); double const scale = tr_stack.descrim(); os.setf(std::ios::fixed); + stroke_opacity=SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); sp_color_get_rgb_floatv(&style->stroke.value.color, rgb); os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n"; os << "\\pscustom[linewidth=" << style->stroke_width.computed*scale<< ",linecolor=curcolor"; + + if (stroke_opacity!=1.0) { + os<<",strokeopacity="<<stroke_opacity; + } if (style->stroke_dasharray_set && style->stroke_dash.n_dash && diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp new file mode 100644 index 000000000..28bba1beb --- /dev/null +++ b/src/extension/internal/latex-text-renderer.cpp @@ -0,0 +1,569 @@ +#define EXTENSION_INTERNAL_LATEX_TEXT_RENDERER_CPP + +/** \file + * Rendering LaTeX file (pdf/eps/ps+latex output) + * + * The idea stems from GNUPlot's epslatex terminal output :-) + */ +/* + * Authors: + * Johan Engelen <goejendaagh@zonnet.nl> + * Miklos Erdelyi <erdelyim@gmail.com> + * + * Copyright (C) 2006-2010 Authors + * + * Licensed under GNU GPL + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "latex-text-renderer.h" + +#include <signal.h> +#include <errno.h> + +#include "libnrtype/Layout-TNG.h" +#include <2geom/transforms.h> +#include <2geom/rect.h> + +#include <glibmm/i18n.h> +#include "sp-item.h" +#include "sp-item-group.h" +#include "style.h" +#include "sp-root.h" +#include "sp-use.h" +#include "sp-text.h" +#include "sp-flowtext.h" +#include "sp-rect.h" +#include "text-editing.h" + +#include <unit-constants.h> + +#include "extension/system.h" + +#include "io/sys.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { + +/** + * This method is called by the PDF, EPS and PS output extensions. + * @param filename This should be the filename without extension to which the tex code should be written. Output goes to <filename>.tex. + */ +bool +latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, + const gchar * const exportId, bool exportDrawing, bool exportCanvas, + bool pdflatex) +{ + sp_document_ensure_up_to_date(doc); + + SPItem *base = NULL; + + bool pageBoundingBox = true; + if (exportId && strcmp(exportId, "")) { + // we want to export the given item only + base = SP_ITEM(doc->getObjectById(exportId)); + pageBoundingBox = exportCanvas; + } + else { + // we want to export the entire document from root + base = SP_ITEM(sp_document_root(doc)); + pageBoundingBox = !exportDrawing; + } + + if (!base) + return false; + + /* Create renderer */ + LaTeXTextRenderer *renderer = new LaTeXTextRenderer(pdflatex); + + bool ret = renderer->setTargetFile(filename); + if (ret) { + /* Render document */ + bool ret = renderer->setupDocument(doc, pageBoundingBox, base); + if (ret) { + renderer->renderItem(base); + } + } + + delete renderer; + + return ret; +} + +LaTeXTextRenderer::LaTeXTextRenderer(bool pdflatex) + : _stream(NULL), + _filename(NULL), + _pdflatex(pdflatex) +{ + push_transform(Geom::identity()); +} + +LaTeXTextRenderer::~LaTeXTextRenderer(void) +{ + if (_stream) { + writePostamble(); + + fclose(_stream); + } + + /* restore default signal handling for SIGPIPE */ +#if !defined(_WIN32) && !defined(__WIN32__) + (void) signal(SIGPIPE, SIG_DFL); +#endif + + if (_filename) { + g_free(_filename); + } + + return; +} + +/** This should create the output LaTeX file, and assign it to _stream. + * @return Returns true when succesfull + */ +bool +LaTeXTextRenderer::setTargetFile(gchar const *filename) { + if (filename != NULL) { + while (isspace(*filename)) filename += 1; + + _filename = g_path_get_basename(filename); + + gchar *filename_ext = g_strdup_printf("%s.tex", filename); + Inkscape::IO::dump_fopen_call(filename_ext, "K"); + FILE *osf = Inkscape::IO::fopen_utf8name(filename_ext, "w+"); + if (!osf) { + fprintf(stderr, "inkscape: fopen(%s): %s\n", + filename_ext, strerror(errno)); + return false; + } + _stream = osf; + g_free(filename_ext); + } + + if (_stream) { + /* fixme: this is kinda icky */ +#if !defined(_WIN32) && !defined(__WIN32__) + (void) signal(SIGPIPE, SIG_IGN); +#endif + } + + fprintf(_stream, "%%%% Creator: Inkscape %s, www.inkscape.org\n", PACKAGE_STRING); + fprintf(_stream, "%%%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010\n"); + fprintf(_stream, "%%%% Accompanies image file '%s' (pdf, eps, ps)\n", _filename); + fprintf(_stream, "%%%%\n"); + /* flush this to test output stream as early as possible */ + if (fflush(_stream)) { + if (ferror(_stream)) { + g_print("Error %d on LaTeX file output stream: %s\n", errno, + g_strerror(errno)); + } + g_print("Output to LaTeX file failed\n"); + /* fixme: should use pclose() for pipes */ + fclose(_stream); + _stream = NULL; + fflush(stdout); + return false; + } + + writePreamble(); + + return true; +} + +static char const preamble[] = +"%% To include the image in your LaTeX document, write\n" +"%% \\input{<filename>.tex}\n" +"%% instead of\n" +"%% \\includegraphics{<filename>.pdf}\n" +"%% To scale the image, write\n" +"%% \\def{\\svgwidth}{<desired width>}\n" +"%% \\input{<filename>.tex}\n" +"%% instead of\n" +"%% \\includegraphics[width=<desired width>]{<filename>.pdf}\n" +"\n" +"\\begingroup\n" +" \\makeatletter\n" +" \\providecommand\\color[2][]{%\n" +" \\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package \'color.sty\' is not loaded}\n" +" \\renewcommand\\color[2][]{}%\n" +" }\n" +" \\providecommand\\transparent[1]{%\n" +" \\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package \'transparent.sty\' is not loaded}\n" +" \\renewcommand\\transparent[1]{}%\n" +" }\n" +" \\providecommand\\rotatebox[2]{#2}\n"; + +static char const postamble[] = +" \\end{picture}%\n" +"\\endgroup\n"; + +void +LaTeXTextRenderer::writePreamble() +{ + fprintf(_stream, "%s", preamble); +} +void +LaTeXTextRenderer::writePostamble() +{ + fprintf(_stream, "%s", postamble); +} + +void +LaTeXTextRenderer::sp_group_render(SPItem *item) +{ + SPGroup *group = SP_GROUP(item); + + GSList *l = g_slist_reverse(group->childList(false)); + while (l) { + SPObject *o = SP_OBJECT (l->data); + if (SP_IS_ITEM(o)) { + renderItem (SP_ITEM (o)); + } + l = g_slist_remove (l, o); + } +} + +void +LaTeXTextRenderer::sp_use_render(SPItem *item) +{ + bool translated = false; + SPUse *use = SP_USE(item); + + if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { + Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed)); + push_transform(tp); + translated = true; + } + + if (use->child && SP_IS_ITEM(use->child)) { + renderItem(SP_ITEM(use->child)); + } + + if (translated) { + pop_transform(); + } +} + +void +LaTeXTextRenderer::sp_text_render(SPItem *item) +{ + SPText *textobj = SP_TEXT (item); + SPStyle *style = SP_OBJECT_STYLE (SP_OBJECT(item)); + + gchar *str = sp_te_get_string_multiline(item); + if (!str) { + return; + } + + // get position and alignment + // Align vertically on the baseline of the font (retreived from the anchor point) + // Align horizontally on anchorpoint + gchar const *alignment = NULL; + switch (style->text_anchor.computed) { + case SP_CSS_TEXT_ANCHOR_START: + alignment = "[lb]"; + break; + case SP_CSS_TEXT_ANCHOR_END: + alignment = "[rb]"; + break; + case SP_CSS_TEXT_ANCHOR_MIDDLE: + default: + alignment = "[b]"; + break; + } + Geom::Point anchor = textobj->attributes.firstXY() * transform(); + Geom::Point pos(anchor); + + // determine color and transparency (for now, use rgb color model as it is most native to Inkscape) + bool has_color = false; // if the item has no color set, don't force black color + bool has_transparency = false; + // TODO: how to handle ICC colors? + // give priority to fill color + guint32 rgba = 0; + float opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); + if (style->fill.set && style->fill.isColor()) { + has_color = true; + rgba = style->fill.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value); + } else if (style->stroke.set && style->stroke.isColor()) { + has_color = true; + rgba = style->stroke.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); + } + if (opacity < 1.0) { + has_transparency = true; + } + + // get rotation + Geom::Matrix i2doc = sp_item_i2doc_affine(item); + Geom::Matrix wotransl = i2doc.without_translation(); + double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); + bool has_rotation = !Geom::are_near(degrees,0.); + + // write to LaTeX + Inkscape::SVGOStringStream os; + os.setf(std::ios::fixed); // don't use scientific notation + + os << " \\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){"; + if (has_color) { + os << "\\color[rgb]{" << SP_RGBA32_R_F(rgba) << "," << SP_RGBA32_G_F(rgba) << "," << SP_RGBA32_B_F(rgba) << "}"; + } + if (_pdflatex && has_transparency) { + os << "\\transparent{" << opacity << "}"; + } + if (has_rotation) { + os << "\\rotatebox{" << degrees << "}{"; + } + os << "\\makebox(0,0)" << alignment << "{"; + os << "\\smash{" << str << "}"; // smash the text, to be able to put the makebox coordinates at the baseline + if (has_rotation) { + os << "}"; // rotatebox end + } + os << "}"; //makebox end + os << "}%\n"; // put end + + fprintf(_stream, "%s", os.str().c_str()); +} + +void +LaTeXTextRenderer::sp_flowtext_render(SPItem * item) +{ +/* +Flowtext is possible by using a minipage! :) +Flowing in rectangle is possible, not in arb shape. +*/ + + SPFlowtext *flowtext = SP_FLOWTEXT(item); + SPStyle *style = SP_OBJECT_STYLE (SP_OBJECT(item)); + + gchar *strtext = sp_te_get_string_multiline(item); + if (!strtext) { + return; + } + // replace carriage return with double slash + gchar ** splitstr = g_strsplit(strtext, "\n", -1); + gchar *str = g_strjoinv("\\\\ ", splitstr); + g_free(strtext); + g_strfreev(splitstr); + + if (!flowtext->has_internal_frame()) { + // has_internal_frame includes a check that frame is a SPRect + g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text."); + return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think + } + + SPRect *frame = SP_RECT(flowtext->get_frame(NULL)); + Geom::Rect framebox = sp_rect_get_rect(frame) * transform(); + + // get position and alignment + // Align on topleft corner. + gchar const *alignment = "[lt]"; + gchar const *justification = ""; + switch (flowtext->layout.paragraphAlignment(flowtext->layout.begin())) { + case Inkscape::Text::Layout::LEFT: + justification = "\\raggedright"; + break; + case Inkscape::Text::Layout::RIGHT: + justification = "\\raggedleft"; + break; + case Inkscape::Text::Layout::CENTER: + justification = "\\centering"; + case Inkscape::Text::Layout::FULL: + default: + // no need to add LaTeX code for standard justified output :) + break; + } + Geom::Point pos(framebox.corner(3)); //topleft corner + + // determine color and transparency (for now, use rgb color model as it is most native to Inkscape) + bool has_color = false; // if the item has no color set, don't force black color + bool has_transparency = false; + // TODO: how to handle ICC colors? + // give priority to fill color + guint32 rgba = 0; + float opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); + if (style->fill.set && style->fill.isColor()) { + has_color = true; + rgba = style->fill.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value); + } else if (style->stroke.set && style->stroke.isColor()) { + has_color = true; + rgba = style->stroke.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); + } + if (opacity < 1.0) { + has_transparency = true; + } + + // get rotation + Geom::Matrix i2doc = sp_item_i2doc_affine(item); + Geom::Matrix wotransl = i2doc.without_translation(); + double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); + bool has_rotation = !Geom::are_near(degrees,0.); + + // write to LaTeX + Inkscape::SVGOStringStream os; + os.setf(std::ios::fixed); // don't use scientific notation + + os << " \\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){"; + if (has_color) { + os << "\\color[rgb]{" << SP_RGBA32_R_F(rgba) << "," << SP_RGBA32_G_F(rgba) << "," << SP_RGBA32_B_F(rgba) << "}"; + } + if (_pdflatex && has_transparency) { + os << "\\transparent{" << opacity << "}"; + } + if (has_rotation) { + os << "\\rotatebox{" << degrees << "}{"; + } + os << "\\makebox(0,0)" << alignment << "{"; + os << "\\begin{minipage}{" << framebox.width() << "\\unitlength}"; + os << justification; + os << str; + os << "\\end{minipage}"; + if (has_rotation) { + os << "}"; // rotatebox end + } + os << "}"; //makebox end + os << "}%\n"; // put end + + fprintf(_stream, "%s", os.str().c_str()); +} + +void +LaTeXTextRenderer::sp_root_render(SPItem *item) +{ + SPRoot *root = SP_ROOT(item); + + push_transform(root->c2p); + sp_group_render(item); + pop_transform(); +} + +void +LaTeXTextRenderer::sp_item_invoke_render(SPItem *item) +{ + // Check item's visibility + if (item->isHidden()) { + return; + } + + if (SP_IS_ROOT(item)) { + return sp_root_render(item); + } else if (SP_IS_GROUP(item)) { + return sp_group_render(item); + } else if (SP_IS_USE(item)) { + sp_use_render(item); + } else if (SP_IS_TEXT(item)) { + return sp_text_render(item); + } else if (SP_IS_FLOWTEXT(item)) { + return sp_flowtext_render(item); + } + // We are not interested in writing the other SPItem types to LaTeX +} + +void +LaTeXTextRenderer::renderItem(SPItem *item) +{ + push_transform(item->transform); + sp_item_invoke_render(item); + pop_transform(); +} + +bool +LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base) +{ +// The boundingbox calculation here should be exactly the same as the one by CairoRenderer::setupDocument ! + + if (!base) + base = SP_ITEM(sp_document_root(doc)); + + Geom::OptRect d; + if (pageBoundingBox) { + d = Geom::Rect( Geom::Point(0,0), + Geom::Point(sp_document_width(doc), sp_document_height(doc)) ); + } else { + sp_item_invoke_bbox(base, d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX); + } + if (!d) { + g_message("LaTeXTextRenderer: could not retrieve boundingbox."); + return false; + } + + // scale all coordinates, such that the width of the image is 1, this is convenient for scaling the image in LaTeX + double scale = 1/(d->width()); + double _width = d->width() * scale; + double _height = d->height() * scale; + push_transform( Geom::Scale(scale, scale) ); + + if (!pageBoundingBox) + { + push_transform( Geom::Translate( - d->min() ) ); + } + + // flip y-axis + push_transform( Geom::Scale(1,-1) * Geom::Translate(0, sp_document_height(doc)) ); + + // write the info to LaTeX + Inkscape::SVGOStringStream os; + os.setf(std::ios::fixed); // no scientific notation + + // scaling of the image when including it in LaTeX + + os << " \\ifx\\svgwidth\\undefined\n"; + os << " \\setlength{\\unitlength}{" << d->width() * PT_PER_PX << "pt}\n"; + os << " \\else\n"; + os << " \\setlength{\\unitlength}{\\svgwidth}\n"; + os << " \\fi\n"; + os << " \\global\\let\\svgwidth\\undefined\n"; + os << " \\makeatother\n"; + + os << " \\begin{picture}(" << _width << "," << _height << ")%\n"; + // strip pathname, as it is probably desired. Having a specific path in the TeX file is not convenient. + os << " \\put(0,0){\\includegraphics[width=\\unitlength]{" << _filename << "}}%\n"; + + fprintf(_stream, "%s", os.str().c_str()); + + return true; +} + +Geom::Matrix const & +LaTeXTextRenderer::transform() +{ + return _transform_stack.top(); +} + +void +LaTeXTextRenderer::push_transform(Geom::Matrix const &tr) +{ + if(_transform_stack.size()){ + Geom::Matrix tr_top = _transform_stack.top(); + _transform_stack.push(tr * tr_top); + } else { + _transform_stack.push(tr); + } +} + +void +LaTeXTextRenderer::pop_transform() +{ + _transform_stack.pop(); +} + +} /* namespace Internal */ +} /* namespace Extension */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h new file mode 100644 index 000000000..b5d4bfac1 --- /dev/null +++ b/src/extension/internal/latex-text-renderer.h @@ -0,0 +1,85 @@ +#ifndef EXTENSION_INTERNAL_LATEX_TEXT_RENDERER_H_SEEN +#define EXTENSION_INTERNAL_LATEX_TEXT_RENDERER_H_SEEN + +/** \file + * Declaration of LaTeXTextRenderer, used for rendering the accompanying LaTeX file when exporting to PDF/EPS/PS + LaTeX + */ +/* + * Authors: + * Johan Engelen <goejendaagh@zonnet.nl> + * + * Copyright (C) 2010 Authors + * + * Licensed under GNU GPL + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "extension/extension.h" +#include <2geom/matrix.h> +#include <stack> + +class SPItem; + +namespace Inkscape { +namespace Extension { +namespace Internal { + +bool latex_render_document_text_to_file(SPDocument *doc, gchar const *filename, + const gchar * const exportId, bool exportDrawing, bool exportCanvas, + bool pdflatex); + +class LaTeXTextRenderer { +public: + LaTeXTextRenderer(bool pdflatex); + virtual ~LaTeXTextRenderer(); + + bool setTargetFile(gchar const *filename); + + /** Initializes the LaTeXTextRenderer according to the specified + SPDocument. Important to set the boundingbox to the pdf boundingbox */ + bool setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem *base); + + /** Traverses the object tree and invokes the render methods. */ + void renderItem(SPItem *item); + +protected: + FILE * _stream; + gchar * _filename; + + bool _pdflatex; /** true if ouputting for pdfLaTeX*/ + + void push_transform(Geom::Matrix const &transform); + Geom::Matrix const & transform(); + void pop_transform(); + std::stack<Geom::Matrix> _transform_stack; + + void writePreamble(); + void writePostamble(); + + void sp_item_invoke_render(SPItem *item); + void sp_root_render(SPItem *item); + void sp_group_render(SPItem *item); + void sp_use_render(SPItem *item); + void sp_text_render(SPItem *item); + void sp_flowtext_render(SPItem *item); +}; + +} /* namespace Internal */ +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* !EXTENSION_INTERNAL_LATEX_TEXT_RENDERER_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index 46e0361ce..5331c072c 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -1659,9 +1659,9 @@ bool OdfOutput::processGradient(Writer &outs, SPItem *item, GradientInfo gi; - SPGradient *grvec = sp_gradient_get_vector(gradient, FALSE); - for (SPStop *stop = sp_first_stop(grvec) ; - stop ; stop = sp_next_stop(stop)) + SPGradient *grvec = gradient->getVector(FALSE); + for (SPStop *stop = grvec->getFirstStop() ; + stop ; stop = stop->getNextStop()) { unsigned long rgba = sp_stop_get_rgba32(stop); unsigned long rgb = (rgba >> 8) & 0xffffff; diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 118896fd3..b37cbb777 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -809,7 +809,11 @@ void PdfParser::opSetExtGState(Object args[], int numArgs) { blendingColorSpace = NULL; isolated = knockout = gFalse; if (!obj4.dictLookup(const_cast<char*>("CS"), &obj5)->isNull()) { +#ifdef POPPLER_NEW_COLOR_SPACE_API + blendingColorSpace = GfxColorSpace::parse(&obj5, NULL); +#else blendingColorSpace = GfxColorSpace::parse(&obj5); +#endif } obj5.free(); if (obj4.dictLookup(const_cast<char*>("I"), &obj5)->isBool()) { @@ -1008,11 +1012,19 @@ void PdfParser::opSetFillColorSpace(Object args[], int numArgs) { state->setFillPattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); +#ifdef POPPLER_NEW_COLOR_SPACE_API + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0], NULL); + } else { + colorSpace = GfxColorSpace::parse(&obj, NULL); + } +#else if (obj.isNull()) { colorSpace = GfxColorSpace::parse(&args[0]); } else { colorSpace = GfxColorSpace::parse(&obj); } +#endif obj.free(); if (colorSpace) { state->setFillColorSpace(colorSpace); @@ -1031,11 +1043,19 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); +#ifdef POPPLER_NEW_COLOR_SPACE_API + if (obj.isNull()) { + colorSpace = GfxColorSpace::parse(&args[0], NULL); + } else { + colorSpace = GfxColorSpace::parse(&obj, NULL); + } +#else if (obj.isNull()) { colorSpace = GfxColorSpace::parse(&args[0]); } else { colorSpace = GfxColorSpace::parse(&obj); } +#endif obj.free(); if (colorSpace) { state->setStrokeColorSpace(colorSpace); @@ -1100,11 +1120,19 @@ void PdfParser::opSetFillColorN(Object args[], int numArgs) { state->setFillColor(&color); builder->updateStyle(state); } +#ifdef POPPLER_NEW_COLOR_SPACE_API + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) { + state->setFillPattern(pattern); + builder->updateStyle(state); + } +#else if (args[numArgs-1].isName() && (pattern = res->lookupPattern(args[numArgs-1].getName()))) { state->setFillPattern(pattern); builder->updateStyle(state); } +#endif } else { if (numArgs != state->getFillColorSpace()->getNComps()) { @@ -1144,11 +1172,19 @@ void PdfParser::opSetStrokeColorN(Object args[], int numArgs) { state->setStrokeColor(&color); builder->updateStyle(state); } +#ifdef POPPLER_NEW_COLOR_SPACE_API + if (args[numArgs-1].isName() && + (pattern = res->lookupPattern(args[numArgs-1].getName(), NULL))) { + state->setStrokePattern(pattern); + builder->updateStyle(state); + } +#else if (args[numArgs-1].isName() && (pattern = res->lookupPattern(args[numArgs-1].getName()))) { state->setStrokePattern(pattern); builder->updateStyle(state); } +#endif } else { if (numArgs != state->getStrokeColorSpace()->getNComps()) { @@ -1543,9 +1579,15 @@ void PdfParser::opShFill(Object args[], int numArgs) { double *matrix = NULL; GBool savedState = gFalse; +#ifdef POPPLER_NEW_COLOR_SPACE_API + if (!(shading = res->lookupShading(args[0].getName(), NULL))) { + return; + } +#else if (!(shading = res->lookupShading(args[0].getName()))) { return; } +#endif // save current graphics state if (shading->getType() != 2 && shading->getType() != 3) { @@ -2507,7 +2549,11 @@ void PdfParser::doImage(Object *ref, Stream *str, GBool inlineImg) { } } if (!obj1.isNull()) { +#ifdef POPPLER_NEW_COLOR_SPACE_API + colorSpace = GfxColorSpace::parse(&obj1, NULL); +#else colorSpace = GfxColorSpace::parse(&obj1); +#endif } else if (csMode == streamCSDeviceGray) { colorSpace = new GfxDeviceGrayColorSpace(); } else if (csMode == streamCSDeviceRGB) { @@ -2592,7 +2638,11 @@ void PdfParser::doImage(Object *ref, Stream *str, GBool inlineImg) { obj2.free(); } } +#ifdef POPPLER_NEW_COLOR_SPACE_API + maskColorSpace = GfxColorSpace::parse(&obj1, NULL); +#else maskColorSpace = GfxColorSpace::parse(&obj1); +#endif obj1.free(); if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; @@ -2767,7 +2817,11 @@ void PdfParser::doForm(Object *str) { if (obj1.dictLookup(const_cast<char*>("S"), &obj2)->isName(const_cast<char*>("Transparency"))) { transpGroup = gTrue; if (!obj1.dictLookup(const_cast<char*>("CS"), &obj3)->isNull()) { +#ifdef POPPLER_NEW_COLOR_SPACE_API + blendingColorSpace = GfxColorSpace::parse(&obj3, NULL); +#else blendingColorSpace = GfxColorSpace::parse(&obj3); +#endif } obj3.free(); if (obj1.dictLookup(const_cast<char*>("I"), &obj3)->isBool()) { diff --git a/src/extension/internal/pov-out.cpp b/src/extension/internal/pov-out.cpp index 1cb14fb58..16877c370 100644 --- a/src/extension/internal/pov-out.cpp +++ b/src/extension/internal/pov-out.cpp @@ -312,12 +312,12 @@ bool PovOutput::doCurve(SPItem *item, const String &id) int segmentCount = 0; /** * For all Subpaths in the <path> - */ + */ for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) { /** * For all segments in the subpath, including extra closing segment defined by 2geom - */ + */ for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit) { @@ -340,14 +340,14 @@ bool PovOutput::doCurve(SPItem *item, const String &id) nrSegments += segmentCount; /** - * at moment of writing, 2geom lacks proper initialization of empty intervals in rect... - */ - Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() ); - - + * at moment of writing, 2geom lacks proper initialization of empty intervals in rect... + */ + Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() ); + + /** * For all Subpaths in the <path> - */ + */ for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) { @@ -355,7 +355,7 @@ bool PovOutput::doCurve(SPItem *item, const String &id) /** * For all segments in the subpath, including extra closing segment defined by 2geom - */ + */ for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit) { @@ -372,7 +372,7 @@ bool PovOutput::doCurve(SPItem *item, const String &id) nrNodes += 8; } else if(Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit)) - { + { std::vector<Geom::Point> points = cubic->points(); Geom::Point p0 = points[0]; Geom::Point p1 = points[1]; @@ -383,7 +383,7 @@ bool PovOutput::doCurve(SPItem *item, const String &id) nrNodes += 8; } else - { + { err("logical error, because pathv_to_linear_and_cubic_beziers was used"); return false; } @@ -444,7 +444,7 @@ bool PovOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) { String id; - if (!obj->id) + if (!obj->getId()) { char buf[16]; sprintf(buf, "id%d", idIndex++); @@ -452,7 +452,7 @@ bool PovOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) } else { - id = obj->id; + id = obj->getId(); } if (SP_IS_ITEM(obj)) @@ -467,9 +467,9 @@ bool PovOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) */ for (SPObject *child = obj->firstChild() ; child ; child = child->next) { - if (!doTreeRecursive(doc, child)) - return false; - } + if (!doTreeRecursive(doc, child)) + return false; + } return true; } @@ -610,7 +610,7 @@ void PovOutput::saveDocument(SPDocument *doc, gchar const *filename_utf8) err("Could not output curves for %s", filename_utf8); return; } - + String curveBuf = outbuf; outbuf.clear(); diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index a3589e905..b10aa87ec 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -21,6 +21,7 @@ #include "extension/system.h" #include "extension/output.h" #include <vector> +#include "xml/attribute-record.h" #ifdef WITH_GNOME_VFS # include <libgnomevfs/gnome-vfs.h> @@ -32,6 +33,37 @@ namespace Internal { #include "clear-n_.h" + +using Inkscape::Util::List; +using Inkscape::XML::AttributeRecord; +using Inkscape::XML::Node; + + + +void pruneExtendedAttributes( Inkscape::XML::Node *repr ) +{ + if (repr) { + if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) { + std::vector<gchar const*> toBeRemoved; + for ( List<AttributeRecord const> it = repr->attributeList(); it; ++it ) { + const gchar* attrName = g_quark_to_string(it->key); + if ((strncmp("inkscape:", attrName, 9) == 0) || (strncmp("sodipodi:", attrName, 9) == 0)) { + toBeRemoved.push_back(attrName); + } + } + // Can't change the set we're interating over while we are iterating. + for ( std::vector<gchar const*>::iterator it = toBeRemoved.begin(); it != toBeRemoved.end(); ++it ) { + repr->setAttribute(*it, 0); + } + } + + for ( Node *child = repr->firstChild(); child; child = child->next() ) { + pruneExtendedAttributes(child); + } + } +} + + /** \return None \brief What would an SVG editor be without loading/saving SVG @@ -179,7 +211,7 @@ Svg::open (Inkscape::Extension::Input */*mod*/, const gchar *uri) we're getting good data. It also checks the module ID of the incoming module to figure out whether this save should include the Inkscape namespace stuff or not. The result of that comparison - is stored in the spns variable. + is stored in the exportExtensions variable. If there is not to be Inkscape name spaces a new document is created without. (I think, I'm not sure on this code) @@ -198,18 +230,20 @@ Svg::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena gchar *save_path = g_path_get_dirname(filename); - bool const spns = ( !mod->get_id() + bool const exportExtensions = ( !mod->get_id() || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE) || !strcmp (mod->get_id(), SP_MODULE_KEY_OUTPUT_SVGZ_INKSCAPE)); Inkscape::XML::Document *rdoc = NULL; Inkscape::XML::Node *repr = NULL; - if (spns) { + if (exportExtensions) { repr = sp_document_repr_root (doc); } else { rdoc = sp_repr_document_new ("svg:svg"); repr = rdoc->root(); repr = sp_document_root (doc)->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD); + + pruneExtendedAttributes(repr); } if (!sp_repr_save_rebased_file(repr->document(), filename, SP_SVG_NS_URI, @@ -217,7 +251,7 @@ Svg::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filena throw Inkscape::Extension::Output::save_failed(); } - if (!spns) { + if (!exportExtensions) { Inkscape::GC::release(rdoc); } diff --git a/src/extension/param/parameter.cpp b/src/extension/param/parameter.cpp index 2773af61d..3320cddca 100644 --- a/src/extension/param/parameter.cpp +++ b/src/extension/param/parameter.cpp @@ -204,6 +204,16 @@ Parameter::get_enum (const SPDocument * doc, const Inkscape::XML::Node * node) return param->get(doc, node); } +/** \brief Wrapper to cast to the object and use it's function. */ +gchar const *Parameter::get_optiongroup(SPDocument const * doc, Inkscape::XML::Node const * node) +{ + ParamRadioButton * param = dynamic_cast<ParamRadioButton *>(this); + if (!param) { + throw Extension::param_not_optiongroup_param(); + } + return param->get(doc, node); +} + guint32 Parameter::get_color(const SPDocument* doc, const Inkscape::XML::Node* node) { @@ -253,6 +263,17 @@ Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * throw Extension::param_not_string_param(); return stringpntr->set(in, doc, node); } + +gchar const * Parameter::set_optiongroup( gchar const * in, SPDocument * doc, Inkscape::XML::Node * node ) +{ + ParamRadioButton *param = dynamic_cast<ParamRadioButton *>(this); + if (!param) { + throw Extension::param_not_optiongroup_param(); + } + return param->set(in, doc, node); +} + + /** \brief Wrapper to cast to the object and use it's function. */ guint32 Parameter::set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node) diff --git a/src/extension/param/parameter.h b/src/extension/param/parameter.h index 54249c12e..c62dad9cc 100644 --- a/src/extension/param/parameter.h +++ b/src/extension/param/parameter.h @@ -98,9 +98,13 @@ public: const gchar * get_enum (const SPDocument * doc, const Inkscape::XML::Node * node); + gchar const * get_optiongroup( SPDocument const * doc, + Inkscape::XML::Node const * node); + bool set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node); int set_int (int in, SPDocument * doc, Inkscape::XML::Node * node); float set_float (float in, SPDocument * doc, Inkscape::XML::Node * node); + gchar const * set_optiongroup(gchar const *in, SPDocument * doc, Inkscape::XML::Node *node); const gchar * set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); guint32 set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node); |
