From c04e30df241a3ee039077425bab9b9c37abe2854 Mon Sep 17 00:00:00 2001 From: Markus Engel Date: Sat, 9 Nov 2013 23:36:13 +0100 Subject: Moved and renamed some tool-related files. (bzr r12785) --- src/draw-context.cpp | 785 --------------------------------------------------- 1 file changed, 785 deletions(-) delete mode 100644 src/draw-context.cpp (limited to 'src/draw-context.cpp') diff --git a/src/draw-context.cpp b/src/draw-context.cpp deleted file mode 100644 index 8fd52b83e..000000000 --- a/src/draw-context.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* - * Generic drawing context - * - * Author: - * Lauris Kaplinski - * Abhishek Sharma - * Jon A. Cruz - * - * Copyright (C) 2000 Lauris Kaplinski - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2002 Lauris Kaplinski - * Copyright (C) 2012 Johan Engelen - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#define DRAW_VERBOSE - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "live_effects/lpe-patternalongpath.h" -#include "display/canvas-bpath.h" -#include "xml/repr.h" -#include "svg/svg.h" -#include -#include "display/curve.h" -#include "desktop.h" -#include "desktop-handles.h" -#include "desktop-style.h" -#include "document.h" -#include "draw-anchor.h" -#include "macros.h" -#include "message-stack.h" -#include "pen-context.h" -#include "lpe-tool-context.h" -#include "preferences.h" -#include "selection.h" -#include "selection-chemistry.h" -#include "snap.h" -#include "sp-path.h" -#include "sp-namedview.h" -#include "live_effects/lpe-powerstroke.h" -#include "style.h" -#include "ui/control-manager.h" -#include "draw-context.h" - -#include - -using Inkscape::DocumentUndo; - -namespace Inkscape { -namespace UI { -namespace Tools { - -static void spdc_selection_changed(Inkscape::Selection *sel, SPDrawContext *dc); -static void spdc_selection_modified(Inkscape::Selection *sel, guint flags, SPDrawContext *dc); - -static void spdc_attach_selection(SPDrawContext *dc, Inkscape::Selection *sel); - -/** - * Flushes white curve(s) and additional curve into object. - * - * No cleaning of colored curves - this has to be done by caller - * No rereading of white data, so if you cannot rely on ::modified, do it in caller - */ -static void spdc_flush_white(SPDrawContext *dc, SPCurve *gc); - -static void spdc_reset_white(SPDrawContext *dc); -static void spdc_free_colors(SPDrawContext *dc); - -SPDrawContext::SPDrawContext() : ToolBase() { - this->selection = 0; - this->grab = 0; - this->anchor_statusbar = false; - - this->attach = FALSE; - - this->red_color = 0xff00007f; - this->blue_color = 0x0000ff7f; - this->green_color = 0x00ff007f; - this->red_curve_is_valid = false; - - this->red_bpath = NULL; - this->red_curve = NULL; - - this->blue_bpath = NULL; - this->blue_curve = NULL; - - this->green_bpaths = NULL; - this->green_curve = NULL; - this->green_anchor = NULL; - this->green_closed = false; - - this->white_item = NULL; - this->white_curves = NULL; - this->white_anchors = NULL; - - this->sa = NULL; - this->ea = NULL; - - this->waiting_LPE_type = Inkscape::LivePathEffect::INVALID_LPE; -} - -SPDrawContext::~SPDrawContext() { - if (this->grab) { - sp_canvas_item_ungrab(this->grab, GDK_CURRENT_TIME); - this->grab = NULL; - } - - if (this->selection) { - this->selection = NULL; - } - - spdc_free_colors(this); -} - -void SPDrawContext::setup() { - ToolBase::setup(); - - this->selection = sp_desktop_selection(desktop); - - // Connect signals to track selection changes - this->sel_changed_connection = this->selection->connectChanged( - sigc::bind(sigc::ptr_fun(&spdc_selection_changed), this) - ); - this->sel_modified_connection = this->selection->connectModified( - sigc::bind(sigc::ptr_fun(&spdc_selection_modified), this) - ); - - // Create red bpath - this->red_bpath = sp_canvas_bpath_new(sp_desktop_sketch(this->desktop), NULL); - sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->red_bpath), this->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - - // Create red curve - this->red_curve = new SPCurve(); - - // Create blue bpath - this->blue_bpath = sp_canvas_bpath_new(sp_desktop_sketch(this->desktop), NULL); - sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->blue_bpath), this->blue_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - - // Create blue curve - this->blue_curve = new SPCurve(); - - // Create green curve - this->green_curve = new SPCurve(); - - // No green anchor by default - this->green_anchor = NULL; - this->green_closed = FALSE; - - this->attach = TRUE; - spdc_attach_selection(this, this->selection); -} - -void SPDrawContext::finish() { - this->sel_changed_connection.disconnect(); - this->sel_modified_connection.disconnect(); - - if (this->grab) { - sp_canvas_item_ungrab(this->grab, GDK_CURRENT_TIME); - } - - if (this->selection) { - this->selection = NULL; - } - - spdc_free_colors(this); -} - -void SPDrawContext::set(const Inkscape::Preferences::Entry& /*value*/) { -} - -bool SPDrawContext::root_handler(GdkEvent* event) { - gint ret = FALSE; - - switch (event->type) { - case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { - case GDK_KEY_Up: - case GDK_KEY_Down: - case GDK_KEY_KP_Up: - case GDK_KEY_KP_Down: - // prevent the zoom field from activation - if (!MOD__CTRL_ONLY(event)) { - ret = TRUE; - } - break; - default: - break; - } - break; - default: - break; - } - - if (!ret) { - ret = ToolBase::root_handler(event); - } - - return ret; -} - -static Glib::ustring const tool_name(SPDrawContext *dc) -{ - return ( SP_IS_PEN_CONTEXT(dc) - ? "/tools/freehand/pen" - : "/tools/freehand/pencil" ); -} - -static void spdc_paste_curve_as_freehand_shape(const SPCurve *c, SPDrawContext *dc, SPItem *item) -{ - using namespace Inkscape::LivePathEffect; - - // TODO: Don't paste path if nothing is on the clipboard - - Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item); - Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE(); - gchar *svgd = sp_svg_write_path(c->get_pathvector()); - static_cast(lpe)->pattern.paste_param_path(svgd); -} - -static void spdc_apply_powerstroke_shape(const std::vector & points, SPDrawContext *dc, SPItem *item) -{ - using namespace Inkscape::LivePathEffect; - - Effect::createAndApply(POWERSTROKE, dc->desktop->doc(), item); - Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE(); - static_cast(lpe)->offset_points.param_set_and_write_new_value(points); - - // 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"); -} - -static void spdc_check_for_and_apply_waiting_LPE(SPDrawContext *dc, SPItem *item, SPCurve *curve) -{ - using namespace Inkscape::LivePathEffect; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - if (item && SP_IS_LPE_ITEM(item)) { - if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) { - Effect::createAndApply(SPIRO, dc->desktop->doc(), item); - } - - int shape = 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"); - -#define SHAPE_LENGTH 10 -#define SHAPE_HEIGHT 10 - - switch (shape) { - case 0: - // don't apply any shape - break; - case 1: - { - // "triangle in" - std::vector points(1); - points[0] = Geom::Point(0., SHAPE_HEIGHT/2); - spdc_apply_powerstroke_shape(points, dc, item); - - shape_applied = true; - break; - } - case 2: - { - // "triangle out" - guint curve_length = curve->get_segment_count(); - std::vector points(1); - points[0] = Geom::Point((double)curve_length, SHAPE_HEIGHT/2); - spdc_apply_powerstroke_shape(points, dc, item); - - shape_applied = true; - break; - } - case 3: - { - // "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, dc, item); - c->unref(); - shape_applied = true; - break; - } - case 4: - { - // take shape from clipboard; TODO: catch the case where clipboard is empty - Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item); - Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE(); - static_cast(lpe)->pattern.on_paste_button_click(); - - shape_applied = true; - break; - } - default: - break; - } - 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_set_polyline_mode(SP_PEN_CONTEXT(dc)); - } - } -} - -/* - * Selection handlers - */ - -static void spdc_selection_changed(Inkscape::Selection *sel, SPDrawContext *dc) -{ - if (dc->attach) { - spdc_attach_selection(dc, sel); - } -} - -/* fixme: We have to ensure this is not delayed (Lauris) */ - -static void spdc_selection_modified(Inkscape::Selection *sel, guint /*flags*/, SPDrawContext *dc) -{ - if (dc->attach) { - spdc_attach_selection(dc, sel); - } -} - -static void spdc_attach_selection(SPDrawContext *dc, Inkscape::Selection */*sel*/) -{ - // We reset white and forget white/start/end anchors - spdc_reset_white(dc); - dc->sa = NULL; - dc->ea = NULL; - - SPItem *item = dc->selection ? dc->selection->singleItem() : NULL; - - if ( item && SP_IS_PATH(item) ) { - // Create new white data - // Item - dc->white_item = item; - - // Curve list - // We keep it in desktop coordinates to eliminate calculation errors - SPCurve *norm = SP_PATH(item)->get_curve_for_edit(); - norm->transform((dc->white_item)->i2dt_affine()); - g_return_if_fail( norm != NULL ); - dc->white_curves = g_slist_reverse(norm->split()); - norm->unref(); - - // Anchor list - for (GSList *l = dc->white_curves; l != NULL; l = l->next) { - SPCurve *c; - c = static_cast(l->data); - g_return_if_fail( c->get_segment_count() > 0 ); - if ( !c->is_closed() ) { - SPDrawAnchor *a; - a = sp_draw_anchor_new(dc, c, TRUE, *(c->first_point())); - if (a) - dc->white_anchors = g_slist_prepend(dc->white_anchors, a); - a = sp_draw_anchor_new(dc, c, FALSE, *(c->last_point())); - if (a) - dc->white_anchors = g_slist_prepend(dc->white_anchors, a); - } - } - // fixme: recalculate active anchor? - } -} - - -void spdc_endpoint_snap_rotation(ToolBase const *const ec, Geom::Point &p, Geom::Point const &o, - guint state) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12)); - - SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager; - m.setup(SP_EVENT_CONTEXT_DESKTOP(ec)); - - bool snap_enabled = m.snapprefs.getSnapEnabledGlobally(); - if (state & GDK_SHIFT_MASK) { - // SHIFT disables all snapping, except the angular snapping. After all, the user explicitly asked for angular - // snapping by pressing CTRL, otherwise we wouldn't have arrived here. But although we temporarily disable - // the snapping here, we must still call for a constrained snap in order to apply the constraints (i.e. round - // to the nearest angle increment) - m.snapprefs.setSnapEnabledGlobally(false); - } - - Inkscape::SnappedPoint dummy = m.constrainedAngularSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE), boost::optional(), o, snaps); - p = dummy.getPoint(); - - if (state & GDK_SHIFT_MASK) { - m.snapprefs.setSnapEnabledGlobally(snap_enabled); // restore the original setting - } - - m.unSetup(); -} - - -void spdc_endpoint_snap_free(ToolBase const * const ec, Geom::Point& p, boost::optional &start_of_line, guint const /*state*/) -{ - SPDesktop *dt = SP_EVENT_CONTEXT_DESKTOP(ec); - SnapManager &m = dt->namedview->snap_manager; - Inkscape::Selection *selection = sp_desktop_selection (dt); - - // selection->singleItem() is the item that is currently being drawn. This item will not be snapped to (to avoid self-snapping) - // TODO: Allow snapping to the stationary parts of the item, and only ignore the last segment - - m.setup(dt, true, selection->singleItem()); - Inkscape::SnapCandidatePoint scp(p, Inkscape::SNAPSOURCE_NODE_HANDLE); - if (start_of_line) { - scp.addOrigin(*start_of_line); - } - - Inkscape::SnappedPoint sp = m.freeSnap(scp); - p = sp.getPoint(); - - m.unSetup(); -} - -static SPCurve *reverse_then_unref(SPCurve *orig) -{ - SPCurve *ret = orig->create_reverse(); - orig->unref(); - return ret; -} - -void spdc_concat_colors_and_flush(SPDrawContext *dc, gboolean forceclosed) -{ - // Concat RBG - SPCurve *c = dc->green_curve; - - // Green - dc->green_curve = new SPCurve(); - while (dc->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->green_bpaths->data)); - dc->green_bpaths = g_slist_remove(dc->green_bpaths, dc->green_bpaths->data); - } - - // Blue - c->append_continuous(dc->blue_curve, 0.0625); - dc->blue_curve->reset(); - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(dc->blue_bpath), NULL); - - // Red - if (dc->red_curve_is_valid) { - c->append_continuous(dc->red_curve, 0.0625); - } - dc->red_curve->reset(); - sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(dc->red_bpath), NULL); - - if (c->is_empty()) { - c->unref(); - return; - } - - // Step A - test, whether we ended on green anchor - if ( forceclosed || ( dc->green_anchor && dc->green_anchor->active ) ) { - // We hit green anchor, closing Green-Blue-Red - SP_EVENT_CONTEXT_DESKTOP(dc)->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Path is closed.")); - c->closepath_current(); - // Closed path, just flush - spdc_flush_white(dc, c); - c->unref(); - return; - } - - // Step B - both start and end anchored to same curve - if ( dc->sa && dc->ea - && ( dc->sa->curve == dc->ea->curve ) - && ( ( dc->sa != dc->ea ) - || dc->sa->curve->is_closed() ) ) - { - // We hit bot start and end of single curve, closing paths - SP_EVENT_CONTEXT_DESKTOP(dc)->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Closing path.")); - if (dc->sa->start && !(dc->sa->curve->is_closed()) ) { - c = reverse_then_unref(c); - } - dc->sa->curve->append_continuous(c, 0.0625); - c->unref(); - dc->sa->curve->closepath_current(); - spdc_flush_white(dc, NULL); - return; - } - - // Step C - test start - if (dc->sa) { - SPCurve *s = dc->sa->curve; - dc->white_curves = g_slist_remove(dc->white_curves, s); - if (dc->sa->start) { - s = reverse_then_unref(s); - } - s->append_continuous(c, 0.0625); - c->unref(); - c = s; - } else /* Step D - test end */ if (dc->ea) { - SPCurve *e = dc->ea->curve; - dc->white_curves = g_slist_remove(dc->white_curves, e); - if (!dc->ea->start) { - e = reverse_then_unref(e); - } - c->append_continuous(e, 0.0625); - e->unref(); - } - - - spdc_flush_white(dc, c); - - c->unref(); -} - -static void spdc_flush_white(SPDrawContext *dc, SPCurve *gc) -{ - SPCurve *c; - - if (dc->white_curves) { - g_assert(dc->white_item); - c = SPCurve::concat(dc->white_curves); - g_slist_free(dc->white_curves); - dc->white_curves = NULL; - if (gc) { - c->append(gc, FALSE); - } - } else if (gc) { - c = gc; - c->ref(); - } else { - return; - } - - // Now we have to go back to item coordinates at last - c->transform( dc->white_item - ? (dc->white_item)->dt2i_affine() - : SP_EVENT_CONTEXT_DESKTOP(dc)->dt2doc() ); - - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(dc); - SPDocument *doc = sp_desktop_document(desktop); - Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - - if ( c && !c->is_empty() ) { - // We actually have something to write - - bool has_lpe = false; - Inkscape::XML::Node *repr; - if (dc->white_item) { - repr = dc->white_item->getRepr(); - has_lpe = SP_LPE_ITEM(dc->white_item)->hasPathEffectRecursive(); - } else { - repr = xml_doc->createElement("svg:path"); - // Set style - sp_desktop_apply_style_tool(desktop, repr, tool_name(dc).data(), false); - } - - gchar *str = sp_svg_write_path( c->get_pathvector() ); - g_assert( str != NULL ); - if (has_lpe) - repr->setAttribute("inkscape:original-d", str); - else - repr->setAttribute("d", str); - g_free(str); - - if (!dc->white_item) { - // Attach repr - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - - // we finished the path; now apply any waiting LPEs or freehand shapes - spdc_check_for_and_apply_waiting_LPE(dc, item, c); - - dc->selection->set(repr); - Inkscape::GC::release(repr); - item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - item->doWriteTransform(item->getRepr(), item->transform, NULL, true); - item->updateRepr(); - } - - DocumentUndo::done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL, - _("Draw path")); - - // When quickly drawing several subpaths with Shift, the next subpath may be finished and - // flushed before the selection_modified signal is fired by the previous change, which - // results in the tool losing all of the selected path's curve except that last subpath. To - // fix this, we force the selection_modified callback now, to make sure the tool's curve is - // in sync immediately. - spdc_selection_modified(sp_desktop_selection(desktop), 0, dc); - } - - c->unref(); - - // Flush pending updates - doc->ensureUpToDate(); -} - -SPDrawAnchor *spdc_test_inside(SPDrawContext *dc, Geom::Point p) -{ - SPDrawAnchor *active = NULL; - - // Test green anchor - if (dc->green_anchor) { - active = sp_draw_anchor_test(dc->green_anchor, p, TRUE); - } - - for (GSList *l = dc->white_anchors; l != NULL; l = l->next) { - SPDrawAnchor *na = sp_draw_anchor_test(static_cast(l->data), p, !active); - if ( !active && na ) { - active = na; - } - } - - return active; -} - -static void spdc_reset_white(SPDrawContext *dc) -{ - if (dc->white_item) { - // We do not hold refcount - dc->white_item = NULL; - } - while (dc->white_curves) { - reinterpret_cast(dc->white_curves->data)->unref(); - dc->white_curves = g_slist_remove(dc->white_curves, dc->white_curves->data); - } - while (dc->white_anchors) { - sp_draw_anchor_destroy(static_cast(dc->white_anchors->data)); - dc->white_anchors = g_slist_remove(dc->white_anchors, dc->white_anchors->data); - } -} - -static void spdc_free_colors(SPDrawContext *dc) -{ - // Red - if (dc->red_bpath) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->red_bpath)); - dc->red_bpath = NULL; - } - if (dc->red_curve) { - dc->red_curve = dc->red_curve->unref(); - } - - // Blue - if (dc->blue_bpath) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->blue_bpath)); - dc->blue_bpath = NULL; - } - if (dc->blue_curve) { - dc->blue_curve = dc->blue_curve->unref(); - } - - // Green - while (dc->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->green_bpaths->data)); - dc->green_bpaths = g_slist_remove(dc->green_bpaths, dc->green_bpaths->data); - } - if (dc->green_curve) { - dc->green_curve = dc->green_curve->unref(); - } - if (dc->green_anchor) { - dc->green_anchor = sp_draw_anchor_destroy(dc->green_anchor); - } - - // White - if (dc->white_item) { - // We do not hold refcount - dc->white_item = NULL; - } - while (dc->white_curves) { - reinterpret_cast(dc->white_curves->data)->unref(); - dc->white_curves = g_slist_remove(dc->white_curves, dc->white_curves->data); - } - while (dc->white_anchors) { - sp_draw_anchor_destroy(static_cast(dc->white_anchors->data)); - dc->white_anchors = g_slist_remove(dc->white_anchors, dc->white_anchors->data); - } -} - -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 = SP_EVENT_CONTEXT_DESKTOP(ec); - 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 = NULL; - style_str = repr->attribute("style"); - if (style_str) { - SPStyle *style = sp_style_new(SP_ACTIVE_DOCUMENT); - sp_style_merge_from_style_string(style, style_str); - stroke_width = style->stroke_width.computed; - style->stroke_width.computed = 0; - sp_style_unref(style); - } - - // 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(); - - sp_desktop_selection(desktop)->set(item); - - desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating single dot")); - DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE, _("Create single dot")); -} - -} -} -} - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3