static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem) { g_return_if_fail(lpeitem != NULL); SPMask * mask = lpeitem->mask_ref->getObject(); if(mask) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); } SPClipPath * clipPath = lpeitem->clip_ref->getObject(); if(clipPath) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild())); } if (SP_IS_GROUP(lpeitem)) { GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); if (SP_IS_LPE_ITEM(subitem)) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem)); } } } else if (SP_IS_PATH(lpeitem)) { Inkscape::XML::Node *pathrepr = lpeitem->getRepr(); if ( !pathrepr->attribute("inkscape:original-d") ) { pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d")); } } }
/** * Adds menu items for pattern list - derived from marker code, left hb etc in to make addition of previews easier at some point. */ static void sp_pattern_menu_build (GtkWidget *combo, GSList *pattern_list, SPDocument */*source*/) { GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo))); GtkTreeIter iter; for (; pattern_list != NULL; pattern_list = pattern_list->next) { Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(pattern_list->data)->getRepr(); // label for combobox gchar const *label; if (repr->attribute("inkscape:stockid")) { label = _(repr->attribute("inkscape:stockid")); } else { label = _(repr->attribute("id")); } gchar const *patid = repr->attribute("id"); gboolean stockid = false; if (repr->attribute("inkscape:stockid")) { stockid = true; } gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COMBO_COL_LABEL, label, COMBO_COL_STOCK, stockid, COMBO_COL_PATTERN, patid, COMBO_COL_SEP, FALSE, -1); } }
bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) { bool changed = false; if ( doc ) { // TODO debug g_message("FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP"); // TODO debug g_message(" base is [%s]", doc->getBase()); std::vector<Glib::ustring> brokenHrefs = findBrokenLinks(doc); if ( !brokenHrefs.empty() ) { // TODO debug g_message(" FOUND SOME LINKS %d", static_cast<int>(brokenHrefs.size())); for ( std::vector<Glib::ustring>::iterator it = brokenHrefs.begin(); it != brokenHrefs.end(); ++it ) { // TODO debug g_message(" [%s]", it->c_str()); } } std::map<Glib::ustring, Glib::ustring> mapping = locateLinks(doc->getBase(), brokenHrefs); for ( std::map<Glib::ustring, Glib::ustring>::iterator it = mapping.begin(); it != mapping.end(); ++it ) { // TODO debug g_message(" [%s] ==> {%s}", it->first.c_str(), it->second.c_str()); } bool savedUndoState = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, true); GSList const *images = doc->getResourceList("image"); for (GSList const *it = images; it; it = it->next) { Inkscape::XML::Node *ir = static_cast<SPObject *>(it->data)->getRepr(); gchar const *href = ir->attribute("xlink:href"); if ( href ) { // TODO debug g_message(" consider [%s]", href); if ( mapping.find(href) != mapping.end() ) { // TODO debug g_message(" Found a replacement"); ir->setAttribute( "xlink:href", mapping[href].c_str() ); if ( ir->attribute( "sodipodi:absref" ) ) { ir->setAttribute( "sodipodi:absref", 0 ); // Remove this attribute } SPObject *updated = doc->getObjectByRepr(ir); if (updated) { // force immediate update of dependant attributes updated->updateRepr(); } changed = true; } } } if ( changed ) { DocumentUndo::done( doc, SP_VERB_DIALOG_XML_EDITOR, _("Fixup broken links") ); } DocumentUndo::setUndoSensitive(doc, savedUndoState); } return changed; }
std::string NodeTraits::get_type_string(Inkscape::XML::Node const &node) { std::string name; switch (node.type()) { case Inkscape::XML::TEXT_NODE: name = "string"; break; case Inkscape::XML::ELEMENT_NODE: { char const *const sptype = node.attribute("sodipodi:type"); if (sptype) { name = sptype; } else { name = node.name(); } break; } default: name = ""; break; } return name; }
Inkscape::XML::Node *Parameter::document_param_node(SPDocument * doc) { Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node * defs = doc->getDefs()->getRepr(); Inkscape::XML::Node * params = NULL; GQuark const name_quark = g_quark_from_string("inkscape:extension-params"); for (Inkscape::XML::Node * child = defs->firstChild(); child != NULL; child = child->next()) { if ((GQuark)child->code() == name_quark && !strcmp(child->attribute("extension"), extension->get_id())) { params = child; break; } } if (params == NULL) { params = xml_doc->createElement("inkscape:extension-param"); params->setAttribute("extension", extension->get_id()); defs->appendChild(params); Inkscape::GC::release(params); } return params; }
// Create a mask element (using passed elements), add it to <defs> const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath"); repr->setAttribute("clipPathUnits", "userSpaceOnUse"); defsrepr->appendChild(repr); const gchar *id = repr->attribute("id"); SPObject *clip_path_object = document->getObjectById(id); for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { Geom::Affine transform (item->transform); transform *= (*applyTransform); item->doWriteTransform(item->getRepr(), transform); } } Inkscape::GC::release(repr); return id; }
// Create a mask element (using passed elements), add it to <defs> const gchar * sp_clippath_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document); Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath"); repr->setAttribute("clipPathUnits", "userSpaceOnUse"); defsrepr->appendChild(repr); const gchar *id = repr->attribute("id"); SPObject *clip_path_object = document->getObjectById(id); for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { Geom::Matrix transform (item->transform); transform *= (*applyTransform); sp_item_write_transform(item, SP_OBJECT_REPR(item), transform); } } Inkscape::GC::release(repr); return id; }
std::vector<Glib::ustring> ResourceManagerImpl::findBrokenLinks( SPDocument *doc ) { std::vector<Glib::ustring> result; std::set<Glib::ustring> uniques; if ( doc ) { GSList const *images = doc->getResourceList("image"); for (GSList const *it = images; it; it = it->next) { Inkscape::XML::Node *ir = static_cast<SPObject *>(it->data)->getRepr(); gchar const *href = ir->attribute("xlink:href"); if ( href && ( uniques.find(href) == uniques.end() ) ) { std::string uri; if ( extractFilepath( href, uri ) ) { if ( Glib::path_is_absolute(uri) ) { if ( !Glib::file_test(uri, Glib::FILE_TEST_EXISTS) ) { result.push_back(href); uniques.insert(href); } } else { std::string combined = Glib::build_filename(doc->getBase(), uri); if ( !Glib::file_test(uri, Glib::FILE_TEST_EXISTS) ) { result.push_back(href); uniques.insert(href); } } } } } } return result; }
Glib::ustring sp_filter_get_new_result_name(SPFilter *filter) { g_assert(filter != NULL); int largest = 0; SPObject *primitive_obj = filter->children; while (primitive_obj) { if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) { Inkscape::XML::Node *repr = primitive_obj->getRepr(); char const *result = repr->attribute("result"); int index; if (result) { if (sscanf(result, "result%5d", &index) == 1) { if (index > largest) { largest = index; } } } } primitive_obj = primitive_obj->next; } return "result" + Glib::Ascii::dtostr(largest + 1); }
void spdc_create_single_dot(ToolBase *ec, Geom::Point const &pt, char const *tool, guint event_state) { g_return_if_fail(!strcmp(tool, "/tools/freehand/pen") || !strcmp(tool, "/tools/freehand/pencil")); Glib::ustring tool_path = tool; SPDesktop *desktop = ec->desktop; Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("sodipodi:type", "arc"); SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); // apply the tool's current style sp_desktop_apply_style_tool(desktop, repr, tool, false); // find out stroke width (TODO: is there an easier way??) double stroke_width = 3.0; gchar const *style_str = repr->attribute("style"); if (style_str) { SPStyle style(SP_ACTIVE_DOCUMENT); style.mergeString(style_str); stroke_width = style.stroke_width.computed; } // unset stroke and set fill color to former stroke color gchar * str; str = g_strdup_printf("fill:#%06x;stroke:none;", sp_desktop_get_color_tool(desktop, tool, false) >> 8); repr->setAttribute("style", str); g_free(str); // put the circle where the mouse click occurred and set the diameter to the // current stroke width, multiplied by the amount specified in the preferences Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Geom::Affine const i2d (item->i2dt_affine ()); Geom::Point pp = pt * i2d.inverse(); double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0); if (event_state & GDK_MOD1_MASK) { // TODO: We vary the dot size between 0.5*rad and 1.5*rad, where rad is the dot size // as specified in prefs. Very simple, but it might be sufficient in practice. If not, // we need to devise something more sophisticated. double s = g_random_double_range(-0.5, 0.5); rad *= (1 + s); } if (event_state & GDK_SHIFT_MASK) { // double the point size rad *= 2; } sp_repr_set_svg_double (repr, "sodipodi:cx", pp[Geom::X]); sp_repr_set_svg_double (repr, "sodipodi:cy", pp[Geom::Y]); sp_repr_set_svg_double (repr, "sodipodi:rx", rad * stroke_width); sp_repr_set_svg_double (repr, "sodipodi:ry", rad * stroke_width); item->updateRepr(); desktop->getSelection()->set(item); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating single dot")); DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE, _("Create single dot")); }
void SPLPEItem::apply_to_clippath(SPItem *item) { SPClipPath *clipPath = item->clip_ref->getObject(); if(clipPath) { SPObject * clip_data = clipPath->firstChild(); SPCurve * clip_curve = NULL; if (SP_IS_PATH(clip_data)) { clip_curve = SP_PATH(clip_data)->get_original_curve(); } else if(SP_IS_SHAPE(clip_data)) { clip_curve = SP_SHAPE(clip_data)->getCurve(); } else if(SP_IS_GROUP(clip_data)) { apply_to_clip_or_mask_group(SP_ITEM(clip_data), item); return; } if(clip_curve) { bool success = false; if(SP_IS_GROUP(this)){ clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this))); success = this->performPathEffect(clip_curve); clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse()); } else { success = this->performPathEffect(clip_curve); } Inkscape::XML::Node *reprClip = clip_data->getRepr(); if (success) { gchar *str = sp_svg_write_path(clip_curve->get_pathvector()); reprClip->setAttribute("d", str); g_free(str); } else { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = reprClip->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } clip_curve->unref(); } } if(SP_IS_GROUP(item)){ GSList const *item_list = sp_item_group_item_list(SP_GROUP(item)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); apply_to_clippath(SP_ITEM(subitem)); } } }
/* function which evaluates if item should be displayed */ bool sp_item_evaluate(SPItem const *item) { Inkscape::XML::Node *grepr = SP_OBJECT_REPR (item); for ( unsigned int i = 0 ; i < sizeof(_condition_handlers)/sizeof(_condition_handlers[0]) ; i++ ) { gchar const *value = grepr->attribute(_condition_handlers[i].attribute); if ( NULL == value ) continue; if (!_condition_handlers[i].evaluator(item, value)) return false; } return true; }
void Effect::createAndApply(const char* name, SPDocument *doc, SPItem *item) { // Path effect definition Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect"); repr->setAttribute("effect", name); SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute const gchar * repr_id = repr->attribute("id"); Inkscape::GC::release(repr); gchar *href = g_strdup_printf("#%s", repr_id); sp_lpe_item_add_path_effect(SP_LPE_ITEM(item), href, true); g_free(href); }
static void sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) { SPShape * const shape = (SPShape *) lpeitem; Inkscape::XML::Node *repr = shape->getRepr(); #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect"); #endif if (shape->_curve_before_lpe && sp_lpe_item_has_path_effect_recursive(lpeitem)) { SPCurve *curve = shape->_curve_before_lpe->copy(); /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe. * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ shape->setCurveInsync(curve, TRUE); bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve); if (success && write) { // could also do shape->getRepr()->updateRepr(); but only the d attribute needs updating. #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect writes 'd' attribute"); #endif if ( shape->_curve != NULL ) { gchar *str = sp_svg_write_path(shape->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } } else if (!success) { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = repr->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { shape->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); curve->unref(); } }
void Preferences::_getRawValue(Glib::ustring const &path, gchar const *&result) { // create node and attribute keys Glib::ustring node_key, attr_key; _keySplit(path, node_key, attr_key); // retrieve the attribute Inkscape::XML::Node *node = _getNode(node_key, false); if ( node == NULL ) { result = NULL; } else { gchar const *attr = node->attribute(attr_key.data()); if ( attr == NULL ) { result = NULL; } else { result = attr; } } }
void PathEffect::processPathEffects (SPDocument * doc, Inkscape::XML::Node * path) { gchar const * patheffectlist = path->attribute("inkscape:path-effects"); if (patheffectlist == NULL) return; gchar ** patheffects = g_strsplit(patheffectlist, ";", 128); Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc)); for (int i = 0; patheffects[i] != NULL && i < 128; i++) { gchar * patheffect = patheffects[i]; // This is weird, they should all be references... but anyway if (patheffect[0] != '#') continue; Inkscape::XML::Node * prefs = sp_repr_lookup_child(defs, "id", &(patheffect[1])); if (prefs == NULL) { continue; } gchar const * ext_id = prefs->attribute("extension"); if (ext_id == NULL) { continue; } Inkscape::Extension::PathEffect * peffect; peffect = dynamic_cast<Inkscape::Extension::PathEffect *>(Inkscape::Extension::db.get(ext_id)); if (peffect != NULL) { continue; } peffect->processPath(doc, path, prefs); } g_strfreev(patheffects); return; }
static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points, FreehandBase *dc, SPItem *item) { using namespace Inkscape::LivePathEffect; Effect::createAndApply(POWERSTROKE, dc->desktop->doc(), item); Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE(); static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points); // find out stroke width (TODO: is there an easier way??) SPDesktop *desktop = dc->desktop; Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); Inkscape::GC::release(repr); char const* tool = SP_IS_PEN_CONTEXT(dc) ? "/tools/freehand/pen" : "/tools/freehand/pencil"; // apply the tool's current style sp_desktop_apply_style_tool(desktop, repr, tool, false); double stroke_width = 1.0; char const *style_str = NULL; style_str = repr->attribute("style"); if (style_str) { SPStyle style(SP_ACTIVE_DOCUMENT); style.mergeString(style_str); stroke_width = style.stroke_width.computed; } std::ostringstream s; s.imbue(std::locale::classic()); s << points[0][Geom::X] << "," << stroke_width / 2.; // write powerstroke parameters: lpe->getRepr()->setAttribute("start_linecap_type", "zerowidth"); lpe->getRepr()->setAttribute("end_linecap_type", "zerowidth"); lpe->getRepr()->setAttribute("cusp_linecap_type", "round"); lpe->getRepr()->setAttribute("sort_points", "true"); lpe->getRepr()->setAttribute("interpolator_type", "CubicBezierJohan"); lpe->getRepr()->setAttribute("interpolator_beta", "0.2"); lpe->getRepr()->setAttribute("offset_points", s.str().c_str()); }
static void sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) { SPItem *item = SP_ITEM(object); GtkWidget *w; /* Link dialog */ w = gtk_menu_item_new_with_mnemonic(_("Image _Properties")); gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop); gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_properties), item); gtk_widget_show(w); gtk_menu_append(GTK_MENU(m), w); w = gtk_menu_item_new_with_mnemonic(_("Edit Externally...")); gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop); gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_edit), item); gtk_widget_show(w); gtk_menu_append(GTK_MENU(m), w); Inkscape::XML::Node *ir = SP_OBJECT_REPR(object); const gchar *href = ir->attribute("xlink:href"); if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { gtk_widget_set_sensitive( w, FALSE ); } }
static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop) { if (!SP_IS_GRADIENT(gradient)) { return; } blocked = TRUE; /* Clear old list, if there is any */ GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box")); if (!combo_box) { return; } GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box))); if (!store) { return; } gtk_list_store_clear(store); GtkTreeIter iter; /* Populate the combobox store */ GSList *sl = NULL; if ( gradient->hasStops() ) { for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { sl = g_slist_append(sl, ochild); } } } if (!sl) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, NULL, 1, _("No stops in gradient"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } else { for (; sl != NULL; sl = sl->next){ if (SP_IS_STOP(sl->data)){ SPStop *stop = SP_STOP(sl->data); Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr(); Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32())); GdkPixbuf *pb = cpv->toPixbuf(64, 16); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1); gtk_widget_set_sensitive (combo_box, FALSE); } } gtk_widget_set_sensitive(combo_box, TRUE); } /* Set history */ if (new_stop == NULL) { gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0); } else { select_stop_in_list(vb, gradient, new_stop); } blocked = FALSE; }
static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, SPCurve *curve) { using namespace Inkscape::LivePathEffect; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (item && SP_IS_LPE_ITEM(item)) { bool simplify = prefs->getInt(tool_name(dc) + "/simplify", 0); if(simplify){ double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0); tol = tol/(100.0*(102.0-tol)); std::ostringstream ss; ss << tol; spdc_apply_simplify(ss.str(), dc, item); sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); } if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) { Effect::createAndApply(SPIRO, dc->desktop->doc(), item); } if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) { Effect::createAndApply(BSPLINE, dc->desktop->doc(), item); } SPShape *sp_shape = dynamic_cast<SPShape *>(item); if (sp_shape) { curve = sp_shape->getCurve(); } //Store the clipboard path to apply in the future without the use of clipboard static Geom::PathVector previous_shape_pathv; shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0); bool shape_applied = false; SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); const char *cstroke = sp_repr_css_property(css_item, "stroke", "none"); static SPItem *bend_item; #define SHAPE_LENGTH 10 #define SHAPE_HEIGHT 10 if(shape == LAST_APPLIED){ shape = previous_shape_type; if(shape == CLIPBOARD || shape == BEND_CLIPBOARD){ shape = LAST_APPLIED; } } switch (shape) { case NONE: // don't apply any shape break; case TRIANGLE_IN: { // "triangle in" std::vector<Geom::Point> points(1); points[0] = Geom::Point(0., SHAPE_HEIGHT/2); spdc_apply_powerstroke_shape(points, dc, item); shape_applied = true; break; } case TRIANGLE_OUT: { // "triangle out" guint curve_length = curve->get_segment_count(); std::vector<Geom::Point> points(1); points[0] = Geom::Point((double)curve_length, SHAPE_HEIGHT/2); spdc_apply_powerstroke_shape(points, dc, item); shape_applied = true; break; } case ELLIPSE: { // "ellipse" SPCurve *c = new SPCurve(); const double C1 = 0.552; c->moveto(0, SHAPE_HEIGHT/2); c->curveto(0, (1 - C1) * SHAPE_HEIGHT/2, (1 - C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH/2, 0); c->curveto((1 + C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH, (1 - C1) * SHAPE_HEIGHT/2, SHAPE_LENGTH, SHAPE_HEIGHT/2); c->curveto(SHAPE_LENGTH, (1 + C1) * SHAPE_HEIGHT/2, (1 + C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, SHAPE_LENGTH/2, SHAPE_HEIGHT); c->curveto((1 - C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, 0, (1 + C1) * SHAPE_HEIGHT/2, 0, SHAPE_HEIGHT/2); c->closepath(); spdc_paste_curve_as_freehand_shape(c->get_pathvector(), dc, item); c->unref(); shape_applied = true; break; } case CLIPBOARD: { // take shape from clipboard; Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){ SPItem * pasted_clipboard = dc->selection->singleItem(); if(pasted_clipboard){ Inkscape::XML::Node *pasted_clipboard_root = pasted_clipboard->getRepr(); Inkscape::XML::Node *path = sp_repr_lookup_name(pasted_clipboard_root, "svg:path", -1); // unlimited search depth if ( path != NULL ) { gchar const *svgd = path->attribute("d"); dc->selection->remove(SP_OBJECT(pasted_clipboard)); previous_shape_pathv = sp_svg_read_pathv(svgd); previous_shape_pathv *= pasted_clipboard->transform; spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item); shape = CLIPBOARD; shape_applied = true; pasted_clipboard->deleteObject(); } else { shape = NONE; } } else { shape = NONE; } } else { shape = NONE; } break; } case BEND_CLIPBOARD: { Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){ gchar const *svgd = item->getRepr()->attribute("d"); bend_item = dc->selection->singleItem(); if(bend_item){ bend_item->moveTo(item,false); bend_item->transform.setTranslation(Geom::Point()); spdc_apply_bend_shape(svgd, dc, bend_item); dc->selection->add(SP_OBJECT(bend_item)); shape = BEND_CLIPBOARD; } else { shape = NONE; } } else { shape = NONE; } break; } case LAST_APPLIED: { if(previous_shape_type == CLIPBOARD){ if(previous_shape_pathv.size() != 0){ spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item); shape_applied = true; shape = CLIPBOARD; } else{ shape = NONE; } } else { if(bend_item != NULL && bend_item->getRepr() != NULL){ gchar const *svgd = item->getRepr()->attribute("d"); dc->selection->add(SP_OBJECT(bend_item)); sp_selection_duplicate(dc->desktop); dc->selection->remove(SP_OBJECT(bend_item)); bend_item = dc->selection->singleItem(); if(bend_item){ bend_item->moveTo(item,false); Geom::Coord expansion_X = bend_item->transform.expansionX(); Geom::Coord expansion_Y = bend_item->transform.expansionY(); bend_item->transform = Geom::Affine(1,0,0,1,0,0); bend_item->transform.setExpansionX(expansion_X); bend_item->transform.setExpansionY(expansion_Y); spdc_apply_bend_shape(svgd, dc, bend_item); dc->selection->add(SP_OBJECT(bend_item)); shape = BEND_CLIPBOARD; } else { shape = NONE; } } else { shape = NONE; } } break; } default: break; } previous_shape_type = shape; if (shape_applied) { // apply original stroke color as fill and unset stroke; then return SPCSSAttr *css = sp_repr_css_attr_new(); if (!strcmp(cstroke, "none")){ sp_repr_css_set_property (css, "fill", "black"); } else { sp_repr_css_set_property (css, "fill", cstroke); } sp_repr_css_set_property (css, "stroke", "none"); sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref(css); return; } if (dc->waiting_LPE_type != INVALID_LPE) { Effect::createAndApply(dc->waiting_LPE_type, dc->desktop->doc(), item); dc->waiting_LPE_type = INVALID_LPE; if (SP_IS_LPETOOL_CONTEXT(dc)) { // since a geometric LPE was applied, we switch back to "inactive" mode lpetool_context_switch_mode(SP_LPETOOL_CONTEXT(dc), INVALID_LPE); } } if (SP_IS_PEN_CONTEXT(dc)) { SP_PEN_CONTEXT(dc)->setPolylineMode(); } } }
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; }
/** * \return None * \brief This is a generic function to use the save function of * a module (including Autodetect) * \param key Identifier of which module to use * \param doc The document to be saved * \param filename The file that the document should be saved to * \param official (optional) whether to set :output_module and :modified in the * document; is true for normal save, false for temporary saves * * 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 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 save function is called in the module itself. */ void save(Extension *key, SPDocument *doc, gchar const *filename, bool setextension, bool check_overwrite, bool official) { Output *omod; if (key == NULL) { gpointer parray[2]; parray[0] = (gpointer)filename; parray[1] = (gpointer)&omod; omod = NULL; db.foreach(save_internal, (gpointer)&parray); /* This is a nasty hack, but it is required to ensure that autodetect will always save with the Inkscape extensions if they are available. */ if (omod != NULL && !strcmp(omod->get_id(), SP_MODULE_KEY_OUTPUT_SVG)) { omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)); } /* If autodetect fails, save as Inkscape SVG */ if (omod == NULL) { omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)); } } else { omod = dynamic_cast<Output *>(key); } if (!dynamic_cast<Output *>(omod)) { g_warning("Unable to find output module to handle file: %s\n", filename); throw Output::no_extension_found(); return; } omod->set_state(Extension::STATE_LOADED); if (!omod->loaded()) { throw Output::save_failed(); } if (!omod->prefs()) { throw Output::save_cancelled(); } gchar *fileName = NULL; if (setextension) { gchar *lowerfile = g_utf8_strdown(filename, -1); gchar *lowerext = g_utf8_strdown(omod->get_extension(), -1); if (!g_str_has_suffix(lowerfile, lowerext)) { fileName = g_strdup_printf("%s%s", filename, omod->get_extension()); } g_free(lowerfile); g_free(lowerext); } if (fileName == NULL) { fileName = g_strdup(filename); } if (check_overwrite && !sp_ui_overwrite_file(fileName)) { g_free(fileName); throw Output::no_overwrite(); } Inkscape::XML::Node *repr = sp_document_repr_root(doc); // remember attributes in case this is an unofficial save bool saved_modified = false; gchar *saved_output_extension = NULL; gchar *saved_dataloss = NULL; gchar *saved_uri = NULL; if (!official) { saved_modified = doc->isModifiedSinceSave(); if (repr->attribute("inkscape:output_extension")) { saved_output_extension = g_strdup(repr->attribute("inkscape:output_extension")); } if (repr->attribute("inkscape:dataloss")) { saved_dataloss = g_strdup(repr->attribute("inkscape:dataloss")); } if (doc->uri) { saved_uri = g_strdup(doc->uri); } } // update attributes: bool saved = sp_document_get_undo_sensitive(doc); sp_document_set_undo_sensitive (doc, false); // save the filename for next use sp_document_set_uri(doc, fileName); // also save the extension for next use repr->setAttribute("inkscape:output_extension", omod->get_id()); // set the "dataloss" attribute if the chosen extension is lossy repr->setAttribute("inkscape:dataloss", NULL); if ( omod->causes_dataloss() ) { repr->setAttribute("inkscape:dataloss", "true"); } sp_document_set_undo_sensitive (doc, saved); doc->setModifiedSinceSave(false); omod->save(doc, fileName); // if it is an unofficial save, set the modified attributes back to what they were if ( !official) { saved = sp_document_get_undo_sensitive(doc); sp_document_set_undo_sensitive (doc, false); repr->setAttribute("inkscape:output_extension", saved_output_extension); repr->setAttribute("inkscape:dataloss", saved_dataloss); sp_document_set_uri(doc, saved_uri); sp_document_set_undo_sensitive (doc, saved); doc->setModifiedSinceSave(saved_modified); } if (saved_output_extension) g_free(saved_output_extension); if (saved_dataloss) g_free(saved_dataloss); if (saved_uri) g_free(saved_uri); g_free(fileName); return; }
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; }
Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) : Extension(in_repr, in_imp), _id_noprefs(Glib::ustring(get_id()) + ".noprefs"), _name_noprefs(Glib::ustring(_(get_name())) + _(" (No preferences)")), _verb(get_id(), get_name(), NULL, NULL, this, true), _verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false), _menu_node(NULL), _workingDialog(true), _prefDialog(NULL) { Inkscape::XML::Node * local_effects_menu = NULL; // This is a weird hack if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow")) return; bool hidden = false; no_doc = false; no_live_preview = false; if (repr != NULL) { for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) { if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) { if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) { no_doc = true; } if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) { no_live_preview = true; } for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) { if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) { // printf("Found local effects menu in %s\n", this->get_name()); local_effects_menu = sp_repr_children(effect_child); if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) { hidden = true; } } if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") || !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) { // printf("Found local effects menu in %s\n", this->get_name()); _verb.set_name(sp_repr_children(effect_child)->content()); } if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") || !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) { // printf("Found local effects menu in %s\n", this->get_name()); _verb.set_tip(sp_repr_children(effect_child)->content()); } } // children of "effect" break; // there can only be one effect } // find "effect" } // children of "inkscape-extension" } // if we have an XML file if (INKSCAPE != NULL) { if (_effects_list == NULL) _effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST); if (_filters_list == NULL) _filters_list = find_menu(inkscape_get_menus(INKSCAPE), FILTERS_LIST); } if ((_effects_list != NULL || _filters_list != NULL)) { Inkscape::XML::Document *xml_doc; xml_doc = _effects_list->document(); _menu_node = xml_doc->createElement("verb"); _menu_node->setAttribute("verb-id", this->get_id(), false); if (!hidden) { if (_filters_list && local_effects_menu && local_effects_menu->attribute("name") && !strcmp(local_effects_menu->attribute("name"), ("Filters"))) { merge_menu(_filters_list->parent(), _filters_list, sp_repr_children(local_effects_menu), _menu_node); } else if (_effects_list) { merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node); } } } return; }
/** * \return None * \brief This is a generic function to use the save function of * a module (including Autodetect) * \param key Identifier of which module to use * \param doc The document to be saved * \param filename The file that the document should be saved to * \param official (optional) whether to set :output_module and :modified in the * document; is true for normal save, false for temporary saves * * 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 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 save function is called in the module itself. */ void save(Extension *key, SPDocument *doc, gchar const *filename, bool setextension, bool check_overwrite, bool official, Inkscape::Extension::FileSaveMethod save_method) { Output *omod; if (key == NULL) { gpointer parray[2]; parray[0] = (gpointer)filename; parray[1] = (gpointer)&omod; omod = NULL; db.foreach(save_internal, (gpointer)&parray); /* This is a nasty hack, but it is required to ensure that autodetect will always save with the Inkscape extensions if they are available. */ if (omod != NULL && !strcmp(omod->get_id(), SP_MODULE_KEY_OUTPUT_SVG)) { omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)); } /* If autodetect fails, save as Inkscape SVG */ if (omod == NULL) { // omod = dynamic_cast<Output *>(db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE)); use exception and let user choose } } else { omod = dynamic_cast<Output *>(key); } if (!dynamic_cast<Output *>(omod)) { g_warning("Unable to find output module to handle file: %s\n", filename); throw Output::no_extension_found(); } omod->set_state(Extension::STATE_LOADED); if (!omod->loaded()) { throw Output::save_failed(); } if (!omod->prefs()) { throw Output::save_cancelled(); } gchar *fileName = NULL; if (setextension) { gchar *lowerfile = g_utf8_strdown(filename, -1); gchar *lowerext = g_utf8_strdown(omod->get_extension(), -1); if (!g_str_has_suffix(lowerfile, lowerext)) { fileName = g_strdup_printf("%s%s", filename, omod->get_extension()); } g_free(lowerfile); g_free(lowerext); } if (fileName == NULL) { fileName = g_strdup(filename); } if (check_overwrite && !sp_ui_overwrite_file(fileName)) { g_free(fileName); throw Output::no_overwrite(); } // test if the file exists and is writable // the test only checks the file attributes and might pass where ACL does not allow to write if (Inkscape::IO::file_test(filename, G_FILE_TEST_EXISTS) && !Inkscape::IO::file_is_writable(filename)) { g_free(fileName); throw Output::file_read_only(); } Inkscape::XML::Node *repr = doc->getReprRoot(); // remember attributes in case this is an unofficial save and/or overwrite fails gchar *saved_uri = g_strdup(doc->getURI()); gchar *saved_output_extension = NULL; gchar *saved_dataloss = NULL; bool saved_modified = doc->isModifiedSinceSave(); saved_output_extension = g_strdup(get_file_save_extension(save_method).c_str()); saved_dataloss = g_strdup(repr->attribute("inkscape:dataloss")); if (official) { // The document is changing name/uri. doc->changeUriAndHrefs(fileName); } // Update attributes: { bool const saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); { // also save the extension for next use store_file_extension_in_prefs (omod->get_id(), save_method); // set the "dataloss" attribute if the chosen extension is lossy repr->setAttribute("inkscape:dataloss", NULL); if (omod->causes_dataloss()) { repr->setAttribute("inkscape:dataloss", "true"); } } DocumentUndo::setUndoSensitive(doc, saved); doc->setModifiedSinceSave(false); } try { omod->save(doc, fileName); } catch(...) { // revert attributes in case of official and overwrite if(check_overwrite && official) { bool const saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); { store_file_extension_in_prefs (saved_output_extension, save_method); repr->setAttribute("inkscape:dataloss", saved_dataloss); } DocumentUndo::setUndoSensitive(doc, saved); doc->changeUriAndHrefs(saved_uri); } doc->setModifiedSinceSave(saved_modified); // free used ressources g_free(saved_output_extension); g_free(saved_dataloss); g_free(saved_uri); g_free(fileName); throw Inkscape::Extension::Output::save_failed(); } // If it is an unofficial save, set the modified attributes back to what they were. if ( !official) { bool const saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); { store_file_extension_in_prefs (saved_output_extension, save_method); repr->setAttribute("inkscape:dataloss", saved_dataloss); } DocumentUndo::setUndoSensitive(doc, saved); doc->setModifiedSinceSave(saved_modified); g_free(saved_output_extension); g_free(saved_dataloss); } g_free(fileName); return; }
static gboolean update_stop_list( GtkWidget *stop_combo, SPGradient *gradient, SPStop *new_stop, GtkWidget *widget, bool gr_multi) { gboolean sensitive = FALSE; if (!stop_combo) { return sensitive; } GtkListStore *store = (GtkListStore *)gtk_combo_box_get_model(GTK_COMBO_BOX(stop_combo)); if (!store) { return sensitive; } blocked = TRUE; /* Clear old list, if there is any */ gtk_list_store_clear(store); GtkTreeIter iter; if (!SP_IS_GRADIENT(gradient)) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("No gradient"), 1, NULL, 2, NULL, -1); gtk_combo_box_set_active(GTK_COMBO_BOX(stop_combo) , 0); sensitive = FALSE; blocked = FALSE; return sensitive; } /* Populate the combobox store */ GSList *sl = NULL; if ( gradient->hasStops() ) { for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { sl = g_slist_append(sl, ochild); } } } if (!sl) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, _("No stops in gradient"), 1, NULL, 2, NULL, -1); sensitive = FALSE; } else { for (; sl != NULL; sl = sl->next){ if (SP_IS_STOP(sl->data)){ SPStop *stop = SP_STOP(sl->data); Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr(); Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32())); GdkPixbuf *pb = cpv->toPixbuf(32, 16); Glib::ustring label = gr_ellipsize_text(repr->attribute("id"), 25); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, label.c_str(), 1, pb, 2, stop, -1); sensitive = FALSE; } } sensitive = TRUE; } if (gr_multi) { sensitive = FALSE; } if (new_stop == NULL) { gtk_combo_box_set_active(GTK_COMBO_BOX(stop_combo) , 0); } else { select_stop_in_list(stop_combo, gradient, new_stop, widget, TRUE); } blocked = FALSE; return sensitive; }
ParamComboBox::ParamComboBox(const gchar *name, const gchar *guitext, const gchar *desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar *gui_tip, Inkscape::Extension::Extension *ext, Inkscape::XML::Node *xml) : Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) , _value(NULL) , _indent(0) , choices(NULL) { const char *xmlval = NULL; // the value stored in XML if (xml != NULL) { // Read XML tree to add enumeration items: for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) { char const * chname = node->name(); if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { Glib::ustring newguitext, newvalue; const char * contents = NULL; if (node->firstChild()) { contents = node->firstChild()->content(); } if (contents != NULL) { // don't translate when 'item' but do translate when '_item' // NOTE: internal extensions use build_from_mem and don't need _item but // still need to include if are to be localized if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { if (node->attribute("msgctxt") != NULL) { newguitext = g_dpgettext2(NULL, node->attribute("msgctxt"), contents); } else { newguitext = _(contents); } } else { newguitext = contents; } } else continue; const char * val = node->attribute("value"); if (val != NULL) { newvalue = val; } else { newvalue = contents; } if ( (!newguitext.empty()) && (!newvalue.empty()) ) { // logical error if this is not true here choices = g_slist_append( choices, new enumentry(newvalue, newguitext) ); } } } // Initialize _value with the default value from xml // for simplicity : default to the contents of the first xml-child if (xml->firstChild() && xml->firstChild()->firstChild()) { xmlval = xml->firstChild()->attribute("value"); } const char *indent = xml->attribute("indent"); if (indent != NULL) { _indent = atoi(indent) * 12; } } gchar * pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Glib::ustring paramval = prefs ? prefs->getString(extension_pref_root + pref_name) : ""; g_free(pref_name); if (!paramval.empty()) { _value = g_strdup(paramval.data()); } else if (xmlval) { _value = g_strdup(xmlval); } }
static void draw_page (GtkPrintOperation */*operation*/, GtkPrintContext *context, gint /*page_nr*/, gpointer user_data) { struct workaround_gtkmm *junk = (struct workaround_gtkmm*)user_data; //printf("%s %d\n",__FUNCTION__, page_nr); if (junk->_tab->as_bitmap()) { // Render as exported PNG gdouble width = sp_document_width(junk->_doc); gdouble height = sp_document_height(junk->_doc); gdouble dpi = junk->_tab->bitmap_dpi(); std::string tmp_png; std::string tmp_base = "inkscape-print-png-XXXXXX"; int tmp_fd; if ( (tmp_fd = Inkscape::IO::file_open_tmp (tmp_png, tmp_base)) >= 0) { close(tmp_fd); guint32 bgcolor = 0x00000000; Inkscape::XML::Node *nv = sp_repr_lookup_name (junk->_doc->rroot, "sodipodi:namedview"); if (nv && nv->attribute("pagecolor")) bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00); if (nv && nv->attribute("inkscape:pageopacity")) bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0)); sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0, width, height, (unsigned long)(width * dpi / PX_PER_IN), (unsigned long)(height * dpi / PX_PER_IN), dpi, dpi, bgcolor, NULL, NULL, true, NULL); // This doesn't seem to work: //context->set_cairo_context ( Cairo::Context::create (Cairo::ImageSurface::create_from_png (tmp_png) ), dpi, dpi ); // // so we'll use a surface pattern blat instead... // // but the C++ interface isn't implemented in cairomm: //context->get_cairo_context ()->set_source_surface(Cairo::ImageSurface::create_from_png (tmp_png) ); // // so do it in C: { Cairo::RefPtr<Cairo::ImageSurface> png = Cairo::ImageSurface::create_from_png (tmp_png); cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_matrix_t m; cairo_get_matrix(cr, &m); cairo_scale(cr, PT_PER_IN / dpi, PT_PER_IN / dpi); // FIXME: why is the origin offset?? cairo_set_source_surface(cr, png->cobj(), -16.0, -16.0); cairo_paint(cr); cairo_set_matrix(cr, &m); } // Clean up unlink (tmp_png.c_str()); } else { g_warning(_("Could not open temporary PNG for bitmap printing")); } } else { // Render as vectors Inkscape::Extension::Internal::CairoRenderer renderer; Inkscape::Extension::Internal::CairoRenderContext *ctx = renderer.createContext(); // ctx->setPSLevel(CAIRO_PS_LEVEL_3); ctx->setTextToPath(false); ctx->setFilterToBitmap(true); ctx->setBitmapResolution(72); cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_surface_t *surface = cairo_get_target(cr); /** Call cairo_win32_printing_surface directly as a workaround until GTK uses this call. When GTK uses cairo_win32_printing_surface this automatically reverts. */ #ifdef WIN32 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_WIN32) { HDC dc = cairo_win32_surface_get_dc (surface); surface = _cairo_win32_printing_surface_create (dc); } #endif bool ret = ctx->setSurfaceTarget (surface, true); if (ret) { ret = renderer.setupDocument (ctx, junk->_doc, TRUE, NULL); if (ret) { renderer.renderItem(ctx, junk->_base); ret = ctx->finish(); } else { g_warning(_("Could not set up Document")); } } else { g_warning(_("Failed to set CairoRenderContext")); } // Clean up renderer.destroyContext(ctx); } }
void Effect::merge_menu (Inkscape::XML::Node * base, Inkscape::XML::Node * start, Inkscape::XML::Node * patern, Inkscape::XML::Node * mergee) { Glib::ustring mergename; Inkscape::XML::Node * tomerge = NULL; Inkscape::XML::Node * submenu = NULL; /* printf("Merge menu with '%s' '%s' '%s'\n", base != NULL ? base->name() : "NULL", patern != NULL ? patern->name() : "NULL", mergee != NULL ? mergee->name() : "NULL"); */ if (patern == NULL) { // Merge the verb name tomerge = mergee; mergename = _(this->get_name()); } else { gchar const * menuname = patern->attribute("name"); if (menuname == NULL) menuname = patern->attribute("_name"); if (menuname == NULL) return; Inkscape::XML::Document *xml_doc; xml_doc = base->document(); tomerge = xml_doc->createElement("submenu"); tomerge->setAttribute("name", menuname, false); mergename = _(menuname); } int position = -1; if (start != NULL) { Inkscape::XML::Node * menupass; for (menupass = start; menupass != NULL && strcmp(menupass->name(), "separator"); menupass = menupass->next()) { gchar const * compare_char = NULL; if (!strcmp(menupass->name(), "verb")) { gchar const * verbid = menupass->attribute("verb-id"); Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid); if (verb == NULL) { g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid); continue; } compare_char = verb->get_name(); } else if (!strcmp(menupass->name(), "submenu")) { compare_char = menupass->attribute("name"); if (compare_char == NULL) compare_char = menupass->attribute("_name"); } position = menupass->position() + 1; /* This will cause us to skip tags we don't understand */ if (compare_char == NULL) { continue; } Glib::ustring compare(_(compare_char)); if (mergename == compare) { Inkscape::GC::release(tomerge); tomerge = NULL; submenu = menupass; break; } if (mergename < compare) { position = menupass->position(); break; } } // for menu items } // start != NULL if (tomerge != NULL) { base->appendChild(tomerge); Inkscape::GC::release(tomerge); if (position != -1) tomerge->setPosition(position); } if (patern != NULL) { if (submenu == NULL) submenu = tomerge; merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee); } return; }
static void sp_image_image_edit(GtkMenuItem *menuitem, SPAnchor *anchor) { SPObject* obj = anchor; Inkscape::XML::Node *ir = obj->getRepr(); const gchar *href = ir->attribute("xlink:href"); GError* errThing = 0; Glib::ustring cmdline = getImageEditorName(); Glib::ustring name; Glib::ustring fullname; #ifdef WIN32 // g_spawn_command_line_sync parsing is done according to Unix shell rules, // not Windows command interpreter rules. Thus we need to enclose the // executable path with sigle quotes. int index = cmdline.find(".exe"); if ( index < 0 ) index = cmdline.find(".bat"); if ( index < 0 ) index = cmdline.find(".com"); if ( index >= 0 ) { Glib::ustring editorBin = cmdline.substr(0, index + 4).c_str(); Glib::ustring args = cmdline.substr(index + 4, cmdline.length()).c_str(); editorBin.insert(0, "'"); editorBin.append("'"); cmdline = editorBin; cmdline.append(args); } else { // Enclose the whole command line if no executable path can be extracted. cmdline.insert(0, "'"); cmdline.append("'"); } #endif if (strncmp (href,"file:",5) == 0) { // URI to filename conversion name = g_filename_from_uri(href, NULL, NULL); } else { name.append(href); } if (Glib::path_is_absolute(name)) { fullname = name; } else if (SP_ACTIVE_DOCUMENT->getBase()) { fullname = Glib::build_filename(SP_ACTIVE_DOCUMENT->getBase(), name); } else { fullname = Glib::build_filename(Glib::get_current_dir(), name); } cmdline.append(" '"); cmdline.append(fullname.c_str()); cmdline.append("'"); //g_warning("##Command line: %s\n", cmdline.c_str()); g_spawn_command_line_async(cmdline.c_str(), &errThing); if ( errThing ) { g_warning("Problem launching editor (%d). %s", errThing->code, errThing->message); SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop"); desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, errThing->message); g_error_free(errThing); errThing = 0; } }