summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/2geom/sbasis-to-bezier.cpp29
-rw-r--r--src/desktop.cpp1
-rw-r--r--src/display/sp-canvas.cpp5
-rw-r--r--src/display/sp-canvas.h1
-rw-r--r--src/document.cpp50
-rw-r--r--src/document.h15
-rw-r--r--src/extension/implementation/xslt.cpp2
-rw-r--r--src/extension/internal/emf-print.cpp18
-rw-r--r--src/helper/png-write.cpp2
-rw-r--r--src/line-geometry.cpp16
-rw-r--r--src/main.cpp30
-rw-r--r--src/selection-chemistry.cpp5
-rw-r--r--src/sp-image.cpp89
-rw-r--r--src/sp-image.h5
-rw-r--r--src/sp-item-transform.cpp22
-rw-r--r--src/ui/dialog/template-load-tab.cpp7
-rw-r--r--src/ui/tools/text-tool.cpp4
-rw-r--r--src/ui/tools/tool-base.cpp7
-rw-r--r--src/ui/tools/tool-base.h1
-rw-r--r--src/uri-references.cpp24
-rw-r--r--src/uri.cpp24
-rw-r--r--src/uri.h3
-rw-r--r--src/widgets/icon.cpp4
-rw-r--r--src/xml/repr-io.cpp5
24 files changed, 229 insertions, 140 deletions
diff --git a/src/2geom/sbasis-to-bezier.cpp b/src/2geom/sbasis-to-bezier.cpp
index bd88f93c0..0525be04b 100644
--- a/src/2geom/sbasis-to-bezier.cpp
+++ b/src/2geom/sbasis-to-bezier.cpp
@@ -242,24 +242,38 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
// calculate Bezier control arms
- if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > 1.e-5) { // general case : fit mid fxn value
+ if ((std::abs(xprime[0]) < EPSILON) && (std::abs(yprime[0]) < EPSILON)
+ && ((std::abs(xprime[1]) > EPSILON) || (std::abs(yprime[1]) > EPSILON))) { // degenerate handle at 0 : use distance of closest approach
+ numer = midx*xprime[1] + midy*yprime[1];
+ denom = 3.0*(xprime[1]*xprime[1] + yprime[1]*yprime[1]);
+ delx[0] = 0;
+ dely[0] = 0;
+ delx[1] = -xprime[1]*numer/denom;
+ dely[1] = -yprime[1]*numer/denom;
+ } else if ((std::abs(xprime[1]) < EPSILON) && (std::abs(yprime[1]) < EPSILON)
+ && ((std::abs(xprime[0]) > EPSILON) || (std::abs(yprime[0]) > EPSILON))) { // degenerate handle at 1 : ditto
+ numer = midx*xprime[0] + midy*yprime[0];
+ denom = 3.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
+ delx[0] = xprime[0]*numer/denom;
+ dely[0] = yprime[0]*numer/denom;
+ delx[1] = 0;
+ dely[1] = 0;
+ } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > EPSILON) { // general case : fit mid fxn value
denom = xprime[1]*yprime[0] - yprime[1]*xprime[0];
for (int i = 0; i < 2; ++i) {
numer = xprime[1 - i]*midy - yprime[1 - i]*midx;
delx[i] = xprime[i]*numer/denom/3;
dely[i] = yprime[i]*numer/denom/3;
}
- }
- else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach
+ } else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach
numer = midx*xprime[0] + midy*yprime[0];
denom = 6.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
delx[0] = xprime[0]*numer/denom;
dely[0] = yprime[0]*numer/denom;
delx[1] = -delx[0];
dely[1] = -dely[0];
- }
- else { // anti-symmetric case : fit mid slope
- // calculate slope at t = 0.5
+ } else { // anti-symmetric case : fit mid slope
+ // calculate slope at t = 0.5
midx = 0;
div = 1;
for (size_t i = 0; i < sb[X].size(); ++i) {
@@ -279,8 +293,7 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
delx[i] = xprime[0]*numer/denom;
dely[i] = yprime[0]*numer/denom;
}
- }
- else { // linear case
+ } else { // linear case
for (int i = 0; i < 2; ++i) {
delx[i] = (bz[3][X] - bz[0][X])/3;
dely[i] = (bz[3][Y] - bz[0][Y])/3;
diff --git a/src/desktop.cpp b/src/desktop.cpp
index bf3b70d43..364b5e930 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -668,6 +668,7 @@ void SPDesktop::set_event_context2(const std::string& toolName)
old_tool->finish();
delete old_tool;
} else {
+ _event_context_changed_signal.emit(this, event_context);
return;
}
}
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 455f628bc..d9640f763 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1545,6 +1545,11 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event)
default:
break;
}
+ // Block Undo and Redo while we drag /anything/
+ if(event->type == GDK_BUTTON_PRESS && event->button.button == 1)
+ canvas->is_dragging = true;
+ else if(event->type == GDK_BUTTON_RELEASE)
+ canvas->is_dragging = false;
// Choose where we send the event
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index b570b739e..72ae4b6bc 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -124,6 +124,7 @@ struct SPCanvas {
SPCanvasItem *root;
+ bool is_dragging;
double dx0;
double dy0;
int x0;
diff --git a/src/document.cpp b/src/document.cpp
index e56adee68..634462001 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -108,7 +108,8 @@ SPDocument::SPDocument() :
_collection_queue(0),
oldSignalsConnected(false),
current_persp3d(NULL),
- current_persp3d_impl(NULL)
+ current_persp3d_impl(NULL),
+ _parent_document(NULL)
{
// Penalise libavoid for choosing paths with needless extra segments.
// This results in much better looking orthogonal connector paths.
@@ -314,7 +315,8 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc,
gchar const *uri,
gchar const *base,
gchar const *name,
- unsigned int keepalive)
+ unsigned int keepalive,
+ SPDocument *parent)
{
SPDocument *document = new SPDocument();
@@ -325,6 +327,10 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc,
document->rdoc = rdoc;
document->rroot = rroot;
+ if (parent) {
+ document->_parent_document = parent;
+ parent->_child_documents.push_back(document);
+ }
if (document->uri){
g_free(document->uri);
@@ -470,10 +476,43 @@ SPDocument *SPDocument::createDoc(Inkscape::XML::Document *rdoc,
}
/**
+ * Fetches a document and attaches it to the current document as a child href
+ */
+SPDocument *SPDocument::createChildDoc(std::string const &uri)
+{
+ SPDocument *parent = this;
+ SPDocument *document = NULL;
+
+ while(parent != NULL && document == NULL) {
+ // Check myself and any parents int he chain
+ if(uri == parent->getURI()) {
+ document = parent;
+ break;
+ }
+ // Then check children of those.
+ boost::ptr_list<SPDocument>::iterator iter;
+ for (iter = parent->_child_documents.begin();
+ iter != parent->_child_documents.end(); ++iter) {
+ if(uri == iter->getURI()) {
+ document = &*iter;
+ break;
+ }
+ }
+ parent = parent->_parent_document;
+ }
+
+ // Load a fresh document from the svg source.
+ if(!document) {
+ const char *path = uri.c_str();
+ document = createNewDoc(path, false, false, this);
+ }
+ return document;
+}
+/**
* Fetches document from URI, or creates new, if NULL; public document
* appears in document list.
*/
-SPDocument *SPDocument::createNewDoc(gchar const *uri, unsigned int keepalive, bool make_new)
+SPDocument *SPDocument::createNewDoc(gchar const *uri, unsigned int keepalive, bool make_new, SPDocument *parent)
{
SPDocument *doc;
Inkscape::XML::Document *rdoc;
@@ -518,7 +557,7 @@ SPDocument *SPDocument::createNewDoc(gchar const *uri, unsigned int keepalive, b
//# These should be set by now
g_assert(name);
- doc = createDoc(rdoc, uri, base, name, keepalive);
+ doc = createDoc(rdoc, uri, base, name, keepalive, parent);
g_free(base);
g_free(name);
@@ -539,7 +578,7 @@ SPDocument *SPDocument::createNewDocFromMem(gchar const *buffer, gint length, un
// TODO fixme: destroy document
} else {
Glib::ustring name = Glib::ustring::compose( _("Memory document %1"), ++doc_mem_count );
- doc = createDoc(rdoc, NULL, NULL, name.c_str(), keepalive);
+ doc = createDoc(rdoc, NULL, NULL, name.c_str(), keepalive, NULL);
}
}
@@ -602,6 +641,7 @@ void SPDocument::setWidth(const Inkscape::Util::Quantity &width)
root->updateRepr();
}
+
Inkscape::Util::Quantity SPDocument::getHeight() const
{
g_return_val_if_fail(this->priv != NULL, Inkscape::Util::Quantity(0.0, unit_table.getUnit("")));
diff --git a/src/document.h b/src/document.h
index cc565e3aa..e5567d3b6 100644
--- a/src/document.h
+++ b/src/document.h
@@ -25,6 +25,7 @@
#include "gc-finalized.h"
#include "gc-anchored.h"
#include <glibmm/ustring.h>
+#include <boost/ptr_container/ptr_list.hpp>
#include <vector>
namespace Avoid {
@@ -202,6 +203,11 @@ private:
Persp3D *current_persp3d; /**< Currently 'active' perspective (to which, e.g., newly created boxes are attached) */
Persp3DImpl *current_persp3d_impl;
+ // A list of svg documents being used or shown within this document
+ boost::ptr_list<SPDocument> _child_documents;
+ // Conversely this is a parent document because this is a child.
+ SPDocument *_parent_document;
+
public:
sigc::connection connectReconstructionStart(ReconstructionStart::slot_type slot);
sigc::connection connectReconstructionFinish(ReconstructionFinish::slot_type slot);
@@ -216,16 +222,19 @@ public:
sigc::connection connectResourcesChanged(const gchar *key, SPDocument::ResourcesChangedSignal::slot_type slot);
void fitToRect(Geom::Rect const &rect, bool with_margins = false);
- static SPDocument *createNewDoc(const gchar *uri, unsigned int keepalive, bool make_new = false);
+ static SPDocument *createNewDoc(const gchar *uri, unsigned int keepalive,
+ bool make_new = false, SPDocument *parent=NULL );
static SPDocument *createNewDocFromMem(const gchar *buffer, gint length, unsigned int keepalive);
+ SPDocument *createChildDoc(std::string const &uri);
/**
* Returns the bottommost item from the list which is at the point, or NULL if none.
*/
static SPItem *getItemFromListAtPointBottom(unsigned int dkey, SPGroup *group, const GSList *list, Geom::Point const &p, bool take_insensitive = false);
- // ToDo - Merge createDoc with createNewDoc
- static SPDocument *createDoc(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive);
+ static SPDocument *createDoc(Inkscape::XML::Document *rdoc, gchar const *uri,
+ gchar const *base, gchar const *name, unsigned int keepalive,
+ SPDocument *parent);
SPDocument *doRef();
SPDocument *doUnref();
diff --git a/src/extension/implementation/xslt.cpp b/src/extension/implementation/xslt.cpp
index 9dd9c83ee..bcea06cb5 100644
--- a/src/extension/implementation/xslt.cpp
+++ b/src/extension/implementation/xslt.cpp
@@ -177,7 +177,7 @@ XSLT::open(Inkscape::Extension::Input */*module*/, gchar const *filename)
}
g_free(s);
- SPDocument * doc = SPDocument::createDoc(rdoc, filename, base, name, true);
+ SPDocument * doc = SPDocument::createDoc(rdoc, filename, base, name, true, NULL);
g_free(base); g_free(name);
diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp
index 3c27ac1b8..2680718cf 100644
--- a/src/extension/internal/emf-print.cpp
+++ b/src/extension/internal/emf-print.cpp
@@ -814,10 +814,10 @@ Geom::Path PrintEmf::pathv_to_simple_polygon(Geom::PathVector const &pathv, int
return(bad);
}
P1_lead = cit->finalPoint();
- if(Geom::are_near(P1_lead,P1))continue; // duplicate points at the same coordinate
+ if(Geom::are_near(P1_lead, P1, 1e-5))continue; // duplicate points at the same coordinate
v1 = unit_vector(P1 - P1_trail);
v2 = unit_vector(P1_lead - P1 );
- if(Geom::are_near(dot(v1,v2),1.0)){ // P1 is within a straight line
+ if(Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ // P1 is within a straight line
P1 = P1_lead;
continue;
}
@@ -867,7 +867,7 @@ Geom::Path PrintEmf::pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect,
P1_lead = cit->finalPoint();
v1 = unit_vector(P1 - P1_trail);
v2 = unit_vector(P1_lead - P1 );
- if(!Geom::are_near(dot(v1,v2),0.0))break; // P1 is center of a turn that is not 90 degrees
+ if(!Geom::are_near(dot(v1,v2), 0.0, 1e-5))break; // P1 is center of a turn that is not 90 degrees
P1_trail = P1;
P1 = P1_lead;
vertex_count++;
@@ -891,12 +891,12 @@ int PrintEmf::vector_rect_alignment(double angle, Geom::Point vtest){
int stat = 0;
Geom::Point v1 = Geom::unit_vector(vtest); // unit vector to test alignment
Geom::Point v2 = Geom::Point(1,0) * Geom::Rotate(-angle); // unit horizontal side (sign change because Y increases DOWN)
- if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 1; }
- else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 2; }
+ if( Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ stat = 1; }
+ else if(Geom::are_near(dot(v1,v2),-1.0, 1e-5)){ stat = 2; }
if(!stat){
v2 = Geom::Point(0,1) * Geom::Rotate(-angle); // unit vertical side
- if( Geom::are_near(dot(v1,v2), 1.0)){ stat = 3; }
- else if(Geom::are_near(dot(v1,v2),-1.0)){ stat = 4; }
+ if( Geom::are_near(dot(v1,v2), 1.0, 1e-5)){ stat = 3; }
+ else if(Geom::are_near(dot(v1,v2),-1.0, 1e-5)){ stat = 4; }
}
return(stat);
}
@@ -1091,7 +1091,6 @@ unsigned int PrintEmf::fill(
U_TRIVERTEX ut[2];
U_GRADIENT4 ug4;
U_RECTL rcb;
- Geom::Affine tf2;
U_XFORM tmpTransform;
double wRect, hRect;
@@ -1107,7 +1106,8 @@ unsigned int PrintEmf::fill(
Actual gradientfill records are either this entire rectangle or slices of it as defined by the stops.
*/
- tf2 = Geom::Rotate(-angle);
+ Geom::Affine tf2 = Geom::Rotate(-angle); // the rectangle may be drawn skewed to the coordinate system
+ tf2 *= tf; // the coordinate system of the rectangular path may be rotated
tmpTransform.eM11 = tf2[0];
tmpTransform.eM12 = tf2[1];
tmpTransform.eM21 = tf2[2];
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index b8b815b4c..a16fe8e12 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -142,7 +142,7 @@ sp_png_write_rgba_striped(SPDocument *doc,
Inkscape::IO::dump_fopen_call(filename, "M");
fp = Inkscape::IO::fopen_utf8name(filename, "wb");
- g_return_val_if_fail(fp != NULL, false);
+ if(fp == NULL) return false;
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
diff --git a/src/line-geometry.cpp b/src/line-geometry.cpp
index e9f07f96f..982762a12 100644
--- a/src/line-geometry.cpp
+++ b/src/line-geometry.cpp
@@ -28,8 +28,9 @@ namespace Box3D {
* of the segment. Otherwise interpret it as the direction of the line.
* FIXME: Think of a better way to distinguish between the two constructors of lines.
*/
-Line::Line(Geom::Point const &start, Geom::Point const &vec, bool is_endpoint) {
- pt = start;
+Line::Line(Geom::Point const &start, Geom::Point const &vec, bool is_endpoint):
+ pt(start)
+{
if (is_endpoint)
v_dir = vec - start;
else
@@ -38,11 +39,12 @@ Line::Line(Geom::Point const &start, Geom::Point const &vec, bool is_endpoint) {
d0 = Geom::dot(normal, pt);
}
-Line::Line(Line const &line) {
- pt = line.pt;
- v_dir = line.v_dir;
- normal = line.normal;
- d0 = line.d0;
+Line::Line(Line const &line):
+ pt(line.pt),
+ v_dir(line.v_dir),
+ normal(line.normal),
+ d0(line.d0)
+{
}
Line &Line::operator=(Line const &line) {
diff --git a/src/main.cpp b/src/main.cpp
index 079944af6..25f813c2b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1515,7 +1515,7 @@ static int sp_do_export_png(SPDocument *doc)
// set filename and dpi from options, if not yet set from the hints
if (filename.empty()) {
- if (!sp_export_png) {
+ if (!sp_export_png || sp_export_png[0] == '\0') {
g_warning ("No export filename given and no filename hint. Nothing exported.");
return 1;
}
@@ -1632,10 +1632,13 @@ static int sp_do_export_png(SPDocument *doc)
g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi);
- g_print("Bitmap saved as: %s\n", filename.c_str());
-
if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
- sp_export_png_file(doc, path.c_str(), area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
+ if( sp_export_png_file(doc, path.c_str(), area, width, height, dpi,
+ dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL) == 1 ) {
+ g_print("Bitmap saved as: %s\n", filename.c_str());
+ } else {
+ g_warning("Bitmap failed to save to: %s", filename.c_str());
+ }
} else {
g_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX);
}
@@ -1771,6 +1774,11 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
}
}
+ if(!uri || uri[0] == '\0') {
+ g_warning ("No export filename given. Nothing exported.");
+ return 0;
+ }
+
//check if specified directory exists
if (!Inkscape::IO::file_directory_exists(uri)) {
g_warning("File path \"%s\" includes directory that doesn't exist.\n", uri);
@@ -1789,7 +1797,11 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
? "PostScript level 3" : "PostScript level 2");
}
- (*i)->save(doc, uri);
+ try {
+ (*i)->save(doc, uri);
+ } catch(...) {
+ g_warning("Failed to save pdf to: %s", uri);
+ }
return 0;
}
@@ -1837,6 +1849,10 @@ static int do_export_win_metafile_common(SPDocument* doc, gchar const* uri, char
static int do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
{
+ if(!uri || uri[0] == '\0') {
+ g_warning("No filename provided for emf export.");
+ return 0;
+ }
return do_export_win_metafile_common(doc, uri, mime);
}
@@ -1850,6 +1866,10 @@ static int do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
static int do_export_wmf(SPDocument* doc, gchar const* uri, char const* mime)
{
+ if(!uri || uri[0] == '\0') {
+ g_warning("No filename provided for wmf export.");
+ return 0;
+ }
return do_export_win_metafile_common(doc, uri, mime);
}
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 1957b9297..3082a2fe4 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -56,6 +56,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "sp-polyline.h"
#include "sp-line.h"
#include "text-editing.h"
+#include "display/sp-canvas.h"
#include "ui/tools/text-tool.h"
#include "ui/tools/connector-tool.h"
#include "sp-path.h"
@@ -1084,7 +1085,7 @@ void
sp_undo(SPDesktop *desktop, SPDocument *)
{
// No re/undo while dragging, too dangerous.
- if(desktop->getEventContext()->is_dragging) return;
+ if(desktop->getCanvas()->is_dragging) return;
if (!DocumentUndo::undo(sp_desktop_document(desktop))) {
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo."));
@@ -1095,7 +1096,7 @@ void
sp_redo(SPDesktop *desktop, SPDocument *)
{
// No re/undo while dragging, too dangerous.
- if(desktop->getEventContext()->is_dragging) return;
+ if(desktop->getCanvas()->is_dragging) return;
if (!DocumentUndo::redo(sp_desktop_document(desktop))) {
desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo."));
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index b08d6f9b0..f1ea737ff 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -76,7 +76,6 @@
static void sp_image_set_curve(SPImage *image);
-gchar const *sp_image_repr_read_filename(gchar const *href, gchar const *absref, gchar const *base );
static void sp_image_update_arenaitem (SPImage *img, Inkscape::DrawingImage *ai);
static void sp_image_update_canvas_image (SPImage *image);
@@ -170,8 +169,7 @@ void SPImage::release() {
this->href = NULL;
}
- delete this->pixbuf;
- this->pixbuf = NULL;
+ this->clear_image();
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
if (this->color_profile) {
@@ -329,29 +327,31 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) {
SPItem::update(ctx, flags);
if (flags & SP_IMAGE_HREF_MODIFIED_FLAG) {
- delete this->pixbuf;
- this->pixbuf = NULL;
+ this->clear_image();
if (this->href) {
Inkscape::Pixbuf *pixbuf = NULL;
+ gchar const* uri = this->getRepr()->attribute("xlink:href");
+
+ if(!uri) {
+ g_warning("Image tag has no valid href: %s", this->getId());
- gchar const* filename = sp_image_repr_read_filename (
- this->getRepr()->attribute("xlink:href"),
- this->getRepr()->attribute("sodipodi:absref"),
- doc->getBase());
-
- Inkscape::Pixbuf::create_from_data_uri(filename);
- if (strncmp (filename,"data:", 5) == 0) {
- filename += 5;
- pixbuf = Inkscape::Pixbuf::create_from_data_uri(filename);
- } else if(filename && g_str_has_suffix(filename, ".svg")) {
- // TODO: We want to deal with svg images properly. This
- // space allows us to do so later.
- g_warning("Including svg images tags is not yet supported.");
- } else if (filename) {
- pixbuf = Inkscape::Pixbuf::create_from_file(filename);
+ } else if (strncmp (uri, "data:", 5) == 0) {
+ uri += 5;
+ pixbuf = Inkscape::Pixbuf::create_from_data_uri(uri);
+
+ } else if(g_str_has_suffix(uri, ".svg")) {
+ SPDocument *doc = this->document->createChildDoc(uri);
+ if(doc) {
+ this->child = SP_ITEM(doc);
+ g_warning("Loaded document: %s", uri);
+ } else {
+ g_warning("Could not load svg for image tag: %s",this->getId());
+ }
+ } else {
+ pixbuf = Inkscape::Pixbuf::create_from_file(uri);
}
- if(!pixbuf) {
+ if(!pixbuf && !this->child) {
/* Nope: We do not find any valid pixmap file :-( */
pixbuf = new Inkscape::Pixbuf(
gdk_pixbuf_new_from_xpm_data((const gchar **) brokenimage_xpm));
@@ -527,6 +527,18 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) {
sp_image_update_canvas_image ((SPImage *) this);
}
+// Remove references to image or child objects.
+void SPImage::clear_image() {
+ if(this->pixbuf) {
+ delete this->pixbuf;
+ this->pixbuf = NULL;
+ }
+ if(this->child) {
+ this->detach(this->child);
+ this->child = NULL;
+ }
+}
+
void SPImage::modified(unsigned int flags) {
// SPItem::onModified(flags);
@@ -667,41 +679,6 @@ Inkscape::DrawingItem* SPImage::show(Inkscape::Drawing &drawing, unsigned int /*
return ai;
}
-gchar const *sp_image_repr_read_filename(gchar const *href, gchar const *absref, gchar const *base)
-{
- gchar const *filename = href;
-
- if (filename != NULL) {
- if (strncmp (filename,"file:",5) == 0) {
- filename = g_filename_from_uri(filename, NULL, NULL);
- } else if (strncmp (filename,"data:",5) == 0) {
- /* data URI - embedded image */
- return filename;
- } else if (!g_path_is_absolute (filename)) {
- /* try to load from relative pos combined with document base*/
- const gchar *docbase = base;
- if (!docbase) docbase = ".";
- filename = g_build_filename(docbase, filename, NULL);
- }
- }
-
- if (filename && g_file_test(filename, G_FILE_TEST_EXISTS) ) {
- return filename;
- }
-
- /* at last try to load from sp absolute path name */
- if (absref != NULL && g_file_test(absref, G_FILE_TEST_EXISTS)) {
- // using absref is outside of SVG rules, so we must at least warn the user
- if ( base != NULL && href != NULL ) {
- g_warning ("<image xlink:href=\"%s\"> did not resolve to a valid image file (base dir is %s), now trying sodipodi:absref=\"%s\"", href, base, absref);
- } else {
- g_warning ("xlink:href did not resolve to a valid image file, now trying sodipodi:absref=\"%s\"", absref);
- }
- return absref;
- }
- return NULL;
-}
-
/* We assert that realpixbuf is either NULL or identical size to pixbuf */
static void
sp_image_update_arenaitem (SPImage *image, Inkscape::DrawingImage *ai)
diff --git a/src/sp-image.h b/src/sp-image.h
index 3b7208487..ad4fd4d54 100644
--- a/src/sp-image.h
+++ b/src/sp-image.h
@@ -53,7 +53,10 @@ public:
gchar *color_profile;
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ // When image is a raster image, we use pixbuf
Inkscape::Pixbuf *pixbuf;
+ // When it's an svg file, we use an SPItem similar to sp-use
+ SPItem *child;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
virtual void release();
@@ -69,6 +72,8 @@ public:
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual Geom::Affine set_transform(Geom::Affine const &transform);
+private:
+ void clear_image();
};
/* Return duplicate of curve or NULL */
diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp
index 854fb9cd7..7fa591fee 100644
--- a/src/sp-item-transform.cpp
+++ b/src/sp-item-transform.cpp
@@ -144,13 +144,11 @@ Geom::Affine get_scale_transform_for_uniform_stroke(Geom::Rect const &bbox_visua
gdouble r1 = r0;
if ((fabs(w0 - stroke_x) < 1e-6) || w1 == 0) { // We have a vertical line at hand
- r1 = transform_stroke ? r0 * sqrt(h1/h0) : r0;
- scale_x = 1;
- scale_y = preserve ? h1/h0 : (h1 - r1)/(h0 - r0);
+ scale_y = h1/h0;
+ scale_x = transform_stroke ? 1 : scale_y;
} else if ((fabs(h0 - stroke_y) < 1e-6) || h1 == 0) { // We have a horizontal line at hand
- r1 = transform_stroke ? r0 * sqrt(w1/w0) : r0;
- scale_x = preserve ? w1/w0 : (w1 - r1)/(w0 - r0);
- scale_y = 1;
+ scale_x = w1/w0;
+ scale_y = transform_stroke ? 1 : scale_x;
} else { // We have a true 2D object at hand
if (transform_stroke && !preserve) {
/* Initial area of the geometric bounding box: A0 = (w0-r0)*(h0-r0)
@@ -297,13 +295,13 @@ Geom::Affine get_scale_transform_for_variable_stroke(Geom::Rect const &bbox_visu
gdouble r1w = r0w;
if ((fabs(w0 - r0w) < 1e-6) || w1 == 0) { // We have a vertical line at hand
- r1h = transform_stroke ? r0h * sqrt(h1/h0) : r0h;
- scale_x = 1;
- scale_y = preserve ? h1/h0 : (h1 - r1h)/(h0 - r0h);
+ scale_y = h1/h0;
+ scale_x = transform_stroke ? 1 : scale_y;
+ unbudge *= Geom::Translate (flip_x * 0.5 * (w1 - w0), 0); // compensate for the fact that this operation cannot be performed
} else if ((fabs(h0 - r0h) < 1e-6) || h1 == 0) { // We have a horizontal line at hand
- r1w = transform_stroke ? r0w * sqrt(w1/w0) : r0w;
- scale_x = preserve ? w1/w0 : (w1 - r1w)/(w0 - r0w);
- scale_y = 1;
+ scale_x = w1/w0;
+ scale_y = transform_stroke ? 1 : scale_x;
+ unbudge *= Geom::Translate (0, flip_y * 0.5 * (h1 - h0)); // compensate for the fact that this operation cannot be performed
} else { // We have a true 2D object at hand
if (transform_stroke && !preserve) {
/* Initial area of the geometric bounding box: A0 = (w0-r0w)*(h0-r0h)
diff --git a/src/ui/dialog/template-load-tab.cpp b/src/ui/dialog/template-load-tab.cpp
index 4f2d51ef7..6b1f4542f 100644
--- a/src/ui/dialog/template-load-tab.cpp
+++ b/src/ui/dialog/template-load-tab.cpp
@@ -220,12 +220,9 @@ TemplateLoadTab::TemplateData TemplateLoadTab::_processTemplateFile(const std::s
n = result.display_name.rfind(".svg");
result.display_name.replace(n, 4, 1, ' ');
- Inkscape::XML::Document *rdoc;
- rdoc = sp_repr_read_file(path.data(), SP_SVG_NS_URI);
- Inkscape::XML::Node *myRoot;
-
+ Inkscape::XML::Document *rdoc = sp_repr_read_file(path.data(), SP_SVG_NS_URI);
if (rdoc){
- myRoot = rdoc->root();
+ Inkscape::XML::Node *myRoot = rdoc->root();
if (strcmp(myRoot->name(), "svg:svg") != 0){ // Wrong file format
return result;
}
diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp
index c73164c09..9b5ab1016 100644
--- a/src/ui/tools/text-tool.cpp
+++ b/src/ui/tools/text-tool.cpp
@@ -1335,7 +1335,7 @@ bool sp_text_paste_inline(ToolBase *ec)
paste_string_uchar == 0x00000009 ||
paste_string_uchar == 0x0000000A ||
paste_string_uchar == 0x0000000D) {
- itr++;
+ ++itr;
} else {
itr = text.erase(itr);
}
@@ -1637,7 +1637,7 @@ static void sp_text_context_update_text_selection(TextTool *tc)
// the selection update (can't do both atomically, alas)
if (!tc->desktop) return;
- for (std::vector<SPCanvasItem*>::iterator it = tc->text_selection_quads.begin() ; it != tc->text_selection_quads.end() ; it++) {
+ for (std::vector<SPCanvasItem*>::iterator it = tc->text_selection_quads.begin() ; it != tc->text_selection_quads.end() ; ++it) {
sp_canvas_item_hide(*it);
sp_canvas_item_destroy(*it);
}
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 3b51147e0..cc028724a 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -98,7 +98,6 @@ ToolBase::ToolBase() {
this->hot_x = 0;
this->yp = 0;
this->within_tolerance = false;
- this->is_dragging = false;
this->tolerance = 0;
//this->key = 0;
this->item_to_select = 0;
@@ -979,14 +978,8 @@ gint sp_event_context_root_handler(ToolBase * event_context,
gint sp_event_context_virtual_root_handler(ToolBase * event_context, GdkEvent * event) {
gint ret = false;
if (event_context) {
- if(event->type == GDK_BUTTON_PRESS)
- event_context->is_dragging = true;
-
ret = event_context->root_handler(event);
set_event_location(event_context->desktop, event);
-
- if(event->type == GDK_BUTTON_RELEASE)
- event_context->is_dragging = false;
}
return ret;
}
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index ab8bd8caa..43edc4bd7 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -118,7 +118,6 @@ public:
gint xp, yp; ///< where drag started
gint tolerance;
- bool is_dragging; // Is a tool currently dragging something
bool within_tolerance; ///< are we still within tolerance of origin
diff --git a/src/uri-references.cpp b/src/uri-references.cpp
index 718b2d451..abe16ec9d 100644
--- a/src/uri-references.cpp
+++ b/src/uri-references.cpp
@@ -57,20 +57,18 @@ void URIReference::attach(const URI &uri) throw(BadURIException)
}
// The path contains references to seperate document files to load.
- const char *path = uri.getPath();
- if(path) {
- if(document != NULL) {
- // Calculate the absolute path from an available document
- std::string basePath = std::string( document->getBase() );
- std::string absPath = Glib::build_filename(basePath, std::string( path ) );
- path = absPath.c_str();
- }
- // TODO: This is inefficient because it will load the same svg file
- // many times if it's used many times. A global list of documents would
- // be useful for tracking linked items.
- document = SPDocument::createNewDoc(path, FALSE);
+ if(document && uri.getPath()) {
+ std::string base = std::string(document->getBase());
+ std::string path = uri.getFullPath(base);
+ if(!path.empty())
+ document = document->createChildDoc(path);
+ else
+ document = NULL;
+ }
+ if(!document) {
+ g_warning("Can't get document for referenced URI: %s", uri.toString());
+ return;
}
- g_return_if_fail(document != NULL);
gchar const *fragment = uri.getFragment();
if ( !uri.isRelative() || uri.getQuery() || !fragment ) {
diff --git a/src/uri.cpp b/src/uri.cpp
index de6a454ec..89f6f33e4 100644
--- a/src/uri.cpp
+++ b/src/uri.cpp
@@ -10,7 +10,9 @@
#include <glib.h>
#include "uri.h"
+#include <string>
#include <glibmm/ustring.h>
+#include <glibmm/miscutils.h>
namespace Inkscape {
@@ -133,6 +135,28 @@ gchar *URI::to_native_filename(gchar const* uri) throw(BadURIException)
filename = tmp.toNativeFilename();
return filename;
}
+/*
+ * Returns the absolute path to an existing file referenced in this URI,
+ * if the uri is data, the path is empty or the file doesn't exist, then
+ * an empty string is returned.
+ *
+ * Does not check if the returned path is the local document's path (local)
+ * and thus redundent. Caller is expected to check against the document's path.
+ */
+const std::string URI::getFullPath(std::string const base) const {
+ std::string path = std::string(_impl->getPath());
+ // Calculate the absolute path from an available base
+ if(!base.empty() && !path.empty() && path[0] != '/') {
+ path = Glib::build_filename(base, path);
+ }
+ // Check the existance of the file
+ if(! g_file_test(path.c_str(), G_FILE_TEST_EXISTS)
+ || g_file_test(path.c_str(), G_FILE_TEST_IS_DIR) ) {
+ path.clear();
+ }
+ return path;
+}
+
/* TODO !!! proper error handling */
gchar *URI::toNativeFilename() const throw(BadURIException) {
diff --git a/src/uri.h b/src/uri.h
index adcc76d6b..74820cb29 100644
--- a/src/uri.h
+++ b/src/uri.h
@@ -15,6 +15,7 @@
#include <exception>
#include <libxml/uri.h>
#include "bad-uri-exception.h"
+#include <string>
namespace Inkscape {
@@ -101,6 +102,8 @@ public:
static gchar *to_native_filename(gchar const* uri) throw(BadURIException);
+ const std::string getFullPath(std::string const base) const;
+
gchar *toNativeFilename() const throw(BadURIException);
/**
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index 92ebf32a8..a059c100c 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -1311,11 +1311,11 @@ guchar *IconImpl::load_svg_pixels(std::list<Glib::ustring> const &names,
}
static void addToIconSet(GdkPixbuf* pb, gchar const* name, GtkIconSize lsize, unsigned psize) {
- static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk");
Glib::RefPtr<Gtk::IconTheme> icon_theme = Gtk::IconTheme::get_default();
bool icon_found = icon_theme->has_icon(name);
if ( !icon_found ) {
Gtk::IconTheme::add_builtin_icon( name, psize, Glib::wrap(pb) );
+ static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk");
if (dump) {
g_message(" set in a builtin for %s:%d:%d", name, lsize, psize);
}
@@ -1355,7 +1355,6 @@ static std::string getDestDir( unsigned psize )
bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psize)
{
bool loadNeeded = false;
- static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk");
static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache", true);
static bool cacheValidated = false;
if (!cacheValidated) {
@@ -1367,6 +1366,7 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz
Glib::ustring key = icon_cache_key(name, psize);
if ( !get_cached_pixbuf(key) ) {
+ static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk");
if ((internalNames.find(name) != internalNames.end())
|| (!gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), name))) {
if (dump) {
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index 54eff00bc..0319bb5e3 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -334,7 +334,10 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
xmlSubstituteEntitiesDefault(1);
g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS ), NULL);
+ if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) {
+ g_warning("Can't open file: %s (doesn't exist)", filename);
+ return NULL;
+ }
/* fixme: A file can disappear at any time, including between now and when we actually try to
* open it. Get rid of the above test once we're sure that we correctly handle
* non-existence. */