summaryrefslogtreecommitdiffstats
path: root/src/helper
diff options
context:
space:
mode:
authorMichael Soegtrop <MSoegtrop@yahoo.de>2017-06-05 13:56:11 +0000
committerMichael Soegtrop <MSoegtrop@yahoo.de>2017-06-05 13:56:11 +0000
commit132e83fd6f6124731dc773ae2978d115ca492ef2 (patch)
treeb561a4dbbacd7eecbdbae3fa220a353375ccecf8 /src/helper
parentupdated to trunk (diff)
parent[Bug #1695016] Xaml export misses some radialGradients. (diff)
downloadinkscape-132e83fd6f6124731dc773ae2978d115ca492ef2.tar.gz
inkscape-132e83fd6f6124731dc773ae2978d115ca492ef2.zip
merged with latest version of lpe-bool and trunk
(bzr r14862.2.3)
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/CMakeLists.txt10
-rw-r--r--src/helper/Makefile_insert45
-rw-r--r--src/helper/action-context.cpp1
-rw-r--r--src/helper/action.cpp2
-rw-r--r--src/helper/geom-nodetype.cpp2
-rw-r--r--src/helper/geom-pathstroke.cpp230
-rw-r--r--src/helper/geom-pathstroke.h17
-rw-r--r--src/helper/geom-pathvectorsatellites.cpp244
-rw-r--r--src/helper/geom-pathvectorsatellites.h58
-rw-r--r--src/helper/geom-satellite.cpp245
-rw-r--r--src/helper/geom-satellite.h110
-rw-r--r--src/helper/geom.cpp14
-rw-r--r--src/helper/geom.h2
-rw-r--r--src/helper/gettext.cpp110
-rw-r--r--src/helper/gettext.h46
-rw-r--r--src/helper/pixbuf-ops.cpp10
-rw-r--r--src/helper/png-write.cpp87
-rw-r--r--src/helper/png-write.h6
-rw-r--r--src/helper/stock-items.cpp30
19 files changed, 1094 insertions, 175 deletions
diff --git a/src/helper/CMakeLists.txt b/src/helper/CMakeLists.txt
index ff4760c24..443648c5c 100644
--- a/src/helper/CMakeLists.txt
+++ b/src/helper/CMakeLists.txt
@@ -10,10 +10,13 @@ set(sp_marshal_SRC
set(helper_SRC
action.cpp
- action-context.cpp
+ action-context.cpp
geom.cpp
geom-nodetype.cpp
geom-pathstroke.cpp
+ geom-pathvectorsatellites.cpp
+ geom-satellite.cpp
+ gettext.cpp
gnome-utils.cpp
pixbuf-ops.cpp
png-write.cpp
@@ -28,11 +31,14 @@ set(helper_SRC
# -------
# Headers
action.h
- action-context.h
+ action-context.h
geom-curves.h
geom-nodetype.h
geom-pathstroke.h
+ geom-pathvectorsatellites.h
+ geom-satellite.h
geom.h
+ gettext.h
gnome-utils.h
mathfns.h
pixbuf-ops.h
diff --git a/src/helper/Makefile_insert b/src/helper/Makefile_insert
deleted file mode 100644
index e59fcfb70..000000000
--- a/src/helper/Makefile_insert
+++ /dev/null
@@ -1,45 +0,0 @@
-## Makefile.am fragment sourced by src/Makefile.am.
-
-helper/unit-menu.$(OBJEXT): helper/sp-marshal.h
-
-ink_common_sources += \
- helper/action.cpp \
- helper/action.h \
- helper/action-context.cpp \
- helper/action-context.h \
- helper/geom.cpp \
- helper/geom.h \
- helper/geom-curves.h \
- helper/geom-nodetype.cpp \
- helper/geom-nodetype.h \
- helper/geom-pathstroke.cpp \
- helper/geom-pathstroke.h \
- helper/gnome-utils.cpp \
- helper/gnome-utils.h \
- helper/mathfns.h \
- helper/png-write.cpp \
- helper/png-write.h \
- helper/sp-marshal.cpp \
- helper/sp-marshal.h \
- helper/window.cpp \
- helper/window.h \
- helper/stock-items.cpp \
- helper/stock-items.h
-
-# cmp exits with status 0 when there are no differences. "if" executes the commands
-# after "then" when the exit status of the if command is 0 (this is crazy).
-helper/sp-marshal.h: helper/sp-marshal.list
- glib-genmarshal --prefix=sp_marshal --header $(srcdir)/helper/sp-marshal.list > helper/tmp.sp-marshal.h
- if cmp -s helper/sp-marshal.h helper/tmp.sp-marshal.h; \
- then rm helper/tmp.sp-marshal.h; \
- else mv helper/tmp.sp-marshal.h helper/sp-marshal.h; fi
-
-helper/sp-marshal.cpp: helper/sp-marshal.list helper/sp-marshal.h
- ( echo '#include "helper/sp-marshal.h"' && \
- glib-genmarshal --prefix=sp_marshal --body $(srcdir)/helper/sp-marshal.list ) \
- > helper/tmp.sp-marshal.cpp; \
- if cmp -s helper/sp-marshal.cpp helper/tmp.sp-marshal.cpp; \
- then rm helper/tmp.sp-marshal.cpp; \
- else mv helper/tmp.sp-marshal.cpp helper/sp-marshal.cpp; fi
-
-helper/sp-marshal.cpp helper/sp-marshal.h: helper/sp-marshal.list
diff --git a/src/helper/action-context.cpp b/src/helper/action-context.cpp
index d52e43d96..1ea12776b 100644
--- a/src/helper/action-context.cpp
+++ b/src/helper/action-context.cpp
@@ -14,7 +14,6 @@
#include "layer-model.h"
#include "selection.h"
#include "helper/action-context.h"
-#include "ui/view/view.h"
namespace Inkscape {
diff --git a/src/helper/action.cpp b/src/helper/action.cpp
index 060bf317c..e37575a9c 100644
--- a/src/helper/action.cpp
+++ b/src/helper/action.cpp
@@ -9,8 +9,6 @@
* This code is in public domain
*/
-#include <string.h>
-
#include "debug/logger.h"
#include "debug/timestamp.h"
#include "debug/simple-event.h"
diff --git a/src/helper/geom-nodetype.cpp b/src/helper/geom-nodetype.cpp
index fe8e8af0e..da620b3fd 100644
--- a/src/helper/geom-nodetype.cpp
+++ b/src/helper/geom-nodetype.cpp
@@ -12,8 +12,6 @@
#include "helper/geom-nodetype.h"
#include <2geom/curve.h>
-#include <2geom/point.h>
-#include <vector>
namespace Geom {
diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp
index d2e9f9a1b..50627fd0b 100644
--- a/src/helper/geom-pathstroke.cpp
+++ b/src/helper/geom-pathstroke.cpp
@@ -1,6 +1,7 @@
/* Authors:
* Liam P. White
* Tavmjong Bah
+ * Alexander Brock
*
* Copyright (C) 2014-2015 Authors
*
@@ -9,13 +10,9 @@
#include <iomanip>
#include <2geom/path-sink.h>
-#include <2geom/point.h>
-#include <2geom/bezier-curve.h>
-#include <2geom/elliptical-arc.h>
#include <2geom/sbasis-to-bezier.h> // cubicbezierpath_from_sbasis
#include <2geom/path-intersection.h>
#include <2geom/circle.h>
-#include <math.h>
#include "helper/geom-pathstroke.h"
@@ -750,33 +747,36 @@ void get_cubic_data(Geom::CubicBezier const& bez, double time, double& len, doub
len = l;
}
-void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, double tol, size_t levels)
-{
+double _offset_cubic_stable_sub(
+ Geom::CubicBezier const& bez,
+ Geom::CubicBezier& c,
+ const Geom::Point& start_normal,
+ const Geom::Point& end_normal,
+ const Geom::Point& start_new,
+ const Geom::Point& end_new,
+ const double start_rad,
+ const double end_rad,
+ const double start_len,
+ const double end_len,
+ const double width,
+ const double width_correction) {
using Geom::X;
using Geom::Y;
- Geom::Point start_pos = bez.initialPoint();
- Geom::Point end_pos = bez.finalPoint();
-
- Geom::Point start_normal = Geom::rot90(bez.unitTangentAt(0));
- Geom::Point end_normal = -Geom::rot90(Geom::unitTangentAt(Geom::reverse(bez.toSBasis()), 0.));
-
- // offset the start and end control points out by the width
- Geom::Point start_new = start_pos + start_normal*width;
- Geom::Point end_new = end_pos + end_normal*width;
-
- // --------
- double start_rad, end_rad;
- double start_len, end_len; // tangent lengths
- get_cubic_data(bez, 0, start_len, start_rad);
- get_cubic_data(bez, 1, end_len, end_rad);
-
double start_off = 1, end_off = 1;
// correction of the lengths of the tangent to the offset
if (!Geom::are_near(start_rad, 0))
- start_off += width / start_rad;
+ start_off += (width + width_correction) / start_rad;
if (!Geom::are_near(end_rad, 0))
- end_off += width / end_rad;
+ end_off += (width + width_correction) / end_rad;
+
+ // We don't change the direction of the control points
+ if (start_off < 0) {
+ start_off = 0;
+ }
+ if (end_off < 0) {
+ end_off = 0;
+ }
start_off *= start_len;
end_off *= end_len;
// --------
@@ -787,23 +787,137 @@ void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, dou
mid2_new = Geom::Point(end_new[X] - mid2_new[X]/3., end_new[Y] - mid2_new[Y]/3.);
// create the estimate curve
- Geom::CubicBezier c = Geom::CubicBezier(start_new, mid1_new, mid2_new, end_new);
+ c = Geom::CubicBezier(start_new, mid1_new, mid2_new, end_new);
+
+ // check the tolerance for our estimate to be a parallel curve
+
+ double worst_residual = 0;
+ for (size_t ii = 3; ii <= 7; ii+=2) {
+ const double t = static_cast<double>(ii) / 10;
+ const Geom::Point req = bez.pointAt(t);
+ const Geom::Point chk = c.pointAt(c.nearestTime(req));
+ const double current_residual = (chk-req).length() - std::abs(width);
+ if (std::abs(current_residual) > std::abs(worst_residual)) {
+ worst_residual = current_residual;
+ }
+ }
+ return worst_residual;
+}
+
+void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, double tol, size_t levels)
+{
+ using Geom::X;
+ using Geom::Y;
+
+ const Geom::Point start_pos = bez.initialPoint();
+ const Geom::Point end_pos = bez.finalPoint();
+
+ const Geom::Point start_normal = Geom::rot90(bez.unitTangentAt(0));
+ const Geom::Point end_normal = -Geom::rot90(Geom::unitTangentAt(Geom::reverse(bez.toSBasis()), 0.));
+
+ // offset the start and end control points out by the width
+ const Geom::Point start_new = start_pos + start_normal*width;
+ const Geom::Point end_new = end_pos + end_normal*width;
+
+ // --------
+ double start_rad, end_rad;
+ double start_len, end_len; // tangent lengths
+ get_cubic_data(bez, 0, start_len, start_rad);
+ get_cubic_data(bez, 1, end_len, end_rad);
+
+
+ Geom::CubicBezier c;
+
+ double best_width_correction = 0;
+ double best_residual = _offset_cubic_stable_sub(
+ bez, c,
+ start_normal, end_normal,
+ start_new, end_new,
+ start_rad, end_rad,
+ start_len, end_len,
+ width, best_width_correction);
+ double stepsize = std::abs(width)/2;
+ bool seen_success = false;
+ double stepsize_threshold = 0;
+ // std::cout << "Residual from " << best_residual << " ";
+ size_t ii = 0;
+ for (; ii < 100 && stepsize > stepsize_threshold; ++ii) {
+ bool success = false;
+ const double width_correction = best_width_correction - (best_residual > 0 ? 1 : -1) * stepsize;
+ Geom::CubicBezier current_curve;
+ const double residual = _offset_cubic_stable_sub(
+ bez, current_curve,
+ start_normal, end_normal,
+ start_new, end_new,
+ start_rad, end_rad,
+ start_len, end_len,
+ width, width_correction);
+ if (std::abs(residual) < std::abs(best_residual)) {
+ best_residual = residual;
+ best_width_correction = width_correction;
+ c = current_curve;
+ success = true;
+ if (std::abs(best_residual) < tol/4) {
+ break;
+ }
+ }
+
+ if (success) {
+ if (!seen_success) {
+ seen_success = true;
+ //std::cout << "Stepsize factor: " << std::abs(width) / stepsize << std::endl;
+ stepsize_threshold = stepsize / 1000;
+ }
+ }
+ else {
+ stepsize /= 2;
+ }
+ if (std::abs(best_width_correction) >= std::abs(width)/2) {
+ //break; // Seems to prevent some numerical instabilities, not clear if useful
+ }
+ }
// reached maximum recursive depth
// don't bother with any more correction
if (levels == 0) {
- p.append(c);
+ try {
+ p.append(c);
+ }
+ catch (...) {
+ if ((p.finalPoint() - c.initialPoint()).length() < 1e-6) {
+ c.setInitial(p.finalPoint());
+ }
+ else {
+ auto line = Geom::LineSegment(p.finalPoint(), c.initialPoint());
+ p.append(line);
+ }
+ p.append(c);
+ }
+
return;
}
- // check the tolerance for our estimate to be a parallel curve
- Geom::Point chk = c.pointAt(.5);
- Geom::Point req = bez.pointAt(.5) + Geom::rot90(bez.unitTangentAt(.5))*width; // required accuracy
-
- Geom::Point const diff = req - chk;
- double const err = Geom::dot(diff, diff);
+ // We find the point on our new curve (c) for which the distance between
+ // (c) and (bez) differs the most from the desired distance (width).
+ double worst_err = std::abs(best_residual);
+ double worst_time = .5;
+ for (size_t ii = 1; ii <= 9; ++ii) {
+ const double t = static_cast<double>(ii) / 10;
+ const Geom::Point req = bez.pointAt(t);
+ // We use the exact solution with nearestTime because it is numerically
+ // much more stable than simply assuming that the point on (c) closest
+ // to bez.pointAt(t) is given by c.pointAt(t)
+ const Geom::Point chk = c.pointAt(c.nearestTime(req));
+
+ Geom::Point const diff = req - chk;
+ const double err = std::abs(diff.length() - std::abs(width));
+ if (err > worst_err) {
+ worst_err = err;
+ worst_time = t;
+ }
+ }
- if (err < tol) {
+ if (worst_err < tol) {
if (Geom::are_near(start_new, p.finalPoint())) {
p.setFinal(start_new); // if it isn't near, we throw
}
@@ -813,7 +927,7 @@ void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, dou
return;
} else {
// split the curve in two
- std::pair<Geom::CubicBezier, Geom::CubicBezier> s = bez.subdivide(.5);
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> s = bez.subdivide(worst_time);
offset_cubic(p, s.first, width, tol, levels - 1);
offset_cubic(p, s.second, width, tol, levels - 1);
}
@@ -831,9 +945,8 @@ void offset_quadratic(Geom::Path& p, Geom::QuadraticBezier const& bez, double wi
offset_cubic(p, cub, width, tol, levels);
}
-void offset_curve(Geom::Path& res, Geom::Curve const* current, double width)
+void offset_curve(Geom::Path& res, Geom::Curve const* current, double width, double tolerance)
{
- double const tolerance = 0.0025;
size_t levels = 8;
if (current->isDegenerate()) return; // don't do anything
@@ -859,14 +972,14 @@ void offset_curve(Geom::Path& res, Geom::Curve const* current, double width)
default: {
Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(current->toSBasis(), tolerance);
for (size_t i = 0; i < sbasis_path.size(); ++i)
- offset_curve(res, &sbasis_path[i], width);
+ offset_curve(res, &sbasis_path[i], width, tolerance);
break;
}
}
} else {
Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(current->toSBasis(), 0.1);
for (size_t i = 0; i < sbasis_path.size(); ++i)
- offset_curve(res, &sbasis_path[i], width);
+ offset_curve(res, &sbasis_path[i], width, tolerance);
}
}
@@ -906,13 +1019,19 @@ void peak_cap(Geom::PathBuilder& res, Geom::Path const& with_dir, Geom::Path con
namespace Inkscape {
-Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join, LineCapType butt)
+Geom::PathVector outline(
+ Geom::Path const& input,
+ double width,
+ double miter,
+ LineJoinType join,
+ LineCapType butt,
+ double tolerance)
{
if (input.size() == 0) return Geom::PathVector(); // nope, don't even try
Geom::PathBuilder res;
- Geom::Path with_dir = half_outline(input, width/2., miter, join);
- Geom::Path against_dir = half_outline(input.reversed(), width/2., miter, join);
+ Geom::Path with_dir = half_outline(input, width/2., miter, join, tolerance);
+ Geom::Path against_dir = half_outline(input.reversed(), width/2., miter, join, tolerance);
res.moveTo(with_dir[0].initialPoint());
res.append(with_dir);
@@ -951,8 +1070,21 @@ Geom::PathVector outline(Geom::Path const& input, double width, double miter, Li
return res.peek();
}
-Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join)
+Geom::Path half_outline(
+ Geom::Path const& input,
+ double width,
+ double miter,
+ LineJoinType join,
+ double tolerance)
{
+ if (tolerance <= 0) {
+ if (std::abs(width) > 0) {
+ tolerance = 5.0 * (std::abs(width)/100);
+ }
+ else {
+ tolerance = 1e-4;
+ }
+ }
Geom::Path res;
if (input.size() == 0) return res;
@@ -967,12 +1099,13 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
res.start(start);
// Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well
- const size_t k = (input.back_closed().isDegenerate() && input.closed())
- ?input.size_default()-1:input.size_default();
+ const Geom::Curve &closingline = input.back_closed();
+ const size_t k = (are_near(closingline.initialPoint(), closingline.finalPoint()) && input.closed() )
+ ?input.size_open():input.size_default();
for (size_t u = 0; u < k; u += 2) {
temp.clear();
- offset_curve(temp, &input[u], width);
+ offset_curve(temp, &input[u], width, tolerance);
// on the first run through, there isn't a join
if (u == 0) {
@@ -985,12 +1118,11 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
// odd number of paths
if (u < k - 1) {
temp.clear();
- offset_curve(temp, &input[u+1], width);
+ offset_curve(temp, &input[u+1], width, tolerance);
tangents(tang, input[u], input[u+1]);
outline_join(res, temp, tang[0], tang[1], width, miter, join);
}
}
-
if (input.closed()) {
Geom::Curve const &c1 = res.back();
Geom::Curve const &c2 = res.front();
@@ -1002,7 +1134,6 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
outline_join(temp, temp2, tang[0], tang[1], width, miter, join);
res.erase(res.begin());
res.erase_last();
- //
res.append(temp);
res.close();
}
@@ -1014,9 +1145,8 @@ void outline_join(Geom::Path &res, Geom::Path const& temp, Geom::Point in_tang,
{
if (res.size() == 0 || temp.size() == 0)
return;
-
Geom::Curve const& outgoing = temp.front();
- if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) {
+ if (Geom::are_near(res.finalPoint(), outgoing.initialPoint(), 0.01)) {
// if the points are /that/ close, just ignore this one
res.setFinal(temp.initialPoint());
res.append(temp);
diff --git a/src/helper/geom-pathstroke.h b/src/helper/geom-pathstroke.h
index 6a753a6fd..4e4b8b91e 100644
--- a/src/helper/geom-pathstroke.h
+++ b/src/helper/geom-pathstroke.h
@@ -42,12 +42,19 @@ enum LineCapType {
* @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
* @param[in] join Line join type used during offset. Member of LineJoinType enum.
* @param[in] cap Line cap type used during stroking. Member of LineCapType enum.
+ * @param[in] tolerance Tolerance, values smaller than 0 lead to automatic tolerance depending on width.
*
* @return Stroked path.
* If the input path is closed, the resultant vector will contain two paths.
* Otherwise, there should be only one in the output.
*/
-Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT);
+Geom::PathVector outline(
+ Geom::Path const& input,
+ double width,
+ double miter,
+ LineJoinType join = JOIN_BEVEL,
+ LineCapType cap = BUTT_FLAT,
+ double tolerance = -1);
/**
* Offset the input path by @a width.
@@ -57,10 +64,16 @@ Geom::PathVector outline(Geom::Path const& input, double width, double miter, Li
* @param[in] width Amount to offset.
* @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
* @param[in] join Line join type used during offset. Member of LineJoinType enum.
+ * @param[in] tolerance Tolerance, values smaller than 0 lead to automatic tolerance depending on width.
*
* @return Offsetted output.
*/
-Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL);
+Geom::Path half_outline(
+ Geom::Path const& input,
+ double width,
+ double miter,
+ LineJoinType join = JOIN_BEVEL,
+ double tolerance = -1);
/**
* Builds a join on the provided path.
diff --git a/src/helper/geom-pathvectorsatellites.cpp b/src/helper/geom-pathvectorsatellites.cpp
new file mode 100644
index 000000000..e995c0a9b
--- /dev/null
+++ b/src/helper/geom-pathvectorsatellites.cpp
@@ -0,0 +1,244 @@
+/**
+ * \file
+ * \brief PathVectorSatellites a class to manage satellites -per node extra data- in a pathvector
+ */ /*
+ * Authors:
+ * Jabiertxof
+ * Nathan Hurst
+ * Johan Engelen
+ * Josh Andler
+ * suv
+ * Mc-
+ * Liam P. White
+ * Krzysztof Kosiński
+ * This code is in public domain
+ */
+
+#include <helper/geom-pathvectorsatellites.h>
+#include "util/units.h"
+
+Geom::PathVector PathVectorSatellites::getPathVector() const
+{
+ return _pathvector;
+}
+
+void PathVectorSatellites::setPathVector(Geom::PathVector pathv)
+{
+ _pathvector = pathv;
+}
+
+Satellites PathVectorSatellites::getSatellites()
+{
+ return _satellites;
+}
+
+void PathVectorSatellites::setSatellites(Satellites satellites)
+{
+ _satellites = satellites;
+}
+
+size_t PathVectorSatellites::getTotalSatellites()
+{
+ size_t counter = 0;
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ counter++;
+ }
+ }
+ return counter;
+}
+
+std::pair<size_t, size_t> PathVectorSatellites::getIndexData(size_t index)
+{
+ size_t counter = 0;
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ if (index == counter) {
+ return std::make_pair(i,j);
+ }
+ counter++;
+ }
+ }
+ return std::make_pair(0,0);
+}
+
+void PathVectorSatellites::setSelected(std::vector<size_t> selected)
+{
+ size_t counter = 0;
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ if (find (selected.begin(), selected.end(), counter) != selected.end()) {
+ _satellites[i][j].setSelected(true);
+ } else {
+ _satellites[i][j].setSelected(false);
+ }
+ counter++;
+ }
+ }
+}
+
+void PathVectorSatellites::updateSteps(size_t steps, bool apply_no_radius, bool apply_with_radius, bool only_selected)
+{
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ if ((!apply_no_radius && _satellites[i][j].amount == 0) ||
+ (!apply_with_radius && _satellites[i][j].amount != 0))
+ {
+ continue;
+ }
+ if (only_selected) {
+ if (_satellites[i][j].selected) {
+ _satellites[i][j].steps = steps;
+ }
+ } else {
+ _satellites[i][j].steps = steps;
+ }
+ }
+ }
+}
+
+void PathVectorSatellites::updateAmount(double radius, bool apply_no_radius, bool apply_with_radius, bool only_selected,
+ bool use_knot_distance, bool flexible)
+{
+ double power = 0;
+ if (!flexible) {
+ power = radius;
+ } else {
+ power = radius / 100;
+ }
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ boost::optional<size_t> previous_index = boost::none;
+ if (j == 0 && _pathvector[i].closed()) {
+ previous_index = _pathvector[i].size() - 1;
+ } else if (!_pathvector[i].closed() || j != 0) {
+ previous_index = j - 1;
+ }
+ if (!_pathvector[i].closed() && j == 0) {
+ _satellites[i][j].amount = 0;
+ continue;
+ }
+ if (_pathvector[i].size() == j) {
+ continue;
+ }
+ if ((!apply_no_radius && _satellites[i][j].amount == 0) ||
+ (!apply_with_radius && _satellites[i][j].amount != 0))
+ {
+ continue;
+ }
+
+ Geom::Point satellite_point = _pathvector[i].pointAt(j);
+ if (_satellites[i][j].selected || !only_selected) {
+ if (!use_knot_distance && !flexible) {
+ if (previous_index) {
+ _satellites[i][j].amount = _satellites[i][j].radToLen(power, _pathvector[i][*previous_index], _pathvector[i][j]);
+ if (power && !_satellites[i][j].amount) {
+ g_warning("Seems a too high radius value");
+ }
+ } else {
+ _satellites[i][j].amount = 0.0;
+ }
+ } else {
+ _satellites[i][j].amount = power;
+ }
+ }
+ }
+ }
+}
+
+void PathVectorSatellites::convertUnit(Glib::ustring in, Glib::ustring to, bool apply_no_radius, bool apply_with_radius)
+{
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ if (!_pathvector[i].closed() && j == 0) {
+ _satellites[i][j].amount = 0;
+ continue;
+ }
+ if (_pathvector[i].size() == j) {
+ continue;
+ }
+ if ((!apply_no_radius && _satellites[i][j].amount == 0) ||
+ (!apply_with_radius && _satellites[i][j].amount != 0))
+ {
+ continue;
+ }
+ _satellites[i][j].amount = Inkscape::Util::Quantity::convert(_satellites[i][j].amount, in.c_str(), to.c_str());
+ }
+ }
+}
+
+void PathVectorSatellites::updateSatelliteType(SatelliteType satellitetype, bool apply_no_radius, bool apply_with_radius,
+ bool only_selected)
+{
+ for (size_t i = 0; i < _satellites.size(); ++i) {
+ for (size_t j = 0; j < _satellites[i].size(); ++j) {
+ if ((!apply_no_radius && _satellites[i][j].amount == 0) ||
+ (!apply_with_radius && _satellites[i][j].amount != 0))
+ {
+ continue;
+ }
+ if (_pathvector[i].size() == j) {
+ if (!only_selected) {
+ _satellites[i][j].satellite_type = satellitetype;
+ }
+ continue;
+ }
+ if (only_selected) {
+ Geom::Point satellite_point = _pathvector[i].pointAt(j);
+ if (_satellites[i][j].selected) {
+ _satellites[i][j].satellite_type = satellitetype;
+ }
+ } else {
+ _satellites[i][j].satellite_type = satellitetype;
+ }
+ }
+ }
+}
+
+void PathVectorSatellites::recalculateForNewPathVector(Geom::PathVector const pathv, Satellite const S)
+{
+ Satellites satellites;
+ bool found = false;
+ //TODO evaluate fix on nodes at same position
+ size_t number_nodes = pathv.nodes().size();
+ size_t previous_number_nodes = _pathvector.nodes().size();
+ for (size_t i = 0; i < pathv.size(); i++) {
+ std::vector<Satellite> path_satellites;
+ for (size_t j = 0; j < pathv[i].size_closed(); j++) {
+ found = false;
+ for (size_t k = 0; k < _pathvector.size(); k++) {
+ for (size_t l = 0; l < _pathvector[k].size_closed(); l++) {
+ if (Geom::are_near(_pathvector[k][l].initialPoint(), pathv[i][j].initialPoint()))
+ {
+ path_satellites.push_back(_satellites[k][l]);
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+
+ if (!found && previous_number_nodes < number_nodes) {
+ path_satellites.push_back(S);
+ }
+ }
+ satellites.push_back(path_satellites);
+ }
+ setPathVector(pathv);
+ setSatellites(satellites);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/helper/geom-pathvectorsatellites.h b/src/helper/geom-pathvectorsatellites.h
new file mode 100644
index 000000000..d86e6cb25
--- /dev/null
+++ b/src/helper/geom-pathvectorsatellites.h
@@ -0,0 +1,58 @@
+/**
+ * \file
+ * \brief PathVectorSatellites a class to manage satellites -per node extra data- in a pathvector
+ */ /*
+ * Authors:
+ * Jabiertxof
+ * Nathan Hurst
+ * Johan Engelen
+ * Josh Andler
+ * suv
+ * Mc-
+ * Liam P. White
+ * Krzysztof Kosiński
+ * This code is in public domain
+ */
+
+#ifndef SEEN_PATHVECTORSATELLITES_H
+#define SEEN_PATHVECTORSATELLITES_H
+
+#include <helper/geom-satellite.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+typedef std::vector<std::vector<Satellite> > Satellites;
+///@brief PathVectorSatellites a class to manage satellites in a pathvector
+class PathVectorSatellites {
+public:
+ Geom::PathVector getPathVector() const;
+ void setPathVector(Geom::PathVector pathv);
+ Satellites getSatellites();
+ void setSatellites(Satellites satellites);
+ size_t getTotalSatellites();
+ void setSelected(std::vector<size_t> selected);
+ void updateSteps(size_t steps, bool apply_no_radius, bool apply_with_radius, bool only_selected);
+ void updateAmount(double radius, bool apply_no_radius, bool apply_with_radius, bool only_selected,
+ bool use_knot_distance, bool flexible);
+ void convertUnit(Glib::ustring in, Glib::ustring to, bool apply_no_radius, bool apply_with_radius);
+ void updateSatelliteType(SatelliteType satellitetype, bool apply_no_radius, bool apply_with_radius, bool only_selected);
+ std::pair<size_t, size_t> getIndexData(size_t index);
+ void recalculateForNewPathVector(Geom::PathVector const pathv, Satellite const S);
+private:
+ Geom::PathVector _pathvector;
+ Satellites _satellites;
+};
+
+#endif //SEEN_PATHVECTORSATELLITES_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/helper/geom-satellite.cpp b/src/helper/geom-satellite.cpp
new file mode 100644
index 000000000..8a92273d0
--- /dev/null
+++ b/src/helper/geom-satellite.cpp
@@ -0,0 +1,245 @@
+/**
+ * \file
+ * \brief Satellite a per node holder of data.
+ */ /*
+ * Authors:
+ * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
+ *
+ * This code is in public domain
+ */
+
+#include <helper/geom-satellite.h>
+#include <2geom/curve.h>
+#include <2geom/nearest-time.h>
+#include <2geom/path-intersection.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/ray.h>
+#include <boost/optional.hpp>
+//log cache
+#ifdef _WIN32
+#include <Windows.h>
+#else
+#include <sys/time.h>
+#include <ctime>
+#endif
+
+///@brief Satellite a per node holder of data.
+Satellite::Satellite() {}
+
+
+Satellite::Satellite(SatelliteType satellite_type)
+ : satellite_type(satellite_type),
+ is_time(false),
+ selected(false),
+ has_mirror(false),
+ hidden(true),
+ amount(0.0),
+ angle(0.0),
+ steps(0)
+{}
+
+Satellite::~Satellite() {}
+
+///Calculate the time in curve_in with a size of A
+//TODO: find a better place to it
+double timeAtArcLength(double const A, Geom::Curve const &curve_in)
+{
+ if ( A == 0 || curve_in.isDegenerate()) {
+ return 0;
+ }
+
+ Geom::D2<Geom::SBasis> d2_in = curve_in.toSBasis();
+ double t = 0;
+ double length_part = curve_in.length();
+ if (A >= length_part || curve_in.isLineSegment()) {
+ if (length_part != 0) {
+ t = A / length_part;
+ }
+ } else if (!curve_in.isLineSegment()) {
+ std::vector<double> t_roots = roots(Geom::arcLengthSb(d2_in) - A);
+ if (!t_roots.empty()) {
+ t = t_roots[0];
+ }
+ }
+ return t;
+}
+
+///Calculate the size in curve_in with a point at A
+//TODO: find a better place to it
+double arcLengthAt(double const A, Geom::Curve const &curve_in)
+{
+ if ( A == 0 || curve_in.isDegenerate()) {
+ return 0;
+ }
+
+ double s = 0;
+ double length_part = curve_in.length();
+ if (A > length_part || curve_in.isLineSegment()) {
+ s = (A * length_part);
+ } else if (!curve_in.isLineSegment()) {
+ Geom::Curve *curve = curve_in.portion(0.0, A);
+ s = curve->length();
+ delete curve;
+ }
+ return s;
+}
+
+///Convert a arc radius of a fillet/chamfer to his satellite length -point position where fillet/chamfer knot be on original curve
+double Satellite::radToLen(
+ double const A, Geom::Curve const &curve_in,
+ Geom::Curve const &curve_out) const
+{
+ double len = 0;
+ Geom::D2<Geom::SBasis> d2_in = curve_in.toSBasis();
+ Geom::D2<Geom::SBasis> d2_out = curve_out.toSBasis();
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > offset_curve0 =
+ Geom::Piecewise<Geom::D2<Geom::SBasis> >(d2_in) +
+ rot90(unitVector(derivative(d2_in))) * (A);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > offset_curve1 =
+ Geom::Piecewise<Geom::D2<Geom::SBasis> >(d2_out) +
+ rot90(unitVector(derivative(d2_out))) * (A);
+ Geom::Path p0 = path_from_piecewise(offset_curve0, 0.1)[0];
+ Geom::Path p1 = path_from_piecewise(offset_curve1, 0.1)[0];
+ Geom::Crossings cs = Geom::crossings(p0, p1);
+ if (cs.size() > 0) {
+ Geom::Point cp = p0(cs[0].ta);
+ double p0pt = nearest_time(cp, curve_out);
+ len = arcLengthAt(p0pt, curve_out);
+ } else {
+ if (A > 0) {
+ len = radToLen(A * -1, curve_in, curve_out);
+ }
+ }
+ return len;
+}
+
+///Convert a satelite length -point position where fillet/chamfer knot be on original curve- to a arc radius of fillet/chamfer
+double Satellite::lenToRad(
+ double const A, Geom::Curve const &curve_in,
+ Geom::Curve const &curve_out,
+ Satellite const previousSatellite) const
+{
+ double time_in = (previousSatellite).time(A, true, curve_in);
+ double time_out = timeAtArcLength(A, curve_out);
+ Geom::Point start_arc_point = curve_in.pointAt(time_in);
+ Geom::Point end_arc_point = curve_out.pointAt(time_out);
+ Geom::Curve *knot_curve1 = curve_in.portion(0, time_in);
+ Geom::Curve *knot_curve2 = curve_out.portion(time_out, 1);
+ Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve1);
+ Geom::Ray ray1(start_arc_point, curve_in.pointAt(1));
+ if (cubic1) {
+ ray1.setPoints((*cubic1)[2], start_arc_point);
+ }
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve2);
+ Geom::Ray ray2(curve_out.pointAt(0), end_arc_point);
+ if (cubic2) {
+ ray2.setPoints(end_arc_point, (*cubic2)[1]);
+ }
+ bool ccw_toggle = cross(curve_in.pointAt(1) - start_arc_point,
+ end_arc_point - start_arc_point) < 0;
+ double distance_arc =
+ Geom::distance(start_arc_point, middle_point(start_arc_point, end_arc_point));
+ double angle = angle_between(ray1, ray2, ccw_toggle);
+ double divisor = std::sin(angle / 2.0);
+ if (divisor > 0) {
+ return distance_arc / divisor;
+ }
+ return 0;
+}
+
+///Get the time position of the satellite in curve_in
+double Satellite::time(Geom::Curve const &curve_in, bool inverse) const
+{
+ double t = amount;
+ if (!is_time) {
+ t = time(t, inverse, curve_in);
+ } else if (inverse) {
+ t = 1-t;
+ }
+ if (t > 1) {
+ t = 1;
+ }
+ return t;
+}
+
+///Get the time from a length A in other curve, a bolean inverse gived to reverse time
+double Satellite::time(double A, bool inverse,
+ Geom::Curve const &curve_in) const
+{
+ if (A == 0 && inverse) {
+ return 1;
+ }
+ if (A == 0 && !inverse) {
+ return 0;
+ }
+ if (!inverse) {
+ return timeAtArcLength(A, curve_in);
+ }
+ double length_part = curve_in.length();
+ A = length_part - A;
+ return timeAtArcLength(A, curve_in);
+}
+
+///Get the length of the satellite in curve_in
+double Satellite::arcDistance(Geom::Curve const &curve_in) const
+{
+ double s = amount;
+ if (is_time) {
+ s = arcLengthAt(s, curve_in);
+ }
+ return s;
+}
+
+///Get the point position of the satellite
+Geom::Point Satellite::getPosition(Geom::Curve const &curve_in, bool inverse) const
+{
+ double t = time(curve_in, inverse);
+ return curve_in.pointAt(t);
+}
+
+///Set the position of the satellite from a gived point P
+void Satellite::setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse)
+{
+ Geom::Curve * curve = const_cast<Geom::Curve *>(&curve_in);
+ if (inverse) {
+ curve = curve->reverse();
+ }
+ double A = Geom::nearest_time(p, *curve);
+ if (!is_time) {
+ A = arcLengthAt(A, *curve);
+ }
+ amount = A;
+}
+
+
+///Map a satellite type with gchar
+void Satellite::setSatelliteType(gchar const *A)
+{
+ std::map<std::string, SatelliteType> gchar_map_to_satellite_type =
+ boost::assign::map_list_of("F", FILLET)("IF", INVERSE_FILLET)("C", CHAMFER)("IC", INVERSE_CHAMFER)("KO", INVALID_SATELLITE);
+ std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(A));
+ if (it != gchar_map_to_satellite_type.end()) {
+ satellite_type = it->second;
+ }
+}
+
+///Map a gchar with satelliteType
+gchar const *Satellite::getSatelliteTypeGchar() const
+{
+ std::map<SatelliteType, gchar const *> satellite_type_to_gchar_map =
+ boost::assign::map_list_of(FILLET, "F")(INVERSE_FILLET, "IF")(CHAMFER, "C")(INVERSE_CHAMFER, "IC")(INVALID_SATELLITE, "KO");
+ return satellite_type_to_gchar_map.at(satellite_type);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/helper/geom-satellite.h b/src/helper/geom-satellite.h
new file mode 100644
index 000000000..b8ca2a490
--- /dev/null
+++ b/src/helper/geom-satellite.h
@@ -0,0 +1,110 @@
+/**
+ * \file
+ * \brief Satellite a per node holder of data.
+ */ /*
+ * Authors:
+ * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
+ *
+ * This code is in public domain
+ */
+
+#ifndef SEEN_SATELLITE_H
+#define SEEN_SATELLITE_H
+
+#include <map>
+#include <boost/assign.hpp>
+#include <2geom/sbasis-geometric.h>
+#include "util/enums.h"
+
+
+enum SatelliteType {
+ FILLET = 0, //Fillet
+ INVERSE_FILLET, //Inverse Fillet
+ CHAMFER, //Chamfer
+ INVERSE_CHAMFER, //Inverse Chamfer
+ INVALID_SATELLITE // Invalid Satellite
+};
+/**
+ * @brief Satellite a per node holder of data.
+ */
+
+class Satellite {
+public:
+
+ Satellite();
+ Satellite(SatelliteType satellite_type);
+
+ virtual ~Satellite();
+ void setIsTime(bool set_is_time)
+ {
+ is_time = set_is_time;
+ }
+ void setSelected(bool set_selected)
+ {
+ selected = set_selected;
+ }
+ void setHasMirror(bool set_has_mirror)
+ {
+ has_mirror = set_has_mirror;
+ }
+ void setHidden(bool set_hidden)
+ {
+ hidden = set_hidden;
+ }
+ void setAmount(double set_amount)
+ {
+ amount = set_amount;
+ }
+ void setAngle(double set_angle)
+ {
+ angle = set_angle;
+ }
+ void setSteps(size_t set_steps)
+ {
+ steps = set_steps;
+ }
+ double lenToRad(double const A, Geom::Curve const &curve_in,
+ Geom::Curve const &curve_out,
+ Satellite const previousSatellite) const;
+ double radToLen(double const A, Geom::Curve const &curve_in,
+ Geom::Curve const &curve_out) const;
+
+ double time(Geom::Curve const &curve_in, bool inverse = false) const;
+ double time(double A, bool inverse, Geom::Curve const &curve_in) const;
+ double arcDistance(Geom::Curve const &curve_in) const;
+
+ void setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse = false);
+ Geom::Point getPosition(Geom::Curve const &curve_in, bool inverse = false) const;
+
+ void setSatelliteType(gchar const *A);
+ gchar const *getSatelliteTypeGchar() const;
+ SatelliteType satellite_type;
+ //The value stored could be a time value of the satellite in the curve or a lenght of distance to the node from the satellite
+ //"is_time" tell is if is a time or lenght value
+ bool is_time;
+ bool selected;
+ bool has_mirror;
+ bool hidden;
+ //in "amount" we store the time or distance used in the satellite
+ double amount;
+ double angle;
+ size_t steps;
+};
+
+double timeAtArcLength(double const A, Geom::Curve const &curve_in);
+double arcLengthAt(double const A, Geom::Curve const &curve_in);
+
+#endif // SEEN_SATELLITE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:
+// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99
+// :
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index ecb330b01..e1f05c3ce 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -12,15 +12,8 @@
#include <algorithm>
#include "helper/geom.h"
#include "helper/geom-curves.h"
-#include <typeinfo>
-#include <2geom/pathvector.h>
-#include <2geom/path.h>
#include <2geom/curves.h>
-#include <2geom/transforms.h>
-#include <2geom/rect.h>
-#include <2geom/coord.h>
#include <2geom/sbasis-to-bezier.h>
-#include <math.h> // for M_PI
using Geom::X;
using Geom::Y;
@@ -850,6 +843,13 @@ recursive_bezier4(const double x1, const double y1,
recursive_bezier4(x1234, y1234, x234, y234, x34, y34, x4, y4, m_points, level + 1);
}
+void
+swap(Geom::Point &A, Geom::Point &B){
+ Geom::Point tmp = A;
+ A = B;
+ B = tmp;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/helper/geom.h b/src/helper/geom.h
index d49e2070c..b3d907e51 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -32,7 +32,7 @@ void recursive_bezier4(const double x1, const double y1, const double x2, const
const double x3, const double y3, const double x4, const double y4,
std::vector<Geom::Point> &pointlist,
int level);
-
+void swap(Geom::Point &A, Geom::Point &B);
#endif // INKSCAPE_HELPER_GEOM_H
/*
diff --git a/src/helper/gettext.cpp b/src/helper/gettext.cpp
new file mode 100644
index 000000000..91dfdbcb8
--- /dev/null
+++ b/src/helper/gettext.cpp
@@ -0,0 +1,110 @@
+/**
+ * \file
+ * \brief helper functions for gettext
+ *//*
+ * Authors:
+ * Eduard Braun <eduard.braun2@gmx.de>
+ *
+ * Copyright 2017 Authors
+ *
+ * This file is part of Inkscape.
+ *
+ * Inkscape is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Inkscape is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Inkscape. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <string>
+#include <glibmm.h>
+#include <glibmm/i18n.h>
+
+namespace Inkscape {
+
+/** does all required gettext initialization and takes care of the respective locale directory paths */
+void initialize_gettext() {
+#ifdef WIN32
+ gchar *datadir = g_win32_get_package_installation_directory_of_module(NULL);
+
+ // obtain short path to executable dir and pass it
+ // to bindtextdomain (it doesn't understand UTF-8)
+ gchar *shortdatadir = g_win32_locale_filename_from_utf8(datadir);
+ gchar *localepath = g_build_filename(shortdatadir, PACKAGE_LOCALE_DIR, NULL);
+ bindtextdomain(GETTEXT_PACKAGE, localepath);
+ g_free(shortdatadir);
+ g_free(localepath);
+
+ g_free(datadir);
+#else
+# ifdef ENABLE_BINRELOC
+ bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
+# else
+ bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+ // needed by Python/Gettext
+ g_setenv("PACKAGE_LOCALE_DIR", PACKAGE_LOCALE_DIR, TRUE);
+# endif
+#endif
+
+ // Allow the user to override the locale directory by setting
+ // the environment variable INKSCAPE_LOCALEDIR.
+ char const *inkscape_localedir = g_getenv("INKSCAPE_LOCALEDIR");
+ if (inkscape_localedir != NULL) {
+ bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
+ }
+
+ // common setup
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+ textdomain(GETTEXT_PACKAGE);
+}
+
+/** set gettext codeset to UTF8 */
+void bind_textdomain_codeset_utf8() {
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+}
+
+/** set gettext codeset to codeset of the system console
+ * - on *nix this is typically the current locale,
+ * - on Windows we don't care and simply use UTF8
+ * any conversion would need to happen in our console wrappers (see winconsole.cpp) anyway
+ * as we have no easy way of determining console encoding from inkscape/inkview.exe process;
+ * for now do something even easier - switch console encoding to UTF8 and be done with it!
+ * this also works nicely on MSYS consoles where UTF8 encoding is used by default, too */
+void bind_textdomain_codeset_console() {
+#ifdef WIN32
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+#else
+ std::string charset;
+ Glib::get_charset(charset);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, charset.c_str());
+#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:fileencoding=utf-8:textwidth=99: \ No newline at end of file
diff --git a/src/helper/gettext.h b/src/helper/gettext.h
new file mode 100644
index 000000000..689bddbbb
--- /dev/null
+++ b/src/helper/gettext.h
@@ -0,0 +1,46 @@
+/**
+ * \file
+ * \brief helper functions for gettext
+ *//*
+ * Authors:
+ * Eduard Braun <eduard.braun2@gmx.de>
+ *
+ * Copyright 2017 Authors
+ *
+ * This file is part of Inkscape.
+ *
+ * Inkscape is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Inkscape is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Inkscape. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SEEN_GETTEXT_HELPER_H
+#define SEEN_GETTEXT_HELPER_H
+
+namespace Inkscape {
+ void initialize_gettext();
+ void bind_textdomain_codeset_utf8();
+ void bind_textdomain_codeset_console();
+}
+
+#endif // SEEN_GETTEXT_HELPER_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99: \ No newline at end of file
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index 9639096fb..bab998fdb 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -12,10 +12,9 @@
*/
#ifdef HAVE_CONFIG_H
-# include "config.h"
+#include <config.h>
#endif
-#include <png.h>
#include <boost/scoped_ptr.hpp>
#include <2geom/transforms.h>
@@ -24,11 +23,8 @@
#include "display/cairo-utils.h"
#include "display/drawing.h"
#include "display/drawing-context.h"
-#include "display/drawing-item.h"
#include "document.h"
-#include "sp-item.h"
#include "sp-root.h"
-#include "sp-use.h"
#include "sp-defs.h"
#include "util/units.h"
@@ -53,8 +49,8 @@ static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dke
// recurse
if (!g_slist_find(list, o)) {
- for ( SPObject *child = o->firstChild() ; child; child = child->getNext() ) {
- hide_other_items_recursively(child, list, dkey);
+ for (auto& child: o->children) {
+ hide_other_items_recursively(&child, list, dkey);
}
}
}
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 9430feeff..e06c539d3 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -14,19 +14,17 @@
*/
#ifdef HAVE_CONFIG_H
-# include "config.h"
+#include <config.h>
#endif
#include <png.h>
#include "ui/interface.h"
#include <2geom/rect.h>
#include <2geom/transforms.h>
-#include <glib.h>
#include "png-write.h"
#include "io/sys.h"
#include "display/drawing.h"
#include "display/drawing-context.h"
-#include "display/drawing-item.h"
#include "document.h"
#include "sp-item.h"
#include "sp-root.h"
@@ -125,8 +123,8 @@ void PngTextList::add(gchar const* key, gchar const* text)
static bool
sp_png_write_rgba_striped(SPDocument *doc,
gchar const *filename, unsigned long int width, unsigned long int height, double xdpi, double ydpi,
- int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data),
- void *data)
+ int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth, int antialias),
+ void *data, bool interlace, int color_type, int bit_depth, int zlib, int antialiasing)
{
g_return_val_if_fail(filename != NULL, false);
g_return_val_if_fail(data != NULL, false);
@@ -186,22 +184,28 @@ sp_png_write_rgba_striped(SPDocument *doc,
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
+
+ png_set_compression_level(png_ptr, zlib);
+
png_set_IHDR(png_ptr, info_ptr,
width,
height,
- 8, /* bit_depth */
- PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE,
+ bit_depth,
+ color_type,
+ interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
- /* otherwise, if we are dealing with a color image then */
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- /* if the image has an alpha channel then */
- sig_bit.alpha = 8;
- png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ if ((color_type&2) && bit_depth == 16) {
+ // otherwise, if we are dealing with a color image then
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ // if the image has an alpha channel then
+ if (color_type&4)
+ sig_bit.alpha = 8;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ }
PngTextList textList;
@@ -250,7 +254,10 @@ sp_png_write_rgba_striped(SPDocument *doc,
/* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
/* note that if sRGB is present the cHRM chunk must be ignored
* on read and must be written in accordance with the sRGB profile */
- png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 + 0.5), unsigned(ydpi / 0.0254 + 0.5), PNG_RESOLUTION_METER);
+ if(xdpi < 0.0254 ) xdpi = 0.0255;
+ if(ydpi < 0.0254 ) ydpi = 0.0255;
+
+ png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 ), unsigned(ydpi / 0.0254 ), PNG_RESOLUTION_METER);
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
@@ -273,15 +280,18 @@ sp_png_write_rgba_striped(SPDocument *doc,
*/
png_bytep* row_pointers = new png_bytep[ebp->sheight];
-
- r = 0;
- while (r < static_cast<png_uint_32>(height)) {
- void *to_free;
- int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data);
- if (!n) break;
- png_write_rows(png_ptr, row_pointers, n);
- g_free(to_free);
- r += n;
+ int number_of_passes = interlace ? png_set_interlace_handling(png_ptr) : 1;
+
+ for(int i=0;i<number_of_passes; ++i){
+ r = 0;
+ while (r < static_cast<png_uint_32>(height)) {
+ void *to_free;
+ int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data, color_type, bit_depth, antialiasing);
+ if (!n) break;
+ png_write_rows(png_ptr, row_pointers, n);
+ g_free(to_free);
+ r += n;
+ }
}
delete[] row_pointers;
@@ -310,7 +320,7 @@ sp_png_write_rgba_striped(SPDocument *doc,
*
*/
static int
-sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data)
+sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth, int antialiasing)
{
struct SPEBP *ebp = (struct SPEBP *) data;
@@ -342,18 +352,17 @@ sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, v
dc.setOperator(CAIRO_OPERATOR_OVER);
/* Render */
- ebp->drawing->render(dc, bbox);
+ ebp->drawing->render(dc, bbox, 0, antialiasing);
cairo_surface_destroy(s);
- *to_free = px;
-
// PNG stores data as unpremultiplied big-endian RGBA, which means
// it's identical to the GdkPixbuf format.
convert_pixels_argb32_to_pixbuf(px, ebp->width, num_rows, stride);
-
- for (int r = 0; r < num_rows; r++) {
- rows[r] = px + r * stride;
- }
+
+ // If a custom bit depth or color type is asked, then convert rgb to grayscale, etc.
+ const guchar* new_data = pixbuf_to_png(rows, px, num_rows, ebp->width, stride, color_type, bit_depth);
+ *to_free = (void*) new_data;
+ free(px);
return num_rows;
}
@@ -374,8 +383,8 @@ static void hide_other_items_recursively(SPObject *o, const std::vector<SPItem*>
// recurse
if (list.end()==find(list.begin(),list.end(),o)) {
- for ( SPObject *child = o->firstChild() ; child; child = child->getNext() ) {
- hide_other_items_recursively(child, list, dkey);
+ for (auto& child: o->children) {
+ hide_other_items_recursively(&child, list, dkey);
}
}
}
@@ -387,10 +396,10 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned int (*status) (float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib, int antialiasing)
{
return sp_export_png_file(doc, filename, Geom::Rect(Geom::Point(x0,y0),Geom::Point(x1,y1)),
- width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only);
+ width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only, interlace, color_type, bit_depth, zlib, antialiasing);
}
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
@@ -399,7 +408,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned (*status)(float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib, int antialiasing)
{
g_return_val_if_fail(doc != NULL, EXPORT_ERROR);
g_return_val_if_fail(filename != NULL, EXPORT_ERROR);
@@ -470,7 +479,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
ebp.px = g_try_new(guchar, 4 * ebp.sheight * width);
if (ebp.px) {
- write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp);
+ write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp, interlace, color_type, bit_depth, zlib, antialiasing);
g_free(ebp.px);
}
diff --git a/src/helper/png-write.h b/src/helper/png-write.h
index 2657fb635..06498f46e 100644
--- a/src/helper/png-write.h
+++ b/src/helper/png-write.h
@@ -34,12 +34,14 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
double x0, double y0, double x1, double y1,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>(),
+ bool interlace = false, int color_type = 6, int bit_depth = 8, int zlib = 6, int antialiasing = 2);
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
Geom::Rect const &area,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>(),
+ bool interlace = false, int color_type = 6, int bit_depth = 8, int zlib = 6, int antialiasing = 2);
#endif // SEEN_SP_PNG_WRITE_H
diff --git a/src/helper/stock-items.cpp b/src/helper/stock-items.cpp
index 5a56b89ff..647e42916 100644
--- a/src/helper/stock-items.cpp
+++ b/src/helper/stock-items.cpp
@@ -204,37 +204,37 @@ SPObject *get_stock_item(gchar const *urn, gboolean stock)
}
SPObject *object = NULL;
if (!strcmp(base, "marker") && !stock) {
- for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
+ for (auto& child: defs->children)
{
- if (child->getRepr()->attribute("inkscape:stockid") &&
- !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
- SP_IS_MARKER(child))
+ if (child.getRepr()->attribute("inkscape:stockid") &&
+ !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
+ SP_IS_MARKER(&child))
{
- object = child;
+ object = &child;
}
}
}
else if (!strcmp(base,"pattern") && !stock) {
- for ( SPObject *child = defs->firstChild() ; child; child = child->getNext() )
+ for (auto& child: defs->children)
{
- if (child->getRepr()->attribute("inkscape:stockid") &&
- !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
- SP_IS_PATTERN(child))
+ if (child.getRepr()->attribute("inkscape:stockid") &&
+ !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
+ SP_IS_PATTERN(&child))
{
- object = child;
+ object = &child;
}
}
}
else if (!strcmp(base,"gradient") && !stock) {
- for ( SPObject *child = defs->firstChild(); child; child = child->getNext() )
+ for (auto& child: defs->children)
{
- if (child->getRepr()->attribute("inkscape:stockid") &&
- !strcmp(name_p, child->getRepr()->attribute("inkscape:stockid")) &&
- SP_IS_GRADIENT(child))
+ if (child.getRepr()->attribute("inkscape:stockid") &&
+ !strcmp(name_p, child.getRepr()->attribute("inkscape:stockid")) &&
+ SP_IS_GRADIENT(&child))
{
- object = child;
+ object = &child;
}
}