From b073ae14af73c121287927890951cbcebd7b90b9 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 19 Aug 2017 18:12:52 +0200 Subject: Change from Measure Line LPE to Measure Segments LPE --- src/live_effects/CMakeLists.txt | 20 +- src/live_effects/effect-enum.h | 2 +- src/live_effects/effect.cpp | 8 +- src/live_effects/lpe-measure-line.cpp | 763 -------------------------- src/live_effects/lpe-measure-line.h | 107 ---- src/live_effects/lpe-measure-segments.cpp | 872 ++++++++++++++++++++++++++++++ src/live_effects/lpe-measure-segments.h | 108 ++++ src/sp-lpe-item.cpp | 1 - 8 files changed, 995 insertions(+), 886 deletions(-) delete mode 100644 src/live_effects/lpe-measure-line.cpp delete mode 100644 src/live_effects/lpe-measure-line.h create mode 100644 src/live_effects/lpe-measure-segments.cpp create mode 100644 src/live_effects/lpe-measure-segments.h (limited to 'src') diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index 2a137d6bb..b1000de01 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -3,6 +3,7 @@ set(live_effects_SRC lpe-angle_bisector.cpp lpe-attach-path.cpp lpe-bendpath.cpp + lpe-bool.cpp lpe-bounding-box.cpp lpe-bspline.cpp lpe-circle_3pts.cpp @@ -14,6 +15,8 @@ set(live_effects_SRC lpe-curvestitch.cpp lpe-dynastroke.cpp lpe-ellipse_5pts.cpp + lpe-embrodery-stitch.cpp + lpe-embrodery-stitch-ordering.cpp lpe-envelope.cpp lpe-extrude.cpp lpe-fill-between-many.cpp @@ -27,7 +30,7 @@ set(live_effects_SRC lpe-lattice.cpp lpe-lattice2.cpp lpe-line_segment.cpp - lpe-measure-line.cpp + lpe-measure-segments.cpp lpe-mirror_symmetry.cpp lpe-offset.cpp lpe-parallel.cpp @@ -55,9 +58,6 @@ set(live_effects_SRC lpegroupbbox.cpp lpeobject-reference.cpp lpe-vonkoch.cpp - lpe-embrodery-stitch.cpp - lpe-embrodery-stitch-ordering.cpp - lpe-bool.cpp lpeobject.cpp spiro-converters.cpp spiro.cpp @@ -75,8 +75,8 @@ set(live_effects_SRC parameter/path.cpp parameter/point.cpp parameter/powerstrokepointarray.cpp - parameter/satellitesarray.cpp parameter/random.cpp + parameter/satellitesarray.cpp parameter/text.cpp parameter/fontbutton.cpp parameter/togglebutton.cpp @@ -92,6 +92,7 @@ set(live_effects_SRC lpe-angle_bisector.h lpe-attach-path.h lpe-bendpath.h + lpe-bool.h lpe-bounding-box.h lpe-bspline.h lpe-circle_3pts.h @@ -103,6 +104,8 @@ set(live_effects_SRC lpe-curvestitch.h lpe-dynastroke.h lpe-ellipse_5pts.h + lpe-embrodery-stitch.h + lpe-embrodery-stitch-ordering.h lpe-envelope.h lpe-extrude.h lpe-fill-between-many.h @@ -116,7 +119,7 @@ set(live_effects_SRC lpe-lattice.h lpe-lattice2.h lpe-line_segment.h - lpe-measure-line.h + lpe-measure-segments.h lpe-mirror_symmetry.h lpe-offset.h lpe-parallel.h @@ -143,9 +146,6 @@ set(live_effects_SRC lpe-test-doEffect-stack.h lpe-text_label.h lpe-vonkoch.h - lpe-embrodery-stitch.h - lpe-embrodery-stitch-ordering.h - lpe-bool.h lpegroupbbox.h lpeobject-reference.h lpeobject.h @@ -166,8 +166,8 @@ set(live_effects_SRC parameter/path.h parameter/point.h parameter/powerstrokepointarray.h - parameter/satellitesarray.h parameter/random.h + parameter/satellitesarray.h parameter/text.h parameter/fontbutton.h parameter/togglebutton.h diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index 6a3aebcd6..20d941e69 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -47,7 +47,7 @@ enum EffectType { FILL_BETWEEN_MANY, ELLIPSE_5PTS, BOUNDING_BOX, - MEASURE_LINE, + MEASURE_SEGMENTS, FILLET_CHAMFER, BOOL_OP, EMBRODERY_STITCH, diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index c817f5caa..b2ba0acdc 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -39,7 +39,7 @@ #include "live_effects/lpe-lattice2.h" #include "live_effects/lpe-lattice.h" #include "live_effects/lpe-line_segment.h" -#include "live_effects/lpe-measure-line.h" +#include "live_effects/lpe-measure-segments.h" #include "live_effects/lpe-mirror_symmetry.h" #include "live_effects/lpe-offset.h" #include "live_effects/lpe-parallel.h" @@ -126,7 +126,7 @@ const Util::EnumData LPETypeData[] = { {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"}, /* 9.93 */ - {MEASURE_LINE, N_("Measure Line"), "measure_line"}, + {MEASURE_SEGMENTS, N_("Measure Segments"), "measure_segments"}, {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet_chamfer"}, {BOOL_OP, N_("Boolean operation"), "bool_op"}, {EMBRODERY_STITCH, N_("Embrodery stitch"), "embrodery_stitch"}, @@ -331,8 +331,8 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) case TRANSFORM_2PTS: neweffect = static_cast ( new LPETransform2Pts(lpeobj) ); break; - case MEASURE_LINE: - neweffect = static_cast ( new LPEMeasureLine(lpeobj) ); + case MEASURE_SEGMENTS: + neweffect = static_cast ( new LPEMeasureSegments(lpeobj) ); break; default: g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr); diff --git a/src/live_effects/lpe-measure-line.cpp b/src/live_effects/lpe-measure-line.cpp deleted file mode 100644 index 99828aef8..000000000 --- a/src/live_effects/lpe-measure-line.cpp +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Author(s): - * Jabiertxo Arraiza Cenoz - * Some code and ideas migrated from dimensioning.py by - * Johannes B. Rutzmoser, johannes.rutzmoser (at) googlemail (dot) com - * https://github.com/Rutzmoser/inkscape_dimensioning - * Copyright (C) 2014 Author(s) - - * Released under GNU GPL, read the file 'COPYING' for more information - */ -#include "live_effects/lpe-measure-line.h" -#include -#include "ui/dialog/livepatheffect-editor.h" -#include -#include "inkscape.h" -#include "xml/node.h" -#include "xml/sp-css-attr.h" -#include "preferences.h" -#include "util/units.h" -#include "svg/svg-length.h" -#include "svg/svg-color.h" -#include "svg/svg.h" -#include "display/curve.h" -#include "helper/geom.h" -#include "2geom/affine.h" -#include "path-chemistry.h" -#include "style.h" -#include "sp-root.h" -#include "sp-defs.h" -#include "sp-item.h" -#include "sp-shape.h" -#include "sp-path.h" -#include "document.h" -#include - -// TODO due to internal breakage in glibmm headers, this must be last: -#include - -using namespace Geom; -namespace Inkscape { -namespace LivePathEffect { - -static const Util::EnumData OrientationMethodData[] = { - { OM_HORIZONTAL, N_("Horizontal"), "horizontal" }, - { OM_VERTICAL, N_("Vertical"), "vertical" }, - { OM_PARALLEL, N_("Parallel"), "parallel" } -}; -static const Util::EnumDataConverter OMConverter(OrientationMethodData, OM_END); - -LPEMeasureLine::LPEMeasureLine(LivePathEffectObject *lpeobject) : - Effect(lpeobject), - unit(_("Unit"), _("Unit"), "unit", &wr, this, "px"), - fontbutton(_("Font"), _("Font Selector"), "fontbutton", &wr, this), - orientation(_("Orientation"), _("Orientation method"), "orientation", OMConverter, &wr, this, OM_PARALLEL, false), - curve_linked(_("Curve on origin"), _("Curve on origin, set 0 to start/end"), "curve_linked", &wr, this, 1), - precision(_("Precision"), _("Precision"), "precision", &wr, this, 2), - position(_("Position"), _("Position"), "position", &wr, this, 5), - text_top_bottom(_("Text top/bottom"), _("Text top/bottom"), "text_top_bottom", &wr, this, 0), - text_right_left(_("Text right/left"), _("Text right/left"), "text_right_left", &wr, this, 0), - helpline_distance(_("Helpline distance"), _("Helpline distance"), "helpline_distance", &wr, this, 0.0), - helpline_overlap(_("Helpline overlap"), _("Helpline overlap"), "helpline_overlap", &wr, this, 2.0), - scale(_("Scale"), _("Scaling factor"), "scale", &wr, this, 1.0), - format(_("Format"), _("Format the number ex:{measure} {unit}, return to save"), "format", &wr, this,"{measure}{unit}"), - id_origin("id_origin", "id_origin", "id_origin", &wr, this,""), - arrows_outside(_("Arrows outside"), _("Arrows outside"), "arrows_outside", &wr, this, false), - flip_side(_("Flip side"), _("Flip side"), "flip_side", &wr, this, false), - scale_sensitive(_("Scale sensitive"), _("Costrained scale sensitive to transformed containers"), "scale_sensitive", &wr, this, true), - local_locale(_("Local Number Format"), _("Local number format"), "local_locale", &wr, this, true), - line_group_05(_("Line Group 0.5"), _("Line Group 0.5, from 0.7"), "line_group_05", &wr, this, true), - rotate_anotation(_("Rotate Anotation"), _("Rotate Anotation"), "rotate_anotation", &wr, this, true), - hide_back(_("Hide if label over"), _("Hide DIN line if label over"), "hide_back", &wr, this, true), - dimline_format(_("CSS DIN line"), _("Override CSS to DIN line, return to save, empty to reset to DIM"), "dimline_format", &wr, this,""), - helperlines_format(_("CSS helpers"), _("Override CSS to helper lines, return to save, empty to reset to DIM"), "helperlines_format", &wr, this,""), - anotation_format(_("CSS anotation"), _("Override CSS to anotation text, return to save, empty to reset to DIM"), "anotation_format", &wr, this,""), - arrows_format(_("CSS arrows"), _("Override CSS to arrows, return to save, empty to reset DIM"), "arrows_format", &wr, this,""), - expanded(false) -{ - //set to true the parameters you want to be changed his default values - registerParameter(&unit); - registerParameter(&fontbutton); - registerParameter(&orientation); - registerParameter(&curve_linked); - registerParameter(&precision); - registerParameter(&position); - registerParameter(&text_top_bottom); - registerParameter(&text_right_left); - registerParameter(&helpline_distance); - registerParameter(&helpline_overlap); - registerParameter(&scale); - registerParameter(&format); - registerParameter(&arrows_outside); - registerParameter(&flip_side); - registerParameter(&scale_sensitive); - registerParameter(&local_locale); - registerParameter(&line_group_05); - registerParameter(&rotate_anotation); - registerParameter(&hide_back); - registerParameter(&dimline_format); - registerParameter(&helperlines_format); - registerParameter(&anotation_format); - registerParameter(&arrows_format); - registerParameter(&id_origin); - - id_origin.param_hide_canvas_text(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - Glib::ustring format_value = prefs->getString("/live_effects/measure-line/format"); - if(format_value.empty()){ - format_value = "{measure}{unit}"; - } - format.param_update_default(format_value.c_str()); - - format.param_hide_canvas_text(); - dimline_format.param_hide_canvas_text(); - helperlines_format.param_hide_canvas_text(); - anotation_format.param_hide_canvas_text(); - arrows_format.param_hide_canvas_text(); - precision.param_set_range(0, 100); - precision.param_set_increments(1, 1); - precision.param_set_digits(0); - precision.param_make_integer(true); - curve_linked.param_set_range(0, 999); - curve_linked.param_set_increments(1, 1); - curve_linked.param_set_digits(0); - curve_linked.param_make_integer(true); - precision.param_make_integer(true); - position.param_set_range(-999999.0, 999999.0); - position.param_set_increments(1, 1); - position.param_set_digits(2); - text_top_bottom.param_set_range(-999999.0, 999999.0); - text_top_bottom.param_set_increments(1, 1); - text_top_bottom.param_set_digits(2); - text_right_left.param_set_range(-999999.0, 999999.0); - text_right_left.param_set_increments(1, 1); - text_right_left.param_set_digits(2); - helpline_distance.param_set_range(-999999.0, 999999.0); - helpline_distance.param_set_increments(1, 1); - helpline_distance.param_set_digits(2); - helpline_overlap.param_set_range(-999999.0, 999999.0); - helpline_overlap.param_set_increments(1, 1); - helpline_overlap.param_set_digits(2); - start_stored = Geom::Point(0,0); - end_stored = Geom::Point(0,0); - id_origin.param_widget_is_visible(false); -} - -LPEMeasureLine::~LPEMeasureLine() {} - -void -LPEMeasureLine::createArrowMarker(const char * mode) -{ - SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { - return; - } - Inkscape::XML::Document *xml_doc = document->getReprDoc(); - SPObject *elemref = NULL; - Inkscape::XML::Node *arrow = NULL; - if ((elemref = document->getObjectById(mode))) { - Inkscape::XML::Node *arrow= elemref->getRepr(); - if (arrow) { - arrow->setAttribute("sodipodi:insensitive", "true"); - arrow->setAttribute("transform", NULL); - Inkscape::XML::Node *arrow_data = arrow->firstChild(); - if (arrow_data) { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property (css, "fill","#000000"); - sp_repr_css_set_property (css, "stroke","none"); - arrow_data->setAttribute("transform", NULL); - sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - arrow_data->setAttribute("style", css_str.c_str()); - } - } - } else { - arrow = xml_doc->createElement("svg:marker"); - arrow->setAttribute("id", mode); - arrow->setAttribute("inkscape:stockid", mode); - arrow->setAttribute("orient", "auto"); - arrow->setAttribute("refX", "0.0"); - arrow->setAttribute("refY", "0.0"); - arrow->setAttribute("style", "overflow:visible"); - arrow->setAttribute("sodipodi:insensitive", "true"); - /* Create */ - Inkscape::XML::Node *arrow_path = xml_doc->createElement("svg:path"); - if (std::strcmp(mode, "ArrowDIN-start") == 0) { - arrow_path->setAttribute("d", "M -8,0 8,-2.11 8,2.11 z"); - } else if (std::strcmp(mode, "ArrowDIN-end") == 0) { - arrow_path->setAttribute("d", "M 8,0 -8,2.11 -8,-2.11 z"); - } else if (std::strcmp(mode, "ArrowDINout-start") == 0) { - arrow_path->setAttribute("d", "M 0,0 -16,2.11 -16,0.5 -26,0.5 -26,-0.5 -16,-0.5 -16,-2.11 z"); - } else { - arrow_path->setAttribute("d", "M 0,0 16,2.11 16,0.5 26,0.5 26,-0.5 16,-0.5 16,-2.11 z"); - } - - arrow_path->setAttribute("id", Glib::ustring(mode).append("_path").c_str()); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property (css, "fill","#000000"); - sp_repr_css_set_property (css, "stroke","none"); - sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - arrow_path->setAttribute("style", css_str.c_str()); - arrow->addChild(arrow_path, NULL); - Inkscape::GC::release(arrow_path); - elemref = SP_OBJECT(document->getDefs()->appendChildRepr(arrow)); - Inkscape::GC::release(arrow); - } - items.push_back(mode); -} - -void -LPEMeasureLine::createTextLabel(Geom::Point pos, double length, Geom::Coord angle, bool remove, bool valid) -{ - SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { - return; - } - Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *rtext = NULL; - double doc_w = document->getRoot()->width.value; - Geom::Scale scale = document->getDocumentScale(); - SPNamedView *nv = sp_document_namedview(document, NULL); - Glib::ustring display_unit = nv->display_units->abbr; - if (display_unit.empty()) { - display_unit = "px"; - } - //only check constrain viewbox on X - doc_scale = Inkscape::Util::Quantity::convert( scale[Geom::X], "px", nv->display_units ); - if( doc_scale > 0 ) { - doc_scale= 1.0/doc_scale; - } else { - doc_scale = 1.0; - } - const char * id = g_strdup(Glib::ustring("text-on-").append(this->getRepr()->attribute("id")).c_str()); - SPObject *elemref = NULL; - Inkscape::XML::Node *rtspan = NULL; - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - return; - } - pos = pos - Point::polar(angle, text_right_left); - rtext = elemref->getRepr(); - sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); - sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); - rtext->setAttribute("sodipodi:insensitive", "true"); - rtext->setAttribute("transform", NULL); - } else { - if (remove) { - return; - } - rtext = xml_doc->createElement("svg:text"); - rtext->setAttribute("xml:space", "preserve"); - rtext->setAttribute("id", id); - rtext->setAttribute("sodipodi:insensitive", "true"); - pos = pos - Point::polar(angle, text_right_left); - sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); - sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); - rtspan = xml_doc->createElement("svg:tspan"); - rtspan->setAttribute("sodipodi:role", "line"); - } - gchar * transform; - Geom::Affine affine = Geom::Affine(Geom::Translate(pos).inverse()); - angle = std::fmod(angle, 2*M_PI); - if (angle < 0) angle += 2*M_PI; - if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { - angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); - if (angle < 0) angle += 2*M_PI; - } - affine *= Geom::Rotate(angle); - affine *= Geom::Translate(pos); - if (rotate_anotation) { - transform = sp_svg_transform_write(affine); - } else { - transform = NULL; - } - rtext->setAttribute("transform", transform); - g_free(transform); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); - Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); - fontlister->fill_css(css, Glib::ustring(fontbutton.param_getSVGValue())); - std::stringstream font_size; - font_size.imbue(std::locale::classic()); - font_size << fontsize << "pt"; - sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); - sp_repr_css_set_property (css, "line-height","125%"); - sp_repr_css_set_property (css, "letter-spacing","0"); - sp_repr_css_set_property (css, "word-spacing", "0"); - sp_repr_css_set_property (css, "text-align", "center"); - sp_repr_css_set_property (css, "text-anchor", "middle"); - sp_repr_css_set_property (css, "fill", "#000000"); - sp_repr_css_set_property (css, "fill-opacity", "1"); - sp_repr_css_set_property (css, "stroke", "none"); - sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - if (!rtspan) { - rtspan = rtext->firstChild(); - } - rtext->setAttribute("style", css_str.c_str()); - rtspan->setAttribute("style", NULL); - rtspan->setAttribute("transform", NULL); - sp_repr_css_attr_unref (css); - if (!elemref) { - rtext->addChild(rtspan, NULL); - Inkscape::GC::release(rtspan); - } - length = Inkscape::Util::Quantity::convert(length / doc_scale, display_unit.c_str(), unit.get_abbreviation()); - char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); - if (local_locale) { - setlocale (LC_NUMERIC, ""); - } else { - setlocale (LC_NUMERIC, "C"); - } - gchar length_str[64]; - g_snprintf(length_str, 64, "%.*f", (int)precision, length); - setlocale (LC_NUMERIC, oldlocale); - g_free (oldlocale); - Glib::ustring label_value(format.param_getSVGValue()); - size_t s = label_value.find(Glib::ustring("{measure}"),0); - if(s < label_value.length()) { - label_value.replace(s,s+9,length_str); - } - s = label_value.find(Glib::ustring("{unit}"),0); - if(s < label_value.length()) { - label_value.replace(s,s+6,unit.get_abbreviation()); - } - if ( !valid ) { - label_value = Glib::ustring(_("Non Uniform Scale")); - } - Inkscape::XML::Node *rstring = NULL; - if (!elemref) { - rstring = xml_doc->createTextNode(label_value.c_str()); - rtspan->addChild(rstring, NULL); - Inkscape::GC::release(rstring); - } else { - rstring = rtspan->firstChild(); - rstring->setContent(label_value.c_str()); - } - if (!elemref) { - elemref = sp_lpe_item->parent->appendChildRepr(rtext); - Inkscape::GC::release(rtext); - } else if (elemref->parent != sp_lpe_item->parent) { - Inkscape::XML::Node *old_repr = elemref->getRepr(); - Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); - SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); - Inkscape::GC::release(copy); - elemref->deleteObject(); - copy->setAttribute("id", id); - elemref = elemref_copy; - } - items.push_back(id); - Geom::OptRect bounds = SP_ITEM(elemref)->bounds(SPItem::GEOMETRIC_BBOX); - if (bounds) { - anotation_width = bounds->width() * 1.15; - } -} - -void -LPEMeasureLine::createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows) -{ - SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { - return; - } - Inkscape::XML::Document *xml_doc = document->getReprDoc(); - SPObject *elemref = NULL; - Inkscape::XML::Node *line = NULL; - if (!main) { - Geom::Ray ray(start, end); - Geom::Coord angle = ray.angle(); - start = start + Point::polar(angle, helpline_distance ); - end = end + Point::polar(angle, helpline_overlap ); - } - Geom::PathVector line_pathv; - if (main && std::abs(text_top_bottom) < fontsize/1.5 && hide_back && !overflow){ - Geom::Path line_path; - double k = 0; - if (flip_side) { - k = (Geom::distance(start,end)/2.0) + arrow_gap - (anotation_width/2.0); - } else { - k = (Geom::distance(start,end)/2.0) - arrow_gap - (anotation_width/2.0); - } - if (Geom::distance(start,end) < anotation_width){ - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - } - return; - } - } - //k = std::max(k , arrow_gap -1); - Geom::Ray ray(end, start); - Geom::Coord angle = ray.angle(); - line_path.start(start); - line_path.appendNew(start - Point::polar(angle, k)); - line_pathv.push_back(line_path); - line_path.clear(); - line_path.start(end + Point::polar(angle, k)); - line_path.appendNew(end); - line_pathv.push_back(line_path); - } else { - Geom::Path line_path; - line_path.start(start); - line_path.appendNew(end); - line_pathv.push_back(line_path); - } - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - return; - } - line = elemref->getRepr(); - - gchar * line_str = sp_svg_write_path( line_pathv ); - line->setAttribute("d" , line_str); - line->setAttribute("transform", NULL); - g_free(line_str); - } else { - if (remove) { - return; - } - line = xml_doc->createElement("svg:path"); - line->setAttribute("id", id); - gchar * line_str = sp_svg_write_path( line_pathv ); - line->setAttribute("d" , line_str); - g_free(line_str); - } - line->setAttribute("sodipodi:insensitive", "true"); - line_pathv.clear(); - - Glib::ustring style = Glib::ustring("stroke:#000000;fill:none;"); - if (overflow && !arrows) { - line->setAttribute("inkscape:label", "downline"); - } else if (main) { - line->setAttribute("inkscape:label", "dinline"); - if (arrows_outside) { - style = style + Glib::ustring("marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);"); - } else { - style = style + Glib::ustring("marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);"); - } - } else { - line->setAttribute("inkscape:label", "dinhelpline"); - } - std::stringstream stroke_w; - stroke_w.imbue(std::locale::classic()); - if (line_group_05) { - double stroke_width = Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); - stroke_w << stroke_width; - style = style + Glib::ustring("stroke-width:" + stroke_w.str()); - } else { - double stroke_width = Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); - stroke_w << stroke_width; - style = style + Glib::ustring("stroke-width:" + stroke_w.str()); - } - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_attr_add_from_string(css, style.c_str()); - if (main) { - sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); - } else { - sp_repr_css_attr_add_from_string(css, helperlines_format.param_getSVGValue()); - } - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - line->setAttribute("style", css_str.c_str()); - if (!elemref) { - elemref = sp_lpe_item->parent->appendChildRepr(line); - Inkscape::GC::release(line); - } else if (elemref->parent != sp_lpe_item->parent) { - Inkscape::XML::Node *old_repr = elemref->getRepr(); - Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); - SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); - Inkscape::GC::release(copy); - elemref->deleteObject(); - copy->setAttribute("id", id); - } - items.push_back(id); -} - -void -LPEMeasureLine::doOnApply(SPLPEItem const* lpeitem) -{ - if (!SP_IS_SHAPE(lpeitem)) { - g_warning("LPE measure line can only be applied to shapes (not groups)."); - SPLPEItem * item = const_cast(lpeitem); - item->removeCurrentPathEffect(false); - } - id_origin.param_setValue(Glib::ustring(lpeitem->getId())); - id_origin.write_to_SVG(); -} - -void -LPEMeasureLine::doBeforeEffect (SPLPEItem const* lpeitem) -{ - SPLPEItem * splpeitem = const_cast(lpeitem); - sp_lpe_item->parent = dynamic_cast(splpeitem->parent); - SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { - return; - } - Inkscape::XML::Node *root = splpeitem->document->getReprRoot(); - Inkscape::XML::Node *root_origin = document->getReprRoot(); - if (root_origin != root) { - return; - } - SPPath *sp_path = dynamic_cast(splpeitem); - if (sp_path) { - Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(document->getRoot())); - Geom::PathVector pathvector = sp_path->get_original_curve()->get_pathvector(); - Geom::Affine writed_transform = Geom::identity(); - sp_svg_transform_read(splpeitem->getAttribute("transform"), &writed_transform ); - pathvector *= writed_transform; - if ((Glib::ustring(format.param_getSVGValue()).empty())) { - format.param_setValue(Glib::ustring("{measure}{unit}")); - } - size_t ncurves = pathvector.curveCount(); - if (ncurves != (size_t)curve_linked.param_get_max()) { - curve_linked.param_set_range(0, ncurves); - } - Geom::Point start = pathvector.initialPoint(); - Geom::Point end = pathvector.finalPoint(); - if (curve_linked) { //!0 - start = pathvector.pointAt(curve_linked -1); - end = pathvector.pointAt(curve_linked); - } - if (Geom::are_near(start, start_stored, 0.01) && - Geom::are_near(end, end_stored, 0.01) && - sp_lpe_item->getCurrentLPE() != this){ - return; - } - items.clear(); - start_stored = start; - end_stored = end; - Geom::Point hstart = start; - Geom::Point hend = end; - bool remove = false; - if (Geom::are_near(hstart, hend)) { - remove = true; - } - if (orientation == OM_VERTICAL) { - Coord xpos = std::max(hstart[Geom::X],hend[Geom::X]); - if (flip_side) { - xpos = std::min(hstart[Geom::X],hend[Geom::X]); - } - hstart[Geom::X] = xpos; - hend[Geom::X] = xpos; - if (hstart[Geom::Y] > hend[Geom::Y]) { - swap(hstart,hend); - swap(start,end); - } - if (Geom::are_near(hstart[Geom::Y], hend[Geom::Y])) { - remove = true; - } - } - if (orientation == OM_HORIZONTAL) { - Coord ypos = std::max(hstart[Geom::Y],hend[Geom::Y]); - if (flip_side) { - ypos = std::min(hstart[Geom::Y],hend[Geom::Y]); - } - hstart[Geom::Y] = ypos; - hend[Geom::Y] = ypos; - if (hstart[Geom::X] < hend[Geom::X]) { - swap(hstart,hend); - swap(start,end); - } - if (Geom::are_near(hstart[Geom::X], hend[Geom::X])) { - remove = true; - } - } - double length = Geom::distance(hstart,hend) * scale; - Geom::Point pos = Geom::middle_point(hstart,hend); - Geom::Ray ray(hstart,hend); - Geom::Coord angle = ray.angle(); - if (flip_side) { - angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); - if (angle < 0) angle += 2*M_PI; - } - if (arrows_outside) { - createArrowMarker("ArrowDINout-start"); - createArrowMarker("ArrowDINout-end"); - } else { - createArrowMarker("ArrowDIN-start"); - createArrowMarker("ArrowDIN-end"); - } - //We get the font size to offset the text to the middle - Pango::FontDescription fontdesc(Glib::ustring(fontbutton.param_getSVGValue())); - fontsize = fontdesc.get_size()/(double)Pango::SCALE; - fontsize *= document->getRoot()->c2p.inverse().expansionX(); - Geom::Coord angle_cross = std::fmod(angle + rad_from_deg(90), 2*M_PI); - if (angle_cross < 0) angle_cross += 2*M_PI; - angle = std::fmod(angle, 2*M_PI); - if (angle < 0) angle += 2*M_PI; - if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { - pos = pos - Point::polar(angle_cross, (position - text_top_bottom) + fontsize/2.5); - } else { - pos = pos - Point::polar(angle_cross, (position + text_top_bottom) - fontsize/2.5); - } - double parents_scale = (affinetransform.expansionX() + affinetransform.expansionY()) / 2.0; - if (scale_sensitive) { - length *= parents_scale; - } - if (scale_sensitive && !affinetransform.preservesAngles()) { - createTextLabel(pos, length, angle, remove, false); - } else { - createTextLabel(pos, length, angle, remove, true); - } - bool overflow = false; - const char * downline = g_strdup(Glib::ustring("downline-").append(this->getRepr()->attribute("id")).c_str()); - //delete residual lines if exist - createLine(Geom::Point(),Geom::Point(), downline, true, overflow, true, false); - //Create it - if ((anotation_width/2) + std::abs(text_right_left) > Geom::distance(start,end)/2.0) { - Geom::Point sstart = end - Point::polar(angle_cross, position); - Geom::Point send = end - Point::polar(angle_cross, position); - if ((text_right_left < 0 && flip_side) || (text_right_left > 0 && !flip_side)) { - sstart = start - Point::polar(angle_cross, position); - send = start - Point::polar(angle_cross, position); - } - Geom::Point prog_end = Geom::Point(); - if (std::abs(text_top_bottom) < fontsize/1.5 && hide_back) { - if (text_right_left > 0 ) { - prog_end = sstart - Point::polar(angle, std::abs(text_right_left) - (anotation_width/1.9) - (Geom::distance(start,end)/2.0)); - } else { - prog_end = sstart + Point::polar(angle, std::abs(text_right_left) - (anotation_width/1.9) - (Geom::distance(start,end)/2.0)); - } - } else { - if (text_right_left > 0 ) { - prog_end = sstart - Point::polar(angle,(anotation_width/2) + std::abs(text_right_left) - (Geom::distance(start,end)/2.0)); - } else { - prog_end = sstart + Point::polar(angle,(anotation_width/2) + std::abs(text_right_left) - (Geom::distance(start,end)/2.0)); - } - } - overflow = true; - createLine(sstart, prog_end, downline, true, overflow, false, false); - } - //LINE - arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); - if (line_group_05) { - arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); - } - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); - char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); - setlocale (LC_NUMERIC, "C"); - double width_line = atof(sp_repr_css_property(css,"stroke-width","-1")); - setlocale (LC_NUMERIC, oldlocale); - g_free (oldlocale); - if (width_line > -0.0001) { - arrow_gap = 8 * Inkscape::Util::Quantity::convert(width_line/ doc_scale, "mm", display_unit.c_str()); - } - if (flip_side) { - arrow_gap *= -1; - } - hstart = hstart - Point::polar(angle_cross, position); - createLine(start, hstart, g_strdup(Glib::ustring("infoline-on-start-").append(this->getRepr()->attribute("id")).c_str()), false, false, remove); - hend = hend - Point::polar(angle_cross, position); - createLine(end, hend, g_strdup(Glib::ustring("infoline-on-end-").append(this->getRepr()->attribute("id")).c_str()), false, false, remove); - if (!arrows_outside) { - hstart = hstart + Point::polar(angle, arrow_gap); - hend = hend - Point::polar(angle, arrow_gap ); - } - createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(this->getRepr()->attribute("id")).c_str()), true, overflow, remove, true); - } -} - -void -LPEMeasureLine::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) -{ - processObjects(LPE_VISIBILITY); -} - -void -LPEMeasureLine::doOnRemove (SPLPEItem const* /*lpeitem*/) -{ - //set "keep paths" hook on sp-lpe-item.cpp - if (keep_paths) { - processObjects(LPE_TO_OBJECTS); - items.clear(); - return; - } - processObjects(LPE_ERASE); -} - -Gtk::Widget *LPEMeasureLine::newWidget() -{ - // use manage here, because after deletion of Effect object, others might - // still be pointing to this widget. - Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); - - vbox->set_border_width(5); - vbox->set_homogeneous(false); - vbox->set_spacing(2); - - std::vector::iterator it = param_vector.begin(); - Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); - vbox_expander->set_border_width(0); - vbox_expander->set_spacing(2); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter *param = *it; - Gtk::Widget *widg = dynamic_cast(param->param_newWidget()); - Glib::ustring *tip = param->param_getTooltip(); - if (widg) { - if (param->param_key != "dimline_format" && - param->param_key != "helperlines_format" && - param->param_key != "arrows_format" && - param->param_key != "anotation_format") { - vbox->pack_start(*widg, true, true, 2); - } else { - vbox_expander->pack_start(*widg, true, true, 2); - } - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; - } - expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show DIM CSS style override")))); - expander->add(*vbox_expander); - expander->set_expanded(expanded); - expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPEMeasureLine::onExpanderChanged) ); - vbox->pack_start(*expander, true, true, 2); - return dynamic_cast(vbox); -} - -void -LPEMeasureLine::onExpanderChanged() -{ - expanded = expander->get_expanded(); - if(expanded) { - expander->set_label (Glib::ustring(_("Hide DIM CSS style override"))); - } else { - expander->set_label (Glib::ustring(_("Show DIM CSS style override"))); - } -} - -Geom::PathVector -LPEMeasureLine::doEffect_path(Geom::PathVector const &path_in) -{ - return path_in; -} - -}; //namespace LivePathEffect -}; /* namespace Inkscape */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offset:((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 : diff --git a/src/live_effects/lpe-measure-line.h b/src/live_effects/lpe-measure-line.h deleted file mode 100644 index b42f7cfd5..000000000 --- a/src/live_effects/lpe-measure-line.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef INKSCAPE_LPE_MEASURE_LINE_H -#define INKSCAPE_LPE_MEASURE_LINE_H - -/* - * Author(s): - * Jabiertxo Arraiza Cenoz - * - * Copyright (C) 2014 Author(s) - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include "live_effects/effect.h" - -#include - -#include "live_effects/parameter/enum.h" -#include "live_effects/parameter/fontbutton.h" -#include "live_effects/parameter/text.h" -#include "live_effects/parameter/unit.h" -#include "live_effects/parameter/bool.h" -#include "live_effects/parameter/originalpath.h" -#include -#include <2geom/angle.h> -#include <2geom/ray.h> -#include <2geom/point.h> - -namespace Inkscape { -namespace LivePathEffect { - -enum OrientationMethod { - OM_HORIZONTAL, - OM_VERTICAL, - OM_PARALLEL, - OM_END -}; - -class LPEMeasureLine : public Effect { -public: - LPEMeasureLine(LivePathEffectObject *lpeobject); - virtual ~LPEMeasureLine(); - virtual void doBeforeEffect (SPLPEItem const* lpeitem); - virtual void doOnApply(SPLPEItem const* lpeitem); - virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); - virtual void doEffect (SPCurve * curve){}; //stop the chain - virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); - virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); - void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows = false); - void createTextLabel(Geom::Point pos, double length, Geom::Coord angle, bool remove, bool valid); - void onExpanderChanged(); - void createArrowMarker(const char * mode); - virtual Gtk::Widget *newWidget(); -private: - UnitParam unit; - FontButtonParam fontbutton; - EnumParam orientation; - ScalarParam curve_linked; - ScalarParam precision; - ScalarParam position; - ScalarParam text_top_bottom; - ScalarParam text_right_left; - ScalarParam helpline_distance; - ScalarParam helpline_overlap; - ScalarParam scale; - TextParam format; - TextParam id_origin; - BoolParam arrows_outside; - BoolParam flip_side; - BoolParam scale_sensitive; - BoolParam local_locale; - BoolParam line_group_05; - BoolParam rotate_anotation; - BoolParam hide_back; - TextParam dimline_format; - TextParam helperlines_format; - TextParam anotation_format; - TextParam arrows_format; - Glib::ustring display_unit; - bool expanded; - Gtk::Expander * expander; - double doc_scale; - double fontsize; - double anotation_width; - double arrow_gap; - Geom::Point start_stored; - Geom::Point end_stored; -/* Geom::Affine affine_over;*/ - LPEMeasureLine(const LPEMeasureLine &); - LPEMeasureLine &operator=(const LPEMeasureLine &); - -}; - -} //namespace LivePathEffect -} //namespace Inkscape - -#endif - -/* - 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 : diff --git a/src/live_effects/lpe-measure-segments.cpp b/src/live_effects/lpe-measure-segments.cpp new file mode 100644 index 000000000..ef7acdcfc --- /dev/null +++ b/src/live_effects/lpe-measure-segments.cpp @@ -0,0 +1,872 @@ +/* + * Author(s): + * Jabiertxo Arraiza Cenoz + * Some code and ideas migrated from dimensioning.py by + * Johannes B. Rutzmoser, johannes.rutzmoser (at) googlemail (dot) com + * https://github.com/Rutzmoser/inkscape_dimensioning + * Copyright (C) 2014 Author(s) + + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#include "live_effects/lpe-measure-segments.h" +#include +#include "ui/dialog/livepatheffect-editor.h" +#include +#include "inkscape.h" +#include "xml/node.h" +#include "xml/sp-css-attr.h" +#include "preferences.h" +#include "util/units.h" +#include "svg/svg-length.h" +#include "svg/svg-color.h" +#include "svg/svg.h" +#include "display/curve.h" +#include "helper/geom.h" +#include "2geom/affine.h" +#include "path-chemistry.h" +#include "style.h" +#include "sp-root.h" +#include "sp-defs.h" +#include "sp-item.h" +#include "sp-shape.h" +#include "sp-path.h" +#include "document.h" +#include +#include + +// TODO due to internal breakage in glibmm headers, this must be last: +#include + +using namespace Geom; +namespace Inkscape { +namespace LivePathEffect { + +static const Util::EnumData OrientationMethodData[] = { + { OM_HORIZONTAL, N_("Horizontal"), "horizontal" }, + { OM_VERTICAL, N_("Vertical"), "vertical" }, + { OM_PARALLEL, N_("Parallel"), "parallel" } +}; +static const Util::EnumDataConverter OMConverter(OrientationMethodData, OM_END); + +LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : + Effect(lpeobject), + unit(_("Unit"), _("Unit"), "unit", &wr, this, "px"), + fontbutton(_("Font"), _("Font Selector"), "fontbutton", &wr, this), + orientation(_("Orientation"), _("Orientation method"), "orientation", OMConverter, &wr, this, OM_PARALLEL, false), + precision(_("Precision"), _("Precision"), "precision", &wr, this, 2), + fix_crossings(_("Fix crossings °"), _("Fix crossings lines limit, 180° no fix"), "fix_crossings", &wr, this, 40), + position(_("Position"), _("Position"), "position", &wr, this, 5), + text_top_bottom(_("Text top/bottom"), _("Text top/bottom"), "text_top_bottom", &wr, this, 0), + text_right_left(_("Text right/left"), _("Text right/left"), "text_right_left", &wr, this, 0), + helpline_distance(_("Helpline distance"), _("Helpline distance"), "helpline_distance", &wr, this, 0.0), + helpline_overlap(_("Helpline overlap"), _("Helpline overlap"), "helpline_overlap", &wr, this, 2.0), + scale(_("Scale"), _("Scaling factor"), "scale", &wr, this, 1.0), + format(_("Format"), _("Format the number ex:{measure} {unit}, return to save"), "format", &wr, this,"{measure}{unit}"), + blacklist(_("Blacklist"), _("Optional line index that exclude measure, comma limited, you can add more LPE like this to fill the holes"), "blacklist", &wr, this,""), + whitelist(_("Inverse blacklist"), _("Blacklist as whitelist"), "whitelist", &wr, this, false), + arrows_outside(_("Arrows outside"), _("Arrows outside"), "arrows_outside", &wr, this, false), + flip_side(_("Flip side"), _("Flip side"), "flip_side", &wr, this, false), + scale_sensitive(_("Scale sensitive"), _("Costrained scale sensitive to transformed containers"), "scale_sensitive", &wr, this, true), + local_locale(_("Local Number Format"), _("Local number format"), "local_locale", &wr, this, true), + line_group_05(_("Line Group 0.5"), _("Line Group 0.5, from 0.7"), "line_group_05", &wr, this, true), + rotate_anotation(_("Rotate Anotation"), _("Rotate Anotation"), "rotate_anotation", &wr, this, true), + hide_back(_("Hide if label over"), _("Hide DIN line if label over"), "hide_back", &wr, this, true), + dimline_format(_("CSS DIN line"), _("Override CSS to DIN line, return to save, empty to reset to DIM"), "dimline_format", &wr, this,""), + helperlines_format(_("CSS helpers"), _("Override CSS to helper lines, return to save, empty to reset to DIM"), "helperlines_format", &wr, this,""), + anotation_format(_("CSS anotation"), _("Override CSS to anotation text, return to save, empty to reset to DIM"), "anotation_format", &wr, this,""), + arrows_format(_("CSS arrows"), _("Override CSS to arrows, return to save, empty to reset DIM"), "arrows_format", &wr, this,""), + expanded(false) +{ + //set to true the parameters you want to be changed his default values + registerParameter(&unit); + registerParameter(&fontbutton); + registerParameter(&orientation); + registerParameter(&precision); + registerParameter(&fix_crossings); + registerParameter(&position); + registerParameter(&text_top_bottom); + registerParameter(&text_right_left); + registerParameter(&helpline_distance); + registerParameter(&helpline_overlap); + registerParameter(&scale); + registerParameter(&format); + registerParameter(&blacklist); + registerParameter(&whitelist); + registerParameter(&arrows_outside); + registerParameter(&flip_side); + registerParameter(&scale_sensitive); + registerParameter(&local_locale); + registerParameter(&line_group_05); + registerParameter(&rotate_anotation); + registerParameter(&hide_back); + registerParameter(&dimline_format); + registerParameter(&helperlines_format); + registerParameter(&anotation_format); + registerParameter(&arrows_format); + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + Glib::ustring format_value = prefs->getString("/live_effects/measure-line/format"); + if(format_value.empty()){ + format_value = "{measure}{unit}"; + } + format.param_update_default(format_value.c_str()); + + format.param_hide_canvas_text(); + blacklist.param_hide_canvas_text(); + dimline_format.param_hide_canvas_text(); + helperlines_format.param_hide_canvas_text(); + anotation_format.param_hide_canvas_text(); + arrows_format.param_hide_canvas_text(); + precision.param_set_range(0, 100); + precision.param_set_increments(1, 1); + precision.param_set_digits(0); + precision.param_make_integer(true); + fix_crossings.param_set_range(0, 180); + fix_crossings.param_set_increments(1, 1); + fix_crossings.param_set_digits(0); + fix_crossings.param_make_integer(true); + position.param_set_range(-999999.0, 999999.0); + position.param_set_increments(1, 1); + position.param_set_digits(2); + scale.param_set_range(-999999.0, 999999.0); + scale.param_set_increments(1, 1); + scale.param_set_digits(4); + text_top_bottom.param_set_range(-999999.0, 999999.0); + text_top_bottom.param_set_increments(1, 1); + text_top_bottom.param_set_digits(2); + text_right_left.param_set_range(-999999.0, 999999.0); + text_right_left.param_set_increments(1, 1); + text_right_left.param_set_digits(2); + helpline_distance.param_set_range(-999999.0, 999999.0); + helpline_distance.param_set_increments(1, 1); + helpline_distance.param_set_digits(2); + helpline_overlap.param_set_range(-999999.0, 999999.0); + helpline_overlap.param_set_increments(1, 1); + helpline_overlap.param_set_digits(2); +} + +LPEMeasureSegments::~LPEMeasureSegments() {} + +void +LPEMeasureSegments::createArrowMarker(const char * mode) +{ + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + SPObject *elemref = NULL; + Inkscape::XML::Node *arrow = NULL; + if ((elemref = document->getObjectById(mode))) { + Inkscape::XML::Node *arrow= elemref->getRepr(); + if (arrow) { + arrow->setAttribute("sodipodi:insensitive", "true"); + arrow->setAttribute("transform", NULL); + Inkscape::XML::Node *arrow_data = arrow->firstChild(); + if (arrow_data) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property (css, "fill","#000000"); + sp_repr_css_set_property (css, "stroke","none"); + arrow_data->setAttribute("transform", NULL); + sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + arrow_data->setAttribute("style", css_str.c_str()); + } + } + } else { + arrow = xml_doc->createElement("svg:marker"); + arrow->setAttribute("id", mode); + arrow->setAttribute("inkscape:stockid", mode); + arrow->setAttribute("orient", "auto"); + arrow->setAttribute("refX", "0.0"); + arrow->setAttribute("refY", "0.0"); + arrow->setAttribute("style", "overflow:visible"); + arrow->setAttribute("sodipodi:insensitive", "true"); + /* Create */ + Inkscape::XML::Node *arrow_path = xml_doc->createElement("svg:path"); + if (std::strcmp(mode, "ArrowDIN-start") == 0) { + arrow_path->setAttribute("d", "M -8,0 8,-2.11 8,2.11 z"); + } else if (std::strcmp(mode, "ArrowDIN-end") == 0) { + arrow_path->setAttribute("d", "M 8,0 -8,2.11 -8,-2.11 z"); + } else if (std::strcmp(mode, "ArrowDINout-start") == 0) { + arrow_path->setAttribute("d", "M 0,0 -16,2.11 -16,0.5 -26,0.5 -26,-0.5 -16,-0.5 -16,-2.11 z"); + } else { + arrow_path->setAttribute("d", "M 0,0 16,2.11 16,0.5 26,0.5 26,-0.5 16,-0.5 16,-2.11 z"); + } + + arrow_path->setAttribute("id", Glib::ustring(mode).append("_path").c_str()); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property (css, "fill","#000000"); + sp_repr_css_set_property (css, "stroke","none"); + sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + arrow_path->setAttribute("style", css_str.c_str()); + arrow->addChild(arrow_path, NULL); + Inkscape::GC::release(arrow_path); + elemref = SP_OBJECT(document->getDefs()->appendChildRepr(arrow)); + Inkscape::GC::release(arrow); + } + items.push_back(mode); +} + +void +LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double length, Geom::Coord angle, bool remove, bool valid) +{ + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Node *rtext = NULL; + double doc_w = document->getRoot()->width.value; + Geom::Scale scale = document->getDocumentScale(); + SPNamedView *nv = sp_document_namedview(document, NULL); + Glib::ustring display_unit = nv->display_units->abbr; + if (display_unit.empty()) { + display_unit = "px"; + } + //only check constrain viewbox on X + doc_scale = Inkscape::Util::Quantity::convert( scale[Geom::X], "px", nv->display_units ); + if( doc_scale > 0 ) { + doc_scale= 1.0/doc_scale; + } else { + doc_scale = 1.0; + } + const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); + SPObject *elemref = NULL; + Inkscape::XML::Node *rtspan = NULL; + if ((elemref = document->getObjectById(id))) { + if (remove) { + elemref->deleteObject(); + return; + } + pos = pos - Point::polar(angle, text_right_left); + rtext = elemref->getRepr(); + sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); + sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); + rtext->setAttribute("sodipodi:insensitive", "true"); + rtext->setAttribute("transform", NULL); + } else { + if (remove) { + return; + } + rtext = xml_doc->createElement("svg:text"); + rtext->setAttribute("xml:space", "preserve"); + rtext->setAttribute("id", id); + rtext->setAttribute("sodipodi:insensitive", "true"); + pos = pos - Point::polar(angle, text_right_left); + sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); + sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); + rtspan = xml_doc->createElement("svg:tspan"); + rtspan->setAttribute("sodipodi:role", "line"); + } + gchar * transform; + Geom::Affine affine = Geom::Affine(Geom::Translate(pos).inverse()); + angle = std::fmod(angle, 2*M_PI); + if (angle < 0) angle += 2*M_PI; + if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { + angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); + if (angle < 0) angle += 2*M_PI; + } + affine *= Geom::Rotate(angle); + affine *= Geom::Translate(pos); + if (rotate_anotation) { + transform = sp_svg_transform_write(affine); + } else { + transform = NULL; + } + rtext->setAttribute("transform", transform); + g_free(transform); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); + Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); + fontlister->fill_css(css, Glib::ustring(fontbutton.param_getSVGValue())); + std::stringstream font_size; + font_size.imbue(std::locale::classic()); + font_size << fontsize << "pt"; + sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); + sp_repr_css_set_property (css, "line-height","125%"); + sp_repr_css_set_property (css, "letter-spacing","0"); + sp_repr_css_set_property (css, "word-spacing", "0"); + sp_repr_css_set_property (css, "text-align", "center"); + sp_repr_css_set_property (css, "text-anchor", "middle"); + sp_repr_css_set_property (css, "fill", "#000000"); + sp_repr_css_set_property (css, "fill-opacity", "1"); + sp_repr_css_set_property (css, "stroke", "none"); + sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + if (!rtspan) { + rtspan = rtext->firstChild(); + } + rtext->setAttribute("style", css_str.c_str()); + rtspan->setAttribute("style", NULL); + rtspan->setAttribute("transform", NULL); + sp_repr_css_attr_unref (css); + if (!elemref) { + rtext->addChild(rtspan, NULL); + Inkscape::GC::release(rtspan); + } + length = Inkscape::Util::Quantity::convert(length / doc_scale, display_unit.c_str(), unit.get_abbreviation()); + char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); + if (local_locale) { + setlocale (LC_NUMERIC, ""); + } else { + setlocale (LC_NUMERIC, "C"); + } + gchar length_str[64]; + g_snprintf(length_str, 64, "%.*f", (int)precision, length); + setlocale (LC_NUMERIC, oldlocale); + g_free (oldlocale); + Glib::ustring label_value(format.param_getSVGValue()); + size_t s = label_value.find(Glib::ustring("{measure}"),0); + if(s < label_value.length()) { + label_value.replace(s,s+9,length_str); + } + s = label_value.find(Glib::ustring("{unit}"),0); + if(s < label_value.length()) { + label_value.replace(s,s+6,unit.get_abbreviation()); + } + if ( !valid ) { + label_value = Glib::ustring(_("Non Uniform Scale")); + } + Inkscape::XML::Node *rstring = NULL; + if (!elemref) { + rstring = xml_doc->createTextNode(label_value.c_str()); + rtspan->addChild(rstring, NULL); + Inkscape::GC::release(rstring); + } else { + rstring = rtspan->firstChild(); + rstring->setContent(label_value.c_str()); + } + if (!elemref) { + elemref = sp_lpe_item->parent->appendChildRepr(rtext); + Inkscape::GC::release(rtext); + } else if (elemref->parent != sp_lpe_item->parent) { + Inkscape::XML::Node *old_repr = elemref->getRepr(); + Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); + SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); + Inkscape::GC::release(copy); + elemref->deleteObject(); + copy->setAttribute("id", id); + elemref = elemref_copy; + } + items.push_back(id); + Geom::OptRect bounds = SP_ITEM(elemref)->bounds(SPItem::GEOMETRIC_BBOX); + if (bounds) { + anotation_width = bounds->width() * 1.15; + } +} + +void +LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows) +{ + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + SPObject *elemref = NULL; + Inkscape::XML::Node *line = NULL; + if (!main) { + Geom::Ray ray(start, end); + Geom::Coord angle = ray.angle(); + start = start + Point::polar(angle, helpline_distance ); + end = end + Point::polar(angle, helpline_overlap ); + } + Geom::PathVector line_pathv; + if (main && std::abs(text_top_bottom) < fontsize/1.5 && hide_back && !overflow){ + Geom::Path line_path; + double k = 0; + if (flip_side) { + k = (Geom::distance(start,end)/2.0) + arrow_gap - (anotation_width/2.0); + } else { + k = (Geom::distance(start,end)/2.0) - arrow_gap - (anotation_width/2.0); + } + if (Geom::distance(start,end) < anotation_width){ + if ((elemref = document->getObjectById(id))) { + if (remove) { + elemref->deleteObject(); + } + return; + } + } + //k = std::max(k , arrow_gap -1); + Geom::Ray ray(end, start); + Geom::Coord angle = ray.angle(); + line_path.start(start); + line_path.appendNew(start - Point::polar(angle, k)); + line_pathv.push_back(line_path); + line_path.clear(); + line_path.start(end + Point::polar(angle, k)); + line_path.appendNew(end); + line_pathv.push_back(line_path); + } else { + Geom::Path line_path; + line_path.start(start); + line_path.appendNew(end); + line_pathv.push_back(line_path); + } + if ((elemref = document->getObjectById(id))) { + if (remove) { + elemref->deleteObject(); + return; + } + line = elemref->getRepr(); + + gchar * line_str = sp_svg_write_path( line_pathv ); + line->setAttribute("d" , line_str); + line->setAttribute("transform", NULL); + g_free(line_str); + } else { + if (remove) { + return; + } + line = xml_doc->createElement("svg:path"); + line->setAttribute("id", id); + gchar * line_str = sp_svg_write_path( line_pathv ); + line->setAttribute("d" , line_str); + g_free(line_str); + } + line->setAttribute("sodipodi:insensitive", "true"); + line_pathv.clear(); + + Glib::ustring style = Glib::ustring("stroke:#000000;fill:none;"); + if (overflow && !arrows) { + line->setAttribute("inkscape:label", "downline"); + } else if (main) { + line->setAttribute("inkscape:label", "dinline"); + if (arrows_outside) { + style = style + Glib::ustring("marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);"); + } else { + style = style + Glib::ustring("marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);"); + } + } else { + line->setAttribute("inkscape:label", "dinhelpline"); + } + std::stringstream stroke_w; + stroke_w.imbue(std::locale::classic()); + if (line_group_05) { + double stroke_width = Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); + stroke_w << stroke_width; + style = style + Glib::ustring("stroke-width:" + stroke_w.str()); + } else { + double stroke_width = Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); + stroke_w << stroke_width; + style = style + Glib::ustring("stroke-width:" + stroke_w.str()); + } + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css, style.c_str()); + if (main) { + sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); + } else { + sp_repr_css_attr_add_from_string(css, helperlines_format.param_getSVGValue()); + } + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + line->setAttribute("style", css_str.c_str()); + if (!elemref) { + elemref = sp_lpe_item->parent->appendChildRepr(line); + Inkscape::GC::release(line); + } else if (elemref->parent != sp_lpe_item->parent) { + Inkscape::XML::Node *old_repr = elemref->getRepr(); + Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); + SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); + Inkscape::GC::release(copy); + elemref->deleteObject(); + copy->setAttribute("id", id); + } + items.push_back(id); +} + +void +LPEMeasureSegments::doOnApply(SPLPEItem const* lpeitem) +{ + if (!SP_IS_SHAPE(lpeitem)) { + g_warning("LPE measure line can only be applied to shapes (not groups)."); + SPLPEItem * item = const_cast(lpeitem); + item->removeCurrentPathEffect(false); + } +} + +bool +LPEMeasureSegments::hasMeassure (size_t i) +{ + std::string listsegments(std::string(blacklist.param_getSVGValue()) + std::string(",")); + listsegments.erase(std::remove(listsegments.begin(), listsegments.end(), ' '), listsegments.end()); + size_t s = listsegments.find(std::to_string(i) + std::string(","),0); + if(s < listsegments.length()) { + if (whitelist) { + return true; + } else { + return false; + } + } else { + if (whitelist) { + return false; + } else { + return true; + } + } + return false; +} + +double getAngle(Geom::Point p1, Geom::Point p2, Geom::Point p3, bool flip_side, double fix_crossings){ + Geom::Ray ray_1(p2,p1); + Geom::Ray ray_2(p3,p1); + bool ccw_toggle = cross(p1 - p2, p3 - p2) < 0; + double angle = angle_between(ray_1, ray_2, ccw_toggle); + if (Geom::deg_from_rad(angle) < fix_crossings || + Geom::deg_from_rad(angle) > 180 || + ((ccw_toggle && flip_side) || (!ccw_toggle && !flip_side))) + { + angle = 0; + } + return angle; +} + +void +LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) +{ + SPLPEItem * splpeitem = const_cast(lpeitem); + sp_lpe_item->parent = dynamic_cast(splpeitem->parent); + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + Inkscape::XML::Node *root = splpeitem->document->getReprRoot(); + Inkscape::XML::Node *root_origin = document->getReprRoot(); + if (root_origin != root) { + return; + } + SPPath *sp_path = dynamic_cast(splpeitem); + if (sp_path) { + Geom::Point start_stored; + Geom::Point end_stored; + Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(document->getRoot())); + Geom::PathVector pathvector = sp_path->get_original_curve()->get_pathvector(); + Geom::Affine writed_transform = Geom::identity(); + sp_svg_transform_read(splpeitem->getAttribute("transform"), &writed_transform ); + pathvector *= writed_transform; + if ((Glib::ustring(format.param_getSVGValue()).empty())) { + format.param_setValue(Glib::ustring("{measure}{unit}")); + } + size_t ncurves = pathvector.curveCount(); + items.clear(); + double start_angle_cross = 0; + double end_angle_cross = 0; + size_t counter = -1; + for (size_t i = 0; i < pathvector.size(); i++) { + for (size_t j = 0; j < pathvector[i].size(); j++) { + counter++; + if(hasMeassure(counter + 1)) { + Geom::Point prev = Geom::Point(0,0); + if (j == 0 && pathvector[i].closed()) { + prev = pathvector.pointAt(pathvector[i].size() - 1); + } else if (j != 0) { + prev = pathvector[i].pointAt(j - 1); + } + Geom::Point start = pathvector[i].pointAt(j); + Geom::Point end = pathvector[i].pointAt(j + 1); + Geom::Point next = Geom::Point(0,0); + if(pathvector[i].closed() && pathvector[i].size() == j+1){ + end = pathvector[i].pointAt(0); + next = pathvector[i].pointAt(1); + } else if (pathvector[i].size() > j + 1) { + next = pathvector[i].pointAt(j+2); + } + const char * idstart = Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str(); + SPObject *elemref = NULL; + if ((elemref = document->getObjectById(idstart))) { + start_stored = *SP_PATH(elemref)->get_curve()->first_point(); + } + const char * idend = Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str(); + elemref = NULL; + if ((elemref = document->getObjectById(idend))) { + end_stored = *SP_PATH(elemref)->get_curve()->first_point(); + } + if (Geom::are_near(start, start_stored, 0.01) && + Geom::are_near(end, end_stored, 0.01)) + { + continue; + } + Geom::Point hstart = start; + Geom::Point hend = end; + bool remove = false; + if (Geom::are_near(hstart, hend)) { + remove = true; + } + + if (orientation == OM_VERTICAL) { + Coord xpos = std::max(hstart[Geom::X],hend[Geom::X]); + if (flip_side) { + xpos = std::min(hstart[Geom::X],hend[Geom::X]); + } + hstart[Geom::X] = xpos; + hend[Geom::X] = xpos; + if (hstart[Geom::Y] > hend[Geom::Y]) { + swap(hstart,hend); + swap(start,end); + } + if (Geom::are_near(hstart[Geom::Y], hend[Geom::Y])) { + remove = true; + } + } else if (orientation == OM_HORIZONTAL) { + Coord ypos = std::max(hstart[Geom::Y],hend[Geom::Y]); + if (flip_side) { + ypos = std::min(hstart[Geom::Y],hend[Geom::Y]); + } + hstart[Geom::Y] = ypos; + hend[Geom::Y] = ypos; + if (hstart[Geom::X] < hend[Geom::X]) { + swap(hstart,hend); + swap(start,end); + } + if (Geom::are_near(hstart[Geom::X], hend[Geom::X])) { + remove = true; + } + } else if (fix_crossings != 180) { + start_angle_cross = getAngle( start, prev, end, flip_side, fix_crossings); + if (prev == Geom::Point(0,0)) { + start_angle_cross = 0; + } + end_angle_cross = getAngle(end, start, next, flip_side, fix_crossings); + if (next == Geom::Point(0,0)) { + end_angle_cross = 0; + } + } + Geom::Ray ray(hstart,hend); + Geom::Coord angle = ray.angle(); + if (flip_side) { + angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); + if (angle < 0) angle += 2*M_PI; + } + Geom::Coord angle_cross = std::fmod(angle + rad_from_deg(90), 2*M_PI); + if (angle_cross < 0) angle_cross += 2*M_PI; + angle = std::fmod(angle, 2*M_PI); + if (angle < 0) angle += 2*M_PI; + double turn = Geom::rad_from_deg(-90); + if (flip_side) { + end_angle_cross *= -1; + start_angle_cross *= -1; + //turn *= -1; + } + if (fix_crossings != 180 && start_angle_cross != 0) { + double position_turned = position / sin(start_angle_cross/2.0); + hstart = hstart - Point::polar(angle_cross - (start_angle_cross/2.0) - turn, position_turned); + } else { + hstart = hstart - Point::polar(angle_cross, position); + } + createLine(start, hstart, g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, false, remove); + + if (fix_crossings != 180 && end_angle_cross != 0) { + double position_turned = position / sin(end_angle_cross/2.0); + hend = hend - Point::polar(angle_cross + (end_angle_cross/2.0) + turn, position_turned); + } else { + hend = hend - Point::polar(angle_cross, position); + } + double length = Geom::distance(hstart,hend) * scale; + Geom::Point pos = Geom::middle_point(hstart,hend); + if (arrows_outside) { + createArrowMarker("ArrowDINout-start"); + createArrowMarker("ArrowDINout-end"); + } else { + createArrowMarker("ArrowDIN-start"); + createArrowMarker("ArrowDIN-end"); + } + //We get the font size to offset the text to the middle + Pango::FontDescription fontdesc(Glib::ustring(fontbutton.param_getSVGValue())); + fontsize = fontdesc.get_size()/(double)Pango::SCALE; + fontsize *= document->getRoot()->c2p.inverse().expansionX(); + + if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { + pos = pos - Point::polar(angle_cross, text_top_bottom + (fontsize/2.5)); + } else { + pos = pos + Point::polar(angle_cross, text_top_bottom + (fontsize/2.5)); + } + double parents_scale = (affinetransform.expansionX() + affinetransform.expansionY()) / 2.0; + if (scale_sensitive) { + length *= parents_scale; + } + if (scale_sensitive && !affinetransform.preservesAngles()) { + createTextLabel(pos, counter, length, angle, remove, false); + } else { + createTextLabel(pos, counter, length, angle, remove, true); + } + bool overflow = false; + const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); + //delete residual lines if exist + createLine(Geom::Point(),Geom::Point(), downline, true, overflow, true, false); + //Create it + if ((anotation_width/2) + std::abs(text_right_left / doc_scale) > Geom::distance(hstart,hend)/2.0) { + Geom::Point sstart = hend - Point::polar(angle_cross, position); + Geom::Point send = hend - Point::polar(angle_cross, position); + if ((text_right_left < 0 && flip_side) || (text_right_left > 0 && !flip_side)) { + sstart = hstart - Point::polar(angle_cross, position); + send = hstart - Point::polar(angle_cross, position); + } + Geom::Point prog_end = Geom::Point(); + if (std::abs(text_top_bottom / doc_scale) < fontsize/1.5 && hide_back) { + if (text_right_left > 0 ) { + prog_end = sstart - Point::polar(angle, std::abs(text_right_left / doc_scale) - (anotation_width/1.9) - (Geom::distance(hstart,hend)/2.0)); + } else { + prog_end = sstart + Point::polar(angle, std::abs(text_right_left / doc_scale) - (anotation_width/1.9) - (Geom::distance(hstart,hend)/2.0)); + } + } else { + if (text_right_left / doc_scale > 0 ) { + prog_end = sstart - Point::polar(angle,(anotation_width/2) + std::abs(text_right_left / doc_scale) - (Geom::distance(hstart,hend)/2.0)); + } else { + prog_end = sstart + Point::polar(angle,(anotation_width/2) + std::abs(text_right_left / doc_scale) - (Geom::distance(hstart,hend)/2.0)); + } + } + overflow = true; + createLine(sstart, prog_end, downline, true, overflow, false, false); + } + //LINE + arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); + if (line_group_05) { + arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); + } + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); + char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); + setlocale (LC_NUMERIC, "C"); + double width_line = atof(sp_repr_css_property(css,"stroke-width","-1")); + setlocale (LC_NUMERIC, oldlocale); + g_free (oldlocale); + if (width_line > -0.0001) { + arrow_gap = 8 * Inkscape::Util::Quantity::convert(width_line/ doc_scale, "mm", display_unit.c_str()); + } + if(flip_side) { + arrow_gap *= -1; + } + createLine(end, hend, g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, false, remove); + if (!arrows_outside) { + hstart = hstart + Point::polar(angle, arrow_gap); + hend = hend - Point::polar(angle, arrow_gap ); + } + createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, overflow, remove, true); + } else { + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); + SPObject *elemref = NULL; + if ((elemref = document->getObjectById(id))) { + elemref->deleteObject(); + } + } + } + } + for (size_t k = ncurves; k <= previous_size; k++) { + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); + SPObject *elemref = NULL; + if ((elemref = document->getObjectById(id))) { + elemref->deleteObject(); + } + } + previous_size = ncurves; + } +} + +void +LPEMeasureSegments::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) +{ + processObjects(LPE_VISIBILITY); +} + +void +LPEMeasureSegments::doOnRemove (SPLPEItem const* /*lpeitem*/) +{ + //set "keep paths" hook on sp-lpe-item.cpp + if (keep_paths) { + processObjects(LPE_TO_OBJECTS); + items.clear(); + return; + } + processObjects(LPE_ERASE); +} + +Gtk::Widget *LPEMeasureSegments::newWidget() +{ + // use manage here, because after deletion of Effect object, others might + // still be pointing to this widget. + Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); + + vbox->set_border_width(5); + vbox->set_homogeneous(false); + vbox->set_spacing(2); + + std::vector::iterator it = param_vector.begin(); + Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); + vbox_expander->set_border_width(0); + vbox_expander->set_spacing(2); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter *param = *it; + Gtk::Widget *widg = dynamic_cast(param->param_newWidget()); + Glib::ustring *tip = param->param_getTooltip(); + if (widg) { + if (param->param_key != "dimline_format" && + param->param_key != "helperlines_format" && + param->param_key != "arrows_format" && + param->param_key != "anotation_format") { + vbox->pack_start(*widg, true, true, 2); + } else { + vbox_expander->pack_start(*widg, true, true, 2); + } + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); + } + } + } + + ++it; + } + expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show DIM CSS style override")))); + expander->add(*vbox_expander); + expander->set_expanded(expanded); + expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPEMeasureSegments::onExpanderChanged) ); + vbox->pack_start(*expander, true, true, 2); + return dynamic_cast(vbox); +} + +void +LPEMeasureSegments::onExpanderChanged() +{ + expanded = expander->get_expanded(); + if(expanded) { + expander->set_label (Glib::ustring(_("Hide DIM CSS style override"))); + } else { + expander->set_label (Glib::ustring(_("Show DIM CSS style override"))); + } +} + +Geom::PathVector +LPEMeasureSegments::doEffect_path(Geom::PathVector const &path_in) +{ + return path_in; +} + +}; //namespace LivePathEffect +}; /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offset:((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 : diff --git a/src/live_effects/lpe-measure-segments.h b/src/live_effects/lpe-measure-segments.h new file mode 100644 index 000000000..d651da8a4 --- /dev/null +++ b/src/live_effects/lpe-measure-segments.h @@ -0,0 +1,108 @@ +#ifndef INKSCAPE_LPE_MEASURE_SEGMENTS_H +#define INKSCAPE_LPE_MEASURE_SEGMENTS_H + +/* + * Author(s): + * Jabiertxo Arraiza Cenoz + * + * Copyright (C) 2014 Author(s) + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/effect.h" + +#include + +#include "live_effects/parameter/enum.h" +#include "live_effects/parameter/fontbutton.h" +#include "live_effects/parameter/text.h" +#include "live_effects/parameter/unit.h" +#include "live_effects/parameter/bool.h" +#include "live_effects/parameter/originalpath.h" +#include +#include <2geom/angle.h> +#include <2geom/ray.h> +#include <2geom/point.h> + +namespace Inkscape { +namespace LivePathEffect { + +enum OrientationMethod { + OM_HORIZONTAL, + OM_VERTICAL, + OM_PARALLEL, + OM_END +}; + +class LPEMeasureSegments : public Effect { +public: + LPEMeasureSegments(LivePathEffectObject *lpeobject); + virtual ~LPEMeasureSegments(); + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual void doOnApply(SPLPEItem const* lpeitem); + virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); + virtual void doEffect (SPCurve * curve){}; //stop the chain + virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); + virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); + void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows = false); + void createTextLabel(Geom::Point pos, size_t counter, double length, Geom::Coord angle, bool remove, bool valid); + void onExpanderChanged(); + void createArrowMarker(const char * mode); + bool hasMeassure (size_t i); + virtual Gtk::Widget *newWidget(); +private: + UnitParam unit; + FontButtonParam fontbutton; + EnumParam orientation; + ScalarParam precision; + ScalarParam fix_crossings; + ScalarParam position; + ScalarParam text_top_bottom; + ScalarParam text_right_left; + ScalarParam helpline_distance; + ScalarParam helpline_overlap; + ScalarParam scale; + TextParam format; + TextParam blacklist; + BoolParam whitelist; + BoolParam arrows_outside; + BoolParam flip_side; + BoolParam scale_sensitive; + BoolParam local_locale; + BoolParam line_group_05; + BoolParam rotate_anotation; + BoolParam hide_back; + TextParam dimline_format; + TextParam helperlines_format; + TextParam anotation_format; + TextParam arrows_format; + Glib::ustring display_unit; + bool expanded; + Gtk::Expander * expander; + double doc_scale; + double fontsize; + double anotation_width; + double previous_size; + double arrow_gap; + + LPEMeasureSegments(const LPEMeasureSegments &); + LPEMeasureSegments &operator=(const LPEMeasureSegments &); + +}; + +} //namespace LivePathEffect +} //namespace Inkscape + +#endif + +/* + 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 : diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 84d318db2..edd572b8b 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -24,7 +24,6 @@ #include "live_effects/lpe-path_length.h" #include "live_effects/lpeobject.h" #include "live_effects/lpeobject-reference.h" -#include "live_effects/lpe-measure-line.h" #include "live_effects/lpe-mirror_symmetry.h" #include "live_effects/lpe-copy_rotate.h" -- cgit v1.2.3