void ExecutionEnv::reselect (void) { if (_doc == NULL) { return; } SPDocument * doc = _doc->doc(); if (doc == NULL) { return; } SPDesktop *desktop = (SPDesktop *)_doc; sp_namedview_document_from_window(desktop); if (desktop == NULL) { return; } Inkscape::Selection * selection = desktop->getSelection(); for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); ++i) { SPObject * obj = doc->getObjectById(i->c_str()); if (obj != NULL) { selection->add(obj); } } return; }
bool ImageIcon::showSvgDocument(const SPDocument *docArg) { if (document) document->doUnref(); SPDocument *doc = const_cast<SPDocument *>(docArg); doc->doRef(); document = doc; //This should remove it from the box, and free resources //if (viewerGtkmm) // viewerGtkmm->destroy(); GtkWidget *viewerGtk = sp_svg_view_widget_new(doc); viewerGtkmm = Glib::wrap(viewerGtk); viewerGtkmm->show(); pack_start(*viewerGtkmm, TRUE, TRUE, 0); //GtkWidget *vbox = GTK_WIDGET(gobj()); //gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0); return true; }
static void mesh_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) { static sigc::connection c_selection_changed; static sigc::connection c_selection_modified; static sigc::connection c_subselection_changed; static sigc::connection c_defs_release; static sigc::connection c_defs_modified; if (SP_IS_MESH_CONTEXT(ec)) { // connect to selection modified and changed signals Inkscape::Selection *selection = desktop->getSelection(); SPDocument *document = desktop->getDocument(); c_selection_changed = selection->connectChanged(sigc::bind(sigc::ptr_fun(&ms_tb_selection_changed), holder)); c_selection_modified = selection->connectModified(sigc::bind(sigc::ptr_fun(&ms_tb_selection_modified), holder)); c_subselection_changed = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&ms_drag_selection_changed), holder)); c_defs_release = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&ms_defs_release), holder)); c_defs_modified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&ms_defs_modified), holder)); ms_tb_selection_changed(selection, holder); } else { if (c_selection_changed) c_selection_changed.disconnect(); if (c_selection_modified) c_selection_modified.disconnect(); if (c_subselection_changed) c_subselection_changed.disconnect(); if (c_defs_release) c_defs_release.disconnect(); if (c_defs_modified) c_defs_modified.disconnect(); } }
static void sp_box3d_finish(Box3DContext *bc) { bc->_message_context->clear(); bc->ctrl_dragged = false; bc->extruded = false; if ( bc->item != NULL ) { SPDesktop * desktop = SP_EVENT_CONTEXT_DESKTOP(bc); SPDocument *doc = sp_desktop_document(desktop); if (!doc || !doc->getCurrentPersp3D()) return; SPBox3D *box = SP_BOX3D(bc->item); box->orig_corner0 = bc->drag_origin_proj; box->orig_corner7 = bc->drag_ptC_proj; box->updateRepr(); box3d_relabel_corners(box); desktop->canvas->end_forced_full_redraws(); sp_desktop_selection(desktop)->set(bc->item); sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, _("Create 3D box")); bc->item = NULL; } }
/** \brief This actually draws the grid. \param module The effect that was called (unused) \param document What should be edited. */ void Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { Inkscape::Selection * selection = ((SPDesktop *)document)->selection; Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100)); if (selection->isEmpty()) { /* get page size */ SPDocument * doc = document->doc(); bounding_area = Geom::Rect( Geom::Point(0,0), Geom::Point(doc->getWidth(), doc->getHeight()) ); } else { Geom::OptRect bounds = selection->visualBounds(); if (bounds) { bounding_area = *bounds; } gdouble doc_height = (document->doc())->getHeight(); Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]), Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y])); bounding_area = temprec; } float spacings[2] = { module->get_param_float("xspacing"), module->get_param_float("yspacing") }; float line_width = module->get_param_float("lineWidth"); float offsets[2] = { module->get_param_float("xoffset"), module->get_param_float("yoffset") }; Glib::ustring path_data(""); path_data = build_lines(bounding_area, offsets, spacings); Inkscape::XML::Document * xml_doc = document->doc()->getReprDoc(); //XML Tree being used directly here while it shouldn't be. Inkscape::XML::Node * current_layer = static_cast<SPDesktop *>(document)->currentLayer()->getRepr(); Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); path->setAttribute("d", path_data.c_str()); Glib::ustring style("fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"); style += ";stroke-width:"; gchar floatstring[64]; std::ostringstream stringstream; stringstream << line_width; sprintf(floatstring, "%s", stringstream.str().c_str()); style += floatstring; style += "pt"; path->setAttribute("style", style.c_str()); current_layer->appendChild(path); Inkscape::GC::release(path); return; }
/** * An idle handler to update the document. Returns true if * the document needs further updates. */ static gint sp_document_idle_handler(gpointer data) { SPDocument *doc = static_cast<SPDocument *>(data); if (doc->_updateDocument()) { doc->modified_id = 0; return false; } else { return true; } }
Inkscape::XML::Node *box3d_side_convert_to_path(Box3DSide *side) { // TODO: Copy over all important attributes (see sp_selected_item_to_curved_repr() for an example) SPDocument *doc = side->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("d", side->getAttribute("d")); repr->setAttribute("style", side->getAttribute("style")); return repr; }
/** * \return A new document created from the filename passed in * \brief This is a generic function to use the open function of * a module (including Autodetect) * \param key Identifier of which module to use * \param filename The file that should be opened * * First things first, are we looking at an autodetection? Well if that's the case then the module * needs to be found, and that is done with a database lookup through the module DB. The foreach * function is called, with the parameter being a gpointer array. It contains both the filename * (to find its extension) and where to write the module when it is found. * * If there is no autodetection, then the module database is queried with the key given. * * If everything is cool at this point, the module is loaded, and there is possibility for * preferences. If there is a function, then it is executed to get the dialog to be displayed. * After it is finished the function continues. * * Lastly, the open function is called in the module itself. */ SPDocument * open(Extension *key, gchar const *filename) { Input *imod = NULL; if (key == NULL) { gpointer parray[2]; parray[0] = (gpointer)filename; parray[1] = (gpointer)&imod; db.foreach(open_internal, (gpointer)&parray); } else { imod = dynamic_cast<Input *>(key); } bool last_chance_svg = false; if (key == NULL && imod == NULL) { last_chance_svg = true; imod = dynamic_cast<Input *>(db.get(SP_MODULE_KEY_INPUT_SVG)); } if (imod == NULL) { throw Input::no_extension_found(); } imod->set_state(Extension::STATE_LOADED); if (!imod->loaded()) { throw Input::open_failed(); } if (!imod->prefs(filename)) return NULL; SPDocument *doc = imod->open(filename); if (!doc) { return NULL; } if (last_chance_svg) { /* We can't call sp_ui_error_dialog because we may be running from the console, in which case calling sp_ui routines will cause a segfault. See bug 1000350 - bryce */ // sp_ui_error_dialog(_("Format autodetect failed. The file is being opened as SVG.")); g_warning(_("Format autodetect failed. The file is being opened as SVG.")); } /* This kinda overkill as most of these are already set, but I want to make sure for this release -- TJG */ doc->setModifiedSinceSave(false); sp_document_set_uri(doc, filename); return doc; }
static bool evaluateSystemLanguage(SPItem const *item, gchar const *value) { if ( NULL == value ) return true; std::set<Glib::ustring> language_codes; gchar *str = NULL; gchar **strlist = g_strsplit( value, ",", 0); for ( int i = 0 ; (str = strlist[i]) ; i++ ) { gchar *lngcode = preprocessLanguageCode(str); if ( 0 == *lngcode ) continue; language_codes.insert(lngcode); gchar *pos = strchr (lngcode, '-'); if (pos) { // if subtag is used, primary tag is still a perfect match *pos = 0; if ( language_codes.find(lngcode) == language_codes.end() ) { language_codes.insert(lngcode); } } } g_strfreev(strlist); if (language_codes.empty()) return false; SPDocument *document = SP_OBJECT_DOCUMENT(item); Glib::ustring document_language = document->getLanguage(); if (document_language.size() == 0) return false; bool match = true; strlist = g_strsplit( document_language.c_str(), ",", 0); for ( int i = 0 ; (str = strlist[i]) ; i++ ) { gchar *lngcode = preprocessLanguageCode(str); if ( 0 == *lngcode ) continue; if ( language_codes.find(lngcode) != language_codes.end() ) { match = true; break; } match = false; } g_strfreev(strlist); return match; }
bool ImageIcon::showSvgFile(const Glib::ustring &theFileName) { Glib::ustring fileName = theFileName; fileName = Glib::filename_to_utf8(fileName); SPDocument *doc = SPDocument::createNewDoc (fileName.c_str(), 0); if (!doc) { g_warning("SVGView: error loading document '%s'\n", fileName.c_str()); return false; } showSvgDocument(doc); doc->doUnref(); return true; }
bool ImageIcon::showSvgFromMemory(const char *xmlBuffer) { if (!xmlBuffer) return false; gint len = (gint)strlen(xmlBuffer); SPDocument *doc = SPDocument::createNewDocFromMem(xmlBuffer, len, 0); if (!doc) { g_warning("SVGView: error loading buffer '%s'\n",xmlBuffer); return false; } showSvgDocument(doc); doc->doUnref(); return true; }
static void sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *sel) { SPDocument *doc = sp_gradient_vector_selector_get_document (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); if (!doc) return; SPGradient *gr = sp_gradient_vector_selector_get_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = NULL; if (gr) { repr = gr->getRepr()->duplicate(xml_doc); } else { repr = xml_doc->createElement("svg:linearGradient"); Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "0"); stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "1"); stop->setAttribute("style", "stop-color:#fff;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); } doc->getDefs()->getRepr()->addChild(repr, NULL); Glib::ustring old_id = gr->getId(); gr = SP_GRADIENT(doc->getObjectByRepr(repr)); // Rename the new gradients id to be similar to the cloned gradients rename_id(gr, old_id); sp_gradient_vector_selector_set_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors), doc, gr); sel->selectGradientInTree(gr); Inkscape::GC::release(repr); }
/** * Checks the current tool and connects gradient aux toolbox signals if it happens to be the gradient tool. * Called every time the current tool changes by signal emission. */ static void gradient_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) { static sigc::connection connChanged; static sigc::connection connModified; static sigc::connection connSubselectionChanged; static sigc::connection connDefsRelease; static sigc::connection connDefsModified; if (SP_IS_GRADIENT_CONTEXT(ec)) { Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *document = sp_desktop_document(desktop); // connect to selection modified and changed signals connChanged = selection->connectChanged(sigc::bind(sigc::ptr_fun(&gr_tb_selection_changed), holder)); connModified = selection->connectModified(sigc::bind(sigc::ptr_fun(&gr_tb_selection_modified), holder)); connSubselectionChanged = desktop->connectToolSubselectionChanged(sigc::bind(sigc::ptr_fun(&gr_drag_selection_changed), holder)); // Is this necessary? Couldn't hurt. gr_tb_selection_changed(selection, holder); // connect to release and modified signals of the defs (i.e. when someone changes gradient) connDefsRelease = document->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&gr_defs_release), GTK_WIDGET(holder))); connDefsModified = document->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&gr_defs_modified), GTK_WIDGET(holder))); } else { if (connChanged) connChanged.disconnect(); if (connModified) connModified.disconnect(); if (connSubselectionChanged) connSubselectionChanged.disconnect(); if (connDefsRelease) connDefsRelease.disconnect(); if (connDefsModified) connDefsModified.disconnect(); } }
static void perform_document_update(SPDocument &doc) { sp_repr_begin_transaction(doc.rdoc); doc.ensureUpToDate(); Inkscape::XML::Event *update_log=sp_repr_commit_undoable(doc.rdoc); if (update_log != NULL) { g_warning("Document was modified while being updated after undo operation"); sp_repr_debug_print_log(update_log); //Coalesce the update changes with the last action performed by user if (!doc.priv->undo.empty()) { Inkscape::Event* undo_stack_top = doc.priv->undo.back(); undo_stack_top->event = sp_repr_coalesce_log(undo_stack_top->event, update_log); } else { sp_repr_free_log(update_log); } } }
SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = sp_desktop_document (desktop); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot"); root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create SPItem *ft_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(root_repr)); SPObject *root_object = doc->getObjectByRepr(root_repr); g_assert(SP_IS_FLOWTEXT(root_object)); Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion"); root_repr->appendChild(region_repr); SPObject *region_object = doc->getObjectByRepr(region_repr); g_assert(SP_IS_FLOWREGION(region_object)); Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path region_repr->appendChild(rect_repr); SPRect *rect = SP_RECT(doc->getObjectByRepr(rect_repr)); p0 *= desktop->dt2doc(); p1 *= desktop->dt2doc(); using Geom::X; using Geom::Y; Geom::Coord const x0 = MIN(p0[X], p1[X]); Geom::Coord const y0 = MIN(p0[Y], p1[Y]); Geom::Coord const x1 = MAX(p0[X], p1[X]); Geom::Coord const y1 = MAX(p0[Y], p1[Y]); Geom::Coord const w = x1 - x0; Geom::Coord const h = y1 - y0; rect->setPosition(x0, y0, w, h); rect->updateRepr(); Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); SPObject *para_object = doc->getObjectByRepr(para_repr); g_assert(SP_IS_FLOWPARA(para_object)); Inkscape::XML::Node *text = xml_doc->createTextNode(""); para_repr->appendChild(text); Inkscape::GC::release(root_repr); Inkscape::GC::release(region_repr); Inkscape::GC::release(para_repr); Inkscape::GC::release(rect_repr); ft_item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); return ft_item; }
static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEvent *event) { static bool dragging; SPDesktop *desktop = event_context->desktop; SPDocument *document = sp_desktop_document (desktop); Inkscape::Selection *selection = sp_desktop_selection (desktop); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); Box3DContext *bc = SP_BOX3D_CONTEXT(event_context); Persp3D *cur_persp = document->getCurrentPersp3D(); event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); gint ret = FALSE; switch (event->type) { case GDK_BUTTON_PRESS: if ( event->button.button == 1 && !event_context->space_panning) { Geom::Point const button_w(event->button.x, event->button.y); // save drag origin event_context->xp = (gint) button_w[Geom::X]; event_context->yp = (gint) button_w[Geom::Y]; event_context->within_tolerance = true; // remember clicked item, *not* disregarding groups (since a 3D box is a group), honoring Alt event_context->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, event->button.state & GDK_CONTROL_MASK); dragging = true; /* */ Geom::Point button_dt(desktop->w2d(button_w)); bc->drag_origin = from_2geom(button_dt); bc->drag_ptB = from_2geom(button_dt); bc->drag_ptC = from_2geom(button_dt); // This can happen after saving when the last remaining perspective was purged and must be recreated. if (!cur_persp) { sp_box3d_context_ensure_persp_in_defs(document); cur_persp = document->getCurrentPersp3D(); } /* Projective preimages of clicked point under current perspective */ bc->drag_origin_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(button_dt), 0, Proj::Z); bc->drag_ptB_proj = bc->drag_origin_proj; bc->drag_ptC_proj = bc->drag_origin_proj; bc->drag_ptC_proj.normalize(); bc->drag_ptC_proj[Proj::Z] = 0.25; /* Snap center */ SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, bc->item); m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); bc->center = from_2geom(button_dt); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), ( GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK ), NULL, event->button.time); ret = TRUE; } break; case GDK_MOTION_NOTIFY: if ( dragging && ( event->motion.state & GDK_BUTTON1_MASK ) && !event_context->space_panning) { if ( event_context->within_tolerance && ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance ) && ( abs( (gint) event->motion.y - event_context->yp ) < event_context->tolerance ) ) { break; // do not drag if we're within tolerance from origin } // Once the user has moved farther than tolerance from the original location // (indicating they intend to draw, not click), then always process the // motion notify coordinates as given (no snapping back to origin) event_context->within_tolerance = false; Geom::Point const motion_w(event->motion.x, event->motion.y); Geom::Point motion_dt(desktop->w2d(motion_w)); SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, bc->item); m.freeSnapReturnByRef(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); bc->ctrl_dragged = event->motion.state & GDK_CONTROL_MASK; if (event->motion.state & GDK_SHIFT_MASK && !bc->extruded && bc->item) { // once shift is pressed, set bc->extruded bc->extruded = true; } if (!bc->extruded) { bc->drag_ptB = from_2geom(motion_dt); bc->drag_ptC = from_2geom(motion_dt); bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z); bc->drag_ptC_proj = bc->drag_ptB_proj; bc->drag_ptC_proj.normalize(); bc->drag_ptC_proj[Proj::Z] = 0.25; } else { // Without Ctrl, motion of the extruded corner is constrained to the // perspective line from drag_ptB to vanishing point Y. if (!bc->ctrl_dragged) { /* snapping */ Box3D::PerspectiveLine pline (bc->drag_ptB, Proj::Z, document->getCurrentPersp3D()); bc->drag_ptC = pline.closest_to (from_2geom(motion_dt)); bc->drag_ptB_proj.normalize(); bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (bc->drag_ptC, bc->drag_ptB_proj[Proj::X], Proj::X); } else { bc->drag_ptC = from_2geom(motion_dt); bc->drag_ptB_proj.normalize(); bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X); } m.freeSnapReturnByRef(bc->drag_ptC, Inkscape::SNAPSOURCE_NODE_HANDLE); } sp_box3d_drag(*bc, event->motion.state); ret = TRUE; } else if (!sp_event_context_knot_mouseover(bc)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Geom::Point const motion_w(event->motion.x, event->motion.y); Geom::Point motion_dt(desktop->w2d(motion_w)); m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE)); } break; case GDK_BUTTON_RELEASE: event_context->xp = event_context->yp = 0; if ( event->button.button == 1 && !event_context->space_panning) { dragging = false; sp_event_context_discard_delayed_snap_event(event_context); if (!event_context->within_tolerance) { // we've been dragging, finish the box sp_box3d_finish(bc); } else if (event_context->item_to_select) { // no dragging, select clicked item if any if (event->button.state & GDK_SHIFT_MASK) { selection->toggle(event_context->item_to_select); } else { selection->set(event_context->item_to_select); } } else { // click in an empty space selection->clear(); } event_context->item_to_select = NULL; ret = TRUE; sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time); } break; case GDK_KEY_PRESS: switch (get_group0_keyval (&event->key)) { case GDK_Up: case GDK_Down: case GDK_KP_Up: case GDK_KP_Down: // prevent the zoom field from activation if (!MOD__CTRL_ONLY) ret = TRUE; break; case GDK_bracketright: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, -180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; case GDK_bracketleft: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, 180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; case GDK_parenright: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, -180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; case GDK_parenleft: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, 180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; case GDK_braceright: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, -180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; case GDK_braceleft: persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, 180/snaps, MOD__ALT); sp_document_done(document, SP_VERB_CONTEXT_3DBOX, _("Change perspective (angle of PLs)")); ret = true; break; /* TODO: what is this??? case GDK_O: if (MOD__CTRL && MOD__SHIFT) { Box3D::create_canvas_point(persp3d_get_VP(document()->getCurrentPersp3D(), Proj::W).affine(), 6, 0xff00ff00); } ret = true; break; */ case GDK_g: case GDK_G: if (MOD__SHIFT_ONLY) { sp_selection_to_guides(desktop); ret = true; } break; case GDK_p: case GDK_P: if (MOD__SHIFT_ONLY) { if (document->getCurrentPersp3D()) { persp3d_print_debugging_info (document->getCurrentPersp3D()); } ret = true; } break; case GDK_x: case GDK_X: if (MOD__ALT_ONLY) { desktop->setToolboxFocusTo ("altx-box3d"); ret = TRUE; } if (MOD__SHIFT_ONLY) { persp3d_toggle_VPs(selection->perspList(), Proj::X); bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically? ret = true; } break; case GDK_y: case GDK_Y: if (MOD__SHIFT_ONLY) { persp3d_toggle_VPs(selection->perspList(), Proj::Y); bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically? ret = true; } break; case GDK_z: case GDK_Z: if (MOD__SHIFT_ONLY) { persp3d_toggle_VPs(selection->perspList(), Proj::Z); bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically? ret = true; } break; case GDK_Escape: sp_desktop_selection(desktop)->clear(); //TODO: make dragging escapable by Esc break; case GDK_space: if (dragging) { sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time); dragging = false; sp_event_context_discard_delayed_snap_event(event_context); if (!event_context->within_tolerance) { // we've been dragging, finish the box sp_box3d_finish(bc); } // do not return true, so that space would work switching to selector } break; default: break; } break; default: break; } if (!ret) { if (((SPEventContextClass *) parent_class)->root_handler) { ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event); } } return ret; }
void sp_selected_path_combine(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *doc = sp_desktop_document(desktop); if (g_slist_length((GSList *) selection->itemList()) < 1) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to combine.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Combining paths...")); // set "busy" cursor desktop->setWaitingCursor(); GSList *items = g_slist_copy((GSList *) selection->itemList()); items = sp_degroup_list (items); // descend into any groups in selection GSList *to_paths = NULL; for (GSList *i = items; i != NULL; i = i->next) { SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item) && !SP_IS_GROUP(item)) to_paths = g_slist_prepend(to_paths, item); } GSList *converted = NULL; bool did = sp_item_list_to_curves(to_paths, &items, &converted); g_slist_free(to_paths); for (GSList *i = converted; i != NULL; i = i->next) items = g_slist_prepend(items, doc->getObjectByRepr((Inkscape::XML::Node*)(i->data))); items = sp_degroup_list (items); // converting to path may have added more groups, descend again items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position); items = g_slist_reverse(items); // remember the position, id, transform and style of the topmost path, they will be assigned to the combined one gint position = 0; char const *id = NULL; char const *transform = NULL; char const *style = NULL; char const *path_effect = NULL; SPCurve* curve = NULL; SPItem *first = NULL; Inkscape::XML::Node *parent = NULL; if (did) { selection->clear(); } for (GSList *i = items; i != NULL; i = i->next) { // going from top to bottom SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item)) { continue; } if (!did) { selection->clear(); did = true; } SPCurve *c = SP_PATH(item)->get_curve_for_edit(); if (first == NULL) { // this is the topmost path first = item; parent = first->getRepr()->parent(); position = first->getRepr()->position(); id = first->getRepr()->attribute("id"); transform = first->getRepr()->attribute("transform"); // FIXME: merge styles of combined objects instead of using the first one's style style = first->getRepr()->attribute("style"); path_effect = first->getRepr()->attribute("inkscape:path-effect"); //c->transform(item->transform); curve = c; } else { c->transform(item->getRelativeTransform(first)); curve->append(c, false); c->unref(); // reduce position only if the same parent if (item->getRepr()->parent() == parent) { position--; } // delete the object for real, so that its clones can take appropriate action item->deleteObject(); } } g_slist_free(items); if (did) { first->deleteObject(false); // delete the topmost. Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); // restore id, transform, path effect, and style repr->setAttribute("id", id); if (transform) { repr->setAttribute("transform", transform); } repr->setAttribute("style", style); repr->setAttribute("inkscape:path-effect", path_effect); // set path data corresponding to new curve gchar *dstring = sp_svg_write_path(curve->get_pathvector()); curve->unref(); if (path_effect) { repr->setAttribute("inkscape:original-d", dstring); } else { repr->setAttribute("d", dstring); } g_free(dstring); // add the new group to the parent of the topmost parent->appendChild(repr); // move to the position of the topmost, reduced by the number of deleted items repr->setPosition(position > 0 ? position : 0); DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_COMBINE, _("Combine")); selection->set(repr); Inkscape::GC::release(repr); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to combine in the selection.")); } desktop->clearWaitingCursor(); }
SPDocument * GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) { // Determine whether the image should be embedded Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool ask = prefs->getBool("/dialogs/import/ask"); Glib::ustring link = prefs->getString("/dialogs/import/link"); bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); Glib::ustring scale = prefs->getString("/dialogs/import/scale"); // std::cout << "GkdpixbufInput::open: " // << " ask: " << ask // << ", link: " << link // << ", forcexdpi: " << forcexdpi // << ", scale: " << scale << std::endl; // std::cout << " in preferences: " // << " ask: " << !mod->get_param_bool("do_not_ask") // << ", link: " << mod->get_param_optiongroup("link") // << ", mod_dpi: " << mod->get_param_optiongroup("dpi") // << ", scale: " << mod->get_param_optiongroup("scale") << std::endl; if( ask ) { Glib::ustring mod_link = mod->get_param_optiongroup("link"); Glib::ustring mod_dpi = mod->get_param_optiongroup("dpi"); bool mod_forcexdpi = ( mod_dpi.compare( "from_default" ) == 0 ); Glib::ustring mod_scale = mod->get_param_optiongroup("scale"); if( link.compare( mod_link ) != 0 ) { link = mod_link; } prefs->setString("/dialogs/import/link", link ); if( forcexdpi != mod_forcexdpi ) { forcexdpi = mod_forcexdpi; } prefs->setBool("/dialogs/import/forcexdpi", forcexdpi ); if( scale.compare( mod_scale ) != 0 ) { scale = mod_scale; } prefs->setString("/dialogs/import/scale", scale ); prefs->setBool("/dialogs/import/ask", !mod->get_param_bool("do_not_ask") ); } bool embed = ( link.compare( "embed" ) == 0 ); SPDocument *doc = NULL; boost::scoped_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri)); // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage. // Find a way to create the pixbuf only once. if (pb) { doc = SPDocument::createNewDoc(NULL, TRUE, TRUE); bool saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); // no need to undo in this temporary document double width = pb->width(); double height = pb->height(); double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px")); //bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); ImageResolution *ir = 0; double xscale = 1; double yscale = 1; if (!ir && !forcexdpi) { ir = new ImageResolution(uri); } if (ir && ir->ok()) { xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi yscale = 900.0 / floor(10.*ir->y() + .5); } else { xscale = 90.0 / defaultxdpi; yscale = 90.0 / defaultxdpi; } width *= xscale; height *= yscale; delete ir; // deleting NULL is safe // Create image node Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image"); sp_repr_set_svg_double(image_node, "width", width); sp_repr_set_svg_double(image_node, "height", height); // Added 11 Feb 2014 as we now honor "preserveAspectRatio" and this is // what Inkscaper's expect. image_node->setAttribute("preserveAspectRatio", "none"); if( scale.compare( "auto" ) != 0 ) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "image-rendering", scale.c_str()); sp_repr_css_set(image_node, css, "style"); sp_repr_css_attr_unref( css ); } if (embed) { sp_embed_image(image_node, pb.get()); } else { // convert filename to uri gchar* _uri = g_filename_to_uri(uri, NULL, NULL); if(_uri) { image_node->setAttribute("xlink:href", _uri); g_free(_uri); } else { image_node->setAttribute("xlink:href", uri); } } // Add it to the current layer doc->getRoot()->appendChildRepr(image_node); Inkscape::GC::release(image_node); fit_canvas_to_drawing(doc); // Set viewBox if it doesn't exist if (!doc->getRoot()->viewBox_set) { //std::cout << "Viewbox not set, setting" << std::endl; doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit()))); } // restore undo, as now this document may be shown to the user if a bitmap was opened DocumentUndo::setUndoSensitive(doc, saved); } else { printf("GdkPixbuf loader failed\n"); } return doc; }
SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) { RVNGFileStream input(uri); if (!libvisio::VisioDocument::isSupported(&input)) { return NULL; } RVNGStringVector output; #if WITH_LIBVISIO01 librevenge::RVNGSVGDrawingGenerator generator(output, "svg"); if (!libvisio::VisioDocument::parse(&input, &generator)) { #else if (!libvisio::VisioDocument::generateSVG(&input, output)) { #endif return NULL; } if (output.empty()) { return NULL; } std::vector<RVNGString> tmpSVGOutput; for (unsigned i=0; i<output.size(); ++i) { RVNGString tmpString("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); tmpString.append(output[i]); tmpSVGOutput.push_back(tmpString); } unsigned page_num = 1; // If only one page is present, import that one without bothering user if (tmpSVGOutput.size() > 1) { VsdImportDialog *dlg = 0; if (inkscape_use_gui()) { dlg = new VsdImportDialog(tmpSVGOutput); if (!dlg->showDialog()) { delete dlg; return NULL; } } // Get needed page if (dlg) { page_num = dlg->getSelectedPage(); if (page_num < 1) page_num = 1; if (page_num > tmpSVGOutput.size()) page_num = tmpSVGOutput.size(); } } SPDocument * doc = SPDocument::createNewDocFromMem(tmpSVGOutput[page_num-1].cstr(), strlen(tmpSVGOutput[page_num-1].cstr()), TRUE); // Set viewBox if it doesn't exist if (!doc->getRoot()->viewBox_set) { doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDefaultUnit()), doc->getHeight().value(doc->getDefaultUnit()))); } return doc; } #include "clear-n_.h" void VsdInput::init(void) { /* VSD */ Inkscape::Extension::build_from_mem( "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" "<name>" N_("VSD Input") "</name>\n" "<id>org.inkscape.input.vsd</id>\n" "<input>\n" "<extension>.vsd</extension>\n" "<mimetype>application/vnd.visio</mimetype>\n" "<filetypename>" N_("Microsoft Visio Diagram (*.vsd)") "</filetypename>\n" "<filetypetooltip>" N_("File format used by Microsoft Visio 6 and later") "</filetypetooltip>\n" "</input>\n" "</inkscape-extension>", new VsdInput()); /* VDX */ Inkscape::Extension::build_from_mem( "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" "<name>" N_("VDX Input") "</name>\n" "<id>org.inkscape.input.vdx</id>\n" "<input>\n" "<extension>.vdx</extension>\n" "<mimetype>application/vnd.visio</mimetype>\n" "<filetypename>" N_("Microsoft Visio XML Diagram (*.vdx)") "</filetypename>\n" "<filetypetooltip>" N_("File format used by Microsoft Visio 2010 and later") "</filetypetooltip>\n" "</input>\n" "</inkscape-extension>", new VsdInput()); /* VSDM */ Inkscape::Extension::build_from_mem( "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" "<name>" N_("VSDM Input") "</name>\n" "<id>org.inkscape.input.vsdm</id>\n" "<input>\n" "<extension>.vsdm</extension>\n" "<mimetype>application/vnd.visio</mimetype>\n" "<filetypename>" N_("Microsoft Visio 2013 drawing (*.vsdm)") "</filetypename>\n" "<filetypetooltip>" N_("File format used by Microsoft Visio 2013 and later") "</filetypetooltip>\n" "</input>\n" "</inkscape-extension>", new VsdInput()); /* VSDX */ Inkscape::Extension::build_from_mem( "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" "<name>" N_("VSDX Input") "</name>\n" "<id>org.inkscape.input.vsdx</id>\n" "<input>\n" "<extension>.vsdx</extension>\n" "<mimetype>application/vnd.visio</mimetype>\n" "<filetypename>" N_("Microsoft Visio 2013 drawing (*.vsdx)") "</filetypename>\n" "<filetypetooltip>" N_("File format used by Microsoft Visio 2013 and later") "</filetypetooltip>\n" "</input>\n" "</inkscape-extension>", new VsdInput()); return; } // init
static void sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) { if (g_object_get_data(G_OBJECT(spw), "update")) { return; } UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(G_OBJECT(spw), "tracker")); if ( !tracker || tracker->isUpdating() ) { /* * When only units are being changed, don't treat changes * to adjuster values as object changes. */ return; } g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *document = sp_desktop_document(desktop); document->ensureUpToDate (); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Geom::OptRect bbox_vis = selection->visualBounds(); Geom::OptRect bbox_geom = selection->geometricBounds(); int prefs_bbox = prefs->getInt("/tools/bounding_box"); SPItem::BBoxType bbox_type = (prefs_bbox == 0)? SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX; Geom::OptRect bbox_user = selection->bounds(bbox_type); if ( !bbox_user ) { g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); return; } gdouble x0 = 0; gdouble y0 = 0; gdouble x1 = 0; gdouble y1 = 0; gdouble xrel = 0; gdouble yrel = 0; SPUnit const &unit = *tracker->getActiveUnit(); GtkAdjustment* a_x = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "X" ) ); GtkAdjustment* a_y = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "Y" ) ); GtkAdjustment* a_w = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "width" ) ); GtkAdjustment* a_h = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "height" ) ); if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { x0 = sp_units_get_pixels (gtk_adjustment_get_value (a_x), unit); y0 = sp_units_get_pixels (gtk_adjustment_get_value (a_y), unit); x1 = x0 + sp_units_get_pixels (gtk_adjustment_get_value (a_w), unit); xrel = sp_units_get_pixels (gtk_adjustment_get_value (a_w), unit) / bbox_user->dimensions()[Geom::X]; y1 = y0 + sp_units_get_pixels (gtk_adjustment_get_value (a_h), unit); yrel = sp_units_get_pixels (gtk_adjustment_get_value (a_h), unit) / bbox_user->dimensions()[Geom::Y]; } else { double const x0_propn = gtk_adjustment_get_value (a_x) * unit.unittobase; x0 = bbox_user->min()[Geom::X] * x0_propn; double const y0_propn = gtk_adjustment_get_value (a_y) * unit.unittobase; y0 = y0_propn * bbox_user->min()[Geom::Y]; xrel = gtk_adjustment_get_value (a_w) * unit.unittobase; x1 = x0 + xrel * bbox_user->dimensions()[Geom::X]; yrel = gtk_adjustment_get_value (a_h) * unit.unittobase; y1 = y0 + yrel * bbox_user->dimensions()[Geom::Y]; } // Keep proportions if lock is on GtkToggleAction *lock = GTK_TOGGLE_ACTION( g_object_get_data(G_OBJECT(spw), "lock") ); if ( gtk_toggle_action_get_active(lock) ) { if (adj == a_h) { x1 = x0 + yrel * bbox_user->dimensions()[Geom::X]; } else if (adj == a_w) { y1 = y0 + xrel * bbox_user->dimensions()[Geom::Y]; } } // scales and moves, in px double mh = fabs(x0 - bbox_user->min()[Geom::X]); double sh = fabs(x1 - bbox_user->max()[Geom::X]); double mv = fabs(y0 - bbox_user->min()[Geom::Y]); double sv = fabs(y1 - bbox_user->max()[Geom::Y]); // unless the unit is %, convert the scales and moves to the unit if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { mh = sp_pixels_get_units (mh, unit); sh = sp_pixels_get_units (sh, unit); mv = sp_pixels_get_units (mv, unit); sv = sp_pixels_get_units (sv, unit); } // do the action only if one of the scales/moves is greater than half the last significant // digit in the spinbox (currently spinboxes have 3 fractional digits, so that makes 0.0005). If // the value was changed by the user, the difference will be at least that much; otherwise it's // just rounding difference between the spinbox value and actual value, so no action is // performed char const * const actionkey = ( mh > 5e-4 ? "selector:toolbar:move:horizontal" : sh > 5e-4 ? "selector:toolbar:scale:horizontal" : mv > 5e-4 ? "selector:toolbar:move:vertical" : sv > 5e-4 ? "selector:toolbar:scale:vertical" : NULL ); if (actionkey != NULL) { // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed sp_desktop_canvas(desktop)->forceFullRedrawAfterInterruptions(0); int transform_stroke = prefs->getBool("/options/transform/stroke", true) ? 1 : 0; Geom::Affine scaler; if (bbox_type == SPItem::VISUAL_BBOX) { scaler = get_scale_transform_for_variable_stroke (*bbox_vis, *bbox_geom, transform_stroke, x0, y0, x1, y1); } else { // 1) We could have use the newer get_scale_transform_for_variable_stroke() here, but to avoid regressions // we'll just use the old get_scale_transform_for_uniform_stroke() for now. // 2) get_scale_transform_for_uniform_stroke() is intended for visual bounding boxes, not geometrical ones! // we'll trick it into using a geometric bounding box though, by setting the stroke width to zero scaler = get_scale_transform_for_uniform_stroke (*bbox_geom, 0, false, x0, y0, x1, y1); } sp_selection_apply_affine(selection, scaler); DocumentUndo::maybeDone(document, actionkey, SP_VERB_CONTEXT_SELECT, _("Transform by toolbar")); // resume interruptibility sp_desktop_canvas(desktop)->endForcedFullRedraws(); } g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); }
void text_flow_into_shape() { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) return; SPDocument *doc = sp_desktop_document (desktop); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::Selection *selection = sp_desktop_selection(desktop); SPItem *text = text_or_flowtext_in_selection(selection); SPItem *shape = shape_in_selection(selection); if (!text || !shape || g_slist_length((GSList *) selection->itemList()) < 2) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>a text</b> and one or more <b>paths or shapes</b> to flow text into frame.")); return; } if (SP_IS_TEXT(text)) { // remove transform from text, but recursively scale text's fontsize by the expansion SP_TEXT(text)->_adjustFontsizeRecursive(text, NR::expansion(SP_ITEM(text)->transform)); SP_OBJECT_REPR(text)->setAttribute("transform", NULL); } Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot"); root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create root_repr->setAttribute("style", SP_OBJECT_REPR(text)->attribute("style")); // fixme: transfer style attrs too SP_OBJECT_REPR(SP_OBJECT_PARENT(shape))->appendChild(root_repr); SPObject *root_object = doc->getObjectByRepr(root_repr); g_return_if_fail(SP_IS_FLOWTEXT(root_object)); Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion"); root_repr->appendChild(region_repr); SPObject *object = doc->getObjectByRepr(region_repr); g_return_if_fail(SP_IS_FLOWREGION(object)); /* Add clones */ for (GSList *items = (GSList *) selection->itemList(); items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); if (SP_IS_SHAPE(item)){ Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); clone->setAttribute("x", "0"); clone->setAttribute("y", "0"); clone->setAttribute("xlink:href", g_strdup_printf("#%s", SP_OBJECT_REPR(item)->attribute("id"))); // add the new clone to the region region_repr->appendChild(clone); } } if (SP_IS_TEXT(text)) { // flow from text, as string Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); object = doc->getObjectByRepr(para_repr); g_return_if_fail(SP_IS_FLOWPARA(object)); Inkscape::Text::Layout const *layout = te_get_layout(text); Glib::ustring text_ustring = sp_te_get_string_multiline(text, layout->begin(), layout->end()); Inkscape::XML::Node *text_repr = xml_doc->createTextNode(text_ustring.c_str()); // FIXME: transfer all formatting! and convert newlines into flowParas! para_repr->appendChild(text_repr); Inkscape::GC::release(para_repr); Inkscape::GC::release(text_repr); } else { // reflow an already flowed text, preserving paras for (SPObject *o = SP_OBJECT(text)->children; o != NULL; o = o->next) { if (SP_IS_FLOWPARA(o)) { Inkscape::XML::Node *para_repr = SP_OBJECT_REPR(o)->duplicate(xml_doc); root_repr->appendChild(para_repr); object = doc->getObjectByRepr(para_repr); g_return_if_fail(SP_IS_FLOWPARA(object)); Inkscape::GC::release(para_repr); } } } SP_OBJECT(text)->deleteObject (true); sp_document_done(doc, SP_VERB_CONTEXT_TEXT, _("Flow text into shape")); sp_desktop_selection(desktop)->set(SP_ITEM(root_object)); Inkscape::GC::release(root_repr); Inkscape::GC::release(region_repr); }
void sp_selected_path_combine(SPDesktop *desktop) { Inkscape::Selection *selection = desktop->getSelection(); SPDocument *doc = desktop->getDocument(); std::vector<SPItem*> items(selection->itemList()); if (items.size() < 1) { desktop->getMessageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to combine.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Combining paths...")); // set "busy" cursor desktop->setWaitingCursor(); items = sp_degroup_list (items); // descend into any groups in selection std::vector<SPItem*> to_paths; for (std::vector<SPItem*>::const_reverse_iterator i = items.rbegin(); i != items.rend(); ++i) { if (!dynamic_cast<SPPath *>(*i) && !dynamic_cast<SPGroup *>(*i)) { to_paths.push_back(*i); } } std::vector<Inkscape::XML::Node*> converted; bool did = sp_item_list_to_curves(to_paths, items, converted); for (std::vector<Inkscape::XML::Node*>::const_iterator i = converted.begin(); i != converted.end(); ++i) items.push_back((SPItem*)doc->getObjectByRepr(*i)); items = sp_degroup_list (items); // converting to path may have added more groups, descend again sort(items.begin(),items.end(),less_than_items); assert(!items.empty()); // cannot be NULL because of list length check at top of function // remember the position, id, transform and style of the topmost path, they will be assigned to the combined one gint position = 0; char const *id = NULL; char const *transform = NULL; char const *style = NULL; char const *path_effect = NULL; SPCurve* curve = NULL; SPItem *first = NULL; Inkscape::XML::Node *parent = NULL; if (did) { selection->clear(); } for (std::vector<SPItem*>::const_reverse_iterator i = items.rbegin(); i != items.rend(); ++i){ SPItem *item = *i; SPPath *path = dynamic_cast<SPPath *>(item); if (!path) { continue; } if (!did) { selection->clear(); did = true; } SPCurve *c = path->get_curve_for_edit(); if (first == NULL) { // this is the topmost path first = item; parent = first->getRepr()->parent(); position = first->getRepr()->position(); id = first->getRepr()->attribute("id"); transform = first->getRepr()->attribute("transform"); // FIXME: merge styles of combined objects instead of using the first one's style style = first->getRepr()->attribute("style"); path_effect = first->getRepr()->attribute("inkscape:path-effect"); //c->transform(item->transform); curve = c; } else { c->transform(item->getRelativeTransform(first)); curve->append(c, false); c->unref(); // reduce position only if the same parent if (item->getRepr()->parent() == parent) { position--; } // delete the object for real, so that its clones can take appropriate action item->deleteObject(); } } if (did) { first->deleteObject(false); // delete the topmost. Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); // restore id, transform, path effect, and style repr->setAttribute("id", id); if (transform) { repr->setAttribute("transform", transform); } repr->setAttribute("style", style); repr->setAttribute("inkscape:path-effect", path_effect); // set path data corresponding to new curve gchar *dstring = sp_svg_write_path(curve->get_pathvector()); curve->unref(); if (path_effect) { repr->setAttribute("inkscape:original-d", dstring); } else { repr->setAttribute("d", dstring); } g_free(dstring); // add the new group to the parent of the topmost parent->appendChild(repr); // move to the position of the topmost, reduced by the number of deleted items repr->setPosition(position > 0 ? position : 0); DocumentUndo::done(desktop->getDocument(), SP_VERB_SELECTION_COMBINE, _("Combine")); selection->set(repr); Inkscape::GC::release(repr); } else { desktop->getMessageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to combine in the selection.")); } desktop->clearWaitingCursor(); }
bool sp_item_list_to_curves(const std::vector<SPItem*> &items, std::vector<SPItem*>& selected, std::vector<Inkscape::XML::Node*> &to_select, bool skip_all_lpeitems) { bool did = false; for (std::vector<SPItem*>::const_iterator i = items.begin(); i != items.end(); ++i){ SPItem *item = *i; g_assert(item != NULL); SPDocument *document = item->document; SPGroup *group = dynamic_cast<SPGroup *>(item); if ( skip_all_lpeitems && dynamic_cast<SPLPEItem *>(item) && !group ) // also convert objects in an SPGroup when skip_all_lpeitems is set. { continue; } SPPath *path = dynamic_cast<SPPath *>(item); if (path && !path->_curve_before_lpe) { // remove connector attributes if (item->getAttribute("inkscape:connector-type") != NULL) { item->removeAttribute("inkscape:connection-start"); item->removeAttribute("inkscape:connection-end"); item->removeAttribute("inkscape:connector-type"); item->removeAttribute("inkscape:connector-curvature"); did = true; } continue; // already a path, and no path effect } SPBox3D *box = dynamic_cast<SPBox3D *>(item); if (box) { // convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group Inkscape::XML::Node *repr = box3d_convert_to_group(box)->getRepr(); if (repr) { to_select.insert(to_select.begin(),repr); did = true; selected.erase(remove(selected.begin(), selected.end(), item), selected.end()); } continue; } if (group) { group->removeAllPathEffects(true); std::vector<SPItem*> item_list = sp_item_group_item_list(group); std::vector<Inkscape::XML::Node*> item_to_select; std::vector<SPItem*> item_selected; if (sp_item_list_to_curves(item_list, item_selected, item_to_select)) did = true; continue; } Inkscape::XML::Node *repr = sp_selected_item_to_curved_repr(item, 0); if (!repr) continue; did = true; selected.erase(remove(selected.begin(), selected.end(), item), selected.end()); // remember the position of the item gint pos = item->getRepr()->position(); // remember parent Inkscape::XML::Node *parent = item->getRepr()->parent(); // remember id char const *id = item->getRepr()->attribute("id"); // remember title gchar *title = item->title(); // remember description gchar *desc = item->desc(); // remember highlight color guint32 highlight_color = 0; if (item->isHighlightSet()) highlight_color = item->highlight_color(); // It's going to resurrect, so we delete without notifying listeners. item->deleteObject(false); // restore id repr->setAttribute("id", id); // add the new repr to the parent parent->appendChild(repr); SPObject* newObj = document->getObjectByRepr(repr); if (title && newObj) { newObj->setTitle(title); g_free(title); } if (desc && newObj) { newObj->setDesc(desc); g_free(desc); } if (highlight_color && newObj) { SP_ITEM(newObj)->setHighlightColor( highlight_color ); } // move to the saved position repr->setPosition(pos > 0 ? pos : 0); /* Buglet: We don't re-add the (new version of the) object to the selection of any other * desktops where it was previously selected. */ to_select.insert(to_select.begin(),repr); Inkscape::GC::release(repr); } return did; }
gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi) { gboolean sensitive = FALSE; if (blocked) { return sensitive; } SPDocument *document = sp_desktop_document(desktop); GtkTreeIter iter; GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)); blocked = TRUE; /* Clear old list, if there is any */ gtk_list_store_clear(store); GSList *gl = NULL; const GSList *gradients = document->getResourceList("gradient"); for (const GSList *i = gradients; i != NULL; i = i->next) { SPGradient *grad = SP_GRADIENT(i->data); if ( grad->hasStops() && !grad->isSolid() ) { gl = g_slist_prepend(gl, i->data); } } gl = g_slist_reverse(gl); guint pos = 0; if (!gl) { // The document has no gradients gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); sensitive = FALSE; } else if (selection_empty) { // Document has gradients, but nothing is currently selected. gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("Nothing selected"), 1, NULL, 2, NULL, -1); sensitive = FALSE; } else { if (gr_selected == NULL) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); sensitive = FALSE; } if (gr_multi) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("Multiple gradients"), 1, NULL, 2, NULL, -1); sensitive = FALSE; } guint idx = 0; while (gl) { SPGradient *gradient = SP_GRADIENT(gl->data); gl = g_slist_remove(gl, gradient); Glib::ustring label = gr_prepare_label(gradient); GdkPixbuf *pixb = sp_gradient_to_pixbuf(gradient, 64, 16); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, label.c_str(), 1, pixb, 2, gradient, -1); if (gradient == gr_selected) { pos = idx; } idx ++; } sensitive = TRUE; } /* Select the current gradient, or the Multi/Nothing line */ if (gr_multi || gr_selected == NULL) { gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box) , 0); } else { gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box) , pos); } blocked = FALSE; return sensitive; }
SPItem *SPUse::unlink() { Inkscape::XML::Node *repr = this->getRepr(); if (!repr) { return NULL; } Inkscape::XML::Node *parent = repr->parent(); SPDocument *document = this->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); // Track the ultimate source of a chain of uses. SPItem *orig = this->root(); if (!orig) { return NULL; } // Calculate the accumulated transform, starting from the original. Geom::Affine t = this->get_root_transform(); Inkscape::XML::Node *copy = NULL; if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) { Inkscape::XML::Node *newchild = child->duplicate(xml_doc); copy->appendChild(newchild); } } else { // just copy copy = orig->getRepr()->duplicate(xml_doc); } // Add the duplicate repr just after the existing one. parent->addChild(copy, repr); // Retrieve the SPItem of the resulting repr. SPObject *unlinked = document->getObjectByRepr(copy); // Merge style from the use. unlinked->style->merge( this->style ); unlinked->style->cascade( unlinked->parent->style ); unlinked->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(this, NULL); Inkscape::GC::anchor(repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. this->deleteObject(false); // Give the copy our old id and let go of our old repr. copy->setAttribute("id", repr->attribute("id")); Inkscape::GC::release(repr); // Remove tiled clone attrs. copy->setAttribute("inkscape:tiled-clone-of", NULL); copy->setAttribute("inkscape:tile-w", NULL); copy->setAttribute("inkscape:tile-h", NULL); copy->setAttribute("inkscape:tile-cx", NULL); copy->setAttribute("inkscape:tile-cy", NULL); // Establish the succession and let go of our object. this->setSuccessor(unlinked); sp_object_unref(this, NULL); SPItem *item = dynamic_cast<SPItem *>(unlinked); g_assert(item != NULL); // Set the accummulated transform. { Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. item->doWriteTransform(item->getRepr(), t, &nomove); } return item; }
/** * This function will create a new tspan element with the same attributes as * the tref had and add the same text as a child. The tref is replaced in the * tree with the new tspan. * The code is based partially on sp_use_unlink */ SPObject * sp_tref_convert_to_tspan(SPObject *obj) { SPObject * new_tspan = NULL; //////////////////// // BASE CASE //////////////////// if (SP_IS_TREF(obj)) { SPTRef *tref = SP_TREF(obj); if (tref && tref->stringChild) { Inkscape::XML::Node *tref_repr = tref->getRepr(); Inkscape::XML::Node *tref_parent = tref_repr->parent(); SPDocument *document = tref->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *new_tspan_repr = xml_doc->createElement("svg:tspan"); // Add the new tspan element just after the current tref tref_parent->addChild(new_tspan_repr, tref_repr); Inkscape::GC::release(new_tspan_repr); new_tspan = document->getObjectByRepr(new_tspan_repr); // Create a new string child for the tspan Inkscape::XML::Node *new_string_repr = tref->stringChild->getRepr()->duplicate(xml_doc); new_tspan_repr->addChild(new_string_repr, NULL); //SPObject * new_string_child = document->getObjectByRepr(new_string_repr); // Merge style from the tref SPStyle *new_tspan_sty = new_tspan->style; SPStyle const *tref_sty = tref->style; sp_style_merge_from_dying_parent(new_tspan_sty, tref_sty); sp_style_merge_from_parent(new_tspan_sty, new_tspan->parent->style); new_tspan->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(tref, NULL); Inkscape::GC::anchor(tref_repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. tref->deleteObject(false); // Give the copy our old id and let go of our old repr. new_tspan_repr->setAttribute("id", tref_repr->attribute("id")); Inkscape::GC::release(tref_repr); // Establish the succession and let go of our object. tref->setSuccessor(new_tspan); sp_object_unref(tref, NULL); } } //////////////////// // RECURSIVE CASE //////////////////// else { GSList *l = NULL; for (SPObject *child = obj->firstChild() ; child != NULL ; child = child->getNext() ) { sp_object_ref(child, obj); l = g_slist_prepend (l, child); } l = g_slist_reverse (l); while (l) { SPObject *child = reinterpret_cast<SPObject *>(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); // Note that there may be more than one conversion happening here, so if it's not a // tref being passed into this function, the returned value can't be specifically known new_tspan = sp_tref_convert_to_tspan(child); sp_object_unref(child, obj); } } return new_tspan; }
bool sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_select, bool skip_all_lpeitems) { bool did = false; for (; items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); SPDocument *document = item->document; if ( skip_all_lpeitems && SP_IS_LPE_ITEM(item) && !SP_IS_GROUP(item) ) // also convert objects in an SPGroup when skip_all_lpeitems is set. { continue; } if (SP_IS_PATH(item) && !SP_SHAPE(item)->_curve_before_lpe) { // remove connector attributes if (item->getAttribute("inkscape:connector-type") != NULL) { item->removeAttribute("inkscape:connection-start"); item->removeAttribute("inkscape:connection-end"); item->removeAttribute("inkscape:connector-type"); item->removeAttribute("inkscape:connector-curvature"); did = true; } continue; // already a path, and no path effect } if (SP_IS_BOX3D(item)) { // convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group Inkscape::XML::Node *repr = box3d_convert_to_group(SP_BOX3D(item))->getRepr(); if (repr) { *to_select = g_slist_prepend (*to_select, repr); did = true; *selected = g_slist_remove (*selected, item); } continue; } if (SP_IS_GROUP(item)) { SP_LPE_ITEM(item)->removeAllPathEffects(true); GSList *item_list = sp_item_group_item_list(SP_GROUP(item)); GSList *item_to_select = NULL; GSList *item_selected = NULL; if (sp_item_list_to_curves(item_list, &item_selected, &item_to_select)) did = true; g_slist_free(item_list); g_slist_free(item_to_select); g_slist_free(item_selected); continue; } Inkscape::XML::Node *repr = sp_selected_item_to_curved_repr(item, 0); if (!repr) continue; did = true; *selected = g_slist_remove (*selected, item); // remember the position of the item gint pos = item->getRepr()->position(); // remember parent Inkscape::XML::Node *parent = item->getRepr()->parent(); // remember id char const *id = item->getRepr()->attribute("id"); // remember title gchar *title = item->title(); // remember description gchar *desc = item->desc(); // It's going to resurrect, so we delete without notifying listeners. item->deleteObject(false); // restore id repr->setAttribute("id", id); // add the new repr to the parent parent->appendChild(repr); SPObject* newObj = document->getObjectByRepr(repr); if (title && newObj) { newObj->setTitle(title); g_free(title); } if (desc && newObj) { newObj->setDesc(desc); g_free(desc); } // move to the saved position repr->setPosition(pos > 0 ? pos : 0); /* Buglet: We don't re-add the (new version of the) object to the selection of any other * desktops where it was previously selected. */ *to_select = g_slist_prepend (*to_select, repr); Inkscape::GC::release(repr); } return did; }
void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); EgeAdjustmentAction* eact = 0; SPDocument *document = sp_desktop_document (desktop); Persp3DImpl *persp_impl = document->getCurrentPersp3DImpl(); EgeAdjustmentAction* box3d_angle_x = 0; EgeAdjustmentAction* box3d_angle_y = 0; EgeAdjustmentAction* box3d_angle_z = 0; /* Angle X */ { gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; eact = create_adjustment_action( "3DBoxAngleXAction", _("Angle in X direction"), _("Angle X:"), // Translators: PL is short for 'perspective line' _("Angle of PLs in X direction"), "/tools/shapes/3dbox/box3d_angle_x", 30, GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-box3d", -360.0, 360.0, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), box3d_angle_x_value_changed ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); g_object_set_data( holder, "box3d_angle_x_action", eact ); box3d_angle_x = eact; } if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::X)) { gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); } /* VP X state */ { InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXStateAction", // Translators: VP is short for 'vanishing point' _("State of VP in X direction"), _("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"), INKSCAPE_ICON("perspective-parallel"), Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_object_set_data( holder, "box3d_vp_x_state_action", act ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_x_state_changed), box3d_angle_x ); gtk_action_set_sensitive( GTK_ACTION(box3d_angle_x), !prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) ); } /* Angle Y */ { gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; eact = create_adjustment_action( "3DBoxAngleYAction", _("Angle in Y direction"), _("Angle Y:"), // Translators: PL is short for 'perspective line' _("Angle of PLs in Y direction"), "/tools/shapes/3dbox/box3d_angle_y", 30, GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, -360.0, 360.0, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), box3d_angle_y_value_changed ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); g_object_set_data( holder, "box3d_angle_y_action", eact ); box3d_angle_y = eact; } if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Y)) { gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); } /* VP Y state */ { InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYStateAction", // Translators: VP is short for 'vanishing point' _("State of VP in Y direction"), _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"), INKSCAPE_ICON("perspective-parallel"), Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_object_set_data( holder, "box3d_vp_y_state_action", act ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_y_state_changed), box3d_angle_y ); gtk_action_set_sensitive( GTK_ACTION(box3d_angle_y), !prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) ); } /* Angle Z */ { gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; eact = create_adjustment_action( "3DBoxAngleZAction", _("Angle in Z direction"), _("Angle Z:"), // Translators: PL is short for 'perspective line' _("Angle of PLs in Z direction"), "/tools/shapes/3dbox/box3d_angle_z", 30, GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, -360.0, 360.0, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), box3d_angle_z_value_changed ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); g_object_set_data( holder, "box3d_angle_z_action", eact ); box3d_angle_z = eact; } if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Z)) { gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); } /* VP Z state */ { InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZStateAction", // Translators: VP is short for 'vanishing point' _("State of VP in Z direction"), _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"), INKSCAPE_ICON("perspective-parallel"), Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_object_set_data( holder, "box3d_vp_z_state_action", act ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_z_state_changed), box3d_angle_z ); gtk_action_set_sensitive( GTK_ACTION(box3d_angle_z), !prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) ); gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) ); } sigc::connection *connection = new sigc::connection( sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), (GObject *)holder)) ); g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection); g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder); }
SPObject *get_stock_item(gchar const *urn, gboolean stock) { g_assert(urn != NULL); /* check its an inkscape URN */ if (!strncmp (urn, "urn:inkscape:", 13)) { gchar const *e = urn + 13; int a = 0; gchar * name = g_strdup(e); gchar *name_p = name; while (*name_p != ':' && *name_p != '\0'){ name_p++; a++; } if (*name_p ==':') { name_p++; } gchar * base = g_strndup(e, a); SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPDefs *defs = doc->getDefs(); if (!defs) { g_free(base); return NULL; } SPObject *object = NULL; if (!strcmp(base, "marker") && !stock) { for ( SPObject *child = defs->firstChild(); child; child = child->getNext() ) { if (child->getRepr()->attribute("inkscape:stockid") && !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) && SP_IS_MARKER(child)) { object = child; } } } else if (!strcmp(base,"pattern") && !stock) { for ( SPObject *child = defs->firstChild() ; child; child = child->getNext() ) { if (child->getRepr()->attribute("inkscape:stockid") && !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) && SP_IS_PATTERN(child)) { object = child; } } } else if (!strcmp(base,"gradient") && !stock) { for ( SPObject *child = defs->firstChild(); child; child = child->getNext() ) { if (child->getRepr()->attribute("inkscape:stockid") && !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) && SP_IS_GRADIENT(child)) { object = child; } } } if (object == NULL) { if (!strcmp(base, "marker")) { object = sp_marker_load_from_svg(name_p, doc); } else if (!strcmp(base, "pattern")) { object = sp_pattern_load_from_svg(name_p, doc); } else if (!strcmp(base, "gradient")) { object = sp_gradient_load_from_svg(name_p, doc); } } g_free(base); g_free(name); if (object) { object->getRepr()->setAttribute("inkscape:isstock", "true"); } return object; } else { SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPObject *object = doc->getObjectById(urn); return object; } }
void text_unflow () { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) return; SPDocument *doc = sp_desktop_document (desktop); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::Selection *selection = sp_desktop_selection(desktop); if (!flowtext_in_selection(selection) || g_slist_length((GSList *) selection->itemList()) < 1) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>a flowed text</b> to unflow it.")); return; } GSList *new_objs = NULL; GSList *old_objs = NULL; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { if (!SP_IS_FLOWTEXT(SP_OBJECT(items->data))) { continue; } SPItem *flowtext = SP_ITEM(items->data); if (sp_te_get_string_multiline(flowtext) == NULL) { // flowtext is empty continue; } /* Create <text> */ Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create /* Set style */ rtext->setAttribute("style", SP_OBJECT_REPR(flowtext)->attribute("style")); // fixme: transfer style attrs too; and from descendants NRRect bbox; sp_item_invoke_bbox(SP_ITEM(flowtext), &bbox, sp_item_i2doc_affine(SP_ITEM(flowtext)), TRUE); Geom::Point xy(bbox.x0, bbox.y0); if (xy[Geom::X] != 1e18 && xy[Geom::Y] != 1e18) { sp_repr_set_svg_double(rtext, "x", xy[Geom::X]); sp_repr_set_svg_double(rtext, "y", xy[Geom::Y]); } /* Create <tspan> */ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); // otherwise, why bother creating the tspan? rtext->addChild(rtspan, NULL); gchar *text_string = sp_te_get_string_multiline(flowtext); Inkscape::XML::Node *text_repr = xml_doc->createTextNode(text_string); // FIXME: transfer all formatting!!! free(text_string); rtspan->appendChild(text_repr); SP_OBJECT_REPR(SP_OBJECT_PARENT(flowtext))->appendChild(rtext); SPObject *text_object = doc->getObjectByRepr(rtext); new_objs = g_slist_prepend (new_objs, text_object); old_objs = g_slist_prepend (old_objs, flowtext); Inkscape::GC::release(rtext); Inkscape::GC::release(rtspan); Inkscape::GC::release(text_repr); } selection->clear(); selection->setList(new_objs); for (GSList *i = old_objs; i; i = i->next) { SP_OBJECT(i->data)->deleteObject (true); } g_slist_free (old_objs); g_slist_free (new_objs); sp_document_done(doc, SP_VERB_CONTEXT_TEXT, _("Unflow flowed text")); }