void SPDocument::add_persp3d (Persp3D * const /*persp*/)
{
    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");
        }
    }

    g_print ("Adding Persp3D to defs\n");
    persp3d_create_xml_element (this);
}
Ejemplo n.º 2
0
/* Create a default perspective in document defs if none is present (which can happen, among other
 * circumstances, after 'vacuum defs' or when a pre-0.46 file is opened).
 */
static void sp_box3d_context_ensure_persp_in_defs(SPDocument *document) {
    SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);

    bool has_persp = false;
    for (SPObject *child = sp_object_first_child(defs); child != NULL; child = SP_OBJECT_NEXT(child) ) {
        if (SP_IS_PERSP3D(child)) {
            has_persp = true;
            break;
        }
    }

    if (!has_persp) {
        document->setCurrentPersp3D(persp3d_create_xml_element (document));
    }
}
SPDocument *
sp_document_create(Inkscape::XML::Document *rdoc,
                   gchar const *uri,
                   gchar const *base,
                   gchar const *name,
                   unsigned int keepalive)
{
    SPDocument *document;
    Inkscape::XML::Node *rroot;
    Inkscape::Version sodipodi_version;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    rroot = rdoc->root();

    document = new SPDocument();

    document->keepalive = keepalive;

    document->rdoc = rdoc;
    document->rroot = rroot;

#ifndef WIN32
    prepend_current_dir_if_relative(&(document->uri), uri);
#else
    // FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test!
    document->uri = uri? g_strdup(uri) : NULL;
#endif

    // base is simply the part of the path before filename; e.g. when running "inkscape ../file.svg" the base is "../"
    // which is why we use g_get_current_dir() in calculating the abs path above
    //This is NULL for a new document
    if (base)
        document->base = g_strdup(base);
    else
        document->base = NULL;
    document->name = g_strdup(name);

    document->root = sp_object_repr_build_tree(document, rroot);

    sodipodi_version = SP_ROOT(document->root)->version.sodipodi;

    /* fixme: Not sure about this, but lets assume ::build updates */
    rroot->setAttribute("sodipodi:version", SODIPODI_VERSION);
    rroot->setAttribute("inkscape:version", Inkscape::version_string);
    /* 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", "100%");
    if (!rroot->attribute("height")) rroot->setAttribute("height", "100%");
    /* End of quick hack 2 */

    /* Quick hack 3 - Set uri attributes */
    if (uri) {
        rroot->setAttribute("sodipodi:docname", uri);
    }
    /* 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,
        Inkscape::XML::Node *rnew = NULL;
        
        rnew = rdoc->createElement("sodipodi:namedview");
        //rnew->setAttribute("id", "base");

        // Add namedview data from the preferences
        // we can't use getAllEntries because this could produce non-SVG doubles
        Glib::ustring pagecolor = prefs->getString("/template/base/pagecolor");
        if (!pagecolor.empty()) {
            rnew->setAttribute("pagecolor", pagecolor.data());
        }
        Glib::ustring bordercolor = prefs->getString("/template/base/bordercolor");
        if (!bordercolor.empty()) {
            rnew->setAttribute("bordercolor", bordercolor.data());
        }
        sp_repr_set_svg_double(rnew, "borderopacity",
            prefs->getDouble("/template/base/borderopacity", 1.0));
        sp_repr_set_svg_double(rnew, "objecttolerance",
            prefs->getDouble("/template/base/objecttolerance", 10.0));
        sp_repr_set_svg_double(rnew, "gridtolerance",
            prefs->getDouble("/template/base/gridtolerance", 10.0));
        sp_repr_set_svg_double(rnew, "guidetolerance",
            prefs->getDouble("/template/base/guidetolerance", 10.0));
        sp_repr_set_svg_double(rnew, "inkscape:pageopacity",
            prefs->getDouble("/template/base/inkscape:pageopacity", 0.0));
        sp_repr_set_int(rnew, "inkscape:pageshadow",
            prefs->getInt("/template/base/inkscape:pageshadow", 2));
        sp_repr_set_int(rnew, "inkscape:window-width",
            prefs->getInt("/template/base/inkscape:window-width", 640));
        sp_repr_set_int(rnew, "inkscape:window-height",
            prefs->getInt("/template/base/inkscape:window-height", 480));
        
        // insert into the document
        rroot->addChild(rnew, NULL);
        // clean up
        Inkscape::GC::release(rnew);
    }

    /* Defs */
    if (!SP_ROOT(document->root)->defs) {
        Inkscape::XML::Node *r;
        r = rdoc->createElement("svg:defs");
        rroot->addChild(r, NULL);
        Inkscape::GC::release(r);
        g_assert(SP_ROOT(document->root)->defs);
    }

    /* Default RDF */
    rdf_set_defaults( document );

    if (keepalive) {
        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
    if (!Inkscape::NSApplication::Application::getNewGui()) {
        g_signal_connect(G_OBJECT(INKSCAPE), "change_selection",
                         G_CALLBACK(sp_document_reset_key), document);
        g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
                         G_CALLBACK(sp_document_reset_key), document);
    } else {
        document->_selection_changed_connection = Inkscape::NSApplication::Editor::connectSelectionChanged (sigc::mem_fun (*document, &SPDocument::reset_key));
        document->_desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*document, &SPDocument::reset_key));
    }

    return document;
}
Ejemplo n.º 4
0
static void
vp_knot_moved_handler (SPKnot */*knot*/, Geom::Point const *ppointer, guint state, gpointer data)
{
    VPDragger *dragger = (VPDragger *) data;
    VPDrag *drag = dragger->parent;

    Geom::Point p = *ppointer;

    // FIXME: take from prefs
    double snap_dist = SNAP_DIST / inkscape_active_desktop()->current_zoom();

    /*
     * We use dragging_started to indicate if we have already checked for the need to split Draggers up.
     * This only has the purpose of avoiding costly checks in the routine below.
     */
    if (!dragger->dragging_started && (state & GDK_SHIFT_MASK)) {
        /* with Shift; if there is more than one box linked to this VP
           we need to split it and create a new perspective */
        if (dragger->numberOfBoxes() > 1) { // FIXME: Don't do anything if *all* boxes of a VP are selected
            std::set<VanishingPoint*, less_ptr> sel_vps = dragger->VPsOfSelectedBoxes();

            std::list<SPBox3D *> sel_boxes;
            for (std::set<VanishingPoint*, less_ptr>::iterator vp = sel_vps.begin(); vp != sel_vps.end(); ++vp) {
                // for each VP that has selected boxes:
                Persp3D *old_persp = (*vp)->get_perspective();
                sel_boxes = (*vp)->selectedBoxes(sp_desktop_selection(inkscape_active_desktop()));

                // we create a new perspective ...
                Persp3D *new_persp = persp3d_create_xml_element (dragger->parent->document, old_persp);

                /* ... unlink the boxes from the old one and
                   FIXME: We need to unlink the _un_selected boxes of each VP so that
                          the correct boxes are kept with the VP being moved */
                std::list<SPBox3D *> bx_lst = persp3d_list_of_boxes(old_persp);
                for (std::list<SPBox3D *>::iterator i = bx_lst.begin(); i != bx_lst.end(); ++i) {
                    if (std::find(sel_boxes.begin(), sel_boxes.end(), *i) == sel_boxes.end()) {
                        /* if a box in the VP is unselected, move it to the
                           newly created perspective so that it doesn't get dragged **/
                        box3d_switch_perspectives(*i, old_persp, new_persp);
                    }
                }
            }
            // FIXME: Do we need to create a new dragger as well?
            dragger->updateZOrders ();
            sp_document_done (sp_desktop_document (inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX,
                              _("Split vanishing points"));
            return;
        }
    }

    if (!(state & GDK_SHIFT_MASK)) {
        // without Shift; see if we need to snap to another dragger
        for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) {
            VPDragger *d_new = (VPDragger *) di->data;
            if ((d_new != dragger) && (Geom::L2 (d_new->point - p) < snap_dist)) {
                if (have_VPs_of_same_perspective (dragger, d_new)) {
                    // this would result in degenerate boxes, which we disallow for the time being
                    continue;
                }

                // update positions ... (this is needed so that the perspectives are detected as identical)
                // FIXME: This is called a bit too often, isn't it?
                for (std::list<VanishingPoint>::iterator j = dragger->vps.begin(); j != dragger->vps.end(); ++j) {
                    (*j).set_pos(d_new->point);
                }

                // ... join lists of VPs ...
                d_new->vps.merge(dragger->vps);

                // ... delete old dragger ...
                drag->draggers = g_list_remove (drag->draggers, dragger);
                delete dragger;
                dragger = NULL;

                // ... and merge any duplicate perspectives
                d_new->mergePerspectives();

                // TODO: Update the new merged dragger
                d_new->updateTip();

                d_new->parent->updateBoxDisplays (); // FIXME: Only update boxes in current dragger!
                d_new->updateZOrders ();

                drag->updateLines ();

                // TODO: Undo machinery; this doesn't work yet because perspectives must be created and
                //       deleted according to changes in the svg representation, not based on any user input
                //       as is currently the case.

                sp_document_done (sp_desktop_document (inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX,
                                  _("Merge vanishing points"));

                return;
            }
        }
    }


    dragger->point = p; // FIXME: Brauchen wir dragger->point überhaupt?

    dragger->updateVPs(p);
    dragger->updateBoxDisplays();
    dragger->parent->updateBoxHandles (); // FIXME: Only update the handles of boxes on this dragger (not on all)
    dragger->updateZOrders();

    drag->updateLines();

    dragger->dragging_started = true;
}