Code

lpe spiro: if path is closed it does not matter to what initial pointtype is initialized.
[inkscape.git] / src / document.cpp
index 2a482648f1044ea6f22e61f5f5f9744e4facf78a..356fba577055c7cab0d165401117f68c68fcadc6 100644 (file)
@@ -38,6 +38,8 @@
 # include "config.h"
 #endif
 #include <gtk/gtkmain.h>
+#include <string>
+#include <cstring>
 #include "application/application.h"
 #include "application/editor.h"
 #include "libnr/nr-matrix-fns.h"
@@ -46,6 +48,8 @@
 #include "inkscape-private.h"
 #include "inkscape_version.h"
 #include "sp-object-repr.h"
+#include "sp-namedview.h"
+#include "desktop.h"
 #include "document-private.h"
 #include "dir-util.h"
 #include "unit-constants.h"
 #include "libavoid/router.h"
 #include "libnr/nr-rect.h"
 #include "sp-item-group.h"
-#include "perspective3d.h"
+#include "profile-manager.h"
+#include "persp3d.h"
 
 #include "display/nr-arena-item.h"
 
 #include "dialogs/rdf.h"
 
-#define A4_WIDTH_STR "210mm"
-#define A4_HEIGHT_STR "297mm"
+#include "transf_mat_3x4.h"
 
 #define SP_DOCUMENT_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE - 1)
 
@@ -73,48 +77,30 @@ static gint doc_count = 0;
 
 static unsigned long next_serial = 0;
 
-SPDocument::SPDocument() {
-    SPDocumentPrivate *p;
-
-    keepalive = FALSE;
-    virgin    = TRUE;
-
-    modified_id = 0;
-
-    rdoc = NULL;
-    rroot = NULL;
-    root = NULL;
-    style_cascade = cr_cascade_new(NULL, NULL, NULL);
-
-    uri = NULL;
-    base = NULL;
-    name = NULL;
-
-    _collection_queue = NULL;
-
-    // Initialise instance of connector router.
-    router = new Avoid::Router();
+SPDocument::SPDocument() :
+    keepalive(FALSE),
+    virgin(TRUE),
+    modified_since_save(FALSE),
+    rdoc(0),
+    rroot(0),
+    root(0),
+    style_cascade(cr_cascade_new(NULL, NULL, NULL)),
+    uri(0),
+    base(0),
+    name(0),
+    priv(0), // reset in ctor
+    actionkey(0),
+    modified_id(0),
+    profileManager(0), // deferred until after other initialization
+    router(new Avoid::Router()),
+    perspectives(0),
+    current_persp3d(0),
+    _collection_queue(0)
+{
     // Don't use the Consolidate moves optimisation.
     router->ConsolidateMoves = false;
 
-    perspectives = NULL;
-
-    /* Create an initial perspective, make it current and append it to the list of existing perspectives */
-    current_perspective = new Box3D::Perspective3D (
-                              // VP in x-direction
-                              Box3D::VanishingPoint( NR::Point(-50.0, 600.0),
-                                                     NR::Point( -1.0,   0.0), Box3D::VP_FINITE),
-                              // VP in y-direction
-                              Box3D::VanishingPoint( NR::Point(500.0,1000.0),
-                                                     NR::Point(  0.0,   1.0), Box3D::VP_INFINITE),
-                              // VP in z-direction
-                              Box3D::VanishingPoint( NR::Point(700.0, 600.0),
-                                                     NR::Point(sqrt(3.0),1.0), Box3D::VP_FINITE),
-                              this);
-
-    add_perspective (current_perspective);    
-
-    p = new SPDocumentPrivate();
+    SPDocumentPrivate *p = new SPDocumentPrivate();
 
     p->serial = next_serial++;
 
@@ -132,6 +118,9 @@ SPDocument::SPDocument() {
 
     priv = p;
 
+    // Once things are set, hook in the manager
+    profileManager = new Inkscape::ProfileManager(this);
+
     // XXX only for testing!
     priv->undoStackObservers.add(p->console_output_undo_observer);
 }
@@ -139,6 +128,12 @@ SPDocument::SPDocument() {
 SPDocument::~SPDocument() {
     collectOrphans();
 
+    // kill/unhook this first
+    if ( profileManager ) {
+        delete profileManager;
+        profileManager = 0;
+    }
+
     if (priv) {
         if (priv->partial) {
             sp_repr_free_log(priv->partial);
@@ -203,65 +198,26 @@ SPDocument::~SPDocument() {
 
     //delete this->_whiteboard_session_manager;
 
-    current_perspective = NULL;
-    // TODO: Do we have to delete the perspectives?
-    /***
-    for (GSList *i = perspectives; i != NULL; ++i) {
-        delete ((Box3D::Perspective3D *) i->data);
-    }
-    g_slist_free (perspectives);
-    ***/
-}
-
-void SPDocument::add_perspective (Box3D::Perspective3D * const persp)
-{
-    // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical?
-    //        If so, we need to take care of relinking the boxes, etc.
-    if (persp == NULL || g_slist_find (perspectives, persp)) return;
-    perspectives = g_slist_prepend (perspectives, persp);
-}
-
-void SPDocument::remove_perspective (Box3D::Perspective3D * const persp)
-{
-    if (persp == NULL || !g_slist_find (perspectives, persp)) return;
-    perspectives = g_slist_remove (perspectives, persp);
 }
 
-// find an existing perspective whose VPs are equal to those of persp
-Box3D::Perspective3D * SPDocument::find_perspective (const Box3D::Perspective3D * persp)
+void SPDocument::add_persp3d (Persp3D * const /*persp*/)
 {
-    for (GSList *p = perspectives; p != NULL; p = p->next) {
-        if (*((Box3D::Perspective3D *) p->data) == *persp) {
-            return ((Box3D::Perspective3D *) p->data);
+    SPDefs *defs = SP_ROOT(this->root)->defs;
+    for (SPObject *i = sp_object_first_child(SP_OBJECT(defs)); i != NULL; i = SP_OBJECT_NEXT(i) ) {
+        if (SP_IS_PERSP3D(i)) {
+            g_print ("Encountered a Persp3D in defs\n");
         }
     }
-    return NULL; // perspective was not found
-}
 
-Box3D::Perspective3D * SPDocument::get_persp_of_box (const SP3DBox *box)
-{
-    for (GSList *p = perspectives; p != NULL; p = p->next) {
-        if (((Box3D::Perspective3D *) p->data)->has_box (box))
-            return (Box3D::Perspective3D *) p->data;
-    }
-    g_warning ("Stray 3D box!\n");
-    g_assert_not_reached();
+    g_print ("Adding Persp3D to defs\n");
+    persp3d_create_xml_element (this);
 }
 
-Box3D::Perspective3D * SPDocument::get_persp_of_VP (const Box3D::VanishingPoint *vp)
+void SPDocument::remove_persp3d (Persp3D * const /*persp*/)
 {
-    Box3D::Perspective3D *persp;
-    for (GSList *p = perspectives; p != NULL; p = p->next) {
-        persp = (Box3D::Perspective3D *) p->data;
-        // we compare the pointers, not the position/state of the VPs; is this correct?
-        if (persp->get_vanishing_point (Box3D::X) == vp ||
-            persp->get_vanishing_point (Box3D::Y) == vp ||
-            persp->get_vanishing_point (Box3D::Z) == vp)
-            return persp;
-    }
-
-    g_warning ("Stray vanishing point!\n");
-    g_assert_not_reached();
+    // TODO: Delete the repr, maybe perform a check if any boxes are still linked to the perspective.
+    //       Anything else?
+    g_print ("Please implement deletion of perspectives here.\n");
 }
 
 unsigned long SPDocument::serial() const {
@@ -289,7 +245,7 @@ void SPDocument::collectOrphans() {
     }
 }
 
-void SPDocument::reset_key (void *dummy)
+void SPDocument::reset_key (void */*dummy*/)
 {
     actionkey = NULL;
 }
@@ -340,8 +296,8 @@ sp_document_create(Inkscape::XML::Document *rdoc,
     /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */
 
     /* Quick hack 2 - get default image size into document */
-    if (!rroot->attribute("width")) rroot->setAttribute("width", A4_WIDTH_STR);
-    if (!rroot->attribute("height")) rroot->setAttribute("height", A4_HEIGHT_STR);
+    if (!rroot->attribute("width")) rroot->setAttribute("width", "100%");
+    if (!rroot->attribute("height")) rroot->setAttribute("height", "100%");
     /* End of quick hack 2 */
 
     /* Quick hack 3 - Set uri attributes */
@@ -350,6 +306,12 @@ sp_document_create(Inkscape::XML::Document *rdoc,
     }
     /* End of quick hack 3 */
 
+    /* Eliminate obsolete sodipodi:docbase, for privacy reasons */
+    rroot->setAttribute("sodipodi:docbase", NULL);
+    
+    /* Eliminate any claim to adhere to a profile, as we don't try to */
+    rroot->setAttribute("baseProfile", NULL);
+
     // creating namedview
     if (!sp_item_group_get_child_by_name((SPGroup *) document->root, NULL, "sodipodi:namedview")) {
         // if there's none in the document already,
@@ -387,6 +349,15 @@ sp_document_create(Inkscape::XML::Document *rdoc,
         inkscape_ref();
     }
 
+    // Remark: Here, we used to create a "currentpersp3d" element in the document defs.
+    // But this is probably a bad idea since we need to adapt it for every change of selection, which will
+    // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup?
+
+    document->current_persp3d = persp3d_document_first_persp(document);
+    if (!document->current_persp3d) {
+        document->current_persp3d = persp3d_create_xml_element (document);
+    }
+
     sp_document_set_undo_sensitive(document, true);
 
     // reset undo key when selection changes, so that same-key actions on different objects are not coalesced
@@ -505,7 +476,11 @@ gdouble sp_document_width(SPDocument *document)
     g_return_val_if_fail(document->priv != NULL, 0.0);
     g_return_val_if_fail(document->root != NULL, 0.0);
 
-    return SP_ROOT(document->root)->width.computed;
+    SPRoot *root = SP_ROOT(document->root);
+
+    if (root->width.unit == SVGLength::PERCENT && root->viewBox_set)
+        return root->viewBox.x1 - root->viewBox.x0;
+    return root->width.computed;
 }
 
 void
@@ -559,7 +534,11 @@ gdouble sp_document_height(SPDocument *document)
     g_return_val_if_fail(document->priv != NULL, 0.0);
     g_return_val_if_fail(document->root != NULL, 0.0);
 
-    return SP_ROOT(document->root)->height.computed;
+    SPRoot *root = SP_ROOT(document->root);
+
+    if (root->height.unit == SVGLength::PERCENT && root->viewBox_set)
+        return root->viewBox.y1 - root->viewBox.y0;
+    return root->height.computed;
 }
 
 /**
@@ -583,6 +562,14 @@ void SPDocument::fitToRect(NR::Rect const &rect)
     NR::translate const tr(NR::Point(0, (old_height - h))
                            - rect.min());
     SP_GROUP(root)->translateChildItems(tr);
+    SPNamedView *nv = sp_document_namedview(this, 0);
+    if(nv) {
+        NR::translate tr2(-rect.min());
+        nv->translateGuides(tr2);
+
+        // update the viewport so the drawing appears to stay where it was
+        nv->scrollAllDesktops(-tr2[0], tr2[1], false);
+    }
 }
 
 void sp_document_set_uri(SPDocument *document, gchar const *uri)
@@ -723,13 +710,13 @@ void SPDocument::bindObjectToId(gchar const *id, SPObject *object) {
 void
 SPDocument::addUndoObserver(Inkscape::UndoStackObserver& observer)
 {
-       this->priv->undoStackObservers.add(observer);
+    this->priv->undoStackObservers.add(observer);
 }
 
 void
 SPDocument::removeUndoObserver(Inkscape::UndoStackObserver& observer)
 {
-       this->priv->undoStackObservers.remove(observer);
+    this->priv->undoStackObservers.remove(observer);
 }
 
 SPObject *SPDocument::getObjectById(gchar const *id) {
@@ -775,7 +762,7 @@ Glib::ustring SPDocument::getLanguage() {
         if ( NULL == document_language || *document_language == 0 ) {
             document_language = getenv ("LANG");
         }
-        
+
         if ( NULL != document_language ) {
             gchar *pos = strchr(document_language, '_');
             if ( NULL != pos ) {
@@ -820,7 +807,7 @@ sp_document_setup_viewport (SPDocument *doc, SPItemCtx *ctx)
 }
 
 /**
- * Tries to update the document state based on the modified and 
+ * Tries to update the document state based on the modified and
  * "update required" flags, and return true if the document has
  * been brought fully up to date.
  */
@@ -993,7 +980,7 @@ find_item_at_point(unsigned int dkey, SPGroup *group, NR::Point const p, gboolea
         if (upto && SP_ITEM(o) == upto)
             break;
 
-        if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups))        {
+        if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) {
             // if nothing found yet, recurse into the group
             newseen = find_item_at_point(dkey, SP_GROUP(o), p, into_groups, take_insensitive, upto);
             if (newseen) {
@@ -1085,8 +1072,8 @@ sp_document_items_at_points(SPDocument *document, unsigned const key, std::vecto
 {
     GSList *items = NULL;
 
-    // When picking along the path, we don't want small objects close together 
-    // (such as hatching strokes) to obscure each other by their deltas, 
+    // When picking along the path, we don't want small objects close together
+    // (such as hatching strokes) to obscure each other by their deltas,
     // so we temporarily set delta to a small value
     gdouble saved_delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0);
     prefs_set_double_attribute ("options.cursortolerance", "value", 0.25);
@@ -1198,7 +1185,7 @@ sigc::connection sp_document_resources_changed_connect(SPDocument *document,
 /* Helpers */
 
 gboolean
-sp_document_resource_list_free(gpointer key, gpointer value, gpointer data)
+sp_document_resource_list_free(gpointer /*key*/, gpointer value, gpointer /*data*/)
 {
     g_slist_free((GSList *) value);
     return TRUE;