summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-style.cpp26
-rw-r--r--src/extension/internal/cairo-render-context.cpp28
-rw-r--r--src/extension/internal/emf-inout.cpp58
-rw-r--r--src/extension/internal/emf-print.cpp53
-rw-r--r--src/extension/internal/javafx-out.cpp31
-rw-r--r--src/extension/internal/latex-pstricks.cpp10
-rw-r--r--src/extension/internal/wmf-inout.cpp33
-rw-r--r--src/extension/internal/wmf-print.cpp49
-rw-r--r--src/livarot/PathCutting.cpp35
-rw-r--r--src/live_effects/lpe-dash-stroke.cpp437
-rw-r--r--src/live_effects/lpe-dash-stroke.h31
-rw-r--r--src/object/sp-item.cpp5
-rw-r--r--src/object/sp-item.h2
-rw-r--r--src/preferences-skeleton.h1
-rw-r--r--src/style-internal.cpp32
-rw-r--r--src/style-internal.h6
-rw-r--r--src/svg/svg-length.h7
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp6
-rw-r--r--src/ui/dialog/inkscape-preferences.h4
-rw-r--r--src/widgets/dash-selector.cpp13
-rw-r--r--src/widgets/stroke-style.cpp40
21 files changed, 619 insertions, 288 deletions
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index cec6de4d3..564a6209b 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -11,6 +11,9 @@
#include "display/nr-style.h"
#include "style.h"
+#include "util/units.h"
+#include "inkscape.h"
+#include "object/sp-namedview.h"
#include "object/sp-paint-server.h"
#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!)
#include "display/drawing-context.h"
@@ -218,10 +221,29 @@ void NRStyle::set(SPStyle *style, SPStyle *context_style)
n_dash = style->stroke_dasharray.values.size();
if (n_dash != 0) {
- dash_offset = style->stroke_dashoffset.value;
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
+ Geom::Rect vbox = document->getViewBox();
+ if (style->stroke_dashoffset.unit == SVGLength::NONE) {
+ dash_offset = style->stroke_dashoffset.value;
+ } else if (style->stroke_dashoffset.unit == SVGLength::PERCENT) {
+ dash_offset = vbox.width() * style->stroke_dashoffset.value;
+ } else {
+ dash_offset = Inkscape::Util::Quantity::convert(style->stroke_dashoffset.computed, "px", display_unit.c_str());
+ }
dash = new double[n_dash];
for (unsigned int i = 0; i < n_dash; ++i) {
- dash[i] = style->stroke_dasharray.values[i];
+ if (style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dash[i] = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dash[i] = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dash[i] = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
}
} else {
dash_offset = 0.0;
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index da0797600..6d2267fde 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -48,7 +48,8 @@
#include "object/sp-pattern.h"
#include "object/sp-mask.h"
#include "object/sp-clippath.h"
-
+#include "object/sp-namedview.h"
+#include "inkscape.h"
#include "util/units.h"
#ifdef WIN32
#include "libnrtype/FontFactory.h" // USE_PANGO_WIN32
@@ -1435,10 +1436,31 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, Geom::OptRect const &p
{
size_t ndashes = style->stroke_dasharray.values.size();
double* dashes =(double*)malloc(ndashes*sizeof(double));
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for( unsigned i = 0; i < ndashes; ++i ) {
- dashes[i] = style->stroke_dasharray.values[i];
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dashes[i] = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dashes[i] = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dashes[i] = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
+ }
+ double dash_offset = 0;
+ if (style->stroke_dashoffset.unit == SVGLength::NONE) {
+ dash_offset = style->stroke_dashoffset.value;
+ } else if (style->stroke_dashoffset.unit == SVGLength::PERCENT) {
+ dash_offset = vbox.width() * style->stroke_dashoffset.value ;
+ } else {
+ dash_offset = Inkscape::Util::Quantity::convert(style->stroke_dashoffset.computed, "px", display_unit.c_str());
}
- cairo_set_dash(_cr, dashes, ndashes, style->stroke_dashoffset.value);
+ cairo_set_dash(_cr, dashes, ndashes, dash_offset);
free(dashes);
} else {
cairo_set_dash(_cr, nullptr, 0, 0.0); // disable dashing
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp
index d0556e467..79645466f 100644
--- a/src/extension/internal/emf-inout.cpp
+++ b/src/extension/internal/emf-inout.cpp
@@ -35,6 +35,7 @@
#include "document.h"
#include "object/sp-root.h"
#include "object/sp-path.h"
+#include "object/sp-namedview.h"
#include "print.h"
#include "extension/system.h"
#include "extension/print.h"
@@ -45,9 +46,11 @@
#include "display/drawing-item.h"
#include "clear-n_.h"
#include "svg/svg.h"
+#include "svg/svg-length.h"
#include "util/units.h" // even though it is included indirectly by emf-inout.h
#include "inkscape.h" // even though it is included indirectly by emf-inout.h
+
#include "emf-print.h"
#include "emf-inout.h"
@@ -981,10 +984,24 @@ Emf::output_style(PEMF_CALLBACK_DATA d, int iType)
!d->dc[d->level].style.stroke_dasharray.values.empty() )
{
tmp_style << "stroke-dasharray:";
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (unsigned i=0; i<d->dc[d->level].style.stroke_dasharray.values.size(); i++) {
if (i)
tmp_style << ",";
- tmp_style << d->dc[d->level].style.stroke_dasharray.values[i];
+ if(d->dc[d->level].style.stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ tmp_style << d->dc[d->level].style.stroke_dasharray.values[i].value;
+ } else if (d->dc[d->level].style.stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ tmp_style << vbox.width() * d->dc[d->level].style.stroke_dasharray.values[i].value;
+ } else {
+ tmp_style << Inkscape::Util::Quantity::convert(d->dc[d->level].style.stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
+
}
tmp_style << ";";
tmp_style << "stroke-dashoffset:0;";
@@ -1097,17 +1114,21 @@ Emf::select_pen(PEMF_CALLBACK_DATA d, int index)
int penstyle = (pEmr->lopn.lopnStyle & U_PS_STYLE_MASK);
if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values)))
d->dc[d->level].style.stroke_dasharray.values.clear();
+ SVGLength svglength;
+ svglength.read("1");
if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 3 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ svglength.read("3");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ svglength.read("1");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
if (penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
d->dc[d->level].style.stroke_dasharray.set = 1;
@@ -1183,7 +1204,9 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index)
d->dc[d->level].style.stroke_dasharray.values.clear();
for (unsigned int i=0; i<pEmr->elp.elpNumEntries; i++) {
double dash_length = pix_to_abs_size( d, pEmr->elp.elpStyleEntry[i] );
- d->dc[d->level].style.stroke_dasharray.values.push_back(dash_length);
+ SVGLength svglength;
+ svglength.set(SVGLength::PX, dash_length);
+ d->dc[d->level].style.stroke_dasharray.values.push_back(svglength);
}
d->dc[d->level].style.stroke_dasharray.set = 1;
} else {
@@ -1200,17 +1223,24 @@ Emf::select_extpen(PEMF_CALLBACK_DATA d, int index)
int penstyle = (pEmr->elp.elpPenStyle & U_PS_STYLE_MASK);
if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values)))
d->dc[d->level].style.stroke_dasharray.values.clear();
+ SVGLength svglength;
if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 3 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 2 );
+ svglength.read("3");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ svglength.read("2");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 2 );
+ svglength.read("1");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ svglength.read("2");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
if (penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 2 );
+ svglength.read("1");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ svglength.read("2");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
d->dc[d->level].style.stroke_dasharray.set = 1;
diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp
index 254000db3..459794654 100644
--- a/src/extension/internal/emf-print.cpp
+++ b/src/extension/internal/emf-print.cpp
@@ -38,7 +38,7 @@
#include "helper/geom.h"
#include "helper/geom-curves.h"
#include "util/units.h"
-
+#include "inkscape.h"
#include "inkscape-version.h"
#include "extension/system.h"
@@ -55,6 +55,7 @@
#include "object/sp-root.h"
#include "object/sp-shape.h"
#include "object/sp-clippath.h"
+#include "object/sp-namedview.h"
#include "style.h"
#include "display/cairo-utils.h"
@@ -695,17 +696,32 @@ int PrintEmf::create_pen(SPStyle const *style, const Geom::Affine &transform)
} else {
unsigned i = 0;
while ((linestyle != U_PS_USERSTYLE) && (i < style->stroke_dasharray.values.size())) {
- if (style->stroke_dasharray.values[i] > 0.00000001) {
+ if (style->stroke_dasharray.values[i].computed > 0.00000001) {
linestyle = U_PS_USERSTYLE;
}
i++;
}
-
+
if (linestyle == U_PS_USERSTYLE) {
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
n_dash = style->stroke_dasharray.values.size();
dash = new uint32_t[n_dash];
for (i = 0; i < n_dash; i++) {
- dash[i] = MAX(1, (uint32_t) round(scale * style->stroke_dasharray.values[i] * PX2WORLD));
+ double dashval = 0;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dashval = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
+ dash[i] = MAX(1, (uint32_t) round(scale * dashval * PX2WORLD));
}
}
}
@@ -1455,10 +1471,25 @@ unsigned int PrintEmf::stroke(
}
tlength = length(tmp_pathpw, 0.1);
tmp_pathpw2 = arc_length_parametrization(tmp_pathpw);
-
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
// go around the dash array repeatedly until the entire path is consumed (but not beyond).
while (slength < tlength) {
- elength = slength + style->stroke_dasharray.values[i++];
+ SVGLength i1 = style->stroke_dasharray.values[i++];
+ double dashval = 0;
+ if(i1.unit == SVGLength::NONE) {
+ dashval = i1.value;
+ } else if (i1.unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * i1.value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(i1.computed, "px", display_unit.c_str());
+ }
+ elength = slength + dashval;
if (elength > tlength) {
elength = tlength;
}
@@ -1469,7 +1500,15 @@ unsigned int PrintEmf::stroke(
first_frag = fragment;
}
slength = elength;
- slength += style->stroke_dasharray.values[i++]; // the gap
+ SVGLength i2 = style->stroke_dasharray.values[i++];
+ if(i2.unit == SVGLength::NONE) {
+ dashval = i2.value;
+ } else if (i2.unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * i2.value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(i2.computed, "px", display_unit.c_str());
+ }
+ slength += dashval; // the gap
if (i >= n_dash) {
i = 0;
}
diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp
index ad8fa855d..9b795ea21 100644
--- a/src/extension/internal/javafx-out.cpp
+++ b/src/extension/internal/javafx-out.cpp
@@ -40,7 +40,9 @@
#include "object/sp-path.h"
#include "object/sp-linear-gradient.h"
#include "object/sp-radial-gradient.h"
+#include "object/sp-namedview.h"
#include "style.h"
+#include "util/units.h"
#include <string>
#include <cstdio>
@@ -435,15 +437,38 @@ bool JavaFXOutput::doStyle(SPStyle *style)
out(" strokeLineJoin: %s\n", getStrokeLineJoin(linejoin).c_str());
out(" strokeMiterLimit: %s\n", DSTR(style->stroke_miterlimit.value));
if (style->stroke_dasharray.set) {
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
+ double dash_offset = 0;
+ if (style->stroke_dashoffset.unit == SVGLength::NONE) {
+ dash_offset = style->stroke_dashoffset.value;
+ } else if (style->stroke_dashoffset.unit == SVGLength::PERCENT) {
+ dash_offset = vbox.width() * style->stroke_dashoffset.value;
+ } else {
+ dash_offset = Inkscape::Util::Quantity::convert(style->stroke_dashoffset.computed, "px", display_unit.c_str());
+ }
if (style->stroke_dashoffset.set) {
- out(" strokeDashOffset: %s\n", DSTR(style->stroke_dashoffset.value));
+ out(" strokeDashOffset: %s\n", DSTR(dash_offset));
}
out(" strokeDashArray: [ ");
for(unsigned i = 0; i < style->stroke_dasharray.values.size(); i++ ) {
+ double dash = 0;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dash = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dash = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dash = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
if (i > 0) {
- out(", %.2lf", style->stroke_dasharray.values[i]);
+ out(", %.2lf", dash);
}else {
- out(" %.2lf", style->stroke_dasharray.values[i]);
+ out(" %.2lf", dash);
}
}
out(" ]\n");
diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp
index f3bf06708..664ec0310 100644
--- a/src/extension/internal/latex-pstricks.cpp
+++ b/src/extension/internal/latex-pstricks.cpp
@@ -23,8 +23,10 @@
#include "util/units.h"
#include "helper/geom-curves.h"
+#include "object/sp-namedview.h"
#include "extension/print.h"
#include "extension/system.h"
+#include "inkscape.h"
#include "inkscape-version.h"
#include "io/sys.h"
#include "latex-pstricks.h"
@@ -240,11 +242,17 @@ unsigned int PrintLatex::stroke(Inkscape::Extension::Print * /*mod*/,
if (style->stroke_dasharray.set && !style->stroke_dasharray.values.empty()) {
os << ",linestyle=dashed,dash=";
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (unsigned i = 0; i < style->stroke_dasharray.values.size(); i++) {
if ((i)) {
os << " ";
}
- os << style->stroke_dasharray.values[i];
+ os << Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
}
}
diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp
index 72d44e123..a3df20903 100644
--- a/src/extension/internal/wmf-inout.cpp
+++ b/src/extension/internal/wmf-inout.cpp
@@ -44,8 +44,10 @@
#include "extension/output.h"
#include "display/drawing.h"
#include "display/drawing-item.h"
+#include "object/sp-namedview.h"
#include "clear-n_.h"
#include "svg/svg.h"
+#include "svg/svg-length.h"
#include "util/units.h" // even though it is included indirectly by wmf-inout.h
#include "inkscape.h" // even though it is included indirectly by wmf-inout.h
@@ -889,10 +891,23 @@ Wmf::output_style(PWMF_CALLBACK_DATA d)
!d->dc[d->level].style.stroke_dasharray.values.empty())
{
tmp_style << "stroke-dasharray:";
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (unsigned i=0; i<d->dc[d->level].style.stroke_dasharray.values.size(); i++) {
if (i)
tmp_style << ",";
- tmp_style << d->dc[d->level].style.stroke_dasharray.values[i];
+ if(d->dc[d->level].style.stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ tmp_style << d->dc[d->level].style.stroke_dasharray.values[i].value;
+ } else if (d->dc[d->level].style.stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ tmp_style << vbox.width() * d->dc[d->level].style.stroke_dasharray.values[i].value;
+ } else {
+ tmp_style << Inkscape::Util::Quantity::convert(d->dc[d->level].style.stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
}
tmp_style << ";";
tmp_style << "stroke-dashoffset:0;";
@@ -987,17 +1002,21 @@ Wmf::select_pen(PWMF_CALLBACK_DATA d, int index)
int penstyle = (up.Style & U_PS_STYLE_MASK);
if (!d->dc[d->level].style.stroke_dasharray.values.empty() && (d->level==0 || (d->level>0 && d->dc[d->level].style.stroke_dasharray.values!=d->dc[d->level-1].style.stroke_dasharray.values)))
d->dc[d->level].style.stroke_dasharray.values.clear();
+ SVGLength svglength;
if (penstyle==U_PS_DASH || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 3 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ svglength.read("3");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ svglength.read("1");
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
+ svglength.read("1");
if (penstyle==U_PS_DOT || penstyle==U_PS_DASHDOT || penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
if (penstyle==U_PS_DASHDOTDOT) {
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
- d->dc[d->level].style.stroke_dasharray.values.push_back( 1 );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
+ d->dc[d->level].style.stroke_dasharray.values.push_back( svglength );
}
d->dc[d->level].style.stroke_dasharray.set = 1;
diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp
index 613ae3f04..dbcfebfc5 100644
--- a/src/extension/internal/wmf-print.cpp
+++ b/src/extension/internal/wmf-print.cpp
@@ -40,6 +40,7 @@
#include "helper/geom-curves.h"
#include "inkscape-version.h"
+#include "inkscape.h"
#include "util/units.h"
@@ -55,6 +56,7 @@
#include "object/sp-linear-gradient.h"
#include "object/sp-root.h"
#include "object/sp-item.h"
+#include "object/sp-namedview.h"
#include "splivarot.h" // pieces for union on shapes
#include <2geom/svg-path-parser.h> // to get from SVG text to Geom::Path
@@ -602,8 +604,23 @@ int PrintWmf::create_pen(SPStyle const *style, const Geom::Affine &transform)
int mark_short=INT_MAX;
int mark_long =0;
int i;
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (i=0;i<n_dash;i++) {
- int mark = style->stroke_dasharray.values[i];
+ double dashval = 0;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dashval = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
+ int mark = (int)dashval;
if (mark>mark_long) { mark_long = mark; }
if (mark<mark_short) { mark_short = mark; }
}
@@ -887,10 +904,25 @@ unsigned int PrintWmf::stroke(
}
tlength = length(tmp_pathpw, 0.1);
tmp_pathpw2 = arc_length_parametrization(tmp_pathpw);
-
// go around the dash array repeatedly until the entire path is consumed (but not beyond).
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
while (slength < tlength) {
- elength = slength + style->stroke_dasharray.values[i++];
+ SVGLength i1 = style->stroke_dasharray.values[i++];
+ double dashval = 0;
+ if(i1.unit == SVGLength::NONE) {
+ dashval = i1.value;
+ } else if (i1.unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * i1.value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(i1.computed, "px", display_unit.c_str());
+ }
+ elength = slength + dashval;
if (elength > tlength) {
elength = tlength;
}
@@ -900,8 +932,15 @@ unsigned int PrintWmf::stroke(
} else {
first_frag = fragment;
}
- slength = elength;
- slength += style->stroke_dasharray.values[i++]; // the gap
+ SVGLength i2 = style->stroke_dasharray.values[i++];
+ if(i2.unit == SVGLength::NONE) {
+ dashval = i2.value;
+ } else if (i2.unit == SVGLength::PERCENT) {
+ dashval = vbox.width() * i2.value;
+ } else {
+ dashval = Inkscape::Util::Quantity::convert(i2.computed, "px", display_unit.c_str());
+ }
+ slength += dashval; // the gap
if (i >= n_dash) {
i = 0;
}
diff --git a/src/livarot/PathCutting.cpp b/src/livarot/PathCutting.cpp
index 3c518c521..b7f736021 100644
--- a/src/livarot/PathCutting.cpp
+++ b/src/livarot/PathCutting.cpp
@@ -20,6 +20,9 @@
#include "Path.h"
#include "style.h"
#include "livarot/path-description.h"
+#include "object/sp-namedview.h"
+#include "util/units.h"
+#include "inkscape.h"
#include <2geom/pathvector.h>
#include <2geom/point.h>
#include <2geom/affine.h>
@@ -62,16 +65,42 @@ void Path::DashPolylineFromStyle(SPStyle *style, float scale, float min_len)
double dlen = 0.0;
// Find total length
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (unsigned i = 0; i < style->stroke_dasharray.values.size(); i++) {
- dlen += style->stroke_dasharray.values[i] * scale;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dlen += style->stroke_dasharray.values[i].value * scale;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dlen += vbox.width() * style->stroke_dasharray.values[i].value * scale;
+ } else {
+ dlen += Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str()) * scale;
+ }
}
if (dlen >= min_len) {
// Extract out dash pattern (relative positions)
- double dash_offset = style->stroke_dashoffset.value * scale;
+ double dash_offset = 0;
+ if (style->stroke_dashoffset.unit == SVGLength::NONE) {
+ dash_offset = style->stroke_dashoffset.value * scale;
+ } else if (style->stroke_dashoffset.unit == SVGLength::PERCENT) {
+ dash_offset = vbox.width() * style->stroke_dashoffset.value * scale;
+ } else {
+ dash_offset = Inkscape::Util::Quantity::convert(style->stroke_dashoffset.computed * scale, "px", display_unit.c_str());
+ }
size_t n_dash = style->stroke_dasharray.values.size();
double *dash = g_new(double, n_dash);
for (unsigned i = 0; i < n_dash; i++) {
- dash[i] = style->stroke_dasharray.values[i] * scale;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dash[i] = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dash[i] = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dash[i] = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
}
// Convert relative positions to absolute postions
diff --git a/src/live_effects/lpe-dash-stroke.cpp b/src/live_effects/lpe-dash-stroke.cpp
index dd30d05a4..dd4efcbc2 100644
--- a/src/live_effects/lpe-dash-stroke.cpp
+++ b/src/live_effects/lpe-dash-stroke.cpp
@@ -12,28 +12,48 @@
namespace Inkscape {
namespace LivePathEffect {
+static const Util::EnumData<DashArraymethod> DashArraymethodData[] = {
+ { DA_LENGHT , N_("Lenght") , "lenght" },
+ { DA_PERCENTAGE, N_("Percentage"), "percent" }
+};
+static const Util::EnumDataConverter<DashArraymethod> DAConverter(DashArraymethodData, DA_END);
+
+static const Util::EnumData<DashAdjustArraymethod> DashAdjustArraymethodData[] = {
+ { DD_NONE , N_("None") , "none" },
+ { DD_STRETCH , N_("Stretch") , "stretch" },
+ { DD_STRETCH_DASHES , N_("Stretch dashes") , "stretch_dashes" },
+ { DD_STRETCH_GAPS , N_("Stretch gaps") , "stretch_gaps" },
+ { DD_COMPRESS , N_("Compress") , "compress" },
+ { DD_COMPRESS_DASHES , N_("Compress dashes") , "compress_dashes" },
+ { DD_COMPRESS_GAPS , N_("Compress gaps") , "compress_gaps" }
+};
+static const Util::EnumDataConverter<DashAdjustArraymethod> DDConverter(DashAdjustArraymethodData, DD_END);
+
LPEDashStroke::LPEDashStroke(LivePathEffectObject *lpeobject)
: Effect(lpeobject),
- numberdashes(_("Number of dashes"), _("Number of dashes"), "numberdashes", &wr, this, 3),
- holefactor(_("Hole factor"), _("Hole factor"), "holefactor", &wr, this, 0.0),
- splitsegments(_("Use segments"), _("Use segments"), "splitsegments", &wr, this, true),
- halfextreme(_("Half start/end"), _("Start and end of each segment has half size"), "halfextreme", &wr, this, true),
- unifysegment(_("Unify dashes"), _("Approximately unify the dashes length using the minimal length segment"), "unifysegment", &wr, this, true),
- message(_("Info Box"), _("Important messages"), "message", &wr, this, _("Add <b>\"Fill Between Many LPE\"</b> to add fill."))
+ unit(_("Unit"), _("Unit"), "unit", &wr, this, "px"),
+ method(_("Value type:"), _("% or units"),"method", DAConverter, &wr, this, DA_LENGHT),
+ dash_adjust(_("Adjust"), _("Adjustments for dahes and gaps"), "dash_adjust", DDConverter, &wr, this, DD_NONE),
+ stroke_dasharray(_("Dash Array"), _("Coma separated values for dashes and holes"), "stroke_dasharray", &wr, this,"1,1"),
+ stroke_dashoffset(_("Dash offset"), _("Dash offset"), "stroke_dashoffset", &wr, this, 0.0),
+ stroke_dashcorner(_("Dash corner"), _("Dash corner"), "stroke_dashcorner", &wr, this, 0.0),
+ message(_("Info Box"), _("Important messages"), "message", &wr, this, _("Add <b>\"Fill Between Many LPE\"</b> to add fill."))
{
- registerParameter(&numberdashes);
- registerParameter(&holefactor);
- registerParameter(&splitsegments);
- registerParameter(&halfextreme);
- registerParameter(&unifysegment);
+ registerParameter(&unit);
+ registerParameter(&method);
+ registerParameter(&dash_adjust);
+ registerParameter(&stroke_dasharray);
+ registerParameter(&stroke_dashoffset);
+ registerParameter(&stroke_dashcorner);
registerParameter(&message);
- numberdashes.param_set_range(2, 999999999);
- numberdashes.param_set_increments(1, 1);
- numberdashes.param_set_digits(0);
- holefactor.param_set_range(-0.99999, 0.99999);
- holefactor.param_set_increments(0.01, 0.01);
- holefactor.param_set_digits(5);
+ stroke_dashoffset.param_set_range(-999999999, 999999999);
+ stroke_dashoffset.param_set_increments(1, 1);
+ stroke_dashoffset.param_set_digits(5);
+ stroke_dashcorner.param_set_range(-999999999, 999999999);
+ stroke_dashcorner.param_set_increments(1, 1);
+ stroke_dashcorner.param_set_digits(5);
message.param_set_min_height(30);
+ stroke_dasharray.param_hide_canvas_text();
}
LPEDashStroke::~LPEDashStroke() = default;
@@ -75,197 +95,198 @@ LPEDashStroke::timeAtLength(double const A, Geom::Piecewise<Geom::D2<Geom::SBasi
Geom::PathVector
LPEDashStroke::doEffect_path(Geom::PathVector const & path_in){
Geom::PathVector const pv = pathv_to_linear_and_cubic_beziers(path_in);
- Geom::PathVector result;
- for (Geom::PathVector::const_iterator path_it = pv.begin(); path_it != pv.end(); ++path_it) {
- if (path_it->empty()) {
- continue;
- }
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- if (path_it->closed()) {
- const Geom::Curve &closingline = path_it->back_closed();
- // the closing line segment is always of type
- // Geom::LineSegment.
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- // closingline.isDegenerate() did not work, because it only checks for
- // *exact* zero length, which goes wrong for relative coordinates and
- // rounding errors...
- // the closing line segment has zero-length. So stop before that one!
- curve_endit = path_it->end_open();
- }
- }
- size_t numberdashes_fixed = numberdashes;
- if(!splitsegments) {
- numberdashes_fixed++;
- }
- size_t numberholes = numberdashes_fixed - 1;
- size_t ammount = numberdashes_fixed + numberholes;
- if (halfextreme) {
- ammount--;
- }
- double base = 1/(double)ammount;
- double globaldash = base * numberdashes_fixed * (1 + holefactor);
- if (halfextreme) {
- globaldash = base * (numberdashes_fixed - 1) * (1 + holefactor);
- }
- double globalhole = 1-globaldash;
- double dashpercent = globaldash/numberdashes_fixed;
- if (halfextreme) {
- dashpercent = globaldash/(numberdashes_fixed -1);
- }
- double holepercent = globalhole/numberholes;
- double dashsize_fixed = 0;
- double holesize_fixed = 0;
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2 = (*path_it).toPwSb();
- double lenght_pwd2 = length (pwd2);
- double minlenght = lenght_pwd2;
- if(unifysegment) {
- while (curve_it1 != curve_endit) {
- double lenght_segment = (*curve_it1).length();
- if (lenght_segment < minlenght) {
- minlenght = lenght_segment;
- dashsize_fixed = (*curve_it1).length() * dashpercent;
- holesize_fixed = (*curve_it1).length() * holepercent;
- }
- ++curve_it1;
- ++curve_it2;
- }
- curve_it1 = path_it->begin();
- curve_it2 = ++(path_it->begin());
- curve_endit = path_it->end_default();
- }
- size_t p_index = 0;
- size_t start_index = result.size();
- if(splitsegments) {
- while (curve_it1 != curve_endit) {
- Geom::Path segment = (*path_it).portion(p_index, p_index + 1);
- if(unifysegment) {
- double integral;
- double fractional = modf((*curve_it1).length()/(dashsize_fixed + holesize_fixed), &integral);
- numberdashes_fixed = (size_t)integral + 1;
- numberholes = numberdashes_fixed - 1;
- ammount = numberdashes_fixed + numberholes;
- if (halfextreme) {
- ammount--;
- }
- base = 1/(double)ammount;
- globaldash = base * numberdashes_fixed * (1 + holefactor);
- if (halfextreme) {
- globaldash = base * (numberdashes_fixed - 1) * (1 + holefactor);
- }
- globalhole = 1-globaldash;
- dashpercent = globaldash/numberdashes_fixed;
- if (halfextreme) {
- dashpercent = globaldash/(numberdashes_fixed -1);
- }
- holepercent = globalhole/numberholes;
- }
- double dashsize = (*curve_it1).length() * dashpercent;
- double holesize = (*curve_it1).length() * holepercent;
- if ((*curve_it1).isLineSegment()) {
- if (result.size() && Geom::are_near(segment.initialPoint(),result[result.size()-1].finalPoint())) {
- result[result.size()-1].setFinal(segment.initialPoint());
- if (halfextreme) {
- result[result.size()-1].append(segment.portion(0.0, dashpercent/2.0));
- } else {
- result[result.size()-1].append(segment.portion(0.0, dashpercent));
- }
- } else {
- if (halfextreme) {
- result.push_back(segment.portion(0.0, dashpercent/2.0));
- } else {
- result.push_back(segment.portion(0.0, dashpercent));
- }
- }
-
- double start = dashpercent + holepercent;
- if (halfextreme) {
- start = (dashpercent/2.0) + holepercent;
- }
- while (start < 1) {
- if (start + dashpercent > 1) {
- result.push_back(segment.portion(start, 1));
- } else {
- result.push_back(segment.portion(start, start + dashpercent));
- }
- start += dashpercent + holepercent;
- }
- } else if (!(*curve_it1).isLineSegment()) {
- double start = 0.0;
- double end = 0.0;
- if (halfextreme) {
- end = timeAtLength(dashsize/2.0,segment);
- } else {
- end = timeAtLength(dashsize,segment);
- }
- if (result.size() && Geom::are_near(segment.initialPoint(),result[result.size()-1].finalPoint())) {
- result[result.size()-1].setFinal(segment.initialPoint());
- result[result.size()-1].append(segment.portion(start, end));
- } else {
- result.push_back(segment.portion(start, end));
- }
- double startsize = dashsize + holesize;
- if (halfextreme) {
- startsize = (dashsize/2.0) + holesize;
- }
- double endsize = startsize + dashsize;
- start = timeAtLength(startsize,segment);
- end = timeAtLength(endsize,segment);
- while (start < 1 && start > 0) {
- result.push_back(segment.portion(start, end));
- startsize = endsize + holesize;
- endsize = startsize + dashsize;
- start = timeAtLength(startsize,segment);
- end = timeAtLength(endsize,segment);
- }
- }
- if (curve_it2 == curve_endit) {
- if (path_it->closed()) {
- Geom::Path end = result[result.size()-1];
- end.setFinal(result[start_index].initialPoint());
- end.append(result[start_index]);
- result[start_index] = end;
- }
- }
- p_index ++;
- ++curve_it1;
- ++curve_it2;
- }
- } else {
- double start = 0.0;
- double end = 0.0;
- double dashsize = lenght_pwd2 * dashpercent;
- double holesize = lenght_pwd2 * holepercent;
- if (halfextreme) {
- end = timeAtLength(dashsize/2.0,pwd2);
- } else {
- end = timeAtLength(dashsize,pwd2);
- }
- result.push_back((*path_it).portion(start, end));
- double startsize = dashsize + holesize;
- if (halfextreme) {
- startsize = (dashsize/2.0) + holesize;
- }
- double endsize = startsize + dashsize;
- start = timeAtLength(startsize,pwd2);
- end = timeAtLength(endsize,pwd2);
- while (start < (*path_it).size() && start > 0) {
- result.push_back((*path_it).portion(start, end));
- startsize = endsize + holesize;
- endsize = startsize + dashsize;
- start = timeAtLength(startsize,pwd2);
- end = timeAtLength(endsize,pwd2);
- }
- if (path_it->closed()) {
- Geom::Path end = result[result.size()-1];
- end.setFinal(result[start_index].initialPoint());
- end.append(result[start_index]);
- result[start_index] = end;
- }
- }
- }
- return result;
+ return pv;
+// Geom::PathVector result;
+// for (Geom::PathVector::const_iterator path_it = pv.begin(); path_it != pv.end(); ++path_it) {
+// if (path_it->empty()) {
+// continue;
+// }
+// Geom::Path::const_iterator curve_it1 = path_it->begin();
+// Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
+// Geom::Path::const_iterator curve_endit = path_it->end_default();
+// if (path_it->closed()) {
+// const Geom::Curve &closingline = path_it->back_closed();
+// // the closing line segment is always of type
+// // Geom::LineSegment.
+// if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+// // closingline.isDegenerate() did not work, because it only checks for
+// // *exact* zero length, which goes wrong for relative coordinates and
+// // rounding errors...
+// // the closing line segment has zero-length. So stop before that one!
+// curve_endit = path_it->end_open();
+// }
+// }
+// size_t numberdashes_fixed = numberdashes;
+// if(!splitsegments) {
+// numberdashes_fixed++;
+// }
+// size_t numberholes = numberdashes_fixed - 1;
+// size_t ammount = numberdashes_fixed + numberholes;
+// if (halfextreme) {
+// ammount--;
+// }
+// double base = 1/(double)ammount;
+// double globaldash = base * numberdashes_fixed * (1 + holefactor);
+// if (halfextreme) {
+// globaldash = base * (numberdashes_fixed - 1) * (1 + holefactor);
+// }
+// double globalhole = 1-globaldash;
+// double dashpercent = globaldash/numberdashes_fixed;
+// if (halfextreme) {
+// dashpercent = globaldash/(numberdashes_fixed -1);
+// }
+// double holepercent = globalhole/numberholes;
+// double dashsize_fixed = 0;
+// double holesize_fixed = 0;
+// Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2 = (*path_it).toPwSb();
+// double lenght_pwd2 = length (pwd2);
+// double minlenght = lenght_pwd2;
+// if(unifysegment) {
+// while (curve_it1 != curve_endit) {
+// double lenght_segment = (*curve_it1).length();
+// if (lenght_segment < minlenght) {
+// minlenght = lenght_segment;
+// dashsize_fixed = (*curve_it1).length() * dashpercent;
+// holesize_fixed = (*curve_it1).length() * holepercent;
+// }
+// ++curve_it1;
+// ++curve_it2;
+// }
+// curve_it1 = path_it->begin();
+// curve_it2 = ++(path_it->begin());
+// curve_endit = path_it->end_default();
+// }
+// size_t p_index = 0;
+// size_t start_index = result.size();
+// if(splitsegments) {
+// while (curve_it1 != curve_endit) {
+// Geom::Path segment = (*path_it).portion(p_index, p_index + 1);
+// if(unifysegment) {
+// double integral;
+// double fractional = modf((*curve_it1).length()/(dashsize_fixed + holesize_fixed), &integral);
+// numberdashes_fixed = (size_t)integral + 1;
+// numberholes = numberdashes_fixed - 1;
+// ammount = numberdashes_fixed + numberholes;
+// if (halfextreme) {
+// ammount--;
+// }
+// base = 1/(double)ammount;
+// globaldash = base * numberdashes_fixed * (1 + holefactor);
+// if (halfextreme) {
+// globaldash = base * (numberdashes_fixed - 1) * (1 + holefactor);
+// }
+// globalhole = 1-globaldash;
+// dashpercent = globaldash/numberdashes_fixed;
+// if (halfextreme) {
+// dashpercent = globaldash/(numberdashes_fixed -1);
+// }
+// holepercent = globalhole/numberholes;
+// }
+// double dashsize = (*curve_it1).length() * dashpercent;
+// double holesize = (*curve_it1).length() * holepercent;
+// if ((*curve_it1).isLineSegment()) {
+// if (result.size() && Geom::are_near(segment.initialPoint(),result[result.size()-1].finalPoint())) {
+// result[result.size()-1].setFinal(segment.initialPoint());
+// if (halfextreme) {
+// result[result.size()-1].append(segment.portion(0.0, dashpercent/2.0));
+// } else {
+// result[result.size()-1].append(segment.portion(0.0, dashpercent));
+// }
+// } else {
+// if (halfextreme) {
+// result.push_back(segment.portion(0.0, dashpercent/2.0));
+// } else {
+// result.push_back(segment.portion(0.0, dashpercent));
+// }
+// }
+//
+// double start = dashpercent + holepercent;
+// if (halfextreme) {
+// start = (dashpercent/2.0) + holepercent;
+// }
+// while (start < 1) {
+// if (start + dashpercent > 1) {
+// result.push_back(segment.portion(start, 1));
+// } else {
+// result.push_back(segment.portion(start, start + dashpercent));
+// }
+// start += dashpercent + holepercent;
+// }
+// } else if (!(*curve_it1).isLineSegment()) {
+// double start = 0.0;
+// double end = 0.0;
+// if (halfextreme) {
+// end = timeAtLength(dashsize/2.0,segment);
+// } else {
+// end = timeAtLength(dashsize,segment);
+// }
+// if (result.size() && Geom::are_near(segment.initialPoint(),result[result.size()-1].finalPoint())) {
+// result[result.size()-1].setFinal(segment.initialPoint());
+// result[result.size()-1].append(segment.portion(start, end));
+// } else {
+// result.push_back(segment.portion(start, end));
+// }
+// double startsize = dashsize + holesize;
+// if (halfextreme) {
+// startsize = (dashsize/2.0) + holesize;
+// }
+// double endsize = startsize + dashsize;
+// start = timeAtLength(startsize,segment);
+// end = timeAtLength(endsize,segment);
+// while (start < 1 && start > 0) {
+// result.push_back(segment.portion(start, end));
+// startsize = endsize + holesize;
+// endsize = startsize + dashsize;
+// start = timeAtLength(startsize,segment);
+// end = timeAtLength(endsize,segment);
+// }
+// }
+// if (curve_it2 == curve_endit) {
+// if (path_it->closed()) {
+// Geom::Path end = result[result.size()-1];
+// end.setFinal(result[start_index].initialPoint());
+// end.append(result[start_index]);
+// result[start_index] = end;
+// }
+// }
+// p_index ++;
+// ++curve_it1;
+// ++curve_it2;
+// }
+// } else {
+// double start = 0.0;
+// double end = 0.0;
+// double dashsize = lenght_pwd2 * dashpercent;
+// double holesize = lenght_pwd2 * holepercent;
+// if (halfextreme) {
+// end = timeAtLength(dashsize/2.0,pwd2);
+// } else {
+// end = timeAtLength(dashsize,pwd2);
+// }
+// result.push_back((*path_it).portion(start, end));
+// double startsize = dashsize + holesize;
+// if (halfextreme) {
+// startsize = (dashsize/2.0) + holesize;
+// }
+// double endsize = startsize + dashsize;
+// start = timeAtLength(startsize,pwd2);
+// end = timeAtLength(endsize,pwd2);
+// while (start < (*path_it).size() && start > 0) {
+// result.push_back((*path_it).portion(start, end));
+// startsize = endsize + holesize;
+// endsize = startsize + dashsize;
+// start = timeAtLength(startsize,pwd2);
+// end = timeAtLength(endsize,pwd2);
+// }
+// if (path_it->closed()) {
+// Geom::Path end = result[result.size()-1];
+// end.setFinal(result[start_index].initialPoint());
+// end.append(result[start_index]);
+// result[start_index] = end;
+// }
+// }
+// }
+// return result;
}
}; //namespace LivePathEffect
diff --git a/src/live_effects/lpe-dash-stroke.h b/src/live_effects/lpe-dash-stroke.h
index c84bd1960..b20b36f63 100644
--- a/src/live_effects/lpe-dash-stroke.h
+++ b/src/live_effects/lpe-dash-stroke.h
@@ -8,11 +8,31 @@
*/
#include "live_effects/effect.h"
+#include "live_effects/parameter/enum.h"
+#include "live_effects/parameter/text.h"
+#include "live_effects/parameter/unit.h"
#include "live_effects/parameter/message.h"
namespace Inkscape {
namespace LivePathEffect {
+enum DashArraymethod {
+ DA_LENGHT,
+ DA_PERCENTAGE,
+ DA_END
+};
+
+enum DashAdjustArraymethod {
+ DD_NONE,
+ DD_STRETCH,
+ DD_STRETCH_DASHES,
+ DD_STRETCH_GAPS,
+ DD_COMPRESS,
+ DD_COMPRESS_DASHES,
+ DD_COMPRESS_GAPS,
+ DD_END
+};
+
class LPEDashStroke : public Effect {
public:
LPEDashStroke(LivePathEffectObject *lpeobject);
@@ -22,11 +42,12 @@ public:
double timeAtLength(double const A, Geom::Path const &segment);
double timeAtLength(double const A, Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2);
private:
- ScalarParam numberdashes;
- ScalarParam holefactor;
- BoolParam splitsegments;
- BoolParam halfextreme;
- BoolParam unifysegment;
+ UnitParam unit;
+ EnumParam<DashArraymethod> method;
+ EnumParam< DashAdjustArraymethod> dash_adjust;
+ TextParam stroke_dasharray;
+ ScalarParam stroke_dashoffset;
+ ScalarParam stroke_dashcorner;
MessageParam message;
};
diff --git a/src/object/sp-item.cpp b/src/object/sp-item.cpp
index ec92c655f..fd27a6e90 100644
--- a/src/object/sp-item.cpp
+++ b/src/object/sp-item.cpp
@@ -1307,9 +1307,10 @@ void SPItem::adjust_stroke( gdouble ex )
if ( !style->stroke_dasharray.values.empty() ) {
for (unsigned i = 0; i < style->stroke_dasharray.values.size(); i++) {
- style->stroke_dasharray.values[i] *= ex;
+ style->stroke_dasharray.values[i].scale(ex);
}
- style->stroke_dashoffset.value *= ex;
+ style->stroke_dashoffset.value = style->stroke_dashoffset.value * ex;
+ style->stroke_dashoffset.computed = style->stroke_dashoffset.computed * ex;
}
updateRepr();
diff --git a/src/object/sp-item.h b/src/object/sp-item.h
index f6a6781e9..9651f9f26 100644
--- a/src/object/sp-item.h
+++ b/src/object/sp-item.h
@@ -395,7 +395,7 @@ public:
virtual Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const;
virtual void print(SPPrintContext *ctx);
- virtual const char* displayName() const;
+ virtual const char* displayName() const;
virtual char* description() const;
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void hide(unsigned int key);
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index 2a6083e55..c9479e90e 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -307,6 +307,7 @@ static char const preferences_skeleton[] =
" <group id=\"stickyzoom\" value=\"0\"/>\n"
" <group id=\"selcue\" value=\"2\"/>\n"
" <group id=\"transform\" stroke=\"1\" rectcorners=\"1\" pattern=\"1\" gradient=\"1\" />\n"
+" <group id=\"dash\" scale=\"1\" />\n"
" <group id=\"kbselection\" inlayer=\"1\" onlyvisible=\"1\" onlysensitive=\"1\" />\n"
" <group id=\"selection\" layerdeselect=\"1\" />\n"
" <group id=\"createbitmap\"/>\n"
diff --git a/src/style-internal.cpp b/src/style-internal.cpp
index 429353493..4ed59e82e 100644
--- a/src/style-internal.cpp
+++ b/src/style-internal.cpp
@@ -2034,20 +2034,17 @@ SPIDashArray::read( gchar const *str ) {
return;
}
- // std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("[,\\s]+", str );
+ std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("[,\\s]+", str );
- gchar *e = nullptr;
bool LineSolid = true;
- while (e != str && *str != '\0') {
- /* TODO: Should allow <length> rather than just a unitless (px) number. */
- double number = g_ascii_strtod(str, (char **) &e);
- values.push_back( number );
- if (number > 0.00000001)
+ for (auto token:tokens) {
+ SVGLength svglength;
+ double value = atof(token.c_str());
+ if(value > 0.00000001) {
LineSolid = false;
- if (e != str) {
- str = e;
}
- while (str && *str && !(isalnum(*str) || *str=='.')) str += 1;
+ svglength.read(token.c_str());
+ values.push_back(svglength);
}
if (LineSolid) {
@@ -2074,7 +2071,7 @@ SPIDashArray::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase
if (i) {
os << ", ";
}
- os << this->values[i];
+ os << this->values[i].write().c_str();
}
os << important_str();
os << ";";
@@ -2088,7 +2085,9 @@ SPIDashArray::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase
void
SPIDashArray::cascade( const SPIBase* const parent ) {
if( const SPIDashArray* p = dynamic_cast<const SPIDashArray*>(parent) ) {
- if( !set || inherit ) values = p->values; // Always inherits
+ if( !set || inherit ) {
+ values = p->values; // Always inherits
+ }
} else {
std::cerr << "SPIDashArray::cascade(): Incorrect parent type" << std::endl;
}
@@ -2112,10 +2111,13 @@ SPIDashArray::merge( const SPIBase* const parent ) {
bool
SPIDashArray::operator==(const SPIBase& rhs) {
if( const SPIDashArray* r = dynamic_cast<const SPIDashArray*>(&rhs) ) {
- return values == r->values && SPIBase::operator==(rhs);
- } else {
- return false;
+ for (int i = 0;i < values.size(); i++) {
+ if (values[i] != r->values[i]) {
+ return false;
+ }
+ }
}
+ return SPIBase::operator==(rhs);
}
diff --git a/src/style-internal.h b/src/style-internal.h
index 869f862af..3bc3d3972 100644
--- a/src/style-internal.h
+++ b/src/style-internal.h
@@ -32,7 +32,7 @@
#include "object/uri.h"
#include "svg/svg-icc-color.h"
-
+#include "svg/svg-length.h"
#include "xml/repr.h"
@@ -1010,9 +1010,9 @@ public:
}
- // To do: make private, change double to SVGLength
+ // To do: make private
public:
- std::vector<double> values;
+ std::vector<SVGLength> values;
};
/// Filter type internal to SPStyle
diff --git a/src/svg/svg-length.h b/src/svg/svg-length.h
index 4663aced4..eecd2f614 100644
--- a/src/svg/svg-length.h
+++ b/src/svg/svg-length.h
@@ -53,6 +53,13 @@ public:
value = computed = v;
return v;
}
+ // Check apples being compared to apples
+ virtual bool operator==(const SVGLength& svglength) const {
+ return (unit == svglength.unit) && (value == svglength.value);
+ }
+ virtual bool operator!=(const SVGLength& svglength) const {
+ return !(*this == svglength);
+ }
bool read(char const *str);
void readOrUnset(char const *str, Unit u = NONE, float v = 0, float c = 0);
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 70ee0a78a..9e6ff92c1 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -1447,6 +1447,12 @@ void InkscapePreferences::initPageBehavior()
_("Always store transformation as a transform= attribute on objects"));
this->AddPage(_page_transforms, _("Transforms"), iter_behavior, PREFS_PAGE_BEHAVIOR_TRANSFORMS);
+
+ _dash_scale.init ( _("Stroke width change dashes"), "/options/dash/scale", true);
+ _page_dashes.add_line( false, "", _dash_scale, "",
+ _("When chage stroke width, scale the dash array"));
+
+ this->AddPage(_page_dashes, _("Dashes"), iter_behavior, PREFS_PAGE_BEHAVIOR_DASHES);
// Scrolling options
_scroll_wheel.init ( "/options/wheelscroll/value", 0.0, 1000.0, 1.0, 1.0, 40.0, true, false);
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index a2f758287..55ea35f63 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -77,6 +77,7 @@ enum {
PREFS_PAGE_BEHAVIOR,
PREFS_PAGE_BEHAVIOR_SELECTING,
PREFS_PAGE_BEHAVIOR_TRANSFORMS,
+ PREFS_PAGE_BEHAVIOR_DASHES,
PREFS_PAGE_BEHAVIOR_SCROLLING,
PREFS_PAGE_BEHAVIOR_SNAPPING,
PREFS_PAGE_BEHAVIOR_STEPS,
@@ -168,6 +169,7 @@ protected:
UI::Widget::DialogPage _page_behavior;
UI::Widget::DialogPage _page_select;
UI::Widget::DialogPage _page_transforms;
+ UI::Widget::DialogPage _page_dashes;
UI::Widget::DialogPage _page_scrolling;
UI::Widget::DialogPage _page_snapping;
UI::Widget::DialogPage _page_steps;
@@ -317,6 +319,8 @@ protected:
UI::Widget::PrefRadioButton _trans_optimized;
UI::Widget::PrefRadioButton _trans_preserved;
+ UI::Widget::PrefCheckButton _dash_scale;
+
UI::Widget::PrefRadioButton _sel_all;
UI::Widget::PrefRadioButton _sel_current;
UI::Widget::PrefRadioButton _sel_recursive;
diff --git a/src/widgets/dash-selector.cpp b/src/widgets/dash-selector.cpp
index 37bf08b3d..43f5f66e9 100644
--- a/src/widgets/dash-selector.cpp
+++ b/src/widgets/dash-selector.cpp
@@ -27,7 +27,9 @@
#include "preferences.h"
#include "display/cairo-utils.h"
-
+#include "util/units.h"
+#include "inkscape.h"
+#include "object/sp-namedview.h"
#include "style.h"
#include "ui/dialog-events.h"
@@ -111,7 +113,12 @@ void SPDashSelector::init_dashes() {
if (!dash_prefs.empty()) {
SPStyle style;
dashes = g_new (double *, dash_prefs.size() + 2); // +1 for custom slot, +1 for terminator slot
-
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (std::vector<Glib::ustring>::iterator i = dash_prefs.begin(); i != dash_prefs.end(); ++i) {
style.readFromPrefs( *i );
@@ -120,7 +127,7 @@ void SPDashSelector::init_dashes() {
double *d = dashes[pos];
unsigned i = 0;
for (; i < style.stroke_dasharray.values.size(); i++) {
- d[i] = style.stroke_dasharray.values[i];
+ d[i] = Inkscape::Util::Quantity::convert(style.stroke_dasharray.values[i].computed, "px", display_unit.c_str());
}
d[i] = -1;
} else {
diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp
index 3a5abbca4..74c5e6efc 100644
--- a/src/widgets/stroke-style.cpp
+++ b/src/widgets/stroke-style.cpp
@@ -25,6 +25,8 @@
#include "object/sp-rect.h"
#include "object/sp-stop.h"
#include "object/sp-text.h"
+#include "util/units.h"
+#include "inkscape.h"
#include "svg/svg-color.h"
@@ -741,15 +743,38 @@ StrokeStyle::setDashSelectorFromStyle(SPDashSelector *dsel, SPStyle *style)
if (!style->stroke_dasharray.values.empty()) {
double d[64];
size_t len = MIN(style->stroke_dasharray.values.size(), 64);
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ SPNamedView *nv = sp_document_namedview(document, NULL);
+ Geom::Rect vbox = document->getViewBox();
+ Glib::ustring display_unit = "px";
+ if (nv) {
+ display_unit = nv->display_units->abbr;
+ }
for (unsigned i = 0; i < len; i++) {
+ double dash = 0;
+ if(style->stroke_dasharray.values[i].unit == SVGLength::NONE) {
+ dash = style->stroke_dasharray.values[i].value;
+ } else if (style->stroke_dasharray.values[i].unit == SVGLength::PERCENT) {
+ dash = vbox.width() * style->stroke_dasharray.values[i].value;
+ } else {
+ dash = Inkscape::Util::Quantity::convert(style->stroke_dasharray.values[i].computed, "px", display_unit.c_str());
+ }
if (style->stroke_width.computed != 0)
- d[i] = style->stroke_dasharray.values[i] / style->stroke_width.computed;
+ d[i] = dash / style->stroke_width.computed;
else
- d[i] = style->stroke_dasharray.values[i]; // is there a better thing to do for stroke_width==0?
+ d[i] = dash; // is there a better thing to do for stroke_width==0?
+ }
+ double dash_offset = 0;
+ if (style->stroke_dashoffset.unit == SVGLength::NONE) {
+ dash_offset = style->stroke_dashoffset.value;
+ } else if (style->stroke_dashoffset.unit == SVGLength::PERCENT) {
+ dash_offset = vbox.width() * style->stroke_dashoffset.value;
+ } else {
+ dash_offset = Inkscape::Util::Quantity::convert(style->stroke_dashoffset.computed, "px", display_unit.c_str());
}
dsel->set_dash(len, d, style->stroke_width.computed != 0 ?
- style->stroke_dashoffset.value / style->stroke_width.computed :
- style->stroke_dashoffset.value);
+ dash_offset / style->stroke_width.computed :
+ dash_offset);
} else {
dsel->set_dash(0, nullptr, 0.0);
}
@@ -1042,8 +1067,11 @@ StrokeStyle::scaleLine()
}
/* Set dash */
- setScaledDash(css, ndash, dash, offset, width);
-
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gboolean scale = prefs->getBool("/options/dash/scale", true);
+ if (scale) {
+ setScaledDash(css, ndash, dash, offset, width);
+ }
sp_desktop_apply_css_recursive ((*i), css, true);
}