summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiam P. White <inkscapebrony@gmail.com>2014-06-19 00:29:52 +0000
committerLiam P. White <inkscapebrony@gmail.com>2014-06-19 00:29:52 +0000
commitfd8dc80e78f402e37d9c4ef29094e69d90653ea6 (patch)
treea858ce047096b8ddb581d76805760e773a251a5f /src
parentRemoved original path helper paths pointed by LiamW (diff)
parentadd win64 files to distribution (Makefile.am) (diff)
downloadinkscape-fd8dc80e78f402e37d9c4ef29094e69d90653ea6.tar.gz
inkscape-fd8dc80e78f402e37d9c4ef29094e69d90653ea6.zip
Update to latest tip (trunk r13432)
(bzr r13341.1.62)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/crossing.cpp20
-rw-r--r--src/2geom/crossing.h1
-rw-r--r--src/2geom/path-intersection.cpp33
-rw-r--r--src/Makefile.am4
-rw-r--r--src/display/snap-indicator.cpp6
-rw-r--r--src/document.cpp111
-rw-r--r--src/extension/CMakeLists.txt2
-rw-r--r--src/extension/dependency.cpp20
-rw-r--r--src/extension/extension.cpp3
-rw-r--r--src/extension/init.cpp8
-rw-r--r--src/extension/internal/Makefile_insert2
-rw-r--r--src/extension/internal/cairo-ps-out.cpp2
-rw-r--r--src/extension/internal/cairo-ps-out.h2
-rw-r--r--src/extension/internal/pdf-input-cairo.cpp680
-rw-r--r--src/extension/internal/pdf-input-cairo.h157
-rw-r--r--src/extension/internal/pdfinput/pdf-input.cpp233
-rw-r--r--src/extension/internal/pdfinput/pdf-input.h4
-rw-r--r--src/extension/param/notebook.cpp2
-rw-r--r--src/extension/prefdialog.cpp3
-rw-r--r--src/id-clash.cpp126
-rw-r--r--src/inkscape.cpp5
-rw-r--r--src/inkscape.rc2
-rw-r--r--src/inkview.rc2
-rw-r--r--src/knot-holder-entity.cpp16
-rw-r--r--src/libdepixelize/kopftracer2011.cpp4
-rw-r--r--src/live_effects/lpe-knot.cpp24
-rw-r--r--src/live_effects/lpe-knot.h1
-rw-r--r--src/main.cpp1
-rw-r--r--src/selection-describer.cpp24
-rw-r--r--src/seltrans.cpp63
-rw-r--r--src/snap.cpp10
-rw-r--r--src/sp-gradient.cpp77
-rw-r--r--src/sp-lpe-item.cpp28
-rw-r--r--src/sp-lpe-item.h11
-rw-r--r--src/ui/dialog/aboutbox.cpp2
-rw-r--r--src/ui/dialog/grid-arrange-tab.cpp2
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp2
-rw-r--r--src/ui/tools/measure-tool.cpp59
-rw-r--r--src/ui/tools/pen-tool.cpp2
-rw-r--r--src/widgets/toolbox.cpp2
-rw-r--r--src/xml/helper-observer.cpp13
-rw-r--r--src/xml/helper-observer.h1
42 files changed, 628 insertions, 1142 deletions
diff --git a/src/2geom/crossing.cpp b/src/2geom/crossing.cpp
index 13affa8e9..513327271 100644
--- a/src/2geom/crossing.cpp
+++ b/src/2geom/crossing.cpp
@@ -154,7 +154,6 @@ Crossings reverse_tb(Crossings const &cr, unsigned split, std::vector<double> ma
Crossings ret;
for(Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) {
double mx = max[i->b - split];
- std::cout << i->b << "\n";
ret.push_back(Crossing(i->ta, i->tb > mx+0.01 ? (1 - (i->tb - mx) + mx) : mx - i->tb,
!i->dir));
}
@@ -181,6 +180,25 @@ CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double
return ret;
}
+// Delete any duplicates in a vector of crossings
+// A crossing is considered to be a duplicate when it has both t_a and t_b near to another crossing's t_a and t_b
+// For example, duplicates will be found when calculating the intersections of a linesegment with a polygon, if the
+// endpoint of that line coincides with a cusp node of the polygon. In that case, an intersection will be found of
+// the linesegment with each of the polygon's linesegments extending from the cusp node (i.e. two intersections)
+void delete_duplicates(Crossings &crs) {
+ Crossings::reverse_iterator rit = crs.rbegin();
+
+ for (rit = crs.rbegin(); rit!= crs.rend(); ++rit) {
+ Crossings::reverse_iterator rit2 = rit;
+ while (++rit2 != crs.rend()) {
+ if (Geom::are_near((*rit).ta, (*rit2).ta) && Geom::are_near((*rit).tb, (*rit2).tb)) {
+ crs.erase((rit + 1).base()); // This +1 and .base() construction is needed to convert to a regular iterator
+ break; // out of while loop, and continue with next iteration of for loop
+ }
+ }
+ }
+}
+
void clean(Crossings &/*cr_a*/, Crossings &/*cr_b*/) {
/* if(cr_a.empty()) return;
diff --git a/src/2geom/crossing.h b/src/2geom/crossing.h
index 75c75fc24..d5012ae2b 100644
--- a/src/2geom/crossing.h
+++ b/src/2geom/crossing.h
@@ -183,6 +183,7 @@ CrossingSet reverse_ta(CrossingSet const &cr, unsigned split, std::vector<double
CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double> max);
void clean(Crossings &cr_a, Crossings &cr_b);
+void delete_duplicates(Crossings &crs);
}
diff --git a/src/2geom/path-intersection.cpp b/src/2geom/path-intersection.cpp
index ff24b92eb..63a29423d 100644
--- a/src/2geom/path-intersection.cpp
+++ b/src/2geom/path-intersection.cpp
@@ -164,20 +164,35 @@ void append(T &a, T const &b) {
bool
linear_intersect(Point A0, Point A1, Point B0, Point B1,
double &tA, double &tB, double &det) {
- // kramers rule as cross products
+ bool both_lines_non_zero = (!are_near(A0, A1)) && (!are_near(B0, B1));
+
+ // Cramer's rule as cross products
Point Ad = A1 - A0,
Bd = B1 - B0,
d = B0 - A0;
det = cross(Ad, Bd);
- if( 1.0 + det == 1.0 )
- return false;
- else
- {
- double detinv = 1.0 / det;
- tA = cross(d, Bd) * detinv;
- tB = cross(d, Ad) * detinv;
- return tA >= 0. && tA <= 1. && tB >= 0. && tB <= 1.;
+
+ double det_rel = det; // Calculate the determinant of the normalized vectors
+ if (both_lines_non_zero) {
+ det_rel /= Ad.length();
+ det_rel /= Bd.length();
}
+
+ if( fabs(det_rel) < 1e-12 ) { // If the cross product is NEARLY zero,
+ // Then one of the linesegments might have length zero
+ if (both_lines_non_zero) {
+ // If that's not the case, then we must have either:
+ // - parallel lines, with no intersections, or
+ // - coincident lines, with an infinite number of intersections
+ // Either is quite useless, so we'll just bail out
+ return false;
+ } // Else, one of the linesegments is zero, and we might still be able to calculate a single intersection point
+ } // Else we haven't bailed out, and we'll try to calculate the intersections
+
+ double detinv = 1.0 / det;
+ tA = cross(d, Bd) * detinv;
+ tB = cross(d, Ad) * detinv;
+ return (tA >= 0.) && (tA <= 1.) && (tB >= 0.) && (tB <= 1.);
}
diff --git a/src/Makefile.am b/src/Makefile.am
index d5439f0ea..bb34047a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,8 @@ BUILT_SOURCES =
EXTRA_DIST =
AM_CPPFLAGS = \
+ -I$(top_srcdir)/cxxtest \
+ -I$(builddir)/extension/dbus \
$(EXIF_CFLAGS) \
$(FREETYPE_CFLAGS) \
$(GNOME_PRINT_CFLAGS) \
@@ -80,9 +82,7 @@ AM_CPPFLAGS = \
$(POPPLER_GLIB_CFLAGS) \
-DPOTRACE=\"potrace\" \
$(INKSCAPE_CFLAGS) \
- -I$(top_srcdir)/cxxtest \
$(WIN32_CFLAGS) \
- -I$(builddir)/extension/dbus \
$(X11_CFLAGS)
CXXTEST_TEMPLATE = $(srcdir)/cxxtest-template.tpl
diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp
index 627bfb2ab..3a8358174 100644
--- a/src/display/snap-indicator.cpp
+++ b/src/display/snap-indicator.cpp
@@ -73,6 +73,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
switch (p.getTarget()) {
case SNAPTARGET_UNDEFINED:
target_name = _("UNDEFINED");
+ g_warning("Snap target has not been specified");
break;
case SNAPTARGET_GRID:
target_name = _("grid line");
@@ -172,7 +173,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
target_name = _("constraint");
break;
default:
- g_warning("Snap target has not yet been defined!");
+ g_warning("Snap target not in SnapTargetType enum");
break;
}
@@ -180,6 +181,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
switch (p.getSource()) {
case SNAPSOURCE_UNDEFINED:
source_name = _("UNDEFINED");
+ g_warning("Snap source has not been specified");
break;
case SNAPSOURCE_BBOX_CORNER:
source_name = _("Bounding box corner");
@@ -235,7 +237,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap
source_name = _("Multiple of grid spacing");
break;
default:
- g_warning("Snap source has not yet been defined!");
+ g_warning("Snap source not in SnapSourceType enum");
break;
}
//std::cout << "Snapped " << source_name << " to " << target_name << std::endl;
diff --git a/src/document.cpp b/src/document.cpp
index dc7ed254c..f79a00178 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -1529,7 +1529,7 @@ void SPDocument::setModifiedSinceSave(bool modified) {
/**
- * Paste SVG defs from the document retrieved from the clipboard into the active document.
+ * Paste SVG defs from the document retrieved from the clipboard or imported document into the active document.
* @param clipdoc The document to paste.
* @pre @c clipdoc != NULL and pasting into the active document is possible.
*/
@@ -1540,27 +1540,117 @@ void SPDocument::importDefs(SPDocument *source)
Inkscape::XML::Node *target_defs = this->getDefs()->getRepr();
prevent_id_clashes(source, this);
+
+ int stagger=0;
+ /* Note, "clipboard" throughout the comments means "the document that is either the clipboard
+ or an imported document", as importDefs is called in both contexts.
+
+ The order of the records in the clipboard is unpredictable and there may be both
+ forward and backwards references to other records within it. There may be definitions in
+ the clipboard that duplicate definitions in the present document OR that duplicate other
+ definitions in the clipboard. (Inkscape will not have created these, but they may be read
+ in from other SVG sources.)
+
+ There are 3 passes to clean this up:
+
+ In the first find and mark definitions in the clipboard that are duplicates of those in the
+ present document. Change the ID to "RESERVED_FOR_INKSCAPE_DUPLICATE_DEF_XXXXXXXXX".
+ (Inkscape will not reuse an ID, and the XXXXXXXXX keeps it from automatically creating new ones.)
+ References in the clipboard to the old clipboard name are converted to the name used
+ in the current document.
+
+ In the second find and mark definitions in the clipboard that are duplicates of earlier
+ definitions in the clipbard. Unfortunately this is O(n^2) and could be very slow for a large
+ SVG with thousands of definitions. As before, references are adjusted to reflect the name
+ going forward.
+
+ In the final cycle copy over those records not marked with that ID.
+
+ If an SVG file uses the special ID it will cause problems!
+
+ If this function is called because of the paste of a true clipboard the caller will have passed in a
+ COPY of the clipboard items. That is good, because this routine modifies that document. If the calling
+ behavior ever changes, so that the same document is passed in on multiple pastes, this routine will break
+ as in the following example:
+ 1. Paste clipboard containing B same as A into document containing A. Result, B is dropped
+ and all references to it will point to A.
+ 2. Paste same clipboard into a new document. It will not contain A, so there will be unsatisfied
+ references in that window.
+ */
+
+ std::string DuplicateDefString = "RESERVED_FOR_INKSCAPE_DUPLICATE_DEF";
+
+ /* First pass: remove duplicates in clipboard of definitions in document */
for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
- gboolean duplicate = false;
+ /* If this clipboard has been pasted into one document, and is now being pasted into another,
+ or pasted again into the same, it will already have been processed. If we detect that then
+ skip the rest of this pass. */
+
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )break;
+
SPObject *src = source->getObjectByRepr(def);
// Prevent duplicates of solid swatches by checking if equivalent swatch already exists
if (src && SP_IS_GRADIENT(src)) {
- SPGradient *gr = SP_GRADIENT(src);
+ SPGradient *s_gr = SP_GRADIENT(src);
for (SPObject *trg = this->getDefs()->firstChild() ; trg ; trg = trg->getNext()) {
- if (trg && SP_IS_GRADIENT(trg) && src != trg) {
- if (gr->isEquivalent(SP_GRADIENT(trg)) &&
- gr->isAligned(SP_GRADIENT(trg))) {
- // Change object references to the existing equivalent gradient
- change_def_references(src, trg);
- duplicate = true;
- break;
+ if (trg && (src != trg) && SP_IS_GRADIENT(trg)) {
+ SPGradient *t_gr = SP_GRADIENT(trg);
+ if (t_gr && s_gr->isEquivalent(t_gr)) {
+ // Change object references to the existing equivalent gradient
+ Glib::ustring newid = trg->getId();
+ if(newid != defid){ // id could be the same if it is a second paste into the same document
+ change_def_references(src, trg);
+ }
+ gchar *longid = g_strdup_printf("%s_%9.9d", DuplicateDefString.c_str(), stagger++);
+ def->setAttribute("id", longid );
+ g_free(longid);
+ // do NOT break here, there could be more than 1 duplicate!
}
}
}
}
+ }
+
+ /* Second pass: remove duplicates in clipboard of earlier definitions in clipboard */
+ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )continue; // this one already handled
+ SPObject *src = source->getObjectByRepr(def);
+ if (src && SP_IS_GRADIENT(src)) {
+ SPGradient *s_gr = SP_GRADIENT(src);
+ for (Inkscape::XML::Node *laterDef = def->next() ; laterDef ; laterDef = laterDef->next()) {
+ SPObject *trg = source->getObjectByRepr(laterDef);
+ if(trg && (src != trg) && SP_IS_GRADIENT(trg)) {
+ Glib::ustring newid = trg->getId();
+ if( newid.find( DuplicateDefString ) != Glib::ustring::npos )continue; // this one already handled
+ SPGradient *t_gr = SP_GRADIENT(trg);
+ if (t_gr && s_gr->isEquivalent(t_gr)) {
+ // Change object references to the existing equivalent gradient
+ // two id's in the clipboard should never be the same, so always change references
+ change_def_references(trg, src);
+ gchar *longid = g_strdup_printf("%s_%9.9d", DuplicateDefString.c_str(), stagger++);
+ laterDef->setAttribute("id", longid );
+ g_free(longid);
+ // do NOT break here, there could be more than 1 duplicate!
+ }
+ }
+ }
+ }
+ }
+
+ /* Final pass: copy over those parts which are not duplicates */
+ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
+
+ /* Ignore duplicate defs marked in the first pass */
+ Glib::ustring defid = def->attribute("id");
+ if( defid.find( DuplicateDefString ) != Glib::ustring::npos )continue;
+
+ bool duplicate = false;
+ SPObject *src = source->getObjectByRepr(def);
// Prevent duplication of symbols... could be more clever.
// The tag "_inkscape_duplicate" is added to "id" by ClipboardManagerImpl::copySymbol().
@@ -1597,7 +1687,6 @@ void SPDocument::importDefs(SPDocument *source)
Inkscape::GC::release(dup);
}
}
-
}
/*
diff --git a/src/extension/CMakeLists.txt b/src/extension/CMakeLists.txt
index 759c704f0..47292fd97 100644
--- a/src/extension/CMakeLists.txt
+++ b/src/extension/CMakeLists.txt
@@ -49,7 +49,6 @@ set(extension_SRC
internal/metafile-print.cpp
internal/odf.cpp
internal/latex-text-renderer.cpp
- internal/pdf-input-cairo.cpp
internal/pov-out.cpp
internal/javafx-out.cpp
internal/svg.cpp
@@ -133,7 +132,6 @@ set(extension_SRC
internal/metafile-inout.h
internal/metafile-print.h
internal/odf.h
- internal/pdf-input-cairo.h
internal/pdfinput/pdf-input.h
internal/pdfinput/pdf-parser.h
internal/pdfinput/svg-builder.h
diff --git a/src/extension/dependency.cpp b/src/extension/dependency.cpp
index 78012ccc8..e46b6fbd2 100644
--- a/src/extension/dependency.cpp
+++ b/src/extension/dependency.cpp
@@ -57,14 +57,22 @@ Dependency::Dependency (Inkscape::XML::Node * in_repr)
Inkscape::GC::anchor(_repr);
- const gchar * location = _repr->attribute("location");
- for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
- if (!strcmp(location, _location_str[i])) {
- _location = (location_t)i;
- break;
+ if (const gchar * location = _repr->attribute("location")) {
+ for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
+ if (!strcmp(location, _location_str[i])) {
+ _location = (location_t)i;
+ break;
+ }
+ }
+ } else if (const gchar * location = _repr->attribute("reldir")) {
+ for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
+ if (!strcmp(location, _location_str[i])) {
+ _location = (location_t)i;
+ break;
+ }
}
}
-
+
const gchar * type = _repr->attribute("type");
for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
if (!strcmp(type, _type_str[i])) {
diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp
index 588efb521..06e35ff3e 100644
--- a/src/extension/extension.cpp
+++ b/src/extension/extension.cpp
@@ -111,6 +111,9 @@ Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementat
if (!strcmp(chname, "dependency")) {
_deps.push_back(new Dependency(child_repr));
} /* dependency */
+ if (!strcmp(chname, "script")) {
+ _deps.push_back(new Dependency(child_repr->firstChild()));
+ } /* check command as a dependency (see LP #505920) */
if (!strcmp(chname, "options")) {
silent = !strcmp( child_repr->attribute("silent"), "true" );
}
diff --git a/src/extension/init.cpp b/src/extension/init.cpp
index 0ff4b79c4..912d58a13 100644
--- a/src/extension/init.cpp
+++ b/src/extension/init.cpp
@@ -19,9 +19,6 @@
#ifdef HAVE_POPPLER
# include "internal/pdfinput/pdf-input.h"
#endif
-#ifdef HAVE_POPPLER_GLIB
-# include "internal/pdf-input-cairo.h"
-#endif
#include "path-prefix.h"
@@ -174,11 +171,6 @@ init()
#ifdef HAVE_POPPLER
Internal::PdfInput::init();
#endif
-#ifdef HAVE_POPPLER_GLIB
- if (1) {
- Internal::PdfInputCairo::init();
- }
-#endif
Internal::PrintEmf::init();
Internal::Emf::init();
Internal::PrintWmf::init();
diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert
index a31843114..125776d41 100644
--- a/src/extension/internal/Makefile_insert
+++ b/src/extension/internal/Makefile_insert
@@ -106,8 +106,6 @@ ink_common_sources += \
extension/internal/svg.cpp \
extension/internal/svgz.h \
extension/internal/svgz.cpp \
- extension/internal/pdf-input-cairo.cpp \
- extension/internal/pdf-input-cairo.h \
extension/internal/cairo-ps-out.h \
extension/internal/cairo-ps-out.cpp \
extension/internal/cairo-render-context.h \
diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp
index 055a30add..4defc2ab9 100644
--- a/src/extension/internal/cairo-ps-out.cpp
+++ b/src/extension/internal/cairo-ps-out.cpp
@@ -5,7 +5,7 @@
* Authors:
* Ted Gould <ted@gould.cx>
* Ulf Erikson <ulferikson@users.sf.net>
- * Adib Taraben <theAdib@yahoo.com>
+ * Adib Taraben <theAdib@gmail.com>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
diff --git a/src/extension/internal/cairo-ps-out.h b/src/extension/internal/cairo-ps-out.h
index 7eda3c510..b438b55b4 100644
--- a/src/extension/internal/cairo-ps-out.h
+++ b/src/extension/internal/cairo-ps-out.h
@@ -5,7 +5,7 @@
* Authors:
* Ted Gould <ted@gould.cx>
* Ulf Erikson <ulferikson@users.sf.net>
- * Adib Taraben <theAdib@yahoo.com>
+ * Adib Taraben <theAdib@gmail.com>
* Abhishek Sharma
*
* Copyright (C) 2004-2006 Authors
diff --git a/src/extension/internal/pdf-input-cairo.cpp b/src/extension/internal/pdf-input-cairo.cpp
deleted file mode 100644
index 9ce73c260..000000000
--- a/src/extension/internal/pdf-input-cairo.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
- /*
- * Simple PDF import extension using libpoppler and Cairo's SVG surface.
- *
- * Authors:
- * miklos erdelyi
- * Abhishek Sharma
- *
- * Copyright (C) 2007 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef HAVE_POPPLER_GLIB
-#ifdef HAVE_POPPLER_CAIRO
-
-#include "pdf-input-cairo.h"
-#include "extension/system.h"
-#include "extension/input.h"
-#include "dialogs/dialog-events.h"
-#include "document.h"
-#include "sp-root.h"
-#include "util/units.h"
-
-#include <2geom/rect.h>
-
-#include "inkscape.h"
-
-#include <cairo-svg.h>
-#include <poppler/glib/poppler.h>
-#include <poppler/glib/poppler-document.h>
-#include <poppler/glib/poppler-page.h>
-
-#include "ui/widget/spinbutton.h"
-#include "ui/widget/frame.h"
-
-#include <gdkmm/general.h>
-
-namespace Inkscape {
-namespace Extension {
-namespace Internal {
-
-
-/**
- * \brief The PDF import dialog
- * FIXME: Probably this should be placed into src/ui/dialog
- */
-
-static const gchar * crop_setting_choices[] = {
- //TRANSLATORS: The following are document crop settings for PDF import
- // more info: http://www.acrobatusers.com/tech_corners/javascript_corner/tips/2006/page_bounds/
- N_("media box"),
- N_("crop box"),
- N_("trim box"),
- N_("bleed box"),
- N_("art box")
-};
-
-PdfImportCairoDialog::PdfImportCairoDialog(PopplerDocument *doc)
-{
- if(doc == NULL) {
- // if there is no document, throw exception here
- throw;
- }
-
- _poppler_doc = doc;
-
- cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel")));
- okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok")));
- _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:")));
-
- // Page number
- int num_pages = poppler_document_get_n_pages(_poppler_doc);
-#if WITH_GTKMM_3_0
- Glib::RefPtr<Gtk::Adjustment> _pageNumberSpin_adj( Gtk::Adjustment::create(1, 1, num_pages, 1, 10, 0) );
- _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(_pageNumberSpin_adj, 1, 1));
-#else
- Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage(new class Gtk::Adjustment(1, 1, num_pages, 1, 10, 0));
- _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(*_pageNumberSpin_adj, 1, 1));
-#endif
- _labelTotalPages = Gtk::manage(new class Gtk::Label());
- hbox2 = Gtk::manage(new class Gtk::HBox(false, 0));
- // Disable the page selector when there's only one page
- if ( num_pages == 1 ) {
- _pageNumberSpin->set_sensitive(false);
- } else {
- // Display total number of pages
- gchar *label_text = g_strdup_printf(_("out of %i"), num_pages);
- _labelTotalPages->set_label(label_text);
- g_free(label_text);
- }
-
- // Crop settings
- _cropCheck = Gtk::manage(new class Gtk::CheckButton(_("Clip to:")));
- _cropTypeCombo = Gtk::manage(new class Gtk::ComboBoxText());
- int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
- for ( int i = 0 ; i < num_crop_choices ; i++ ) {
- _cropTypeCombo->append(_(crop_setting_choices[i]));
- }
- _cropTypeCombo->set_active_text(_(crop_setting_choices[0]));
- _cropTypeCombo->set_sensitive(false);
-
- hbox3 = Gtk::manage(new class Gtk::HBox(false, 4));
- vbox2 = Gtk::manage(new class Gtk::VBox(false, 4));
- _pageSettingsFrame = Gtk::manage(new class Inkscape::UI::Widget::Frame(_("Page settings")));
- _labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximating gradient meshes:")));
- _labelPrecisionWarning = Gtk::manage(new class Gtk::Label(_("<b>Note</b>: setting the precision too high may result in a large SVG file and slow performance.")));
-
-#if WITH_GTKMM_3_0
- _fallbackPrecisionSlider_adj = Gtk::Adjustment::create(2, 1, 256, 1, 10, 10);
- _fallbackPrecisionSlider = Gtk::manage(new Gtk::Scale(_fallbackPrecisionSlider_adj));
-#else
- _fallbackPrecisionSlider_adj = Gtk::manage(new class Gtk::Adjustment(2, 1, 256, 1, 10, 10));
- _fallbackPrecisionSlider = Gtk::manage(new class Gtk::HScale(*_fallbackPrecisionSlider_adj));
-#endif
- _fallbackPrecisionSlider->set_value(2.0);
- _labelPrecisionComment = Gtk::manage(new class Gtk::Label(_("rough")));
- hbox6 = Gtk::manage(new class Gtk::HBox(false, 4));
-
- // Text options
- _labelText = Gtk::manage(new class Gtk::Label(_("Text handling:")));
- _textHandlingCombo = Gtk::manage(new class Gtk::ComboBoxText());
- _textHandlingCombo->append(_("Import text as text"));
- _textHandlingCombo->set_active_text(_("Import text as text"));
- _localFontsCheck = Gtk::manage(new class Gtk::CheckButton(_("Replace PDF fonts by closest-named installed fonts")));
-
- hbox5 = Gtk::manage(new class Gtk::HBox(false, 4));
- _embedImagesCheck = Gtk::manage(new class Gtk::CheckButton(_("Embed images")));
- vbox3 = Gtk::manage(new class Gtk::VBox(false, 4));
- _importSettingsFrame = Gtk::manage(new class Inkscape::UI::Widget::Frame(_("Import settings")));
- vbox1 = Gtk::manage(new class Gtk::VBox(false, 4));
- _previewArea = Gtk::manage(new class Gtk::DrawingArea());
- hbox1 = Gtk::manage(new class Gtk::HBox(false, 4));
- cancelbutton->set_can_focus();
- cancelbutton->set_can_default();
- cancelbutton->set_relief(Gtk::RELIEF_NORMAL);
- okbutton->set_can_focus();
- okbutton->set_can_default();
- okbutton->set_relief(Gtk::RELIEF_NORMAL);
- this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END);
- _labelSelect->set_alignment(0.5,0.5);
- _labelSelect->set_padding(4,0);
- _labelSelect->set_justify(Gtk::JUSTIFY_LEFT);
- _labelSelect->set_line_wrap(false);
- _labelSelect->set_use_markup(false);
- _labelSelect->set_selectable(false);
- _pageNumberSpin->set_can_focus();
- _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS);
- _pageNumberSpin->set_numeric(true);
- _pageNumberSpin->set_digits(0);
- _pageNumberSpin->set_wrap(false);
- _labelTotalPages->set_alignment(0.5,0.5);
- _labelTotalPages->set_padding(4,0);
- _labelTotalPages->set_justify(Gtk::JUSTIFY_LEFT);
- _labelTotalPages->set_line_wrap(false);
- _labelTotalPages->set_use_markup(false);
- _labelTotalPages->set_selectable(false);
- hbox2->pack_start(*_labelSelect, Gtk::PACK_SHRINK, 4);
- hbox2->pack_start(*_pageNumberSpin, Gtk::PACK_SHRINK, 4);
- hbox2->pack_start(*_labelTotalPages, Gtk::PACK_SHRINK, 4);
- _cropCheck->set_can_focus();
- _cropCheck->set_relief(Gtk::RELIEF_NORMAL);
- _cropCheck->set_mode(true);
- _cropCheck->set_active(false);
- _cropTypeCombo->set_border_width(1);
- hbox3->pack_start(*_cropCheck, Gtk::PACK_SHRINK, 4);
- hbox3->pack_start(*_cropTypeCombo, Gtk::PACK_SHRINK, 0);
- vbox2->pack_start(*hbox2);
- vbox2->pack_start(*hbox3);
- _pageSettingsFrame->add(*vbox2);
- _pageSettingsFrame->set_border_width(4);
- _labelPrecision->set_alignment(0,0.5);
- _labelPrecision->set_padding(4,0);
- _labelPrecision->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecision->set_line_wrap(true);
- _labelPrecision->set_use_markup(false);
- _labelPrecision->set_selectable(false);
- _labelPrecisionWarning->set_alignment(0,0.5);
- _labelPrecisionWarning->set_padding(4,0);
- _labelPrecisionWarning->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecisionWarning->set_line_wrap(true);
- _labelPrecisionWarning->set_use_markup(true);
- _labelPrecisionWarning->set_selectable(false);
- _fallbackPrecisionSlider->set_size_request(180,-1);
- _fallbackPrecisionSlider->set_can_focus();
- _fallbackPrecisionSlider->set_inverted(false);
- _fallbackPrecisionSlider->set_digits(1);
- _fallbackPrecisionSlider->set_draw_value(true);
- _fallbackPrecisionSlider->set_value_pos(Gtk::POS_TOP);
- _labelPrecisionComment->set_size_request(90,-1);
- _labelPrecisionComment->set_alignment(0.5,0.5);
- _labelPrecisionComment->set_padding(4,0);
- _labelPrecisionComment->set_justify(Gtk::JUSTIFY_LEFT);
- _labelPrecisionComment->set_line_wrap(false);
- _labelPrecisionComment->set_use_markup(false);
- _labelPrecisionComment->set_selectable(false);
- hbox6->pack_start(*_fallbackPrecisionSlider, Gtk::PACK_SHRINK, 4);
- hbox6->pack_start(*_labelPrecisionComment, Gtk::PACK_SHRINK, 0);
- _labelText->set_alignment(0.5,0.5);
- _labelText->set_padding(4,0);
- _labelText->set_justify(Gtk::JUSTIFY_LEFT);
- _labelText->set_line_wrap(false);
- _labelText->set_use_markup(false);
- _labelText->set_selectable(false);
- hbox5->pack_start(*_labelText, Gtk::PACK_SHRINK, 0);
- hbox5->pack_start(*_textHandlingCombo, Gtk::PACK_SHRINK, 0);
- _localFontsCheck->set_can_focus();
- _localFontsCheck->set_relief(Gtk::RELIEF_NORMAL);
- _localFontsCheck->set_mode(true);
- _localFontsCheck->set_active(true);
- _embedImagesCheck->set_can_focus();
- _embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL);
- _embedImagesCheck->set_mode(true);
- _embedImagesCheck->set_active(true);
- vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*_labelPrecisionWarning, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*hbox5, Gtk::PACK_SHRINK, 4);
- vbox3->pack_start(*_localFontsCheck, Gtk::PACK_SHRINK, 0);
- vbox3->pack_start(*_embedImagesCheck, Gtk::PACK_SHRINK, 0);
- _importSettingsFrame->add(*vbox3);
- _importSettingsFrame->set_border_width(4);
- vbox1->pack_start(*_pageSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
- vbox1->pack_start(*_importSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0);
- hbox1->pack_start(*vbox1);
- hbox1->pack_start(*_previewArea, Gtk::PACK_EXPAND_WIDGET, 4);
-
-#if WITH_GTKMM_3_0
- get_content_area()->set_homogeneous(false);
- get_content_area()->set_spacing(0);
- get_content_area()->pack_start(*hbox1);
-#else
- this->get_vbox()->set_homogeneous(false);
- this->get_vbox()->set_spacing(0);
- this->get_vbox()->pack_start(*hbox1);
-#endif
-
- this->set_title(_("PDF Import Settings"));
- this->set_modal(true);
- sp_transientize(GTK_WIDGET(this->gobj())); //Make transient
- this->property_window_position().set_value(Gtk::WIN_POS_NONE);
- this->set_resizable(true);
- this->property_destroy_with_parent().set_value(false);
- this->add_action_widget(*cancelbutton, -6);
- this->add_action_widget(*okbutton, -5);
- cancelbutton->show();
- okbutton->show();
- _labelSelect->show();
- _pageNumberSpin->show();
- _labelTotalPages->show();
- hbox2->show();
- _cropCheck->show();
- _cropTypeCombo->show();
- hbox3->show();
- vbox2->show();
- _pageSettingsFrame->show();
- _labelPrecision->show();
- _labelPrecisionWarning->show();
- _fallbackPrecisionSlider->show();
- _labelPrecisionComment->show();
- hbox6->show();
- _labelText->show();
- _textHandlingCombo->show();
- hbox5->show();
- _localFontsCheck->show();
- _embedImagesCheck->show();
- vbox3->show();
- _importSettingsFrame->show();
- vbox1->show();
- _previewArea->show();
- hbox1->show();
-
- // Connect signals
-#if WITH_GTKMM_3_0
- _previewArea->signal_draw().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onDraw));
-#else
- _previewArea->signal_expose_event().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onExposePreview));
-#endif
- _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPageNumberChanged));
- _cropCheck->signal_toggled().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onToggleCropping));
- _fallbackPrecisionSlider_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPrecisionChanged));
-
- _render_thumb = false;
- _cairo_surface = NULL;
- _render_thumb = true;
-
- // Set default preview size
- _preview_width = 200;
- _preview_height = 300;
-
- // Init preview
- _thumb_data = NULL;
- _pageNumberSpin_adj->set_value(1.0);
- _current_page = 1;
- _setPreviewPage(_current_page);
-
- set_default (*okbutton);
- set_focus (*okbutton);
-}
-
-PdfImportCairoDialog::~PdfImportCairoDialog() {
- if (_cairo_surface) {
- cairo_surface_destroy(_cairo_surface);
- }
- if (_thumb_data) {
- if (_render_thumb) {
- delete _thumb_data;
- } else {
- // -->gfree(_thumb_data);
- delete _thumb_data;
- }
- }
-}
-
-bool PdfImportCairoDialog::showDialog() {
- show();
- gint b = run();
- hide();
- if ( b == Gtk::RESPONSE_OK ) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-int PdfImportCairoDialog::getSelectedPage() {
- return _current_page;
-}
-
-/**
- * \brief Retrieves the current settings into a repr which SvgBuilder will use
- * for determining the behaviour desired by the user
- */
-void PdfImportCairoDialog::getImportSettings(Inkscape::XML::Node *prefs) {
- sp_repr_set_svg_double(prefs, "selectedPage", (double)_current_page);
- if (_cropCheck->get_active()) {
- Glib::ustring current_choice = _cropTypeCombo->get_active_text();
- int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]);
- int i = 0;
- for ( ; i < num_crop_choices ; i++ ) {
- if ( current_choice == _(crop_setting_choices[i]) ) {
- break;
- }
- }
- sp_repr_set_svg_double(prefs, "cropTo", (double)i);
- } else {
- sp_repr_set_svg_double(prefs, "cropTo", -1.0);
- }
- sp_repr_set_svg_double(prefs, "approximationPrecision",
- _fallbackPrecisionSlider->get_value());
- if (_localFontsCheck->get_active()) {
- prefs->setAttribute("localFonts", "1");
- } else {
- prefs->setAttribute("localFonts", "0");
- }
- if (_embedImagesCheck->get_active()) {
- prefs->setAttribute("embedImages", "1");
- } else {
- prefs->setAttribute("embedImages", "0");
- }
-}
-
-/**
- * \brief Redisplay the comment on the current approximation precision setting
- * Evenly divides the interval of possible values between the available labels.
- */
-void PdfImportCairoDialog::_onPrecisionChanged() {
-
- static Glib::ustring precision_comments[] = {
- Glib::ustring(C_("PDF input precision", "rough")),
- Glib::ustring(C_("PDF input precision", "medium")),
- Glib::ustring(C_("PDF input precision", "fine")),
- Glib::ustring(C_("PDF input precision", "very fine"))
- };
-
- double min = _fallbackPrecisionSlider_adj->get_lower();
- double max = _fallbackPrecisionSlider_adj->get_upper();
- int num_intervals = sizeof(precision_comments) / sizeof(precision_comments[0]);
- double interval_len = ( max - min ) / (double)num_intervals;
- double value = _fallbackPrecisionSlider_adj->get_value();
- int comment_idx = (int)floor( ( value - min ) / interval_len );
- _labelPrecisionComment->set_label(precision_comments[comment_idx]);
-}
-
-void PdfImportCairoDialog::_onToggleCropping() {
- _cropTypeCombo->set_sensitive(_cropCheck->get_active());
-}
-
-void PdfImportCairoDialog::_onPageNumberChanged() {
- int page = _pageNumberSpin->get_value_as_int();
- _current_page = CLAMP(page, 1, poppler_document_get_n_pages(_poppler_doc));
- _setPreviewPage(_current_page);
-}
-
-/**
- * \brief Copies image data from a Cairo surface to a pixbuf
- *
- * Borrowed from libpoppler, from the file poppler-page.cc
- * Copyright (C) 2005, Red Hat, Inc.
- *
- */
-static void copy_cairo_surface_to_pixbuf (cairo_surface_t *surface,
- unsigned char *data,
- GdkPixbuf *pixbuf)
-{
- int cairo_width, cairo_height, cairo_rowstride;
- unsigned char *pixbuf_data, *dst, *cairo_data;
- int pixbuf_rowstride, pixbuf_n_channels;
- unsigned int *src;
- int x, y;
-
- cairo_width = cairo_image_surface_get_width (surface);
- cairo_height = cairo_image_surface_get_height (surface);
- cairo_rowstride = cairo_width * 4;
- cairo_data = data;
-
- pixbuf_data = gdk_pixbuf_get_pixels (pixbuf);
- pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-
- if (cairo_width > gdk_pixbuf_get_width (pixbuf))
- cairo_width = gdk_pixbuf_get_width (pixbuf);
- if (cairo_height > gdk_pixbuf_get_height (pixbuf))
- cairo_height = gdk_pixbuf_get_height (pixbuf);
- for (y = 0; y < cairo_height; y++)
- {
- src = reinterpret_cast<unsigned int *>(cairo_data + y * cairo_rowstride);
- dst = pixbuf_data + y * pixbuf_rowstride;
- for (x = 0; x < cairo_width; x++)
- {
- dst[0] = (*src >> 16) & 0xff;
- dst[1] = (*src >> 8) & 0xff;
- dst[2] = (*src >> 0) & 0xff;
- if (pixbuf_n_channels == 4)
- dst[3] = (*src >> 24) & 0xff;
- dst += pixbuf_n_channels;
- src++;
- }
- }
-}
-
-/**
- * \brief Updates the preview area with the previously rendered thumbnail
- */
-#if !WITH_GTKMM_3_0
-bool PdfImportCairoDialog::_onExposePreview(GdkEventExpose * /*event*/) {
- Cairo::RefPtr<Cairo::Context> cr = _previewArea->get_window()->create_cairo_context();
- return _onDraw(cr);
-}
-#endif
-
-
-bool PdfImportCairoDialog::_onDraw(const Cairo::RefPtr<Cairo::Context>& cr) {
- // Check if we have a thumbnail at all
- if (!_thumb_data) {
- return true;
- }
-
- // Create the pixbuf for the thumbnail
- Glib::RefPtr<Gdk::Pixbuf> thumb;
- if (_render_thumb) {
- thumb = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true,
- 8, _thumb_width, _thumb_height);
- } else {
- thumb = Gdk::Pixbuf::create_from_data(_thumb_data, Gdk::COLORSPACE_RGB,
- false, 8, _thumb_width, _thumb_height, _thumb_rowstride);
- }
- if (!thumb) {
- return true;
- }
-
- // Set background to white
- if (_render_thumb) {
- thumb->fill(0xffffffff);
- Gdk::Cairo::set_source_pixbuf(cr, thumb, 0, 0);
- cr->paint();
- }
-
- // Copy the thumbnail image from the Cairo surface
- if (_render_thumb) {
- copy_cairo_surface_to_pixbuf(_cairo_surface, _thumb_data, thumb->gobj());
- }
- Gdk::Cairo::set_source_pixbuf(cr, thumb, 0, _render_thumb ? 0 : 20);
- cr->paint();
-
- return true;
-}
-
-/**
- * \brief Renders the given page's thumbnail using Cairo
- */
-void PdfImportCairoDialog::_setPreviewPage(int page) {
-
- PopplerPage *_previewed_page = poppler_document_get_page(_poppler_doc, page-1);
-
- // Try to get a thumbnail from the PDF if possible
- if (!_render_thumb) {
- if (_thumb_data) {
- // --> gfree(_thumb_data);
- free(_thumb_data);
- _thumb_data = NULL;
- }
-
-/*
---> if (!_previewed_page->loadThumb(&_thumb_data,
- &_thumb_width, &_thumb_height, &_thumb_rowstride)) {
- return;
- }
-*/
- // Redraw preview area
- _previewArea->set_size_request(_thumb_width, _thumb_height + 20);
- _previewArea->queue_draw();
- return;
- }
-
- // Get page size by accounting for rotation
- double width, height;
- // --> int rotate = _previewed_page->getRotate();
- int rotate = 0;
- if ( rotate == 90 || rotate == 270 ) {
-// --> height = _previewed_page->getCropWidth();
-// --> width = _previewed_page->getCropHeight();
- } else {
- poppler_page_get_size (_previewed_page, &width, &height);
-// --> width = _previewed_page->getCropWidth();
-// --> height = _previewed_page->getCropHeight();
- }
- // Calculate the needed scaling for the page
- double scale_x = (double)_preview_width / width;
- double scale_y = (double)_preview_height / height;
- double scale_factor = ( scale_x > scale_y ) ? scale_y : scale_x;
- // Create new Cairo surface
- _thumb_width = (int)ceil( width * scale_factor );
- _thumb_height = (int)ceil( height * scale_factor );
- _thumb_rowstride = _thumb_width * 4;
- if (_thumb_data) {
- delete _thumb_data;
- }
- _thumb_data = new unsigned char[ _thumb_rowstride * _thumb_height ];
- if (_cairo_surface) {
- cairo_surface_destroy(_cairo_surface);
- }
- _cairo_surface = cairo_image_surface_create_for_data(_thumb_data,
- CAIRO_FORMAT_ARGB32, _thumb_width, _thumb_height, _thumb_rowstride);
- cairo_t *cr = cairo_create(_cairo_surface);
- cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); // Set fill color to white
- cairo_paint(cr); // Clear it
- cairo_scale(cr, scale_factor, scale_factor); // Use Cairo for resizing the image
- // Render page
- if (_poppler_doc != NULL) {
- PopplerPage *poppler_page = poppler_document_get_page(_poppler_doc, page - 1);
- poppler_page_render(poppler_page, cr);
- g_object_unref(G_OBJECT(poppler_page));
- }
- // Clean up
- cairo_destroy(cr);
- // Redraw preview area
- _previewArea->set_size_request(_preview_width, _preview_height);
- _previewArea->queue_draw();
-
-}
-
-
-static cairo_status_t _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length);
-
-SPDocument *
-PdfInputCairo::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) {
-
- g_message("Attempting to open using PdfInputCairo\n");
-
- gchar* filename_uri = g_filename_to_uri(uri, NULL, NULL);
-
- GError *error = NULL;
- /// @todo handle passwort
- /// @todo check if win32 unicode needs special attention
- PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, &error);
-
- if(error != NULL) {
- g_message("Unable to read file: %s\n", error->message);
- g_error_free (error);
- }
-
- if (document == NULL) {
- return NULL;
- }
-
- // create and show the import dialog
- PdfImportCairoDialog *dlg = NULL;
- if (inkscape_use_gui()) {
- dlg = new PdfImportCairoDialog(document);
- if (!dlg->showDialog()) {
- delete dlg;
- return NULL;
- }
- }
-
- // Get needed page
- int page_num;
- if (dlg) {
- page_num = dlg->getSelectedPage();
- delete dlg;
- }
- else
- page_num = 1;
-
- double width, height;
- PopplerPage* page = poppler_document_get_page(document, page_num - 1);
- poppler_page_get_size(page, &width, &height);
-
- Glib::ustring* output = new Glib::ustring("");
- cairo_surface_t* surface = cairo_svg_surface_create_for_stream(Inkscape::Extension::Internal::_write_ustring_cb,
- output, width, height);
- cairo_t* cr = cairo_create(surface);
-
- poppler_page_render_for_printing(page, cr);
- cairo_show_page(cr);
-
- cairo_destroy(cr);
- cairo_surface_destroy(surface);
-
- SPDocument * doc = SPDocument::createNewDocFromMem(output->c_str(), output->length(), TRUE);
-
- // Set viewBox if it doesn't exist
- if (doc && !doc->getRoot()->viewBox_set) {
- doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit())));
- }
-
- delete output;
- g_object_unref(page);
- g_object_unref(document);
-
- return doc;
-}
-
-static cairo_status_t
- _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length)
-{
- Glib::ustring* stream = static_cast<Glib::ustring*>(closure);
- stream->append(reinterpret_cast<const char*>(data), length);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-#include "clear-n_.h"
-
-void
-PdfInputCairo::init(void) {
- Inkscape::Extension::build_from_mem(
- "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
- "<name>" N_("PDF Input") "</name>\n"
- "<id>org.inkscape.input.cairo-pdf</id>\n"
- "<input>\n"
- "<extension>.pdf</extension>\n"
- "<mimetype>application/pdf</mimetype>\n"
- "<filetypename>" N_("Adobe PDF via poppler-cairo (*.pdf)") "</filetypename>\n"
- "<filetypetooltip>" N_("PDF Document") "</filetypetooltip>\n"
- "</input>\n"
- "</inkscape-extension>", new PdfInputCairo());
-} // init
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* HAVE_POPPLER_CAIRO */
-#endif /* HAVE_POPPLER_GLIB */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/internal/pdf-input-cairo.h b/src/extension/internal/pdf-input-cairo.h
deleted file mode 100644
index b65d22f48..000000000
--- a/src/extension/internal/pdf-input-cairo.h
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__
-#define __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__
-
-/*
- * PDF input using libpoppler and Cairo's SVG surface.
- *
- * Authors:
- * miklos erdelyi
- *
- * Copyright (C) 2007 Authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
-#include <glibmm/threads.h>
-#endif
-
-#include <gtkmm/dialog.h>
-#include <gtkmm/button.h>
-#include <gtkmm/buttonbox.h>
-#include <gtkmm/label.h>
-#include <gtkmm/box.h>
-#include <gtkmm/checkbutton.h>
-#include <gtkmm/comboboxtext.h>
-#include <gtkmm/drawingarea.h>
-#include <gtkmm/alignment.h>
-#include <gtkmm/frame.h>
-#include <gtkmm/scale.h>
-#include <glibmm/i18n.h>
-#include <gdk/gdk.h>
-
-#ifdef HAVE_POPPLER_GLIB
-#ifdef HAVE_POPPLER_CAIRO
-
-#include <poppler/glib/poppler.h>
-
-#include "../implementation/implementation.h"
-
-namespace Gtk {
-#if WITH_GTKMM_3_0
- class Scale;
-#else
- class HScale;
-#endif
-}
-
-namespace Inkscape {
-
-namespace UI {
-namespace Widget {
- class SpinButton;
- class Frame;
-}
-}
-
-namespace Extension {
-namespace Internal {
-
-class PdfImportCairoDialog : public Gtk::Dialog
-{
-public:
- PdfImportCairoDialog(PopplerDocument* doc);
- virtual ~PdfImportCairoDialog();
-
- bool showDialog();
- int getSelectedPage();
- void getImportSettings(Inkscape::XML::Node *prefs);
-
-private:
- void _setPreviewPage(int page);
-
- // Signal handlers
-#if !WITH_GTKMM_3_0
- bool _onExposePreview(GdkEventExpose *event);
-#endif
-
- bool _onDraw(const Cairo::RefPtr<Cairo::Context>& cr);
- void _onPageNumberChanged();
- void _onToggleCropping();
- void _onPrecisionChanged();
-
- class Gtk::Button * cancelbutton;
- class Gtk::Button * okbutton;
- class Gtk::Label * _labelSelect;
- class Inkscape::UI::Widget::SpinButton * _pageNumberSpin;
- class Gtk::Label * _labelTotalPages;
- class Gtk::HBox * hbox2;
- class Gtk::CheckButton * _cropCheck;
- class Gtk::ComboBoxText * _cropTypeCombo;
- class Gtk::HBox * hbox3;
- class Gtk::VBox * vbox2;
- class Inkscape::UI::Widget::Frame * _pageSettingsFrame;
- class Gtk::Label * _labelPrecision;
- class Gtk::Label * _labelPrecisionWarning;
-#if WITH_GTKMM_3_0
- class Gtk::Scale * _fallbackPrecisionSlider;
- Glib::RefPtr<Gtk::Adjustment> _fallbackPrecisionSlider_adj;
-#else
- class Gtk::HScale * _fallbackPrecisionSlider;
- class Gtk::Adjustment *_fallbackPrecisionSlider_adj;
-#endif
- class Gtk::Label * _labelPrecisionComment;
- class Gtk::HBox * hbox6;
- class Gtk::Label * _labelText;
- class Gtk::ComboBoxText * _textHandlingCombo;
- class Gtk::HBox * hbox5;
- class Gtk::CheckButton * _localFontsCheck;
- class Gtk::CheckButton * _embedImagesCheck;
- class Gtk::VBox * vbox3;
- class Inkscape::UI::Widget::Frame * _importSettingsFrame;
- class Gtk::VBox * vbox1;
- class Gtk::DrawingArea * _previewArea;
- class Gtk::HBox * hbox1;
-
- PopplerDocument *_poppler_doc;
- // PopplerPage *_previewed_page;
- int _current_page; // Current selected page
- unsigned char *_thumb_data; // Thumbnail image data
- int _thumb_width, _thumb_height; // Thumbnail size
- int _thumb_rowstride;
- int _preview_width, _preview_height; // Size of the preview area
- bool _render_thumb; // Whether we can/shall render thumbnails
- cairo_surface_t *_cairo_surface; // this cairo surface is used for preview
-};
-
-
-class PdfInputCairo: public Inkscape::Extension::Implementation::Implementation {
- PdfInputCairo () { };
-public:
- SPDocument *open( Inkscape::Extension::Input *mod,
- const gchar *uri );
- static void init( void );
-
-};
-
-} } } /* namespace Inkscape, Extension, Implementation */
-
-#endif /* HAVE_POPPLER_CAIRO */
-#endif /* HAVE_POPPLER_GLIB */
-
-#endif /* __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp
index 3155ac098..63581bd8a 100644
--- a/src/extension/internal/pdfinput/pdf-input.cpp
+++ b/src/extension/internal/pdfinput/pdf-input.cpp
@@ -124,6 +124,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximating gradient meshes:")));
_labelPrecisionWarning = Gtk::manage(new class Gtk::Label(_("<b>Note</b>: setting the precision too high may result in a large SVG file and slow performance.")));
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck = Gtk::manage(new class Gtk::CheckButton(_("import via Poppler")));
+#endif
#if WITH_GTKMM_3_0
_fallbackPrecisionSlider_adj = Gtk::Adjustment::create(2, 1, 256, 1, 10, 10);
_fallbackPrecisionSlider = Gtk::manage(new class Gtk::Scale(_fallbackPrecisionSlider_adj));
@@ -199,6 +202,12 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_labelPrecisionWarning->set_line_wrap(true);
_labelPrecisionWarning->set_use_markup(true);
_labelPrecisionWarning->set_selectable(false);
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck->set_can_focus();
+ _importviaPopplerCheck->set_relief(Gtk::RELIEF_NORMAL);
+ _importviaPopplerCheck->set_mode(true);
+ _importviaPopplerCheck->set_active(false);
+#endif
_fallbackPrecisionSlider->set_size_request(180,-1);
_fallbackPrecisionSlider->set_can_focus();
_fallbackPrecisionSlider->set_inverted(false);
@@ -230,6 +239,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL);
_embedImagesCheck->set_mode(true);
_embedImagesCheck->set_active(true);
+#ifdef HAVE_POPPLER_CAIRO
+ vbox3->pack_start(*_importviaPopplerCheck, Gtk::PACK_SHRINK, 0);
+#endif
vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 0);
vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0);
vbox3->pack_start(*_labelPrecisionWarning, Gtk::PACK_SHRINK, 0);
@@ -274,6 +286,9 @@ PdfImportDialog::PdfImportDialog(PDFDoc *doc, const gchar */*uri*/)
_pageSettingsFrame->show();
_labelPrecision->show();
_labelPrecisionWarning->show();
+#ifdef HAVE_POPPLER_CAIRO
+ _importviaPopplerCheck->show();
+#endif
_fallbackPrecisionSlider->show();
_labelPrecisionComment->show();
hbox6->show();
@@ -358,6 +373,14 @@ int PdfImportDialog::getSelectedPage() {
return _current_page;
}
+int PdfImportDialog::getImportMethod() {
+#ifdef HAVE_POPPLER_CAIRO
+ return (_importviaPopplerCheck->get_active()) ? 1 : 0;
+#else
+ return 0;
+#endif
+}
+
/**
* \brief Retrieves the current settings into a repr which SvgBuilder will use
* for determining the behaviour desired by the user
@@ -389,6 +412,13 @@ void PdfImportDialog::getImportSettings(Inkscape::XML::Node *prefs) {
} else {
prefs->setAttribute("embedImages", "0");
}
+#ifdef HAVE_POPPLER_CAIRO
+ if (_importviaPopplerCheck->get_active()) {
+ prefs->setAttribute("importviapoppler", "1");
+ } else {
+ prefs->setAttribute("importviapoppler", "0");
+ }
+#endif
}
/**
@@ -595,6 +625,18 @@ PdfInput::wasCancelled () {
return _cancelled;
}
+#ifdef HAVE_POPPLER_CAIRO
+/// helper method
+static cairo_status_t
+ _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length)
+{
+ Glib::ustring* stream = static_cast<Glib::ustring*>(closure);
+ stream->append(reinterpret_cast<const char*>(data), length);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
/**
* Parses the selected page of the given PDF document using PdfParser.
*/
@@ -672,79 +714,146 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) {
page_num = 1;
Catalog *catalog = pdf_doc->getCatalog();
Page *page = catalog->getPage(page_num);
+
+ int is_importvia_poppler = 0;
+ if(dlg)
+ {
+#ifdef HAVE_POPPLER_CAIRO
+ is_importvia_poppler = dlg->getImportMethod();
+#endif
+ }
- SPDocument *doc = SPDocument::createNewDoc(NULL, TRUE, TRUE);
- bool saved = DocumentUndo::getUndoSensitive(doc);
- DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+ SPDocument *doc = NULL;
+ bool saved = false;
+ if(is_importvia_poppler == 0)
+ {
+ // native importer
+ doc = SPDocument::createNewDoc(NULL, TRUE, TRUE);
+ saved = DocumentUndo::getUndoSensitive(doc);
+ DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+
+ // Create builder
+ gchar *docname = g_path_get_basename(uri);
+ gchar *dot = g_strrstr(docname, ".");
+ if (dot) {
+ *dot = 0;
+ }
+ SvgBuilder *builder = new SvgBuilder(doc, docname, pdf_doc->getXRef());
+
+ // Get preferences
+ Inkscape::XML::Node *prefs = builder->getPreferences();
+ if (dlg)
+ dlg->getImportSettings(prefs);
+
+ printf("pdf import via %s.", (is_importvia_poppler != 0) ? "poppler" : "native");
+
+ // Apply crop settings
+ PDFRectangle *clipToBox = NULL;
+ double crop_setting;
+ sp_repr_get_double(prefs, "cropTo", &crop_setting);
+ if ( crop_setting >= 0.0 ) { // Do page clipping
+ int crop_choice = (int)crop_setting;
+ switch (crop_choice) {
+ case 0: // Media box
+ clipToBox = page->getMediaBox();
+ break;
+ case 1: // Crop box
+ clipToBox = page->getCropBox();
+ break;
+ case 2: // Bleed box
+ clipToBox = page->getBleedBox();
+ break;
+ case 3: // Trim box
+ clipToBox = page->getTrimBox();
+ break;
+ case 4: // Art box
+ clipToBox = page->getArtBox();
+ break;
+ default:
+ break;
+ }
+ }
- // Create builder
- gchar *docname = g_path_get_basename(uri);
- gchar *dot = g_strrstr(docname, ".");
- if (dot) {
- *dot = 0;
- }
- SvgBuilder *builder = new SvgBuilder(doc, docname, pdf_doc->getXRef());
+ // Create parser
+ PdfParser *pdf_parser = new PdfParser(pdf_doc->getXRef(), builder, page_num-1, page->getRotate(),
+ page->getResourceDict(), page->getCropBox(), clipToBox);
- // Get preferences
- Inkscape::XML::Node *prefs = builder->getPreferences();
- if (dlg)
- dlg->getImportSettings(prefs);
-
- // Apply crop settings
- PDFRectangle *clipToBox = NULL;
- double crop_setting;
- sp_repr_get_double(prefs, "cropTo", &crop_setting);
- if ( crop_setting >= 0.0 ) { // Do page clipping
- int crop_choice = (int)crop_setting;
- switch (crop_choice) {
- case 0: // Media box
- clipToBox = page->getMediaBox();
- break;
- case 1: // Crop box
- clipToBox = page->getCropBox();
- break;
- case 2: // Bleed box
- clipToBox = page->getBleedBox();
- break;
- case 3: // Trim box
- clipToBox = page->getTrimBox();
- break;
- case 4: // Art box
- clipToBox = page->getArtBox();
- break;
- default:
- break;
+ // Set up approximation precision for parser
+ double color_delta;
+ sp_repr_get_double(prefs, "approximationPrecision", &color_delta);
+ if ( color_delta <= 0.0 ) {
+ color_delta = 1.0 / 2.0;
+ } else {
+ color_delta = 1.0 / color_delta;
+ }
+ for ( int i = 1 ; i <= pdfNumShadingTypes ; i++ ) {
+ pdf_parser->setApproximationPrecision(i, color_delta, 6);
}
- }
- // Create parser
- PdfParser *pdf_parser = new PdfParser(pdf_doc->getXRef(), builder, page_num-1, page->getRotate(),
- page->getResourceDict(), page->getCropBox(), clipToBox);
+ // Parse the document structure
+ Object obj;
+ page->getContents(&obj);
+ if (!obj.isNull()) {
+ pdf_parser->parse(&obj);
+ }
- // Set up approximation precision for parser
- double color_delta;
- sp_repr_get_double(prefs, "approximationPrecision", &color_delta);
- if ( color_delta <= 0.0 ) {
- color_delta = 1.0 / 2.0;
- } else {
- color_delta = 1.0 / color_delta;
- }
- for ( int i = 1 ; i <= pdfNumShadingTypes ; i++ ) {
- pdf_parser->setApproximationPrecision(i, color_delta, 6);
+ // Cleanup
+ obj.free();
+ delete pdf_parser;
+ delete builder;
+ g_free(docname);
}
+ else
+ {
+#ifdef HAVE_POPPLER_CAIRO
+ // the poppler import
+ gchar* filename_uri = g_filename_to_uri(uri, NULL, NULL);
+ GError *error = NULL;
+ /// @todo handle passwort
+ /// @todo check if win32 unicode needs special attention
+ PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, &error);
+
+ if(error != NULL) {
+ g_error_free (error);
+ }
- // Parse the document structure
- Object obj;
- page->getContents(&obj);
- if (!obj.isNull()) {
- pdf_parser->parse(&obj);
+ if (document != NULL)
+ {
+ double width, height;
+ PopplerPage* page = poppler_document_get_page(document, page_num - 1);
+ poppler_page_get_size(page, &width, &height);
+
+ Glib::ustring output;
+ cairo_surface_t* surface = cairo_svg_surface_create_for_stream(Inkscape::Extension::Internal::_write_ustring_cb,
+ &output, width, height);
+ cairo_t* cr = cairo_create(surface);
+
+ poppler_page_render_for_printing(page, cr);
+ cairo_show_page(cr);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+
+ doc = SPDocument::createNewDocFromMem(output.c_str(), output.length(), TRUE);
+
+ // Cleanup
+ // delete output;
+ g_object_unref(G_OBJECT(page));
+ g_object_unref(G_OBJECT(document));
+ }
+ else
+ {
+ doc = SPDocument::createNewDoc(NULL, TRUE, TRUE); // fallback create empthy document
+ }
+ saved = DocumentUndo::getUndoSensitive(doc);
+ DocumentUndo::setUndoSensitive(doc, false); // No need to undo in this temporary document
+
+ // Cleanup
+ g_free(filename_uri);
+#endif
}
// Cleanup
- obj.free();
- delete pdf_parser;
- delete builder;
- g_free(docname);
delete pdf_doc;
delete dlg;
diff --git a/src/extension/internal/pdfinput/pdf-input.h b/src/extension/internal/pdfinput/pdf-input.h
index f22a783ff..d57c3e993 100644
--- a/src/extension/internal/pdfinput/pdf-input.h
+++ b/src/extension/internal/pdfinput/pdf-input.h
@@ -75,6 +75,7 @@ public:
bool showDialog();
int getSelectedPage();
+ int getImportMethod();
void getImportSettings(Inkscape::XML::Node *prefs);
private:
@@ -103,6 +104,9 @@ private:
class Inkscape::UI::Widget::Frame * _pageSettingsFrame;
class Gtk::Label * _labelPrecision;
class Gtk::Label * _labelPrecisionWarning;
+#ifdef HAVE_POPPLER_CAIRO
+ class Gtk::CheckButton * _importviaPopplerCheck; // using poppler_cairo for importing
+#endif
#if WITH_GTKMM_3_0
class Gtk::Scale * _fallbackPrecisionSlider;
Glib::RefPtr<Gtk::Adjustment> _fallbackPrecisionSlider_adj;
diff --git a/src/extension/param/notebook.cpp b/src/extension/param/notebook.cpp
index 97002e33f..9ec31ca6b 100644
--- a/src/extension/param/notebook.cpp
+++ b/src/extension/param/notebook.cpp
@@ -214,7 +214,7 @@ Gtk::Widget * ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Nod
// printf("Tip: '%s'\n", tip);
vbox->pack_start(*widg, false, false, 2);
if (tip) {
- widg->set_tooltip_text(tip);
+ widg->set_tooltip_text(_(tip));
} else {
widg->set_tooltip_text("");
widg->set_has_tooltip(false);
diff --git a/src/extension/prefdialog.cpp b/src/extension/prefdialog.cpp
index 1b657f644..d1f83701f 100644
--- a/src/extension/prefdialog.cpp
+++ b/src/extension/prefdialog.cpp
@@ -212,6 +212,9 @@ PrefDialog::preview_toggle (void) {
void
PrefDialog::param_change (void) {
if (_exEnv != NULL) {
+ if (!_effect->loaded()) {
+ _effect->set_state(Extension::STATE_LOADED);
+ }
_timersig.disconnect();
_timersig = Glib::signal_timeout().connect(sigc::mem_fun(this, &PrefDialog::param_timer_expire),
250, /* ms */
diff --git a/src/id-clash.cpp b/src/id-clash.cpp
index 66357b75b..4bd66e858 100644
--- a/src/id-clash.cpp
+++ b/src/id-clash.cpp
@@ -92,7 +92,7 @@ const char* clipboard_properties[] = {
* (e.g., ID selectors in CSS stylesheets, and references in scripts).
*/
static void
-find_references(SPObject *elem, refmap_type *refmap)
+find_references(SPObject *elem, refmap_type &refmap)
{
if (elem->cloned) return;
Inkscape::XML::Node *repr_elem = elem->getRepr();
@@ -110,7 +110,7 @@ find_references(SPObject *elem, refmap_type *refmap)
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_CLIPBOARD, elem, attr };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -127,7 +127,7 @@ find_references(SPObject *elem, refmap_type *refmap)
if (val && val[0] == '#') {
std::string id(val+1);
IdReference idref = { REF_HREF, elem, attr };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
@@ -142,7 +142,7 @@ find_references(SPObject *elem, refmap_type *refmap)
if (obj) {
const gchar *id = obj->getId();
IdReference idref = { REF_STYLE, elem, SPIPaint_properties[i] };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
}
@@ -154,7 +154,7 @@ find_references(SPObject *elem, refmap_type *refmap)
if (obj) {
const gchar *id = obj->getId();
IdReference idref = { REF_STYLE, elem, "filter" };
- (*refmap)[id].push_back(idref);
+ refmap[id].push_back(idref);
}
}
@@ -166,7 +166,7 @@ find_references(SPObject *elem, refmap_type *refmap)
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_STYLE, elem, markers[i] };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -180,7 +180,7 @@ find_references(SPObject *elem, refmap_type *refmap)
gchar *uri = extract_uri(value);
if (uri && uri[0] == '#') {
IdReference idref = { REF_URL, elem, attr };
- (*refmap)[uri+1].push_back(idref);
+ refmap[uri+1].push_back(idref);
}
g_free(uri);
}
@@ -199,7 +199,7 @@ find_references(SPObject *elem, refmap_type *refmap)
*/
static void
change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
- SPObject *elem, const refmap_type *refmap,
+ SPObject *elem, refmap_type const &refmap,
id_changelist_type *id_changes)
{
const gchar *id = elem->getId();
@@ -216,8 +216,7 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
if (cd_obj && SP_IS_GRADIENT(cd_obj)) {
SPGradient *cd_gr = SP_GRADIENT(cd_obj);
- if ( cd_gr->isEquivalent(SP_GRADIENT(elem)) &&
- cd_gr->isAligned(SP_GRADIENT(elem))) {
+ if ( cd_gr->isEquivalent(SP_GRADIENT(elem))) {
fix_clashing_ids = false;
}
}
@@ -234,9 +233,9 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
}
// Change to the new ID
- elem->getRepr()->setAttribute("id", new_id.c_str());
+ elem->getRepr()->setAttribute("id", new_id);
// Make a note of this change, if we need to fix up refs to it
- if (refmap->find(old_id) != refmap->end())
+ if (refmap.find(old_id) != refmap.end())
id_changes->push_back(id_changeitem_type(elem, old_id));
}
}
@@ -253,36 +252,43 @@ change_clashing_ids(SPDocument *imported_doc, SPDocument *current_doc,
* Fix up references to changed IDs.
*/
static void
-fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes)
+fix_up_refs(refmap_type const &refmap, const id_changelist_type &id_changes)
{
id_changelist_type::const_iterator pp;
const id_changelist_type::const_iterator pp_end = id_changes.end();
for (pp = id_changes.begin(); pp != pp_end; ++pp) {
SPObject *obj = pp->first;
- refmap_type::const_iterator pos = refmap->find(pp->second);
+ refmap_type::const_iterator pos = refmap.find(pp->second);
std::list<IdReference>::const_iterator it;
const std::list<IdReference>::const_iterator it_end = pos->second.end();
for (it = pos->second.begin(); it != it_end; ++it) {
- if (it->type == REF_HREF) {
- gchar *new_uri = g_strdup_printf("#%s", obj->getId());
- it->elem->getRepr()->setAttribute(it->attr, new_uri);
- g_free(new_uri);
- } else if (it->type == REF_STYLE) {
- sp_style_set_property_url(it->elem, it->attr, obj, false);
- } else if (it->type == REF_URL) {
- gchar *url = g_strdup_printf("url(#%s)", obj->getId());
- it->elem->getRepr()->setAttribute(it->attr, url);
- g_free(url);
- } else if (it->type == REF_CLIPBOARD) {
- SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
- gchar *url = g_strdup_printf("url(#%s)", obj->getId());
- sp_repr_css_set_property(style, it->attr, url);
- g_free(url);
- Glib::ustring style_string;
- sp_repr_css_write_string(style, style_string);
- it->elem->getRepr()->setAttribute("style", style_string.c_str());
- } else {
- g_assert(0); // shouldn't happen
+ switch (it->type) {
+ case REF_HREF: {
+ gchar *new_uri = g_strdup_printf("#%s", obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, new_uri);
+ g_free(new_uri);
+ break;
+ }
+ case REF_STYLE: {
+ sp_style_set_property_url(it->elem, it->attr, obj, false);
+ break;
+ }
+ case REF_URL: {
+ gchar *url = g_strdup_printf("url(#%s)", obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, url);
+ g_free(url);
+ break;
+ }
+ case REF_CLIPBOARD: {
+ SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
+ gchar *url = g_strdup_printf("url(#%s)", obj->getId());
+ sp_repr_css_set_property(style, it->attr, url);
+ g_free(url);
+ Glib::ustring style_string;
+ sp_repr_css_write_string(style, style_string);
+ it->elem->getRepr()->setAttribute("style", style_string);
+ break;
+ }
}
}
}
@@ -297,7 +303,7 @@ fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes)
void
prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
{
- refmap_type *refmap = new refmap_type;
+ refmap_type refmap;
id_changelist_type id_changes;
SPObject *imported_root = imported_doc->getRoot();
@@ -305,8 +311,6 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
change_clashing_ids(imported_doc, current_doc, imported_root, refmap,
&id_changes);
fix_up_refs(refmap, id_changes);
-
- delete refmap;
}
/*
@@ -315,24 +319,47 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc)
void
change_def_references(SPObject *from_obj, SPObject *to_obj)
{
- refmap_type *refmap = new refmap_type;
+ refmap_type refmap;
SPDocument *current_doc = from_obj->document;
std::string old_id(from_obj->getId());
find_references(current_doc->getRoot(), refmap);
- refmap_type::const_iterator pos = refmap->find(old_id);
- if (pos != refmap->end()) {
+ refmap_type::const_iterator pos = refmap.find(old_id);
+ if (pos != refmap.end()) {
std::list<IdReference>::const_iterator it;
const std::list<IdReference>::const_iterator it_end = pos->second.end();
for (it = pos->second.begin(); it != it_end; ++it) {
- if (it->type == REF_STYLE) {
- sp_style_set_property_url(it->elem, it->attr, to_obj, false);
- }
+ switch (it->type) {
+ case REF_HREF: {
+ gchar *new_uri = g_strdup_printf("#%s", to_obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, new_uri);
+ g_free(new_uri);
+ break;
+ }
+ case REF_STYLE: {
+ sp_style_set_property_url(it->elem, it->attr, to_obj, false);
+ break;
+ }
+ case REF_URL: {
+ gchar *url = g_strdup_printf("url(#%s)", to_obj->getId());
+ it->elem->getRepr()->setAttribute(it->attr, url);
+ g_free(url);
+ break;
+ }
+ case REF_CLIPBOARD: {
+ SPCSSAttr *style = sp_repr_css_attr(it->elem->getRepr(), "style");
+ gchar *url = g_strdup_printf("url(#%s)", to_obj->getId());
+ sp_repr_css_set_property(style, it->attr, url);
+ g_free(url);
+ Glib::ustring style_string;
+ sp_repr_css_write_string(style, style_string);
+ it->elem->getRepr()->setAttribute("style", style_string);
+ break;
+ }
+ }
}
}
-
- delete refmap;
}
/*
@@ -355,8 +382,7 @@ void rename_id(SPObject *elem, Glib::ustring const &new_name)
}
SPDocument *current_doc = elem->document;
- refmap_type *refmap = new refmap_type;
- id_changelist_type id_changes;
+ refmap_type refmap;
find_references(current_doc->getRoot(), refmap);
std::string old_id(elem->getId());
@@ -374,14 +400,14 @@ void rename_id(SPObject *elem, Glib::ustring const &new_name)
}
// Change to the new ID
- elem->getRepr()->setAttribute("id", new_name2.c_str());
+ elem->getRepr()->setAttribute("id", new_name2);
// Make a note of this change, if we need to fix up refs to it
- if (refmap->find(old_id) != refmap->end()) {
+ id_changelist_type id_changes;
+ if (refmap.find(old_id) != refmap.end()) {
id_changes.push_back(id_changeitem_type(elem, old_id));
}
fix_up_refs(refmap, id_changes);
- delete refmap;
}
/*
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 54451aba4..4b4c8c678 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -1445,6 +1445,11 @@ profile_path(const char *filename)
if (val) {
prefdir = g_strdup(val);
}
+ // Then check for a custom user environment variable
+ gchar const *userenv = g_getenv("INKSCAPE_PROFILE_DIR");
+ if (userenv) {
+ prefdir = g_strdup(userenv);
+ }
#ifdef HAS_SHGetSpecialFolderLocation
// prefer c:\Documents and Settings\UserName\Application Data\ to
diff --git a/src/inkscape.rc b/src/inkscape.rc
index efa360c8d..395ef39e1 100644
--- a/src/inkscape.rc
+++ b/src/inkscape.rc
@@ -15,7 +15,7 @@ BEGIN
VALUE "FileDescription", "Inkscape"
VALUE "FileVersion", "0.48+devel"
VALUE "InternalName", "Inkscape"
- VALUE "LegalCopyright", "© 2012 Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
VALUE "ProductName", "Inkscape"
VALUE "ProductVersion", "0.48+devel"
END
diff --git a/src/inkview.rc b/src/inkview.rc
index f1fa92247..fd7eb50a1 100644
--- a/src/inkview.rc
+++ b/src/inkview.rc
@@ -15,7 +15,7 @@ BEGIN
VALUE "FileDescription", "Inkview"
VALUE "FileVersion", "0.48+devel"
VALUE "InternalName", "Inkview"
- VALUE "LegalCopyright", "© 2012 Inkscape"
+ VALUE "LegalCopyright", "© 2014 Inkscape"
VALUE "ProductName", "Inkview"
VALUE "ProductVersion", "0.48+devel"
END
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 6471124ec..6af5c6a56 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -80,13 +80,17 @@ KnotHolderEntity::~KnotHolderEntity()
void
KnotHolderEntity::update_knot()
{
- Geom::Affine const i2dt(item->i2dt_affine());
+ Geom::Point knot_pos(knot_get());
+ if (knot_pos.isFinite()) {
+ Geom::Point dp(knot_pos * item->i2dt_affine());
- Geom::Point dp(knot_get() * i2dt);
-
- _moved_connection.block();
- knot->setPosition(dp, SP_KNOT_STATE_NORMAL);
- _moved_connection.unblock();
+ _moved_connection.block();
+ knot->setPosition(dp, SP_KNOT_STATE_NORMAL);
+ _moved_connection.unblock();
+ } else {
+ // knot coords are non-finite, hide knot
+ knot->hide();
+ }
}
Geom::Point
diff --git a/src/libdepixelize/kopftracer2011.cpp b/src/libdepixelize/kopftracer2011.cpp
index bbb73d445..1e769b0c9 100644
--- a/src/libdepixelize/kopftracer2011.cpp
+++ b/src/libdepixelize/kopftracer2011.cpp
@@ -26,8 +26,7 @@
# include <config.h>
#endif
-
-#include "kopftracer2011.h"
+#include <glibmm.h>
// Build fix under Inkscape build tree
#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
@@ -35,6 +34,7 @@
#endif
#include <algorithm>
+#include "kopftracer2011.h"
#include "priv/colorspace.h"
#include "priv/homogeneoussplines.h"
#include "priv/branchless.h"
diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp
index 581c632f5..cac3a9347 100644
--- a/src/live_effects/lpe-knot.cpp
+++ b/src/live_effects/lpe-knot.cpp
@@ -353,7 +353,11 @@ LPEKnot::LPEKnot(LivePathEffectObject *lpeobject) :
add_other_stroke_width(_("_Crossing path stroke width"), _("Add crossed stroke width to the interruption size"), "add_other_stroke_width", &wr, this, true),
switcher_size(_("S_witcher size:"), _("Orientation indicator/switcher size"), "switcher_size", &wr, this, 15),
crossing_points_vector(_("Crossing Signs"), _("Crossings signs"), "crossing_points_vector", &wr, this),
- gpaths(),gstroke_widths()
+ crossing_points(),
+ gpaths(),
+ gstroke_widths(),
+ selectedCrossing(0),
+ switcher(0.,0.)
{
// register all your parameters here, so Inkscape knows which parameters this effect has:
registerParameter( dynamic_cast<Parameter *>(&interruption_width) );
@@ -363,10 +367,6 @@ LPEKnot::LPEKnot(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&switcher_size) );
registerParameter( dynamic_cast<Parameter *>(&crossing_points_vector) );
- crossing_points = LPEKnotNS::CrossingPoints();
- selectedCrossing = 0;
- switcher = Geom::Point(0,0);
-
_provides_knotholder_entities = true;
}
@@ -386,9 +386,7 @@ LPEKnot::updateSwitcher(){
//std::cout<<"placing switcher at "<<switcher<<" \n";
}else{
//std::cout<<"hiding switcher!\n";
- //TODO: is there a way to properly hide the helper.
- //switcher = Geom::Point(Geom::infinity(),Geom::infinity());
- switcher = Geom::Point(1e10,1e10);
+ switcher = Geom::Point(Geom::infinity(),Geom::infinity());
}
}
@@ -539,8 +537,9 @@ LPEKnot::doBeforeEffect (SPLPEItem const* lpeitem)
using namespace Geom;
original_bbox(lpeitem);
- gpaths = std::vector<Geom::Path>();
- gstroke_widths = std::vector<double>();
+ gpaths.clear();
+ gstroke_widths.clear();
+
collectPathsAndWidths(lpeitem, gpaths, gstroke_widths);
// std::cout<<"\nPaths on input:\n";
@@ -586,7 +585,10 @@ LPEKnot::doBeforeEffect (SPLPEItem const* lpeitem)
// std::cout<<crossing_points[toto].sign<<"),";
// }
crossing_points.inherit_signs(old_crdata);
- crossing_points_vector.param_set_and_write_new_value(crossing_points.to_vector());
+
+ // Don't write to XML here, only store it in the param itself. Will be written to SVG later
+ crossing_points_vector.param_setValue(crossing_points.to_vector());
+
updateSwitcher();
}
diff --git a/src/live_effects/lpe-knot.h b/src/live_effects/lpe-knot.h
index b937f9021..f926bf085 100644
--- a/src/live_effects/lpe-knot.h
+++ b/src/live_effects/lpe-knot.h
@@ -74,7 +74,6 @@ private:
BoolParam add_stroke_width;
BoolParam add_other_stroke_width;
ScalarParam switcher_size;
- double stroke_width;
ArrayParam<double> crossing_points_vector;//svg storage of crossing_points
LPEKnotNS::CrossingPoints crossing_points;//topology representation of the knot.
diff --git a/src/main.cpp b/src/main.cpp
index 6f4add4b1..517ba0506 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1158,6 +1158,7 @@ static int sp_process_file_list(GSList *fl)
if (sp_export_text_to_path) {
GSList *items = NULL;
SPRoot *root = doc->getRoot();
+ doc->ensureUpToDate();
for ( SPObject *iter = root->firstChild(); iter ; iter = iter->getNext()) {
SPItem* item = (SPItem*) iter;
if (! (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_GROUP(item))) {
diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp
index 88450dfdf..1cb96fed0 100644
--- a/src/selection-describer.cpp
+++ b/src/selection-describer.cpp
@@ -56,6 +56,21 @@ char* collect_terms (GSList *items)
return g_strdup(ss.str().c_str());
}
+// Returns the number of terms in the list
+static int count_terms (GSList *items)
+{
+ GSList *check = NULL;
+ int count=0;
+ for (GSList *i = (GSList *)items; i != NULL; i = i->next) {
+ const char *term = SP_ITEM(i->data)->displayName();
+ if (term != NULL && g_slist_find (check, term) == NULL) {
+ check = g_slist_prepend (check, (void *) term);
+ count++;
+ }
+ }
+ return count;
+}
+
// Returns the number of filtered items in the list
static int count_filtered (GSList *items)
{
@@ -194,9 +209,12 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select
} else { // multiple items
int objcount = g_slist_length((GSList *)items);
char *terms = collect_terms ((GSList *)items);
-
- gchar *objects_str = g_strdup_printf(
- "<b>%i</b> objects selected of types %s", objcount, terms);
+ int n_terms = count_terms((GSList *)items);
+
+ gchar *objects_str = g_strdup_printf(ngettext(
+ "<b>%i</b> objects selected of type %s",
+ "<b>%i</b> objects selected of types %s", n_terms),
+ objcount, terms);
g_free(terms);
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 7708c999e..d6f31f073 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -929,23 +929,28 @@ gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
sn = m.freeSnapScale(_snap_points, _point, geom_scale, _origin_for_specpoints);
}
- if (!(bb.getSnapped() || sn.getSnapped())) {
+ // These lines below are duplicated in stretchRequest
+ if (bb.getSnapped() || sn.getSnapped()) {
+ if (bb.getSnapped()) {
+ if (!bb.isOtherSnapBetter(sn, false)) {
+ // We snapped the bbox (which is either visual or geometric)
+ _desktop->snapindicator->set_new_snaptarget(bb);
+ default_scale = Geom::Scale(bb.getTransformation());
+ // Calculate the new transformation and update the handle position
+ pt = _calcAbsAffineDefault(default_scale);
+ }
+ } else if (sn.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(sn);
+ // We snapped the special points (e.g. nodes), which are not at the visual bbox
+ // The handle location however (pt) might however be at the visual bbox, so we
+ // will have to calculate pt taking the stroke width into account
+ geom_scale = Geom::Scale(sn.getTransformation());
+ pt = _calcAbsAffineGeom(geom_scale);
+ }
+ } else {
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
- // We snapped the bbox (which is either visual or geometric)
- _desktop->snapindicator->set_new_snaptarget(bb);
- default_scale = Geom::Scale(bb.getTransformation());
- // Calculate the new transformation and update the handle position
- pt = _calcAbsAffineDefault(default_scale);
- } else {
- _desktop->snapindicator->set_new_snaptarget(sn);
- // We snapped the special points (e.g. nodes), which are not at the visual bbox
- // The handle location however (pt) might however be at the visual bbox, so we
- // will have to calculate pt taking the stroke width into account
- geom_scale = Geom::Scale(sn.getTransformation());
- pt = _calcAbsAffineGeom(geom_scale);
}
m.unSetup();
}
@@ -1028,20 +1033,28 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
geom_scale[perp] = fabs(geom_scale[axis]);
}
- if (!(bb.getSnapped() || sn.getSnapped())) {
+ // These lines below are duplicated in scaleRequest
+ if (bb.getSnapped() || sn.getSnapped()) {
+ if (bb.getSnapped()) {
+ if (!bb.isOtherSnapBetter(sn, false)) {
+ // We snapped the bbox (which is either visual or geometric)
+ _desktop->snapindicator->set_new_snaptarget(bb);
+ default_scale = Geom::Scale(bb.getTransformation());
+ // Calculate the new transformation and update the handle position
+ pt = _calcAbsAffineDefault(default_scale);
+ }
+ } else if (sn.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(sn);
+ // We snapped the special points (e.g. nodes), which are not at the visual bbox
+ // The handle location however (pt) might however be at the visual bbox, so we
+ // will have to calculate pt taking the stroke width into account
+ geom_scale = Geom::Scale(sn.getTransformation());
+ pt = _calcAbsAffineGeom(geom_scale);
+ }
+ } else {
// We didn't snap at all! Don't update the handle position, just calculate the new transformation
_calcAbsAffineDefault(default_scale);
_desktop->snapindicator->remove_snaptarget();
- } else if (bb.getSnapped() && !bb.isOtherSnapBetter(sn, false)) {
- _desktop->snapindicator->set_new_snaptarget(bb);
- // Calculate the new transformation and update the handle position
- pt = _calcAbsAffineDefault(default_scale);
- } else {
- _desktop->snapindicator->set_new_snaptarget(sn);
- // We snapped the special points (e.g. nodes), which are not at the visual bbox
- // The handle location however (pt) might however be at the visual bbox, so we
- // will have to calculate pt taking the stroke width into account
- pt = _calcAbsAffineGeom(geom_scale);
}
m.unSetup();
diff --git a/src/snap.cpp b/src/snap.cpp
index ecf799cdc..ea6322e37 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -239,7 +239,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
// Snapping the mouse pointer instead of the constrained position of the knot allows
// to snap to things which don't intersect with the constraint line; this is basically
// then just a freesnap with the constraint applied afterwards
- // We'll only to this if we're dragging a single handle, and for example not when transforming an object in the selector tool
+ // We'll only do this if we're dragging a single handle, and for example not when transforming an object in the selector tool
result = freeSnap(p, bbox_to_snap);
if (result.getSnapped()) {
// only change the snap indicator if we really snapped to something
@@ -570,7 +570,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// be collected. Therefore we enforce that the first SnapCandidatePoint that is to be freeSnapped always
// has source_num == 0;
// TODO: This is a bit ugly so fix this; do we need sourcenum for anything else? if we don't then get rid
- // of it and explicitely communicate to the object snapper that this is a first point
+ // of it and explicitly communicate to the object snapper that this is a first point
if (first_free_snap) {
(*j).setSourceNum(0);
first_free_snap = false;
@@ -616,8 +616,8 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// and the scaling factor for the other direction should remain
// untouched (unless scaling is uniform of course)
for (int index = 0; index < 2; index++) {
- if (fabs(b[index]) > 1e-6) { // if SCALING CAN occur in this direction
- if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction
+ if (fabs(b[index]) > 1e-4) { // if SCALING CAN occur in this direction
+ if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-7) { // if SNAPPING DID occur in this direction
result[index] = a[index] / b[index]; // then calculate it!
}
// we might have left result[1-index] = Geom::infinity()
@@ -669,7 +669,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
case ROTATE:
// a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b
result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a));
- result[1] = result[1]; // how else should we store an angle in a point ;-)
+ result[1] = result[0]; // dummy value; how else should we store an angle in a point ;-)
if (Geom::L2(b) < 1e-9) { // points too close to the rotation center will not move. Don't try to snap these
// as they will always yield a perfect snap result if they're already snapped beforehand (e.g.
// when the transformation center has been snapped to a grid intersection in the selector tool)
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 115cb754a..1479acd69 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -117,12 +117,17 @@ gboolean SPGradient::isEquivalent(SPGradient *that)
if (this->getStopCount() != that->getStopCount()) { break; }
if (this->hasStops() != that->hasStops()) { break; }
if (!this->getVector() || !that->getVector()) { break; }
- if ( (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) ||
- (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) ||
- (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
- /* OK! */
+ if (this->isSwatch() != that->isSwatch()) { break; }
+ if ( this->isSwatch() ){
+ // drop down to check stops.
}
- else { break; }
+ else if (
+ (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) ||
+ (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) ||
+ (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
+ if(!this->isAligned(that))break;
+ }
+ else { break; } // this should never happen, some unhandled type of gradient
SPStop *as = this->getVector()->getFirstStop();
SPStop *bs = that->getVector()->getFirstStop();
@@ -156,6 +161,18 @@ gboolean SPGradient::isAligned(SPGradient *that)
{
bool status = FALSE;
+ /* Some gradients have coordinates/other values specified, some don't.
+ yes/yes check the coordinates/other values
+ no/no aligned (because both have all default values)
+ yes/no not aligned
+ no/yes not aligned
+ It is NOT safe to just compare the computed values because if that field has
+ not been set the computed value could be full of garbage.
+
+ In theory the yes/no and no/yes cases could be aligned if the specified value
+ matches the default value.
+ */
+
while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function
if(this->gradientTransform_set != that->gradientTransform_set) { break; }
if(this->gradientTransform_set &&
@@ -164,31 +181,45 @@ gboolean SPGradient::isAligned(SPGradient *that)
SPLinearGradient *sg=SP_LINEARGRADIENT(this);
SPLinearGradient *tg=SP_LINEARGRADIENT(that);
- if( !sg->x1._set || !tg->x1._set || // assume that if these are set so will be all the others
- (sg->x1.computed != tg->x1.computed) ||
- (sg->y1.computed != tg->y1.computed) ||
- (sg->x2.computed != tg->x2.computed) ||
- (sg->y2.computed != tg->y2.computed)
- ) { break; }
+ if( sg->x1._set != tg->x1._set) { break; }
+ if( sg->y1._set != tg->y1._set) { break; }
+ if( sg->x2._set != tg->x2._set) { break; }
+ if( sg->y2._set != tg->y2._set) { break; }
+ if( sg->x1._set && sg->y1._set && sg->x2._set && sg->y2._set) {
+ if( (sg->x1.computed != tg->x1.computed) ||
+ (sg->y1.computed != tg->y1.computed) ||
+ (sg->x2.computed != tg->x2.computed) ||
+ (sg->y2.computed != tg->y2.computed) ) { break; }
+ } else if( sg->x1._set || sg->y1._set || sg->x2._set || sg->y2._set) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else if (SP_IS_RADIALGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) {
SPRadialGradient *sg=SP_RADIALGRADIENT(this);
SPRadialGradient *tg=SP_RADIALGRADIENT(that);
- if( !sg->cx._set || !tg->cx._set || // assume that if these are set so will be all the others
- (sg->cx.computed != tg->cx.computed) ||
- (sg->cy.computed != tg->cy.computed) ||
- (sg->r.computed != tg->r.computed ) ||
- (sg->fx.computed != tg->fx.computed) ||
- (sg->fy.computed != tg->fy.computed)
- ) { break; }
+
+ if( sg->cx._set != tg->cx._set) { break; }
+ if( sg->cy._set != tg->cy._set) { break; }
+ if( sg->r._set != tg->r._set) { break; }
+ if( sg->fx._set != tg->fx._set) { break; }
+ if( sg->fy._set != tg->fy._set) { break; }
+ if( sg->cx._set && sg->cy._set && sg->fx._set && sg->fy._set && sg->r._set) {
+ if( (sg->cx.computed != tg->cx.computed) ||
+ (sg->cy.computed != tg->cy.computed) ||
+ (sg->r.computed != tg->r.computed ) ||
+ (sg->fx.computed != tg->fx.computed) ||
+ (sg->fy.computed != tg->fy.computed) ) { break; }
+ } else if( sg->cx._set || sg->cy._set || sg->fx._set || sg->fy._set || sg->r._set ) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else if (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that)) {
SPMeshGradient *sg=SP_MESHGRADIENT(this);
SPMeshGradient *tg=SP_MESHGRADIENT(that);
- if( !sg->x._set || !tg->x._set ||
- !sg->y._set || !tg->y._set ||
- (sg->x.computed != tg->x.computed) ||
- (sg->y.computed != tg->y.computed)
- ) { break; }
+ if( sg->x._set != !tg->x._set) { break; }
+ if( sg->y._set != !tg->y._set) { break; }
+ if( sg->x._set && sg->y._set) {
+ if( (sg->x.computed != tg->x.computed) ||
+ (sg->y.computed != tg->y.computed) ) { break; }
+ } else if( sg->x._set || sg->y._set) { break; } // some mix of set and not set
+ // none set? assume aligned and fall through
} else {
break;
}
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 5818054a7..15206d446 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -50,8 +50,6 @@
#include <algorithm>
/* LPEItem base class */
-static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
-
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
@@ -115,7 +113,7 @@ void SPLPEItem::set(unsigned int key, gchar const* value) {
this->current_path_effect = NULL;
// Disable the path effects while populating the LPE list
- sp_lpe_item_enable_path_effects(this, false);
+ enablePathEffects(false);
// disconnect all modified listeners:
for ( std::list<sigc::connection>::iterator mod_it = this->lpe_modified_connection_list->begin();
@@ -168,7 +166,7 @@ void SPLPEItem::set(unsigned int key, gchar const* value) {
}
}
- sp_lpe_item_enable_path_effects(this, true);
+ enablePathEffects(true);
}
break;
@@ -409,7 +407,7 @@ void SPLPEItem::addPathEffect(gchar *value, bool reset)
sp_lpe_item_update_patheffect(this, false, true);
// Disable the path effects while preparing the new lpe
- sp_lpe_item_enable_path_effects(this, false);
+ enablePathEffects(false);
// Add the new reference to the list of LPE references
HRefList hreflist;
@@ -446,7 +444,7 @@ void SPLPEItem::addPathEffect(gchar *value, bool reset)
}
//Enable the path effects now that everything is ready to apply the new path effect
- sp_lpe_item_enable_path_effects(this, true);
+ enablePathEffects(true);
// Apply the path effect
sp_lpe_item_update_patheffect(this, true, true);
@@ -958,24 +956,6 @@ bool SPLPEItem::forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users)
return forked;
}
-// Enable or disable the path effects of the item.
-// The counter allows nested calls
-static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable)
-{
- if (enable) {
- lpeitem->path_effects_enabled++;
- }
- else {
- lpeitem->path_effects_enabled--;
- }
-}
-
-// Are the path effects enabled on this item ?
-bool SPLPEItem::pathEffectsEnabled() const
-{
- return path_effects_enabled > 0;
-}
-
/*
Local Variables:
mode:c++
diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h
index 3e858748d..2bde25be8 100644
--- a/src/sp-lpe-item.h
+++ b/src/sp-lpe-item.h
@@ -39,11 +39,13 @@ namespace LivePathEffect{
typedef std::list<Inkscape::LivePathEffect::LPEObjectReference *> PathEffectList;
class SPLPEItem : public SPItem {
+private:
+ mutable bool path_effects_enabled; // (mutable because preserves logical const-ness)
+
public:
- SPLPEItem();
- virtual ~SPLPEItem();
+ SPLPEItem();
+ virtual ~SPLPEItem();
- int path_effects_enabled;
PathEffectList* path_effect_list;
std::list<sigc::connection> *lpe_modified_connection_list; // this list contains the connections for listening to lpeobject parameter changes
@@ -72,7 +74,8 @@ public:
bool performPathEffect(SPCurve *curve);
- bool pathEffectsEnabled() const;
+ void enablePathEffects(bool enable) const { path_effects_enabled = enable; }; // (const because logically const)
+ bool pathEffectsEnabled() const { return path_effects_enabled; };
bool hasPathEffect() const;
bool hasPathEffectOfType(int const type) const;
bool hasPathEffectRecursive() const;
diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp
index 121773b6d..a66855b2a 100644
--- a/src/ui/dialog/aboutbox.cpp
+++ b/src/ui/dialog/aboutbox.cpp
@@ -442,7 +442,7 @@ void AboutBox::initStrings() {
*/
gchar const *allTranslators =
"3ARRANO.com <3arrano@3arrano.com>, 2005.\n"
-"Adib Taraben <theadib@googlemail.com>, 2004.\n"
+"Adib Taraben <theadib@gmail.com>, 2004.\n"
"Alan Monfort <alan.monfort@free.fr>, 2009-2010.\n"
"Alastair McKinstry <mckinstry@computer.org>, 2000.\n"
"Aleksandar Urošević <urke@users.sourceforge.net>, 2004-2006.\n"
diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp
index 8c0a4dc66..72217c729 100644
--- a/src/ui/dialog/grid-arrange-tab.cpp
+++ b/src/ui/dialog/grid-arrange-tab.cpp
@@ -708,7 +708,7 @@ GridArrangeTab::GridArrangeTab(ArrangeDialog *parent)
HorizAlign = prefs->getInt("/dialogs/gridtiler/HorizAlign", 1);
// Anchor selection widget
- AlignLabel.set_label("Alignment:");
+ AlignLabel.set_label(_("Alignment:"));
AlignLabel.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
AlignmentSelector.setAlignment(HorizAlign, VertAlign);
AlignmentSelector.on_selectionChanged().connect(sigc::mem_fun(*this, &GridArrangeTab::Align_changed));
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index b6095fa8b..f1a29e971 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -1468,7 +1468,7 @@ void InkscapePreferences::initPageBitmaps()
_page_bitmaps.add_group_header( _("Render"));
// rendering outlines for pixmap image tags
_rendering_image_outline.init( _("Images in Outline Mode"), "/options/rendering/imageinoutlinemode", false);
- _page_bitmaps.add_line(false, _(""), _rendering_image_outline, "", _("When active will render images while in outline mode instead of a red box with an x. This is useful for manual tracing."));
+ _page_bitmaps.add_line(false, "", _rendering_image_outline, "", _("When active will render images while in outline mode instead of a red box with an x. This is useful for manual tracing."));
this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS);
}
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index 2c85874bc..feeb68288 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -277,21 +277,13 @@ void MeasureTool::finish() {
// return ret;
//}
-static bool GeomPointSortPredicate(const Geom::Point& p1, const Geom::Point& p2)
+static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<double> &intersections)
{
- if (p1[Geom::Y] == p2[Geom::Y]) {
- return p1[Geom::X] < p2[Geom::X];
- } else {
- return p1[Geom::Y] < p2[Geom::Y];
- }
-}
-static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<Geom::Point> &intersections)
-{
curve->transform(item->i2doc_affine());
-
// Find all intersections of the control-line with this shape
Geom::CrossingSet cs = Geom::crossings(lineseg, curve->get_pathvector());
+ Geom::delete_duplicates(cs[0]);
// Reconstruct and store the points of intersection
for (Geom::Crossings::const_iterator m = cs[0].begin(); m != cs[0].end(); ++m) {
@@ -304,10 +296,11 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom:
item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) ||
((*m).ta + eps < 1 &&
item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) {
- intersections.push_back(intersection);
+ intersections.push_back((*m).ta);
}
#else
- intersections.push_back(lineseg[0].pointAt((*m).ta));
+ intersections.push_back((*m).ta);
+
#endif
}
}
@@ -441,28 +434,20 @@ bool MeasureTool::root_handler(GdkEvent* event) {
points.push_back(desktop->d2w(start_point + (i / NPOINTS) * (end_point - start_point)));
}
-// TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
-// with the measurement line, instead of interpolating? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
-// That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
+ // TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
+ // with the measurement line, instead of interpolating over 800 points? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
+ // That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
+
+ // TODO switch to a different variable name. The single letter 'l' is easy to misread.
//select elements crossed by line segment:
GSList *items = sp_desktop_document(desktop)->getItemsAtPoints(desktop->dkey, points);
- std::vector<Geom::Point> intersections;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool ignore_1st_and_last = prefs->getBool("/tools/measure/ignore_1st_and_last", true);
-
- if (!ignore_1st_and_last) {
- intersections.push_back(desktop->dt2doc(start_point));
- }
-
- std::vector<LabelPlacement> placements;
-
- // TODO switch to a different variable name. The single letter 'l' is easy to misread.
+ std::vector<double> intersection_times;
for (GSList *l = items; l != NULL; l = l->next) {
SPItem *item = static_cast<SPItem*>(l->data);
if (SP_IS_SHAPE(item)) {
- calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersections);
+ calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times);
} else {
if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
@@ -486,7 +471,7 @@ bool MeasureTool::root_handler(GdkEvent* event) {
curve->transform(item->i2doc_affine());
- calculate_intersections(desktop, item, lineseg, curve, intersections);
+ calculate_intersections(desktop, item, lineseg, curve, intersection_times);
if (iter == te_get_layout(item)->end()) {
break;
@@ -496,13 +481,10 @@ bool MeasureTool::root_handler(GdkEvent* event) {
}
}
- if (!ignore_1st_and_last) {
- intersections.push_back(desktop->dt2doc(end_point));
- }
-
- //sort intersections
- if (intersections.size() > 2) {
- std::sort(intersections.begin(), intersections.end(), GeomPointSortPredicate);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
+ intersection_times.push_back(0);
+ intersection_times.push_back(1);
}
Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
@@ -516,6 +498,13 @@ bool MeasureTool::root_handler(GdkEvent* event) {
Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point)));
Geom::Point normal = desktop->w2d(windowNormal);
+ std::vector<Geom::Point> intersections;
+ std::sort(intersection_times.begin(), intersection_times.end());
+ for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) {
+ intersections.push_back(lineseg[0].pointAt(*iter_t));
+ }
+
+ std::vector<LabelPlacement> placements;
for (size_t idx = 1; idx < intersections.size(); ++idx) {
LabelPlacement placement;
placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index f8243fb7f..0d8a2668b 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -538,6 +538,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
ret = true;
} else if (bevent.button == 3 && this->npoints != 0) {
// right click - finish path
+ this->ea = NULL; // unset end anchor if set (otherwise crashes)
this->_finish(false);
ret = true;
}
@@ -1202,6 +1203,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
if (this->npoints != 0) {
+ this->ea = NULL; // unset end anchor if set (otherwise crashes)
this->_finish(false);
ret = true;
}
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 3d6f73ef1..939546f78 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -314,8 +314,8 @@ static gchar const * ui_descr =
" <toolitem action='SprayModeAction' />"
" <separator />"
" <toolitem action='SprayWidthAction' />"
- " <toolitem action='SprayPressureAction' />"
" <toolitem action='SprayPopulationAction' />"
+ " <toolitem action='SprayPressureAction' />"
" <separator />"
" <toolitem action='SprayRotationAction' />"
" <toolitem action='SprayScaleAction' />"
diff --git a/src/xml/helper-observer.cpp b/src/xml/helper-observer.cpp
index c54dd8e74..957f3df0a 100644
--- a/src/xml/helper-observer.cpp
+++ b/src/xml/helper-observer.cpp
@@ -5,25 +5,34 @@ namespace XML {
// Very simple observer that just emits a signal if anything happens to a node
SignalObserver::SignalObserver()
- : _oldsel(0)
+ : _oldsel(NULL)
{}
+SignalObserver::~SignalObserver()
+{
+ set(NULL); // if _oldsel!=nullptr, remove observer and decrease refcount
+}
+
// Add this observer to the SPObject and remove it from any previous object
void SignalObserver::set(SPObject* o)
{
// XML Tree being used direcly in this function in the following code
// while it shouldn't be
+ // Pointer to object is stored, so refcounting should be increased/decreased
if(_oldsel) {
if (_oldsel->getRepr()) {
_oldsel->getRepr()->removeObserver(*this);
}
+ sp_object_unref(_oldsel);
+ _oldsel = NULL;
}
if(o) {
if (o->getRepr()) {
o->getRepr()->addObserver(*this);
+ sp_object_ref(o);
+ _oldsel = o;
}
}
- _oldsel = o;
}
void SignalObserver::notifyChildAdded(XML::Node&, XML::Node&, XML::Node*)
diff --git a/src/xml/helper-observer.h b/src/xml/helper-observer.h
index e7881cd4d..2f70ba792 100644
--- a/src/xml/helper-observer.h
+++ b/src/xml/helper-observer.h
@@ -17,6 +17,7 @@ namespace Inkscape {
{
public:
SignalObserver();
+ ~SignalObserver();
// Add this observer to the SPObject and remove it from any previous object
void set(SPObject* o);