diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/2geom/sbasis-to-bezier.cpp | 29 | ||||
| -rw-r--r-- | src/desktop.cpp | 1 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 5 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 1 | ||||
| -rw-r--r-- | src/document.cpp | 50 | ||||
| -rw-r--r-- | src/document.h | 15 | ||||
| -rw-r--r-- | src/extension/implementation/xslt.cpp | 2 | ||||
| -rw-r--r-- | src/extension/internal/emf-print.cpp | 18 | ||||
| -rw-r--r-- | src/helper/png-write.cpp | 2 | ||||
| -rw-r--r-- | src/line-geometry.cpp | 16 | ||||
| -rw-r--r-- | src/main.cpp | 30 | ||||
| -rw-r--r-- | src/selection-chemistry.cpp | 5 | ||||
| -rw-r--r-- | src/sp-image.cpp | 89 | ||||
| -rw-r--r-- | src/sp-image.h | 5 | ||||
| -rw-r--r-- | src/sp-item-transform.cpp | 22 | ||||
| -rw-r--r-- | src/ui/dialog/template-load-tab.cpp | 7 | ||||
| -rw-r--r-- | src/ui/tools/text-tool.cpp | 4 | ||||
| -rw-r--r-- | src/ui/tools/tool-base.cpp | 7 | ||||
| -rw-r--r-- | src/ui/tools/tool-base.h | 1 | ||||
| -rw-r--r-- | src/uri-references.cpp | 24 | ||||
| -rw-r--r-- | src/uri.cpp | 24 | ||||
| -rw-r--r-- | src/uri.h | 3 | ||||
| -rw-r--r-- | src/widgets/icon.cpp | 4 | ||||
| -rw-r--r-- | src/xml/repr-io.cpp | 5 |
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) { @@ -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. */ |
