summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Jeanmougin <marc@jeanmougin.fr>2015-04-26 09:46:39 +0000
committerMarc Jeanmougin <mc@M0nst3r.bouyguesbox.fr>2015-04-26 09:46:39 +0000
commitac6617a55b9f7c05db084eeaa5684fb42d5e1406 (patch)
tree1fc8e668890618463d48298074559c7fe6bc5040 /src
parentmerge (diff)
parentextensions. ink2canvas.py - do not parse html comments. (Bug 1446204) (diff)
downloadinkscape-ac6617a55b9f7c05db084eeaa5684fb42d5e1406.tar.gz
inkscape-ac6617a55b9f7c05db084eeaa5684fb42d5e1406.zip
merging
(bzr r13922.1.13)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/line.h17
-rw-r--r--src/2geom/sbasis-to-bezier.cpp21
-rw-r--r--src/CMakeLists.txt44
-rw-r--r--src/Makefile_insert2
-rw-r--r--src/attributes.cpp2
-rw-r--r--src/attributes.h2
-rw-r--r--src/display/drawing.cpp6
-rw-r--r--src/document.cpp35
-rw-r--r--src/document.h3
-rw-r--r--src/extension/internal/cairo-render-context.cpp5
-rw-r--r--src/extension/internal/cairo-renderer.cpp2
-rw-r--r--src/extension/internal/filter/color.h77
-rw-r--r--src/extension/internal/filter/filter-all.cpp1
-rw-r--r--src/extension/param/radiobutton.cpp41
-rw-r--r--src/gradient-chemistry.cpp22
-rw-r--r--src/gradient-drag.cpp38
-rw-r--r--src/gradient-drag.h4
-rw-r--r--src/helper/CMakeLists.txt2
-rw-r--r--src/helper/Makefile_insert2
-rw-r--r--src/helper/geom-pathstroke.cpp770
-rw-r--r--src/helper/geom-pathstroke.h58
-rw-r--r--src/helper/geom.cpp49
-rw-r--r--src/helper/geom.h1
-rw-r--r--src/inkgc/CMakeLists.txt5
-rw-r--r--src/knotholder.cpp3
-rw-r--r--src/libcroco/cr-statement.c2
-rw-r--r--src/livarot/ShapeMisc.cpp8
-rw-r--r--src/live_effects/CMakeLists.txt51
-rw-r--r--src/live_effects/Makefile_insert2
-rw-r--r--src/live_effects/effect.cpp16
-rw-r--r--src/live_effects/effect.h2
-rw-r--r--src/live_effects/lpe-bspline.cpp403
-rw-r--r--src/live_effects/lpe-bspline.h12
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp3
-rw-r--r--src/live_effects/lpe-fillet-chamfer.cpp2
-rw-r--r--src/live_effects/lpe-jointype.cpp129
-rw-r--r--src/live_effects/lpe-jointype.h5
-rw-r--r--src/live_effects/lpe-knot.cpp2
-rw-r--r--src/live_effects/lpe-lattice.cpp15
-rw-r--r--src/live_effects/lpe-lattice2.cpp567
-rw-r--r--src/live_effects/lpe-lattice2.h72
-rw-r--r--src/live_effects/lpe-offset.cpp4
-rw-r--r--src/live_effects/lpe-parallel.cpp5
-rw-r--r--src/live_effects/lpe-perspective-envelope.cpp346
-rw-r--r--src/live_effects/lpe-perspective-envelope.h26
-rw-r--r--src/live_effects/lpe-powerstroke.cpp33
-rw-r--r--src/live_effects/lpe-roughen.cpp206
-rw-r--r--src/live_effects/lpe-roughen.h14
-rw-r--r--src/live_effects/lpe-show_handles.cpp76
-rw-r--r--src/live_effects/lpe-show_handles.h14
-rw-r--r--src/live_effects/lpe-simplify.cpp237
-rw-r--r--src/live_effects/lpe-simplify.h48
-rw-r--r--src/live_effects/lpe-sketch.cpp2
-rw-r--r--src/live_effects/lpe-taperstroke.cpp204
-rw-r--r--src/live_effects/lpe-test-doEffect-stack.cpp1
-rw-r--r--src/live_effects/parameter/Makefile_insert2
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.cpp2
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.h4
-rw-r--r--src/live_effects/parameter/point.cpp100
-rw-r--r--src/live_effects/parameter/point.h13
-rw-r--r--src/live_effects/parameter/pointreseteable.cpp210
-rw-r--r--src/live_effects/parameter/pointreseteable.h74
-rw-r--r--src/live_effects/pathoutlineprovider.cpp803
-rw-r--r--src/live_effects/pathoutlineprovider.h55
-rw-r--r--src/selection-describer.cpp4
-rw-r--r--src/sp-ellipse.cpp83
-rw-r--r--src/sp-factory.cpp14
-rw-r--r--src/sp-gradient.cpp24
-rw-r--r--src/sp-gradient.h8
-rw-r--r--src/sp-item-group.cpp2
-rw-r--r--src/sp-item-transform.cpp8
-rw-r--r--src/sp-item.cpp69
-rw-r--r--src/sp-item.h1
-rw-r--r--src/sp-lpe-item.cpp2
-rw-r--r--src/sp-mesh-array.cpp474
-rw-r--r--src/sp-mesh-array.h33
-rw-r--r--src/sp-mesh-gradient.cpp299
-rw-r--r--src/sp-mesh-patch.cpp28
-rw-r--r--src/sp-mesh-patch.h18
-rw-r--r--src/sp-mesh-row.cpp30
-rw-r--r--src/sp-mesh-row.h18
-rw-r--r--src/sp-mesh.cpp252
-rw-r--r--src/sp-mesh.h (renamed from src/sp-mesh-gradient.h)22
-rw-r--r--src/sp-namedview.cpp4
-rw-r--r--src/sp-path.cpp34
-rw-r--r--src/sp-rect.cpp110
-rw-r--r--src/splivarot.cpp2
-rw-r--r--src/svg-profile.h2
-rw-r--r--src/svg/svg-length.cpp52
-rw-r--r--src/svg/svg-length.h8
-rw-r--r--src/trace/potrace/auxiliary.h31
-rw-r--r--src/trace/potrace/bitmap.h33
-rw-r--r--src/trace/potrace/bitops.h83
-rw-r--r--src/trace/potrace/curve.cpp26
-rw-r--r--src/trace/potrace/curve.h2
-rw-r--r--src/trace/potrace/decompose.cpp29
-rw-r--r--src/trace/potrace/decompose.h2
-rw-r--r--src/trace/potrace/greymap.cpp61
-rw-r--r--src/trace/potrace/greymap.h5
-rw-r--r--src/trace/potrace/lists.h2
-rw-r--r--src/trace/potrace/potracelib.cpp2
-rw-r--r--src/trace/potrace/potracelib.h2
-rw-r--r--src/trace/potrace/progress.h2
-rw-r--r--src/trace/potrace/render.cpp4
-rw-r--r--src/trace/potrace/render.h2
-rw-r--r--src/trace/potrace/trace.cpp66
-rw-r--r--src/trace/potrace/trace.h2
-rw-r--r--src/ui/CMakeLists.txt29
-rw-r--r--src/ui/dialog/document-properties.cpp5
-rw-r--r--src/ui/dialog/filedialogimpl-win32.cpp8
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp2
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp4
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.cpp8
-rw-r--r--src/ui/dialog/lpe-fillet-chamfer-properties.h6
-rw-r--r--src/ui/dialog/print.cpp21
-rw-r--r--src/ui/object-edit.cpp96
-rw-r--r--src/ui/tool/curve-drag-point.cpp4
-rw-r--r--src/ui/tool/multi-path-manipulator.h2
-rw-r--r--src/ui/tool/node.cpp103
-rw-r--r--src/ui/tool/path-manipulator.cpp142
-rw-r--r--src/ui/tool/path-manipulator.h12
-rw-r--r--src/ui/tools/box3d-tool.h2
-rw-r--r--src/ui/tools/connector-tool.cpp2
-rw-r--r--src/ui/tools/dynamic-base.h2
-rw-r--r--src/ui/tools/flood-tool.cpp54
-rw-r--r--src/ui/tools/flood-tool.h6
-rw-r--r--src/ui/tools/freehand-base.cpp12
-rw-r--r--src/ui/tools/freehand-base.h2
-rw-r--r--src/ui/tools/gradient-tool.cpp2
-rw-r--r--src/ui/tools/mesh-tool.cpp16
-rw-r--r--src/ui/tools/node-tool.cpp2
-rw-r--r--src/ui/tools/pen-tool.cpp411
-rw-r--r--src/ui/tools/pen-tool.h28
-rw-r--r--src/ui/tools/pencil-tool.cpp22
-rw-r--r--src/ui/tools/spray-tool.cpp68
-rw-r--r--src/ui/widget/page-sizer.cpp242
-rw-r--r--src/ui/widget/page-sizer.h40
-rw-r--r--src/ui/widget/selected-style.cpp4
-rw-r--r--src/uri-references.cpp2
-rw-r--r--src/widgets/box3d-toolbar.cpp14
-rw-r--r--src/widgets/mesh-toolbar.cpp125
-rw-r--r--src/widgets/paint-selector.cpp6
-rw-r--r--src/widgets/paintbucket-toolbar.cpp21
-rw-r--r--src/widgets/rect-toolbar.cpp11
-rw-r--r--src/xml/repr-util.cpp15
-rw-r--r--src/xml/repr.h2
146 files changed, 4303 insertions, 4187 deletions
diff --git a/src/2geom/line.h b/src/2geom/line.h
index ade67f818..cbd68fa08 100644
--- a/src/2geom/line.h
+++ b/src/2geom/line.h
@@ -35,6 +35,7 @@
#define LIB2GEOM_SEEN_LINE_H
#include <cmath>
+#include <iostream>
#include <boost/optional.hpp>
#include <2geom/bezier-curve.h> // for LineSegment
#include <2geom/rect.h>
@@ -258,9 +259,19 @@ public:
dist = -dot(n, m_origin);
return n;
}
- /// @}
+
+ friend inline std::ostream &operator<< (std::ostream &out_file, const Geom::Line &in_line);
+/// @}
}; // end class Line
+/** @brief Output operator for lines.
+ * Prints out representation (point + versor)
+ */
+inline std::ostream &operator<< (std::ostream &out_file, const Geom::Line &in_line) {
+ out_file << "X: " << in_line.m_origin[X] << " Y: " << in_line.m_origin[Y]
+ << " dX: " << in_line.m_versor[X] << " dY: " << in_line.m_versor[Y];
+ return out_file;
+}
inline
double distance(Point const& _point, Line const& _line)
@@ -365,6 +376,10 @@ inline
Line make_angle_bisector_line(Point const& A, Point const& O, Point const& B)
{
Point M = middle_point(A,B);
+ if (are_near(O,M)) {
+ Line l(A,B);
+ M += (make_orthogonal_line(O,l)).versor();
+ }
return Line(O,M);
}
diff --git a/src/2geom/sbasis-to-bezier.cpp b/src/2geom/sbasis-to-bezier.cpp
index 0525be04b..a2e4253d2 100644
--- a/src/2geom/sbasis-to-bezier.cpp
+++ b/src/2geom/sbasis-to-bezier.cpp
@@ -37,6 +37,7 @@
#include <2geom/choose.h>
#include <2geom/path-sink.h>
#include <2geom/exception.h>
+#include <2geom/convex-cover.h>
#include <iostream>
@@ -203,11 +204,8 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
THROW_RANGEERROR("size of sb is too small");
}
- bz.resize(4, Point(0,0));
- bz[0][X] = sb[X][0][0];
- bz[0][Y] = sb[Y][0][0];
- bz[3][X] = sb[X][0][1];
- bz[3][Y] = sb[Y][0][1];
+ sbasis_to_bezier(bz, sb, 4); // zeroth-order estimate
+ Geom::ConvexHull bezhull(bz);
// calculate first derivatives of x and y wrt t
@@ -231,17 +229,23 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
midx += (sb[X][i][0] + sb[X][i][1])/div;
div *= 4;
}
- midx = 8*midx - 4*bz[0][X] - 4*bz[3][X];
div = 2;
for (size_t i = 0; i < sb[Y].size(); ++i) {
midy += (sb[Y][i][0] + sb[Y][i][1])/div;
div *= 4;
}
- midy = 8*midy - 4*bz[0][Y] - 4*bz[3][Y];
+
+// is midpoint in hull: if not, the solution will be ill-conditioned, LP Bug 1428683
+
+ if (!bezhull.contains_point(Geom::Point(midx, midy)))
+ return;
// calculate Bezier control arms
+ midx = 8*midx - 4*bz[0][X] - 4*bz[3][X]; // re-define relative to center
+ midy = 8*midy - 4*bz[0][Y] - 4*bz[3][Y];
+
if ((std::abs(xprime[0]) < EPSILON) && (std::abs(yprime[0]) < EPSILON)
&& ((std::abs(xprime[1]) > EPSILON) || (std::abs(yprime[1]) > EPSILON))) { // degenerate handle at 0 : use distance of closest approach
numer = midx*xprime[1] + midy*yprime[1];
@@ -258,7 +262,8 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
dely[0] = yprime[0]*numer/denom;
delx[1] = 0;
dely[1] = 0;
- } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > EPSILON) { // general case : fit mid fxn value
+ } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > // general case : fit mid fxn value
+ 0.002 * std::abs(xprime[1]*xprime[0] + yprime[1]*yprime[0])) { // approx. 0.1 degree of angle
denom = xprime[1]*yprime[0] - yprime[1]*xprime[0];
for (int i = 0; i < 2; ++i) {
numer = xprime[1 - i]*midy - yprime[1 - i]*midx;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0b1e3931b..27c5e49db 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,4 +1,3 @@
-
# -----------------------------------------------------------------------------
# Define the main source
# -----------------------------------------------------------------------------
@@ -33,8 +32,8 @@ set(sp_SRC
sp-gradient-reference.cpp
sp-gradient.cpp
sp-guide.cpp
- sp-hatch.cpp
sp-hatch-path.cpp
+ sp-hatch.cpp
sp-image.cpp
sp-item-group.cpp
sp-item-notify-moveto.cpp
@@ -48,9 +47,9 @@ set(sp_SRC
sp-marker.cpp
sp-mask.cpp
sp-mesh-array.cpp
- sp-mesh-gradient.cpp
sp-mesh-patch.cpp
sp-mesh-row.cpp
+ sp-mesh.cpp
sp-metadata.cpp
sp-missing-glyph.cpp
sp-namedview.cpp
@@ -75,6 +74,9 @@ set(sp_SRC
sp-style-elem.cpp
sp-switch.cpp
sp-symbol.cpp
+ sp-tag-use-reference.cpp
+ sp-tag-use.cpp
+ sp-tag.cpp
sp-text.cpp
sp-title.cpp
sp-tref-reference.cpp
@@ -119,8 +121,8 @@ set(sp_SRC
sp-guide-attachment.h
sp-guide-constraint.h
sp-guide.h
- sp-hatch.h
sp-hatch-path.h
+ sp-hatch.h
sp-image.h
sp-item-group.h
sp-item-notify-moveto.h
@@ -131,13 +133,13 @@ set(sp_SRC
sp-line.h
sp-linear-gradient.h
sp-lpe-item.h
- sp-marker.h
sp-marker-loc.h
+ sp-marker.h
sp-mask.h
sp-mesh-array.h
- sp-mesh-gradient.h
sp-mesh-patch.h
sp-mesh-row.h
+ sp-mesh.h
sp-metadata.h
sp-missing-glyph.h
sp-namedview.h
@@ -203,21 +205,17 @@ set(inkscape_SRC
filter-enums.cpp
gc-anchored.cpp
gc-finalized.cpp
- gc.cpp
gradient-chemistry.cpp
gradient-drag.cpp
graphlayout.cpp
guide-snapper.cpp
help.cpp
id-clash.cpp
- # ige-mac-menu.c
inkscape.cpp
- inkscape.rc
- interface.cpp
knot-holder-entity.cpp
+ knot-ptr.cpp
knot.cpp
knotholder.cpp
- knot-ptr.cpp
layer-fns.cpp
layer-manager.cpp
layer-model.cpp
@@ -257,8 +255,8 @@ set(inkscape_SRC
snapped-line.cpp
snapped-point.cpp
snapper.cpp
- style.cpp
style-internal.cpp
+ style.cpp
svg-view-widget.cpp
svg-view.cpp
text-chemistry.cpp
@@ -313,18 +311,12 @@ set(inkscape_SRC
event.h
extract-uri-test.h
extract-uri.h
- factory.h
file.h
fill-or-stroke.h
filter-chemistry.h
filter-enums.h
- gc-alloc.h
- gc-allocator.h
gc-anchored.h
- gc-core.h
gc-finalized.h
- gc-managed.h
- gc-soft-ptr.h
gradient-chemistry.h
gradient-drag.h
graphlayout.h
@@ -333,16 +325,14 @@ set(inkscape_SRC
helper-fns.h
icon-size.h
id-clash.h
- # ige-mac-menu.h
inkscape-version.h
inkscape.h
- interface.h
isinf.h
knot-enums.h
knot-holder-entity.h
+ knot-ptr.h
knot.h
knotholder.h
- knot-ptr.h
layer-fns.h
layer-manager.h
layer-model.h
@@ -351,7 +341,6 @@ set(inkscape_SRC
macros.h
main-cmdlineact.h
marker-test.h
- marker.h
media.h
menus-skeleton.h
message-context.h
@@ -376,7 +365,6 @@ set(inkscape_SRC
profile-manager.h
proj_pt.h
rdf.h
- registrytool.h
remove-last.h
removeoverlap.h
require-config.h
@@ -403,10 +391,10 @@ set(inkscape_SRC
splivarot.h
streq.h
strneq.h
- style-test.h
- style.h
style-enums.h
style-internal.h
+ style-test.h
+ style.h
svg-profile.h
svg-view-widget.h
svg-view.h
@@ -430,8 +418,10 @@ set(inkscape_SRC
if(WIN32)
list(APPEND inkscape_SRC
+ inkscape.rc
registrytool.cpp
#deptool.cpp
+ winconsole.cpp
winmain.cpp
)
endif()
@@ -471,7 +461,6 @@ list(APPEND inkscape_SRC
# All folders for internal inkscape
# these call add_inkscape_source
add_subdirectory(debug)
-add_subdirectory(dialogs)
add_subdirectory(display)
add_subdirectory(extension)
add_subdirectory(filters)
@@ -545,6 +534,8 @@ target_link_libraries(inkscape
uemf_LIB
2geom_LIB
depixelize_LIB
+ util_LIB
+ gc_LIB
${INKSCAPE_LIBS}
)
@@ -553,4 +544,3 @@ target_link_libraries(inkscape
# make executable for INKVIEW
#add_executable(inkview inkview.cpp)
# ...
-
diff --git a/src/Makefile_insert b/src/Makefile_insert
index 2bd457529..800752df4 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -154,8 +154,8 @@ ink_common_sources += \
sp-marker-loc.h \
sp-mask.cpp sp-mask.h \
sp-metadata.cpp sp-metadata.h \
+ sp-mesh.cpp sp-mesh.h \
sp-mesh-array.cpp sp-mesh-array.h \
- sp-mesh-gradient.cpp sp-mesh-gradient.h \
sp-mesh-patch.cpp sp-mesh-patch.h \
sp-mesh-row.cpp sp-mesh-row.h \
sp-missing-glyph.cpp sp-missing-glyph.h \
diff --git a/src/attributes.cpp b/src/attributes.cpp
index 0b18b80cf..568f0528a 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -291,7 +291,7 @@ static SPStyleProp const props[] = {
{SP_ATTR_FY, "fy"},
/* SPMeshPatch */
{SP_ATTR_TENSOR, "tensor"},
- {SP_ATTR_SMOOTH, "smooth"},
+ //{SP_ATTR_TYPE, "type"},
/* SPPattern */
{SP_ATTR_PATTERNUNITS, "patternUnits"},
{SP_ATTR_PATTERNCONTENTUNITS, "patternContentUnits"},
diff --git a/src/attributes.h b/src/attributes.h
index 645aad00b..91c8868f9 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -293,7 +293,7 @@ enum SPAttributeEnum {
SP_ATTR_FY,
/* SPMeshPatch */
SP_ATTR_TENSOR,
- SP_ATTR_SMOOTH,
+ //SP_ATTR_TYPE,
/* SPPattern */
SP_ATTR_PATTERNUNITS,
SP_ATTR_PATTERNCONTENTUNITS,
diff --git a/src/display/drawing.cpp b/src/display/drawing.cpp
index 6e728b03d..eadd7e528 100644
--- a/src/display/drawing.cpp
+++ b/src/display/drawing.cpp
@@ -210,9 +210,9 @@ Drawing::_pickItemsForCaching()
}
std::set<DrawingItem*> to_cache;
- for (i = _candidate_items.begin(); i != _candidate_items.end(); ++i) {
- i->item->setCached(true);
- to_cache.insert(i->item);
+ for (CandidateList::iterator j = _candidate_items.begin(); j != i; ++j) {
+ j->item->setCached(true);
+ to_cache.insert(j->item);
}
// Everything which is now in _cached_items but not in to_cache must be uncached
// Note that calling setCached on an item modifies _cached_items
diff --git a/src/document.cpp b/src/document.cpp
index 2c301f5f8..f06953e34 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -611,7 +611,25 @@ Inkscape::Util::Unit const& SPDocument::getSVGUnit() const
return nv ? nv->getSVGUnit() : *unit_table.getUnit("px");
}
-/// Returns document scale as defined by width/height and viewBox (real world to user-units).
+/// Sets document scale (by changing viewBox)
+void SPDocument::setDocumentScale( double scaleX, double scaleY ) {
+
+ root->viewBox = Geom::Rect::from_xywh(
+ root->viewBox.left(),
+ root->viewBox.top(),
+ root->width.computed * scaleX,
+ root->height.computed * scaleY );
+ root->viewBox_set = true;
+ root->updateRepr();
+}
+
+/// Sets document scale (by changing viewBox, x and y scaling equal)
+void SPDocument::setDocumentScale( double scale ) {
+ setDocumentScale( scale, scale );
+}
+
+/// Returns document scale as defined by width/height (in pixels) and viewBox (real world to
+/// user-units).
Geom::Scale SPDocument::getDocumentScale() const
{
Geom::Scale scale;
@@ -660,10 +678,12 @@ void SPDocument::setWidthAndHeight(const Inkscape::Util::Quantity &width, const
root->height.value = height.quantity;
root->height.unit = (SVGLength::Unit) height.unit->svgUnit();
- if (root->viewBox_set && changeSize)
+ // viewBox scaled by relative change in page size (maintains document scale).
+ if (root->viewBox_set && changeSize) {
root->viewBox.setMax(Geom::Point(
root->viewBox.left() + (root->width.value / old_width_converted ) * root->viewBox.width(),
root->viewBox.top() + (root->height.value / old_height_converted) * root->viewBox.height()));
+ }
root->updateRepr();
}
@@ -744,6 +764,17 @@ void SPDocument::setHeight(const Inkscape::Util::Quantity &height, bool changeSi
root->updateRepr();
}
+Geom::Rect SPDocument::getViewBox() const
+{
+ Geom::Rect viewBox;
+ if (root->viewBox_set) {
+ viewBox = root->viewBox;
+ } else {
+ viewBox = Geom::Rect::from_xywh( 0, 0, getWidth().value("px"), getHeight().value("px"));
+ }
+ return viewBox;
+}
+
void SPDocument::setViewBox(const Geom::Rect &viewBox)
{
root->viewBox_set = true;
diff --git a/src/document.h b/src/document.h
index cf958f03e..16b9bb28d 100644
--- a/src/document.h
+++ b/src/document.h
@@ -242,9 +242,12 @@ public:
SPDocument *doUnref();
Inkscape::Util::Unit const* getDisplayUnit() const;
Inkscape::Util::Unit const& getSVGUnit() const;
+ void setDocumentScale( const double scaleX, const double scaleY );
+ void setDocumentScale( const double scale );
Geom::Scale getDocumentScale() const;
Inkscape::Util::Quantity getWidth() const;
Inkscape::Util::Quantity getHeight() const;
+ Geom::Rect getViewBox() const;
Geom::Point getDimensions() const;
Geom::OptRect preferredBounds() const;
void setWidthAndHeight(const Inkscape::Util::Quantity &width, const Inkscape::Util::Quantity &height, bool changeSize=true);
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index d76c187a2..2d6619e1e 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -42,6 +42,7 @@
#include "sp-hatch.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
+#include "sp-mesh.h"
#include "sp-pattern.h"
#include "sp-mask.h"
#include "sp-clippath.h"
@@ -1259,6 +1260,10 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
sp_color_get_rgb_floatv(&rg->vector.stops[i].color, rgb);
cairo_pattern_add_color_stop_rgba(pattern, rg->vector.stops[i].offset, rgb[0], rgb[1], rgb[2], rg->vector.stops[i].opacity * alpha);
}
+ } else if (SP_IS_MESH (paintserver)) {
+ SPMesh *mg = SP_MESH(paintserver);
+
+ pattern = mg->pattern_new(_cr, pbox, 1.0);
} else if (SP_IS_PATTERN (paintserver)) {
pattern = _createPatternPainter(paintserver, pbox);
} else if ( dynamic_cast<SPHatch const *>(paintserver) ) {
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index a2cea014b..49e145de0 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -515,7 +515,7 @@ static void sp_item_invoke_render(SPItem *item, CairoRenderContext *ctx)
SPStyle* style = item->style;
if((ctx->getFilterToBitmap() == TRUE) && (style->filter.set != 0)) {
- sp_asbitmap_render(item, ctx);
+ return sp_asbitmap_render(item, ctx);
}
SPRoot *root = dynamic_cast<SPRoot *>(item);
diff --git a/src/extension/internal/filter/color.h b/src/extension/internal/filter/color.h
index 19af6e969..c3c26bf8b 100644
--- a/src/extension/internal/filter/color.h
+++ b/src/extension/internal/filter/color.h
@@ -3,13 +3,14 @@
/* Change the 'COLOR' above to be your file name */
/*
- * Copyright (C) 2013 Authors:
+ * Copyright (C) 2013-2015 Authors:
* Ivan Louette (filters)
* Nicolas Dufour (UI) <nicoduf@yahoo.fr>
*
* Color filters
* Brilliance
* Channel painting
+ * Color blindness
* Color shift
* Colorize
* Component transfer
@@ -231,6 +232,80 @@ ChannelPaint::get_filter_text (Inkscape::Extension::Extension * ext)
}; /* Channel Painting filter */
/**
+ \brief Custom predefined Color Blindness filter.
+
+ Color Blindness filter.
+ Based on https://openclipart.org/detail/22299/Color%20Blindness%20filters
+
+ Filter's parameters:
+ * Blindness type (enum, default Achromatomaly) -> colormatrix
+*/
+class ColorBlindness : public Inkscape::Extension::Internal::Filter::Filter {
+protected:
+ virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext);
+
+public:
+ ColorBlindness ( ) : Filter() { };
+ virtual ~ColorBlindness ( ) { if (_filter != NULL) g_free((void *)_filter); return; }
+
+ static void init (void) {
+ Inkscape::Extension::build_from_mem(
+ "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
+ "<name>" N_("Color Blindness") "</name>\n"
+ "<id>org.inkscape.effect.filter.ColorBlindness</id>\n"
+ "<param name=\"tab\" type=\"notebook\">\n"
+ "<page name=\"optionstab\" _gui-text=\"Options\">\n"
+ "<param name=\"type\" gui-text=\"" N_("Blindness type:") "\" type=\"enum\">\n"
+ "<_item value=\"0.618 0.32 0.062 0 0 0.163 0.775 0.062 0 0 0.163 0.32 0.516 0 0 0 0 0 1 0 \">" N_("Rod monochromacy (atypical achromatopsia)") "</_item>\n"
+ "<_item value=\"0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0.299 0.587 0.114 0 0 0 0 0 1 0 \">" N_("Cone monochromacy (typical achromatopsia)") "</_item>\n"
+ "<_item value=\"0.8 0.2 0 0 0 0.2583 0.74167 0 0 0 0 0.14167 0.85833 0 0 0 0 0 1 0 \">" N_("Geen weak (deuteranomaly)") "</_item>\n"
+ "<_item value=\"0.625 0.375 0 0 0 0.7 0.3 0 0 0 0 0.3 0.7 0 0 0 0 0 1 0 \">" N_("Green blind (deuteranopia)") "</_item>\n"
+ "<_item value=\"0.8166 0.1833 0 0 0 0.333 0.666 0 0 0 0 0.125 0.875 0 0 0 0 0 1 0 \">" N_("Red weak (protanomaly)") "</_item>\n"
+ "<_item value=\"0.566 0.43333 0 0 0 0.55833 0.4416 0 0 0 0 0.24167 0.75833 0 0 0 0 0 1 0 \">" N_("Red blind (protanopia)") "</_item>\n"
+ "<_item value=\"0.966 0.033 0 0 0 0 0.733 0.266 0 0 0 0.1833 0.816 0 0 0 0 0 1 0 \">" N_("Blue weak (tritanomaly)") "</_item>\n"
+ "<_item value=\"0.95 0.05 0 0 0 0.2583 0.4333 0.5667 0 0 0 0.475 0.525 0 0 0 0 0 1 0 \">" N_("Blue blind (tritanopia)") "</_item>\n"
+ "</param>\n"
+ "</page>\n"
+ "<page name=\"helptab\" _gui-text=\"Help\">\n"
+ "<param name=\"help\" xml:space=\"preserve\" type=\"description\">\n"
+"Filters based on https://openclipart.org/detail/22299/Color%20Blindness%20filters\n"
+"\n"
+"These filters don't correctly reflect actual color blindness for two main reasons:\n"
+" * Everyone is different, and is not affected exactly the same way.\n"
+" * The filters are in the RGB color space, and ignore confusion lines.\n"
+ "</param>\n"
+ "</page>\n"
+ "</param>\n"
+ "<effect>\n"
+ "<object-type>all</object-type>\n"
+ "<effects-menu>\n"
+ "<submenu name=\"" N_("Filters") "\">\n"
+ "<submenu name=\"" N_("Color") "\"/>\n"
+ "</submenu>\n"
+ "</effects-menu>\n"
+ "<menu-tip>" N_("Simulate color blindness") "</menu-tip>\n"
+ "</effect>\n"
+ "</inkscape-extension>\n", new ColorBlindness());
+ };
+};
+
+gchar const *
+ColorBlindness::get_filter_text (Inkscape::Extension::Extension * ext)
+{
+ if (_filter != NULL) g_free((void *)_filter);
+
+ std::ostringstream type;
+ type << ext->get_param_enum("type");
+
+ _filter = g_strdup_printf(
+ "<filter xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" style=\"color-interpolation-filters:sRGB;\" height=\"1\" width=\"1\" y=\"0\" x=\"0\" inkscape:label=\"Color Blindness\">\n"
+ "<feColorMatrix values=\"%s\" type=\"matrix\" result=\"colormatrix1\" />\n"
+ "</filter>\n", type.str().c_str());
+
+ return _filter;
+}; /* Color Blindness filter */
+
+/**
\brief Custom predefined Color shift filter.
Rotate and desaturate hue
diff --git a/src/extension/internal/filter/filter-all.cpp b/src/extension/internal/filter/filter-all.cpp
index 0273d1669..35504d37f 100644
--- a/src/extension/internal/filter/filter-all.cpp
+++ b/src/extension/internal/filter/filter-all.cpp
@@ -54,6 +54,7 @@ Filter::filters_all (void )
// Color
Brilliance::init();
ChannelPaint::init();
+ ColorBlindness::init();
ColorShift::init();
Colorize::init();
ComponentTransfer::init();
diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp
index f9515197c..740acf1d1 100644
--- a/src/extension/param/radiobutton.cpp
+++ b/src/extension/param/radiobutton.cpp
@@ -249,28 +249,35 @@ void ParamRadioButtonWdg::changed(void)
class ComboWdg : public Gtk::ComboBoxText {
+private:
+ ParamRadioButton* _base;
+ SPDocument* _doc;
+ Inkscape::XML::Node* _node;
+ sigc::signal<void> * _changeSignal;
+
public:
- ComboWdg(ParamRadioButton* base, SPDocument * doc, Inkscape::XML::Node * node) :
- Gtk::ComboBoxText(),
- base(base),
- doc(doc),
- node(node)
+ ComboWdg(ParamRadioButton* base, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) :
+ _base(base),
+ _doc(doc),
+ _node(node),
+ _changeSignal(changeSignal)
{
+ this->signal_changed().connect(sigc::mem_fun(this, &ComboWdg::changed));
}
virtual ~ComboWdg() {}
+ void changed (void);
+};
-protected:
- ParamRadioButton* base;
- SPDocument* doc;
- Inkscape::XML::Node* node;
-
- virtual void on_changed() {
- if ( base ) {
- Glib::ustring value = base->value_from_label(get_active_text());
- base->set(value.c_str(), doc, node);
- }
+void ComboWdg::changed(void)
+{
+ if ( _base ) {
+ Glib::ustring value = _base->value_from_label(get_active_text());
+ _base->set(value.c_str(), _doc, _node);
}
-};
+ if (_changeSignal != NULL) {
+ _changeSignal->emit();
+ }
+}
/**
* Returns the value for the options label parameter
@@ -317,7 +324,7 @@ Gtk::Widget * ParamRadioButton::get_widget(SPDocument * doc, Inkscape::XML::Node
Gtk::ComboBoxText* cbt = 0;
bool comboSet = false;
if (_mode == MINIMAL) {
- cbt = Gtk::manage(new ComboWdg(this, doc, node));
+ cbt = Gtk::manage(new ComboWdg(this, doc, node, changeSignal));
cbt->show();
vbox->pack_start(*cbt, false, false);
}
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index b59b38475..d90972961 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -41,7 +41,7 @@
#include "sp-gradient-vector.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "sp-stop.h"
#include "gradient-drag.h"
#include "gradient-chemistry.h"
@@ -151,7 +151,7 @@ static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGr
repr = xml_doc->createElement("svg:radialGradient");
} else {
// Rows/patches added in sp_gradient_reset_to_userspace for new meshes.
- repr = xml_doc->createElement("svg:meshGradient");
+ repr = xml_doc->createElement("svg:mesh");
}
// privates are garbage-collectable
@@ -413,7 +413,7 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item)
// IN SPMeshNodeArray::create()
//sp_repr_set_svg_double(repr, "x", bbox->min()[Geom::X]);
//sp_repr_set_svg_double(repr, "y", bbox->min()[Geom::Y]);
- SPMeshGradient* mg = SP_MESHGRADIENT( gr );
+ SPMesh* mg = SP_MESH( gr );
mg->array.create( mg, item, bbox );
}
@@ -758,10 +758,10 @@ guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type,
break;
}
return 0;
- } else if (SP_IS_MESHGRADIENT(gradient)) {
+ } else if (SP_IS_MESH(gradient)) {
// Mesh gradient
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ SPMesh *mg = SP_MESH(gradient);
switch (point_type) {
case POINT_MG_CORNER: {
@@ -859,7 +859,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint
} else {
// Mesh gradient
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ SPMesh *mg = SP_MESH(gradient);
bool changed = false;
switch (point_type) {
@@ -1209,8 +1209,8 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
gradient->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
}
- } else if (SP_IS_MESHGRADIENT(gradient)) {
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ } else if (SP_IS_MESH(gradient)) {
+ SPMesh *mg = SP_MESH(gradient);
//Geom::Affine new_transform;
//bool transform_set = false;
@@ -1240,7 +1240,7 @@ void sp_item_gradient_set_coords(SPItem *item, GrPointType point_type, guint poi
}
if( write_repr ) {
//std::cout << "Write mesh repr" << std::endl;
- sp_meshgradient_repr_write( mg );
+ sp_mesh_repr_write( mg );
}
}
@@ -1346,8 +1346,8 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
g_warning( "Bad radial gradient handle type" );
break;
}
- } else if (SP_IS_MESHGRADIENT(gradient)) {
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ } else if (SP_IS_MESH(gradient)) {
+ SPMesh *mg = SP_MESH(gradient);
switch (point_type) {
case POINT_MG_CORNER:
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index 5a49435d4..169710114 100644
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
@@ -43,7 +43,7 @@
#include "knot.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "sp-mesh-row.h"
#include "sp-mesh-patch.h"
#include "gradient-chemistry.h"
@@ -414,7 +414,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
//r1_knot = false;
}
}
- } else if (SP_IS_MESHGRADIENT(gradient)) {
+ } else if (SP_IS_MESH(gradient)) {
// add_stop_near_point()
// Find out which curve pointer is over and use that curve to determine
@@ -422,7 +422,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
// This is silly as we already should know which line we are over...
// but that information is not saved (sp_gradient_context_is_over_line).
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ SPMesh *mg = SP_MESH(gradient);
Geom::Affine transform = Geom::Affine(mg->gradientTransform)*(Geom::Affine)item->i2dt_affine();
guint rows = mg->array.patch_rows();
@@ -550,7 +550,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
} else {
- SPMeshGradient *mg = SP_MESHGRADIENT(gradient);
+ SPMesh *mg = SP_MESH(gradient);
if( divide_row > -1 ) {
mg->array.split_row( divide_row, divide_coord );
@@ -559,7 +559,7 @@ SPStop *GrDrag::addStopNearPoint(SPItem *item, Geom::Point mouse_p, double toler
}
// Update repr
- sp_meshgradient_repr_write( mg );
+ sp_mesh_repr_write( mg );
mg->array.built = false;
mg->ensureArray();
// How do we do this?
@@ -1349,7 +1349,7 @@ GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op )
// Must be a mesh gradient
SPGradient *gradient = getGradient(draggable->item, draggable->fill_or_stroke);
- if ( !SP_IS_MESHGRADIENT( gradient ) ) continue;
+ if ( !SP_IS_MESH( gradient ) ) continue;
selected_corners[ gradient ].push_back( draggable->point_i );
}
@@ -1374,8 +1374,8 @@ GrDragger::updateHandles ( Geom::Point pc_old, MeshNodeOperation op )
// Must be a mesh gradient
SPGradient *gradient = getGradient(item, fill_or_stroke);
- if ( !SP_IS_MESHGRADIENT( gradient ) ) continue;
- SPMeshGradient *mg = SP_MESHGRADIENT( gradient );
+ if ( !SP_IS_MESH( gradient ) ) continue;
+ SPMesh *mg = SP_MESH( gradient );
// pc_old is the old corner position in desktop coordinates, we need it in gradient coordinate.
gradient = sp_gradient_convert_to_userspace (gradient, item, (fill_or_stroke == Inkscape::FOR_FILL) ? "fill" : "stroke");
@@ -1958,7 +1958,7 @@ void GrDrag::addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::Pai
/**
*Add draggers for the mesh gradient mg on item
*/
-void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke)
+void GrDrag::addDraggersMesh(SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke)
{
std::vector< std::vector< SPMeshNode* > > nodes = mg->array.nodes;
@@ -1977,7 +1977,7 @@ void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTa
// Make sure we have at least one patch defined.
if( mg->array.patch_rows() == 0 || mg->array.patch_columns() == 0 ) {
- std::cout << "Empty Mesh Gradient, No Draggers to Add" << std::endl;
+ std::cout << "Empty Mesh, No Draggers to Add" << std::endl;
return;
}
@@ -2032,7 +2032,7 @@ void GrDrag::addDraggersMesh(SPMeshGradient *mg, SPItem *item, Inkscape::PaintTa
}
default:
- std::cout << "Bad Mesh Gradient draggable type" << std::endl;
+ std::cout << "Bad Mesh draggable type" << std::endl;
break;
}
}
@@ -2097,8 +2097,8 @@ void GrDrag::updateDraggers()
addDraggersLinear( SP_LINEARGRADIENT(server), item, Inkscape::FOR_FILL );
} else if ( SP_IS_RADIALGRADIENT(server) ) {
addDraggersRadial( SP_RADIALGRADIENT(server), item, Inkscape::FOR_FILL );
- } else if ( SP_IS_MESHGRADIENT(server) ) {
- addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_FILL );
+ } else if ( SP_IS_MESH(server) ) {
+ addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_FILL );
}
}
}
@@ -2113,8 +2113,8 @@ void GrDrag::updateDraggers()
addDraggersLinear( SP_LINEARGRADIENT(server), item, Inkscape::FOR_STROKE );
} else if ( SP_IS_RADIALGRADIENT(server) ) {
addDraggersRadial( SP_RADIALGRADIENT(server), item, Inkscape::FOR_STROKE );
- } else if ( SP_IS_MESHGRADIENT(server) ) {
- addDraggersMesh( SP_MESHGRADIENT(server), item, Inkscape::FOR_STROKE );
+ } else if ( SP_IS_MESH(server) ) {
+ addDraggersMesh( SP_MESH(server), item, Inkscape::FOR_STROKE );
}
}
}
@@ -2169,9 +2169,9 @@ void GrDrag::updateLines()
Geom::Point center = getGradientCoords(item, POINT_RG_CENTER, 0, Inkscape::FOR_FILL);
addLine(item, center, getGradientCoords(item, POINT_RG_R1, 0, Inkscape::FOR_FILL), Inkscape::FOR_FILL);
addLine(item, center, getGradientCoords(item, POINT_RG_R2, 0, Inkscape::FOR_FILL), Inkscape::FOR_FILL);
- } else if ( SP_IS_MESHGRADIENT(server) ) {
+ } else if ( SP_IS_MESH(server) ) {
- SPMeshGradient *mg = SP_MESHGRADIENT(server);
+ SPMesh *mg = SP_MESH(server);
guint rows = mg->array.patch_rows();
guint columns = mg->array.patch_columns();
@@ -2231,10 +2231,10 @@ void GrDrag::updateLines()
Geom::Point center = getGradientCoords(item, POINT_RG_CENTER, 0, Inkscape::FOR_STROKE);
addLine(item, center, getGradientCoords(item, POINT_RG_R1, 0, Inkscape::FOR_STROKE), Inkscape::FOR_STROKE);
addLine(item, center, getGradientCoords(item, POINT_RG_R2, 0, Inkscape::FOR_STROKE), Inkscape::FOR_STROKE);
- } else if ( SP_IS_MESHGRADIENT(server) ) {
+ } else if ( SP_IS_MESH(server) ) {
// MESH FIXME: TURN ROUTINE INTO FUNCTION AND CALL FOR BOTH FILL AND STROKE.
- SPMeshGradient *mg = SP_MESHGRADIENT(server);
+ SPMesh *mg = SP_MESH(server);
guint rows = mg->array.patch_rows();
guint columns = mg->array.patch_columns();
diff --git a/src/gradient-drag.h b/src/gradient-drag.h
index 964ea8093..da264b4bb 100644
--- a/src/gradient-drag.h
+++ b/src/gradient-drag.h
@@ -33,7 +33,7 @@ class SPKnot;
class SPDesktop;
class SPCSSAttr;
class SPLinearGradient;
-class SPMeshGradient;
+class SPMesh;
class SPItem;
class SPObject;
class SPRadialGradient;
@@ -206,7 +206,7 @@ private:
void addDraggersRadial(SPRadialGradient *rg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
void addDraggersLinear(SPLinearGradient *lg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
- void addDraggersMesh( SPMeshGradient *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
+ void addDraggersMesh( SPMesh *mg, SPItem *item, Inkscape::PaintTarget fill_or_stroke);
bool styleSet( const SPCSSAttr *css );
diff --git a/src/helper/CMakeLists.txt b/src/helper/CMakeLists.txt
index 74ce2c85d..ff4760c24 100644
--- a/src/helper/CMakeLists.txt
+++ b/src/helper/CMakeLists.txt
@@ -13,6 +13,7 @@ set(helper_SRC
action-context.cpp
geom.cpp
geom-nodetype.cpp
+ geom-pathstroke.cpp
gnome-utils.cpp
pixbuf-ops.cpp
png-write.cpp
@@ -30,6 +31,7 @@ set(helper_SRC
action-context.h
geom-curves.h
geom-nodetype.h
+ geom-pathstroke.h
geom.h
gnome-utils.h
mathfns.h
diff --git a/src/helper/Makefile_insert b/src/helper/Makefile_insert
index 5cb4cea8d..e59fcfb70 100644
--- a/src/helper/Makefile_insert
+++ b/src/helper/Makefile_insert
@@ -12,6 +12,8 @@ ink_common_sources += \
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 \
diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp
new file mode 100644
index 000000000..eb0c432c6
--- /dev/null
+++ b/src/helper/geom-pathstroke.cpp
@@ -0,0 +1,770 @@
+/* Author:
+ * Liam P. White
+ *
+ * Copyright (C) 2014-2015 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <iomanip>
+#include <2geom/path-sink.h>
+#include <2geom/point.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/svg-elliptical-arc.h>
+#include <2geom/sbasis-to-bezier.h> // cubicbezierpath_from_sbasis
+#include <2geom/path-intersection.h>
+
+#include "helper/geom-pathstroke.h"
+
+namespace Geom {
+// 2geom/circle-circle.cpp, no header
+int circle_circle_intersection(Point X0, double r0, Point X1, double r1, Point &p0, Point &p1);
+
+/**
+ * Determine the intersection points between a circle C0 and a line defined
+ * by two points, X0 and X1.
+ *
+ * Which intersection point is assigned to p0 or p1 is unspecified, and callers
+ * should not depend on any particular intersection always being assigned to p0.
+ *
+ * Returns:
+ * If the line and circle do not cross, 0 is returned.
+ * If solution(s) exist, 2 is returned, and the results are written to p0 and p1.
+ */
+static int circle_line_intersection(Circle C0, Point X0, Point X1, Point &p0, Point &p1)
+{
+ /* equation of a circle: (x - h)^2 + (y - k)^2 = r^2 */
+ Coord r = C0.ray();
+ Coord h = C0.center()[X];
+ Coord k = C0.center()[Y];
+
+ Coord x0, y0;
+ Coord x1, y1;
+
+ if (are_near(X1[X], X0[X])) {
+ /* slope is undefined (vertical line) */
+ Coord c = X0[X];
+ Coord det = r*r - (c-h)*(c-h);
+
+ /* no intersection */
+ if (det < 0)
+ return 0;
+
+ /* solve for y */
+ y0 = k + std::sqrt(det);
+ y1 = k - std::sqrt(det);
+
+ // x == c (always)
+ x0 = c;
+ x1 = c;
+ } else {
+ /* equation of a line: y = mx + b */
+ Coord m = (X1[Y] - X0[Y]) / (X1[X] - X0[X]);
+ Coord b = X0[Y] - m*X0[X];
+
+ /* obtain quadratic for x: */
+ Coord A = m*m + 1;
+ Coord B = 2*h - 2*b*m + 2*k*m;
+ Coord C = b*b + h*h + k*k - r*r - 2*b*k;
+
+ Coord det = B*B - 4*A*C;
+
+ /* no intersection, circle and line do not cross */
+ if (det < 0)
+ return 0;
+
+ /* solve quadratic */
+ x0 = (B + std::sqrt(det)) / (2*A);
+ x1 = (B - std::sqrt(det)) / (2*A);
+
+ /* substitute the calculated x times to determine the y values */
+ y0 = m*x0 + b;
+ y1 = m*x1 + b;
+ }
+
+ p0 = Point(x0, y0);
+ p1 = Point(x1, y1);
+
+ return 2;
+}
+
+static Point intersection_point(Point origin_a, Point vector_a, Point origin_b, Point vector_b)
+{
+ Coord denom = cross(vector_b, vector_a);
+ if (!are_near(denom,0.)) {
+ Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
+ return origin_a + vector_a*t;
+ }
+ return Point(infinity(), infinity());
+}
+
+/**
+* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
+* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
+*/
+static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
+{
+ D2<SBasis> dM=derivative(curve);
+ if ( are_near(L2sq(dM(t)),0.) ) {
+ dM=derivative(dM);
+ }
+ if ( are_near(L2sq(dM(t)),0.) ) { // try second time
+ dM=derivative(dM);
+ }
+ Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
+ Piecewise<SBasis> k = cross(derivative(unitv),unitv);
+ k = divide(k,dMlength,tol,3);
+ double curv = k(t); // note that this value is signed
+
+ Geom::Point normal = unitTangentAt(curve, t).cw();
+ double radius = 1/curv;
+ Geom::Point center = curve(t) + radius*normal;
+ return Geom::Circle(center, fabs(radius));
+}
+
+}
+
+namespace {
+
+// Join functions may:
+// - inspect any curve of the current path
+// - append any type of curve to the current path
+// - inspect the outgoing path
+//
+// Join functions must:
+// - append the outgoing curve
+// OR
+// - end at outgoing.finalPoint
+
+typedef void join_func(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width);
+
+void bevel_join(Geom::Path& res, Geom::Curve const& outgoing, double /*miter*/, double /*width*/)
+{
+ res.appendNew<Geom::LineSegment>(outgoing.initialPoint());
+ res.append(outgoing);
+}
+
+void round_join(Geom::Path& res, Geom::Curve const& outgoing, double /*miter*/, double width)
+{
+ res.appendNew<Geom::SVGEllipticalArc>(width, width, 0, false, width <= 0, outgoing.initialPoint());
+ res.append(outgoing);
+}
+
+void miter_join_internal(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width, bool clip)
+{
+ Geom::Curve const& incoming = res.back();
+ Geom::Point tang1 = Geom::unitTangentAt(reverse(incoming.toSBasis()), 0.);
+ Geom::Point tang2 = outgoing.unitTangentAt(0);
+ Geom::Point p = Geom::intersection_point(incoming.finalPoint(), tang1, outgoing.initialPoint(), tang2);
+
+ bool satisfied = false;
+ bool inc_ls = res.back_open().degreesOfFreedom() <= 4;
+
+ if (p.isFinite()) {
+ // check size of miter
+ Geom::Point point_on_path = incoming.finalPoint() + Geom::rot90(tang1)*width;
+ satisfied = Geom::distance(p, point_on_path) <= miter * 2.0 * width;
+ if (satisfied) {
+ // miter OK, check to see if we can do a relocation
+ if (inc_ls) {
+ res.setFinal(p);
+ } else {
+ res.appendNew<Geom::LineSegment>(p);
+ }
+ } else if (clip) {
+ // miter needs clipping, find two points
+ Geom::Point bisector_versor = Geom::Line(point_on_path, p).versor();
+ Geom::Point point_limit = point_on_path + miter * 2.0 * width * bisector_versor;
+
+ Geom::Point p1 = Geom::intersection_point(incoming.finalPoint(), tang1, point_limit, bisector_versor.cw());
+ Geom::Point p2 = Geom::intersection_point(outgoing.initialPoint(), tang2, point_limit, bisector_versor.cw());
+
+ if (inc_ls) {
+ res.setFinal(p1);
+ } else {
+ res.appendNew<Geom::LineSegment>(p1);
+ }
+ res.appendNew<Geom::LineSegment>(p2);
+ }
+ }
+
+ res.appendNew<Geom::LineSegment>(outgoing.initialPoint());
+
+ // check if we can do another relocation
+ bool out_ls = outgoing.degreesOfFreedom() <= 4;
+
+ if ( (satisfied || clip) && out_ls) {
+ res.setFinal(outgoing.finalPoint());
+ } else {
+ res.append(outgoing);
+ }
+}
+
+void miter_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width) {
+ miter_join_internal( res, outgoing, miter, width, false );
+}
+
+void miter_clip_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width) {
+ miter_join_internal( res, outgoing, miter, width, true );
+}
+
+Geom::Point pick_solution(Geom::Point points[2], Geom::Point tang2, Geom::Point endPt)
+{
+ Geom::Point sol;
+ if ( dot(tang2,points[0]-endPt) > 0 ) {
+ // points[0] is bad, choose points[1]
+ sol = points[1];
+ } else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1]
+ // points[1] is bad, choose points[0]
+ sol = points[0];
+ } else {
+ // both points are good, choose nearest
+ sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? points[0] : points[1];
+ }
+ return sol;
+}
+
+void extrapolate_join(Geom::Path& res, Geom::Curve const& outgoing, double miter, double width)
+{
+ using namespace Geom;
+
+ Geom::Curve const& incoming = res.back();
+ Geom::Point startPt = incoming.finalPoint();
+ Geom::Point endPt = outgoing.initialPoint();
+ Geom::Point tang1 = Geom::unitTangentAt(reverse(incoming.toSBasis()), 0.);
+ Geom::Point tang2 = outgoing.unitTangentAt(0);
+
+ Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(incoming.toSBasis()), 0.);
+ Geom::Circle circle2 = Geom::touching_circle(outgoing.toSBasis(), 0);
+
+ bool inc_ls = !circle1.center().isFinite();
+ bool out_ls = !circle2.center().isFinite();
+
+ Geom::Point points[2];
+
+ int solutions = 0;
+ Geom::EllipticalArc *arc1 = NULL;
+ Geom::EllipticalArc *arc2 = NULL;
+ Geom::Point sol;
+ Geom::Point p1;
+ Geom::Point p2;
+
+ if (!inc_ls && !out_ls) {
+ // Two circles
+ solutions = Geom::circle_circle_intersection(circle1.center(), circle1.ray(),
+ circle2.center(), circle2.ray(),
+ points[0], points[1]);
+ if (solutions == 2) {
+ sol = pick_solution(points, tang2, endPt);
+ arc1 = circle1.arc(startPt, 0.5*(startPt+sol), sol, true);
+ arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
+ }
+ } else if (inc_ls && !out_ls) {
+ // Line and circle
+ solutions = Geom::circle_line_intersection(circle2, incoming.initialPoint(), incoming.finalPoint(), points[0], points[1]);
+
+ if (solutions == 2) {
+ sol = pick_solution(points, tang2, endPt);
+ arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
+ }
+ } else if (!inc_ls && out_ls) {
+ // Circle and line
+ solutions = Geom::circle_line_intersection(circle1, outgoing.initialPoint(), outgoing.finalPoint(), points[0], points[1]);
+
+ if (solutions == 2) {
+ sol = pick_solution(points, tang2, endPt);
+ arc1 = circle1.arc(startPt, 0.5*(sol+startPt), sol, true);
+ }
+ }
+
+ if (solutions != 2)
+ // no solutions available, fall back to miter
+ return miter_clip_join(res, outgoing, miter, width);
+
+ // We have a solution, thus sol is defined.
+ p1 = sol;
+
+ // See if we need to clip. Miter length is measured along a circular arc that is tangent to the
+ // bisector of the incoming and out going angles and passes through the end point (sol) of the
+ // line join.
+
+ // Center of circle is intersection of a line orthogonal to bisector and a line bisecting
+ // a chord connecting the path end point (point_on_path) and the join end point (sol).
+ Geom::Point point_on_path = startPt + Geom::rot90(tang1)*width;
+ Geom::Line bisector = make_angle_bisector_line(startPt, point_on_path, endPt);
+ Geom::Line ortho = make_orthogonal_line(point_on_path, bisector);
+
+ Geom::LineSegment chord(point_on_path, sol);
+ Geom::Line bisector_chord = make_bisector_line(chord);
+
+ Geom::Line limit_line;
+ double miter_limit = 2.0 * width * miter;
+ bool clipped = false;
+
+ if (are_parallel(bisector_chord, ortho)) {
+ // No intersection (can happen if curvatures are equal but opposite)
+ if (Geom::distance(point_on_path, sol) > miter_limit) {
+ clipped = true;
+ Geom::Point limit_point = point_on_path + miter_limit * bisector.versor();
+ limit_line = make_parallel_line( limit_point, ortho );
+ }
+ } else {
+ Geom::Point center =
+ Geom::intersection_point( bisector_chord.pointAt(0), bisector_chord.versor(),
+ ortho.pointAt(0), ortho.versor() );
+ Geom::Coord radius = distance(center, point_on_path);
+ Geom::Circle circle_center(center, radius);
+
+ double limit_angle = miter_limit / radius;
+
+ Geom::Ray start_ray(center, point_on_path);
+ Geom::Ray end_ray(center, sol);
+ Geom::Line limit_line(center, 0); // Angle set below
+
+ if (Geom::cross(start_ray.versor(), end_ray.versor()) > 0) {
+ limit_line.setAngle(start_ray.angle() - limit_angle);
+ } else {
+ limit_line.setAngle(start_ray.angle() + limit_angle);
+ }
+
+ Geom::EllipticalArc *arc_center = circle_center.arc(point_on_path, 0.5*(point_on_path + sol), sol, true);
+ if (arc_center && arc_center->sweepAngle() > limit_angle) {
+ // We need to clip
+ clipped = true;
+
+ if (!inc_ls) {
+ // Incoming circular
+ solutions = Geom::circle_line_intersection(circle1, limit_line.pointAt(0), limit_line.pointAt(1), points[0], points[1]);
+
+ if (solutions == 2) {
+ p1 = pick_solution(points, tang2, endPt);
+ delete arc1;
+ arc1 = circle1.arc(startPt, 0.5*(p1+startPt), p1, true);
+ }
+ } else {
+ p1 = Geom::intersection_point(startPt, tang1, limit_line.pointAt(0), limit_line.versor());
+ }
+
+ if (!out_ls) {
+ // Outgoing circular
+ solutions = Geom::circle_line_intersection(circle2, limit_line.pointAt(0), limit_line.pointAt(1), points[0], points[1]);
+
+ if (solutions == 2) {
+ p2 = pick_solution(points, tang1, endPt);
+ delete arc2;
+ arc2 = circle2.arc(p2, 0.5*(p2+endPt), endPt, true);
+ }
+ } else {
+ p2 = Geom::intersection_point(endPt, tang2, limit_line.pointAt(0), limit_line.versor());
+ }
+ }
+ }
+
+ // Add initial
+ if (arc1) {
+ res.append(*arc1);
+ } else {
+ // Straight line segment: move last point
+ res.setFinal(p1);
+ }
+
+ if (clipped) {
+ res.appendNew<Geom::LineSegment>(p2);
+ }
+
+ // Add outgoing
+ if (arc2) {
+ res.append(*arc2);
+ res.append(outgoing);
+ } else {
+ // Straight line segment:
+ res.appendNew<Geom::LineSegment>(outgoing.finalPoint());
+ }
+
+ delete arc1;
+ delete arc2;
+}
+
+void join_inside(Geom::Path& res, Geom::Curve const& outgoing)
+{
+ Geom::Curve const& incoming = res.back_open();
+ Geom::Crossings cross = Geom::crossings(incoming, outgoing);
+
+ if (!cross.empty()) {
+ // yeah if we could avoid allocing that'd be great
+ Geom::Curve *d1 = incoming.portion(0., cross[0].ta);
+ res.erase_last();
+ res.append(*d1);
+ delete d1;
+
+ Geom::Curve *d2 = outgoing.portion(cross[0].tb, 1.);
+ res.setFinal(d2->initialPoint());
+ res.append(*d2);
+ delete d2;
+ } else {
+ res.appendNew<Geom::LineSegment>(outgoing.initialPoint());
+ res.append(outgoing);
+ }
+}
+
+bool decide(Geom::Curve const& incoming, Geom::Curve const& outgoing)
+{
+ Geom::Point tang1 = Geom::unitTangentAt(reverse(incoming.toSBasis()), 0.);
+ Geom::Point tang2 = outgoing.unitTangentAt(0.);
+ return (Geom::cross(tang1, tang2) < 0);
+}
+
+void outline_helper(Geom::Path& res, Geom::Path const& to_add, double width, bool on_outside, double miter, Inkscape::LineJoinType join)
+{
+ if (res.size() == 0 || to_add.size() == 0)
+ return;
+
+ Geom::Curve const& outgoing = to_add[0];
+ if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) {
+ // if the points are /that/ close, just ignore this one
+ res.setFinal(outgoing.initialPoint());
+ res.append(outgoing);
+ return;
+ }
+
+ if (on_outside) {
+ join_func *jf;
+ switch (join) {
+ case Inkscape::JOIN_BEVEL:
+ jf = &bevel_join;
+ break;
+ case Inkscape::JOIN_ROUND:
+ jf = &round_join;
+ break;
+ case Inkscape::JOIN_EXTRAPOLATE:
+ jf = &extrapolate_join;
+ break;
+ case Inkscape::JOIN_MITER_CLIP:
+ jf = &miter_clip_join;
+ break;
+ default:
+ jf = &miter_join;
+ }
+ jf(res, outgoing, miter, width);
+ } else {
+ join_inside(res, outgoing);
+ }
+}
+
+// Offsetting a line segment is mathematically stable and quick to do
+Geom::LineSegment offset_line(Geom::LineSegment const& l, double width)
+{
+ Geom::Point tang1 = Geom::rot90(l.unitTangentAt(0));
+ Geom::Point tang2 = Geom::rot90(unitTangentAt(reverse(l.toSBasis()), 0.));
+
+ Geom::Point start = l.initialPoint() + tang1 * width;
+ Geom::Point end = l.finalPoint() - tang2 * width;
+
+ return Geom::LineSegment(start, end);
+}
+
+void get_cubic_data(Geom::CubicBezier const& bez, double time, double& len, double& rad)
+{
+ // get derivatives
+ std::vector<Geom::Point> derivs = bez.pointAndDerivatives(time, 3);
+
+ Geom::Point der1 = derivs[1]; // first deriv (tangent vector)
+ Geom::Point der2 = derivs[2]; // second deriv (tangent's tangent)
+ double l = Geom::L2(der1); // length
+
+ len = rad = 0;
+
+ // TODO: we might want to consider using Geom::touching_circle to determine the
+ // curvature radius here. Less code duplication, but slower
+
+ if (Geom::are_near(l, 0, 1e-4)) {
+ l = Geom::L2(der2);
+ Geom::Point der3 = derivs.at(3); // try second time
+ if (Geom::are_near(l, 0, 1e-4)) {
+ l = Geom::L2(der3);
+ if (Geom::are_near(l, 0)) {
+ return; // this isn't a segment...
+ }
+ rad = 1e8;
+ } else {
+ rad = -l * (Geom::dot(der2, der2) / Geom::cross(der3, der2));
+ }
+ } else {
+ rad = -l * (Geom::dot(der1, der1) / Geom::cross(der2, der1));
+ }
+ len = l;
+}
+
+void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, double tol, size_t levels)
+{
+ 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;
+ if (!Geom::are_near(end_rad, 0))
+ end_off += width / end_rad;
+ start_off *= start_len;
+ end_off *= end_len;
+ // --------
+
+ Geom::Point mid1_new = start_normal.ccw()*start_off;
+ mid1_new = Geom::Point(start_new[X] + mid1_new[X]/3., start_new[Y] + mid1_new[Y]/3.);
+ Geom::Point mid2_new = end_normal.ccw()*end_off;
+ 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);
+
+ // reached maximum recursive depth
+ // don't bother with any more correction
+ if (levels == 0) {
+ p.append(c, Geom::Path::STITCH_DISCONTINUOUS);
+ 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);
+
+ if (err < tol) {
+ if (Geom::are_near(start_new, p.finalPoint())) {
+ p.setFinal(start_new); // if it isn't near, we throw
+ }
+
+ // we're good, curve is accurate enough
+ p.append(c);
+ return;
+ } else {
+ // split the curve in two
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> s = bez.subdivide(.5);
+ offset_cubic(p, s.first, width, tol, levels - 1);
+ offset_cubic(p, s.second, width, tol, levels - 1);
+ }
+}
+
+void offset_quadratic(Geom::Path& p, Geom::QuadraticBezier const& bez, double width, double tol, size_t levels)
+{
+ // cheat
+ // it's faster
+ // seriously
+ std::vector<Geom::Point> points = bez.points();
+ Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
+ Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
+ Geom::CubicBezier cub = Geom::CubicBezier(points[0], b1, b2, points[2]);
+ offset_cubic(p, cub, width, tol, levels);
+}
+
+void offset_curve(Geom::Path& res, Geom::Curve const* current, double width)
+{
+ double const tolerance = 0.005;
+ size_t levels = 8;
+
+ if (current->isDegenerate()) return; // don't do anything
+
+ // TODO: we can handle SVGEllipticalArc here as well, do that!
+
+ if (Geom::BezierCurve const *b = dynamic_cast<Geom::BezierCurve const*>(current)) {
+ size_t order = b->order();
+ switch (order) {
+ case 1:
+ res.append(offset_line(static_cast<Geom::LineSegment const&>(*current), width));
+ break;
+ case 2: {
+ Geom::QuadraticBezier const& q = static_cast<Geom::QuadraticBezier const&>(*current);
+ offset_quadratic(res, q, width, tolerance, levels);
+ break;
+ }
+ case 3: {
+ Geom::CubicBezier const& cb = static_cast<Geom::CubicBezier const&>(*current);
+ offset_cubic(res, cb, width, tolerance, levels);
+ break;
+ }
+ 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);
+ 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);
+ }
+}
+
+typedef void cap_func(Geom::PathBuilder& res, Geom::Path const& with_dir, Geom::Path const& against_dir, double width);
+
+void flat_cap(Geom::PathBuilder& res, Geom::Path const&, Geom::Path const& against_dir, double)
+{
+ res.lineTo(against_dir.initialPoint());
+}
+
+void round_cap(Geom::PathBuilder& res, Geom::Path const&, Geom::Path const& against_dir, double width)
+{
+ res.arcTo(width / 2., width / 2., 0., true, false, against_dir.initialPoint());
+}
+
+void square_cap(Geom::PathBuilder& res, Geom::Path const& with_dir, Geom::Path const& against_dir, double width)
+{
+ width /= 2.;
+ Geom::Point normal_1 = -Geom::unitTangentAt(Geom::reverse(with_dir.back().toSBasis()), 0.);
+ Geom::Point normal_2 = -against_dir[0].unitTangentAt(0.);
+ res.lineTo(with_dir.finalPoint() + normal_1*width);
+ res.lineTo(against_dir.initialPoint() + normal_2*width);
+ res.lineTo(against_dir.initialPoint());
+}
+
+void peak_cap(Geom::PathBuilder& res, Geom::Path const& with_dir, Geom::Path const& against_dir, double width)
+{
+ width /= 2.;
+ Geom::Point normal_1 = -Geom::unitTangentAt(Geom::reverse(with_dir.back().toSBasis()), 0.);
+ Geom::Point normal_2 = -against_dir[0].unitTangentAt(0.);
+ Geom::Point midpoint = ((with_dir.finalPoint() + normal_1*width) + (against_dir.initialPoint() + normal_2*width)) * 0.5;
+ res.lineTo(midpoint);
+ res.lineTo(against_dir.initialPoint());
+}
+
+} // namespace
+
+namespace Inkscape {
+
+Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join, LineCapType butt)
+{
+ 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.reverse(), width/2., miter, join);
+
+ res.moveTo(with_dir[0].initialPoint());
+ res.append(with_dir);
+
+ cap_func *cf;
+ switch (butt) {
+ case BUTT_ROUND:
+ cf = &round_cap;
+ break;
+ case BUTT_SQUARE:
+ cf = &square_cap;
+ break;
+ case BUTT_PEAK:
+ cf = &peak_cap;
+ break;
+ default:
+ cf = &flat_cap;
+ }
+
+ // glue caps
+ if (!input.closed()) {
+ cf(res, with_dir, against_dir, width);
+ } else {
+ res.closePath();
+ res.moveTo(against_dir.initialPoint());
+ }
+
+ res.append(against_dir);
+
+ if (!input.closed()) {
+ cf(res, against_dir, with_dir, width);
+ }
+
+ res.closePath();
+ res.flush();
+ return res.peek();
+}
+
+Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join)
+{
+ Geom::Path res;
+ if (input.size() == 0) return res;
+
+ Geom::Point tang1 = input[0].unitTangentAt(0);
+ Geom::Point start = input.initialPoint() + tang1 * width;
+ Geom::Path temp;
+
+ 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();
+ for (size_t u = 0; u < k; u += 2) {
+ temp = Geom::Path();
+
+ offset_curve(temp, &input[u], width);
+
+ // on the first run through, there isn't a join
+ if (u == 0) {
+ res.append(temp);
+ } else {
+ bool on_outside = decide(input[u-1], input[u]);
+ outline_helper(res, temp, width, on_outside, miter, join);
+ if (temp.size() > 0)
+ res.insert(res.end(), ++temp.begin(), temp.end());
+ }
+
+ // odd number of paths
+ if (u < k - 1) {
+ temp = Geom::Path();
+ offset_curve(temp, &input[u+1], width);
+ bool on_outside = decide(input[u], input[u+1]);
+ outline_helper(res, temp, width, on_outside, miter, join);
+ if (temp.size() > 0)
+ res.insert(res.end(), ++temp.begin(), temp.end());
+ }
+ }
+
+ if (input.closed()) {
+ Geom::Curve const &c1 = res.back();
+ Geom::Curve const &c2 = res.front();
+ temp = Geom::Path();
+ temp.append(c1);
+ Geom::Path temp2;
+ temp2.append(c2);
+ bool on_outside = decide(input.back(), input.front());
+ outline_helper(temp, temp2, width, on_outside, miter, join);
+ res.erase(res.begin());
+ res.erase_last();
+ //
+ res.append(temp);
+ res.close();
+ }
+
+ return res;
+}
+
+} // namespace Inkscape
+
+/*
+ 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:encoding=utf-8 :
diff --git a/src/helper/geom-pathstroke.h b/src/helper/geom-pathstroke.h
new file mode 100644
index 000000000..0cfb9f817
--- /dev/null
+++ b/src/helper/geom-pathstroke.h
@@ -0,0 +1,58 @@
+#ifndef INKSCAPE_HELPER_PATH_STROKE_H
+#define INKSCAPE_HELPER_PATH_STROKE_H
+
+/* Author:
+ * Liam P. White
+ *
+ * Copyright (C) 2014-2015 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+namespace Inkscape {
+
+enum LineJoinType {
+ JOIN_BEVEL,
+ JOIN_ROUND,
+ JOIN_MITER,
+ JOIN_MITER_CLIP,
+ JOIN_EXTRAPOLATE,
+};
+
+enum LineCapType {
+ BUTT_FLAT,
+ BUTT_ROUND,
+ BUTT_SQUARE,
+ BUTT_PEAK, // ?
+};
+
+/**
+ * Offset the input path by @a width.
+ * Joins may behave oddly if the width is negative.
+ *
+ * @param input
+ * @param width Amount to offset.
+ * @param miter Miter limit. Only used with JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
+ * @param join
+ */
+Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL);
+
+Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT);
+
+} // namespace Inkscape
+
+#endif // INKSCAPE_HELPER_PATH_STROKE_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 :
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index 6eba6e949..91689375f 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -556,6 +556,55 @@ pathv_to_linear( Geom::PathVector const &pathv, double /*maxdisp*/)
return output;
}
+/*
+ * Converts all segments in all paths to Geom Cubic bezier.
+ * This is used in lattice2 LPE, maybe is better move the function to the effect
+ * But maybe could be usable by others, so i put here.
+ * The straight curve part is needed as it for the effect to work apropiately
+ */
+Geom::PathVector
+pathv_to_cubicbezier( Geom::PathVector const &pathv)
+{
+ Geom::PathVector output;
+ double cubicGap = 0.01;
+ for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) {
+ output.push_back( Geom::Path() );
+ output.back().start( pit->initialPoint() );
+ output.back().close( pit->closed() );
+ bool end_open = false;
+ if (pit->closed()) {
+ const Geom::Curve &closingline = pit->back_closed();
+ if (!are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ end_open = true;
+ }
+ }
+ Geom::Path pitCubic = (Geom::Path)(*pit);
+ if(end_open && pit->closed()){
+ pitCubic.close(false);
+ pitCubic.appendNew<Geom::LineSegment>( pitCubic.initialPoint() );
+ pitCubic.close(true);
+ }
+ for (Geom::Path::const_iterator cit = pitCubic.begin(); cit != pitCubic.end_open(); ++cit) {
+ if (is_straight_curve(*cit)) {
+ Geom::CubicBezier b(cit->initialPoint(), cit->pointAt(0.3334) + Geom::Point(cubicGap,cubicGap), cit->finalPoint(), cit->finalPoint());
+ output.back().append(b);
+ } else {
+ Geom::BezierCurve const *curve = dynamic_cast<Geom::BezierCurve const *>(&*cit);
+ if (curve && curve->order() == 3) {
+ Geom::CubicBezier b((*curve)[0], (*curve)[1], (*curve)[2], (*curve)[3]);
+ output.back().append(b);
+ } else {
+ // convert all other curve types to cubicbeziers
+ Geom::Path cubicbezier_path = Geom::cubicbezierpath_from_sbasis(cit->toSBasis(), 0.1);
+ output.back().append(cubicbezier_path);
+ }
+ }
+ }
+ }
+
+ return output;
+}
+
// The next routine is modified from curv4_div::recursive_bezier from file agg_curves.cpp
//----------------------------------------------------------------------------
// Anti-Grain Geometry (AGG) - Version 2.5
diff --git a/src/helper/geom.h b/src/helper/geom.h
index caff95733..3232d9fd5 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -27,6 +27,7 @@ void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geo
Geom::PathVector pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv );
Geom::PathVector pathv_to_linear( Geom::PathVector const &pathv, double maxdisp );
+Geom::PathVector pathv_to_cubicbezier( Geom::PathVector const &pathv);
void recursive_bezier4(const double x1, const double y1, const double x2, const double y2,
const double x3, const double y3, const double x4, const double y4,
std::vector<Geom::Point> &pointlist,
diff --git a/src/inkgc/CMakeLists.txt b/src/inkgc/CMakeLists.txt
index 22dd464e1..a4b96d5ee 100644
--- a/src/inkgc/CMakeLists.txt
+++ b/src/inkgc/CMakeLists.txt
@@ -1,11 +1,10 @@
-
set(libgc_SRC
gc.cpp
-
+
# -------
# Headers
gc-alloc.h
- gc-anchored.h
+ ../gc-anchored.h
gc-core.h
gc-managed.h
gc-soft-ptr.h
diff --git a/src/knotholder.cpp b/src/knotholder.cpp
index f46daa09e..a2d1cf017 100644
--- a/src/knotholder.cpp
+++ b/src/knotholder.cpp
@@ -165,7 +165,8 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state)
if (saved_item) { //increasingly aggressive sanity checks
if (saved_item->document) {
- if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) {
+ // enum is unsigned so can't be less than SP_VERB_INVALID
+ if (object_verb <= SP_VERB_LAST) {
DocumentUndo::done(saved_item->document, object_verb,
_("Change handle"));
}
diff --git a/src/libcroco/cr-statement.c b/src/libcroco/cr-statement.c
index fb8df867f..4666f26ec 100644
--- a/src/libcroco/cr-statement.c
+++ b/src/libcroco/cr-statement.c
@@ -2011,7 +2011,7 @@ cr_statement_ruleset_set_sel_list (CRStatement * a_this,
* cr_statement_ruleset_get_declarations:
*
*@a_this: the current instance of #CRStatement.
- *@a_decl_list: out parameter. A pointer to the the returned
+ *@a_decl_list: out parameter. A pointer to the returned
*list of declaration. Must not be NULL.
*
*Gets a pointer to the list of declaration contained
diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp
index c0bfe9428..4f63007e7 100644
--- a/src/livarot/ShapeMisc.cpp
+++ b/src/livarot/ShapeMisc.cpp
@@ -371,9 +371,9 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int /*wildPath*
int searchInd = 0;
int lastPtUsed = 0;
+ int parentContour=-1;
do
{
- int parentContour=-1;
int childEdge = -1;
bool foundChild = false;
int startBord = -1;
@@ -389,8 +389,10 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int /*wildPath*
if (askTo < 0 || askTo >= numberOfEdges() ) {
parentContour=-1;
} else {
- parentContour = GPOINTER_TO_INT(swdData[askTo].misc);
- parentContour-=1; // pour compenser le decalage
+ if (getEdge(askTo).prevS >= 0) {
+ parentContour = GPOINTER_TO_INT(swdData[askTo].misc);
+ parentContour-=1; // pour compenser le decalage
+ }
childEdge = getPoint(fi).incidentEdge[FIRST];
}
}
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index c8a02c810..c4b92e579 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -1,4 +1,3 @@
-
set(live_effects_SRC
effect.cpp
lpe-angle_bisector.cpp
@@ -6,6 +5,7 @@ set(live_effects_SRC
lpe-bendpath.cpp
lpe-boolops.cpp
lpe-bounding-box.cpp
+ lpe-bspline.cpp
lpe-circle_3pts.cpp
lpe-circle_with_radius.cpp
lpe-clone-original.cpp
@@ -13,7 +13,7 @@ set(live_effects_SRC
lpe-copy_rotate.cpp
lpe-curvestitch.cpp
lpe-dynastroke.cpp
- lpe-ellipse-5pts.cpp
+ lpe-ellipse_5pts.cpp
lpe-envelope.cpp
lpe-extrude.cpp
lpe-fill-between-many.cpp
@@ -21,8 +21,11 @@ set(live_effects_SRC
lpe-fillet-chamfer.cpp
lpe-gears.cpp
lpe-interpolate.cpp
+ lpe-interpolate_points.cpp
+ lpe-jointype.cpp
lpe-knot.cpp
lpe-lattice.cpp
+ lpe-lattice2.cpp
lpe-line_segment.cpp
lpe-mirror_symmetry.cpp
lpe-offset.cpp
@@ -30,43 +33,43 @@ set(live_effects_SRC
lpe-path_length.cpp
lpe-patternalongpath.cpp
lpe-perp_bisector.cpp
- lpe-perspective_path.cpp
lpe-perspective-envelope.cpp
+ lpe-perspective_path.cpp
lpe-powerstroke.cpp
lpe-recursiveskeleton.cpp
lpe-rough-hatches.cpp
+ lpe-roughen.cpp
lpe-ruler.cpp
lpe-show_handles.cpp
lpe-simplify.cpp
- # lpe-skeleton.cpp
+ lpe-skeleton.cpp
lpe-sketch.cpp
lpe-spiro.cpp
- lpe-roughen.cpp
lpe-tangent_to_curve.cpp
+ lpe-taperstroke.cpp
lpe-test-doEffect-stack.cpp
- lpe-bspline.cpp
lpe-text_label.cpp
- lpe-vonkoch.cpp
lpegroupbbox.cpp
lpeobject-reference.cpp
+ lpe-vonkoch.cpp
lpeobject.cpp
- spiro.cpp
spiro-converters.cpp
+ spiro.cpp
parameter/array.cpp
parameter/bool.cpp
parameter/filletchamferpointarray.cpp
- parameter/parameter.cpp
- parameter/path.cpp
parameter/originalpath.cpp
parameter/originalpatharray.cpp
+ parameter/parameter.cpp
parameter/path-reference.cpp
+ parameter/path.cpp
parameter/point.cpp
parameter/powerstrokepointarray.cpp
parameter/random.cpp
parameter/text.cpp
- paramter/transformedpoint.cpp
parameter/togglebutton.cpp
+ parameter/transformedpoint.cpp
parameter/unit.cpp
parameter/vector.cpp
@@ -80,6 +83,7 @@ set(live_effects_SRC
lpe-bendpath.h
lpe-boolops.h
lpe-bounding-box.h
+ lpe-bspline.h
lpe-circle_3pts.h
lpe-circle_with_radius.h
lpe-clone-original.h
@@ -87,7 +91,7 @@ set(live_effects_SRC
lpe-copy_rotate.h
lpe-curvestitch.h
lpe-dynastroke.h
- lpe-ellipse-5pts.h
+ lpe-ellipse_5pts.h
lpe-envelope.h
lpe-extrude.h
lpe-fill-between-many.h
@@ -95,8 +99,11 @@ set(live_effects_SRC
lpe-fillet-chamfer.h
lpe-gears.h
lpe-interpolate.h
+ lpe-interpolate_points.h
+ lpe-jointype.h
lpe-knot.h
lpe-lattice.h
+ lpe-lattice2.h
lpe-line_segment.h
lpe-mirror_symmetry.h
lpe-offset.h
@@ -104,47 +111,47 @@ set(live_effects_SRC
lpe-path_length.h
lpe-patternalongpath.h
lpe-perp_bisector.h
- lpe-perspective_path.h
lpe-perspective-envelope.h
- lpe-powerstroke.h
+ lpe-perspective_path.h
lpe-powerstroke-interpolators.h
+ lpe-powerstroke.h
lpe-recursiveskeleton.h
lpe-rough-hatches.h
+ lpe-roughen.h
lpe-ruler.h
- lpe-simplify.h
lpe-show_handles.h
+ lpe-simplify.h
lpe-skeleton.h
lpe-sketch.h
lpe-spiro.h
- lpe-roughen.h
lpe-tangent_to_curve.h
+ lpe-taperstroke.h
lpe-test-doEffect-stack.h
- lpe-bspline.h
lpe-text_label.h
lpe-vonkoch.h
lpegroupbbox.h
lpeobject-reference.h
lpeobject.h
- spiro.h
spiro-converters.h
+ spiro.h
parameter/array.h
parameter/bool.h
- parameter/filletchamferpointarray.h
parameter/enum.h
+ parameter/filletchamferpointarray.h
+ parameter/originalpath.h
+ parameter/originalpatharray.h
parameter/parameter.h
parameter/path-reference.h
parameter/path.h
- parameter/originalpath.h
- parameter/originalpatharray.h
parameter/point.h
parameter/powerstrokepointarray.h
parameter/random.h
parameter/text.h
parameter/togglebutton.h
+ parameter/transformedpoint.h
parameter/unit.h
parameter/vector.h
-
)
# add_inkscape_lib(live_effects_LIB "${live_effects_SRC}")
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index 8f0a3ac57..dace45739 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -109,8 +109,6 @@ ink_common_sources += \
live_effects/lpe-fill-between-many.h \
live_effects/lpe-ellipse_5pts.cpp \
live_effects/lpe-ellipse_5pts.h \
- live_effects/pathoutlineprovider.cpp \
- live_effects/pathoutlineprovider.h \
live_effects/lpe-jointype.cpp \
live_effects/lpe-jointype.h \
live_effects/lpe-taperstroke.cpp \
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 827f70749..1da364580 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -363,6 +363,10 @@ Effect::Effect(LivePathEffectObject *lpeobject)
show_orig_path(false),
lpeobj(lpeobject),
concatenate_before_pwd2(false),
+ sp_lpe_item(NULL),
+ defaultUnit("px"),
+ current_zoom(1),
+ sp_curve(NULL),
provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden
is_ready(false) // is automatically set to false if providesOwnFlashPaths() is not overridden
{
@@ -450,7 +454,7 @@ void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/)
void Effect::doOnApply_impl(SPLPEItem const* lpeitem)
{
sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
- defaultUnit = &sp_lpe_item->document->getDisplayUnit()->abbr;
+ defaultUnit = sp_lpe_item->document->getDisplayUnit()->abbr;
/*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
pathvector_before_effect = sp_curve->get_pathvector();*/
doOnApply(lpeitem);
@@ -459,11 +463,13 @@ void Effect::doOnApply_impl(SPLPEItem const* lpeitem)
void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
{
sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
- defaultUnit = &sp_lpe_item->document->getDisplayUnit()->abbr;
+ defaultUnit = sp_lpe_item->document->getDisplayUnit()->abbr;
//printf("(SPLPEITEM*) %p\n", sp_lpe_item);
- sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
- pathvector_before_effect = sp_curve->get_pathvector();
-
+ SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item);
+ if(shape){
+ sp_curve = shape->getCurve();
+ pathvector_before_effect = sp_curve->get_pathvector();
+ }
doBeforeEffect(lpeitem);
}
diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h
index 7da76b267..ac1f0b8dc 100644
--- a/src/live_effects/effect.h
+++ b/src/live_effects/effect.h
@@ -159,7 +159,7 @@ protected:
bool concatenate_before_pwd2;
SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
- Glib::ustring const * defaultUnit; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
+ Glib::ustring defaultUnit; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
double current_zoom;
std::vector<Geom::Point> selectedNodesPoints;
SPCurve * sp_curve;
diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp
index 2bed90139..ecbfef76a 100644
--- a/src/live_effects/lpe-bspline.cpp
+++ b/src/live_effects/lpe-bspline.cpp
@@ -1,88 +1,57 @@
/*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <gtkmm.h>
-
-#if WITH_GLIBMM_2_32
-# include <glibmm/threads.h>
-#endif
-
-#include <glib.h>
-#include <glibmm/i18n.h>
-
-
-#include "display/curve.h"
-#include <2geom/bezier-curve.h>
-#include <2geom/point.h>
-#include "helper/geom-curves.h"
#include "live_effects/lpe-bspline.h"
-#include "live_effects/lpeobject.h"
-#include "live_effects/parameter/parameter.h"
#include "ui/widget/scalar.h"
-#include "xml/repr.h"
-#include "svg/svg.h"
+#include "display/curve.h"
+#include "helper/geom-curves.h"
#include "sp-path.h"
-#include "style.h"
-#include "document-private.h"
-#include "document.h"
-#include "document-undo.h"
-#include "verbs.h"
-#include "sp-lpe-item.h"
-#include "sp-namedview.h"
-#include "display/sp-canvas.h"
-#include <typeinfo>
-#include <vector>
-#include "util/units.h"
-// For handling un-continuous paths:
-#include "message-stack.h"
-#include "inkscape.h"
-
-using Inkscape::DocumentUndo;
+#include "svg/svg.h"
+#include "xml/repr.h"
+// TODO due to internal breakage in glibmm headers, this must be last:
+#include <glibmm/i18n.h>
namespace Inkscape {
namespace LivePathEffect {
-const double handleCubicGap = 0.01;
-const double noPower = 0.0;
-const double defaultStartPower = 0.3334;
-const double defaultEndPower = 0.6667;
+const double HANDLE_CUBIC_GAP = 0.01;
+const double NO_POWER = 0.0;
+const double DEFAULT_START_POWER = 0.3334;
+const double DEFAULT_END_POWER = 0.6667;
LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject)
: Effect(lpeobject),
- // initialise your parameters here:
- //testpointA(_("Test Point A"), _("Test A"), "ptA", &wr, this,
- //Geom::Point(100,100)),
steps(_("Steps with CTRL:"), _("Change number of steps with CTRL pressed"), "steps", &wr, this, 2),
- ignoreCusp(_("Ignore cusp nodes"), _("Change ignoring cusp nodes"), "ignoreCusp", &wr, this, true),
- onlySelected(_("Change only selected nodes"), _("Change only selected nodes"), "onlySelected", &wr, this, false),
- showHelper(_("Show helper paths"), _("Show helper paths"), "showHelper", &wr, this, false),
- weight(_("Change weight:"), _("Change weight of the effect"), "weight", &wr, this, defaultStartPower)
+ helper_size(_("Helper size:"), _("Helper size"), "helper_size", &wr, this, 0),
+ ignore_cusp(_("Ignore cusp nodes"), _("Change ignoring cusp nodes"), "ignore_cusp", &wr, this, true),
+ only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false),
+ weight(_("Change weight:"), _("Change weight of the effect"), "weight", &wr, this, DEFAULT_START_POWER)
{
- registerParameter(dynamic_cast<Parameter *>(&weight));
- registerParameter(dynamic_cast<Parameter *>(&steps));
- registerParameter(dynamic_cast<Parameter *>(&ignoreCusp));
- registerParameter(dynamic_cast<Parameter *>(&onlySelected));
- registerParameter(dynamic_cast<Parameter *>(&showHelper));
+ registerParameter(&weight);
+ registerParameter(&steps);
+ registerParameter(&helper_size);
+ registerParameter(&ignore_cusp);
+ registerParameter(&only_selected);
- weight.param_set_range(noPower, 1);
+ weight.param_set_range(NO_POWER, 1);
weight.param_set_increments(0.1, 0.1);
weight.param_set_digits(4);
steps.param_set_range(1, 10);
steps.param_set_increments(1, 1);
steps.param_set_digits(0);
+
+ helper_size.param_set_range(0.0, 999.0);
+ helper_size.param_set_increments(5, 5);
+ helper_size.param_set_digits(2);
}
LPEBSpline::~LPEBSpline() {}
void LPEBSpline::doBeforeEffect (SPLPEItem const* /*lpeitem*/)
{
- if(!hp.empty()){
+ if(!hp.empty()) {
hp.clear();
}
}
@@ -100,32 +69,32 @@ void LPEBSpline::doOnApply(SPLPEItem const* lpeitem)
void LPEBSpline::doEffect(SPCurve *curve)
{
- if (curve->get_segment_count() < 1){
+ if (curve->get_segment_count() < 1) {
return;
}
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
+
curve->reset();
- double radiusHelperNodes = 6.0;
- radiusHelperNodes /= current_zoom;
- radiusHelperNodes = Inkscape::Util::Quantity::convert(radiusHelperNodes, "px", *defaultUnit);
+
for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
path_it != original_pathv.end(); ++path_it) {
- if (path_it->empty())
+ if (path_it->empty()) {
continue;
-
+ }
+ hp.push_back(*path_it);
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();
- SPCurve *nCurve = new SPCurve();
+ SPCurve *curve_n = new SPCurve();
Geom::Point previousNode(0, 0);
Geom::Point node(0, 0);
- Geom::Point pointAt1(0, 0);
- Geom::Point pointAt2(0, 0);
- Geom::Point nextPointAt1(0, 0);
- Geom::D2<Geom::SBasis> SBasisIn;
- Geom::D2<Geom::SBasis> SBasisOut;
- Geom::D2<Geom::SBasis> SBasisHelper;
+ Geom::Point point_at1(0, 0);
+ Geom::Point point_at2(0, 0);
+ Geom::Point next_point_at1(0, 0);
+ Geom::D2<Geom::SBasis> sbasis_in;
+ Geom::D2<Geom::SBasis> sbasis_out;
+ Geom::D2<Geom::SBasis> sbasis_helper;
Geom::CubicBezier const *cubic = NULL;
if (path_it->closed()) {
// if the path is closed, maybe we have to stop a bit earlier because the
@@ -141,27 +110,27 @@ void LPEBSpline::doEffect(SPCurve *curve)
curve_endit = path_it->end_open();
}
}
- nCurve->moveto(curve_it1->initialPoint());
+ curve_n->moveto(curve_it1->initialPoint());
while (curve_it1 != curve_endit) {
SPCurve *in = new SPCurve();
in->moveto(curve_it1->initialPoint());
in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
- SBasisIn = in->first_segment()->toSBasis();
+ sbasis_in = in->first_segment()->toSBasis();
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- pointAt1 = SBasisIn.valueAt(defaultStartPower);
+ point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ point_at1 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
}
if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
- pointAt2 = SBasisIn.valueAt(defaultEndPower);
+ point_at2 = sbasis_in.valueAt(DEFAULT_END_POWER);
} else {
- pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ point_at2 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
- pointAt2 = in->first_segment()->finalPoint();
+ point_at1 = in->first_segment()->initialPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
in->reset();
delete in;
@@ -171,14 +140,14 @@ void LPEBSpline::doEffect(SPCurve *curve)
out->lineto(curve_it2->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
if (cubic) {
- SBasisOut = out->first_segment()->toSBasis();
+ sbasis_out = out->first_segment()->toSBasis();
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- nextPointAt1 = SBasisIn.valueAt(defaultStartPower);
+ next_point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ next_point_at1 = sbasis_out.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
}
} else {
- nextPointAt1 = out->first_segment()->initialPoint();
+ next_point_at1 = out->first_segment()->initialPoint();
}
out->reset();
delete out;
@@ -187,14 +156,14 @@ void LPEBSpline::doEffect(SPCurve *curve)
SPCurve *start = new SPCurve();
start->moveto(path_it->begin()->initialPoint());
start->lineto(path_it->begin()->finalPoint());
- Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
- SPCurve *lineHelper = new SPCurve();
+ Geom::D2<Geom::SBasis> sbasis_start = start->first_segment()->toSBasis();
+ SPCurve *line_helper = new SPCurve();
cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
if (cubic) {
- lineHelper->moveto(SBasisStart.valueAt(
+ line_helper->moveto(sbasis_start.valueAt(
Geom::nearest_point((*cubic)[1], *start->first_segment())));
} else {
- lineHelper->moveto(start->first_segment()->initialPoint());
+ line_helper->moveto(start->first_segment()->initialPoint());
}
start->reset();
delete start;
@@ -202,69 +171,69 @@ void LPEBSpline::doEffect(SPCurve *curve)
SPCurve *end = new SPCurve();
end->moveto(curve_it1->initialPoint());
end->lineto(curve_it1->finalPoint());
- Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ Geom::D2<Geom::SBasis> sbasis_end = end->first_segment()->toSBasis();
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
- lineHelper->lineto(SBasisEnd.valueAt(
+ line_helper->lineto(sbasis_end.valueAt(
Geom::nearest_point((*cubic)[2], *end->first_segment())));
} else {
- lineHelper->lineto(end->first_segment()->finalPoint());
+ line_helper->lineto(end->first_segment()->finalPoint());
}
end->reset();
delete end;
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- node = SBasisHelper.valueAt(0.5);
- nCurve->curveto(pointAt1, pointAt2, node);
- nCurve->move_endpoints(node, node);
+ sbasis_helper = line_helper->first_segment()->toSBasis();
+ line_helper->reset();
+ delete line_helper;
+ node = sbasis_helper.valueAt(0.5);
+ curve_n->curveto(point_at1, point_at2, node);
+ curve_n->move_endpoints(node, node);
} else if ( curve_it2 == curve_endit) {
- nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
- nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
+ curve_n->curveto(point_at1, point_at2, curve_it1->finalPoint());
+ curve_n->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
} else {
- SPCurve *lineHelper = new SPCurve();
- lineHelper->moveto(pointAt2);
- lineHelper->lineto(nextPointAt1);
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
+ SPCurve *line_helper = new SPCurve();
+ line_helper->moveto(point_at2);
+ line_helper->lineto(next_point_at1);
+ sbasis_helper = line_helper->first_segment()->toSBasis();
+ line_helper->reset();
+ delete line_helper;
previousNode = node;
- node = SBasisHelper.valueAt(0.5);
+ node = sbasis_helper.valueAt(0.5);
Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
node = curve_it1->finalPoint();
}
- nCurve->curveto(pointAt1, pointAt2, node);
+ curve_n->curveto(point_at1, point_at2, node);
}
- if(!are_near(node,curve_it1->finalPoint()) && showHelper){
- drawHandle(node, radiusHelperNodes);
+ if(!are_near(node,curve_it1->finalPoint()) && helper_size > 0.0) {
+ drawHandle(node, helper_size);
}
++curve_it1;
++curve_it2;
}
//y cerramos la curva
if (path_it->closed()) {
- nCurve->closepath_current();
+ curve_n->closepath_current();
}
- curve->append(nCurve, false);
- nCurve->reset();
- delete nCurve;
+ curve->append(curve_n, false);
+ curve_n->reset();
+ delete curve_n;
}
- if(showHelper){
+ if(helper_size > 0.0) {
Geom::PathVector const pathv = curve->get_pathvector();
- hp.push_back(pathv[0]);
+ hp.push_back(pathv[0]);
}
}
void
-LPEBSpline::drawHandle(Geom::Point p, double radiusHelperNodes)
+LPEBSpline::drawHandle(Geom::Point p, double helper_size)
{
char const * svgd = "M 1,0.5 A 0.5,0.5 0 0 1 0.5,1 0.5,0.5 0 0 1 0,0.5 0.5,0.5 0 0 1 0.5,0 0.5,0.5 0 0 1 1,0.5 Z";
Geom::PathVector pathv = sp_svg_read_pathv(svgd);
Geom::Affine aff = Geom::Affine();
- aff *= Geom::Scale(radiusHelperNodes);
+ aff *= Geom::Scale(helper_size);
pathv *= aff;
- pathv += p - Geom::Point(0.5*radiusHelperNodes, 0.5*radiusHelperNodes);
+ pathv += p - Geom::Point(0.5*helper_size, 0.5*helper_size);
hp.push_back(pathv[0]);
}
@@ -287,40 +256,40 @@ Gtk::Widget *LPEBSpline::newWidget()
Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
if (param->param_key == "weight") {
Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0));
- Gtk::Button *defaultWeight =
+ Gtk::Button *default_weight =
Gtk::manage(new Gtk::Button(Glib::ustring(_("Default weight"))));
- defaultWeight->signal_clicked()
+ default_weight->signal_clicked()
.connect(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight));
- buttons->pack_start(*defaultWeight, true, true, 2);
- Gtk::Button *makeCusp =
+ buttons->pack_start(*default_weight, true, true, 2);
+ Gtk::Button *make_cusp =
Gtk::manage(new Gtk::Button(Glib::ustring(_("Make cusp"))));
- makeCusp->signal_clicked()
+ make_cusp->signal_clicked()
.connect(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp));
- buttons->pack_start(*makeCusp, true, true, 2);
+ buttons->pack_start(*make_cusp, true, true, 2);
vbox->pack_start(*buttons, true, true, 2);
}
if (param->param_key == "weight" || param->param_key == "steps") {
- Inkscape::UI::Widget::Scalar *widgRegistered =
+ Inkscape::UI::Widget::Scalar *widg_registered =
Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
- widgRegistered->signal_value_changed()
+ widg_registered->signal_value_changed()
.connect(sigc::mem_fun(*this, &LPEBSpline::toWeight));
- widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ widg = dynamic_cast<Gtk::Widget *>(widg_registered);
if (widg) {
- Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
- std::vector< Gtk::Widget* > childList = scalarParameter->get_children();
- Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
- entryWidg->set_width_chars(6);
+ Gtk::HBox * hbox_weight_steps = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > childList = hbox_weight_steps->get_children();
+ Gtk::Entry* entry_widget = dynamic_cast<Gtk::Entry *>(childList[1]);
+ entry_widget->set_width_chars(6);
}
}
- if (param->param_key == "onlySelected") {
- Gtk::CheckButton *widgRegistered =
+ if (param->param_key == "only_selected") {
+ Gtk::CheckButton *widg_registered =
Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
- widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ widg = dynamic_cast<Gtk::Widget *>(widg_registered);
}
- if (param->param_key == "ignoreCusp") {
- Gtk::CheckButton *widgRegistered =
+ if (param->param_key == "ignore_cusp") {
+ Gtk::CheckButton *widg_registered =
Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
- widg = dynamic_cast<Gtk::Widget *>(widgRegistered);
+ widg = dynamic_cast<Gtk::Widget *>(widg_registered);
}
Glib::ustring *tip = param->param_getTooltip();
if (widg) {
@@ -341,12 +310,12 @@ Gtk::Widget *LPEBSpline::newWidget()
void LPEBSpline::toDefaultWeight()
{
- changeWeight(defaultStartPower);
+ changeWeight(DEFAULT_START_POWER);
}
void LPEBSpline::toMakeCusp()
{
- changeWeight(noPower);
+ changeWeight(NO_POWER);
}
void LPEBSpline::toWeight()
@@ -354,20 +323,22 @@ void LPEBSpline::toWeight()
changeWeight(weight);
}
-void LPEBSpline::changeWeight(double weightValue)
+void LPEBSpline::changeWeight(double weight_ammount)
{
- SPPath *path = SP_PATH(sp_lpe_item);
- SPCurve *curve = path->get_curve_for_edit();
- LPEBSpline::doBSplineFromWidget(curve, weightValue);
- gchar *str = sp_svg_write_path(curve->get_pathvector());
- path->getRepr()->setAttribute("inkscape:original-d", str);
+ SPPath *path = dynamic_cast<SPPath *>(sp_lpe_item);
+ if(path) {
+ SPCurve *curve = path->get_curve_for_edit();
+ doBSplineFromWidget(curve, weight_ammount);
+ gchar *str = sp_svg_write_path(curve->get_pathvector());
+ path->getRepr()->setAttribute("inkscape:original-d", str);
+ }
}
-void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
+void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weight_ammount)
{
using Geom::X;
using Geom::Y;
-
+
if (curve->get_segment_count() < 1)
return;
// Make copy of old path as it is changed during processing
@@ -377,20 +348,20 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
path_it != original_pathv.end(); ++path_it) {
- if (path_it->empty()){
+ 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();
- SPCurve *nCurve = new SPCurve();
- Geom::Point pointAt0(0, 0);
- Geom::Point pointAt1(0, 0);
- Geom::Point pointAt2(0, 0);
- Geom::Point pointAt3(0, 0);
- Geom::D2<Geom::SBasis> SBasisIn;
- Geom::D2<Geom::SBasis> SBasisOut;
+ SPCurve *curve_n = new SPCurve();
+ Geom::Point point_at0(0, 0);
+ Geom::Point point_at1(0, 0);
+ Geom::Point point_at2(0, 0);
+ Geom::Point point_at3(0, 0);
+ Geom::D2<Geom::SBasis> sbasis_in;
+ Geom::D2<Geom::SBasis> sbasis_out;
Geom::CubicBezier const *cubic = NULL;
if (path_it->closed()) {
// if the path is closed, maybe we have to stop a bit earlier because the
@@ -406,120 +377,120 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
curve_endit = path_it->end_open();
}
}
- nCurve->moveto(curve_it1->initialPoint());
+ curve_n->moveto(curve_it1->initialPoint());
while (curve_it1 != curve_endit) {
SPCurve *in = new SPCurve();
in->moveto(curve_it1->initialPoint());
in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- pointAt0 = in->first_segment()->initialPoint();
- pointAt3 = in->first_segment()->finalPoint();
- SBasisIn = in->first_segment()->toSBasis();
- if (!onlySelected) {
+ point_at0 = in->first_segment()->initialPoint();
+ point_at3 = in->first_segment()->finalPoint();
+ sbasis_in = in->first_segment()->toSBasis();
+ if (!only_selected) {
if (cubic) {
- if (!ignoreCusp || !Geom::are_near((*cubic)[1], pointAt0)) {
- pointAt1 = SBasisIn.valueAt(weightValue);
- if (weightValue != noPower) {
- pointAt1 =
- Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ if (!ignore_cusp || !Geom::are_near((*cubic)[1], point_at0)) {
+ point_at1 = sbasis_in.valueAt(weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at1 =
+ Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
+ point_at1 = in->first_segment()->initialPoint();
}
- if (!ignoreCusp || !Geom::are_near((*cubic)[2], pointAt3)) {
- pointAt2 = SBasisIn.valueAt(1 - weightValue);
- if (weightValue != noPower) {
- pointAt2 =
- Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ if (!ignore_cusp || !Geom::are_near((*cubic)[2], point_at3)) {
+ point_at2 = sbasis_in.valueAt(1 - weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at2 =
+ Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
}
} else {
- pointAt2 = in->first_segment()->finalPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
} else {
- if (!ignoreCusp && weightValue != noPower) {
- pointAt1 = SBasisIn.valueAt(weightValue);
- if (weightValue != noPower) {
- pointAt1 =
- Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ if (!ignore_cusp && weight_ammount != NO_POWER) {
+ point_at1 = sbasis_in.valueAt(weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at1 =
+ Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
}
- pointAt2 = SBasisIn.valueAt(1 - weightValue);
- if (weightValue != noPower) {
- pointAt2 =
- Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ point_at2 = sbasis_in.valueAt(1 - weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at2 =
+ Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
- pointAt2 = in->first_segment()->finalPoint();
+ point_at1 = in->first_segment()->initialPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
}
} else {
if (cubic) {
- if (!ignoreCusp || !Geom::are_near((*cubic)[1], pointAt0)) {
- if (isNodePointSelected(pointAt0)) {
- pointAt1 = SBasisIn.valueAt(weightValue);
- if (weightValue != noPower) {
- pointAt1 =
- Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ if (!ignore_cusp || !Geom::are_near((*cubic)[1], point_at0)) {
+ if (isNodePointSelected(point_at0)) {
+ point_at1 = sbasis_in.valueAt(weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at1 =
+ Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
}
} else {
- pointAt1 = (*cubic)[1];
+ point_at1 = (*cubic)[1];
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
+ point_at1 = in->first_segment()->initialPoint();
}
- if (!ignoreCusp || !Geom::are_near((*cubic)[2], pointAt3)) {
- if (isNodePointSelected(pointAt3)) {
- pointAt2 = SBasisIn.valueAt(1 - weightValue);
- if (weightValue != noPower) {
- pointAt2 =
- Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ if (!ignore_cusp || !Geom::are_near((*cubic)[2], point_at3)) {
+ if (isNodePointSelected(point_at3)) {
+ point_at2 = sbasis_in.valueAt(1 - weight_ammount);
+ if (weight_ammount != NO_POWER) {
+ point_at2 =
+ Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
}
} else {
- pointAt2 = (*cubic)[2];
+ point_at2 = (*cubic)[2];
}
} else {
- pointAt2 = in->first_segment()->finalPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
} else {
- if (!ignoreCusp && weightValue != noPower) {
- if (isNodePointSelected(pointAt0)) {
- pointAt1 = SBasisIn.valueAt(weightValue);
- pointAt1 =
- Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
+ if (!ignore_cusp && weight_ammount != NO_POWER) {
+ if (isNodePointSelected(point_at0)) {
+ point_at1 = sbasis_in.valueAt(weight_ammount);
+ point_at1 =
+ Geom::Point(point_at1[X] + HANDLE_CUBIC_GAP, point_at1[Y] + HANDLE_CUBIC_GAP);
} else {
- pointAt1 = in->first_segment()->initialPoint();
+ point_at1 = in->first_segment()->initialPoint();
}
- if (isNodePointSelected(pointAt3)) {
- pointAt2 = SBasisIn.valueAt(weightValue);
- pointAt2 =
- Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
+ if (isNodePointSelected(point_at3)) {
+ point_at2 = sbasis_in.valueAt(weight_ammount);
+ point_at2 =
+ Geom::Point(point_at2[X] + HANDLE_CUBIC_GAP, point_at2[Y] + HANDLE_CUBIC_GAP);
} else {
- pointAt2 = in->first_segment()->finalPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
- pointAt2 = in->first_segment()->finalPoint();
+ point_at1 = in->first_segment()->initialPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
}
}
in->reset();
delete in;
- nCurve->curveto(pointAt1, pointAt2, pointAt3);
+ curve_n->curveto(point_at1, point_at2, point_at3);
++curve_it1;
++curve_it2;
}
if (path_it->closed()) {
- nCurve->move_endpoints(path_it->begin()->initialPoint(),
+ curve_n->move_endpoints(path_it->begin()->initialPoint(),
path_it->begin()->initialPoint());
} else {
- nCurve->move_endpoints(path_it->begin()->initialPoint(), pointAt3);
+ curve_n->move_endpoints(path_it->begin()->initialPoint(), point_at3);
}
if (path_it->closed()) {
- nCurve->closepath_current();
+ curve_n->closepath_current();
}
- curve->append(nCurve, false);
- nCurve->reset();
- delete nCurve;
+ curve->append(curve_n, false);
+ curve_n->reset();
+ delete curve_n;
}
}
diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h
index a17c0c4ac..fc0f66353 100644
--- a/src/live_effects/lpe-bspline.h
+++ b/src/live_effects/lpe-bspline.h
@@ -6,9 +6,8 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
#include "live_effects/effect.h"
-#include "live_effects/parameter/bool.h"
+
#include <vector>
namespace Inkscape {
@@ -19,7 +18,8 @@ public:
LPEBSpline(LivePathEffectObject *lpeobject);
virtual ~LPEBSpline();
- virtual LPEPathFlashType pathFlashType() const {
+ virtual LPEPathFlashType pathFlashType() const
+ {
return SUPPRESS_FLASH;
}
virtual void doOnApply(SPLPEItem const* lpeitem);
@@ -38,9 +38,9 @@ public:
ScalarParam steps;
private:
- BoolParam ignoreCusp;
- BoolParam onlySelected;
- BoolParam showHelper;
+ ScalarParam helper_size;
+ BoolParam ignore_cusp;
+ BoolParam only_selected;
ScalarParam weight;
Geom::PathVector hp;
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index 0fa2ebedc..fd9b853d5 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -69,7 +69,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
registerParameter(&rotation_angle);
registerParameter(&num_copies);
registerParameter(&origin);
-
+
num_copies.param_make_integer(true);
num_copies.param_set_range(0, 1000);
}
@@ -88,6 +88,7 @@ LPECopyRotate::doOnApply(SPLPEItem const* lpeitem)
A = Point(boundingbox_X.min(), boundingbox_Y.middle());
B = Point(boundingbox_X.middle(), boundingbox_Y.middle());
origin.param_setValue(A);
+ origin.param_update_default(A);
dist_angle_handle = L2(B - A);
dir = unit_vector(B - A);
}
diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp
index d2bdf2d8d..c8458b8cb 100644
--- a/src/live_effects/lpe-fillet-chamfer.cpp
+++ b/src/live_effects/lpe-fillet-chamfer.cpp
@@ -223,7 +223,7 @@ void LPEFilletChamfer::updateFillet()
{
double power = 0;
if (!flexible) {
- power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), *defaultUnit) * -1;
+ power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), defaultUnit) * -1;
} else {
power = radius;
}
diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp
index bf2526986..0111a0f99 100644
--- a/src/live_effects/lpe-jointype.cpp
+++ b/src/live_effects/lpe-jointype.cpp
@@ -8,7 +8,7 @@
*/
#include "live_effects/parameter/enum.h"
-#include "live_effects/pathoutlineprovider.h"
+#include "helper/geom-pathstroke.h"
#include "sp-shape.h"
#include "style.h"
@@ -28,19 +28,19 @@ namespace Inkscape {
namespace LivePathEffect {
static const Util::EnumData<unsigned> JoinTypeData[] = {
- {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
- {LINEJOIN_ROUND, N_("Rounded"), "round"},
- {LINEJOIN_POINTY, N_("Miter"), "miter"},
- {LINEJOIN_REFLECTED, N_("Reflected"), "extrapolated"},
- {LINEJOIN_EXTRAPOLATED, N_("Extrapolated arc"), "extrp_arc"}
+ {JOIN_BEVEL, N_("Beveled"), "bevel"},
+ {JOIN_ROUND, N_("Rounded"), "round"},
+ {JOIN_MITER, N_("Miter"), "miter"},
+ {JOIN_MITER_CLIP, N_("Miter Clip"), "miter-clip"},
+ {JOIN_EXTRAPOLATE, N_("Extrapolated arc"), "extrp_arc"},
};
static const Util::EnumData<unsigned> CapTypeData[] = {
- {BUTT_STRAIGHT, N_("Butt"), "butt"},
+ {BUTT_FLAT, N_("Butt"), "butt"},
{BUTT_ROUND, N_("Rounded"), "round"},
{BUTT_SQUARE, N_("Square"), "square"},
- {BUTT_POINTY, N_("Peak"), "peak"},
- {BUTT_LEANED, N_("Leaned"), "leaned"}
+ {BUTT_PEAK, N_("Peak"), "peak"},
+ //{BUTT_LEANED, N_("Leaned"), "leaned"}
};
static const Util::EnumDataConverter<unsigned> CapTypeConverter(CapTypeData, sizeof(CapTypeData)/sizeof(*CapTypeData));
@@ -50,9 +50,9 @@ LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 1.),
linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight),
- linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
- start_lean(_("Start path lean"), _("Start path lean"), "start_lean", &wr, this, 0.),
- end_lean(_("End path lean"), _("End path lean"), "end_lean", &wr, this, 0.),
+ linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, JOIN_EXTRAPOLATE),
+ //start_lean(_("Start path lean"), _("Start path lean"), "start_lean", &wr, this, 0.),
+ //end_lean(_("End path lean"), _("End path lean"), "end_lean", &wr, this, 0.),
miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.),
attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true)
{
@@ -60,17 +60,16 @@ LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) :
registerParameter(&linecap_type);
registerParameter(&line_width);
registerParameter(&linejoin_type);
- registerParameter(&start_lean);
- registerParameter(&end_lean);
+ //registerParameter(&start_lean);
+ //registerParameter(&end_lean);
registerParameter(&miter_limit);
registerParameter(&attempt_force_join);
- was_initialized = false;
- start_lean.param_set_range(-1,1);
- start_lean.param_set_increments(0.1, 0.1);
- start_lean.param_set_digits(4);
- end_lean.param_set_range(-1,1);
- end_lean.param_set_increments(0.1, 0.1);
- end_lean.param_set_digits(4);
+ //start_lean.param_set_range(-1,1);
+ //start_lean.param_set_increments(0.1, 0.1);
+ //start_lean.param_set_digits(4);
+ //end_lean.param_set_range(-1,1);
+ //end_lean.param_set_increments(0.1, 0.1);
+ //end_lean.param_set_digits(4);
}
LPEJoinType::~LPEJoinType()
@@ -87,38 +86,30 @@ void LPEJoinType::doOnApply(SPLPEItem const* lpeitem)
double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
SPCSSAttr *css = sp_repr_css_attr_new ();
- if (true) {
- if (lpeitem->style->stroke.isPaintserver()) {
- SPPaintServer * server = lpeitem->style->getStrokePaintServer();
- if (server) {
- Glib::ustring str;
- str += "url(#";
- str += server->getId();
- str += ")";
- sp_repr_css_set_property (css, "fill", str.c_str());
- }
- } else if (lpeitem->style->stroke.isColor()) {
- gchar c[64];
- sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
- sp_repr_css_set_property (css, "fill", c);
- } else {
- sp_repr_css_set_property (css, "fill", "none");
+ if (lpeitem->style->stroke.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getStrokePaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "fill", str.c_str());
}
+ } else if (lpeitem->style->stroke.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "fill", c);
} else {
- sp_repr_css_unset_property (css, "fill");
+ sp_repr_css_set_property (css, "fill", "none");
}
+ sp_repr_css_set_property(css, "fill-rule", "nonzero");
sp_repr_css_set_property(css, "stroke", "none");
sp_desktop_apply_css_recursive(item, css, true);
sp_repr_css_attr_unref (css);
- if (!was_initialized)
- {
- was_initialized = true;
- line_width.param_set_value(width);
- }
- } else {
- g_warning("LPE Join Type can only be applied to paths (not groups).");
+
+ line_width.param_set_value(width);
}
}
@@ -126,30 +117,25 @@ void LPEJoinType::doOnApply(SPLPEItem const* lpeitem)
void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem)
{
-
if (SP_IS_SHAPE(lpeitem)) {
SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
SPCSSAttr *css = sp_repr_css_attr_new ();
- if (true) {
- if (lpeitem->style->fill.isPaintserver()) {
- SPPaintServer * server = lpeitem->style->getFillPaintServer();
- if (server) {
- Glib::ustring str;
- str += "url(#";
- str += server->getId();
- str += ")";
- sp_repr_css_set_property (css, "stroke", str.c_str());
- }
- } else if (lpeitem->style->fill.isColor()) {
- gchar c[64];
- sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
- sp_repr_css_set_property (css, "stroke", c);
- } else {
- sp_repr_css_set_property (css, "stroke", "none");
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
}
+ } else if (lpeitem->style->fill.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->fill.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->fill_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
} else {
- sp_repr_css_unset_property (css, "stroke");
+ sp_repr_css_set_property (css, "stroke", "none");
}
Inkscape::CSSOStringStream os;
@@ -164,15 +150,18 @@ void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem)
}
}
-// NOTE: I originally had all the outliner functions defined in here, but they were actually useful
-// enough for other LPEs so I moved them all into pathoutlineprovider.cpp. The code here is just a
-// wrapper around it.
std::vector<Geom::Path> LPEJoinType::doEffect_path(std::vector<Geom::Path> const & path_in)
{
- return Outline::PathVectorOutline(path_in, line_width, static_cast<ButtTypeMod>(linecap_type.get_value()),
- static_cast<LineJoinType>(linejoin_type.get_value()),
- (attempt_force_join ? std::numeric_limits<double>::max() : miter_limit),
- start_lean/2 ,end_lean/2);
+ Geom::PathVector ret;
+ for (size_t i = 0; i < path_in.size(); ++i) {
+ Geom::PathVector tmp = Inkscape::outline(path_in[i], line_width,
+ (attempt_force_join ? std::numeric_limits<double>::max() : miter_limit),
+ static_cast<LineJoinType>(linejoin_type.get_value()),
+ static_cast<LineCapType>(linecap_type.get_value()));
+ ret.insert(ret.begin(), tmp.begin(), tmp.end());
+ }
+
+ return ret;
}
} // namespace LivePathEffect
diff --git a/src/live_effects/lpe-jointype.h b/src/live_effects/lpe-jointype.h
index 73705666d..bca0961c9 100644
--- a/src/live_effects/lpe-jointype.h
+++ b/src/live_effects/lpe-jointype.h
@@ -33,11 +33,10 @@ private:
ScalarParam line_width;
EnumParam<unsigned> linecap_type;
EnumParam<unsigned> linejoin_type;
- ScalarParam start_lean;
- ScalarParam end_lean;
+ //ScalarParam start_lean;
+ //ScalarParam end_lean;
ScalarParam miter_limit;
BoolParam attempt_force_join;
- bool was_initialized;
};
} //namespace LivePathEffect
diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp
index 6ec4b969b..ec2f9c419 100644
--- a/src/live_effects/lpe-knot.cpp
+++ b/src/live_effects/lpe-knot.cpp
@@ -404,7 +404,7 @@ LPEKnot::doEffect_path (std::vector<Geom::Path> const &path_in)
for (unsigned comp=0; comp<path_in.size(); comp++){
//find the relevant path component in gpaths (required to allow groups!)
- //Q: do we always recieve the group members in the same order? can we rest on that?
+ //Q: do we always receive the group members in the same order? can we rest on that?
unsigned i0 = 0;
for (i0=0; i0<gpaths.size(); i0++){
if (path_in[comp]==gpaths[i0]) break;
diff --git a/src/live_effects/lpe-lattice.cpp b/src/live_effects/lpe-lattice.cpp
index a241a8a2e..c05bae7e1 100644
--- a/src/live_effects/lpe-lattice.cpp
+++ b/src/live_effects/lpe-lattice.cpp
@@ -236,6 +236,21 @@ LPELattice::resetDefaults(SPItem const* item)
grid_point15[Geom::X] = 2.0/3*boundingbox_X.max()+1.0/3*boundingbox_X.min();
grid_point15[Geom::Y] = 2.0/3*boundingbox_Y.max()+1.0/3*boundingbox_Y.min();
+ grid_point1.param_update_default(grid_point1);
+ grid_point2.param_update_default(grid_point2);
+ grid_point3.param_update_default(grid_point3);
+ grid_point4.param_update_default(grid_point4);
+ grid_point5.param_update_default(grid_point5);
+ grid_point6.param_update_default(grid_point6);
+ grid_point7.param_update_default(grid_point7);
+ grid_point8.param_update_default(grid_point8);
+ grid_point9.param_update_default(grid_point9);
+ grid_point10.param_update_default(grid_point10);
+ grid_point11.param_update_default(grid_point11);
+ grid_point12.param_update_default(grid_point12);
+ grid_point13.param_update_default(grid_point13);
+ grid_point14.param_update_default(grid_point14);
+ grid_point15.param_update_default(grid_point15);
}
/**
diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp
index e1cd91340..abd6e7786 100644
--- a/src/live_effects/lpe-lattice2.cpp
+++ b/src/live_effects/lpe-lattice2.cpp
@@ -1,6 +1,6 @@
/** \file
* LPE <lattice2> implementation
-
+
*/
/*
* Authors:
@@ -11,7 +11,7 @@
* ~suv
* Jabiertxo Arraiza
*
-* Copyright (C) 2007-2008 Authors
+* Copyright (C) 2007-2008 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -23,18 +23,17 @@
#include "sp-path.h"
#include "display/curve.h"
#include "svg/svg.h"
-
+#include "helper/geom.h"
+#include <2geom/path.h>
#include <2geom/sbasis.h>
#include <2geom/sbasis-2d.h>
+#include "helper/geom-curves.h"
#include <2geom/sbasis-geometric.h>
#include <2geom/bezier-to-sbasis.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/d2.h>
#include <2geom/piecewise.h>
#include <2geom/transforms.h>
-#include "ui/tools-switch.h"
-
-#include "desktop.h" // TODO: should be factored out (see below)
using namespace Geom;
@@ -43,61 +42,63 @@ namespace LivePathEffect {
LPELattice2::LPELattice2(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- // initialise your parameters here:
- grid_point0(_("Control handle 0:"), _("Control handle 0 - Ctrl+Alt+Click to reset"), "gridpoint0", &wr, this),
- grid_point1(_("Control handle 1:"), _("Control handle 1 - Ctrl+Alt+Click to reset"), "gridpoint1", &wr, this),
- grid_point2(_("Control handle 2:"), _("Control handle 2 - Ctrl+Alt+Click to reset"), "gridpoint2", &wr, this),
- grid_point3(_("Control handle 3:"), _("Control handle 3 - Ctrl+Alt+Click to reset"), "gridpoint3", &wr, this),
- grid_point4(_("Control handle 4:"), _("Control handle 4 - Ctrl+Alt+Click to reset"), "gridpoint4", &wr, this),
- grid_point5(_("Control handle 5:"), _("Control handle 5 - Ctrl+Alt+Click to reset"), "gridpoint5", &wr, this),
- grid_point6(_("Control handle 6:"), _("Control handle 6 - Ctrl+Alt+Click to reset"), "gridpoint6", &wr, this),
- grid_point7(_("Control handle 7:"), _("Control handle 7 - Ctrl+Alt+Click to reset"), "gridpoint7", &wr, this),
- grid_point8x9(_("Control handle 8x9:"), _("Control handle 8x9 - Ctrl+Alt+Click to reset"), "gridpoint8x9", &wr, this),
- grid_point10x11(_("Control handle 10x11:"), _("Control handle 10x11 - Ctrl+Alt+Click to reset"), "gridpoint10x11", &wr, this),
- grid_point12(_("Control handle 12:"), _("Control handle 12 - Ctrl+Alt+Click to reset"), "gridpoint12", &wr, this),
- grid_point13(_("Control handle 13:"), _("Control handle 13 - Ctrl+Alt+Click to reset"), "gridpoint13", &wr, this),
- grid_point14(_("Control handle 14:"), _("Control handle 14 - Ctrl+Alt+Click to reset"), "gridpoint14", &wr, this),
- grid_point15(_("Control handle 15:"), _("Control handle 15 - Ctrl+Alt+Click to reset"), "gridpoint15", &wr, this),
- grid_point16(_("Control handle 16:"), _("Control handle 16 - Ctrl+Alt+Click to reset"), "gridpoint16", &wr, this),
- grid_point17(_("Control handle 17:"), _("Control handle 17 - Ctrl+Alt+Click to reset"), "gridpoint17", &wr, this),
- grid_point18(_("Control handle 18:"), _("Control handle 18 - Ctrl+Alt+Click to reset"), "gridpoint18", &wr, this),
- grid_point19(_("Control handle 19:"), _("Control handle 19 - Ctrl+Alt+Click to reset"), "gridpoint19", &wr, this),
- grid_point20x21(_("Control handle 20x21:"), _("Control handle 20x21 - Ctrl+Alt+Click to reset"), "gridpoint20x21", &wr, this),
- grid_point22x23(_("Control handle 22x23:"), _("Control handle 22x23 - Ctrl+Alt+Click to reset"), "gridpoint22x23", &wr, this),
- grid_point24x26(_("Control handle 24x26:"), _("Control handle 24x26 - Ctrl+Alt+Click to reset"), "gridpoint24x26", &wr, this),
- grid_point25x27(_("Control handle 25x27:"), _("Control handle 25x27 - Ctrl+Alt+Click to reset"), "gridpoint25x27", &wr, this),
- grid_point28x30(_("Control handle 28x30:"), _("Control handle 28x30 - Ctrl+Alt+Click to reset"), "gridpoint28x30", &wr, this),
- grid_point29x31(_("Control handle 29x31:"), _("Control handle 29x31 - Ctrl+Alt+Click to reset"), "gridpoint29x31", &wr, this),
- grid_point32x33x34x35(_("Control handle 32x33x34x35:"), _("Control handle 32x33x34x35 - Ctrl+Alt+Click to reset"), "gridpoint32x33x34x35", &wr, this)
-
-
+ horizontal_mirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontal_mirror", &wr, this, false),
+ vertical_mirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "vertical_mirror", &wr, this, false),
+ grid_point_0(_("Control 0:"), _("Control 0 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint0", &wr, this),
+ grid_point_1(_("Control 1:"), _("Control 1 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint1", &wr, this),
+ grid_point_2(_("Control 2:"), _("Control 2 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint2", &wr, this),
+ grid_point_3(_("Control 3:"), _("Control 3 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint3", &wr, this),
+ grid_point_4(_("Control 4:"), _("Control 4 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint4", &wr, this),
+ grid_point_5(_("Control 5:"), _("Control 5 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint5", &wr, this),
+ grid_point_6(_("Control 6:"), _("Control 6 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint6", &wr, this),
+ grid_point_7(_("Control 7:"), _("Control 7 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint7", &wr, this),
+ grid_point_8x9(_("Control 8x9:"), _("Control 8x9 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint8x9", &wr, this),
+ grid_point_10x11(_("Control 10x11:"), _("Control 10x11 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint10x11", &wr, this),
+ grid_point_12(_("Control 12:"), _("Control 12 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint12", &wr, this),
+ grid_point_13(_("Control 13:"), _("Control 13 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint13", &wr, this),
+ grid_point_14(_("Control 14:"), _("Control 14 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint14", &wr, this),
+ grid_point_15(_("Control 15:"), _("Control 15 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint15", &wr, this),
+ grid_point_16(_("Control 16:"), _("Control 16 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint16", &wr, this),
+ grid_point_17(_("Control 17:"), _("Control 17 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint17", &wr, this),
+ grid_point_18(_("Control 18:"), _("Control 18 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint18", &wr, this),
+ grid_point_19(_("Control 19:"), _("Control 19 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint19", &wr, this),
+ grid_point_20x21(_("Control 20x21:"), _("Control 20x21 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint20x21", &wr, this),
+ grid_point_22x23(_("Control 22x23:"), _("Control 22x23 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint22x23", &wr, this),
+ grid_point_24x26(_("Control 24x26:"), _("Control 24x26 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint24x26", &wr, this),
+ grid_point_25x27(_("Control 25x27:"), _("Control 25x27 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint25x27", &wr, this),
+ grid_point_28x30(_("Control 28x30:"), _("Control 28x30 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint28x30", &wr, this),
+ grid_point_29x31(_("Control 29x31:"), _("Control 29x31 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint29x31", &wr, this),
+ grid_point_32x33x34x35(_("Control 32x33x34x35:"), _("Control 32x33x34x35 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint32x33x34x35", &wr, this),
+ expanded(false)
{
// register all your parameters here, so Inkscape knows which parameters this effect has:
- registerParameter( dynamic_cast<Parameter *>(&grid_point0) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point1) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point2) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point3) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point4) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point5) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point6) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point7) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point8x9) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point10x11) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point12) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point13) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point14) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point15) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point16) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point17) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point18) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point19) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point20x21) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point22x23) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point24x26) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point25x27) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point28x30) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point29x31) );
- registerParameter( dynamic_cast<Parameter *>(&grid_point32x33x34x35) );
+ registerParameter(&horizontal_mirror);
+ registerParameter(&vertical_mirror);
+ registerParameter(&grid_point_0);
+ registerParameter(&grid_point_1);
+ registerParameter(&grid_point_2);
+ registerParameter(&grid_point_3);
+ registerParameter(&grid_point_4);
+ registerParameter(&grid_point_5);
+ registerParameter(&grid_point_6);
+ registerParameter(&grid_point_7);
+ registerParameter(&grid_point_8x9);
+ registerParameter(&grid_point_10x11);
+ registerParameter(&grid_point_12);
+ registerParameter(&grid_point_13);
+ registerParameter(&grid_point_14);
+ registerParameter(&grid_point_15);
+ registerParameter(&grid_point_16);
+ registerParameter(&grid_point_17);
+ registerParameter(&grid_point_18);
+ registerParameter(&grid_point_19);
+ registerParameter(&grid_point_20x21);
+ registerParameter(&grid_point_22x23);
+ registerParameter(&grid_point_24x26);
+ registerParameter(&grid_point_25x27);
+ registerParameter(&grid_point_28x30);
+ registerParameter(&grid_point_29x31);
+ registerParameter(&grid_point_32x33x34x35);
}
LPELattice2::~LPELattice2()
@@ -107,8 +108,12 @@ LPELattice2::~LPELattice2()
Geom::Piecewise<Geom::D2<Geom::SBasis> >
LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
+ PathVector pathv = path_from_piecewise(pwd2_in,0.001);
+ //this is because strange problems whith sb2 and LineSegment
+ PathVector cubic = pathv_to_cubicbezier(pathv);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in_linear_and_cubic = paths_to_pw(cubic);
D2<SBasis2d> sb2;
-
+
//Initialisation of the sb2
for(unsigned dim = 0; dim < 2; dim++) {
sb2[dim].us = 3;
@@ -118,47 +123,48 @@ LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
}
//Grouping the point params in a convenient vector
- std::vector<Geom::Point *> handles(36);
-
- handles[0] = &grid_point0;
- handles[1] = &grid_point1;
- handles[2] = &grid_point2;
- handles[3] = &grid_point3;
- handles[4] = &grid_point4;
- handles[5] = &grid_point5;
- handles[6] = &grid_point6;
- handles[7] = &grid_point7;
- handles[8] = &grid_point8x9;
- handles[9] = &grid_point8x9;
- handles[10] = &grid_point10x11;
- handles[11] = &grid_point10x11;
- handles[12] = &grid_point12;
- handles[13] = &grid_point13;
- handles[14] = &grid_point14;
- handles[15] = &grid_point15;
- handles[16] = &grid_point16;
- handles[17] = &grid_point17;
- handles[18] = &grid_point18;
- handles[19] = &grid_point19;
- handles[20] = &grid_point20x21;
- handles[21] = &grid_point20x21;
- handles[22] = &grid_point22x23;
- handles[23] = &grid_point22x23;
- handles[24] = &grid_point24x26;
- handles[25] = &grid_point25x27;
- handles[26] = &grid_point24x26;
- handles[27] = &grid_point25x27;
- handles[28] = &grid_point28x30;
- handles[29] = &grid_point29x31;
- handles[30] = &grid_point28x30;
- handles[31] = &grid_point29x31;
- handles[32] = &grid_point32x33x34x35;
- handles[33] = &grid_point32x33x34x35;
- handles[34] = &grid_point32x33x34x35;
- handles[35] = &grid_point32x33x34x35;
+
+ std::vector<Geom::Point > handles(36);
+
+ handles[0] = grid_point_0;
+ handles[1] = grid_point_1;
+ handles[2] = grid_point_2;
+ handles[3] = grid_point_3;
+ handles[4] = grid_point_4;
+ handles[5] = grid_point_5;
+ handles[6] = grid_point_6;
+ handles[7] = grid_point_7;
+ handles[8] = grid_point_8x9;
+ handles[9] = grid_point_8x9;
+ handles[10] = grid_point_10x11;
+ handles[11] = grid_point_10x11;
+ handles[12] = grid_point_12;
+ handles[13] = grid_point_13;
+ handles[14] = grid_point_14;
+ handles[15] = grid_point_15;
+ handles[16] = grid_point_16;
+ handles[17] = grid_point_17;
+ handles[18] = grid_point_18;
+ handles[19] = grid_point_19;
+ handles[20] = grid_point_20x21;
+ handles[21] = grid_point_20x21;
+ handles[22] = grid_point_22x23;
+ handles[23] = grid_point_22x23;
+ handles[24] = grid_point_24x26;
+ handles[25] = grid_point_25x27;
+ handles[26] = grid_point_24x26;
+ handles[27] = grid_point_25x27;
+ handles[28] = grid_point_28x30;
+ handles[29] = grid_point_29x31;
+ handles[30] = grid_point_28x30;
+ handles[31] = grid_point_29x31;
+ handles[32] = grid_point_32x33x34x35;
+ handles[33] = grid_point_32x33x34x35;
+ handles[34] = grid_point_32x33x34x35;
+ handles[35] = grid_point_32x33x34x35;
Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
-
+
double width = boundingbox_X.extent();
double height = boundingbox_Y.extent();
@@ -172,31 +178,31 @@ LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
for(unsigned iu = 0; iu < 2; iu++) {
unsigned corner = iu + 2*iv;
unsigned i = ui + vi*sb2[dim].us;
-
+
//This is the offset from the Upperleft point
Geom::Point base( (ui + iu*(4-2*ui))*width/4.,
(vi + iv*(4-2*vi))*height/4.);
-
+
//Special action for corners
if(vi == 0 && ui == 0) {
base = Geom::Point(0,0);
}
-
+
// i = Upperleft corner of the considerated rectangle
// corner = actual corner of the rectangle
// origin = Upperleft point
- double dl = dot((*handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
+ double dl = dot((handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
}
}
}
}
}
-
+
Piecewise<D2<SBasis> > output;
output.push_cut(0.);
- for(unsigned i = 0; i < pwd2_in.size(); i++) {
- D2<SBasis> B = pwd2_in[i];
+ for(unsigned i = 0; i < pwd2_in_linear_and_cubic.size(); i++) {
+ D2<SBasis> B = pwd2_in_linear_and_cubic[i];
B[Geom::X] -= origin[Geom::X];
B[Geom::X]*= 1/width;
B[Geom::Y] -= origin[Geom::Y];
@@ -211,6 +217,7 @@ LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
return output;
}
+
Gtk::Widget *
LPELattice2::newWidget()
{
@@ -218,23 +225,32 @@ LPELattice2::newWidget()
Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
vbox->set_border_width(5);
- Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
- resetButton->set_alignment(0.0, 0.5);
- resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
- Gtk::Widget* resetButtonWidget = dynamic_cast<Gtk::Widget *>(resetButton);
- resetButtonWidget->set_tooltip_text("Reset grid");
- vbox->pack_start(*resetButtonWidget, true, true,2);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(6);
+ Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+ vbox_expander->set_border_width(0);
+ vbox_expander->set_spacing(2);
+ Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
+ reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
+ reset_button->set_size_request(140,30);
+ vbox->pack_start(*hbox, true,true,2);
+ hbox->pack_start(*reset_button, false, false,2);
std::vector<Parameter *>::iterator it = param_vector.begin();
while (it != param_vector.end()) {
if ((*it)->widget_is_visible) {
Parameter * param = *it;
Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
- if(param->param_key == "grid"){
+ if(param->param_key == "grid") {
widg = NULL;
}
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
- vbox->pack_start(*widg, true, true, 2);
+ if (param->param_key == "horizontal_mirror" || param->param_key == "vertical_mirror") {
+ vbox->pack_start(*widg, true, true, 2);
+ } else {
+ vbox_expander->pack_start(*widg, true, true, 2);
+ }
if (tip) {
widg->set_tooltip_text(*tip);
} else {
@@ -246,14 +262,98 @@ LPELattice2::newWidget()
++it;
}
+
+ expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show Points"))));
+ expander->add(*vbox_expander);
+ expander->set_expanded(expanded);
+ vbox->pack_start(*expander, true, true, 2);
+ expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPELattice2::onExpanderChanged) );
return dynamic_cast<Gtk::Widget *>(vbox);
}
void
+LPELattice2::onExpanderChanged()
+{
+ expanded = expander->get_expanded();
+ if(expander->get_expanded()) {
+ expander->set_label (Glib::ustring(_("Hide Points")));
+ } else {
+ expander->set_label (Glib::ustring(_("Show Points")));
+ }
+}
+void
+LPELattice2::vertical(PointParam &param_one, PointParam &param_two, Geom::Line vert)
+{
+ Geom::Point A = param_one;
+ Geom::Point B = param_two;
+ double Y = (A[Geom::Y] + B[Geom::Y])/2;
+ A[Geom::Y] = Y;
+ B[Geom::Y] = Y;
+ Geom::Point nearest = vert.pointAt(vert.nearestPoint(A));
+ double distance_one = Geom::distance(A,nearest);
+ double distance_two = Geom::distance(B,nearest);
+ double distance_middle = (distance_one + distance_two)/2;
+ if(A[Geom::X] > B[Geom::X]) {
+ distance_middle *= -1;
+ }
+ A[Geom::X] = nearest[Geom::X] - distance_middle;
+ B[Geom::X] = nearest[Geom::X] + distance_middle;
+ param_one.param_setValue(A, true);
+ param_two.param_setValue(B, true);
+}
+
+void
+LPELattice2::horizontal(PointParam &param_one, PointParam &param_two, Geom::Line horiz)
+{
+ Geom::Point A = param_one;
+ Geom::Point B = param_two;
+ double X = (A[Geom::X] + B[Geom::X])/2;
+ A[Geom::X] = X;
+ B[Geom::X] = X;
+ Geom::Point nearest = horiz.pointAt(horiz.nearestPoint(A));
+ double distance_one = Geom::distance(A,nearest);
+ double distance_two = Geom::distance(B,nearest);
+ double distance_middle = (distance_one + distance_two)/2;
+ if(A[Geom::Y] > B[Geom::Y]) {
+ distance_middle *= -1;
+ }
+ A[Geom::Y] = nearest[Geom::Y] - distance_middle;
+ B[Geom::Y] = nearest[Geom::Y] + distance_middle;
+ param_one.param_setValue(A, true);
+ param_two.param_setValue(B, true);
+}
+
+void
LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
{
original_bbox(lpeitem);
setDefaults();
+ Geom::Line vert(grid_point_8x9.param_get_default(),grid_point_10x11.param_get_default());
+ Geom::Line horiz(grid_point_24x26.param_get_default(),grid_point_25x27.param_get_default());
+ if(vertical_mirror) {
+ vertical(grid_point_0, grid_point_1,vert);
+ vertical(grid_point_2, grid_point_3,vert);
+ vertical(grid_point_4, grid_point_5,vert);
+ vertical(grid_point_6, grid_point_7,vert);
+ vertical(grid_point_12, grid_point_13,vert);
+ vertical(grid_point_14, grid_point_15,vert);
+ vertical(grid_point_16, grid_point_17,vert);
+ vertical(grid_point_18, grid_point_19,vert);
+ vertical(grid_point_24x26, grid_point_25x27,vert);
+ vertical(grid_point_28x30, grid_point_29x31,vert);
+ }
+ if(horizontal_mirror) {
+ horizontal(grid_point_0, grid_point_2,horiz);
+ horizontal(grid_point_1, grid_point_3,horiz);
+ horizontal(grid_point_4, grid_point_6,horiz);
+ horizontal(grid_point_5, grid_point_7,horiz);
+ horizontal(grid_point_8x9, grid_point_10x11,horiz);
+ horizontal(grid_point_12, grid_point_14,horiz);
+ horizontal(grid_point_13, grid_point_15,horiz);
+ horizontal(grid_point_16, grid_point_18,horiz);
+ horizontal(grid_point_17, grid_point_19,horiz);
+ horizontal(grid_point_20x21, grid_point_22x23,horiz);
+ }
SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
item->apply_to_clippath(item);
item->apply_to_mask(item);
@@ -287,116 +387,111 @@ LPELattice2::setDefaults()
(boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
Geom::Point gp8x9((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
Geom::Point gp10x11((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
Geom::Point gp12((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
Geom::Point gp13((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
Geom::Point gp14((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
Geom::Point gp15((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
Geom::Point gp16((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
Geom::Point gp17((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
Geom::Point gp18((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
Geom::Point gp19((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
Geom::Point gp20x21((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
Geom::Point gp22x23((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
Geom::Point gp24x26((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
Geom::Point gp25x27((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
Geom::Point gp28x30((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
Geom::Point gp29x31((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
Geom::Point gp32x33x34x35((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
- (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
-
- grid_point0.param_update_default(gp0);
- grid_point1.param_update_default(gp1);
- grid_point2.param_update_default(gp2);
- grid_point3.param_update_default(gp3);
- grid_point4.param_update_default(gp4);
- grid_point5.param_update_default(gp5);
- grid_point6.param_update_default(gp6);
- grid_point7.param_update_default(gp7);
- grid_point8x9.param_update_default(gp8x9);
- grid_point10x11.param_update_default(gp10x11);
- grid_point12.param_update_default(gp12);
- grid_point13.param_update_default(gp13);
- grid_point14.param_update_default(gp14);
- grid_point15.param_update_default(gp15);
- grid_point16.param_update_default(gp16);
- grid_point17.param_update_default(gp17);
- grid_point18.param_update_default(gp18);
- grid_point19.param_update_default(gp19);
- grid_point20x21.param_update_default(gp20x21);
- grid_point22x23.param_update_default(gp22x23);
- grid_point24x26.param_update_default(gp24x26);
- grid_point25x27.param_update_default(gp25x27);
- grid_point28x30.param_update_default(gp28x30);
- grid_point29x31.param_update_default(gp29x31);
- grid_point32x33x34x35.param_update_default(gp32x33x34x35);
+ (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
+
+ grid_point_0.param_update_default(gp0);
+ grid_point_1.param_update_default(gp1);
+ grid_point_2.param_update_default(gp2);
+ grid_point_3.param_update_default(gp3);
+ grid_point_4.param_update_default(gp4);
+ grid_point_5.param_update_default(gp5);
+ grid_point_6.param_update_default(gp6);
+ grid_point_7.param_update_default(gp7);
+ grid_point_8x9.param_update_default(gp8x9);
+ grid_point_10x11.param_update_default(gp10x11);
+ grid_point_12.param_update_default(gp12);
+ grid_point_13.param_update_default(gp13);
+ grid_point_14.param_update_default(gp14);
+ grid_point_15.param_update_default(gp15);
+ grid_point_16.param_update_default(gp16);
+ grid_point_17.param_update_default(gp17);
+ grid_point_18.param_update_default(gp18);
+ grid_point_19.param_update_default(gp19);
+ grid_point_20x21.param_update_default(gp20x21);
+ grid_point_22x23.param_update_default(gp22x23);
+ grid_point_24x26.param_update_default(gp24x26);
+ grid_point_25x27.param_update_default(gp25x27);
+ grid_point_28x30.param_update_default(gp28x30);
+ grid_point_29x31.param_update_default(gp29x31);
+ grid_point_32x33x34x35.param_update_default(gp32x33x34x35);
}
void
LPELattice2::resetGrid()
{
- grid_point0.param_set_and_write_default();
- grid_point1.param_set_and_write_default();
- grid_point2.param_set_and_write_default();
- grid_point3.param_set_and_write_default();
- grid_point4.param_set_and_write_default();
- grid_point5.param_set_and_write_default();
- grid_point6.param_set_and_write_default();
- grid_point7.param_set_and_write_default();
- grid_point8x9.param_set_and_write_default();
- grid_point10x11.param_set_and_write_default();
- grid_point12.param_set_and_write_default();
- grid_point13.param_set_and_write_default();
- grid_point14.param_set_and_write_default();
- grid_point15.param_set_and_write_default();
- grid_point16.param_set_and_write_default();
- grid_point17.param_set_and_write_default();
- grid_point18.param_set_and_write_default();
- grid_point19.param_set_and_write_default();
- grid_point20x21.param_set_and_write_default();
- grid_point22x23.param_set_and_write_default();
- grid_point24x26.param_set_and_write_default();
- grid_point25x27.param_set_and_write_default();
- grid_point28x30.param_set_and_write_default();
- grid_point29x31.param_set_and_write_default();
- grid_point32x33x34x35.param_set_and_write_default();
- //todo:this hack is only to reposition the knots on reser grid button
- //Better update path effect in LPEITEM
- SPDesktop * desktop = SP_ACTIVE_DESKTOP;
- tools_switch(desktop, TOOLS_SELECT);
- tools_switch(desktop, TOOLS_NODES);
+ grid_point_0.param_set_default();
+ grid_point_1.param_set_default();
+ grid_point_2.param_set_default();
+ grid_point_3.param_set_default();
+ grid_point_4.param_set_default();
+ grid_point_5.param_set_default();
+ grid_point_6.param_set_default();
+ grid_point_7.param_set_default();
+ grid_point_8x9.param_set_default();
+ grid_point_10x11.param_set_default();
+ grid_point_12.param_set_default();
+ grid_point_13.param_set_default();
+ grid_point_14.param_set_default();
+ grid_point_15.param_set_default();
+ grid_point_16.param_set_default();
+ grid_point_17.param_set_default();
+ grid_point_18.param_set_default();
+ grid_point_19.param_set_default();
+ grid_point_20x21.param_set_default();
+ grid_point_22x23.param_set_default();
+ grid_point_24x26.param_set_default();
+ grid_point_25x27.param_set_default();
+ grid_point_28x30.param_set_default();
+ grid_point_29x31.param_set_default();
+ grid_point_32x33x34x35.param_set_default();
}
void
@@ -426,55 +521,55 @@ LPELattice2::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom:
hp_vec.clear();
SPCurve *c = new SPCurve();
- calculateCurve(grid_point0,grid_point4, c,true, true);
- calculateCurve(grid_point4,grid_point8x9, c,true, false);
- calculateCurve(grid_point8x9,grid_point5, c,true, false);
- calculateCurve(grid_point5,grid_point1, c,true, false);
-
- calculateCurve(grid_point12,grid_point16, c,true, true);
- calculateCurve(grid_point16,grid_point20x21, c,true, false);
- calculateCurve(grid_point20x21,grid_point17, c,true, false);
- calculateCurve(grid_point17,grid_point13, c,true, false);
-
- calculateCurve(grid_point24x26,grid_point28x30, c,true, true);
- calculateCurve(grid_point28x30,grid_point32x33x34x35, c,true, false);
- calculateCurve(grid_point32x33x34x35,grid_point29x31, c,true, false);
- calculateCurve(grid_point29x31,grid_point25x27, c,true, false);
-
- calculateCurve(grid_point14,grid_point18, c,true, true);
- calculateCurve(grid_point18,grid_point22x23, c,true, false);
- calculateCurve(grid_point22x23,grid_point19, c,true, false);
- calculateCurve(grid_point19,grid_point15, c,true, false);
-
- calculateCurve(grid_point2,grid_point6, c,true, true);
- calculateCurve(grid_point6,grid_point10x11, c,true, false);
- calculateCurve(grid_point10x11,grid_point7, c,true, false);
- calculateCurve(grid_point7,grid_point3, c,true, false);
-
- calculateCurve(grid_point0,grid_point12, c,false, true);
- calculateCurve(grid_point12,grid_point24x26, c,false, false);
- calculateCurve(grid_point24x26,grid_point14, c,false, false);
- calculateCurve(grid_point14,grid_point2, c,false, false);
-
- calculateCurve(grid_point4,grid_point16, c,false, true);
- calculateCurve(grid_point16,grid_point28x30, c,false, false);
- calculateCurve(grid_point28x30,grid_point18, c,false, false);
- calculateCurve(grid_point18,grid_point6, c,false, false);
-
- calculateCurve(grid_point8x9,grid_point20x21, c,false, true);
- calculateCurve(grid_point20x21,grid_point32x33x34x35, c,false, false);
- calculateCurve(grid_point32x33x34x35,grid_point22x23, c,false, false);
- calculateCurve(grid_point22x23,grid_point10x11, c,false, false);
-
- calculateCurve(grid_point5,grid_point17, c, false, true);
- calculateCurve(grid_point17,grid_point29x31, c,false, false);
- calculateCurve(grid_point29x31,grid_point19, c,false, false);
- calculateCurve(grid_point19,grid_point7, c,false, false);
-
- calculateCurve(grid_point1,grid_point13, c, false, true);
- calculateCurve(grid_point13,grid_point25x27, c,false, false);
- calculateCurve(grid_point25x27,grid_point15, c,false, false);
- calculateCurve(grid_point15,grid_point3, c, false, false);
+ calculateCurve(grid_point_0,grid_point_4, c,true, true);
+ calculateCurve(grid_point_4,grid_point_8x9, c,true, false);
+ calculateCurve(grid_point_8x9,grid_point_5, c,true, false);
+ calculateCurve(grid_point_5,grid_point_1, c,true, false);
+
+ calculateCurve(grid_point_12,grid_point_16, c,true, true);
+ calculateCurve(grid_point_16,grid_point_20x21, c,true, false);
+ calculateCurve(grid_point_20x21,grid_point_17, c,true, false);
+ calculateCurve(grid_point_17,grid_point_13, c,true, false);
+
+ calculateCurve(grid_point_24x26,grid_point_28x30, c,true, true);
+ calculateCurve(grid_point_28x30,grid_point_32x33x34x35, c,true, false);
+ calculateCurve(grid_point_32x33x34x35,grid_point_29x31, c,true, false);
+ calculateCurve(grid_point_29x31,grid_point_25x27, c,true, false);
+
+ calculateCurve(grid_point_14,grid_point_18, c,true, true);
+ calculateCurve(grid_point_18,grid_point_22x23, c,true, false);
+ calculateCurve(grid_point_22x23,grid_point_19, c,true, false);
+ calculateCurve(grid_point_19,grid_point_15, c,true, false);
+
+ calculateCurve(grid_point_2,grid_point_6, c,true, true);
+ calculateCurve(grid_point_6,grid_point_10x11, c,true, false);
+ calculateCurve(grid_point_10x11,grid_point_7, c,true, false);
+ calculateCurve(grid_point_7,grid_point_3, c,true, false);
+
+ calculateCurve(grid_point_0,grid_point_12, c,false, true);
+ calculateCurve(grid_point_12,grid_point_24x26, c,false, false);
+ calculateCurve(grid_point_24x26,grid_point_14, c,false, false);
+ calculateCurve(grid_point_14,grid_point_2, c,false, false);
+
+ calculateCurve(grid_point_4,grid_point_16, c,false, true);
+ calculateCurve(grid_point_16,grid_point_28x30, c,false, false);
+ calculateCurve(grid_point_28x30,grid_point_18, c,false, false);
+ calculateCurve(grid_point_18,grid_point_6, c,false, false);
+
+ calculateCurve(grid_point_8x9,grid_point_20x21, c,false, true);
+ calculateCurve(grid_point_20x21,grid_point_32x33x34x35, c,false, false);
+ calculateCurve(grid_point_32x33x34x35,grid_point_22x23, c,false, false);
+ calculateCurve(grid_point_22x23,grid_point_10x11, c,false, false);
+
+ calculateCurve(grid_point_5,grid_point_17, c, false, true);
+ calculateCurve(grid_point_17,grid_point_29x31, c,false, false);
+ calculateCurve(grid_point_29x31,grid_point_19, c,false, false);
+ calculateCurve(grid_point_19,grid_point_7, c,false, false);
+
+ calculateCurve(grid_point_1,grid_point_13, c, false, true);
+ calculateCurve(grid_point_13,grid_point_25x27, c,false, false);
+ calculateCurve(grid_point_25x27,grid_point_15, c,false, false);
+ calculateCurve(grid_point_15,grid_point_3, c, false, false);
hp_vec.push_back(c->get_pathvector());
}
diff --git a/src/live_effects/lpe-lattice2.h b/src/live_effects/lpe-lattice2.h
index 461f835c6..ff2e75641 100644
--- a/src/live_effects/lpe-lattice2.h
+++ b/src/live_effects/lpe-lattice2.h
@@ -18,10 +18,10 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
+#include <gtkmm.h>
#include "live_effects/parameter/enum.h"
#include "live_effects/effect.h"
-#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/parameter/point.h"
#include "live_effects/lpegroupbbox.h"
namespace Inkscape {
@@ -34,7 +34,7 @@ public:
virtual ~LPELattice2();
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
-
+
virtual void resetDefaults(SPItem const* item);
virtual void doBeforeEffect(SPLPEItem const* lpeitem);
@@ -43,44 +43,50 @@ public:
virtual void calculateCurve(Geom::Point a,Geom::Point b, SPCurve *c, bool horizontal, bool move);
- virtual void setDefaults();
+ virtual void vertical(PointParam &paramA,PointParam &paramB, Geom::Line vert);
- virtual void resetGrid();
+ virtual void horizontal(PointParam &paramA,PointParam &paramB,Geom::Line horiz);
- //virtual void original_bbox(SPLPEItem const* lpeitem, bool absolute = false);
+ virtual void setDefaults();
+
+ virtual void onExpanderChanged();
- //virtual void addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &/*hp_vec*/);
+ virtual void resetGrid();
- //virtual std::vector<Geom::PathVector> getHelperPaths(SPLPEItem const* lpeitem);
protected:
void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
private:
- PointReseteableParam grid_point0;
- PointReseteableParam grid_point1;
- PointReseteableParam grid_point2;
- PointReseteableParam grid_point3;
- PointReseteableParam grid_point4;
- PointReseteableParam grid_point5;
- PointReseteableParam grid_point6;
- PointReseteableParam grid_point7;
- PointReseteableParam grid_point8x9;
- PointReseteableParam grid_point10x11;
- PointReseteableParam grid_point12;
- PointReseteableParam grid_point13;
- PointReseteableParam grid_point14;
- PointReseteableParam grid_point15;
- PointReseteableParam grid_point16;
- PointReseteableParam grid_point17;
- PointReseteableParam grid_point18;
- PointReseteableParam grid_point19;
- PointReseteableParam grid_point20x21;
- PointReseteableParam grid_point22x23;
- PointReseteableParam grid_point24x26;
- PointReseteableParam grid_point25x27;
- PointReseteableParam grid_point28x30;
- PointReseteableParam grid_point29x31;
- PointReseteableParam grid_point32x33x34x35;
+ BoolParam horizontal_mirror;
+ BoolParam vertical_mirror;
+ PointParam grid_point_0;
+ PointParam grid_point_1;
+ PointParam grid_point_2;
+ PointParam grid_point_3;
+ PointParam grid_point_4;
+ PointParam grid_point_5;
+ PointParam grid_point_6;
+ PointParam grid_point_7;
+ PointParam grid_point_8x9;
+ PointParam grid_point_10x11;
+ PointParam grid_point_12;
+ PointParam grid_point_13;
+ PointParam grid_point_14;
+ PointParam grid_point_15;
+ PointParam grid_point_16;
+ PointParam grid_point_17;
+ PointParam grid_point_18;
+ PointParam grid_point_19;
+ PointParam grid_point_20x21;
+ PointParam grid_point_22x23;
+ PointParam grid_point_24x26;
+ PointParam grid_point_25x27;
+ PointParam grid_point_28x30;
+ PointParam grid_point_29x31;
+ PointParam grid_point_32x33x34x35;
+
+ bool expanded;
+ Gtk::Expander * expander;
LPELattice2(const LPELattice2&);
LPELattice2& operator=(const LPELattice2&);
diff --git a/src/live_effects/lpe-offset.cpp b/src/live_effects/lpe-offset.cpp
index dc91775b7..ba7179476 100644
--- a/src/live_effects/lpe-offset.cpp
+++ b/src/live_effects/lpe-offset.cpp
@@ -42,7 +42,9 @@ LPEOffset::~LPEOffset()
void
LPEOffset::doOnApply(SPLPEItem const* lpeitem)
{
- offset_pt.param_set_and_write_new_value(*(SP_SHAPE(lpeitem)->_curve->first_point()));
+ Geom::Point offset = *(SP_SHAPE(lpeitem)->_curve->first_point());
+ offset_pt.param_update_default(offset);
+ offset_pt.param_setValue(offset,true);
}
static void append_half_circle(Geom::Piecewise<Geom::D2<Geom::SBasis> > &pwd2,
diff --git a/src/live_effects/lpe-parallel.cpp b/src/live_effects/lpe-parallel.cpp
index bb37fd42c..aa7405607 100644
--- a/src/live_effects/lpe-parallel.cpp
+++ b/src/live_effects/lpe-parallel.cpp
@@ -72,8 +72,9 @@ LPEParallel::doOnApply (SPLPEItem const* lpeitem)
A = *(curve->first_point());
B = *(curve->last_point());
dir = unit_vector(B - A);
-
- offset_pt.param_set_and_write_new_value((A + B)/2 + dir.ccw() * 100);
+ Geom::Point offset = (A + B)/2 + dir.ccw() * 100;
+ offset_pt.param_update_default(offset);
+ offset_pt.param_setValue(offset, true);
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp
index b5ef26e2f..08100bb2d 100644
--- a/src/live_effects/lpe-perspective-envelope.cpp
+++ b/src/live_effects/lpe-perspective-envelope.cpp
@@ -1,6 +1,6 @@
/** \file
* LPE <perspective-envelope> implementation
-
+
*/
/*
* Authors:
@@ -8,8 +8,8 @@
* Aaron Spike, aaron@ekips.org from envelope and perspective phyton code
* Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math
* Jose Hevia (freon) Transform algorithm from envelope
- *
- * Copyright (C) 2007-2014 Authors
+ *
+ * Copyright (C) 2007-2014 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -19,9 +19,7 @@
#include "helper/geom.h"
#include "display/curve.h"
#include "svg/svg.h"
-#include "ui/tools-switch.h"
#include <gsl/gsl_linalg.h>
-#include "desktop.h"
using namespace Geom;
@@ -29,8 +27,8 @@ namespace Inkscape {
namespace LivePathEffect {
enum DeformationType {
- DEFORMATION_PERSPECTIVE,
- DEFORMATION_ENVELOPE
+ DEFORMATION_PERSPECTIVE,
+ DEFORMATION_ENVELOPE
};
static const Util::EnumData<unsigned> DeformationTypeData[] = {
@@ -42,54 +40,65 @@ static const Util::EnumDataConverter<unsigned> DeformationTypeConverter(Deformat
LPEPerspectiveEnvelope::LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- // initialise your parameters here:
+ horizontal_mirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontal_mirror", &wr, this, false),
+ vertical_mirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "vertical_mirror", &wr, this, false),
deform_type(_("Type"), _("Select the type of deformation"), "deform_type", DeformationTypeConverter, &wr, this, DEFORMATION_PERSPECTIVE),
- Up_Left_Point(_("Top Left"), _("Top Left - Ctrl+Alt+Click to reset"), "Up_Left_Point", &wr, this),
- Up_Right_Point(_("Top Right"), _("Top Right - Ctrl+Alt+Click to reset"), "Up_Right_Point", &wr, this),
- Down_Left_Point(_("Down Left"), _("Down Left - Ctrl+Alt+Click to reset"), "Down_Left_Point", &wr, this),
- Down_Right_Point(_("Down Right"), _("Down Right - Ctrl+Alt+Click to reset"), "Down_Right_Point", &wr, this)
+ up_left_point(_("Top Left"), _("Top Left - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "up_left_point", &wr, this),
+ up_right_point(_("Top Right"), _("Top Right - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "up_right_point", &wr, this),
+ down_left_point(_("Down Left"), _("Down Left - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "down_left_point", &wr, this),
+ down_right_point(_("Down Right"), _("Down Right - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "down_right_point", &wr, this)
{
// register all your parameters here, so Inkscape knows which parameters this effect has:
- registerParameter( dynamic_cast<Parameter *>(&deform_type));
- registerParameter( dynamic_cast<Parameter *>(&Up_Left_Point) );
- registerParameter( dynamic_cast<Parameter *>(&Up_Right_Point) );
- registerParameter( dynamic_cast<Parameter *>(&Down_Left_Point) );
- registerParameter( dynamic_cast<Parameter *>(&Down_Right_Point) );
+ registerParameter(&deform_type);
+ registerParameter(&horizontal_mirror);
+ registerParameter(&vertical_mirror);
+ registerParameter(&up_left_point);
+ registerParameter(&up_right_point);
+ registerParameter(&down_left_point);
+ registerParameter(&down_right_point);
}
LPEPerspectiveEnvelope::~LPEPerspectiveEnvelope()
{
}
-void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
+void LPEPerspectiveEnvelope::doEffect(SPCurve *curve)
+{
using Geom::X;
using Geom::Y;
+ if(are_near(up_left_point, up_right_point) &&
+ are_near(up_right_point, down_left_point) &&
+ are_near(down_left_point, down_right_point)) {
+ g_warning("Perspective/Envelope LPE::doBeforeEffect - lpeobj with invalid parameter, the same value in 4 handles!");
+ resetGrid();
+ return;
+ }
double projmatrix[3][3];
- if(deform_type == DEFORMATION_PERSPECTIVE){
+ if(deform_type == DEFORMATION_PERSPECTIVE) {
std::vector<Geom::Point> handles(4);
- handles[0] = Down_Left_Point;
- handles[1] = Up_Left_Point;
- handles[2] = Up_Right_Point;
- handles[3] = Down_Right_Point;
- std::vector<Geom::Point> sourceHandles(4);
- sourceHandles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max());
- sourceHandles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min());
- sourceHandles[2] = Geom::Point(boundingbox_X.max(), boundingbox_Y.min());
- sourceHandles[3] = Geom::Point(boundingbox_X.max(), boundingbox_Y.max());
+ handles[0] = down_left_point;
+ handles[1] = up_left_point;
+ handles[2] = up_right_point;
+ handles[3] = down_right_point;
+ std::vector<Geom::Point> source_handles(4);
+ source_handles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max());
+ source_handles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min());
+ source_handles[2] = Geom::Point(boundingbox_X.max(), boundingbox_Y.min());
+ source_handles[3] = Geom::Point(boundingbox_X.max(), boundingbox_Y.max());
double solmatrix[8][8] = {{0}};
double free_term[8] = {0};
double gslSolmatrix[64];
- for(unsigned int i = 0; i < 4; ++i){
- solmatrix[i][0] = sourceHandles[i][X];
- solmatrix[i][1] = sourceHandles[i][Y];
+ for(unsigned int i = 0; i < 4; ++i) {
+ solmatrix[i][0] = source_handles[i][X];
+ solmatrix[i][1] = source_handles[i][Y];
solmatrix[i][2] = 1;
- solmatrix[i][6] = -handles[i][X] * sourceHandles[i][X];
- solmatrix[i][7] = -handles[i][X] * sourceHandles[i][Y];
- solmatrix[i+4][3] = sourceHandles[i][X];
- solmatrix[i+4][4] = sourceHandles[i][Y];
+ solmatrix[i][6] = -handles[i][X] * source_handles[i][X];
+ solmatrix[i][7] = -handles[i][X] * source_handles[i][Y];
+ solmatrix[i+4][3] = source_handles[i][X];
+ solmatrix[i+4][4] = source_handles[i][Y];
solmatrix[i+4][5] = 1;
- solmatrix[i+4][6] = -handles[i][Y] * sourceHandles[i][X];
- solmatrix[i+4][7] = -handles[i][Y] * sourceHandles[i][Y];
+ solmatrix[i+4][6] = -handles[i][Y] * source_handles[i][X];
+ solmatrix[i+4][7] = -handles[i][Y] * source_handles[i][Y];
free_term[i] = handles[i][X];
free_term[i+4] = handles[i][Y];
}
@@ -112,7 +121,7 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
h = 0;
for( int i = 0; i < 3; i++ ) {
for( int j = 0; j < 3; j++ ) {
- if(h==8){
+ if(h==8) {
projmatrix[2][2] = 1.0;
continue;
}
@@ -126,19 +135,19 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
curve->reset();
Geom::CubicBezier const *cubic = NULL;
- Geom::Point pointAt1(0, 0);
- Geom::Point pointAt2(0, 0);
- Geom::Point pointAt3(0, 0);
+ Geom::Point point_at1(0, 0);
+ Geom::Point point_at2(0, 0);
+ Geom::Point point_at3(0, 0);
for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
//Si está vacío...
if (path_it->empty())
- continue;
+ continue;
//Itreadores
SPCurve *nCurve = new SPCurve();
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();
@@ -146,40 +155,40 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
curve_endit = path_it->end_open();
}
}
- if(deform_type == DEFORMATION_PERSPECTIVE){
- nCurve->moveto(project_point(curve_it1->initialPoint(),projmatrix));
- }else{
- nCurve->moveto(project_point(curve_it1->initialPoint()));
+ if(deform_type == DEFORMATION_PERSPECTIVE) {
+ nCurve->moveto(projectPoint(curve_it1->initialPoint(),projmatrix));
+ } else {
+ nCurve->moveto(projectPoint(curve_it1->initialPoint()));
}
while (curve_it1 != curve_endit) {
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- pointAt1 = (*cubic)[1];
- pointAt2 = (*cubic)[2];
- } else {
- pointAt1 = curve_it1->initialPoint();
- pointAt2 = curve_it1->finalPoint();
- }
- pointAt3 = curve_it1->finalPoint();
- if(deform_type == DEFORMATION_PERSPECTIVE){
- pointAt1 = project_point(pointAt1,projmatrix);
- pointAt2 = project_point(pointAt2,projmatrix);
- pointAt3 = project_point(pointAt3,projmatrix);
- }else{
- pointAt1 = project_point(pointAt1);
- pointAt2 = project_point(pointAt2);
- pointAt3 = project_point(pointAt3);
- }
- nCurve->curveto(pointAt1, pointAt2, pointAt3);
- ++curve_it1;
- if(curve_it2 != curve_endit) {
- ++curve_it2;
- }
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ point_at1 = (*cubic)[1];
+ point_at2 = (*cubic)[2];
+ } else {
+ point_at1 = curve_it1->initialPoint();
+ point_at2 = curve_it1->finalPoint();
+ }
+ point_at3 = curve_it1->finalPoint();
+ if(deform_type == DEFORMATION_PERSPECTIVE) {
+ point_at1 = projectPoint(point_at1,projmatrix);
+ point_at2 = projectPoint(point_at2,projmatrix);
+ point_at3 = projectPoint(point_at3,projmatrix);
+ } else {
+ point_at1 = projectPoint(point_at1);
+ point_at2 = projectPoint(point_at2);
+ point_at3 = projectPoint(point_at3);
+ }
+ nCurve->curveto(point_at1, point_at2, point_at3);
+ ++curve_it1;
+ if(curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
}
//y cerramos la curva
if (path_it->closed()) {
- nCurve->move_endpoints(pointAt3, pointAt3);
- nCurve->closepath_current();
+ nCurve->move_endpoints(point_at3, point_at3);
+ nCurve->closepath_current();
}
curve->append(nCurve, false);
nCurve->reset();
@@ -187,41 +196,44 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve) {
}
}
-Geom::Point
-LPEPerspectiveEnvelope::project_point(Geom::Point p){
+Geom::Point
+LPEPerspectiveEnvelope::projectPoint(Geom::Point p)
+{
double width = boundingbox_X.extent();
double height = boundingbox_Y.extent();
double delta_x = boundingbox_X.min() - p[X];
double delta_y = boundingbox_Y.max() - p[Y];
- Geom::Coord xratio = (delta_x * -1) / width;
- Geom::Coord yratio = delta_y / height;
+ Geom::Coord x_ratio = (delta_x * -1) / width;
+ Geom::Coord y_ratio = delta_y / height;
Geom::Line* horiz = new Geom::Line();
Geom::Line* vert = new Geom::Line();
- vert->setPoints (pointAtRatio(yratio,Down_Left_Point,Up_Left_Point),pointAtRatio(yratio,Down_Right_Point,Up_Right_Point));
- horiz->setPoints (pointAtRatio(xratio,Down_Left_Point,Down_Right_Point),pointAtRatio(xratio,Up_Left_Point,Up_Right_Point));
+ vert->setPoints (pointAtRatio(y_ratio,down_left_point,up_left_point),pointAtRatio(y_ratio,down_right_point,up_right_point));
+ horiz->setPoints (pointAtRatio(x_ratio,down_left_point,down_right_point),pointAtRatio(x_ratio,up_left_point,up_right_point));
OptCrossing crossPoint = intersection(*horiz,*vert);
- if(crossPoint){
+ if(crossPoint) {
return horiz->pointAt(Geom::Coord(crossPoint->ta));
- }else{
+ } else {
return p;
}
}
-Geom::Point
-LPEPerspectiveEnvelope::project_point(Geom::Point p, double m[][3]){
+Geom::Point
+LPEPerspectiveEnvelope::projectPoint(Geom::Point p, double m[][3])
+{
Geom::Coord x = p[0];
Geom::Coord y = p[1];
return Geom::Point(
- Geom::Coord((x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2])),
- Geom::Coord((x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2])));
+ Geom::Coord((x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2])),
+ Geom::Coord((x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2])));
}
Geom::Point
-LPEPerspectiveEnvelope::pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B){
- Geom::Coord x = A[X] + (ratio * (B[X]-A[X]));
- Geom::Coord y = A[Y]+ (ratio * (B[Y]-A[Y]));
- return Point(x, y);
+LPEPerspectiveEnvelope::pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B)
+{
+ Geom::Coord x = A[X] + (ratio * (B[X]-A[X]));
+ Geom::Coord y = A[Y]+ (ratio * (B[Y]-A[Y]));
+ return Point(x, y);
}
@@ -235,36 +247,35 @@ LPEPerspectiveEnvelope::newWidget()
vbox->set_homogeneous(false);
vbox->set_spacing(6);
std::vector<Parameter *>::iterator it = param_vector.begin();
- Gtk::HBox * hboxUpHandles = Gtk::manage(new Gtk::HBox(false,0));
- Gtk::HBox * hboxDownHandles = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::HBox * hbox_up_handles = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::HBox * hbox_down_handles = Gtk::manage(new Gtk::HBox(false,0));
while (it != param_vector.end()) {
if ((*it)->widget_is_visible) {
Parameter * param = *it;
Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
- if (param->param_key == "Up_Left_Point" ||
- param->param_key == "Up_Right_Point" ||
- param->param_key == "Down_Left_Point" ||
- param->param_key == "Down_Right_Point")
- {
- Gtk::HBox * pointParameter = dynamic_cast<Gtk::HBox *>(widg);
- std::vector< Gtk::Widget* > childList = pointParameter->get_children();
- Gtk::HBox * pointParameterHBox = dynamic_cast<Gtk::HBox *>(childList[0]);
- std::vector< Gtk::Widget* > childList2 = pointParameterHBox->get_children();
- pointParameterHBox->remove(childList2[0][0]);
+ if (param->param_key == "up_left_point" ||
+ param->param_key == "up_right_point" ||
+ param->param_key == "down_left_point" ||
+ param->param_key == "down_right_point") {
+ Gtk::HBox * point_hbox = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > child_list = point_hbox->get_children();
+ Gtk::HBox * point_hboxHBox = dynamic_cast<Gtk::HBox *>(child_list[0]);
+ std::vector< Gtk::Widget* > child_list2 = point_hboxHBox->get_children();
+ point_hboxHBox->remove(child_list2[0][0]);
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
- if(param->param_key == "Up_Left_Point"){
+ if(param->param_key == "up_left_point") {
Gtk::Label* handles = Gtk::manage(new Gtk::Label(Glib::ustring(_("Handles:")),Gtk::ALIGN_START));
vbox->pack_start(*handles, false, false, 2);
- hboxUpHandles->pack_start(*widg, true, true, 2);
- hboxUpHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
- }else if(param->param_key == "Up_Right_Point"){
- hboxUpHandles->pack_start(*widg, true, true, 2);
- }else if(param->param_key == "Down_Left_Point"){
- hboxDownHandles->pack_start(*widg, true, true, 2);
- hboxDownHandles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
- }else{
- hboxDownHandles->pack_start(*widg, true, true, 2);
+ hbox_up_handles->pack_start(*widg, true, true, 2);
+ hbox_up_handles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ } else if(param->param_key == "up_right_point") {
+ hbox_up_handles->pack_start(*widg, true, true, 2);
+ } else if(param->param_key == "down_left_point") {
+ hbox_down_handles->pack_start(*widg, true, true, 2);
+ hbox_down_handles->pack_start(*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ } else {
+ hbox_down_handles->pack_start(*widg, true, true, 2);
}
if (tip) {
widg->set_tooltip_text(*tip);
@@ -273,7 +284,7 @@ LPEPerspectiveEnvelope::newWidget()
widg->set_has_tooltip(false);
}
}
- }else{
+ } else {
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
vbox->pack_start(*widg, true, true, 2);
@@ -289,25 +300,77 @@ LPEPerspectiveEnvelope::newWidget()
++it;
}
- vbox->pack_start(*hboxUpHandles,true, true, 2);
- Gtk::HBox * hboxMiddle = Gtk::manage(new Gtk::HBox(true,2));
- hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
- hboxMiddle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
- vbox->pack_start(*hboxMiddle, false, true, 2);
- vbox->pack_start(*hboxDownHandles, true, true, 2);
+ vbox->pack_start(*hbox_up_handles,true, true, 2);
+ Gtk::HBox * hbox_middle = Gtk::manage(new Gtk::HBox(true,2));
+ hbox_middle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ hbox_middle->pack_start(*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET);
+ vbox->pack_start(*hbox_middle, false, true, 2);
+ vbox->pack_start(*hbox_down_handles, true, true, 2);
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
- Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Gtk::Stock::CLEAR));
- resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPEPerspectiveEnvelope::resetGrid));
- resetButton->set_size_request(140,45);
+ Gtk::Button* reset_button = Gtk::manage(new Gtk::Button(Gtk::Stock::CLEAR));
+ reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPEPerspectiveEnvelope::resetGrid));
+ reset_button->set_size_request(140,30);
vbox->pack_start(*hbox, true,true,2);
- hbox->pack_start(*resetButton, false, false,2);
+ hbox->pack_start(*reset_button, false, false,2);
return dynamic_cast<Gtk::Widget *>(vbox);
}
void
+LPEPerspectiveEnvelope::vertical(PointParam &param_one, PointParam &param_two, Geom::Line vert)
+{
+ Geom::Point A = param_one;
+ Geom::Point B = param_two;
+ double Y = (A[Geom::Y] + B[Geom::Y])/2;
+ A[Geom::Y] = Y;
+ B[Geom::Y] = Y;
+ Geom::Point nearest = vert.pointAt(vert.nearestPoint(A));
+ double distance_one = Geom::distance(A,nearest);
+ double distance_two = Geom::distance(B,nearest);
+ double distance_middle = (distance_one + distance_two)/2;
+ if(A[Geom::X] > B[Geom::X]) {
+ distance_middle *= -1;
+ }
+ A[Geom::X] = nearest[Geom::X] - distance_middle;
+ B[Geom::X] = nearest[Geom::X] + distance_middle;
+ param_one.param_setValue(A, true);
+ param_two.param_setValue(B, true);
+}
+
+void
+LPEPerspectiveEnvelope::horizontal(PointParam &param_one, PointParam &param_two, Geom::Line horiz)
+{
+ Geom::Point A = param_one;
+ Geom::Point B = param_two;
+ double X = (A[Geom::X] + B[Geom::X])/2;
+ A[Geom::X] = X;
+ B[Geom::X] = X;
+ Geom::Point nearest = horiz.pointAt(horiz.nearestPoint(A));
+ double distance_one = Geom::distance(A,nearest);
+ double distance_two = Geom::distance(B,nearest);
+ double distance_middle = (distance_one + distance_two)/2;
+ if(A[Geom::Y] > B[Geom::Y]) {
+ distance_middle *= -1;
+ }
+ A[Geom::Y] = nearest[Geom::Y] - distance_middle;
+ B[Geom::Y] = nearest[Geom::Y] + distance_middle;
+ param_one.param_setValue(A, true);
+ param_two.param_setValue(B, true);
+}
+
+void
LPEPerspectiveEnvelope::doBeforeEffect (SPLPEItem const* lpeitem)
{
original_bbox(lpeitem);
+ Geom::Line vert(Geom::Point(boundingbox_X.middle(),boundingbox_Y.max()), Geom::Point(boundingbox_X.middle(), boundingbox_Y.min()));
+ Geom::Line horiz(Geom::Point(boundingbox_X.min(),boundingbox_Y.middle()), Geom::Point(boundingbox_X.max(), boundingbox_Y.middle()));
+ if(vertical_mirror) {
+ vertical(up_left_point, up_right_point,vert);
+ vertical(down_left_point, down_right_point,vert);
+ }
+ if(horizontal_mirror) {
+ horizontal(up_left_point, down_left_point,horiz);
+ horizontal(up_right_point, down_right_point,horiz);
+ }
SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
item->apply_to_clippath(item);
item->apply_to_mask(item);
@@ -317,29 +380,24 @@ LPEPerspectiveEnvelope::doBeforeEffect (SPLPEItem const* lpeitem)
void
LPEPerspectiveEnvelope::setDefaults()
{
- Geom::Point Up_Left(boundingbox_X.min(), boundingbox_Y.min());
- Geom::Point Up_Right(boundingbox_X.max(), boundingbox_Y.min());
- Geom::Point Down_Left(boundingbox_X.min(), boundingbox_Y.max());
- Geom::Point Down_Right(boundingbox_X.max(), boundingbox_Y.max());
-
- Up_Left_Point.param_update_default(Up_Left);
- Up_Right_Point.param_update_default(Up_Right);
- Down_Right_Point.param_update_default(Down_Right);
- Down_Left_Point.param_update_default(Down_Left);
+ Geom::Point up_left(boundingbox_X.min(), boundingbox_Y.min());
+ Geom::Point up_right(boundingbox_X.max(), boundingbox_Y.min());
+ Geom::Point down_left(boundingbox_X.min(), boundingbox_Y.max());
+ Geom::Point down_right(boundingbox_X.max(), boundingbox_Y.max());
+
+ up_left_point.param_update_default(up_left);
+ up_right_point.param_update_default(up_right);
+ down_right_point.param_update_default(down_right);
+ down_left_point.param_update_default(down_left);
}
void
LPEPerspectiveEnvelope::resetGrid()
{
- Up_Left_Point.param_set_and_write_default();
- Up_Right_Point.param_set_and_write_default();
- Down_Right_Point.param_set_and_write_default();
- Down_Left_Point.param_set_and_write_default();
- //todo:this hack is only to reposition the knots on reser grid button
- //Better update path effect in LPEITEM
- SPDesktop * desktop = SP_ACTIVE_DESKTOP;
- tools_switch(desktop, TOOLS_SELECT);
- tools_switch(desktop, TOOLS_NODES);
+ up_left_point.param_set_default();
+ up_right_point.param_set_default();
+ down_right_point.param_set_default();
+ down_left_point.param_set_default();
}
void
@@ -358,11 +416,11 @@ LPEPerspectiveEnvelope::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::v
SPCurve *c = new SPCurve();
c->reset();
- c->moveto(Up_Left_Point);
- c->lineto(Up_Right_Point);
- c->lineto(Down_Right_Point);
- c->lineto(Down_Left_Point);
- c->lineto(Up_Left_Point);
+ c->moveto(up_left_point);
+ c->lineto(up_right_point);
+ c->lineto(down_right_point);
+ c->lineto(down_left_point);
+ c->lineto(up_left_point);
hp_vec.push_back(c->get_pathvector());
}
diff --git a/src/live_effects/lpe-perspective-envelope.h b/src/live_effects/lpe-perspective-envelope.h
index 2f253882e..dd14dc212 100644
--- a/src/live_effects/lpe-perspective-envelope.h
+++ b/src/live_effects/lpe-perspective-envelope.h
@@ -3,7 +3,7 @@
/** \file
* LPE <perspective-envelope> implementation , see lpe-perspective-envelope.cpp.
-
+
*/
/*
* Authors:
@@ -11,15 +11,15 @@
* Aaron Spike, aaron@ekips.org from envelope and perspective phyton code
* Dmitry Platonov, shadowjack@mail.ru, 2006 perspective approach & math
* Jose Hevia (freon) Transform algorithm from envelope
- *
- * Copyright (C) 2007-2014 Authors
+ *
+ * Copyright (C) 2007-2014 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "live_effects/parameter/enum.h"
#include "live_effects/effect.h"
-#include "live_effects/parameter/pointreseteable.h"
+#include "live_effects/parameter/point.h"
#include "live_effects/lpegroupbbox.h"
namespace Inkscape {
@@ -34,14 +34,18 @@ public:
virtual void doEffect(SPCurve *curve);
- virtual Geom::Point project_point(Geom::Point p);
+ virtual Geom::Point projectPoint(Geom::Point p);
- virtual Geom::Point project_point(Geom::Point p, double m[][3]);
+ virtual Geom::Point projectPoint(Geom::Point p, double m[][3]);
virtual Geom::Point pointAtRatio(Geom::Coord ratio,Geom::Point A, Geom::Point B);
virtual void resetDefaults(SPItem const* item);
+ virtual void vertical(PointParam &paramA,PointParam &paramB, Geom::Line vert);
+
+ virtual void horizontal(PointParam &paramA,PointParam &paramB,Geom::Line horiz);
+
virtual void doBeforeEffect(SPLPEItem const* lpeitem);
virtual Gtk::Widget * newWidget();
@@ -54,11 +58,13 @@ protected:
void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
private:
+ BoolParam horizontal_mirror;
+ BoolParam vertical_mirror;
EnumParam<unsigned> deform_type;
- PointReseteableParam Up_Left_Point;
- PointReseteableParam Up_Right_Point;
- PointReseteableParam Down_Left_Point;
- PointReseteableParam Down_Right_Point;
+ PointParam up_left_point;
+ PointParam up_right_point;
+ PointParam down_left_point;
+ PointParam down_right_point;
LPEPerspectiveEnvelope(const LPEPerspectiveEnvelope&);
LPEPerspectiveEnvelope& operator=(const LPEPerspectiveEnvelope&);
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index f7fe9592d..5d9d224e8 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -297,7 +297,8 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
} else {
sp_repr_css_unset_property (css, "fill");
}
-
+
+ sp_repr_css_set_property(css, "fill-rule", "nonzero");
sp_repr_css_set_property(css, "stroke", "none");
sp_desktop_apply_css_recursive(item, css, true);
@@ -330,25 +331,21 @@ void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem)
if (SP_IS_SHAPE(lpeitem)) {
SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
SPCSSAttr *css = sp_repr_css_attr_new ();
- if (true) {
- if (lpeitem->style->fill.isPaintserver()) {
- SPPaintServer * server = lpeitem->style->getFillPaintServer();
- if (server) {
- Glib::ustring str;
- str += "url(#";
- str += server->getId();
- str += ")";
- sp_repr_css_set_property (css, "stroke", str.c_str());
- }
- } else if (lpeitem->style->fill.isColor()) {
- gchar c[64];
- sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
- sp_repr_css_set_property (css, "stroke", c);
- } else {
- sp_repr_css_set_property (css, "stroke", "none");
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
}
+ } else if (lpeitem->style->fill.isColor()) {
+ char c[64] = {0};
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->fill.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->fill_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
} else {
- sp_repr_css_unset_property (css, "stroke");
+ sp_repr_css_set_property (css, "stroke", "none");
}
Inkscape::CSSOStringStream os;
diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp
index 8cef9a3a3..9d1c3152b 100644
--- a/src/live_effects/lpe-roughen.cpp
+++ b/src/live_effects/lpe-roughen.cpp
@@ -39,36 +39,36 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject)
unit(_("Unit"), _("Unit"), "unit", &wr, this),
method(_("Method"), _("Division method"), "method", DMConverter, &wr,
this, DM_SEGMENTS),
- maxSegmentSize(_("Max. segment size"), _("Max. segment size"),
- "maxSegmentSize", &wr, this, 10.),
+ max_segment_size(_("Max. segment size"), _("Max. segment size"),
+ "max_segment_size", &wr, this, 10.),
segments(_("Number of segments"), _("Number of segments"), "segments",
&wr, this, 2),
- displaceX(_("Max. displacement in X"), _("Max. displacement in X"),
- "displaceX", &wr, this, 10.),
- displaceY(_("Max. displacement in Y"), _("Max. displacement in Y"),
- "displaceY", &wr, this, 10.),
- globalRandomize(_("Global randomize"), _("Global randomize"),
- "globalRandomize", &wr, this, 1.),
- shiftNodes(_("Shift nodes"), _("Shift nodes"), "shiftNodes", &wr, this,
+ displace_x(_("Max. displacement in X"), _("Max. displacement in X"),
+ "displace_x", &wr, this, 10.),
+ displace_y(_("Max. displacement in Y"), _("Max. displacement in Y"),
+ "displace_y", &wr, this, 10.),
+ global_randomize(_("Global randomize"), _("Global randomize"),
+ "global_randomize", &wr, this, 1.),
+ shift_nodes(_("Shift nodes"), _("Shift nodes"), "shift_nodes", &wr, this,
true),
- shiftNodeHandles(_("Shift node handles"), _("Shift node handles"),
- "shiftNodeHandles", &wr, this, true)
+ shift_node_handles(_("Shift node handles"), _("Shift node handles"),
+ "shift_node_handles", &wr, this, true)
{
registerParameter(&unit);
registerParameter(&method);
- registerParameter(&maxSegmentSize);
+ registerParameter(&max_segment_size);
registerParameter(&segments);
- registerParameter(&displaceX);
- registerParameter(&displaceY);
- registerParameter(&globalRandomize);
- registerParameter(&shiftNodes);
- registerParameter(&shiftNodeHandles);
- displaceX.param_set_range(0., Geom::infinity());
- displaceY.param_set_range(0., Geom::infinity());
- globalRandomize.param_set_range(0., Geom::infinity());
- maxSegmentSize.param_set_range(0., Geom::infinity());
- maxSegmentSize.param_set_increments(1, 1);
- maxSegmentSize.param_set_digits(1);
+ registerParameter(&displace_x);
+ registerParameter(&displace_y);
+ registerParameter(&global_randomize);
+ registerParameter(&shift_nodes);
+ registerParameter(&shift_node_handles);
+ displace_x.param_set_range(0., Geom::infinity());
+ displace_y.param_set_range(0., Geom::infinity());
+ global_randomize.param_set_range(0., Geom::infinity());
+ max_segment_size.param_set_range(0., Geom::infinity());
+ max_segment_size.param_set_increments(1, 1);
+ max_segment_size.param_set_digits(1);
segments.param_set_range(1, Geom::infinity());
segments.param_set_increments(1, 1);
segments.param_set_digits(0);
@@ -78,9 +78,9 @@ LPERoughen::~LPERoughen() {}
void LPERoughen::doBeforeEffect(SPLPEItem const *lpeitem)
{
- displaceX.resetRandomizer();
- displaceY.resetRandomizer();
- globalRandomize.resetRandomizer();
+ displace_x.resetRandomizer();
+ displace_y.resetRandomizer();
+ global_randomize.resetRandomizer();
srand(1);
SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
item->apply_to_clippath(item);
@@ -99,37 +99,37 @@ Gtk::Widget *LPERoughen::newWidget()
Parameter *param = *it;
Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
if (param->param_key == "unit") {
- Gtk::Label *unitLabel = Gtk::manage(new Gtk::Label(
+ Gtk::Label *unit_label = Gtk::manage(new Gtk::Label(
Glib::ustring(_("<b>Roughen unit</b>")), Gtk::ALIGN_START));
- unitLabel->set_use_markup(true);
- vbox->pack_start(*unitLabel, false, false, 2);
+ unit_label->set_use_markup(true);
+ vbox->pack_start(*unit_label, false, false, 2);
vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
Gtk::PACK_EXPAND_WIDGET);
}
if (param->param_key == "method") {
- Gtk::Label *methodLabel = Gtk::manage(new Gtk::Label(
+ Gtk::Label *method_label = Gtk::manage(new Gtk::Label(
Glib::ustring(_("<b>Add nodes</b> Subdivide each segment")),
Gtk::ALIGN_START));
- methodLabel->set_use_markup(true);
- vbox->pack_start(*methodLabel, false, false, 2);
+ method_label->set_use_markup(true);
+ vbox->pack_start(*method_label, false, false, 2);
vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
Gtk::PACK_EXPAND_WIDGET);
}
- if (param->param_key == "displaceX") {
- Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label(
+ if (param->param_key == "displace_x") {
+ Gtk::Label *displace_x_label = Gtk::manage(new Gtk::Label(
Glib::ustring(_("<b>Jitter nodes</b> Move nodes/handles")),
Gtk::ALIGN_START));
- displaceXLabel->set_use_markup(true);
- vbox->pack_start(*displaceXLabel, false, false, 2);
+ displace_x_label->set_use_markup(true);
+ vbox->pack_start(*displace_x_label, false, false, 2);
vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
Gtk::PACK_EXPAND_WIDGET);
}
- if (param->param_key == "globalRandomize") {
- Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label(
+ if (param->param_key == "global_randomize") {
+ Gtk::Label *global_rand = Gtk::manage(new Gtk::Label(
Glib::ustring(_("<b>Extra roughen</b> Add a extra layer of rough")),
Gtk::ALIGN_START));
- displaceXLabel->set_use_markup(true);
- vbox->pack_start(*displaceXLabel, false, false, 2);
+ global_rand->set_use_markup(true);
+ vbox->pack_start(*global_rand, false, false, 2);
vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
Gtk::PACK_EXPAND_WIDGET);
}
@@ -150,23 +150,23 @@ Gtk::Widget *LPERoughen::newWidget()
return dynamic_cast<Gtk::Widget *>(vbox);
}
-double LPERoughen::sign(double randNumber)
+double LPERoughen::sign(double random_number)
{
if (rand() % 100 < 49) {
- randNumber *= -1.;
+ random_number *= -1.;
}
- return randNumber;
+ return random_number;
}
Geom::Point LPERoughen::randomize()
{
Inkscape::Util::Unit const *svg_units = SP_ACTIVE_DESKTOP->namedview->svg_units;
- double displaceXParsed = Inkscape::Util::Quantity::convert(
- displaceX * globalRandomize, unit.get_abbreviation(), svg_units->abbr);
- double displaceYParsed = Inkscape::Util::Quantity::convert(
- displaceY * globalRandomize, unit.get_abbreviation(), svg_units->abbr);
+ double displace_x_parsed = Inkscape::Util::Quantity::convert(
+ displace_x * global_randomize, unit.get_abbreviation(), svg_units->abbr);
+ double displace_y_parsed = Inkscape::Util::Quantity::convert(
+ displace_y * global_randomize, unit.get_abbreviation(), svg_units->abbr);
- Geom::Point output = Geom::Point(sign(displaceXParsed), sign(displaceYParsed));
+ Geom::Point output = Geom::Point(sign(displace_x_parsed), sign(displace_y_parsed));
return output;
}
@@ -193,32 +193,32 @@ void LPERoughen::doEffect(SPCurve *curve)
}
}
Geom::Point initialMove(0, 0);
- if (shiftNodes) {
+ if (shift_nodes) {
initialMove = randomize();
}
Geom::Point initialPoint = curve_it1->initialPoint() + initialMove;
nCurve->moveto(initialPoint);
- Geom::Point A0(0, 0);
- Geom::Point A1(0, 0);
- Geom::Point A2(0, 0);
- Geom::Point A3(0, 0);
+ Geom::Point point0(0, 0);
+ Geom::Point point1(0, 0);
+ Geom::Point point2(0, 0);
+ Geom::Point point3(0, 0);
bool first = true;
while (curve_it1 != curve_endit) {
Geom::CubicBezier const *cubic = NULL;
- A0 = curve_it1->initialPoint();
- A1 = curve_it1->initialPoint();
- A2 = curve_it1->finalPoint();
- A3 = curve_it1->finalPoint();
+ point0 = curve_it1->initialPoint();
+ point1 = curve_it1->initialPoint();
+ point2 = curve_it1->finalPoint();
+ point3 = curve_it1->finalPoint();
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
- A1 = (*cubic)[1];
- if (shiftNodes && first) {
- A1 = (*cubic)[1] + initialMove;
+ point1 = (*cubic)[1];
+ if (shift_nodes && first) {
+ point1 = (*cubic)[1] + initialMove;
}
- A2 = (*cubic)[2];
- nCurve->curveto(A1, A2, A3);
+ point2 = (*cubic)[2];
+ nCurve->curveto(point1, point2, point3);
} else {
- nCurve->lineto(A3);
+ nCurve->lineto(point3);
}
double length = Inkscape::Util::Quantity::convert(
curve_it1->length(0.001), svg_units->abbr, unit.get_abbreviation());
@@ -226,7 +226,7 @@ void LPERoughen::doEffect(SPCurve *curve)
if (method == DM_SEGMENTS) {
splits = segments;
} else {
- splits = ceil(length / maxSegmentSize);
+ splits = ceil(length / max_segment_size);
}
for (unsigned int t = splits; t >= 1; t--) {
if (t == 1 && splits != 1) {
@@ -265,42 +265,42 @@ SPCurve *LPERoughen::addNodesAndJitter(const Geom::Curve *A, double t)
{
SPCurve *out = new SPCurve();
Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
- Geom::Point A1(0, 0);
- Geom::Point A2(0, 0);
- Geom::Point A3(0, 0);
- Geom::Point B1(0, 0);
- Geom::Point B2(0, 0);
- Geom::Point B3(0, 0);
- if (shiftNodes) {
- A3 = randomize();
- B3 = randomize();
+ Geom::Point point1(0, 0);
+ Geom::Point point2(0, 0);
+ Geom::Point point3(0, 0);
+ Geom::Point point_b1(0, 0);
+ Geom::Point point_b2(0, 0);
+ Geom::Point point_b3(0, 0);
+ if (shift_nodes) {
+ point3 = randomize();
+ point_b3 = randomize();
}
- if (shiftNodeHandles) {
- A1 = randomize();
- A2 = randomize();
- B1 = randomize();
- B2 = randomize();
+ if (shift_node_handles) {
+ point1 = randomize();
+ point2 = randomize();
+ point_b1 = randomize();
+ point_b2 = randomize();
} else {
- A2 = A3;
- B1 = A3;
- B2 = B3;
+ point2 = point3;
+ point_b1 = point3;
+ point_b2 = point_b3;
}
if (cubic) {
std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
std::vector<Geom::Point> seg1 = div.first.points(),
seg2 = div.second.points();
out->moveto(seg1[0]);
- out->curveto(seg1[1] + A1, seg1[2] + A2, seg1[3] + A3);
- out->curveto(seg2[1] + B1, seg2[2], seg2[3]);
- } else if (shiftNodeHandles) {
+ out->curveto(seg1[1] + point1, seg1[2] + point2, seg1[3] + point3);
+ out->curveto(seg2[1] + point_b1, seg2[2], seg2[3]);
+ } else if (shift_node_handles) {
out->moveto(A->initialPoint());
- out->curveto(A->pointAt(t / 3) + A1, A->pointAt((t / 3) * 2) + A2,
- A->pointAt(t) + A3);
- out->curveto(A->pointAt(t + (t / 3)) + B1, A->pointAt(t + ((t / 3) * 2)),
+ out->curveto(A->pointAt(t / 3) + point1, A->pointAt((t / 3) * 2) + point2,
+ A->pointAt(t) + point3);
+ out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t + ((t / 3) * 2)),
A->finalPoint());
} else {
out->moveto(A->initialPoint());
- out->lineto(A->pointAt(t) + A3);
+ out->lineto(A->pointAt(t) + point3);
out->lineto(A->finalPoint());
}
return out;
@@ -310,33 +310,33 @@ SPCurve *LPERoughen::jitter(const Geom::Curve *A)
{
SPCurve *out = new SPCurve();
Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
- Geom::Point A1(0, 0);
- Geom::Point A2(0, 0);
- Geom::Point A3(0, 0);
- if (shiftNodes) {
- A3 = randomize();
+ Geom::Point point1(0, 0);
+ Geom::Point point2(0, 0);
+ Geom::Point point3(0, 0);
+ if (shift_nodes) {
+ point3 = randomize();
}
- if (shiftNodeHandles) {
- A1 = randomize();
- A2 = randomize();
+ if (shift_node_handles) {
+ point1 = randomize();
+ point2 = randomize();
} else {
- A2 = A3;
+ point2 = point3;
}
if (cubic) {
out->moveto((*cubic)[0]);
- out->curveto((*cubic)[1] + A1, (*cubic)[2] + A2, (*cubic)[3] + A3);
- } else if (shiftNodeHandles) {
+ out->curveto((*cubic)[1] + point1, (*cubic)[2] + point2, (*cubic)[3] + point3);
+ } else if (shift_node_handles) {
out->moveto(A->initialPoint());
- out->curveto(A->pointAt(0.3333) + A1, A->pointAt(0.6666) + A2,
- A->finalPoint() + A3);
+ out->curveto(A->pointAt(0.3333) + point1, A->pointAt(0.6666) + point2,
+ A->finalPoint() + point3);
} else {
out->moveto(A->initialPoint());
- out->lineto(A->finalPoint() + A3);
+ out->lineto(A->finalPoint() + point3);
}
return out;
}
-Geom::Point LPERoughen::tpoint(Geom::Point A, Geom::Point B, double t)
+Geom::Point LPERoughen::tPoint(Geom::Point A, Geom::Point B, double t)
{
using Geom::X;
using Geom::Y;
diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h
index 74331f1ef..ed9f06cf7 100644
--- a/src/live_effects/lpe-roughen.h
+++ b/src/live_effects/lpe-roughen.h
@@ -41,19 +41,19 @@ public:
virtual void doBeforeEffect(SPLPEItem const * lpeitem);
virtual SPCurve *addNodesAndJitter(const Geom::Curve *A, double t);
virtual SPCurve *jitter(const Geom::Curve *A);
- virtual Geom::Point tpoint(Geom::Point A, Geom::Point B, double t = 0.5);
+ virtual Geom::Point tPoint(Geom::Point A, Geom::Point B, double t = 0.5);
virtual Gtk::Widget *newWidget();
private:
UnitParam unit;
EnumParam<DivisionMethod> method;
- ScalarParam maxSegmentSize;
+ ScalarParam max_segment_size;
ScalarParam segments;
- RandomParam displaceX;
- RandomParam displaceY;
- RandomParam globalRandomize;
- BoolParam shiftNodes;
- BoolParam shiftNodeHandles;
+ RandomParam displace_x;
+ RandomParam displace_y;
+ RandomParam global_randomize;
+ BoolParam shift_nodes;
+ BoolParam shift_node_handles;
LPERoughen(const LPERoughen &);
LPERoughen &operator=(const LPERoughen &);
diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp
index 2d8148730..2638f312e 100644
--- a/src/live_effects/lpe-show_handles.cpp
+++ b/src/live_effects/lpe-show_handles.cpp
@@ -24,25 +24,25 @@ LPEShowHandles::LPEShowHandles(LivePathEffectObject *lpeobject)
: Effect(lpeobject),
nodes(_("Show nodes"), _("Show nodes"), "nodes", &wr, this, true),
handles(_("Show handles"), _("Show handles"), "handles", &wr, this, true),
- originalPath(_("Show path"), _("Show path"), "originalPath", &wr, this, true),
- scaleNodesAndHandles(_("Scale nodes and handles"), _("Scale nodes and handles"), "scaleNodesAndHandles", &wr, this, 10),
- rotateNodes(_("Rotate nodes"), _("Rotate nodes"), "rotateNodes", &wr, this, 0)
+ original_path(_("Show path"), _("Show path"), "original_path", &wr, this, true),
+ scale_nodes_and_handles(_("Scale nodes and handles"), _("Scale nodes and handles"), "scale_nodes_and_handles", &wr, this, 10),
+ rotate_nodes(_("Rotate nodes"), _("Rotate nodes"), "rotate_nodes", &wr, this, 0)
{
- registerParameter(dynamic_cast<Parameter *>(&nodes));
- registerParameter(dynamic_cast<Parameter *>(&handles));
- registerParameter(dynamic_cast<Parameter *>(&originalPath));
- registerParameter(dynamic_cast<Parameter *>(&scaleNodesAndHandles));
- registerParameter(dynamic_cast<Parameter *>(&rotateNodes));
- scaleNodesAndHandles.param_set_range(0, 500.);
- scaleNodesAndHandles.param_set_increments(1, 1);
- scaleNodesAndHandles.param_set_digits(2);
- rotateNodes.param_set_range(0, 365);
- rotateNodes.param_set_increments(1, 1);
- rotateNodes.param_set_digits(0);
- strokeWidth = 1.0;
+ registerParameter(&nodes);
+ registerParameter(&handles);
+ registerParameter(&original_path);
+ registerParameter(&scale_nodes_and_handles);
+ registerParameter(&rotate_nodes);
+ scale_nodes_and_handles.param_set_range(0, 500.);
+ scale_nodes_and_handles.param_set_increments(1, 1);
+ scale_nodes_and_handles.param_set_digits(2);
+ rotate_nodes.param_set_range(0, 365);
+ rotate_nodes.param_set_increments(1, 1);
+ rotate_nodes.param_set_digits(0);
+ stroke_width = 1.0;
}
-bool LPEShowHandles::alertsOff = false;
+bool LPEShowHandles::alerts_off = false;
/**
* Sets default styles to element
@@ -51,11 +51,11 @@ bool LPEShowHandles::alertsOff = false;
void LPEShowHandles::doOnApply(SPLPEItem const* lpeitem)
{
- if(!alertsOff) {
+ if(!alerts_off) {
char *msg = _("The \"show handles\" path effect will remove any custom style on the object you are applying it to. If this is not what you want, click Cancel.");
Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
gint response = dialog.run();
- alertsOff = true;
+ alerts_off = true;
if(response == GTK_RESPONSE_CANCEL) {
SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
item->removeCurrentPathEffect(false);
@@ -76,24 +76,24 @@ void LPEShowHandles::doOnApply(SPLPEItem const* lpeitem)
void LPEShowHandles::doBeforeEffect (SPLPEItem const* lpeitem)
{
SPItem const* item = SP_ITEM(lpeitem);
- strokeWidth = item->style->stroke_width.computed;
+ stroke_width = item->style->stroke_width.computed;
}
std::vector<Geom::Path> LPEShowHandles::doEffect_path (std::vector<Geom::Path> const & path_in)
{
std::vector<Geom::Path> path_out;
Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in);
- if(originalPath) {
+ if(original_path) {
for (unsigned int i=0; i < path_in.size(); i++) {
path_out.push_back(path_in[i]);
}
}
- if(!outlinepath.empty()) {
- outlinepath.clear();
+ if(!outline_path.empty()) {
+ outline_path.clear();
}
generateHelperPath(original_pathv);
- for (unsigned int i=0; i < outlinepath.size(); i++) {
- path_out.push_back(outlinepath[i]);
+ for (unsigned int i=0; i < outline_path.size(); i++) {
+ path_out.push_back(outline_path[i]);
}
return path_out;
}
@@ -136,11 +136,11 @@ LPEShowHandles::generateHelperPath(Geom::PathVector result)
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
if(handles) {
- if(!are_near((*cubic)[0],(*cubic)[1])){
+ if(!are_near((*cubic)[0],(*cubic)[1])) {
drawHandle((*cubic)[1]);
drawHandleLine((*cubic)[0],(*cubic)[1]);
}
- if(!are_near((*cubic)[3],(*cubic)[2])){
+ if(!are_near((*cubic)[3],(*cubic)[2])) {
drawHandle((*cubic)[2]);
drawHandleLine((*cubic)[3],(*cubic)[2]);
}
@@ -150,7 +150,7 @@ LPEShowHandles::generateHelperPath(Geom::PathVector result)
drawNode(curve_it1->finalPoint());
}
++curve_it1;
- if(curve_it2 != curve_endit){
+ if(curve_it2 != curve_endit) {
++curve_it2;
}
}
@@ -160,30 +160,30 @@ LPEShowHandles::generateHelperPath(Geom::PathVector result)
void
LPEShowHandles::drawNode(Geom::Point p)
{
- if(strokeWidth * scaleNodesAndHandles > 0.0) {
- double diameter = strokeWidth * scaleNodesAndHandles;
+ if(stroke_width * scale_nodes_and_handles > 0.0) {
+ double diameter = stroke_width * scale_nodes_and_handles;
char const * svgd;
svgd = "M 0.05,0 A 0.05,0.05 0 0 1 0,0.05 0.05,0.05 0 0 1 -0.05,0 0.05,0.05 0 0 1 0,-0.05 0.05,0.05 0 0 1 0.05,0 Z M -0.5,-0.5 0.5,-0.5 0.5,0.5 -0.5,0.5 Z";
Geom::PathVector pathv = sp_svg_read_pathv(svgd);
- pathv *= Geom::Rotate::from_degrees(rotateNodes);
+ pathv *= Geom::Rotate::from_degrees(rotate_nodes);
pathv *= Geom::Scale (diameter);
pathv += p;
- outlinepath.push_back(pathv[0]);
- outlinepath.push_back(pathv[1]);
+ outline_path.push_back(pathv[0]);
+ outline_path.push_back(pathv[1]);
}
}
void
LPEShowHandles::drawHandle(Geom::Point p)
{
- if(strokeWidth * scaleNodesAndHandles > 0.0) {
- double diameter = strokeWidth * scaleNodesAndHandles;
+ if(stroke_width * scale_nodes_and_handles > 0.0) {
+ double diameter = stroke_width * scale_nodes_and_handles;
char const * svgd;
svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z";
Geom::PathVector pathv = sp_svg_read_pathv(svgd);
pathv *= Geom::Scale (diameter);
pathv += p-Geom::Point(diameter * 0.35,diameter * 0.35);
- outlinepath.push_back(pathv[0]);
+ outline_path.push_back(pathv[0]);
}
}
@@ -192,14 +192,14 @@ void
LPEShowHandles::drawHandleLine(Geom::Point p,Geom::Point p2)
{
Geom::Path path;
- double diameter = strokeWidth * scaleNodesAndHandles;
- if(diameter > 0.0 && Geom::distance(p,p2) > (diameter * 0.35)){
+ double diameter = stroke_width * scale_nodes_and_handles;
+ if(diameter > 0.0 && Geom::distance(p,p2) > (diameter * 0.35)) {
Geom::Ray ray2(p, p2);
p2 = p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35));
}
path.start( p );
path.appendNew<Geom::LineSegment>( p2 );
- outlinepath.push_back(path);
+ outline_path.push_back(path);
}
}; //namespace LivePathEffect
diff --git a/src/live_effects/lpe-show_handles.h b/src/live_effects/lpe-show_handles.h
index a405c26ee..77b28e77a 100644
--- a/src/live_effects/lpe-show_handles.h
+++ b/src/live_effects/lpe-show_handles.h
@@ -20,7 +20,7 @@ class LPEShowHandles : public Effect , GroupBBoxEffect {
public:
LPEShowHandles(LivePathEffectObject *lpeobject);
- virtual ~LPEShowHandles(){}
+ virtual ~LPEShowHandles() {}
virtual void doOnApply(SPLPEItem const* lpeitem);
@@ -42,13 +42,13 @@ private:
BoolParam nodes;
BoolParam handles;
- BoolParam originalPath;
- ScalarParam scaleNodesAndHandles;
- ScalarParam rotateNodes;
- double strokeWidth;
- static bool alertsOff;
+ BoolParam original_path;
+ ScalarParam scale_nodes_and_handles;
+ ScalarParam rotate_nodes;
+ double stroke_width;
+ static bool alerts_off;
- Geom::PathVector outlinepath;
+ Geom::PathVector outline_path;
LPEShowHandles(const LPEShowHandles &);
LPEShowHandles &operator=(const LPEShowHandles &);
diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp
index 2b2efb1a9..7fc20ede1 100644
--- a/src/live_effects/lpe-simplify.cpp
+++ b/src/live_effects/lpe-simplify.cpp
@@ -20,40 +20,46 @@
#include <2geom/generic-rect.h>
#include <2geom/interval.h>
#include "ui/icon-names.h"
+#include "util/units.h"
namespace Inkscape {
namespace LivePathEffect {
LPESimplify::LPESimplify(LivePathEffectObject *lpeobject)
: Effect(lpeobject),
- steps(_("Steps:"),_("Change number of simplify steps "), "steps", &wr, this,1),
- threshold(_("Roughly threshold:"), _("Roughly threshold:"), "threshold", &wr, this, 0.003),
- helper_size(_("Helper size:"), _("Helper size"), "helper_size", &wr, this, 2.),
- nodes(_("Helper nodes"), _("Show helper nodes"), "nodes", &wr, this, false,
- "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
- handles(_("Helper handles"), _("Show helper handles"), "handles", &wr, this, false,
- "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
- simplifyindividualpaths(_("Paths separately"), _("Simplifying paths (separately)"), "simplifyindividualpaths", &wr, this, false,
- "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
- simplifyJustCoalesce(_("Just coalesce"), _("Simplify just coalesce"), "simplifyJustCoalesce", &wr, this, false,
- "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off"))
- {
- registerParameter(dynamic_cast<Parameter *>(&steps));
- registerParameter(dynamic_cast<Parameter *>(&threshold));
- registerParameter(dynamic_cast<Parameter *>(&helper_size));
- registerParameter(dynamic_cast<Parameter *>(&nodes));
- registerParameter(dynamic_cast<Parameter *>(&handles));
- registerParameter(dynamic_cast<Parameter *>(&simplifyindividualpaths));
- registerParameter(dynamic_cast<Parameter *>(&simplifyJustCoalesce));
- threshold.param_set_range(0.0001, Geom::infinity());
- threshold.param_set_increments(0.0001, 0.0001);
- threshold.param_set_digits(6);
- steps.param_set_range(0, 100);
- steps.param_set_increments(1, 1);
- steps.param_set_digits(0);
- helper_size.param_set_range(0.1, 100);
- helper_size.param_set_increments(1, 1);
- helper_size.param_set_digits(1);
+ steps(_("Steps:"),_("Change number of simplify steps "), "steps", &wr, this,1),
+ threshold(_("Roughly threshold:"), _("Roughly threshold:"), "threshold", &wr, this, 0.003),
+ smooth_angles(_("Smooth angles:"), _("Max degree difference on handles to preform a smooth"), "smooth_angles", &wr, this, 20.),
+ helper_size(_("Helper size:"), _("Helper size"), "helper_size", &wr, this, 5),
+ simplify_individual_paths(_("Paths separately"), _("Simplifying paths (separately)"), "simplify_individual_paths", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off")),
+ simplify_just_coalesce(_("Just coalesce"), _("Simplify just coalesce"), "simplify_just_coalesce", &wr, this, false,
+ "", INKSCAPE_ICON("on"), INKSCAPE_ICON("off"))
+{
+ registerParameter(&steps);
+ registerParameter(&threshold);
+ registerParameter(&smooth_angles);
+ registerParameter(&helper_size);
+ registerParameter(&simplify_individual_paths);
+ registerParameter(&simplify_just_coalesce);
+
+ threshold.param_set_range(0.0001, Geom::infinity());
+ threshold.param_set_increments(0.0001, 0.0001);
+ threshold.param_set_digits(6);
+
+ steps.param_set_range(0, 100);
+ steps.param_set_increments(1, 1);
+ steps.param_set_digits(0);
+
+ smooth_angles.param_set_range(0.0, 365.0);
+ smooth_angles.param_set_increments(10, 10);
+ smooth_angles.param_set_digits(2);
+
+ helper_size.param_set_range(0.0, 999.0);
+ helper_size.param_set_increments(5, 5);
+ helper_size.param_set_digits(2);
+
+ radius_helper_nodes = 6.0;
}
LPESimplify::~LPESimplify() {}
@@ -61,14 +67,14 @@ LPESimplify::~LPESimplify() {}
void
LPESimplify::doBeforeEffect (SPLPEItem const* lpeitem)
{
- if(!hp.empty()){
+ if(!hp.empty()) {
hp.clear();
}
bbox = SP_ITEM(lpeitem)->visualBounds();
SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
+ radius_helper_nodes = helper_size;
item->apply_to_clippath(item);
item->apply_to_mask(item);
-
}
Gtk::Widget *
@@ -81,27 +87,12 @@ LPESimplify::newWidget()
vbox->set_spacing(2);
std::vector<Parameter *>::iterator it = param_vector.begin();
Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0));
- Gtk::HBox * buttonsTwo = Gtk::manage(new Gtk::HBox(true,0));
while (it != param_vector.end()) {
if ((*it)->widget_is_visible) {
Parameter * param = *it;
Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
- if (param->param_key == "simplifyindividualpaths" ||
- param->param_key == "simplifyJustCoalesce")
- {
- Glib::ustring * tip = param->param_getTooltip();
- if (widg) {
- buttonsTwo->pack_start(*widg, true, true, 2);
- if (tip) {
- widg->set_tooltip_text(*tip);
- } else {
- widg->set_tooltip_text("");
- widg->set_has_tooltip(false);
- }
- }
- } else if (param->param_key == "nodes" ||
- param->param_key == "handles")
- {
+ if (param->param_key == "simplify_individual_paths" ||
+ param->param_key == "simplify_just_coalesce") {
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
buttons->pack_start(*widg, true, true, 2);
@@ -112,13 +103,13 @@ LPESimplify::newWidget()
widg->set_has_tooltip(false);
}
}
- }else{
+ } else {
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
- Gtk::HBox * scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
- std::vector< Gtk::Widget* > childList = scalarParameter->get_children();
- Gtk::Entry* entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
- entryWidg->set_width_chars(8);
+ Gtk::HBox * horizontal_box = dynamic_cast<Gtk::HBox *>(widg);
+ std::vector< Gtk::Widget* > child_list = horizontal_box->get_children();
+ Gtk::Entry* entry_widg = dynamic_cast<Gtk::Entry *>(child_list[1]);
+ entry_widg->set_width_chars(8);
vbox->pack_start(*widg, true, true, 2);
if (tip) {
widg->set_tooltip_text(*tip);
@@ -133,107 +124,143 @@ LPESimplify::newWidget()
++it;
}
vbox->pack_start(*buttons,true, true, 2);
- vbox->pack_start(*buttonsTwo,true, true, 2);
return dynamic_cast<Gtk::Widget *>(vbox);
}
-void
-LPESimplify::doEffect(SPCurve *curve) {
+void
+LPESimplify::doEffect(SPCurve *curve)
+{
Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
gdouble size = Geom::L2(bbox->dimensions());
//size /= Geom::Affine(0,0,0,0,0,0).descrim();
Path* pathliv = Path_for_pathvector(original_pathv);
- if(simplifyindividualpaths){
+ if(simplify_individual_paths) {
size = Geom::L2(Geom::bounds_fast(original_pathv)->dimensions());
}
- for (int unsigned i = 0; i < steps; i++){
- if ( simplifyJustCoalesce ) {
- pathliv->Coalesce(threshold * size);
- }else{
- pathliv->ConvertEvenLines(threshold * size);
- pathliv->Simplify(threshold * size);
+ for (int unsigned i = 0; i < steps; i++) {
+ if ( simplify_just_coalesce ) {
+ pathliv->Coalesce(threshold * size);
+ } else {
+ pathliv->ConvertEvenLines(threshold * size);
+ pathliv->Simplify(threshold * size);
}
}
- Geom::PathVector outres = Geom::parse_svg_path(pathliv->svg_dump_path());
- generateHelperPath(outres);
- curve->set_pathvector(outres);
+ Geom::PathVector result = Geom::parse_svg_path(pathliv->svg_dump_path());
+ generateHelperPathAndSmooth(result);
+ curve->set_pathvector(result);
SPDesktop* desktop = SP_ACTIVE_DESKTOP;
- if(desktop && INK_IS_NODE_TOOL(desktop->event_context)){
+ if(desktop && INK_IS_NODE_TOOL(desktop->event_context)) {
Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context);
nt->update_helperpath();
}
}
void
-LPESimplify::generateHelperPath(Geom::PathVector result)
+LPESimplify::generateHelperPathAndSmooth(Geom::PathVector &result)
{
- if(!handles && !nodes){
+ if(steps < 1) {
return;
}
-
- if(steps < 1){
- return;
- }
-
+ Geom::PathVector tmp_path;
Geom::CubicBezier const *cubic = NULL;
for (Geom::PathVector::iterator path_it = result.begin(); path_it != result.end(); ++path_it) {
//Si está vacío...
- if (path_it->empty()){
- continue;
+ if (path_it->empty()) {
+ continue;
}
//Itreadores
Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
- Geom::Path::const_iterator curve_it2 =
- ++(path_it->begin()); // outgoing curve
- Geom::Path::const_iterator curve_endit =
- path_it->end_default(); // this determines when the loop has to stop
-
+ Geom::Path::const_iterator curve_it2 = ++(path_it->begin());// outgoing curve
+ Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop
+ SPCurve *nCurve = new SPCurve();
if (path_it->closed()) {
- // if the path is closed, maybe we have to stop a bit earlier because the
- // closing line segment has zerolength.
- 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();
- }
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ 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();
+ }
}
- if(nodes){
+ if(helper_size > 0) {
drawNode(curve_it1->initialPoint());
}
+ nCurve->moveto(curve_it1->initialPoint());
+ Geom::Point start = Geom::Point(0,0);
while (curve_it1 != curve_endit) {
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ Geom::Point point_at1 = curve_it1->initialPoint();
+ Geom::Point point_at2 = curve_it1->finalPoint();
+ Geom::Point point_at3 = curve_it1->finalPoint();
+ Geom::Point point_at4 = curve_it1->finalPoint();
if (cubic) {
- if(handles) {
- if(!are_near((*cubic)[0],(*cubic)[1])){
+ point_at1 = (*cubic)[1];
+ point_at2 = (*cubic)[2];
+ }
+ if(start == Geom::Point(0,0)) {
+ start = point_at1;
+ }
+
+ if(path_it->closed() && curve_it2 == curve_endit) {
+ point_at4 = start;
+ }
+ if(curve_it2 != curve_endit) {
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
+ if (cubic) {
+ point_at4 = (*cubic)[1];
+ }
+ }
+ Geom::Ray ray1(point_at2, point_at3);
+ Geom::Ray ray2(point_at3, point_at4);
+ double angle1 = Geom::rad_to_deg(ray1.angle());
+ double angle2 = Geom::rad_to_deg(ray2.angle());
+ if((smooth_angles >= angle2 - angle1) && !are_near(point_at4,point_at3) && !are_near(point_at2,point_at3)) {
+ double dist = Geom::distance(point_at2,point_at3);
+ Geom::Angle angleFixed = ray2.angle();
+ angleFixed -= Geom::Angle::from_degrees(180.0);
+ point_at2 = Geom::Point::polar(angleFixed,dist) + point_at3;
+ }
+ nCurve->curveto(point_at1, point_at2, curve_it1->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(nCurve->last_segment());
+ if (cubic) {
+ point_at1 = (*cubic)[1];
+ point_at2 = (*cubic)[2];
+ if(helper_size > 0) {
+ if(!are_near((*cubic)[0],(*cubic)[1])) {
drawHandle((*cubic)[1]);
drawHandleLine((*cubic)[0],(*cubic)[1]);
}
- if(!are_near((*cubic)[3],(*cubic)[2])){
+ if(!are_near((*cubic)[3],(*cubic)[2])) {
drawHandle((*cubic)[2]);
drawHandleLine((*cubic)[3],(*cubic)[2]);
}
}
}
- if(nodes) {
+ if(helper_size > 0) {
drawNode(curve_it1->finalPoint());
}
++curve_it1;
- if(curve_it2 != curve_endit){
- ++curve_it2;
- }
+ ++curve_it2;
+ }
+ if (path_it->closed()) {
+ nCurve->closepath_current();
}
+ tmp_path.push_back(nCurve->get_pathvector()[0]);
+ nCurve->reset();
+ delete nCurve;
}
+ result = tmp_path;
}
-void
+void
LPESimplify::drawNode(Geom::Point p)
{
- double r = helper_size/0.67;
+ double r = radius_helper_nodes;
char const * svgd;
svgd = "M 0.55,0.5 A 0.05,0.05 0 0 1 0.5,0.55 0.05,0.05 0 0 1 0.45,0.5 0.05,0.05 0 0 1 0.5,0.45 0.05,0.05 0 0 1 0.55,0.5 Z M 0,0 1,0 1,1 0,1 Z";
Geom::PathVector pathv = sp_svg_read_pathv(svgd);
@@ -246,7 +273,7 @@ LPESimplify::drawNode(Geom::Point p)
void
LPESimplify::drawHandle(Geom::Point p)
{
- double r = helper_size/0.67;
+ double r = radius_helper_nodes;
char const * svgd;
svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z";
Geom::PathVector pathv = sp_svg_read_pathv(svgd);
@@ -261,8 +288,8 @@ LPESimplify::drawHandleLine(Geom::Point p,Geom::Point p2)
{
Geom::Path path;
path.start( p );
- double diameter = helper_size/0.67;
- if(helper_size > 0.0 && Geom::distance(p,p2) > (diameter * 0.35)){
+ double diameter = radius_helper_nodes;
+ if(helper_size > 0 && Geom::distance(p,p2) > (diameter * 0.35)) {
Geom::Ray ray2(p, p2);
p2 = p2 - Geom::Point::polar(ray2.angle(),(diameter * 0.35));
}
diff --git a/src/live_effects/lpe-simplify.h b/src/live_effects/lpe-simplify.h
index 6acf2f2d4..294d77b35 100644
--- a/src/live_effects/lpe-simplify.h
+++ b/src/live_effects/lpe-simplify.h
@@ -14,43 +14,43 @@
namespace Inkscape {
namespace LivePathEffect {
-class LPESimplify : public Effect , GroupBBoxEffect{
+class LPESimplify : public Effect , GroupBBoxEffect {
public:
- LPESimplify(LivePathEffectObject *lpeobject);
- virtual ~LPESimplify();
+ LPESimplify(LivePathEffectObject *lpeobject);
+ virtual ~LPESimplify();
- virtual void doEffect(SPCurve *curve);
+ virtual void doEffect(SPCurve *curve);
- virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
- virtual void generateHelperPath(Geom::PathVector result);
+ virtual void generateHelperPathAndSmooth(Geom::PathVector &result);
- virtual Gtk::Widget * newWidget();
+ virtual Gtk::Widget * newWidget();
- virtual void drawNode(Geom::Point p);
-
- virtual void drawHandle(Geom::Point p);
+ virtual void drawNode(Geom::Point p);
- virtual void drawHandleLine(Geom::Point p,Geom::Point p2);
+ virtual void drawHandle(Geom::Point p);
+
+ virtual void drawHandleLine(Geom::Point p,Geom::Point p2);
protected:
void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
private:
- ScalarParam steps;
- ScalarParam threshold;
- ScalarParam helper_size;
- ToggleButtonParam nodes;
- ToggleButtonParam handles;
- ToggleButtonParam simplifyindividualpaths;
- ToggleButtonParam simplifyJustCoalesce;
-
- Geom::PathVector hp;
- Geom::OptRect bbox;
-
- LPESimplify(const LPESimplify &);
- LPESimplify &operator=(const LPESimplify &);
+ ScalarParam steps;
+ ScalarParam threshold;
+ ScalarParam smooth_angles;
+ ScalarParam helper_size;
+ ToggleButtonParam simplify_individual_paths;
+ ToggleButtonParam simplify_just_coalesce;
+
+ double radius_helper_nodes;
+ Geom::PathVector hp;
+ Geom::OptRect bbox;
+
+ LPESimplify(const LPESimplify &);
+ LPESimplify &operator=(const LPESimplify &);
};
diff --git a/src/live_effects/lpe-sketch.cpp b/src/live_effects/lpe-sketch.cpp
index 8ad0e616f..551dbe16a 100644
--- a/src/live_effects/lpe-sketch.cpp
+++ b/src/live_effects/lpe-sketch.cpp
@@ -240,7 +240,7 @@ LPESketch::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_
for (unsigned i = 0; i<nbiter_approxstrokes; i++){
//Basic steps:
- //- Choose a rdm seg [s0,s1], find coresponding [t0,t1],
+ //- Choose a rdm seg [s0,s1], find corresponding [t0,t1],
//- Pick a rdm perturbation delta(s), collect 'piece(t)+delta(s(t))' over [t0,t1] into output.
// pick a point where to start the stroke (s0 = dist from start).
diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp
index 7a024147c..2c74af6d6 100644
--- a/src/live_effects/lpe-taperstroke.cpp
+++ b/src/live_effects/lpe-taperstroke.cpp
@@ -19,7 +19,8 @@
#include <2geom/circle.h>
#include <2geom/sbasis-to-bezier.h>
-#include "pathoutlineprovider.h"
+#include "helper/geom-nodetype.h"
+#include "helper/geom-pathstroke.h"
#include "display/curve.h"
#include "sp-shape.h"
#include "style.h"
@@ -60,11 +61,10 @@ namespace TpS {
} // TpS
static const Util::EnumData<unsigned> JoinType[] = {
- {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
- {LINEJOIN_ROUND, N_("Rounded"), "round"},
- {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"},
- {LINEJOIN_POINTY, N_("Miter"), "miter"},
- {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"}
+ {JOIN_BEVEL, N_("Beveled"), "bevel"},
+ {JOIN_ROUND, N_("Rounded"), "round"},
+ {JOIN_MITER, N_("Miter"), "miter"},
+ {JOIN_EXTRAPOLATE, N_("Extrapolated"), "extrapolated"},
};
static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType));
@@ -75,7 +75,7 @@ LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) :
attach_start(_("Start offset:"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2),
attach_end(_("End offset:"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2),
smoothing(_("Taper smoothing:"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5),
- join_type(_("Join type:"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
+ join_type(_("Join type:"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, JOIN_EXTRAPOLATE),
miter_limit(_("Miter limit:"), _("Limit for miter joins"), "miter_limit", &wr, this, 100.)
{
show_orig_path = true;
@@ -102,27 +102,24 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
SPCSSAttr *css = sp_repr_css_attr_new ();
- if (true) {
- if (lpeitem->style->stroke.isPaintserver()) {
- SPPaintServer * server = lpeitem->style->getStrokePaintServer();
- if (server) {
- Glib::ustring str;
- str += "url(#";
- str += server->getId();
- str += ")";
- sp_repr_css_set_property (css, "fill", str.c_str());
- }
- } else if (lpeitem->style->stroke.isColor()) {
- gchar c[64];
- sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
- sp_repr_css_set_property (css, "fill", c);
- } else {
- sp_repr_css_set_property (css, "fill", "none");
+ if (lpeitem->style->stroke.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getStrokePaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "fill", str.c_str());
}
+ } else if (lpeitem->style->stroke.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
+ sp_repr_css_set_property (css, "fill", c);
} else {
- sp_repr_css_unset_property (css, "fill");
+ sp_repr_css_set_property (css, "fill", "none");
}
+ sp_repr_css_set_property(css, "fill-rule", "nonzero");
sp_repr_css_set_property(css, "stroke", "none");
sp_desktop_apply_css_recursive(item, css, true);
@@ -130,7 +127,7 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
line_width.param_set_value(width);
} else {
- printf("WARNING: It only makes sense to apply Join Type to paths (not groups).\n");
+ printf("WARNING: It only makes sense to apply Taper stroke to paths (not groups).\n");
}
}
@@ -142,25 +139,21 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
SPCSSAttr *css = sp_repr_css_attr_new ();
- if (true) {
- if (lpeitem->style->fill.isPaintserver()) {
- SPPaintServer * server = lpeitem->style->getFillPaintServer();
- if (server) {
- Glib::ustring str;
- str += "url(#";
- str += server->getId();
- str += ")";
- sp_repr_css_set_property (css, "stroke", str.c_str());
- }
- } else if (lpeitem->style->fill.isColor()) {
- gchar c[64];
- sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
- sp_repr_css_set_property (css, "stroke", c);
- } else {
- sp_repr_css_set_property (css, "stroke", "none");
+ if (lpeitem->style->fill.isPaintserver()) {
+ SPPaintServer * server = lpeitem->style->getFillPaintServer();
+ if (server) {
+ Glib::ustring str;
+ str += "url(#";
+ str += server->getId();
+ str += ")";
+ sp_repr_css_set_property (css, "stroke", str.c_str());
}
+ } else if (lpeitem->style->fill.isColor()) {
+ gchar c[64];
+ sp_svg_write_color (c, sizeof(c), lpeitem->style->fill.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->fill_opacity.value)));
+ sp_repr_css_set_property (css, "stroke", c);
} else {
- sp_repr_css_unset_property (css, "stroke");
+ sp_repr_css_set_property (css, "stroke", "none");
}
Inkscape::CSSOStringStream os;
@@ -179,15 +172,22 @@ using Geom::D2;
using Geom::SBasis;
// leave Geom::Path
-Geom::Path return_at_first_cusp(Geom::Path const & path_in, double /*smooth_tolerance*/ = 0.05) {
- return Geom::split_at_cusps(path_in)[0];
+static Geom::Path return_at_first_cusp(Geom::Path const & path_in, double /*smooth_tolerance*/ = 0.05)
+{
+ Geom::Path temp;
+
+ for (unsigned i = 0; i < path_in.size(); i++) {
+ temp.append(path_in[i]);
+ if (Geom::get_nodetype(path_in[i], path_in[i + 1]) != Geom::NODE_SMOOTH ) {
+ break;
+ }
+ }
+
+ return temp;
}
Piecewise<D2<SBasis> > stretch_along(Piecewise<D2<SBasis> > pwd2_in, Geom::Path pattern, double width);
-// references to pointers
-void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second);
-
// actual effect
Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
@@ -285,7 +285,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
// although this seems obvious, it can probably lead to bugs.
if (!metInMiddle) {
// append the outside outline of the path (goes with the direction of the path)
- throwaway_path = Outline::PathOutsideOutline(pathv_out[1], -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+ throwaway_path = half_outline(pathv_out[1], fabs(line_width)/2., miter_limit, static_cast<LineJoinType>(join_type.get_value()));
if (!zeroStart && real_path.size() >= 1 && throwaway_path.size() >= 1) {
if (!Geom::are_near(real_path.finalPoint(), throwaway_path.initialPoint())) {
real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
@@ -317,7 +317,7 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
if (!metInMiddle) {
// append the inside outline of the path (against direction)
- throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(), -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+ throwaway_path = half_outline(pathv_out[1].reverse(), fabs(line_width)/2., miter_limit, static_cast<LineJoinType>(join_type.get_value()));
if (!Geom::are_near(real_path.finalPoint(), throwaway_path.initialPoint()) && real_path.size() >= 1) {
real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
@@ -347,85 +347,18 @@ Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
*/
Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in)
{
- size_t size = path_in[0].size();
-
- unsigned loc = (unsigned)attach_start;
- Geom::Curve * curve_start = path_in[0] [loc].duplicate();
-
- std::vector<Geom::Path> pathv_out;
- Geom::Path path_out = Geom::Path();
-
- Geom::Path trimmed_start = Geom::Path();
- Geom::Path trimmed_end = Geom::Path();
-
- for (size_t i = 0; i < loc; ++i) {
- trimmed_start.append(path_in[0] [i]);
- }
-
- Geom::Curve * temp;
- subdivideCurve(curve_start, attach_start - loc, temp, curve_start);
- trimmed_start.append(*temp);
- if (temp) delete temp; temp = 0;
-
- // special case: path is one segment long
- // special case: what if the two knots occupy the same segment?
- if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) {
-
- // If you look into it, I don't actually think there is a working way to do this
- // with only point math. So we use nearest_point instead.
- Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start);
-
- // it is just a dumb segment
- // we have to do some shifting here because the value changed when we reduced the length
- // of the previous segment.
-
- subdivideCurve(curve_start, t, curve_start, temp);
- trimmed_end.append(*temp);
- if (temp) delete temp; temp = 0;
-
- for (size_t j = (size - attach_end) + 1; j < size; ++j) {
- trimmed_end.append(path_in[0] [j]);
- }
+ Geom::Coord endTime = path_in[0].size() - attach_end;
- path_out.append(*curve_start);
- pathv_out.push_back(trimmed_start);
- pathv_out.push_back(path_out);
- pathv_out.push_back(trimmed_end);
- return pathv_out;
- }
-
- pathv_out.push_back(trimmed_start);
-
- // append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute)
- path_out.append(*curve_start);
-
- for (size_t k = loc + 1; k < (size - unsigned(attach_end)) - 1; ++k) {
- path_out.append(path_in[0] [k]);
- }
-
- // deal with the last segment in a very similar fashion to the first
- loc = size - attach_end;
-
- Geom::Curve * curve_end = path_in[0] [loc].duplicate();
-
- Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end);
-
- subdivideCurve(curve_end, t, curve_end, temp);
- trimmed_end.append(*temp);
- if (temp) delete temp; temp = 0;
-
- for (size_t j = (size - attach_end) + 1; j < size; ++j) {
- trimmed_end.append(path_in[0] [j]);
- }
-
- path_out.append(*curve_end);
- pathv_out.push_back(path_out);
-
- pathv_out.push_back(trimmed_end);
-
- if (curve_end) delete curve_end;
- if (curve_start) delete curve_start;
- return pathv_out;
+ Geom::Path p1 = path_in[0].portion(0., attach_start);
+ Geom::Path p2 = path_in[0].portion(attach_start, endTime);
+ Geom::Path p3 = path_in[0].portion(endTime, path_in[0].size());
+
+ Geom::PathVector out;
+ out.push_back(p1);
+ out.push_back(p2);
+ out.push_back(p3);
+
+ return out;
}
@@ -513,23 +446,6 @@ Piecewise<D2<SBasis> > stretch_along(Piecewise<D2<SBasis> > pwd2_in, Geom::Path
}
}
-void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second)
-{
- if (Geom::LineSegment* linear = dynamic_cast<Geom::LineSegment*>(curve_in)) {
- // special case for line segments
- std::pair<Geom::LineSegment, Geom::LineSegment> seg_pair = linear->subdivide(t);
- val_first = seg_pair.first.duplicate();
- val_second = seg_pair.second.duplicate();
- } else {
- // all other cases:
- Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(curve_in->toSBasis());
- std::pair<Geom::CubicBezier, Geom::CubicBezier> cubic_pair = cubic.subdivide(t);
- val_first = cubic_pair.first.duplicate();
- val_second = cubic_pair.second.duplicate();
- }
-}
-
-
void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
{
KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this);
diff --git a/src/live_effects/lpe-test-doEffect-stack.cpp b/src/live_effects/lpe-test-doEffect-stack.cpp
index 03e3e7997..c6787aae1 100644
--- a/src/live_effects/lpe-test-doEffect-stack.cpp
+++ b/src/live_effects/lpe-test-doEffect-stack.cpp
@@ -28,6 +28,7 @@ LPEdoEffectStackTest::LPEdoEffectStackTest(LivePathEffectObject *lpeobject) :
registerParameter( dynamic_cast<Parameter *>(&path) );
point.set_oncanvas_looks(SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR, 0x00ff0000);
+ point.param_setValue(point,true);
}
LPEdoEffectStackTest::~LPEdoEffectStackTest()
diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert
index f990f41c7..bd1c5b600 100644
--- a/src/live_effects/parameter/Makefile_insert
+++ b/src/live_effects/parameter/Makefile_insert
@@ -11,8 +11,6 @@ ink_common_sources += \
live_effects/parameter/random.h \
live_effects/parameter/point.cpp \
live_effects/parameter/point.h \
- live_effects/parameter/pointreseteable.cpp \
- live_effects/parameter/pointreseteable.h \
live_effects/parameter/enum.h \
live_effects/parameter/path-reference.cpp \
live_effects/parameter/path-reference.h \
diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp
index 2ebe11b4b..e9d375b93 100644
--- a/src/live_effects/parameter/filletchamferpointarray.cpp
+++ b/src/live_effects/parameter/filletchamferpointarray.cpp
@@ -354,7 +354,7 @@ void FilletChamferPointArrayParam::set_pwd2(
last_pwd2_normal = pwd2_normal_in;
}
-void FilletChamferPointArrayParam::set_document_unit(Glib::ustring const * value_document_unit)
+void FilletChamferPointArrayParam::set_document_unit(Glib::ustring value_document_unit)
{
documentUnit = value_document_unit;
}
diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h
index 6e5cce353..7849d5afb 100644
--- a/src/live_effects/parameter/filletchamferpointarray.h
+++ b/src/live_effects/parameter/filletchamferpointarray.h
@@ -53,7 +53,7 @@ public:
virtual void set_helper_size(int hs);
virtual void set_use_distance(bool use_knot_distance);
virtual void set_chamfer_steps(int value_chamfer_steps);
- virtual void set_document_unit(Glib::ustring const * value_document_unit);
+ virtual void set_document_unit(Glib::ustring value_document_unit);
virtual void set_unit(const gchar *abbr);
virtual void addCanvasIndicators(SPLPEItem const *lpeitem,
std::vector<Geom::PathVector> &hp_vec);
@@ -90,7 +90,7 @@ private:
int chamfer_steps;
bool use_distance;
const gchar *unit;
- Glib::ustring const * documentUnit;
+ Glib::ustring documentUnit;
Geom::PathVector hp;
Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2;
diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp
index 302818e55..4c4d2cd9c 100644
--- a/src/live_effects/parameter/point.cpp
+++ b/src/live_effects/parameter/point.cpp
@@ -26,7 +26,9 @@ namespace LivePathEffect {
PointParam::PointParam( const Glib::ustring& label, const Glib::ustring& tip,
const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
Effect* effect, const gchar *htip, Geom::Point default_value)
- : Geom::Point(default_value), Parameter(label, tip, key, wr, effect), defvalue(default_value)
+ : Parameter(label, tip, key, wr, effect),
+ defvalue(default_value),
+ knoth(NULL)
{
knot_shape = SP_KNOT_SHAPE_DIAMOND;
knot_mode = SP_KNOT_MODE_XOR;
@@ -43,7 +45,34 @@ PointParam::~PointParam()
void
PointParam::param_set_default()
{
- param_setValue(defvalue);
+ param_setValue(defvalue,true);
+}
+
+Geom::Point
+PointParam::param_get_default() const{
+ return defvalue;
+}
+
+void
+PointParam::param_update_default(Geom::Point newpoint)
+{
+ defvalue = newpoint;
+}
+
+void
+PointParam::param_setValue(Geom::Point newpoint, bool write)
+{
+ *dynamic_cast<Geom::Point *>( this ) = newpoint;
+ if(write){
+ Inkscape::SVGOStringStream os;
+ os << newpoint;
+ gchar * str = g_strdup(os.str().c_str());
+ param_write_to_repr(str);
+ g_free(str);
+ }
+ if(knoth){
+ knoth->update_knots();
+ }
}
bool
@@ -70,6 +99,12 @@ PointParam::param_getSVGValue() const
return str;
}
+void
+PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
+{
+ param_setValue( (*this) * postmul, true);
+}
+
Gtk::Widget *
PointParam::param_newWidget()
{
@@ -96,29 +131,6 @@ PointParam::param_newWidget()
}
void
-PointParam::param_setValue(Geom::Point newpoint)
-{
- *dynamic_cast<Geom::Point *>( this ) = newpoint;
-}
-
-void
-PointParam::param_set_and_write_new_value (Geom::Point newpoint)
-{
- Inkscape::SVGOStringStream os;
- os << newpoint;
- gchar * str = g_strdup(os.str().c_str());
- param_write_to_repr(str);
- g_free(str);
-}
-
-void
-PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
-{
- param_set_and_write_new_value( (*this) * postmul );
-}
-
-
-void
PointParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
{
knot_shape = shape;
@@ -129,7 +141,7 @@ PointParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint
class PointParamKnotHolderEntity : public KnotHolderEntity {
public:
PointParamKnotHolderEntity(PointParam *p) { this->pparam = p; }
- virtual ~PointParamKnotHolderEntity() {}
+ virtual ~PointParamKnotHolderEntity() { this->pparam->knoth = NULL;}
virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
virtual Geom::Point knot_get() const;
@@ -140,11 +152,25 @@ private:
};
void
-PointParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+PointParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
{
- Geom::Point const s = snap_knot_position(p, state);
- pparam->param_setValue(s);
- sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ Geom::Point s = snap_knot_position(p, state);
+ if (state & GDK_CONTROL_MASK) {
+ Geom::Point A(origin[Geom::X],p[Geom::Y]);
+ Geom::Point B(p[Geom::X],origin[Geom::Y]);
+ double distanceA = Geom::distance(A,p);
+ double distanceB = Geom::distance(B,p);
+ if(distanceA > distanceB){
+ s = B;
+ } else {
+ s = A;
+ }
+ }
+ pparam->param_setValue(s, true);
+ SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item);
+ if(splpeitem){
+ sp_lpe_item_update_patheffect(splpeitem, false, false);
+ }
}
Geom::Point
@@ -154,19 +180,27 @@ PointParamKnotHolderEntity::knot_get() const
}
void
-PointParamKnotHolderEntity::knot_click(guint /*state*/)
+PointParamKnotHolderEntity::knot_click(guint state)
{
- g_print ("This is the handle associated to parameter '%s'\n", pparam->param_key.c_str());
+ if (state & GDK_CONTROL_MASK) {
+ if (state & GDK_MOD1_MASK) {
+ this->pparam->param_set_default();
+ SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item);
+ if(splpeitem){
+ sp_lpe_item_update_patheffect(splpeitem, false, false);
+ }
+ }
+ }
}
void
PointParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
{
+ knoth = knotholder;
PointParamKnotHolderEntity *e = new PointParamKnotHolderEntity(this);
// TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself???
e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), knot_shape, knot_mode, knot_color);
knotholder->add(e);
-
}
} /* namespace LivePathEffect */
diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h
index 319835bb3..471fbc993 100644
--- a/src/live_effects/parameter/point.h
+++ b/src/live_effects/parameter/point.h
@@ -20,6 +20,7 @@ namespace Inkscape {
namespace LivePathEffect {
+class PointParamKnotHolderEntity;
class PointParam : public Geom::Point, public Parameter {
public:
@@ -37,12 +38,10 @@ public:
bool param_readSVGValue(const gchar * strvalue);
gchar * param_getSVGValue() const;
inline const gchar *handleTip() const { return handle_tip ? handle_tip : param_tooltip.c_str(); }
-
- void param_setValue(Geom::Point newpoint);
+ void param_setValue(Geom::Point newpoint, bool write = false);
void param_set_default();
-
- void param_set_and_write_new_value(Geom::Point newpoint);
-
+ Geom::Point param_get_default() const;
+ void param_update_default(Geom::Point newpoint);
virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
@@ -50,12 +49,12 @@ public:
virtual bool providesKnotHolderEntities() const { return true; }
virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
+ friend class PointParamKnotHolderEntity;
private:
PointParam(const PointParam&);
PointParam& operator=(const PointParam&);
-
Geom::Point defvalue;
-
+ KnotHolder *knoth;
SPKnotShapeType knot_shape;
SPKnotModeType knot_mode;
guint32 knot_color;
diff --git a/src/live_effects/parameter/pointreseteable.cpp b/src/live_effects/parameter/pointreseteable.cpp
deleted file mode 100644
index c0f8858b8..000000000
--- a/src/live_effects/parameter/pointreseteable.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "ui/widget/registered-widget.h"
-#include "live_effects/parameter/pointreseteable.h"
-#include "live_effects/effect.h"
-#include "svg/svg.h"
-#include "svg/stringstream.h"
-#include "ui/widget/point.h"
-#include "widgets/icon.h"
-#include "inkscape.h"
-#include "verbs.h"
-#include "knotholder.h"
-#include <glibmm/i18n.h>
-#include "ui/tools-switch.h"
-#include "ui/tools/node-tool.h"
-
-// needed for on-canvas editting:
-#include "desktop.h"
-
-namespace Inkscape {
-
-namespace LivePathEffect {
-
-PointReseteableParam::PointReseteableParam( const Glib::ustring& label, const Glib::ustring& tip,
- const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
- Effect* effect, const gchar *htip, Geom::Point default_value)
- : Geom::Point(default_value), Parameter(label, tip, key, wr, effect), defvalue(default_value)
-{
- knot_shape = SP_KNOT_SHAPE_DIAMOND;
- knot_mode = SP_KNOT_MODE_XOR;
- knot_color = 0xffffff00;
- handle_tip = g_strdup(htip);
-}
-
-PointReseteableParam::~PointReseteableParam()
-{
- if (handle_tip)
- g_free(handle_tip);
-}
-
-void
-PointReseteableParam::param_set_default()
-{
- param_setValue(defvalue);
-}
-
-void
-PointReseteableParam::param_set_and_write_default()
-{
- param_set_and_write_new_value(defvalue);
-}
-
-void
-PointReseteableParam::param_update_default(Geom::Point newpoint)
-{
- this->defvalue = newpoint;
-}
-
-bool
-PointReseteableParam::param_readSVGValue(const gchar * strvalue)
-{
- gchar ** strarray = g_strsplit(strvalue, ",", 2);
- double newx, newy;
- unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
- success += sp_svg_number_read_d(strarray[1], &newy);
- g_strfreev (strarray);
- if (success == 2) {
- param_setValue( Geom::Point(newx, newy) );
- return true;
- }
- return false;
-}
-
-gchar *
-PointReseteableParam::param_getSVGValue() const
-{
- Inkscape::SVGOStringStream os;
- os << *dynamic_cast<Geom::Point const *>( this );
- gchar * str = g_strdup(os.str().c_str());
- return str;
-}
-
-Gtk::Widget *
-PointReseteableParam::param_newWidget()
-{
- Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage(
- new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label,
- param_tooltip,
- param_key,
- *param_wr,
- param_effect->getRepr(),
- param_effect->getSPDoc() ) );
- // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- Geom::Affine transf = desktop->doc2dt();
- pointwdg->setTransform(transf);
- pointwdg->setValue( *this );
- pointwdg->clearProgrammatically();
- pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
-
- Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
- static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
- static_cast<Gtk::HBox*>(hbox)->show_all_children();
-
- return dynamic_cast<Gtk::Widget *> (hbox);
-}
-
-void
-PointReseteableParam::param_setValue(Geom::Point newpoint)
-{
- *dynamic_cast<Geom::Point *>( this ) = newpoint;
- if(SP_ACTIVE_DESKTOP){
- SPDesktop* desktop = SP_ACTIVE_DESKTOP;
- if (tools_isactive( desktop, TOOLS_NODES)) {
- Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>( desktop->event_context);
- nt->update_helperpath();
- }
- }
-}
-
-void
-PointReseteableParam::param_set_and_write_new_value (Geom::Point newpoint)
-{
- Inkscape::SVGOStringStream os;
- os << newpoint;
- gchar * str = g_strdup(os.str().c_str());
- param_write_to_repr(str);
- g_free(str);
-}
-
-void
-PointReseteableParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
-{
- param_set_and_write_new_value( (*this) * postmul );
-}
-
-
-void
-PointReseteableParam::set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
-{
- knot_shape = shape;
- knot_mode = mode;
- knot_color = color;
-}
-
-class PointReseteableParamKnotHolderEntity : public KnotHolderEntity {
-public:
- PointReseteableParamKnotHolderEntity(PointReseteableParam *p) { this->pparam = p; }
- virtual ~PointReseteableParamKnotHolderEntity() {}
-
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual Geom::Point knot_get() const;
- virtual void knot_click(guint state);
-
-private:
- PointReseteableParam *pparam;
-};
-
-void
-PointReseteableParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
-{
- Geom::Point const s = snap_knot_position(p, state);
- pparam->param_setValue(s);
- sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
-}
-
-Geom::Point
-PointReseteableParamKnotHolderEntity::knot_get() const
-{
- return *pparam;
-}
-
-void
-PointReseteableParamKnotHolderEntity::knot_click(guint state)
-{
- if (state & GDK_CONTROL_MASK) {
- if (state & GDK_MOD1_MASK) {
- this->pparam->param_set_default();
- sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
- }
- }
-}
-
-void
-PointReseteableParam::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
-{
- PointReseteableParamKnotHolderEntity *e = new PointReseteableParamKnotHolderEntity(this);
- // TODO: can we ditch handleTip() etc. because we have access to handle_tip etc. itself???
- e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, handleTip(), knot_shape, knot_mode, knot_color);
- knotholder->add(e);
-}
-
-} /* namespace LivePathEffect */
-
-} /* namespace Inkscape */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/pointreseteable.h b/src/live_effects/parameter/pointreseteable.h
deleted file mode 100644
index 5ae1fdf02..000000000
--- a/src/live_effects/parameter/pointreseteable.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
-#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_POINT_RESETEABLE_H
-
-/*
- * Inkscape::LivePathEffectParameters
- *
-* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <glib.h>
-#include <2geom/point.h>
-
-#include "live_effects/parameter/parameter.h"
-
-#include "knot-holder-entity.h"
-
-namespace Inkscape {
-
-namespace LivePathEffect {
-
-class PointReseteableParamKnotHolderEntity;
-
-class PointReseteableParam : public Geom::Point, public Parameter {
-public:
- PointReseteableParam( const Glib::ustring& label,
- const Glib::ustring& tip,
- const Glib::ustring& key,
- Inkscape::UI::Widget::Registry* wr,
- Effect* effect,
- const gchar *handle_tip = NULL,
- Geom::Point default_value = Geom::Point(0,0) ); // tip for automatically associated on-canvas handle
- virtual ~PointReseteableParam();
-
- virtual Gtk::Widget * param_newWidget();
-
- bool param_readSVGValue(const gchar * strvalue);
- gchar * param_getSVGValue() const;
- inline const gchar *handleTip() const { return handle_tip ? handle_tip : param_tooltip.c_str(); }
-
- void param_setValue(Geom::Point newpoint);
- void param_set_default();
- void param_set_and_write_default();
- void param_update_default(Geom::Point newpoint);
-
- void param_set_and_write_new_value(Geom::Point newpoint);
-
- virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
-
- void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
-
- virtual bool providesKnotHolderEntities() const { return true; }
- virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
-
- friend class PointReseteableParamKnotHolderEntity;
-private:
- PointReseteableParam(const PointReseteableParam&);
- PointReseteableParam& operator=(const PointReseteableParam&);
-
- Geom::Point defvalue;
-
- SPKnotShapeType knot_shape;
- SPKnotModeType knot_mode;
- guint32 knot_color;
- gchar *handle_tip;
-};
-
-
-} //namespace LivePathEffect
-
-} //namespace Inkscape
-
-#endif
diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp
deleted file mode 100644
index 21a0fb809..000000000
--- a/src/live_effects/pathoutlineprovider.cpp
+++ /dev/null
@@ -1,803 +0,0 @@
-/* Author:
- * Liam P. White <inkscapebrony@gmail.com>
- *
- * Copyright (C) 2014 Author
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <2geom/angle.h>
-#include <2geom/path.h>
-#include <2geom/circle.h>
-#include <2geom/sbasis-to-bezier.h>
-#include <2geom/shape.h>
-#include <2geom/transforms.h>
-#include <2geom/path-sink.h>
-#include <cstdio>
-
-#include "pathoutlineprovider.h"
-#include "livarot/path-description.h"
-#include "helper/geom-nodetype.h"
-#include "svg/svg.h"
-
-namespace Geom {
-/**
-* Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
- From MathWorld--A Wolfram Web Resource.
- http://mathworld.wolfram.com/Circle-CircleIntersection.html
-*
-* @return 0 if no intersection
-* @return 1 if one circle is contained in the other
-* @return 2 if intersections are found (they are written to p0 and p1)
-*/
-static int circle_circle_intersection(Circle const &circle0, Circle const &circle1, Point & p0, Point & p1)
-{
- Point X0 = circle0.center();
- double r0 = circle0.ray();
- Point X1 = circle1.center();
- double r1 = circle1.ray();
-
- /* dx and dy are the vertical and horizontal distances between
- * the circle centers.
- */
- Point D = X1 - X0;
-
- /* Determine the straight-line distance between the centers. */
- double d = L2(D);
-
- /* Check for solvability. */
- if (d > (r0 + r1)) {
- /* no solution. circles do not intersect. */
- return 0;
- }
- if (d <= fabs(r0 - r1)) {
- /* no solution. one circle is contained in the other */
- return 1;
- }
-
- /* 'point 2' is the point where the line through the circle
- * intersection points crosses the line between the circle
- * centers.
- */
-
- /* Determine the distance from point 0 to point 2. */
- double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
-
- /* Determine the coordinates of point 2. */
- Point p2 = X0 + D * (a/d);
-
- /* Determine the distance from point 2 to either of the
- * intersection points.
- */
- double h = std::sqrt((r0*r0) - (a*a));
-
- /* Now determine the offsets of the intersection points from
- * point 2.
- */
- Point r = (h/d)*rot90(D);
-
- /* Determine the absolute intersection points. */
- p0 = p2 + r;
- p1 = p2 - r;
-
- return 2;
-}
-/**
-* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
-* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
-*/
-static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
-{
- D2<SBasis> dM=derivative(curve);
- if ( are_near(L2sq(dM(t)),0.) ) {
- dM=derivative(dM);
- }
- if ( are_near(L2sq(dM(t)),0.) ) { // try second time
- dM=derivative(dM);
- }
- Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
- Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
- Piecewise<SBasis> k = cross(derivative(unitv),unitv);
- k = divide(k,dMlength,tol,3);
- double curv = k(t); // note that this value is signed
-
- Geom::Point normal = unitTangentAt(curve, t).cw();
- double radius = 1/curv;
- Geom::Point center = curve(t) + radius*normal;
- return Geom::Circle(center, fabs(radius));
-}
-
-std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
-{
- PathVector out = PathVector();
- Path temp = Path();
-
- for (unsigned i = 0; i < in.size(); i++) {
- temp.append(in[i]);
- if ( get_nodetype(in[i], in[i + 1]) != Geom::NODE_SMOOTH ) {
- out.push_back(temp);
- temp = Path();
- }
- }
- if (temp.size() > 0) {
- out.push_back(temp);
- }
- return out;
-}
-
-Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
-{
- std::vector<Geom::Point> temp;
- sbasis_to_bezier(temp, sbasis_in, 4);
- return Geom::CubicBezier( temp );
-}
-
-static boost::optional<Geom::Point> intersection_point(Geom::Point const & origin_a, Geom::Point const & vector_a, Geom::Point const & origin_b, Geom::Point const & vector_b)
-{
- Geom::Coord denom = cross(vector_b, vector_a);
- if (!Geom::are_near(denom,0.)) {
- Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
- return origin_a + t * vector_a;
- }
- return boost::none;
-}
-
-} // namespace Geom
-
-namespace Outline {
-
-typedef Geom::D2<Geom::SBasis> D2SB;
-typedef Geom::Piecewise<D2SB> PWD2;
-
-// UTILITY
-
-unsigned bezierOrder (const Geom::Curve* curve_in)
-{
- using namespace Geom;
- if ( const BezierCurve* bz = dynamic_cast<const BezierCurve*>(curve_in) ) {
- return bz->order();
- }
- return 0;
-}
-
-/**
- * @return true if the angle formed by the curves and their handles is greater than 180 degrees clockwise, otherwise false.
- */
-bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2)
-{
- Geom::Point start_point;
- Geom::Point cross_point = cbc1.finalPoint();
- Geom::Point end_point;
-
- if (cross_point != cbc2.initialPoint()) {
- printf("WARNING: Non-contiguous path in Outline::outside_angle()");
- return false;
- }
-
- Geom::CubicBezier cubicBezier = Geom::sbasis_to_cubicbezier(cbc1.toSBasis());
- start_point = cubicBezier [2];
-
- /*
- * Because the node editor does not yet support true quadratics, paths are converted to
- * cubic beziers in the node tool with degenerate handles on one side.
- */
-
- if (are_near(start_point, cross_point, 0.0000001)) {
- start_point = cubicBezier [1];
- }
- cubicBezier = Geom::sbasis_to_cubicbezier(cbc2.toSBasis());
- end_point = cubicBezier [1];
- if (are_near(end_point, cross_point, 0.0000001)) {
- end_point = cubicBezier [2];
- }
-
- // got our three points, now let's see what their clockwise angle is
-
- // Definition of a Graham scan
-
- /********************************************************************
- # Three points are a counter-clockwise turn if ccw > 0, clockwise if
- # ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
- # gives the signed area of the triangle formed by p1, p2 and p3.
- function ccw(p1, p2, p3):
- return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
- *********************************************************************/
-
- double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) -
- ( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) );
- return ccw > 0;
-}
-
-// LINE JOINS
-
-typedef Geom::BezierCurveN<1u> BezierLine;
-
-/**
- * Removes the crossings on an interior join.
- * @param path_builder Contains the incoming segment; result is appended to this
- * @param outgoing The outgoing segment
- */
-void joinInside(Geom::Path& path_builder, Geom::Curve const& outgoing)
-{
- Geom::Curve const& incoming = path_builder.back();
-
- // Using Geom::crossings to find intersections between two curves
- Geom::Crossings cross = Geom::crossings(incoming, outgoing);
- if (!cross.empty()) {
- // Crossings found, create the join
- Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(incoming.toSBasis());
- cubic = cubic.subdivide(cross[0].ta).first;
- // erase the last segment, as we're going to overwrite it now
- path_builder.erase_last();
- path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS);
-
- cubic = Geom::sbasis_to_cubicbezier(outgoing.toSBasis());
- cubic = cubic.subdivide(cross[0].tb).second;
- path_builder.append(cubic, Geom::Path::STITCH_DISCONTINUOUS);
- } else {
- // No crossings occurred, or Geom::crossings() failed; default to bevel
- if (Geom::are_near(incoming.finalPoint(), outgoing.initialPoint())) {
- path_builder.appendNew<BezierLine>(outgoing.initialPoint());
- } else {
- path_builder.setFinal(outgoing.initialPoint());
- }
- }
-}
-
-/**
- * Try to create a miter join. Falls back to bevel if no miter can be created.
- * @param path_builder Path to append curves to; back() is the incoming curve
- * @param outgoing Outgoing curve.
- * @param miter_limit When mitering, don't exceed this length
- * @param line_width The thickness of the line.
- */
-void miter_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
-{
- using namespace Geom;
- Curve const& incoming = path_builder.back();
- Point tang1 = unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.);
- Point tang2 = unitTangentAt(outgoing.toSBasis(), 0);
-
- boost::optional <Point> p = intersection_point (incoming.finalPoint(), tang1, outgoing.initialPoint(), tang2);
- if (p) {
- // check size of miter
- Point point_on_path = incoming.finalPoint() - rot90(tang1) * line_width;
- Coord len = distance(*p, point_on_path);
- if (len <= miter_limit) {
- // miter OK
- path_builder.appendNew<BezierLine>(*p);
- }
- }
- path_builder.appendNew<BezierLine>(outgoing.initialPoint());
-}
-
-/**
- * Smoothly extrapolate curves along a circular route. Falls back to miter if necessary.
- * @param path_builder Path to append curves to; back() is the incoming curve
- * @param outgoing Outgoing curve.
- * @param miter_limit When mitering, don't exceed this length
- * @param line_width The thickness of the line. Used for miter fallback.
- */
-void extrapolate_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
-{
- Geom::Curve const& incoming = path_builder.back();
- Geom::Point endPt = outgoing.initialPoint();
-
- // The method used when extrapolating curves fails to work when either side of the join to be extrapolated
- // is a line segment. When this situation is encountered, fall back to a regular miter join.
- bool lineProblem = (dynamic_cast<const BezierLine *>(&incoming)) || (dynamic_cast<const BezierLine *>(&outgoing));
- if (lineProblem == false) {
- // Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(incoming.toSBasis()), 0.);
- Geom::Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0);
-
- Geom::Circle circle1 = Geom::touching_circle(Geom::reverse(incoming.toSBasis()), 0.);
- Geom::Circle circle2 = Geom::touching_circle(outgoing.toSBasis(), 0);
-
- Geom::Point points[2];
- int solutions = Geom::circle_circle_intersection(circle1, circle2, points[0], points[1]);
- if (solutions == 2) {
- Geom::Point sol(0,0);
- if ( dot(tang2,points[0]-endPt) > 0 ) {
- // points[0] is bad, choose points[1]
- sol = points[1];
- } else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1]
- // points[1] is bad, choose points[0]
- sol = points[0];
- } else {
- // both points are good, choose nearest
- sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? points[0] : points[1];
- }
-
- Geom::EllipticalArc *arc0 = circle1.arc(incoming.finalPoint(), 0.5*(incoming.finalPoint()+sol), sol, true);
- Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
- try {
- if (arc0) {
- path_builder.append (arc0->toSBasis());
- delete arc0;
- arc0 = NULL;
- } else {
- throw std::exception();
- }
-
- if (arc1) {
- path_builder.append (arc1->toSBasis());
- delete arc1;
- arc1 = NULL;
- } else {
- throw std::exception();
- }
-
- } catch (std::exception const & ex) {
- printf("WARNING: Error extrapolating line join: %s\n", ex.what());
- path_builder.appendNew<Geom::LineSegment>(endPt);
- }
- } else {
- // 1 or no solutions found, default to miter
- miter_curves(path_builder, outgoing, miter_limit, line_width);
- }
- } else {
- // Line segments exist
- miter_curves(path_builder, outgoing, miter_limit, line_width);
- }
-}
-
-/**
- * Extrapolate curves by reflecting them along the line that would be given by beveling the join.
- * @param path_builder Path to append curves to; back() is the incoming curve
- * @param outgoing Outgoing curve.
- * @param miter_limit When mitering, don't exceed this length
- * @param line_width The thickness of the line. Used for miter fallback.
- */
-void reflect_curves(Geom::Path& path_builder, Geom::Curve const& outgoing, double miter_limit, double line_width)
-{
- using namespace Geom;
- Curve const& incoming = path_builder.back();
- // On the outside, we'll take the incoming curve, the outgoing curve, and
- // reflect them over the line formed by taking the unit tangent vector at times
- // 0 and 1, respectively, rotated by 90 degrees.
- Crossings cross;
-
- // reflect curves along the line that would be given by beveling the join
- Point tang1 = unitTangentAt(reverse(incoming.toSBasis()), 0.);
- D2SB newcurve1 = incoming.toSBasis() * reflection(-rot90(tang1), incoming.finalPoint());
- CubicBezier bzr1 = sbasis_to_cubicbezier(reverse(newcurve1));
-
- Point tang2 = Geom::unitTangentAt(outgoing.toSBasis(), 0.);
- D2SB newcurve2 = outgoing.toSBasis() * reflection(-rot90(tang2), outgoing.initialPoint());
- CubicBezier bzr2 = sbasis_to_cubicbezier(reverse(newcurve2));
-
- cross = crossings(bzr1, bzr2);
- if (cross.empty()) {
- // paths don't cross, fall back to miter
- miter_curves(path_builder, outgoing, miter_limit, line_width);
- } else {
- // reflected join
- std::pair<CubicBezier, CubicBezier> sub1 = bzr1.subdivide(cross[0].ta);
- std::pair<CubicBezier, CubicBezier> sub2 = bzr2.subdivide(cross[0].tb);
-
- // TODO it seems as if a bug in 2geom sometimes doesn't catch the first
- // crossing of paths, but the second instead; but only sometimes.
- path_builder.appendNew <CubicBezier> (sub1.first[1], sub1.first[2], sub2.second[0]);
- path_builder.appendNew <CubicBezier> (sub2.second[1], sub2.second[2], outgoing.initialPoint());
- }
-}
-
-// Ideal function pointer we want to pass
-typedef void JoinFunc(Geom::Path& /*path_builder*/, Geom::Curve const& /*outgoing*/, double /*miter_limit*/, double /*line_width*/);
-
-/**
- * Helper function for repeated logic in outlineHalf.
- */
-static void outlineHelper(Geom::Path& path_builder, Geom::PathVector* path_vec, bool outside, double width, double miter, JoinFunc func)
-{
- Geom::Curve * cbc2 = path_vec->front()[0].duplicate();
-
- if (outside) {
- func(path_builder, *cbc2, miter, width);
- } else {
- joinInside(path_builder, *cbc2);
- }
-
- // store it
- Geom::Path temp_path = path_vec->front();
- if (!outside) {
- // erase the first segment since the inside join code already appended it
- temp_path.erase(temp_path.begin());
- }
-
- if (temp_path.initialPoint() != path_builder.finalPoint()) {
- temp_path.setInitial(path_builder.finalPoint());
- }
-
- path_builder.append(temp_path);
-
- delete cbc2;
-}
-
-/**
- * Offsets exactly one half of a bezier spline (path).
- * @param path_in The input path to use. (To create the other side use path_in.reverse() )
- * @param line_width the line width to use (usually you want to divide this by 2)
- * @param miter_limit the miter parameter
- * @param func Join function to apply at each join.
- */
-
-Geom::Path outlineHalf(const Geom::Path& path_in, double line_width, double miter_limit, JoinFunc func)
-{
- // NOTE: it is important to notice the distinction between a Geom::Path and a livarot ::Path here!
- // if you do not see "Geom::" there is a different function set!
-
- Geom::PathVector pv = split_at_cusps(path_in);
-
- ::Path to_outline;
- ::Path outlined_result;
-
- Geom::Path path_builder = Geom::Path(); // the path to store the result in
- Geom::PathVector* path_vec; // needed because livarot returns a pointer (TODO make this not a pointer)
-
- // Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well
- const size_t k = pv.size();
- for (size_t u = 0; u < k; u += 2) {
- to_outline = Path();
- outlined_result = Path();
-
- to_outline.LoadPath(pv[u], Geom::identity(), false, false);
- to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
- // now a curve has been outside outlined and loaded into outlined_result
-
- // get the Geom::Path
- path_vec = outlined_result.MakePathVector();
-
- // on the first run through, there is no join
- if (u == 0) {
- path_builder.start(path_vec->front().initialPoint());
- path_builder.append(path_vec->front());
- } else {
- outlineHelper(path_builder, path_vec, outside_angle(pv[u-1][pv[u-1].size()-1], pv[u][0]), line_width, miter_limit, func);
- }
-
- // outline the next segment, but don't store it yet
- if (path_vec)
- delete path_vec;
- path_vec = NULL;
-
- // odd number of paths
- if (u < k - 1) {
- outlined_result = Path();
- to_outline = Path();
-
- to_outline.LoadPath(pv[u+1], Geom::Affine(), false, false);
- to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
- path_vec = outlined_result.MakePathVector();
- outlineHelper(path_builder, path_vec, outside_angle(pv[u][pv[u].size()-1], pv[u+1][0]), line_width, miter_limit, func);
-
- if (path_vec)
- delete path_vec;
- path_vec = NULL;
- }
- }
-
- if (path_in.closed()) {
- Geom::Curve * cbc1;
- Geom::Curve * cbc2;
-
- if ( path_in[path_in.size()].isDegenerate() ) {
- // handle case for last segment curved
- outlined_result = Path();
- to_outline = Path();
-
- Geom::Path oneCurve; oneCurve.append(path_in[0]);
-
- to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
- to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
- path_vec = outlined_result.MakePathVector();
-
- cbc1 = path_builder[path_builder.size() - 1].duplicate();
- cbc2 = path_vec->front()[0].duplicate();
-
- delete path_vec;
- } else {
- // handle case for last segment straight
- // since the path doesn't actually give us access to it, we'll do it ourselves
- outlined_result = Path();
- to_outline = Path();
-
- Geom::Path oneCurve; oneCurve.append(Geom::LineSegment(path_in.finalPoint(), path_in.initialPoint()));
-
- to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
- to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
- path_vec = outlined_result.MakePathVector();
-
- cbc1 = path_builder[path_builder.size() - 1].duplicate();
- cbc2 = (*path_vec)[0] [0].duplicate();
-
- outlineHelper(path_builder, path_vec, outside_angle(path_in[path_in.size()-1], oneCurve[0]), line_width, miter_limit, func);
-
- delete cbc1;
- cbc1 = cbc2->duplicate();
- delete path_vec;
-
- oneCurve = Geom::Path(); oneCurve.append(path_in[0]);
-
- to_outline.LoadPath(oneCurve, Geom::Affine(), false, false);
- to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
- path_vec = outlined_result.MakePathVector();
- delete cbc2; cbc2 = (*path_vec)[0] [0].duplicate();
- delete path_vec;
- }
-
- Geom::Path temporary;
- temporary.append(*cbc1);
-
- Geom::Curve const & prev_curve = path_in[path_in.size()].isDegenerate() ? path_in[path_in.size() - 1] : path_in[path_in.size()];
- Geom::Path isStraight;
- isStraight.append(prev_curve);
- isStraight.append(path_in[0]);
- // does closing path require a join?
- if (Geom::split_at_cusps(isStraight).size() > 1) {
- bool outside = outside_angle(prev_curve, path_in[0]);
- if (outside) {
- func(temporary, *cbc2, miter_limit, line_width);
- } else {
- joinInside(temporary, *cbc2);
- path_builder.erase(path_builder.begin());
- }
-
- // extract the appended curves
- path_builder.erase_last();
- if (Geom::are_near(path_builder.finalPoint(), temporary.initialPoint())) {
- path_builder.setFinal(temporary.initialPoint());
- } else {
- path_builder.appendNew<BezierLine>(temporary.initialPoint());
- }
- path_builder.append(temporary);
- } else {
- // closing path does not require a join
- path_builder.setFinal(path_builder.initialPoint());
- }
- path_builder.close();
-
- if (cbc1) delete cbc1;
- if (cbc2) delete cbc2;
- }
-
- return path_builder;
-}
-
-Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join, ButtTypeMod butt, double miter_lim, bool extrapolate, double start_lean, double end_lean)
-{
- Geom::PathVector path_out;
-
- unsigned pv_size = path_in.size();
- for (unsigned i = 0; i < pv_size; i++) {
-
- if (path_in[i].size() > 1) {
- Geom::Path with_direction;
- Geom::Path against_direction;
-
- with_direction = Outline::outlineHalf(path_in[i], -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves);
- against_direction = Outline::outlineHalf(path_in[i].reverse(), -line_width, miter_lim, extrapolate ? extrapolate_curves : reflect_curves);
-
- Geom::PathBuilder pb;
-
- pb.moveTo(with_direction.initialPoint());
- pb.append(with_direction);
-
- //add in our line caps
- if (!path_in[i].closed()) {
- switch (butt) {
- case BUTT_STRAIGHT:
- pb.lineTo(against_direction.initialPoint());
- break;
- case BUTT_ROUND:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
- break;
- case BUTT_POINTY: {
- Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
- double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
- Geom::Point midpoint = 0.5 * (with_direction.finalPoint() + against_direction.initialPoint()) + radius*end_deriv;
- pb.lineTo(midpoint);
- pb.lineTo(against_direction.initialPoint());
- break;
- }
- case BUTT_SQUARE: {
- Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
- double radius = 0.5 * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
- pb.lineTo(with_direction.finalPoint() + radius*end_deriv);
- pb.lineTo(against_direction.initialPoint() + radius*end_deriv);
- pb.lineTo(against_direction.initialPoint());
- break;
- }
- case BUTT_LEANED: {
- Geom::Point end_deriv = -Geom::unitTangentAt(Geom::reverse(path_in[i].back().toSBasis()), 0.);
- double maxRadius = (end_lean+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
- double minRadius = ((end_lean*-1)+0.5) * Geom::distance(with_direction.finalPoint(), against_direction.initialPoint());
- pb.lineTo(with_direction.finalPoint() + maxRadius*end_deriv);
- pb.lineTo(against_direction.initialPoint() + minRadius*end_deriv);
- pb.lineTo(against_direction.initialPoint());
- break;
- }
- }
- } else {
- pb.moveTo(against_direction.initialPoint());
- }
-
- pb.append(against_direction);
-
- //cap (if necessary)
- if (!path_in[i].closed()) {
- switch (butt) {
- case BUTT_STRAIGHT:
- pb.lineTo(with_direction.initialPoint());
- break;
- case BUTT_ROUND:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
- break;
- case BUTT_POINTY: {
- Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
- double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
- Geom::Point midpoint = 0.5 * (against_direction.finalPoint() + with_direction.initialPoint()) + radius*end_deriv;
- pb.lineTo(midpoint);
- pb.lineTo(with_direction.initialPoint());
- break;
- }
- case BUTT_SQUARE: {
- Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
- double radius = 0.5 * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
- pb.lineTo(against_direction.finalPoint() + radius*end_deriv);
- pb.lineTo(with_direction.initialPoint() + radius*end_deriv);
- pb.lineTo(with_direction.initialPoint());
- break;
- }
- case BUTT_LEANED: {
- Geom::Point end_deriv = -Geom::unitTangentAt(path_in[i].front().toSBasis(), 0.);
- double maxRadius = (start_lean+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
- double minRadius = ((start_lean*-1)+0.5) * Geom::distance(against_direction.finalPoint(), with_direction.initialPoint());
- pb.lineTo(against_direction.finalPoint() + minRadius*end_deriv);
- pb.lineTo(with_direction.initialPoint() + maxRadius*end_deriv);
- pb.lineTo(with_direction.initialPoint());
- break;
- }
- }
- }
- pb.flush();
- path_out.push_back(pb.peek()[0]);
- if (path_in[i].closed()) {
- path_out.push_back(pb.peek()[1]);
- }
- } else {
- Path p = Path();
- Path outlinepath = Path();
- ButtType original_butt;
- switch (butt) {
- case BUTT_STRAIGHT:
- original_butt = butt_straight;
- break;
- case BUTT_ROUND:
- original_butt = butt_round;
- break;
- case butt_pointy: {
- original_butt = butt_pointy;
- break;
- }
- case BUTT_SQUARE: {
- original_butt = butt_square;
- break;
- }
- case BUTT_LEANED: {
- original_butt = butt_straight;
- break;
- }
- }
- p.LoadPath(path_in[i], Geom::Affine(), false, false);
- p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(join), original_butt, miter_lim);
- Geom::PathVector *pv_p = outlinepath.MakePathVector();
- //somewhat hack-ish
- path_out.push_back( (*pv_p)[0].reverse() );
- if (pv_p) delete pv_p;
- }
- }
- return path_out;
-}
-
-#define miter_lim fabs(line_width * miter_limit)
-
-Geom::PathVector PathVectorOutline(Geom::PathVector const & path_in, double line_width, ButtTypeMod linecap_type, LineJoinType linejoin_type, double miter_limit, double start_lean, double end_lean)
-{
- std::vector<Geom::Path> path_out = std::vector<Geom::Path>();
- if (path_in.empty()) {
- return path_out;
- }
- Path p = Path();
- Path outlinepath = Path();
- for (unsigned i = 0; i < path_in.size(); i++) {
- p.LoadPath(path_in[i], Geom::Affine(), false, ( (i==0) ? false : true));
- }
-
- // magic!
- ButtType original_butt;
- switch (linecap_type) {
- case BUTT_STRAIGHT:
- original_butt = butt_straight;
- break;
- case BUTT_ROUND:
- original_butt = butt_round;
- break;
- case butt_pointy: {
- original_butt = butt_pointy;
- break;
- }
- case BUTT_SQUARE: {
- original_butt = butt_square;
- break;
- }
- case BUTT_LEANED: {
- original_butt = butt_straight;
- break;
- }
- }
- if (linejoin_type <= LINEJOIN_POINTY) {
- p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(linejoin_type),
- original_butt, miter_lim);
- // fix memory leak
- std::vector<Geom::Path> *pv_p = outlinepath.MakePathVector();
- path_out = *pv_p;
- delete pv_p;
-
- } else if (linejoin_type == LINEJOIN_REFLECTED) {
- // reflected arc join
- path_out = outlinePath(path_in, line_width, static_cast<LineJoinType>(linejoin_type),
- linecap_type , miter_lim, false, start_lean, end_lean);
-
- } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) {
- // extrapolated arc join
- path_out = outlinePath(path_in, line_width, LINEJOIN_STRAIGHT, linecap_type, miter_lim, true, start_lean, end_lean);
- }
-
- return path_out;
-}
-
-Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit)
-{
-
- Geom::Path path_out;
-
- if (linejoin_type <= LINEJOIN_POINTY || path_in.size() <= 1) {
-
- Geom::PathVector * pathvec;
-
- Path path_tangent = Path();
- Path path_outline = Path();
- path_outline.LoadPath(path_in, Geom::Affine(), false, false);
- path_outline.OutsideOutline(&path_tangent, line_width / 2, static_cast<join_typ>(linejoin_type), butt_straight, miter_lim);
-
- pathvec = path_tangent.MakePathVector();
- path_out = pathvec->front();
- delete pathvec;
- return path_out;
- } else if (linejoin_type == LINEJOIN_REFLECTED) {
- path_out = outlineHalf(path_in, line_width, miter_lim, reflect_curves);
- return path_out;
- } else if (linejoin_type == LINEJOIN_EXTRAPOLATED) {
- path_out = outlineHalf(path_in, line_width, miter_lim, extrapolate_curves);
- return path_out;
- }
- return path_out;
-}
-
-} // namespace Outline
-
-/*
- 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:encoding=utf-8 :
diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h
deleted file mode 100644
index c17584be2..000000000
--- a/src/live_effects/pathoutlineprovider.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef SEEN_PATH_OUTLINE_H
-#define SEEN_PATH_OUTLINE_H
-
-/* Author:
- * Liam P. White <inkscapebrony@gmail.com>
- *
- * Copyright (C) 2014 Author
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <livarot/Path.h>
-#include <livarot/LivarotDefs.h>
-
-enum LineJoinType {
- LINEJOIN_STRAIGHT,
- LINEJOIN_ROUND,
- LINEJOIN_POINTY,
- LINEJOIN_REFLECTED,
- LINEJOIN_EXTRAPOLATED
-};
-enum ButtTypeMod {
- BUTT_STRAIGHT,
- BUTT_ROUND,
- BUTT_SQUARE,
- BUTT_POINTY,
- BUTT_LEANED
-};
-
-namespace Geom
-{
- Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in);
- std::vector<Geom::Path> split_at_cusps(const Geom::Path& in);
-}
-
-namespace Outline
-{
- unsigned bezierOrder (const Geom::Curve* curve_in);
- std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtTypeMod linecap_type,
- LineJoinType linejoin_type, double miter_limit, double start_lean = 0, double end_lean = 0);
- Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit);
-}
-
-#endif // SEEN_PATH_OUTLINE_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 :
diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp
index 441ce6ea6..8304db684 100644
--- a/src/selection-describer.cpp
+++ b/src/selection-describer.cpp
@@ -233,8 +233,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select
int n_terms = count_terms(items);
gchar *objects_str = g_strdup_printf(ngettext(
- "<b>%i</b> objects selected of type %s",
- "<b>%i</b> objects selected of types %s", n_terms),
+ "<b>%1$i</b> objects selected of type %2$s",
+ "<b>%1$i</b> objects selected of types %2$s", n_terms),
objcount, terms);
g_free(terms);
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index 885fedafa..932a3a1b7 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -95,6 +95,10 @@ void SPGenericEllipse::build(SPDocument *document, Inkscape::XML::Node *repr)
std::cerr << "SPGenericEllipse::build() unknown defined type." << std::endl;
}
+ // std::cout << " cx: " << cx.write() << std::endl;
+ // std::cout << " cy: " << cy.write() << std::endl;
+ // std::cout << " rx: " << rx.write() << std::endl;
+ // std::cout << " ry: " << ry.write() << std::endl;
SPShape::build(document, repr);
}
@@ -103,29 +107,41 @@ void SPGenericEllipse::set(unsigned int key, gchar const *value)
// There are multiple ways to set internal cx, cy, rx, and ry (via SVG attributes or Sodipodi
// attributes) thus we don't want to unset them if a read fails (e.g., when we explicitly clear
// an attribute by setting it to NULL).
+
+ // We must update the SVGLengths immediately or nodes may be misplaced after they are moved.
+ double const w = viewport.width();
+ double const h = viewport.height();
+ double const d = hypot(w, h) / sqrt(2); // diagonal
+ double const em = style->font_size.computed;
+ double const ex = em * 0.5;
+
SVGLength t;
switch (key) {
case SP_ATTR_CX:
case SP_ATTR_SODIPODI_CX:
if( t.read(value) ) cx = t;
+ cx.update( em, ex, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_CY:
case SP_ATTR_SODIPODI_CY:
if( t.read(value) ) cy = t;
+ cy.update( em, ex, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_RX:
case SP_ATTR_SODIPODI_RX:
- if( t.read(value) && t.value > 0.0 ) this->rx = t;
+ if( t.read(value) && t.value > 0.0 ) rx = t;
+ rx.update( em, ex, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_RY:
case SP_ATTR_SODIPODI_RY:
- if( t.read(value) && t.value > 0.0 ) this->ry = t;
+ if( t.read(value) && t.value > 0.0 ) ry = t;
+ ry.update( em, ex, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -133,6 +149,8 @@ void SPGenericEllipse::set(unsigned int key, gchar const *value)
if( t.read(value) && t.value > 0.0 ) {
this->ry = this->rx = t;
}
+ rx.update( em, ex, d );
+ ry.update( em, ex, d );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -196,7 +214,7 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
// << ")" << std::endl;
GenericEllipseType new_type = SP_GENERIC_ELLIPSE_UNDEFINED;
- if (this->_isSlice() || hasPathEffect() ) {
+ if (_isSlice() || hasPathEffect() ) {
new_type = SP_GENERIC_ELLIPSE_ARC;
} else if ( rx.computed == ry.computed ) {
new_type = SP_GENERIC_ELLIPSE_CIRCLE;
@@ -246,10 +264,10 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
}
// std::cout << " type: " << g_quark_to_string( repr->code() ) << std::endl;
- // std::cout << " cx: " << cx.computed
- // << " cy: " << cy.computed
- // << " rx: " << rx.computed
- // << " ry: " << ry.computed << std::endl;
+ // std::cout << " cx: " << cx.write() << " " << cx.computed
+ // << " cy: " << cy.write() << " " << cy.computed
+ // << " rx: " << rx.write() << " " << rx.computed
+ // << " ry: " << ry.write() << " " << ry.computed << std::endl;
switch ( type ) {
case SP_GENERIC_ELLIPSE_UNDEFINED:
@@ -264,17 +282,17 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
if (flags & SP_OBJECT_WRITE_EXT) {
repr->setAttribute("sodipodi:type", "arc");
- sp_repr_set_svg_double(repr, "sodipodi:cx", this->cx.computed);
- sp_repr_set_svg_double(repr, "sodipodi:cy", this->cy.computed);
- sp_repr_set_svg_double(repr, "sodipodi:rx", this->rx.computed);
- sp_repr_set_svg_double(repr, "sodipodi:ry", this->ry.computed);
+ sp_repr_set_svg_length(repr, "sodipodi:cx", cx);
+ sp_repr_set_svg_length(repr, "sodipodi:cy", cy);
+ sp_repr_set_svg_length(repr, "sodipodi:rx", rx);
+ sp_repr_set_svg_length(repr, "sodipodi:ry", ry);
// write start and end only if they are non-trivial; otherwise remove
- if (this->_isSlice()) {
- sp_repr_set_svg_double(repr, "sodipodi:start", this->start);
- sp_repr_set_svg_double(repr, "sodipodi:end", this->end);
+ if (_isSlice()) {
+ sp_repr_set_svg_double(repr, "sodipodi:start", start);
+ sp_repr_set_svg_double(repr, "sodipodi:end", end);
- repr->setAttribute("sodipodi:open", (!this->_closed) ? "true" : NULL);
+ repr->setAttribute("sodipodi:open", (!_closed) ? "true" : NULL);
} else {
repr->setAttribute("sodipodi:end", NULL);
repr->setAttribute("sodipodi:start", NULL);
@@ -283,13 +301,13 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
}
// write d=
- this->set_elliptical_path_attribute(repr);
+ set_elliptical_path_attribute(repr);
break;
case SP_GENERIC_ELLIPSE_CIRCLE:
- sp_repr_set_svg_double(repr, "cx", this->cx.computed);
- sp_repr_set_svg_double(repr, "cy", this->cy.computed);
- sp_repr_set_svg_double(repr, "r", this->rx.computed);
+ sp_repr_set_svg_length(repr, "cx", cx);
+ sp_repr_set_svg_length(repr, "cy", cy);
+ sp_repr_set_svg_length(repr, "r", rx);
repr->setAttribute("rx", NULL );
repr->setAttribute("ry", NULL );
repr->setAttribute("sodipodi:cx", NULL );
@@ -304,10 +322,10 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
break;
case SP_GENERIC_ELLIPSE_ELLIPSE:
- sp_repr_set_svg_double(repr, "cx", this->cx.computed);
- sp_repr_set_svg_double(repr, "cy", this->cy.computed);
- sp_repr_set_svg_double(repr, "rx", this->rx.computed);
- sp_repr_set_svg_double(repr, "ry", this->ry.computed);
+ sp_repr_set_svg_length(repr, "cx", cx);
+ sp_repr_set_svg_length(repr, "cy", cy);
+ sp_repr_set_svg_length(repr, "rx", rx);
+ sp_repr_set_svg_length(repr, "ry", ry);
repr->setAttribute("r", NULL );
repr->setAttribute("sodipodi:cx", NULL );
repr->setAttribute("sodipodi:cy", NULL );
@@ -324,11 +342,10 @@ Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I
std::cerr << "SPGenericEllipse::write: unknown type." << std::endl;
}
- this->set_shape(); // evaluate SPCurve
+ set_shape(); // evaluate SPCurve
SPShape::write(xml_doc, repr, flags);
- // std::cout << "SPGenericEllipse::write: Exit: " << g_quark_to_string(repr->code()) << "\n" << std::endl;
return repr;
}
@@ -339,8 +356,8 @@ const char *SPGenericEllipse::displayName() const
case SP_GENERIC_ELLIPSE_UNDEFINED:
case SP_GENERIC_ELLIPSE_ARC:
- if (this->_isSlice()) {
- if (this->_closed) {
+ if (_isSlice()) {
+ if (_closed) {
return _("Segment");
} else {
return _("Arc");
@@ -480,11 +497,11 @@ Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform)
}
if (this->rx._set) {
- this->rx = this->rx.computed * sw;
+ this->rx.scale( sw );
}
if (this->ry._set) {
- this->ry = this->ry.computed * sh;
+ this->ry.scale( sh );
}
/* Find start in item coords */
@@ -628,10 +645,10 @@ bool SPGenericEllipse::set_elliptical_path_attribute(Inkscape::XML::Node *repr)
void SPGenericEllipse::position_set(gdouble x, gdouble y, gdouble rx, gdouble ry)
{
- this->cx.computed = x;
- this->cy.computed = y;
- this->rx.computed = rx;
- this->ry.computed = ry;
+ this->cx = x;
+ this->cy = y;
+ this->rx = rx;
+ this->ry = ry;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
diff --git a/src/sp-factory.cpp b/src/sp-factory.cpp
index 9911222e5..e48646f8d 100644
--- a/src/sp-factory.cpp
+++ b/src/sp-factory.cpp
@@ -36,7 +36,7 @@
#include "sp-linear-gradient.h"
#include "sp-marker.h"
#include "sp-mask.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "sp-mesh-patch.h"
#include "sp-mesh-row.h"
#include "sp-metadata.h"
@@ -168,12 +168,12 @@ SPObject *SPFactory::createObject(std::string const& id)
ret = new SPMarker;
else if (id == "svg:mask")
ret = new SPMask;
- else if (id == "svg:meshGradient")
- ret = new SPMeshGradient;
- else if (id == "svg:meshPatch")
- ret = new SPMeshPatch;
- else if (id == "svg:meshRow")
- ret = new SPMeshRow;
+ else if (id == "svg:mesh")
+ ret = new SPMesh;
+ else if (id == "svg:meshpatch")
+ ret = new SPMeshpatch;
+ else if (id == "svg:meshrow")
+ ret = new SPMeshrow;
else if (id == "svg:metadata")
ret = new SPMetadata;
else if (id == "svg:missing-glyph")
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index b3e885560..854d53dc4 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -1,6 +1,6 @@
/** \file
* SPGradient, SPStop, SPLinearGradient, SPRadialGradient,
- * SPMeshGradient, SPMeshRow, SPMeshPatch
+ * SPMesh, SPMeshRow, SPMeshPatch
*/
/*
* Authors:
@@ -44,7 +44,7 @@
#include "sp-gradient-reference.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "sp-mesh-row.h"
#include "sp-mesh-patch.h"
#include "sp-stop.h"
@@ -121,7 +121,7 @@ bool SPGradient::isEquivalent(SPGradient *that)
else if (
(SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) ||
(SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) ||
- (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that))) {
+ (SP_IS_MESH(this) && SP_IS_MESH(that))) {
if(!this->isAligned(that))break;
}
else { break; } // this should never happen, some unhandled type of gradient
@@ -206,9 +206,9 @@ bool SPGradient::isAligned(SPGradient *that)
(sg->fy.computed != tg->fy.computed) ) { break; }
} else if( sg->cx._set || sg->cy._set || sg->fx._set || sg->fy._set || sg->r._set ) { break; } // some mix of set and not set
// none set? assume aligned and fall through
- } else if (SP_IS_MESHGRADIENT(this) && SP_IS_MESHGRADIENT(that)) {
- SPMeshGradient *sg=SP_MESHGRADIENT(this);
- SPMeshGradient *tg=SP_MESHGRADIENT(that);
+ } else if (SP_IS_MESH(this) && SP_IS_MESH(that)) {
+ SPMesh *sg=SP_MESH(this);
+ SPMesh *tg=SP_MESH(that);
if( sg->x._set != !tg->x._set) { break; }
if( sg->y._set != !tg->y._set) { break; }
@@ -508,9 +508,9 @@ void SPGradient::modified(guint flags)
if (flags & SP_OBJECT_CHILD_MODIFIED_FLAG) {
// CPPIFY
// This comparison has never worked (i. e. always evaluated to false),
- // the right value would have been SP_TYPE_MESHGRADIENT
+ // the right value would have been SP_TYPE_MESH
//if( this->get_type() != SP_GRADIENT_TYPE_MESH ) {
-// if (!SP_IS_MESHGRADIENT(this)) {
+// if (!SP_IS_MESH(this)) {
// this->invalidateVector();
// } else {
// this->invalidateArray();
@@ -522,7 +522,7 @@ void SPGradient::modified(guint flags)
// CPPIFY
// see above
//if( this->get_type() != SP_GRADIENT_TYPE_MESH ) {
-// if (!SP_IS_MESHGRADIENT(this)) {
+// if (!SP_IS_MESH(this)) {
// this->ensureVector();
// } else {
// this->ensureArray();
@@ -1014,12 +1014,12 @@ void SPGradient::rebuildArray()
{
// std::cout << "SPGradient::rebuildArray()" << std::endl;
- if( !SP_IS_MESHGRADIENT(this) ) {
+ if( !SP_IS_MESH(this) ) {
g_warning( "SPGradient::rebuildArray() called for non-mesh gradient" );
return;
}
- array.read( SP_MESHGRADIENT( this ) );
+ array.read( SP_MESH( this ) );
has_patches = false;
for ( SPObject *ro = firstChild() ; ro ; ro = ro->getNext() ) {
@@ -1139,7 +1139,7 @@ sp_gradient_create_preview_pattern(SPGradient *gr, double width)
// CPPIFY
//if( gr->get_type() != SP_GRADIENT_TYPE_MESH ) {
- if (!SP_IS_MESHGRADIENT(gr)) {
+ if (!SP_IS_MESH(gr)) {
gr->ensureVector();
pat = cairo_pattern_create_linear(0, 0, width, 0);
diff --git a/src/sp-gradient.h b/src/sp-gradient.h
index f80d806fc..ab45d6f08 100644
--- a/src/sp-gradient.h
+++ b/src/sp-gradient.h
@@ -39,12 +39,6 @@ enum SPGradientType {
SP_GRADIENT_TYPE_MESH
};
-enum SPGradientMeshType {
- SP_GRADIENT_MESH_TYPE_UNKNOWN,
- SP_GRADIENT_MESH_TYPE_NORMAL,
- SP_GRADIENT_MESH_TYPE_CONICAL
-};
-
enum SPGradientState {
SP_GRADIENT_STATE_UNKNOWN,
SP_GRADIENT_STATE_VECTOR,
@@ -216,7 +210,7 @@ sp_gradient_pattern_common_setup(cairo_pattern_t *cp,
void sp_gradient_repr_write_vector(SPGradient *gr);
void sp_gradient_repr_clear_vector(SPGradient *gr);
-void sp_meshgradient_repr_write(SPMeshGradient *mg);
+void sp_mesh_repr_write(SPMesh *mg);
cairo_pattern_t *sp_gradient_create_preview_pattern(SPGradient *gradient, double width);
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index cfa142acd..9bd42665d 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -822,7 +822,7 @@ void SPGroup::update_patheffect(bool write) {
LivePathEffectObject *lpeobj = (*it)->lpeobject;
if (lpeobj && lpeobj->get_lpe()) {
- lpeobj->get_lpe()->doBeforeEffect(this);
+ lpeobj->get_lpe()->doBeforeEffect_impl(this);
}
}
diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp
index 86beee907..767f0ed91 100644
--- a/src/sp-item-transform.cpp
+++ b/src/sp-item-transform.cpp
@@ -181,7 +181,9 @@ Geom::Affine get_scale_transform_for_uniform_stroke(Geom::Rect const &bbox_visua
if (B*B - 4*A*C < 0) {
g_message("stroke scaling error : %d, %f, %f, %f, %f, %f", preserve, r0, w0, h0, w1, h1);
} else {
- r1 = fabs((-B - sqrt(B*B - 4*A*C))/(2*A));
+ r1 = -C/B;
+ if (!Geom::are_near(A*C/B/B, 0.0, Geom::EPSILON))
+ r1 = fabs((-B - sqrt(B*B - 4*A*C))/(2*A));
// If w1 < 0 then the scale will be wrong if we just assume that scale_x = (w1 - r1)/(w0 - r0);
// Therefore we here need the absolute values of w0, w1, h0, h1, and r0, as taken care of earlier
scale_x = (w1 - r1)/(w0 - r0);
@@ -339,7 +341,9 @@ Geom::Affine get_scale_transform_for_variable_stroke(Geom::Rect const &bbox_visu
if (B*B - 4*A*C < 0) {
g_message("variable stroke scaling error : %d, %d, %f, %f, %f, %f, %f, %f", transform_stroke, preserve, r0w, r0h, w0, h0, w1, h1);
} else {
- gdouble det = (-B + sqrt(B*B - 4*A*C))/(2*A);
+ gdouble det = -C/B;
+ if (!Geom::are_near(A*C/B/B, 0.0, Geom::EPSILON))
+ det = (-B + sqrt(B*B - 4*A*C))/(2*A);
r1w = r0w*det;
r1h = r0h*det;
// If w1 < 0 then the scale will be wrong if we just assume that scale_x = (w1 - r1)/(w0 - r0);
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 5d181b80a..8c99e9bcf 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -75,18 +75,6 @@ static SPItemView* sp_item_view_list_remove(SPItemView *list,
SPItem::SPItem() : SPObject() {
- this->sensitive = 0;
- this->clip_ref = NULL;
- this->avoidRef = NULL;
- this->_is_evaluated = false;
- this->stop_paint = 0;
- this->_evaluated_status = StatusUnknown;
- this->bbox_valid = 0;
- this->freeze_stroke_width = false;
- this->transform_center_x = 0;
- this->transform_center_y = 0;
- this->display = NULL;
- this->mask_ref = NULL;
sensitive = TRUE;
bbox_valid = FALSE;
@@ -96,12 +84,13 @@ SPItem::SPItem() : SPObject() {
transform_center_x = 0;
transform_center_y = 0;
+ freeze_stroke_width = false;
+
_is_evaluated = true;
_evaluated_status = StatusUnknown;
transform = Geom::identity();
- doc_bbox = Geom::OptRect();
- freeze_stroke_width = false;
+ // doc_bbox = Geom::OptRect();
display = NULL;
@@ -670,54 +659,56 @@ void SPItem::stroke_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item)
}
}
-void SPItem::update(SPCtx* /*ctx*/, guint flags) {
- SPItem *item = this;
- SPItem* object = item;
+void SPItem::update(SPCtx* ctx, guint flags) {
-// SPObject::onUpdate(ctx, flags);
+ SPItemCtx const *ictx = reinterpret_cast<SPItemCtx const *>(ctx);
- // any of the modifications defined in sp-object.h might change bbox,
+ // Any of the modifications defined in sp-object.h might change bbox,
// so we invalidate it unconditionally
- item->bbox_valid = FALSE;
+ bbox_valid = FALSE;
+
+ viewport = ictx->viewport; // Cache viewport
- if (flags & (SP_OBJECT_CHILD_MODIFIED_FLAG | SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG)) {
+ if (flags & (SP_OBJECT_CHILD_MODIFIED_FLAG |
+ SP_OBJECT_MODIFIED_FLAG |
+ SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
if (flags & SP_OBJECT_MODIFIED_FLAG) {
- for (SPItemView *v = item->display; v != NULL; v = v->next) {
- v->arenaitem->setTransform(item->transform);
+ for (SPItemView *v = display; v != NULL; v = v->next) {
+ v->arenaitem->setTransform(transform);
}
}
- SPClipPath *clip_path = item->clip_ref ? item->clip_ref->getObject() : NULL;
- SPMask *mask = item->mask_ref ? item->mask_ref->getObject() : NULL;
+ SPClipPath *clip_path = clip_ref ? clip_ref->getObject() : NULL;
+ SPMask *mask = mask_ref ? mask_ref->getObject() : NULL;
if ( clip_path || mask ) {
- Geom::OptRect bbox = item->geometricBounds();
+ Geom::OptRect bbox = geometricBounds();
if (clip_path) {
- for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ for (SPItemView *v = display; v != NULL; v = v->next) {
clip_path->setBBox(v->arenaitem->key(), bbox);
}
}
if (mask) {
- for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ for (SPItemView *v = display; v != NULL; v = v->next) {
mask->sp_mask_set_bbox(v->arenaitem->key(), bbox);
}
}
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
- for (SPItemView *v = item->display; v != NULL; v = v->next) {
- v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value));
- v->arenaitem->setAntialiasing(object->style->shape_rendering.computed != SP_CSS_SHAPE_RENDERING_CRISPEDGES);
- v->arenaitem->setIsolation( object->style->isolation.value );
- v->arenaitem->setBlendMode( object->style->mix_blend_mode.value );
- v->arenaitem->setVisible(!item->isHidden());
+ for (SPItemView *v = display; v != NULL; v = v->next) {
+ v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value));
+ v->arenaitem->setAntialiasing(style->shape_rendering.computed != SP_CSS_SHAPE_RENDERING_CRISPEDGES);
+ v->arenaitem->setIsolation( style->isolation.value );
+ v->arenaitem->setBlendMode( style->mix_blend_mode.value );
+ v->arenaitem->setVisible(!isHidden());
}
}
}
/* Update bounding box in user space, used for filter and objectBoundingBox units */
- if (item->style->filter.set && item->display) {
- Geom::OptRect item_bbox = item->geometricBounds();
- SPItemView *itemview = item->display;
+ if (style->filter.set && display) {
+ Geom::OptRect item_bbox = geometricBounds();
+ SPItemView *itemview = display;
do {
if (itemview->arenaitem)
itemview->arenaitem->setItemBounds(item_bbox);
@@ -725,8 +716,8 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
}
// Update libavoid with item geometry (for connector routing).
- if (item->avoidRef)
- item->avoidRef->handleSettingChange();
+ if (avoidRef)
+ avoidRef->handleSettingChange();
}
void SPItem::modified(unsigned int /*flags*/)
diff --git a/src/sp-item.h b/src/sp-item.h
index b9d71c551..bdc6a0ad9 100644
--- a/src/sp-item.h
+++ b/src/sp-item.h
@@ -145,6 +145,7 @@ public:
Geom::Affine transform;
mutable Geom::OptRect doc_bbox;
+ Geom::Rect viewport; // Cache viewport information
SPClipPathReference *clip_ref;
SPMaskReference *mask_ref;
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 6228f3692..9befd2a2b 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -263,7 +263,7 @@ bool SPLPEItem::performPathEffect(SPCurve *curve) {
}
if (!SP_IS_GROUP(this)) {
lpe->doAfterEffect(this);
- }
+ }
}
}
}
diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp
index e2d654f2f..445c9a8f6 100644
--- a/src/sp-mesh-array.cpp
+++ b/src/sp-mesh-array.cpp
@@ -46,8 +46,8 @@
#include "document.h"
#include "sp-root.h"
+#include "sp-mesh.h"
#include "sp-mesh-array.h"
-#include "sp-mesh-gradient.h"
#include "sp-mesh-row.h"
#include "sp-mesh-patch.h"
#include "sp-stop.h"
@@ -289,7 +289,7 @@ bool SPMeshPatchI::tensorIsSet() {
/**
Return if tensor control point for "corner" i is set.
*/
-bool SPMeshPatchI::tensorIsSet( guint i ) {
+bool SPMeshPatchI::tensorIsSet( unsigned int i ) {
assert( i < 4 );
@@ -574,7 +574,7 @@ void SPMeshPatchI::setOpacity( guint i, gdouble opacity ) {
};
-SPMeshNodeArray::SPMeshNodeArray( SPMeshGradient *mg ) {
+SPMeshNodeArray::SPMeshNodeArray( SPMesh *mg ) {
read( mg );
@@ -621,7 +621,7 @@ SPMeshNodeArray& SPMeshNodeArray::operator=( const SPMeshNodeArray& rhs ) {
};
-void SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
+void SPMeshNodeArray::read( SPMesh *mg_in ) {
mg = mg_in;
@@ -641,7 +641,7 @@ void SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
if (SP_IS_MESHPATCH(po)) {
- SPMeshPatch *patch = SP_MESHPATCH(po);
+ SPMeshpatch *patch = SP_MESHPATCH(po);
// std::cout << "SPMeshNodeArray::read: row size: " << nodes.size() << std::endl;
SPMeshPatchI new_patch( &nodes, irow, icolumn ); // Adds new nodes.
@@ -838,7 +838,7 @@ void SPMeshNodeArray::read( SPMeshGradient *mg_in ) {
/**
Write repr using our array.
*/
-void SPMeshNodeArray::write( SPMeshGradient *mg ) {
+void SPMeshNodeArray::write( SPMesh *mg ) {
// std::cout << "SPMeshNodeArray::write: entrance:" << std::endl;
// print();
@@ -889,14 +889,14 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
for( guint i = 0; i < rows; ++i ) {
// Write row
- Inkscape::XML::Node *row = xml_doc->createElement("svg:meshRow");
+ Inkscape::XML::Node *row = xml_doc->createElement("svg:meshrow");
mesh->appendChild( row ); // No attributes
guint columns = array->patch_columns();
for( guint j = 0; j < columns; ++j ) {
// Write patch
- Inkscape::XML::Node *patch = xml_doc->createElement("svg:meshPatch");
+ Inkscape::XML::Node *patch = xml_doc->createElement("svg:meshpatch");
SPMeshPatchI patchi( &(array->nodes), i, j );
@@ -967,10 +967,10 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) {
break;
case 'z':
case 'Z':
- std::cout << "sp_meshgradient_repr_write: bad path type" << path_type << std::endl;
+ std::cout << "sp_mesh_repr_write: bad path type" << path_type << std::endl;
break;
default:
- std::cout << "sp_meshgradient_repr_write: unhandled path type" << path_type << std::endl;
+ std::cout << "sp_mesh_repr_write: unhandled path type" << path_type << std::endl;
}
stop->setAttribute("path", is.str().c_str());
// std::cout << "SPMeshNodeArray::write: path: " << is.str().c_str() << std::endl;
@@ -1039,7 +1039,7 @@ static SPColor default_color( SPItem *item ) {
/**
Create a default mesh.
*/
-void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox ) {
+void SPMeshNodeArray::create( SPMesh *mg, SPItem *item, Geom::OptRect bbox ) {
// std::cout << "SPMeshNodeArray::create: Entrance" << std::endl;
@@ -1077,10 +1077,10 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb
guint prows = prefs->getInt("/tools/mesh/mesh_rows", 1);
guint pcols = prefs->getInt("/tools/mesh/mesh_cols", 1);
- SPGradientMeshType mesh_type =
- (SPGradientMeshType) prefs->getInt("/tools/mesh/mesh_type", SP_GRADIENT_MESH_TYPE_NORMAL);
+ SPMeshGeometry mesh_type =
+ (SPMeshGeometry) prefs->getInt("/tools/mesh/mesh_geometry", SP_MESH_GEOMETRY_NORMAL);
- if( mesh_type == SP_GRADIENT_MESH_TYPE_CONICAL ) {
+ if( mesh_type == SP_MESH_GEOMETRY_CONICAL ) {
// Conical gradient.. for any shape/path using geometric bounding box.
@@ -1424,133 +1424,7 @@ void SPMeshNodeArray::print() {
-// Find the slopes at start and end for Hermite interpolation.
-// Smooth using Hermite interpolation.
-// Inputs are:
-// pb: color value before patch
-// p0: color value start of patch
-// p1: color value end of patch
-// pa: color value after patch
-// lb0: distance between points b and 0
-// l01: distance between points 0 and 1
-// l1a: distance between points 1 and a
-// is_first: If first patch in row/column
-// is_last: If last patch in row/column
-// type: Type of smoothing
-// Output:
-// m0: slope of Hermite function at start.
-// m1: slope of Hermite function at end.
-void find_slopes( const double &pb, const double &p0, const double &p1, const double &pa,
- const double &lb0, const double &l01, const double &l1a,
- const bool &is_first, const bool &is_last, const SPMeshSmooth type,
- double &m0, double &m1 ) {
-
- // We use Hermite interpolation. We have end points, we need tangents.
-
- // Try various ways of finding tangents m0, m1
-
- // Default to Catmul-Rom (assumes pb and pa already calculatedd)
- m0 = (p1 - pb)/2.0;
- m1 = (pa - p0)/2.0;
-
- // Finite differences
- if( lb0 > 0 && l01 > 0 )
- m0 = 0.5 * ((p0 - pb )/lb0 + (p1 - p0)/l01) * l01;
- if( l01 > 0 && l1a > 0 )
- m1 = 0.5 * ((p1 - p0 )/l01 + (pa - p1)/l1a) * l01;
-
- bool parabolic = false; // Require end patches to be parabolic
- switch (type) {
- case SP_MESH_SMOOTH_SMOOTH1:
- // Flat
- m0 = 0.0;
- m1 = 0.0;
- break;
- case SP_MESH_SMOOTH_SMOOTH2:
- // Catmul-Rom, standard end treatment. Double first/last point.
- if( is_first ) {
- m0 = (p1-p0)/2.0;
- }
- if( is_last ) {
- m1 = (p1-p0)/2.0;
- }
- break;
- case SP_MESH_SMOOTH_SMOOTH3:
- // Catmul-Rom, standard end treatment. Reflect first/last point.
- if( is_first ) {
- m0 = (p1-p0);
- }
- if( is_last ) {
- m1 = (p1-p0);
- }
- break;
- case SP_MESH_SMOOTH_SMOOTH4:
- // Catmul-Rom, Parabolic ends
- parabolic = true;
- break;
- case SP_MESH_SMOOTH_SMOOTH5:
- // Catmul-Rom, Parabolic ends, no color min/max in middle of patch.
- parabolic = true;
-
- if( (pb > p0 && p1 > p0) ||
- (pb < p0 && p1 < p0) ) {
- // tangents flat at min/max
- m0 = 0;
- } else {
- // https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
- // ensure we don't overshoot
- if( fabs(m0) > fabs(3*(p1-p0)) ) {
- m0 = 3*(p1-p0);
- }
- if( fabs(m0) > fabs(3*(p0-pb)) * l01 / lb0 ) {
- m0 = 3*(p0-pb) * l01 / lb0;
- }
- }
- if( (p0 > p1 && pa > p1) ||
- (p0 < p1 && pa < p1) ) {
- // tangents flat at min/max
- m1 = 0;
- } else {
- // ensure we don't overshoot
- if( fabs(m1) > fabs(3*(pa-p1) * l01 / l1a) ) {
- m1 = 3*(pa-p1) * l01 / l1a;
- }
- if( fabs(m1) > fabs(3*(p1-p0)) ) {
- m1 = 3*(p1-p0);
- }
- }
- break;
- case SP_MESH_SMOOTH_NONE:
- default:
- std::cerr << "find_slopes() Invalid smoothing type." << std::endl;
- break;
- }
-
- // Force end patches to be parabolic
- if( parabolic ) {
- if( is_first ) {
- // Constraint for parabola
- m0 = 2.0*(p1-p0) - m1;
- if ( ((p1-p0) < 0 && m0 > 0) || ((p1-p0) > 0 && m0 < 0 ) ) {
- m0 = 0; // Prevent overshooting start value;
- }
- } else if( is_last ) {
- // Constraint for parabola
- m1 = 2.0*(p1-p0) - m0;
- if ( ((p1-p0) < 0 && m1 > 0) || ((p1-p0) > 0 && m1 < 0 ) ) {
- m1 = 0; // Prevent overshooting end value;
- }
- }
- }
-
- // std::cout << " pb: " << pb
- // << " p0: " << p0
- // << " p1: " << p1
- // << " pa: " << pa
- // << " m0: " << m0
- // << " m1: " << m1 << std::endl;
-}
-
+/*
double hermite( const double p0, const double p1, const double m0, const double m1, const double t ) {
double t2 = t*t;
double t3 = t2*t;
@@ -1562,178 +1436,7 @@ double hermite( const double p0, const double p1, const double m0, const double
return result;
}
-
-
-/**
- Fill 'smooth' with a smoothed version of the array by subdividing each patch into smaller patches.
*/
-void SPMeshNodeArray::smooth( SPMeshNodeArray* smooth, SPMeshSmooth type ) {
-
- *smooth = *this; // Deep copy via copy assignment constructor, smooth cleared before copy
- // std::cout << "SPMeshNodeArray::smooth(): " << this->patch_rows() << " " << smooth->patch_rows() << std::endl;
- // std::cout << " " << smooth << " " << this << std::endl;
- // Next split each patch into 8x8 smaller patches.
-
- // Do rows first.
-
- // Split each row into eight rows.
- // Must do it from end so inserted rows don't mess up indexing
- for( int i = smooth->patch_rows() - 1; i >= 0; --i ) {
- smooth->split_row( i, unsigned(8) );
- }
-
- // Update color values (every third node is a corner)
- for( unsigned i = 0; i < this->patch_rows(); ++i ) { // i is orignal patch index
-
- bool is_first_row = (i == 0);
- bool is_last_row = (i == this->patch_rows() - 1 );
- //std::cout << " last row: " << smooth->patch_rows()/8 - 1 << " " << is_last_row << std::endl;
- for( unsigned j = 0; j < smooth->patch_columns()+1; ++j ) { // j is smooth patch index
-
- // Can't use guint32 since delta can be negative
- float pb[3]; // Point before patch
- float p0[3]; // Point at start of patch
- float p1[3]; // Point at end of patch
- float pa[3]; // Point after patch
- float result[3][8];
- sp_color_get_rgb_floatv( &this->nodes[ i *3 ][ j*3 ]->color, p0 );
- sp_color_get_rgb_floatv( &this->nodes[ (i+1)*3 ][ j*3 ]->color, p1 );
-
- // Use linear distance to avoid calculation overhead of calculating true path length
- Geom::Point *ptb = NULL;
- Geom::Point *pt0 = &this->nodes[ i *3 ][ j*3 ]->p;
- Geom::Point *pt1 = &this->nodes[ (i+1)*3 ][ j*3 ]->p;
- Geom::Point *pta = NULL;
-
- double lb0 = 0.0;
- double l01 = Geom::distance( *pt0, *pt1 );
- double l1a = 0.0;
-
- if( !is_first_row ) {
- sp_color_get_rgb_floatv( &this->nodes[ (i-1)*3 ][ j*3 ]->color, pb );
- ptb = &this->nodes[ (i-1)*3 ][ j*3 ]->p;
- lb0 = Geom::distance( *ptb, *pt0 );
- } else {
- pb[0] = 2.0*p0[0] - p1[0];
- pb[1] = 2.0*p0[1] - p1[1];
- pb[2] = 2.0*p0[2] - p1[2];
- }
- if( !is_last_row ) {
- sp_color_get_rgb_floatv( &this->nodes[ (i+2)*3 ][ j*3 ]->color, pa );
- pta = &this->nodes[ (i+2)*3 ][ j*3 ]->p;
- l1a = Geom::distance( *pt1, *pta );
- } else {
- pa[0] = 2.0*p1[0] - p0[0];
- pa[1] = 2.0*p1[1] - p0[1];
- pa[2] = 2.0*p1[2] - p0[2];
- }
-
- for( unsigned n = 0; n < 3; ++n ) { // Loop over colors
-
- // We use Hermite interpolation. We have end points, we need tangents.
- double m0 = 0;
- double m1 = 0;
- find_slopes( pb[n], p0[n], p1[n], pa[n],
- lb0, l01, l1a,
- is_first_row, is_last_row, type, m0, m1 );
-
- for( unsigned k = 1; k < 8; ++k ) {
- double t = k/8.0;
- // Cubic Hermite (four constraints)
- result[n][k] = hermite( p0[n], p1[n], m0, m1, t );
- // Clamp to allowed values
- if( result[n][k] > 1.0 )
- result[n][k] = 1.0;
- if( result[n][k] < 0.0 )
- result[n][k] = 0.0;
- }
- }
-
- for( unsigned k = 1; k < 8; ++k ) {
- smooth->nodes[ (i*8+k)*3 ][ j*3 ]->color.set( result[0][k], result[1][k], result[2][k] );
- }
- }
- }
-
- // Split each column into eight columns.
- // Must do it from end so inserted columns don't mess up indexing
- for( int i = smooth->patch_columns() - 1; i >= 0; --i ) {
- smooth->split_column( i, (unsigned)8 );
- }
-
- // Update color values (every third node is a corner)
- for( unsigned i = 0; i < this->patch_columns(); ++i ) { // i is orignal patch index
-
- bool is_first_column = (i == 0);
- bool is_last_column = (i == this->patch_columns() - 1 );
- //std::cout << " last column: " << smooth->patch_columns()/8 - 1 << " " << is_last_column << std::endl;
- for( unsigned j = 0; j < smooth->patch_rows()+1; ++j ) { // j is smooth patch index
-
- // Can't use guint32 since delta can be negative
- float pb[3]; // Point before patch
- float p0[3]; // Point at start of patch
- float p1[3]; // Point at end of patch
- float pa[3]; // Point after patch
- float result[3][8];
- sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ i *3*8 ]->color, p0 );
- sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i+1)*3*8 ]->color, p1 );
-
- // Use linear distance to avoid calculation overhead of calculating true path length
- Geom::Point *ptb = NULL;
- Geom::Point *pt0 = &smooth->nodes[ j*3 ][ i *3*8 ]->p;
- Geom::Point *pt1 = &smooth->nodes[ j*3 ][ (i+1)*3*8 ]->p;
- Geom::Point *pta = NULL;
-
- double lb0 = 0.0;
- double l01 = Geom::distance( *pt0, *pt1 );
- double l1a = 0.0;
-
- if( !is_first_column ) {
- sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i-1)*3*8 ]->color, pb );
- ptb = &smooth->nodes[ j*3 ][ (i-1)*3*8 ]->p;
- lb0 = Geom::distance( *ptb, *pt0 );
- } else {
- pb[0] = 2.0*p0[0] - p1[0];
- pb[1] = 2.0*p0[1] - p1[1];
- pb[2] = 2.0*p0[2] - p1[2];
- }
- if( !is_last_column ) {
- sp_color_get_rgb_floatv( &smooth->nodes[ j*3 ][ (i+2)*3*8 ]->color, pa );
- pta = &smooth->nodes[ j*3 ][ (i+2)*3*8 ]->p;
- l1a = Geom::distance( *pt1, *pta );
- } else {
- pa[0] = 2.0*p1[0] - p0[0];
- pa[1] = 2.0*p1[1] - p0[1];
- pa[2] = 2.0*p1[2] - p0[2];
- }
-
- for( unsigned n = 0; n < 3; ++n ) { // Loop over colors
-
- // We use Hermite interpolation. We have end points, we need tangents.
- double m0 = 0;
- double m1 = 0;
- find_slopes( pb[n], p0[n], p1[n], pa[n],
- lb0, l01, l1a,
- is_first_column, is_last_column, type, m0, m1 );
-
- for( unsigned k = 1; k < 8; ++k ) {
- double t = k/8.0;
- // Cubic Hermite (four constraints)
- result[n][k] = hermite( p0[n], p1[n], m0, m1, t );
- // Clamp to allowed values
- if( result[n][k] > 1.0 )
- result[n][k] = 1.0;
- if( result[n][k] < 0.0 )
- result[n][k] = 0.0;
- }
- }
-
- for( unsigned k = 1; k < 8; ++k ) {
- smooth->nodes[ j*3 ][ (i*8+k)*3 ]->color.set( result[0][k], result[1][k], result[2][k] );
- }
- }
- }
-}
class SPMeshSmoothCorner {
@@ -1792,6 +1495,7 @@ double find_slope1( const double &p0, const double &p1, const double &p2,
};
+/*
// Find slope at point 0 given values at previous and next points
// TO DO: TAKE DISTANCE BETWEEN POINTS INTO ACCOUNT
double find_slope2( double pmm, double ppm, double pmp, double ppp, double p0 ) {
@@ -1819,6 +1523,7 @@ double find_slope2( double pmm, double ppm, double pmp, double ppp, double p0 )
}
return slope;
}
+*/
// https://en.wikipedia.org/wiki/Bicubic_interpolation
void invert( const double v[16], double alpha[16] ) {
@@ -1883,7 +1588,7 @@ double sum( const double alpha[16], const double& x, const double& y ) {
/**
Fill 'smooth' with a smoothed version of the array by subdividing each patch into smaller patches.
*/
-void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) {
+void SPMeshNodeArray::bicubic( SPMeshNodeArray* smooth, SPMeshType type ) {
*smooth = *this; // Deep copy via copy assignment constructor, smooth cleared before copy
@@ -1911,40 +1616,29 @@ void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) {
for( unsigned i = 0; i < d.size(); ++i ) {
for( unsigned j = 0; j < d[i].size(); ++j ) {
for( unsigned k = 0; k < 3; ++k ) { // Loop over colors
- if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) {
- // dx
- if( i != 0 && i != d.size()-1 ) {
- double lm = Geom::distance( d[i-1][j].p, d[i][j].p );
- double lp = Geom::distance( d[i+1][j].p, d[i][j].p );
- d[i][j].g[k][1] = find_slope1( d[i-1][j].g[k][0], d[i][j].g[k][0], d[i+1][j].g[k][0], lm, lp );
- }
+ // dx
- // dy
- if( j != 0 && j != d[i].size()-1 ) {
- double lm = Geom::distance( d[i][j-1].p, d[i][j].p );
- double lp = Geom::distance( d[i][j+1].p, d[i][j].p );
- d[i][j].g[k][2] = find_slope1( d[i][j-1].g[k][0], d[i][j].g[k][0], d[i][j+1].g[k][0], lm, lp );
- }
-
- // dxdy if needed, need to take lengths into account
- // if( i != 0 && i != d.size()-1 && j != 0 && j != d[i].size()-1 ) {
- // d[i][j].g[k][3] = find_slope2( d[i-1][j-1].g[k][0], d[i+1][j-1].g[k][0],
- // d[i-1][j+1].g[k][0], d[i-1][j-1].g[k][0],
- // d[i][j].g[k][0] );
- // }
+ if( i != 0 && i != d.size()-1 ) {
+ double lm = Geom::distance( d[i-1][j].p, d[i][j].p );
+ double lp = Geom::distance( d[i+1][j].p, d[i][j].p );
+ d[i][j].g[k][1] = find_slope1( d[i-1][j].g[k][0], d[i][j].g[k][0], d[i+1][j].g[k][0], lm, lp );
+ }
- } else {
- // Catmul-Rom
- if( i != 0 && i != d.size()-1 ) {
- double d2 = Geom::distance( d[i-1][j].p, d[i+1][j].p );
- d[i][j].g[k][1] = (d[i+1][j].g[k][0] - d[i-1][j].g[k][0])/d2;
- }
- if( j != 0 && j != d[i].size()-1 ) {
- double d2 = Geom::distance( d[i][j-1].p, d[i][j+1].p );
- d[i][j].g[k][2] = (d[i][j+1].g[k][0] - d[i][j-1].g[k][0])/d2;
- }
+ // dy
+ if( j != 0 && j != d[i].size()-1 ) {
+ double lm = Geom::distance( d[i][j-1].p, d[i][j].p );
+ double lp = Geom::distance( d[i][j+1].p, d[i][j].p );
+ d[i][j].g[k][2] = find_slope1( d[i][j-1].g[k][0], d[i][j].g[k][0], d[i][j+1].g[k][0], lm, lp );
}
+
+ // dxdy if needed, need to take lengths into account
+ // if( i != 0 && i != d.size()-1 && j != 0 && j != d[i].size()-1 ) {
+ // d[i][j].g[k][3] = find_slope2( d[i-1][j-1].g[k][0], d[i+1][j-1].g[k][0],
+ // d[i-1][j+1].g[k][0], d[i-1][j-1].g[k][0],
+ // d[i][j].g[k][0] );
+ // }
+
}
}
}
@@ -1954,80 +1648,42 @@ void SPMeshNodeArray::smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type ) {
// have the non-exterior derivative calculated for finding the parabola.
for( unsigned j = 0; j< d[0].size(); ++j ) {
for( unsigned k = 0; k < 3; ++k ) { // Loop over colors
- unsigned z = d.size()-1;
- if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) {
-
- // Parabolic
- double d0 = Geom::distance( d[1][j].p, d[0 ][j].p );
- if( d0 > 0 ) {
- d[0][j].g[k][1] = 2.0*(d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0 - d[1][j].g[k][1];
- } else {
- d[0][j].g[k][1] = 0;
- }
-
- double dz = Geom::distance( d[z][j].p, d[z-1][j].p );
- if( dz > 0 ) {
- d[z][j].g[k][1] = 2.0*(d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz - d[z-1][j].g[k][1];
- } else {
- d[z][j].g[k][1] = 0;
- }
+ // Parabolic
+ double d0 = Geom::distance( d[1][j].p, d[0 ][j].p );
+ if( d0 > 0 ) {
+ d[0][j].g[k][1] = 2.0*(d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0 - d[1][j].g[k][1];
} else {
+ d[0][j].g[k][1] = 0;
+ }
- // Catmul-Rom
- double d0 = Geom::distance( d[1][j].p, d[0 ][j].p );
- if( d0 > 0 ) {
- d[0][j].g[k][1] = (d[1][j].g[k][0] - d[0 ][j].g[k][0])/d0;
- } else {
- d[0][j].g[k][1] = 0;
- }
-
- double dz = Geom::distance( d[z][j].p, d[z-1][j].p );
- if( dz > 0 ) {
- d[z][j].g[k][1] = (d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz;
- } else {
- d[z][j].g[k][1] = 0;
- }
+ unsigned z = d.size()-1;
+ double dz = Geom::distance( d[z][j].p, d[z-1][j].p );
+ if( dz > 0 ) {
+ d[z][j].g[k][1] = 2.0*(d[z][j].g[k][0] - d[z-1][j].g[k][0])/dz - d[z-1][j].g[k][1];
+ } else {
+ d[z][j].g[k][1] = 0;
}
}
}
for( unsigned i = 0; i< d.size(); ++i ) {
for( unsigned k = 0; k < 3; ++k ) { // Loop over colors
- unsigned z = d[0].size()-1;
- if( type == SP_MESH_SMOOTH_SMOOTH7 || type == SP_MESH_SMOOTH_SMOOTH ) {
-
- // Parabolic
- double d0 = Geom::distance( d[i][1].p, d[i][0 ].p );
- if( d0 > 0 ) {
- d[i][0].g[k][2] = 2.0*(d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0 - d[i][1].g[k][2];
- } else {
- d[i][0].g[k][2] = 0;
- }
- double dz = Geom::distance( d[i][z].p, d[i][z-1].p );
- if( dz > 0 ) {
- d[i][z].g[k][2] = 2.0*(d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz - d[i][z-1].g[k][2];
- } else {
- d[i][z].g[k][2] = 0;
- }
-
+ // Parabolic
+ double d0 = Geom::distance( d[i][1].p, d[i][0 ].p );
+ if( d0 > 0 ) {
+ d[i][0].g[k][2] = 2.0*(d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0 - d[i][1].g[k][2];
} else {
+ d[i][0].g[k][2] = 0;
+ }
- // Catmul-Rom
- double d0 = Geom::distance( d[i][1].p, d[i][0 ].p );
- if( d0 > 0 ) {
- d[i][0].g[k][2] = (d[i][1].g[k][0] - d[i][0 ].g[k][0])/d0;
- } else {
- d[i][0].g[k][2] = 0;
- }
-
- double dz = Geom::distance( d[i][z].p, d[i][z-1].p );
- if( dz > 0 ) {
- d[i][z].g[k][2] = (d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz;
- } else {
- d[i][z].g[k][2] = 0;
- }
+ unsigned z = d[0].size()-1;
+ double dz = Geom::distance( d[i][z].p, d[i][z-1].p );
+ if( dz > 0 ) {
+ d[i][z].g[k][2] = 2.0*(d[i][z].g[k][0] - d[i][z-1].g[k][0])/dz - d[i][z-1].g[k][2];
+ } else {
+ d[i][z].g[k][2] = 0;
}
}
}
@@ -2964,7 +2620,7 @@ guint32 average_color(guint32 c1, guint32 c2, gdouble p);
/**
Split a row into n equal parts.
*/
-void SPMeshNodeArray::split_row( guint row, guint n ) {
+void SPMeshNodeArray::split_row( unsigned int row, unsigned int n ) {
double nn = n;
if( n > 1 ) split_row( row, (nn-1)/nn );
@@ -2974,7 +2630,7 @@ void SPMeshNodeArray::split_row( guint row, guint n ) {
/**
Split a column into n equal parts.
*/
-void SPMeshNodeArray::split_column( guint col, guint n ) {
+void SPMeshNodeArray::split_column( unsigned int col, unsigned int n ) {
double nn = n;
if( n > 1 ) split_column( col, (nn-1)/nn );
@@ -2984,7 +2640,7 @@ void SPMeshNodeArray::split_column( guint col, guint n ) {
/**
Split a row into two rows at coord (fraction of row height).
*/
-void SPMeshNodeArray::split_row( guint row, double coord ) {
+void SPMeshNodeArray::split_row( unsigned int row, double coord ) {
// std::cout << "Splitting row: " << row << " at " << coord << std::endl;
// print();
@@ -3107,7 +2763,7 @@ void SPMeshNodeArray::split_row( guint row, double coord ) {
/**
Split a column into two columns at coord (fraction of column width).
*/
-void SPMeshNodeArray::split_column( guint col, double coord ) {
+void SPMeshNodeArray::split_column( unsigned int col, double coord ) {
// std::cout << "Splitting column: " << col << " at " << coord << std::endl;
// print();
diff --git a/src/sp-mesh-array.h b/src/sp-mesh-array.h
index 19f8634f8..b078b221e 100644
--- a/src/sp-mesh-array.h
+++ b/src/sp-mesh-array.h
@@ -45,16 +45,14 @@
// For color picking
#include "sp-item.h"
-enum SPMeshSmooth {
- SP_MESH_SMOOTH_NONE,
- SP_MESH_SMOOTH_SMOOTH,
- SP_MESH_SMOOTH_SMOOTH1,
- SP_MESH_SMOOTH_SMOOTH2,
- SP_MESH_SMOOTH_SMOOTH3,
- SP_MESH_SMOOTH_SMOOTH4,
- SP_MESH_SMOOTH_SMOOTH5,
- SP_MESH_SMOOTH_SMOOTH6,
- SP_MESH_SMOOTH_SMOOTH7
+enum SPMeshType {
+ SP_MESH_TYPE_COONS,
+ SP_MESH_TYPE_BICUBIC
+};
+
+enum SPMeshGeometry {
+ SP_MESH_GEOMETRY_NORMAL,
+ SP_MESH_GEOMETRY_CONICAL
};
enum NodeType {
@@ -137,14 +135,14 @@ public:
void setOpacity( unsigned int i, double o );
};
-class SPMeshGradient;
+class SPMesh;
// An array of mesh nodes.
class SPMeshNodeArray {
// Should be private
public:
- SPMeshGradient *mg;
+ SPMesh *mg;
std::vector< std::vector< SPMeshNode* > > nodes;
public:
@@ -159,22 +157,21 @@ public:
friend class SPMeshPatchI;
SPMeshNodeArray() { built = false; mg = NULL; drag_valid = false; };
- SPMeshNodeArray( SPMeshGradient *mg );
+ SPMeshNodeArray( SPMesh *mg );
SPMeshNodeArray( const SPMeshNodeArray& rhs );
SPMeshNodeArray& operator=(const SPMeshNodeArray& rhs);
~SPMeshNodeArray() { clear(); };
bool built;
- void read( SPMeshGradient *mg );
- void write( SPMeshGradient *mg );
- void create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox );
+ void read( SPMesh *mg );
+ void write( SPMesh *mg );
+ void create( SPMesh *mg, SPItem *item, Geom::OptRect bbox );
void clear();
void print();
// Fill 'smooth' with a smoothed version by subdividing each patch.
- void smooth( SPMeshNodeArray* smooth, SPMeshSmooth type);
- void smooth2( SPMeshNodeArray* smooth, SPMeshSmooth type);
+ void bicubic( SPMeshNodeArray* smooth, SPMeshType type);
// Get size of patch
unsigned int patch_rows();
diff --git a/src/sp-mesh-gradient.cpp b/src/sp-mesh-gradient.cpp
deleted file mode 100644
index 3301d257c..000000000
--- a/src/sp-mesh-gradient.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <glibmm.h>
-
-#include "attributes.h"
-#include "display/cairo-utils.h"
-#include "xml/repr.h"
-
-#include "sp-mesh-gradient.h"
-
-/*
- * Mesh Gradient
- */
-//#define MESH_DEBUG
-SPMeshGradient::SPMeshGradient() : SPGradient(), smooth(SP_MESH_SMOOTH_NONE), smooth_set(false) {
- // Start coordinate of mesh
- this->x.unset(SVGLength::NONE, 0.0, 0.0);
- this->y.unset(SVGLength::NONE, 0.0, 0.0);
-}
-
-SPMeshGradient::~SPMeshGradient() {
-}
-
-void SPMeshGradient::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPGradient::build(document, repr);
-
- // Start coordinate of mesh
- this->readAttr( "x" );
- this->readAttr( "y" );
-
- this->readAttr( "smooth" );
-}
-
-
-void SPMeshGradient::set(unsigned key, gchar const *value) {
- switch (key) {
- case SP_ATTR_X:
- if (!this->x.read(value)) {
- this->x.unset(SVGLength::NONE, 0.0, 0.0);
- }
-
- this->requestModified(SP_OBJECT_MODIFIED_FLAG);
- break;
-
- case SP_ATTR_Y:
- if (!this->y.read(value)) {
- this->y.unset(SVGLength::NONE, 0.0, 0.0);
- }
-
- this->requestModified(SP_OBJECT_MODIFIED_FLAG);
- break;
-
- case SP_ATTR_SMOOTH:
- if (value) {
- if (!strcmp(value, "none")) {
- this->smooth = SP_MESH_SMOOTH_NONE;
- } else if (!strcmp(value, "smooth")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH;
- } else if (!strcmp(value, "smooth1")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH1;
- } else if (!strcmp(value, "smooth2")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH2;
- } else if (!strcmp(value, "smooth3")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH3;
- } else if (!strcmp(value, "smooth4")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH4;
- } else if (!strcmp(value, "smooth5")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH5;
- } else if (!strcmp(value, "smooth6")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH6;
- } else if (!strcmp(value, "smooth7")) {
- this->smooth = SP_MESH_SMOOTH_SMOOTH7;
- } else {
- std::cout << "SPMeshGradient::set(): invalid value " << value << std::endl;
- }
- this->smooth_set = TRUE;
- } else {
- // std::cout << "SPMeshGradient::set() No value " << std::endl;
- this->smooth = SP_MESH_SMOOTH_NONE;
- this->smooth_set = FALSE;
- }
-
- this->requestModified(SP_OBJECT_MODIFIED_FLAG);
- break;
-
- default:
- SPGradient::set(key, value);
- break;
- }
-}
-
-/**
- * Write mesh gradient attributes to associated repr.
- */
-Inkscape::XML::Node* SPMeshGradient::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
-#ifdef MESH_DEBUG
- std::cout << "sp_meshgradient_write() ***************************" << std::endl;
-#endif
-
- if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:meshGradient");
- }
-
- if ((flags & SP_OBJECT_WRITE_ALL) || this->x._set) {
- sp_repr_set_svg_double(repr, "x", this->x.computed);
- }
-
- if ((flags & SP_OBJECT_WRITE_ALL) || this->y._set) {
- sp_repr_set_svg_double(repr, "y", this->y.computed);
- }
-
- if ((flags & SP_OBJECT_WRITE_ALL) || this->smooth_set) {
- switch (this->smooth) {
- case SP_MESH_SMOOTH_SMOOTH:
- repr->setAttribute("smooth", "smooth");
- break;
- case SP_MESH_SMOOTH_SMOOTH1:
- repr->setAttribute("smooth", "smooth1");
- break;
- case SP_MESH_SMOOTH_SMOOTH2:
- repr->setAttribute("smooth", "smooth2");
- break;
- case SP_MESH_SMOOTH_SMOOTH3:
- repr->setAttribute("smooth", "smooth3");
- break;
- case SP_MESH_SMOOTH_SMOOTH4:
- repr->setAttribute("smooth", "smooth4");
- break;
- case SP_MESH_SMOOTH_SMOOTH5:
- repr->setAttribute("smooth", "smooth5");
- break;
- case SP_MESH_SMOOTH_SMOOTH6:
- repr->setAttribute("smooth", "smooth6");
- break;
- case SP_MESH_SMOOTH_SMOOTH7:
- repr->setAttribute("smooth", "smooth7");
- break;
- case SP_MESH_SMOOTH_NONE:
- repr->setAttribute("smooth", "none");
- break;
- default:
- // Do nothing
- break;
- }
- }
-
- SPGradient::write(xml_doc, repr, flags);
-
- return repr;
-}
-
-void
-sp_meshgradient_repr_write(SPMeshGradient *mg)
-{
- mg->array.write( mg );
-}
-
-
-cairo_pattern_t* SPMeshGradient::pattern_new(cairo_t * /*ct*/,
-#if defined(MESH_DEBUG) || (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4))
- Geom::OptRect const &bbox,
- double opacity
-#else
- Geom::OptRect const & /*bbox*/,
- double /*opacity*/
-#endif
- )
-{
- using Geom::X;
- using Geom::Y;
-
-#ifdef MESH_DEBUG
- std::cout << "sp_meshgradient_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl;
-#endif
-
- this->ensureArray();
-
- cairo_pattern_t *cp = NULL;
-
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4)
- SPMeshNodeArray* my_array = &array;
-
- if( smooth_set ) {
- switch (smooth) {
- case SP_MESH_SMOOTH_NONE:
- // std::cout << "SPMeshGradient::pattern_new: no smoothing" << std::endl;
- break;
- case SP_MESH_SMOOTH_SMOOTH1:
- case SP_MESH_SMOOTH_SMOOTH2:
- case SP_MESH_SMOOTH_SMOOTH3:
- case SP_MESH_SMOOTH_SMOOTH4:
- case SP_MESH_SMOOTH_SMOOTH5:
- // std::cout << "SPMeshGradient::pattern_new: calling array.smooth" << std::endl;
- array.smooth( &array_smoothed, smooth );
- my_array = &array_smoothed;
- break;
- case SP_MESH_SMOOTH_SMOOTH:
- case SP_MESH_SMOOTH_SMOOTH6:
- case SP_MESH_SMOOTH_SMOOTH7:
- // std::cout << "SPMeshGradient::pattern_new: calling array.smooth2" << std::endl;
- array.smooth2( &array_smoothed, smooth );
- my_array = &array_smoothed;
- break;
- }
- }
-
- cp = cairo_pattern_create_mesh();
-
- for( unsigned int i = 0; i < my_array->patch_rows(); ++i ) {
- for( unsigned int j = 0; j < my_array->patch_columns(); ++j ) {
-
- SPMeshPatchI patch( &(my_array->nodes), i, j );
-
- cairo_mesh_pattern_begin_patch( cp );
- cairo_mesh_pattern_move_to( cp, patch.getPoint( 0, 0 )[X], patch.getPoint( 0, 0 )[Y] );
-
- for( unsigned int k = 0; k < 4; ++k ) {
-#ifdef DEBUG_MESH
- std::cout << i << " " << j << " "
- << patch.getPathType( k ) << " (";
- for( int p = 0; p < 4; ++p ) {
- std::cout << patch.getPoint( k, p );
- }
- std::cout << ") "
- << patch.getColor( k ).toString() << std::endl;
-#endif
-
- switch ( patch.getPathType( k ) ) {
- case 'l':
- case 'L':
- case 'z':
- case 'Z':
- cairo_mesh_pattern_line_to( cp,
- patch.getPoint( k, 3 )[X],
- patch.getPoint( k, 3 )[Y] );
- break;
- case 'c':
- case 'C':
- {
- std::vector< Geom::Point > pts = patch.getPointsForSide( k );
- cairo_mesh_pattern_curve_to( cp,
- pts[1][X], pts[1][Y],
- pts[2][X], pts[2][Y],
- pts[3][X], pts[3][Y] );
- break;
- }
- default:
- // Shouldn't happen
- std::cout << "sp_meshgradient_create_pattern: path error" << std::endl;
- }
-
- if( patch.tensorIsSet(k) ) {
- // Tensor point defined relative to corner.
- Geom::Point t = patch.getTensorPoint(k);
- cairo_mesh_pattern_set_control_point( cp, k, t[X], t[Y] );
- //std::cout << " sp_meshgradient_create_pattern: tensor " << k
- // << " set to " << t << "." << std::endl;
- } else {
- // Geom::Point t = patch.coonsTensorPoint(k);
- //std::cout << " sp_meshgradient_create_pattern: tensor " << k
- // << " calculated as " << t << "." <<std::endl;
- }
-
- cairo_mesh_pattern_set_corner_color_rgba(
- cp, k,
- patch.getColor( k ).v.c[0],
- patch.getColor( k ).v.c[1],
- patch.getColor( k ).v.c[2],
- patch.getOpacity( k ) * opacity );
- }
-
- cairo_mesh_pattern_end_patch( cp );
- }
- }
-
- // set pattern matrix
- Geom::Affine gs2user = this->gradientTransform;
- if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
- Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top());
- gs2user *= bbox2user;
- }
- ink_cairo_pattern_set_matrix(cp, gs2user.inverse());
-
-#else
- static bool shown = false;
- if( !shown ) {
- std::cout << "sp_meshgradient_create_pattern: needs cairo >= 1.11.4, using "
- << cairo_version_string() << std::endl;
- shown = true;
- }
-#endif
-
-/*
- cairo_pattern_t *cp = cairo_pattern_create_radial(
- rg->fx.computed, rg->fy.computed, 0,
- rg->cx.computed, rg->cy.computed, rg->r.computed);
- sp_gradient_pattern_common_setup(cp, gr, bbox, opacity);
-*/
-
- return cp;
-}
diff --git a/src/sp-mesh-patch.cpp b/src/sp-mesh-patch.cpp
index e7c7c837d..834c09935 100644
--- a/src/sp-mesh-patch.cpp
+++ b/src/sp-mesh-patch.cpp
@@ -20,9 +20,9 @@
#include "attributes.h"
#include "xml/repr.h"
-SPMeshPatch* SPMeshPatch::getNextMeshPatch()
+SPMeshpatch* SPMeshpatch::getNextMeshpatch()
{
- SPMeshPatch *result = 0;
+ SPMeshpatch *result = 0;
for (SPObject* obj = getNext(); obj && !result; obj = obj->getNext()) {
if (SP_IS_MESHPATCH(obj)) {
@@ -33,19 +33,19 @@ SPMeshPatch* SPMeshPatch::getNextMeshPatch()
return result;
}
-SPMeshPatch* SPMeshPatch::getPrevMeshPatch()
+SPMeshpatch* SPMeshpatch::getPrevMeshpatch()
{
- SPMeshPatch *result = 0;
+ SPMeshpatch *result = 0;
for (SPObject* obj = getPrev(); obj; obj = obj->getPrev()) {
- // The closest previous SPObject that is an SPMeshPatch *should* be ourself.
+ // The closest previous SPObject that is an SPMeshpatch *should* be ourself.
if (SP_IS_MESHPATCH(obj)) {
- SPMeshPatch* meshpatch = SP_MESHPATCH(obj);
+ SPMeshpatch* meshpatch = SP_MESHPATCH(obj);
// Sanity check to ensure we have a proper sibling structure.
- if (meshpatch->getNextMeshPatch() == this) {
+ if (meshpatch->getNextMeshpatch() == this) {
result = meshpatch;
} else {
- g_warning("SPMeshPatch previous/next relationship broken");
+ g_warning("SPMeshpatch previous/next relationship broken");
}
break;
}
@@ -59,14 +59,14 @@ SPMeshPatch* SPMeshPatch::getPrevMeshPatch()
* Mesh Patch
*/
-SPMeshPatch::SPMeshPatch() : SPObject() {
+SPMeshpatch::SPMeshpatch() : SPObject() {
this->tensor_string = NULL;
}
-SPMeshPatch::~SPMeshPatch() {
+SPMeshpatch::~SPMeshpatch() {
}
-void SPMeshPatch::build(SPDocument* doc, Inkscape::XML::Node* repr) {
+void SPMeshpatch::build(SPDocument* doc, Inkscape::XML::Node* repr) {
SPObject::build(doc, repr);
this->readAttr( "tensor" );
@@ -76,7 +76,7 @@ void SPMeshPatch::build(SPDocument* doc, Inkscape::XML::Node* repr) {
* Virtual build: set meshpatch attributes from its associated XML node.
*/
-void SPMeshPatch::set(unsigned int key, const gchar* value) {
+void SPMeshpatch::set(unsigned int key, const gchar* value) {
switch (key) {
case SP_ATTR_TENSOR: {
if (value) {
@@ -95,9 +95,9 @@ void SPMeshPatch::set(unsigned int key, const gchar* value) {
* Virtual set: set attribute to value.
*/
-Inkscape::XML::Node* SPMeshPatch::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
+Inkscape::XML::Node* SPMeshpatch::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:meshPatch");
+ repr = xml_doc->createElement("svg:meshpatch");
}
SPObject::write(xml_doc, repr, flags);
diff --git a/src/sp-mesh-patch.h b/src/sp-mesh-patch.h
index e57ad1699..88d6325c3 100644
--- a/src/sp-mesh-patch.h
+++ b/src/sp-mesh-patch.h
@@ -2,7 +2,7 @@
#define SEEN_SP_MESHPATCH_H
/** \file
- * SPMeshPatch: SVG <meshpatch> implementation.
+ * SPMeshpatch: SVG <meshpatch> implementation.
*/
/*
* Authors: Tavmjong Bah
@@ -15,17 +15,17 @@
#include <glibmm/ustring.h>
#include "sp-object.h"
-#define SP_MESHPATCH(obj) (dynamic_cast<SPMeshPatch*>((SPObject*)obj))
-#define SP_IS_MESHPATCH(obj) (dynamic_cast<const SPMeshPatch*>((SPObject*)obj) != NULL)
+#define SP_MESHPATCH(obj) (dynamic_cast<SPMeshpatch*>((SPObject*)obj))
+#define SP_IS_MESHPATCH(obj) (dynamic_cast<const SPMeshpatch*>((SPObject*)obj) != NULL)
-/** Gradient MeshPatch. */
-class SPMeshPatch : public SPObject {
+/** Gradient Meshpatch. */
+class SPMeshpatch : public SPObject {
public:
- SPMeshPatch();
- virtual ~SPMeshPatch();
+ SPMeshpatch();
+ virtual ~SPMeshpatch();
- SPMeshPatch* getNextMeshPatch();
- SPMeshPatch* getPrevMeshPatch();
+ SPMeshpatch* getNextMeshpatch();
+ SPMeshpatch* getPrevMeshpatch();
Glib::ustring * tensor_string;
//SVGLength tx[4]; // Tensor points
//SVGLength ty[4]; // Tensor points
diff --git a/src/sp-mesh-row.cpp b/src/sp-mesh-row.cpp
index f95909b63..dd7948bdf 100644
--- a/src/sp-mesh-row.cpp
+++ b/src/sp-mesh-row.cpp
@@ -1,5 +1,5 @@
/** @file
- * @gradient meshpatch class.
+ * @gradient meshrow class.
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
@@ -19,9 +19,9 @@
#include "xml/repr.h"
-SPMeshRow* SPMeshRow::getNextMeshRow()
+SPMeshrow* SPMeshrow::getNextMeshrow()
{
- SPMeshRow *result = 0;
+ SPMeshrow *result = 0;
for (SPObject* obj = getNext(); obj && !result; obj = obj->getNext()) {
if (SP_IS_MESHROW(obj)) {
@@ -32,19 +32,19 @@ SPMeshRow* SPMeshRow::getNextMeshRow()
return result;
}
-SPMeshRow* SPMeshRow::getPrevMeshRow()
+SPMeshrow* SPMeshrow::getPrevMeshrow()
{
- SPMeshRow *result = 0;
+ SPMeshrow *result = 0;
for (SPObject* obj = getPrev(); obj; obj = obj->getPrev()) {
- // The closest previous SPObject that is an SPMeshRow *should* be ourself.
+ // The closest previous SPObject that is an SPMeshrow *should* be ourself.
if (SP_IS_MESHROW(obj)) {
- SPMeshRow* meshrow = SP_MESHROW(obj);
+ SPMeshrow* meshrow = SP_MESHROW(obj);
// Sanity check to ensure we have a proper sibling structure.
- if (meshrow->getNextMeshRow() == this) {
+ if (meshrow->getNextMeshrow() == this) {
result = meshrow;
} else {
- g_warning("SPMeshRow previous/next relationship broken");
+ g_warning("SPMeshrow previous/next relationship broken");
}
break;
}
@@ -57,13 +57,13 @@ SPMeshRow* SPMeshRow::getPrevMeshRow()
/*
* Mesh Row
*/
-SPMeshRow::SPMeshRow() : SPObject() {
+SPMeshrow::SPMeshrow() : SPObject() {
}
-SPMeshRow::~SPMeshRow() {
+SPMeshrow::~SPMeshrow() {
}
-void SPMeshRow::build(SPDocument* doc, Inkscape::XML::Node* repr) {
+void SPMeshrow::build(SPDocument* doc, Inkscape::XML::Node* repr) {
SPObject::build(doc, repr);
}
@@ -71,16 +71,16 @@ void SPMeshRow::build(SPDocument* doc, Inkscape::XML::Node* repr) {
* Virtual build: set meshrow attributes from its associated XML node.
*/
-void SPMeshRow::set(unsigned int /*key*/, const gchar* /*value*/) {
+void SPMeshrow::set(unsigned int /*key*/, const gchar* /*value*/) {
}
/**
* Virtual set: set attribute to value.
*/
-Inkscape::XML::Node* SPMeshRow::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
+Inkscape::XML::Node* SPMeshrow::write(Inkscape::XML::Document* xml_doc, Inkscape::XML::Node* repr, guint flags) {
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:meshRow");
+ repr = xml_doc->createElement("svg:meshrow");
}
SPObject::write(xml_doc, repr, flags);
diff --git a/src/sp-mesh-row.h b/src/sp-mesh-row.h
index 793b5a645..ffb3efa6b 100644
--- a/src/sp-mesh-row.h
+++ b/src/sp-mesh-row.h
@@ -2,7 +2,7 @@
#define SEEN_SP_MESHROW_H
/** \file
- * SPMeshRow: SVG <meshRow> implementation.
+ * SPMeshrow: SVG <meshrow> implementation.
*/
/*
* Authors: Tavmjong Bah
@@ -13,17 +13,17 @@
#include "sp-object.h"
-#define SP_MESHROW(obj) (dynamic_cast<SPMeshRow*>((SPObject*)obj))
-#define SP_IS_MESHROW(obj) (dynamic_cast<const SPMeshRow*>((SPObject*)obj) != NULL)
+#define SP_MESHROW(obj) (dynamic_cast<SPMeshrow*>((SPObject*)obj))
+#define SP_IS_MESHROW(obj) (dynamic_cast<const SPMeshrow*>((SPObject*)obj) != NULL)
-/** Gradient MeshRow. */
-class SPMeshRow : public SPObject {
+/** Gradient Meshrow. */
+class SPMeshrow : public SPObject {
public:
- SPMeshRow();
- virtual ~SPMeshRow();
+ SPMeshrow();
+ virtual ~SPMeshrow();
- SPMeshRow* getNextMeshRow();
- SPMeshRow* getPrevMeshRow();
+ SPMeshrow* getNextMeshrow();
+ SPMeshrow* getPrevMeshrow();
protected:
virtual void build(SPDocument* doc, Inkscape::XML::Node* repr);
diff --git a/src/sp-mesh.cpp b/src/sp-mesh.cpp
new file mode 100644
index 000000000..e04c29e8e
--- /dev/null
+++ b/src/sp-mesh.cpp
@@ -0,0 +1,252 @@
+#include <glibmm.h>
+
+#include "attributes.h"
+#include "display/cairo-utils.h"
+#include "xml/repr.h"
+
+#include "sp-mesh.h"
+
+/*
+ * Mesh Gradient
+ */
+//#define MESH_DEBUG
+SPMesh::SPMesh() : SPGradient(), type( SP_MESH_TYPE_COONS ), type_set(false) {
+ // Start coordinate of mesh
+ this->x.unset(SVGLength::NONE, 0.0, 0.0);
+ this->y.unset(SVGLength::NONE, 0.0, 0.0);
+}
+
+SPMesh::~SPMesh() {
+}
+
+void SPMesh::build(SPDocument *document, Inkscape::XML::Node *repr) {
+ SPGradient::build(document, repr);
+
+ // Start coordinate of mesh
+ this->readAttr( "x" );
+ this->readAttr( "y" );
+
+ this->readAttr( "type" );
+}
+
+
+void SPMesh::set(unsigned key, gchar const *value) {
+ switch (key) {
+ case SP_ATTR_X:
+ if (!this->x.read(value)) {
+ this->x.unset(SVGLength::NONE, 0.0, 0.0);
+ }
+
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_Y:
+ if (!this->y.read(value)) {
+ this->y.unset(SVGLength::NONE, 0.0, 0.0);
+ }
+
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_TYPE:
+ if (value) {
+ if (!strcmp(value, "coons")) {
+ this->type = SP_MESH_TYPE_COONS;
+ } else if (!strcmp(value, "bicubic")) {
+ this->type = SP_MESH_TYPE_BICUBIC;
+ } else {
+ std::cerr << "SPMesh::set(): invalid value " << value << std::endl;
+ }
+ this->type_set = TRUE;
+ } else {
+ // std::cout << "SPMesh::set() No value " << std::endl;
+ this->type = SP_MESH_TYPE_COONS;
+ this->type_set = FALSE;
+ }
+
+ this->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ default:
+ SPGradient::set(key, value);
+ break;
+ }
+}
+
+/**
+ * Write mesh gradient attributes to associated repr.
+ */
+Inkscape::XML::Node* SPMesh::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
+#ifdef MESH_DEBUG
+ std::cout << "sp_mesh_write() ***************************" << std::endl;
+#endif
+
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("svg:mesh");
+ }
+
+ if ((flags & SP_OBJECT_WRITE_ALL) || this->x._set) {
+ sp_repr_set_svg_double(repr, "x", this->x.computed);
+ }
+
+ if ((flags & SP_OBJECT_WRITE_ALL) || this->y._set) {
+ sp_repr_set_svg_double(repr, "y", this->y.computed);
+ }
+
+ if ((flags & SP_OBJECT_WRITE_ALL) || this->type_set) {
+ switch (this->type) {
+ case SP_MESH_TYPE_COONS:
+ repr->setAttribute("type", "coons");
+ break;
+ case SP_MESH_TYPE_BICUBIC:
+ repr->setAttribute("type", "bicubic");
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ SPGradient::write(xml_doc, repr, flags);
+
+ return repr;
+}
+
+void
+sp_mesh_repr_write(SPMesh *mg)
+{
+ mg->array.write( mg );
+}
+
+
+cairo_pattern_t* SPMesh::pattern_new(cairo_t * /*ct*/,
+#if defined(MESH_DEBUG) || (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4))
+ Geom::OptRect const &bbox,
+ double opacity
+#else
+ Geom::OptRect const & /*bbox*/,
+ double /*opacity*/
+#endif
+ )
+{
+ using Geom::X;
+ using Geom::Y;
+
+#ifdef MESH_DEBUG
+ std::cout << "sp_mesh_create_pattern: (" << bbox->x0 << "," << bbox->y0 << ") (" << bbox->x1 << "," << bbox->y1 << ") " << opacity << std::endl;
+#endif
+
+ this->ensureArray();
+
+ cairo_pattern_t *cp = NULL;
+
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 4)
+ SPMeshNodeArray* my_array = &array;
+
+ if( type_set ) {
+ switch (type) {
+ case SP_MESH_TYPE_COONS:
+ // std::cout << "SPMesh::pattern_new: Coons" << std::endl;
+ break;
+ case SP_MESH_TYPE_BICUBIC:
+ array.bicubic( &array_smoothed, type );
+ my_array = &array_smoothed;
+ break;
+ }
+ }
+
+ cp = cairo_pattern_create_mesh();
+
+ for( unsigned int i = 0; i < my_array->patch_rows(); ++i ) {
+ for( unsigned int j = 0; j < my_array->patch_columns(); ++j ) {
+
+ SPMeshPatchI patch( &(my_array->nodes), i, j );
+
+ cairo_mesh_pattern_begin_patch( cp );
+ cairo_mesh_pattern_move_to( cp, patch.getPoint( 0, 0 )[X], patch.getPoint( 0, 0 )[Y] );
+
+ for( unsigned int k = 0; k < 4; ++k ) {
+#ifdef DEBUG_MESH
+ std::cout << i << " " << j << " "
+ << patch.getPathType( k ) << " (";
+ for( int p = 0; p < 4; ++p ) {
+ std::cout << patch.getPoint( k, p );
+ }
+ std::cout << ") "
+ << patch.getColor( k ).toString() << std::endl;
+#endif
+
+ switch ( patch.getPathType( k ) ) {
+ case 'l':
+ case 'L':
+ case 'z':
+ case 'Z':
+ cairo_mesh_pattern_line_to( cp,
+ patch.getPoint( k, 3 )[X],
+ patch.getPoint( k, 3 )[Y] );
+ break;
+ case 'c':
+ case 'C':
+ {
+ std::vector< Geom::Point > pts = patch.getPointsForSide( k );
+ cairo_mesh_pattern_curve_to( cp,
+ pts[1][X], pts[1][Y],
+ pts[2][X], pts[2][Y],
+ pts[3][X], pts[3][Y] );
+ break;
+ }
+ default:
+ // Shouldn't happen
+ std::cout << "sp_mesh_create_pattern: path error" << std::endl;
+ }
+
+ if( patch.tensorIsSet(k) ) {
+ // Tensor point defined relative to corner.
+ Geom::Point t = patch.getTensorPoint(k);
+ cairo_mesh_pattern_set_control_point( cp, k, t[X], t[Y] );
+ //std::cout << " sp_mesh_create_pattern: tensor " << k
+ // << " set to " << t << "." << std::endl;
+ } else {
+ // Geom::Point t = patch.coonsTensorPoint(k);
+ //std::cout << " sp_mesh_create_pattern: tensor " << k
+ // << " calculated as " << t << "." <<std::endl;
+ }
+
+ cairo_mesh_pattern_set_corner_color_rgba(
+ cp, k,
+ patch.getColor( k ).v.c[0],
+ patch.getColor( k ).v.c[1],
+ patch.getColor( k ).v.c[2],
+ patch.getOpacity( k ) * opacity );
+ }
+
+ cairo_mesh_pattern_end_patch( cp );
+ }
+ }
+
+ // set pattern matrix
+ Geom::Affine gs2user = this->gradientTransform;
+ if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) {
+ Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top());
+ gs2user *= bbox2user;
+ }
+ ink_cairo_pattern_set_matrix(cp, gs2user.inverse());
+
+#else
+ static bool shown = false;
+ if( !shown ) {
+ std::cout << "sp_mesh_create_pattern: needs cairo >= 1.11.4, using "
+ << cairo_version_string() << std::endl;
+ shown = true;
+ }
+#endif
+
+ /*
+ cairo_pattern_t *cp = cairo_pattern_create_radial(
+ rg->fx.computed, rg->fy.computed, 0,
+ rg->cx.computed, rg->cy.computed, rg->r.computed);
+ sp_gradient_pattern_common_setup(cp, gr, bbox, opacity);
+ */
+
+ return cp;
+}
diff --git a/src/sp-mesh-gradient.h b/src/sp-mesh.h
index 343cae840..6f992d034 100644
--- a/src/sp-mesh-gradient.h
+++ b/src/sp-mesh.h
@@ -1,26 +1,26 @@
-#ifndef SP_MESH_GRADIENT_H
-#define SP_MESH_GRADIENT_H
+#ifndef SP_MESH_H
+#define SP_MESH_H
/** \file
- * SPMeshGradient: SVG <meshgradient> implementation.
+ * SPMesh: SVG <mesh> implementation.
*/
#include "svg/svg-length.h"
#include "sp-gradient.h"
-#define SP_MESHGRADIENT(obj) (dynamic_cast<SPMeshGradient*>((SPObject*)obj))
-#define SP_IS_MESHGRADIENT(obj) (dynamic_cast<const SPMeshGradient*>((SPObject*)obj) != NULL)
+#define SP_MESH(obj) (dynamic_cast<SPMesh*>((SPObject*)obj))
+#define SP_IS_MESH(obj) (dynamic_cast<const SPMesh*>((SPObject*)obj) != NULL)
/** Mesh gradient. */
-class SPMeshGradient : public SPGradient {
+class SPMesh : public SPGradient {
public:
- SPMeshGradient();
- virtual ~SPMeshGradient();
+ SPMesh();
+ virtual ~SPMesh();
SVGLength x; // Upper left corner of mesh
SVGLength y; // Upper right corner of mesh
- SPMeshSmooth smooth;
- bool smooth_set;
+ SPMeshType type;
+ bool type_set;
virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity);
protected:
@@ -29,7 +29,7 @@ protected:
virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
};
-#endif /* !SP_MESH_GRADIENT_H */
+#endif /* !SP_MESH_H */
/*
Local Variables:
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index c26eff39f..3154c9e7b 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -261,6 +261,8 @@ void SPNamedView::build(SPDocument *document, Inkscape::XML::Node *repr) {
Geom::Rect viewbox = document->getRoot()->viewBox;
double factor = svgwidth.value(unit_table.primary(Inkscape::Util::UNIT_TYPE_LINEAR)) / viewbox.width();
svg_units = unit_table.findUnit(factor, Inkscape::Util::UNIT_TYPE_LINEAR);
+ } else { // force the document units to be px
+ repr->setAttribute("inkscape:document-units", "px");
}
}
@@ -551,7 +553,7 @@ void SPNamedView::set(unsigned int key, const gchar* value) {
static Inkscape::Util::Unit const *px = unit_table.getUnit("px");
Inkscape::Util::Unit const *new_unit = px;
- if (value) {
+ if (value && document->getRoot()->viewBox_set) {
Inkscape::Util::Unit const *const req_unit = unit_table.getUnit(value);
if ( !unit_table.hasUnit(value) ) {
g_warning("Unrecognized unit `%s'", value);
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index 51cc8d6dc..42883588b 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -130,10 +130,29 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) {
SPShape::build(document, repr);
- // this->readAttr( "inkscape:original-d" ); // lp1299948
+ // this->readAttr( "inkscape:original-d" ); // bug #1299948
+ // Why we take the long way of doing this probably needs some explaining:
+ //
+ // Normally upon being built, reading the inkscape:original-d attribute
+ // will cause the path to actually _write to its repr_ in response to this.
+ // This is bad, bad news if the attached effect refers to a path which
+ // hasn't been constructed yet.
+ //
+ // What will happen is the effect parameter will cause the effect to
+ // recalculate with a completely different value due to the parameter being
+ // "empty" -- even worse, an undo event might be created with the bad value,
+ // and undoing the current action could cause it to revert to the "bad"
+ // state. (After that, the referred object will be constructed and the
+ // reference will trigger the path effect to update and commit the right
+ // value to "d".)
+ //
+ // This mild nastiness here (don't recalculate effects on build) prevents a
+ // plethora of issues with effects with linked parameters doing wild and
+ // stupid things on new documents upon a mere undo.
+
if (gchar const* s = this->getRepr()->attribute("inkscape:original-d"))
{
- // write it to XML, and to my curve, but don't update patheffects
+ // Write the value to _curve_before_lpe, do not recalculate effects
Geom::PathVector pv = sp_svg_read_pathv(s);
SPCurve *curve = new SPCurve(pv);
@@ -148,10 +167,17 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) {
this->readAttr( "d" );
/* d is a required attribute */
- gchar const *d = this->getAttribute("d", NULL);
+ char const *d = this->getAttribute("d", NULL);
if (d == NULL) {
- this->setKeyValue( sp_attribute_lookup("d"), "");
+ // First see if calculating the path effect will generate "d":
+ this->update_patheffect(true);
+ d = this->getAttribute("d", NULL);
+
+ // I guess that didn't work, now we have nothing useful to write ("")
+ if (d == NULL) {
+ this->setKeyValue( sp_attribute_lookup("d"), "");
+ }
}
}
diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp
index 361d3c8c0..e17d7373c 100644
--- a/src/sp-rect.cpp
+++ b/src/sp-rect.cpp
@@ -52,22 +52,30 @@ void SPRect::build(SPDocument* doc, Inkscape::XML::Node* repr) {
void SPRect::set(unsigned key, gchar const *value) {
/* fixme: We need real error processing some time */
+ // We must update the SVGLengths immediately or nodes may be misplaced after they are moved.
+ double const w = viewport.width();
+ double const h = viewport.height();
+ double const em = style->font_size.computed;
+ double const ex = em * 0.5;
+
switch (key) {
case SP_ATTR_X:
- this->x.readOrUnset(value);
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ this->x.readOrUnset(value);
+ this->x.update( ex, em, w );
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_Y:
- this->y.readOrUnset(value);
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ this->y.readOrUnset(value);
+ this->y.update( ex, em, h );
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_WIDTH:
if (!this->width.read(value) || this->width.value < 0.0) {
this->width.unset();
}
-
+ this->width.update( ex, em, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -75,7 +83,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->height.read(value) || this->height.value < 0.0) {
this->height.unset();
}
-
+ this->height.update( ex, em, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -83,7 +91,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->rx.read(value) || this->rx.value <= 0.0) {
this->rx.unset();
}
-
+ this->rx.update( ex, em, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -91,7 +99,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->ry.read(value) || this->ry.value <= 0.0) {
this->ry.unset();
}
-
+ this->ry.update( ex, em, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -129,19 +137,19 @@ Inkscape::XML::Node * SPRect::write(Inkscape::XML::Document *xml_doc, Inkscape::
repr = xml_doc->createElement("svg:rect");
}
- sp_repr_set_svg_double(repr, "width", this->width.computed);
- sp_repr_set_svg_double(repr, "height", this->height.computed);
+ sp_repr_set_svg_length(repr, "width", this->width);
+ sp_repr_set_svg_length(repr, "height", this->height);
if (this->rx._set) {
- sp_repr_set_svg_double(repr, "rx", this->rx.computed);
+ sp_repr_set_svg_length(repr, "rx", this->rx);
}
if (this->ry._set) {
- sp_repr_set_svg_double(repr, "ry", this->ry.computed);
+ sp_repr_set_svg_length(repr, "ry", this->ry);
}
- sp_repr_set_svg_double(repr, "x", this->x.computed);
- sp_repr_set_svg_double(repr, "y", this->y.computed);
+ sp_repr_set_svg_length(repr, "x", this->x);
+ sp_repr_set_svg_length(repr, "y", this->y);
this->set_shape(); // evaluate SPCurve
SPShape::write(xml_doc, repr, flags);
@@ -235,29 +243,29 @@ void SPRect::set_shape() {
/* fixme: Think (Lauris) */
void SPRect::setPosition(gdouble x, gdouble y, gdouble width, gdouble height) {
- this->x.computed = x;
- this->y.computed = y;
- this->width.computed = width;
- this->height.computed = height;
+ this->x = x;
+ this->y = y;
+ this->width = width;
+ this->height = height;
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void SPRect::setRx(bool set, gdouble value) {
- this->rx._set = set;
+ this->rx._set = set;
if (set) {
- this->rx.computed = value;
+ this->rx = value;
}
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void SPRect::setRy(bool set, gdouble value) {
- this->ry._set = set;
+ this->ry._set = set;
if (set) {
- this->ry.computed = value;
+ this->ry = value;
}
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -289,16 +297,16 @@ Geom::Affine SPRect::set_transform(Geom::Affine const& xform) {
ret[3] = 1.0;
}
- /* fixme: Would be nice to preserve units here */
- this->width = this->width.computed * sw;
- this->height = this->height.computed * sh;
+ /* Preserve units */
+ this->width.scale( sw );
+ this->height.scale( sh );
if (this->rx._set) {
- this->rx = this->rx.computed * sw;
+ this->rx.scale( sw );
}
if (this->ry._set) {
- this->ry = this->ry.computed * sh;
+ this->ry.scale( sh );
}
/* Find start in item coords */
@@ -336,15 +344,12 @@ gdouble SPRect::vectorStretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform
void SPRect::setVisibleRx(gdouble rx) {
if (rx == 0) {
- this->rx.computed = 0;
- this->rx._set = false;
+ this->rx.unset();
} else {
- this->rx.computed = rx / SPRect::vectorStretch(
+ this->rx = rx / SPRect::vectorStretch(
Geom::Point(this->x.computed + 1, this->y.computed),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
-
- this->rx._set = true;
+ this->i2doc_affine());
}
this->updateRepr();
@@ -352,15 +357,12 @@ void SPRect::setVisibleRx(gdouble rx) {
void SPRect::setVisibleRy(gdouble ry) {
if (ry == 0) {
- this->ry.computed = 0;
- this->ry._set = false;
+ this->ry.unset();
} else {
- this->ry.computed = ry / SPRect::vectorStretch(
+ this->ry = ry / SPRect::vectorStretch(
Geom::Point(this->x.computed, this->y.computed + 1),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
-
- this->ry._set = true;
+ this->i2doc_affine());
}
this->updateRepr();
@@ -374,7 +376,7 @@ gdouble SPRect::getVisibleRx() const {
return this->rx.computed * SPRect::vectorStretch(
Geom::Point(this->x.computed + 1, this->y.computed),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
}
gdouble SPRect::getVisibleRy() const {
@@ -385,7 +387,7 @@ gdouble SPRect::getVisibleRy() const {
return this->ry.computed * SPRect::vectorStretch(
Geom::Point(this->x.computed, this->y.computed + 1),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
}
Geom::Rect SPRect::getRect() const {
@@ -418,37 +420,33 @@ void SPRect::compensateRxRy(Geom::Affine xform) {
// This is needed because if we just set them the same length in SVG, they might end up unequal because of transform
if ((this->rx._set && !this->ry._set) || (this->ry._set && !this->rx._set)) {
gdouble r = MAX(this->rx.computed, this->ry.computed);
- this->rx.computed = r / eX;
- this->ry.computed = r / eY;
+ this->rx = r / eX;
+ this->ry = r / eY;
} else {
- this->rx.computed = this->rx.computed / eX;
- this->ry.computed = this->ry.computed / eY;
+ this->rx = this->rx.computed / eX;
+ this->ry = this->ry.computed / eY;
}
// Note that a radius may end up larger than half-side if the rect is scaled down;
// that's ok because this preserves the intended radii in case the rect is enlarged again,
// and set_shape will take care of trimming too large radii when generating d=
-
- this->rx._set = this->ry._set = true;
}
void SPRect::setVisibleWidth(gdouble width) {
- this->width.computed = width / SPRect::vectorStretch(
+ this->width = width / SPRect::vectorStretch(
Geom::Point(this->x.computed + 1, this->y.computed),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
- this->width._set = true;
- this->updateRepr();
+ this->updateRepr();
}
void SPRect::setVisibleHeight(gdouble height) {
- this->height.computed = height / SPRect::vectorStretch(
+ this->height = height / SPRect::vectorStretch(
Geom::Point(this->x.computed, this->y.computed + 1),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
- this->height._set = true;
this->updateRepr();
}
@@ -460,7 +458,7 @@ gdouble SPRect::getVisibleWidth() const {
return this->width.computed * SPRect::vectorStretch(
Geom::Point(this->x.computed + 1, this->y.computed),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
}
gdouble SPRect::getVisibleHeight() const {
@@ -471,7 +469,7 @@ gdouble SPRect::getVisibleHeight() const {
return this->height.computed * SPRect::vectorStretch(
Geom::Point(this->x.computed, this->y.computed + 1),
Geom::Point(this->x.computed, this->y.computed),
- this->transform);
+ this->i2doc_affine());
}
void SPRect::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const {
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index c668199c0..a04dedda9 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -1717,7 +1717,9 @@ void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool
if ( !updating ) {
// delete original, apply the transform to the offset
+ const char *n_id = item->getRepr()->attribute("id");
item->deleteObject(false);
+ repr->setAttribute("id", n_id);
nitem->doWriteTransform(repr, transform);
}
diff --git a/src/svg-profile.h b/src/svg-profile.h
index 9d221fc76..8945ee313 100644
--- a/src/svg-profile.h
+++ b/src/svg-profile.h
@@ -74,7 +74,7 @@ public:
SVG_PRINT_1_1, /**< */
- PROFILE_UNIQUE_CNT, /**< A marker to seperate between the entires
+ PROFILE_UNIQUE_CNT, /**< A marker to separate between the entires
that are unique, and those which are
aggregates of them. */
diff --git a/src/svg/svg-length.cpp b/src/svg/svg-length.cpp
index ea235b2e4..edbc59c36 100644
--- a/src/svg/svg-length.cpp
+++ b/src/svg/svg-length.cpp
@@ -14,6 +14,7 @@
#include <cstring>
#include <string>
#include <glib.h>
+#include <iostream>
#include "svg.h"
#include "stringstream.h"
@@ -462,6 +463,51 @@ unsigned int sp_svg_length_read_ldd(gchar const *str, SVGLength::Unit *unit, dou
return r;
}
+std::string const SVGLength::write()
+{
+ return sp_svg_length_write_with_units(*this);
+}
+
+void SVGLength::set(SVGLength::Unit u, float v)
+{
+ _set = true;
+ unit = u;
+ Glib::ustring hack("px");
+ switch( unit ) {
+ case NONE:
+ case PX:
+ case EM:
+ case EX:
+ case PERCENT:
+ break;
+ case PT:
+ hack = "pt";
+ break;
+ case PC:
+ hack = "pc";
+ break;
+ case MM:
+ hack = "pt";
+ break;
+ case CM:
+ hack = "pt";
+ break;
+ case INCH:
+ hack = "pt";
+ break;
+ case FOOT:
+ hack = "pt";
+ break;
+ case MITRE:
+ hack = "m";
+ break;
+ default:
+ break;
+ }
+ value = v;
+ computed = Inkscape::Util::Quantity::convert(v, hack, "px");
+}
+
void SVGLength::set(SVGLength::Unit u, float v, float c)
{
_set = true;
@@ -478,6 +524,12 @@ void SVGLength::unset(SVGLength::Unit u, float v, float c)
computed = c;
}
+void SVGLength::scale(double scale)
+{
+ value *= scale;
+ computed *= scale;
+}
+
void SVGLength::update(double em, double ex, double scale)
{
if (unit == EM) {
diff --git a/src/svg/svg-length.h b/src/svg/svg-length.h
index 1e6b4c96c..84056dd5f 100644
--- a/src/svg/svg-length.h
+++ b/src/svg/svg-length.h
@@ -57,9 +57,13 @@ public:
bool read(char const *str);
void readOrUnset(char const *str, Unit u = NONE, float v = 0, float c = 0);
bool readAbsolute(char const *str);
- void set(Unit u, float v, float c);
+ std::string const write();
+ // To set 'v' use '='
+ void set(Unit u, float v); // Sets computed value based on u and v.
+ void set(Unit u, float v, float c); // Sets all three values.
void unset(Unit u = NONE, float v = 0, float c = 0);
- void update(double em, double ex, double scale);
+ void scale(double scale); // Scales length (value, computed), leaving unit alone.
+ void update(double em, double ex, double scale); // Updates computed value
};
#endif // SEEN_SP_SVG_LENGTH_H
diff --git a/src/trace/potrace/auxiliary.h b/src/trace/potrace/auxiliary.h
index b7480bbb8..dbf124d7c 100644
--- a/src/trace/potrace/auxiliary.h
+++ b/src/trace/potrace/auxiliary.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -8,6 +8,8 @@
#ifndef AUXILIARY_H
#define AUXILIARY_H
+#include <stdlib.h>
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -75,31 +77,4 @@ static inline int floordiv(int a, int n) {
#define sq(a) ((a)*(a))
#define cu(a) ((a)*(a)*(a))
-/* ---------------------------------------------------------------------- */
-/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
-static inline int detrand(int x, int y) {
- unsigned int z;
- static const unsigned char t[256] = {
- /* non-linear sequence: constant term of inverse in GF(8),
- mod x^8+x^4+x^3+x+1 */
- 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
- 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
- 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
- 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
- 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
- 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
- 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
- };
-
- /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
- 5-bit sequence */
- z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
- z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
- return z;
-}
-
#endif /* AUXILIARY_H */
diff --git a/src/trace/potrace/bitmap.h b/src/trace/potrace/bitmap.h
index 2df04b46f..086bbb046 100644
--- a/src/trace/potrace/bitmap.h
+++ b/src/trace/potrace/bitmap.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -7,6 +7,7 @@
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
/* The bitmap type is defined in potracelib.h */
#include "potracelib.h"
@@ -27,7 +28,7 @@
/* macros for accessing pixel at index (x,y). U* macros omit the
bounds check. */
-#define bm_scanline(bm, y) ((bm)->map + (y)*(bm)->dy)
+#define bm_scanline(bm, y) ((bm)->map + (ssize_t)(y)*(ssize_t)(bm)->dy)
#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
@@ -51,10 +52,18 @@ static inline void bm_free(potrace_bitmap_t *bm) {
free(bm);
}
-/* return new un-initialized bitmap. NULL with errno on error */
+/* return new un-initialized bitmap. NULL with errno on error.
+ Assumes w, h >= 0. */
static inline potrace_bitmap_t *bm_new(int w, int h) {
potrace_bitmap_t *bm;
- int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
+ int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
+ ssize_t size = (ssize_t)dy * (ssize_t)h * (ssize_t)BM_WORDSIZE;
+
+ /* check for overflow error */
+ if (size < 0 || size / h / dy != BM_WORDSIZE) {
+ errno = ENOMEM;
+ return NULL;
+ }
bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
if (!bm) {
@@ -63,7 +72,7 @@ static inline potrace_bitmap_t *bm_new(int w, int h) {
bm->w = w;
bm->h = h;
bm->dy = dy;
- bm->map = (potrace_word *) malloc(dy * h * BM_WORDSIZE);
+ bm->map = (potrace_word *) malloc(size);
if (!bm->map) {
free(bm);
return NULL;
@@ -73,23 +82,29 @@ static inline potrace_bitmap_t *bm_new(int w, int h) {
/* clear the given bitmap. Set all bits to c. */
static inline void bm_clear(potrace_bitmap_t *bm, int c) {
- memset(bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE);
+ /* Note: if the bitmap was created with bm_new, then it is
+ guaranteed that size will fit into the ssize_t type. */
+ ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h * (ssize_t)BM_WORDSIZE;
+ memset(bm->map, c ? -1 : 0, size);
}
/* duplicate the given bitmap. Return NULL on error with errno set. */
static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
+ ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h * (ssize_t)BM_WORDSIZE;
if (!bm1) {
return NULL;
}
- memcpy(bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE);
+ memcpy(bm1->map, bm->map, size);
return bm1;
}
/* invert the given bitmap. */
static inline void bm_invert(potrace_bitmap_t *bm) {
- int i;
- for (i = 0; i < bm->dy * bm->h; i++) {
+ ssize_t i;
+ ssize_t size = (ssize_t)bm->dy * (ssize_t)bm->h;
+
+ for (i = 0; i < size; i++) {
bm->map[i] ^= BM_ALLBITS;
}
}
diff --git a/src/trace/potrace/bitops.h b/src/trace/potrace/bitops.h
new file mode 100644
index 000000000..cff734a46
--- /dev/null
+++ b/src/trace/potrace/bitops.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2001-2015 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* bits.h: this file defines some macros for bit manipulations. We
+ provide a generic implementation, as well as machine- and
+ compiler-specific fast implementations */
+
+/* lobit: return the position of the rightmost "1" bit of an int, or
+ 32 if none. hibit: return 1 + the position of the leftmost "1" bit
+ of an int, or 0 if none. Note: these functions work on 32-bit
+ integers. */
+
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* machine specific macros */
+
+#if defined(HAVE_I386)
+
+static inline unsigned int lobit(unsigned int x) {
+ unsigned int res;
+ asm ("bsf %1,%0\n\t"
+ "jnz 0f\n\t"
+ "movl $32,%0\n"
+ "0:"
+ : "=r" (res)
+ : "r" (x)
+ : "cc");
+ return res;
+}
+
+static inline unsigned int hibit(unsigned int x) {
+ unsigned int res;
+
+ asm ("bsr %1,%0\n\t"
+ "jnz 0f\n\t"
+ "movl $-1,%0\n"
+ "0:"
+ : "=r" (res)
+ : "r" (x)
+ : "cc");
+ return res+1;
+}
+
+/* ---------------------------------------------------------------------- */
+#else /* generic macros */
+
+static inline unsigned int lobit(unsigned int x) {
+ unsigned int res = 32;
+ while (x & 0xffffff) {
+ x <<= 8;
+ res -= 8;
+ }
+ while (x) {
+ x <<= 1;
+ res -= 1;
+ }
+ return res;
+}
+
+static inline unsigned int hibit(unsigned int x) {
+ unsigned int res = 0;
+ while (x > 0xff) {
+ x >>= 8;
+ res += 8;
+ }
+ while (x) {
+ x >>= 1;
+ res += 1;
+ }
+ return res;
+}
+
+#endif
+
+#endif /* BITOPS_H */
diff --git a/src/trace/potrace/curve.cpp b/src/trace/potrace/curve.cpp
index d2e32aa7b..e6a9a4721 100644
--- a/src/trace/potrace/curve.cpp
+++ b/src/trace/potrace/curve.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -12,8 +12,8 @@
#include "lists.h"
#include "curve.h"
-#define SAFE_MALLOC(var, n, typ) \
- if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
/* ---------------------------------------------------------------------- */
/* allocate and free path objects */
@@ -22,14 +22,14 @@ path_t *path_new(void) {
path_t *p = NULL;
privpath_t *priv = NULL;
- SAFE_MALLOC(p, 1, path_t);
+ SAFE_CALLOC(p, 1, path_t);
memset(p, 0, sizeof(path_t));
- SAFE_MALLOC(priv, 1, privpath_t);
+ SAFE_CALLOC(priv, 1, privpath_t);
memset(priv, 0, sizeof(privpath_t));
p->priv = priv;
return p;
- malloc_error:
+ calloc_error:
free(p);
free(priv);
return NULL;
@@ -81,15 +81,15 @@ typedef dpoint_t dpoint3_t[3];
int privcurve_init(privcurve_t *curve, int n) {
memset(curve, 0, sizeof(privcurve_t));
curve->n = n;
- SAFE_MALLOC(curve->tag, n, int);
- SAFE_MALLOC(curve->c, n, dpoint3_t);
- SAFE_MALLOC(curve->vertex, n, dpoint_t);
- SAFE_MALLOC(curve->alpha, n, double);
- SAFE_MALLOC(curve->alpha0, n, double);
- SAFE_MALLOC(curve->beta, n, double);
+ SAFE_CALLOC(curve->tag, n, int);
+ SAFE_CALLOC(curve->c, n, dpoint3_t);
+ SAFE_CALLOC(curve->vertex, n, dpoint_t);
+ SAFE_CALLOC(curve->alpha, n, double);
+ SAFE_CALLOC(curve->alpha0, n, double);
+ SAFE_CALLOC(curve->beta, n, double);
return 0;
- malloc_error:
+ calloc_error:
free(curve->tag);
free(curve->c);
free(curve->vertex);
diff --git a/src/trace/potrace/curve.h b/src/trace/potrace/curve.h
index 6ceae0c3a..feb95b39b 100644
--- a/src/trace/potrace/curve.h
+++ b/src/trace/potrace/curve.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/decompose.cpp b/src/trace/potrace/decompose.cpp
index 6c27a7ebf..7628b202d 100644
--- a/src/trace/potrace/decompose.cpp
+++ b/src/trace/potrace/decompose.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -15,6 +15,33 @@
#include "decompose.h"
#include "progress.h"
+/* ---------------------------------------------------------------------- */
+/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
+
+static inline int detrand(int x, int y) {
+ unsigned int z;
+ static const unsigned char t[256] = {
+ /* non-linear sequence: constant term of inverse in GF(8),
+ mod x^8+x^4+x^3+x+1 */
+ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
+ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ };
+
+ /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
+ 5-bit sequence */
+ z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
+ z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
+ return z;
+}
/* ---------------------------------------------------------------------- */
/* auxiliary bitmap manipulations */
diff --git a/src/trace/potrace/decompose.h b/src/trace/potrace/decompose.h
index 89b01e504..8ae89b8ad 100644
--- a/src/trace/potrace/decompose.h
+++ b/src/trace/potrace/decompose.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/greymap.cpp b/src/trace/potrace/greymap.cpp
index e116021c1..4ef2ec8df 100644
--- a/src/trace/potrace/greymap.cpp
+++ b/src/trace/potrace/greymap.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -9,8 +9,10 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <errno.h>
#include "greymap.h"
+#include "bitops.h"
#define INTBITS (8*sizeof(int))
@@ -22,10 +24,17 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp);
/* ---------------------------------------------------------------------- */
/* basic greymap routines */
-/* return new un-initialized greymap. NULL with errno on error */
-
+/* return new un-initialized greymap. NULL with errno on error.
+ Assumes w, h >= 0. */
greymap_t *gm_new(int w, int h) {
greymap_t *gm;
+ ssize_t size = (ssize_t)w * (ssize_t)h * (ssize_t)sizeof(signed short int);
+
+ /* check for overflow error */
+ if (size < 0 || size / w / h != sizeof(signed short int)) {
+ errno = ENOMEM;
+ return NULL;
+ }
gm = (greymap_t *) malloc(sizeof(greymap_t));
if (!gm) {
@@ -33,7 +42,7 @@ greymap_t *gm_new(int w, int h) {
}
gm->w = w;
gm->h = h;
- gm->map = (signed short int *) malloc(w*h*sizeof(signed short int));
+ gm->map = (signed short int *) malloc(size);
if (!gm->map) {
free(gm);
return NULL;
@@ -405,6 +414,10 @@ struct bmp_info_s {
unsigned int YpixelsPerM;
unsigned int ncolors; /* number of colors in palette */
unsigned int ColorsImportant;
+ unsigned int RedMask;
+ unsigned int GreenMask;
+ unsigned int BlueMask;
+ unsigned int AlphaMask;
unsigned int ctbits; /* sample size for color table */
int topdown; /* top-down mode? */
};
@@ -495,6 +508,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
int col[2];
unsigned int bitbuf;
unsigned int n;
+ unsigned int redshift, greenshift, blueshift;
gm_read_error = NULL;
gm = NULL;
@@ -523,12 +537,24 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
- if ((signed int)bmpinfo.h < 0) {
- bmpinfo.h = -bmpinfo.h;
+ if (bmpinfo.InfoSize >= 108) { /* V4 and V5 bitmaps */
+ TRY(bmp_readint(f, 4, &bmpinfo.RedMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.GreenMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.BlueMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.AlphaMask));
+ }
+ if (bmpinfo.w > 0x7fffffff) {
+ goto format_error;
+ }
+ if (bmpinfo.h > 0x7fffffff) {
+ bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
bmpinfo.topdown = 1;
} else {
bmpinfo.topdown = 0;
}
+ if (bmpinfo.h > 0x7fffffff) {
+ goto format_error;
+ }
} else if (bmpinfo.InfoSize == 12) {
/* old OS/2 format */
bmpinfo.ctbits = 24; /* sample size in color table */
@@ -543,6 +569,11 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
goto format_error;
}
+ if (bmpinfo.comp == 3 && bmpinfo.InfoSize < 108) {
+ /* bitfield feature is only understood with V4 and V5 format */
+ goto format_error;
+ }
+
/* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
@@ -557,7 +588,7 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
/* color table, present only if bmpinfo.bits <= 8. */
if (bmpinfo.bits <= 8) {
- coltable = (int *) malloc(bmpinfo.ncolors * sizeof(int));
+ coltable = (int *) calloc(bmpinfo.ncolors, sizeof(int));
if (!coltable) {
goto std_error;
}
@@ -651,6 +682,22 @@ static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
}
break;
+ case 0x320: /* 32-bit encoding with bitfields */
+ redshift = lobit(bmpinfo.RedMask);
+ greenshift = lobit(bmpinfo.GreenMask);
+ blueshift = lobit(bmpinfo.BlueMask);
+
+ for (y=0; y<bmpinfo.h; y++) {
+ bmp_pad_reset();
+ for (x=0; x<bmpinfo.w; x++) {
+ TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
+ c = ((c & bmpinfo.RedMask) >> redshift) + ((c & bmpinfo.GreenMask) >> greenshift) + ((c & bmpinfo.BlueMask) >> blueshift);
+ GM_UPUT(gm, x, ycorr(y), c/3);
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
x = 0;
y = 0;
diff --git a/src/trace/potrace/greymap.h b/src/trace/potrace/greymap.h
index 1fb5426c1..8c9db9bbf 100644
--- a/src/trace/potrace/greymap.h
+++ b/src/trace/potrace/greymap.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -7,6 +7,7 @@
#define GREYMAP_H
#include <stdio.h>
+#include <stdlib.h>
/* internal format for greymaps. Note: in this format, rows are
ordered from bottom to top. The pixels in each row are given from
@@ -22,7 +23,7 @@ typedef struct greymap_s greymap_t;
/* macros for accessing pixel at index (x,y). Note that the origin is
in the *lower* left corner. U* macros omit the bounds check. */
-#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(gm)->w])
+#define gm_index(gm, x, y) (&(gm)->map[(x)+(y)*(ssize_t)(gm)->w])
#define gm_safe(gm, x, y) ((int)(x)>=0 && (int)(x)<(gm)->w && (int)(y)>=0 && (int)(y)<(gm)->h)
#define gm_bound(x, m) ((x)<0 ? 0 : (x)>=(m) ? (m)-1 : (x))
#define GM_UGET(gm, x, y) (*gm_index(gm, x, y))
diff --git a/src/trace/potrace/lists.h b/src/trace/potrace/lists.h
index 078129afc..394262c23 100644
--- a/src/trace/potrace/lists.h
+++ b/src/trace/potrace/lists.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/potracelib.cpp b/src/trace/potrace/potracelib.cpp
index 0fb835593..b5463d676 100644
--- a/src/trace/potrace/potracelib.cpp
+++ b/src/trace/potrace/potracelib.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/potracelib.h b/src/trace/potrace/potracelib.h
index cd142a6e1..0a6ddbf1f 100644
--- a/src/trace/potrace/potracelib.h
+++ b/src/trace/potrace/potracelib.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/progress.h b/src/trace/potrace/progress.h
index 3e1dfb34e..ecc2ba217 100644
--- a/src/trace/potrace/progress.h
+++ b/src/trace/potrace/progress.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/render.cpp b/src/trace/potrace/render.cpp
index 3c8f79c05..4f44ae6a6 100644
--- a/src/trace/potrace/render.cpp
+++ b/src/trace/potrace/render.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -52,7 +52,7 @@ render_t *render_new(greymap_t *gm) {
}
memset(rm, 0, sizeof(render_t));
rm->gm = gm;
- rm->incrow_buf = (int *) malloc(gm->h * sizeof(int));
+ rm->incrow_buf = (int *) calloc(gm->h, sizeof(int));
if (!rm->incrow_buf) {
free(rm);
return NULL;
diff --git a/src/trace/potrace/render.h b/src/trace/potrace/render.h
index ad600156a..0caaedff6 100644
--- a/src/trace/potrace/render.h
+++ b/src/trace/potrace/render.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/trace/potrace/trace.cpp b/src/trace/potrace/trace.cpp
index f1e88a908..469262b67 100644
--- a/src/trace/potrace/trace.cpp
+++ b/src/trace/potrace/trace.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
@@ -21,8 +21,8 @@
#define COS179 -0.999847695156 /* the cosine of 179 degrees */
/* ---------------------------------------------------------------------- */
-#define SAFE_MALLOC(var, n, typ) \
- if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
/* ---------------------------------------------------------------------- */
/* auxiliary functions */
@@ -265,7 +265,7 @@ static int calc_sums(privpath_t *pp) {
int i, x, y;
int n = pp->len;
- SAFE_MALLOC(pp->sums, pp->len+1, sums_t);
+ SAFE_CALLOC(pp->sums, pp->len+1, sums_t);
/* origin */
pp->x0 = pp->pt[0].x;
@@ -284,7 +284,7 @@ static int calc_sums(privpath_t *pp) {
}
return 0;
- malloc_error:
+ calloc_error:
return 1;
}
@@ -331,8 +331,8 @@ static int calc_lon(privpath_t *pp) {
point_t dk; /* direction of k-k1 */
int a, b, c, d;
- SAFE_MALLOC(pivk, n, int);
- SAFE_MALLOC(nc, n, int);
+ SAFE_CALLOC(pivk, n, int);
+ SAFE_CALLOC(nc, n, int);
/* initialize the nc data structure. Point from each point to the
furthest future point to which it is connected by a vertical or
@@ -349,7 +349,7 @@ static int calc_lon(privpath_t *pp) {
nc[i] = k;
}
- SAFE_MALLOC(pp->lon, n, int);
+ SAFE_CALLOC(pp->lon, n, int);
/* determine pivot points: for each i, let pivk[i] be the furthest k
such that all j with i<j<k lie on a line connecting i,k. */
@@ -458,7 +458,7 @@ static int calc_lon(privpath_t *pp) {
free(nc);
return 0;
- malloc_error:
+ calloc_error:
free(pivk);
free(nc);
return 1;
@@ -537,12 +537,12 @@ static int bestpolygon(privpath_t *pp)
double best;
int c;
- SAFE_MALLOC(pen, n+1, double);
- SAFE_MALLOC(prev, n+1, int);
- SAFE_MALLOC(clip0, n, int);
- SAFE_MALLOC(clip1, n+1, int);
- SAFE_MALLOC(seg0, n+1, int);
- SAFE_MALLOC(seg1, n+1, int);
+ SAFE_CALLOC(pen, n+1, double);
+ SAFE_CALLOC(prev, n+1, int);
+ SAFE_CALLOC(clip0, n, int);
+ SAFE_CALLOC(clip1, n+1, int);
+ SAFE_CALLOC(seg0, n+1, int);
+ SAFE_CALLOC(seg1, n+1, int);
/* calculate clipped paths */
for (i=0; i<n; i++) {
@@ -604,7 +604,7 @@ static int bestpolygon(privpath_t *pp)
}
pp->m = m;
- SAFE_MALLOC(pp->po, m, int);
+ SAFE_CALLOC(pp->po, m, int);
/* read off shortest path */
for (i=n, j=m-1; i>0; j--) {
@@ -620,7 +620,7 @@ static int bestpolygon(privpath_t *pp)
free(seg1);
return 0;
- malloc_error:
+ calloc_error:
free(pen);
free(prev);
free(clip0);
@@ -655,13 +655,13 @@ static int adjust_vertices(privpath_t *pp) {
dpoint_t s;
int r;
- SAFE_MALLOC(ctr, m, dpoint_t);
- SAFE_MALLOC(dir, m, dpoint_t);
- SAFE_MALLOC(q, m, quadform_t);
+ SAFE_CALLOC(ctr, m, dpoint_t);
+ SAFE_CALLOC(dir, m, dpoint_t);
+ SAFE_CALLOC(q, m, quadform_t);
r = privcurve_init(&pp->curve, m);
if (r) {
- goto malloc_error;
+ goto calloc_error;
}
/* calculate "optimal" point-slope representation for each line
@@ -827,7 +827,7 @@ static int adjust_vertices(privpath_t *pp) {
free(q);
return 0;
- malloc_error:
+ calloc_error:
free(ctr);
free(dir);
free(q);
@@ -875,7 +875,7 @@ static void smooth(privcurve_t *curve, double alphamax) {
}
curve->alpha0[j] = alpha; /* remember "original" value of alpha */
- if (alpha > alphamax) { /* pointed corner */
+ if (alpha >= alphamax) { /* pointed corner */
curve->tag[j] = POTRACE_CORNER;
curve->c[j][1] = curve->vertex[j];
curve->c[j][2] = p4;
@@ -1075,12 +1075,12 @@ static int opticurve(privpath_t *pp, double opttolerance) {
int *convc = NULL; /* conv[m]: pre-computed convexities */
double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
- SAFE_MALLOC(pt, m+1, int);
- SAFE_MALLOC(pen, m+1, double);
- SAFE_MALLOC(len, m+1, int);
- SAFE_MALLOC(opt, m+1, opti_t);
- SAFE_MALLOC(convc, m, int);
- SAFE_MALLOC(areac, m+1, double);
+ SAFE_CALLOC(pt, m+1, int);
+ SAFE_CALLOC(pen, m+1, double);
+ SAFE_CALLOC(len, m+1, int);
+ SAFE_CALLOC(opt, m+1, opti_t);
+ SAFE_CALLOC(convc, m, int);
+ SAFE_CALLOC(areac, m+1, double);
/* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
for (i=0; i<m; i++) {
@@ -1134,10 +1134,10 @@ static int opticurve(privpath_t *pp, double opttolerance) {
om = len[m];
r = privcurve_init(&pp->ocurve, om);
if (r) {
- goto malloc_error;
+ goto calloc_error;
}
- SAFE_MALLOC(s, om, double);
- SAFE_MALLOC(t, om, double);
+ SAFE_CALLOC(s, om, double);
+ SAFE_CALLOC(t, om, double);
j = m;
for (i=om-1; i>=0; i--) {
@@ -1182,7 +1182,7 @@ static int opticurve(privpath_t *pp, double opttolerance) {
free(areac);
return 0;
- malloc_error:
+ calloc_error:
free(pt);
free(pen);
free(len);
diff --git a/src/trace/potrace/trace.h b/src/trace/potrace/trace.h
index dc2b9247a..c53cdd10f 100644
--- a/src/trace/potrace/trace.h
+++ b/src/trace/potrace/trace.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2011 Peter Selinger.
+/* Copyright (C) 2001-2015 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 674254686..991d11feb 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -1,11 +1,10 @@
-
set(ui_SRC
clipboard.cpp
control-manager.cpp
dialog-events.cpp
draw-anchor.cpp
- interface.cpp
- object-edit.cpp
+ interface.cpp
+ object-edit.cpp
previewholder.cpp
shape-editor.cpp
tool-factory.cpp
@@ -56,8 +55,8 @@ set(ui_SRC
dialog/aboutbox.cpp
dialog/align-and-distribute.cpp
dialog/calligraphic-profile-rename.cpp
- dialog/color-item.cpp
dialog/clonetiler.cpp
+ dialog/color-item.cpp
dialog/debug.cpp
dialog/desktop-tracker.cpp
dialog/dialog-manager.cpp
@@ -86,31 +85,36 @@ set(ui_SRC
dialog/livepatheffect-add.cpp
dialog/livepatheffect-editor.cpp
dialog/lpe-fillet-chamfer-properties.cpp
+ dialog/lpe-powerstroke-properties.cpp
dialog/memory.cpp
dialog/messages.cpp
dialog/new-from-template.cpp
dialog/object-attributes.cpp
dialog/object-properties.cpp
+ dialog/objects.cpp
dialog/ocaldialogs.cpp
+ dialog/pixelartdialog.cpp
dialog/polar-arrange-tab.cpp
dialog/print-colors-preview-dialog.cpp
dialog/print.cpp
- dialog/symbols.cpp
- dialog/xml-tree.cpp
dialog/spellcheck.cpp
dialog/svg-fonts-dialog.cpp
dialog/swatches.cpp
+ dialog/symbols.cpp
+ dialog/tags.cpp
dialog/template-load-tab.cpp
dialog/template-widget.cpp
dialog/text-edit.cpp
dialog/tile.cpp
dialog/tracedialog.cpp
- dialog/pixelartdialog.cpp
dialog/transformation.cpp
dialog/undo-history.cpp
+ dialog/xml-tree.cpp
+ widget/addtoicon.cpp
widget/anchor-selector.cpp
widget/button.cpp
+ widget/clipmaskicon.cpp
widget/color-picker.cpp
widget/color-preview.cpp
widget/dock-item.cpp
@@ -121,10 +125,13 @@ set(ui_SRC
widget/frame.cpp
widget/gimpcolorwheel.c
widget/gimpspinscale.c
+ widget/highlight-picker.cpp
widget/imageicon.cpp
widget/imagetoggler.cpp
+ widget/insertordericon.cpp
widget/labelled.cpp
widget/layer-selector.cpp
+ widget/layertypeicon.cpp
widget/licensor.cpp
widget/notebook-page.cpp
widget/object-composite-settings.cpp
@@ -179,8 +186,8 @@ set(ui_SRC
dialog/arrange-tab.h
dialog/behavior.h
dialog/calligraphic-profile-rename.h
- dialog/color-item.h
dialog/clonetiler.h
+ dialog/color-item.h
dialog/debug.h
dialog/desktop-tracker.h
dialog/dialog-manager.h
@@ -200,8 +207,8 @@ set(ui_SRC
dialog/floating-behavior.h
dialog/font-substitution.h
dialog/glyphs.h
- dialog/guides.h
dialog/grid-arrange-tab.h
+ dialog/guides.h
dialog/icon-preview.h
dialog/inkscape-preferences.h
dialog/input.h
@@ -215,13 +222,13 @@ set(ui_SRC
dialog/new-from-template.h
dialog/object-attributes.h
dialog/object-properties.h
+ dialog/objects.h
dialog/ocaldialogs.h
dialog/panel-dialog.h
- dialog/polar-arrange-tab.h
dialog/pixelartdialog.h
+ dialog/polar-arrange-tab.h
dialog/print-colors-preview-dialog.h
dialog/print.h
-
dialog/spellcheck.h
dialog/svg-fonts-dialog.h
dialog/swatches.h
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index f324f285d..c381ed755 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -1473,6 +1473,7 @@ void DocumentProperties::update()
}
_page_sizer.setDim(Inkscape::Util::Quantity(doc_w, doc_w_unit), Inkscape::Util::Quantity(doc_h, doc_h_unit));
_page_sizer.updateFitMarginsUI(nv->getRepr());
+ _page_sizer.updateScaleUI();
//-----------------------------------------------------------guide page
@@ -1655,6 +1656,8 @@ void DocumentProperties::onRemoveGrid()
}
/** Callback for document unit change. */
+/* This should not effect anything in the SVG tree (other than "inkscape:document-units").
+ This should only effect values displayed in the GUI. */
void DocumentProperties::onDocUnitChange()
{
SPDocument *doc = SP_ACTIVE_DOCUMENT;
@@ -1680,6 +1683,8 @@ void DocumentProperties::onDocUnitChange()
os << doc_unit->abbr;
repr->setAttribute("inkscape:document-units", os.str().c_str());
+ _page_sizer.updateScaleUI();
+
// Disable changing of SVG Units. The intent here is to change the units in the UI, not the units in SVG.
// This code should be moved (and fixed) once we have an "SVG Units" setting that sets what units are used in SVG data.
#if 0
diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp
index 34339dab2..cafc3be4f 100644
--- a/src/ui/dialog/filedialogimpl-win32.cpp
+++ b/src/ui/dialog/filedialogimpl-win32.cpp
@@ -44,6 +44,7 @@
#include "filedialog.h"
#include "sp-root.h"
+#include "preferences.h"
#include <zlib.h>
#include <cairomm/win32_surface.h>
@@ -272,6 +273,9 @@ void FileOpenDialogImplWin32::createFilterMenu()
}
if (dialogType != EXE_TYPES) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ _show_preview = prefs->getBool("/dialogs/open/enable_preview", true);
+
// Compose the filter string
Inkscape::Extension::DB::InputList extension_list;
Inkscape::Extension::db.get_input_list(extension_list);
@@ -842,6 +846,10 @@ LRESULT CALLBACK FileOpenDialogImplWin32::preview_wnd_proc(HWND hwnd, UINT uMsg,
void FileOpenDialogImplWin32::enable_preview(bool enable)
{
+ if (_show_preview != enable) {
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/dialogs/open/enable_preview", enable);
+ }
_show_preview = enable;
// Relayout the dialog
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index cb2771503..f81519ed1 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -211,7 +211,7 @@ private:
ComboBoxEnum<T>* combo;
};
-// Contains an arbitrary number of spin buttons that use seperate attributes
+// Contains an arbitrary number of spin buttons that use separate attributes
class MultiSpinButton : public Gtk::HBox
{
public:
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 9f86158aa..3b0731953 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -529,14 +529,14 @@ void InkscapePreferences::initPageUI()
_("English/Canada (en_CA)"), _("English/Great Britain (en_GB)"), _("Pig Latin (en_US@piglatin)"),
_("Esperanto (eo)"), _("Estonian (et)"), _("Farsi (fa)"), _("Finnish (fi)"),
_("French (fr)"), _("Irish (ga)"), _("Galician (gl)"), _("Hebrew (he)"), _("Hungarian (hu)"),
- _("Indonesian (id)"), _("Italian (it)"), _("Japanese (ja)"), _("Khmer (km)"), _("Kinyarwanda (rw)"), _("Korean (ko)"), _("Lithuanian (lt)"), _("Latvian (lv)"), _("Macedonian (mk)"),
+ _("Indonesian (id)"), _("Icelandic (is)"), _("Italian (it)"), _("Japanese (ja)"), _("Khmer (km)"), _("Kinyarwanda (rw)"), _("Korean (ko)"), _("Lithuanian (lt)"), _("Latvian (lv)"), _("Macedonian (mk)"),
_("Mongolian (mn)"), _("Nepali (ne)"), _("Norwegian Bokmål (nb)"), _("Norwegian Nynorsk (nn)"), _("Panjabi (pa)"),
_("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"), _("Romanian (ro)"), _("Russian (ru)"),
_("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"),
_("Swedish (sv)"),_("Telugu (te)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
Glib::ustring langValues[] = {"", "sq", "am", "ar", "hy", "az", "eu", "be", "bg", "bn", "bn_BD", "br", "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs", "da", "nl",
"dz", "de", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et", "fa", "fi", "fr", "ga",
- "gl", "he", "hu", "id", "it", "ja", "km", "rw", "ko", "lt", "lv", "mk", "mn", "ne", "nb", "nn", "pa",
+ "gl", "he", "hu", "id", "is", "it", "ja", "km", "rw", "ko", "lt", "lv", "mk", "mn", "ne", "nb", "nn", "pa",
"pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te", "th", "tr", "uk", "vi" };
{
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
index b318933a7..7e5c17133 100644
--- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp
@@ -129,7 +129,7 @@ void FilletChamferPropertiesDialog::showDialog(
const gchar *unit,
bool use_distance,
bool aprox_radius,
- Glib::ustring const * documentUnit)
+ Glib::ustring documentUnit)
{
FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog();
@@ -172,7 +172,7 @@ void FilletChamferPropertiesDialog::_apply()
}
d_pos = _index + (d_pos / 100);
} else {
- d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, *document_unit);
+ d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, document_unit);
d_pos = d_pos * -1;
}
_knotpoint->knot_set_offset(Geom::Point(d_pos, d_width));
@@ -226,7 +226,7 @@ void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint)
_fillet_chamfer_position_label.set_label(_(posConcat.c_str()));
position = knotpoint[Geom::X] * -1;
- position = Inkscape::Util::Quantity::convert(position, *document_unit, unit);
+ position = Inkscape::Util::Quantity::convert(position, document_unit, unit);
}
_fillet_chamfer_position_numeric.set_value(position);
if (knotpoint.y() == 1) {
@@ -256,7 +256,7 @@ void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr)
unit = abbr;
}
-void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring const *abbr)
+void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring abbr)
{
document_unit = abbr;
}
diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h
index 3807e98c8..870a1734f 100644
--- a/src/ui/dialog/lpe-fillet-chamfer-properties.h
+++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h
@@ -33,7 +33,7 @@ public:
const gchar *unit,
bool use_distance,
bool aprox_radius,
- Glib::ustring const * documentUnit);
+ Glib::ustring documentUnit);
protected:
@@ -69,14 +69,14 @@ protected:
void _set_pt(const Inkscape::LivePathEffect::
FilletChamferPointArrayParamKnotHolderEntity *pt);
void _set_unit(const gchar *abbr);
- void _set_document_unit(Glib::ustring const * abbr);
+ void _set_document_unit(Glib::ustring abbr);
void _set_use_distance(bool use_knot_distance);
void _set_aprox(bool aprox_radius);
void _apply();
void _close();
bool _flexible;
const gchar *unit;
- Glib::ustring const * document_unit;
+ Glib::ustring document_unit;
bool use_distance;
bool aprox;
void _set_knot_point(Geom::Point knotpoint);
diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp
index 351971294..c44d645a5 100644
--- a/src/ui/dialog/print.cpp
+++ b/src/ui/dialog/print.cpp
@@ -126,30 +126,13 @@ static void draw_page(
cairo_surface_t *surface = cairo_get_target(cr);
cairo_matrix_t ctm;
cairo_get_matrix(cr, &ctm);
-#ifdef WIN32
- //Gtk+ does not take the non printable area into account
- //http://bugzilla.gnome.org/show_bug.cgi?id=381371
- //
- // This workaround translates the origin from the top left of the
- // printable area to the top left of the page.
- GtkPrintSettings *settings = gtk_print_operation_get_print_settings(operation);
- const gchar *printerName = gtk_print_settings_get_printer(settings);
- HDC hdc = CreateDC("WINSPOOL", printerName, NULL, NULL);
- if (hdc) {
- cairo_matrix_t mat;
- int x_off = GetDeviceCaps (hdc, PHYSICALOFFSETX);
- int y_off = GetDeviceCaps (hdc, PHYSICALOFFSETY);
- cairo_matrix_init_translate(&mat, -x_off, -y_off);
- cairo_matrix_multiply (&ctm, &ctm, &mat);
- DeleteDC(hdc);
- }
-#endif
+
bool ret = ctx->setSurfaceTarget (surface, true, &ctm);
if (ret) {
ret = renderer.setupDocument (ctx, junk->_doc, TRUE, 0., NULL);
if (ret) {
renderer.renderItem(ctx, junk->_base);
- ret = ctx->finish();
+ ctx->finish();
}
else {
g_warning("%s", _("Could not set up Document"));
diff --git a/src/ui/object-edit.cpp b/src/ui/object-edit.cpp
index c3bc2d52c..0a6c792dc 100644
--- a/src/ui/object-edit.cpp
+++ b/src/ui/object-edit.cpp
@@ -154,12 +154,9 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig
if (state & GDK_CONTROL_MASK) {
gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0;
- rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, temp);
- rect->rx._set = rect->ry._set = true;
-
+ rect->rx = rect->ry = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, temp);
} else {
- rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, rect->width.computed / 2.0);
- rect->rx._set = true;
+ rect->rx = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, rect->width.computed / 2.0);
}
update_knot();
@@ -207,20 +204,17 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig
if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry,
// resulting in a perfect circle (and not an ellipse)
gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0;
- rect->rx.computed = rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp);
- rect->ry._set = rect->rx._set = true;
+ rect->rx = rect->ry = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp);
} else {
if (!rect->rx._set || rect->rx.computed == 0) {
- rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed,
- 0.0,
- MIN(rect->height.computed / 2.0, rect->width.computed / 2.0));
+ rect->ry = CLAMP(s[Geom::Y] - rect->y.computed,
+ 0.0,
+ MIN(rect->height.computed / 2.0, rect->width.computed / 2.0));
} else {
- rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed,
- 0.0,
- rect->height.computed / 2.0);
+ rect->ry = CLAMP(s[Geom::Y] - rect->y.computed,
+ 0.0,
+ rect->height.computed / 2.0);
}
-
- rect->ry._set = true;
}
update_knot();
@@ -250,12 +244,10 @@ static void sp_rect_clamp_radii(SPRect *rect)
{
// clamp rounding radii so that they do not exceed width/height
if (2 * rect->rx.computed > rect->width.computed) {
- rect->rx.computed = 0.5 * rect->width.computed;
- rect->rx._set = true;
+ rect->rx = 0.5 * rect->width.computed;
}
if (2 * rect->ry.computed > rect->height.computed) {
- rect->ry.computed = 0.5 * rect->height.computed;
- rect->ry._set = true;
+ rect->ry = 0.5 * rect->height.computed;
}
}
@@ -298,16 +290,16 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
minx = s[Geom::X] - origin[Geom::X];
// Dead assignment: Value stored to 'miny' is never read
//miny = s[Geom::Y] - origin[Geom::Y];
- rect->height.computed = MAX(h_orig + minx / ratio, 0);
+ rect->height = MAX(h_orig + minx / ratio, 0);
} else {
// closer to the horizontal, change only width, height is h_orig
s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0)), state);
minx = s[Geom::X] - origin[Geom::X];
// Dead assignment: Value stored to 'miny' is never read
//miny = s[Geom::Y] - origin[Geom::Y];
- rect->height.computed = MAX(h_orig, 0);
+ rect->height = MAX(h_orig, 0);
}
- rect->width.computed = MAX(w_orig + minx, 0);
+ rect->width = MAX(w_orig + minx, 0);
} else {
// snap to vertical or diagonal
@@ -317,27 +309,24 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or
// Dead assignment: Value stored to 'minx' is never read
//minx = s[Geom::X] - origin[Geom::X];
miny = s[Geom::Y] - origin[Geom::Y];
- rect->width.computed = MAX(w_orig + miny * ratio, 0);
+ rect->width = MAX(w_orig + miny * ratio, 0);
} else {
// closer to the vertical, change only height, width is w_orig
s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1)), state);
// Dead assignment: Value stored to 'minx' is never read
//minx = s[Geom::X] - origin[Geom::X];
miny = s[Geom::Y] - origin[Geom::Y];
- rect->width.computed = MAX(w_orig, 0);
+ rect->width = MAX(w_orig, 0);
}
- rect->height.computed = MAX(h_orig + miny, 0);
+ rect->height = MAX(h_orig + miny, 0);
}
- rect->width._set = rect->height._set = true;
-
} else {
// move freely
s = snap_knot_position(p, state);
- rect->width.computed = MAX(s[Geom::X] - rect->x.computed, 0);
- rect->height.computed = MAX(s[Geom::Y] - rect->y.computed, 0);
- rect->width._set = rect->height._set = true;
+ rect->width = MAX(s[Geom::X] - rect->x.computed, 0);
+ rect->height = MAX(s[Geom::Y] - rect->y.computed, 0);
}
sp_rect_clamp_radii(rect);
@@ -394,19 +383,19 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin
minx = s[Geom::X] - origin[Geom::X];
// Dead assignment: Value stored to 'miny' is never read
//miny = s[Geom::Y] - origin[Geom::Y];
- rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y);
- rect->height.computed = MAX(h_orig - minx / ratio, 0);
+ rect->y = MIN(origin[Geom::Y] + minx / ratio, opposite_y);
+ rect->height = MAX(h_orig - minx / ratio, 0);
} else {
// closer to the horizontal, change only width, height is h_orig
s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(-1, 0)), state);
minx = s[Geom::X] - origin[Geom::X];
// Dead assignment: Value stored to 'miny' is never read
//miny = s[Geom::Y] - origin[Geom::Y];
- rect->y.computed = MIN(origin[Geom::Y], opposite_y);
- rect->height.computed = MAX(h_orig, 0);
+ rect->y = MIN(origin[Geom::Y], opposite_y);
+ rect->height = MAX(h_orig, 0);
}
- rect->x.computed = MIN(s[Geom::X], opposite_x);
- rect->width.computed = MAX(w_orig - minx, 0);
+ rect->x = MIN(s[Geom::X], opposite_x);
+ rect->width = MAX(w_orig - minx, 0);
} else {
// snap to vertical or diagonal
if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) {
@@ -415,34 +404,31 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin
// Dead assignment: Value stored to 'minx' is never read
//minx = s[Geom::X] - origin[Geom::X];
miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x);
- rect->width.computed = MAX(w_orig - miny * ratio, 0);
+ rect->x = MIN(origin[Geom::X] + miny * ratio, opposite_x);
+ rect->width = MAX(w_orig - miny * ratio, 0);
} else {
// closer to the vertical, change only height, width is w_orig
s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(p_handle, Geom::Point(0, -1)), state);
// Dead assignment: Value stored to 'minx' is never read
//minx = s[Geom::X] - origin[Geom::X];
miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(origin[Geom::X], opposite_x);
- rect->width.computed = MAX(w_orig, 0);
+ rect->x = MIN(origin[Geom::X], opposite_x);
+ rect->width = MAX(w_orig, 0);
}
- rect->y.computed = MIN(s[Geom::Y], opposite_y);
- rect->height.computed = MAX(h_orig - miny, 0);
+ rect->y = MIN(s[Geom::Y], opposite_y);
+ rect->height = MAX(h_orig - miny, 0);
}
- rect->width._set = rect->height._set = rect->x._set = rect->y._set = true;
-
} else {
// move freely
s = snap_knot_position(p, state);
minx = s[Geom::X] - origin[Geom::X];
miny = s[Geom::Y] - origin[Geom::Y];
- rect->x.computed = MIN(s[Geom::X], opposite_x);
- rect->width.computed = MAX(w_orig - minx, 0);
- rect->y.computed = MIN(s[Geom::Y], opposite_y);
- rect->height.computed = MAX(h_orig - miny, 0);
- rect->width._set = rect->height._set = rect->x._set = rect->y._set = true;
+ rect->x = MIN(s[Geom::X], opposite_x);
+ rect->y = MIN(s[Geom::Y], opposite_y);
+ rect->width = MAX(w_orig - minx, 0);
+ rect->height = MAX(h_orig - miny, 0);
}
sp_rect_clamp_radii(rect);
@@ -917,10 +903,10 @@ ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origi
Geom::Point const s = snap_knot_position(p, state);
- ge->rx.computed = fabs( ge->cx.computed - s[Geom::X] );
+ ge->rx = fabs( ge->cx.computed - s[Geom::X] );
if ( state & GDK_CONTROL_MASK ) {
- ge->ry.computed = ge->rx.computed;
+ ge->ry = ge->rx.computed;
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -942,7 +928,7 @@ ArcKnotHolderEntityRX::knot_click(unsigned int state)
g_assert(ge != NULL);
if (state & GDK_CONTROL_MASK) {
- ge->ry.computed = ge->rx.computed;
+ ge->ry = ge->rx.computed;
ge->updateRepr();
}
}
@@ -955,10 +941,10 @@ ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origi
Geom::Point const s = snap_knot_position(p, state);
- ge->ry.computed = fabs( ge->cy.computed - s[Geom::Y] );
+ ge->ry = fabs( ge->cy.computed - s[Geom::Y] );
if ( state & GDK_CONTROL_MASK ) {
- ge->rx.computed = ge->ry.computed;
+ ge->rx = ge->ry.computed;
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -980,7 +966,7 @@ ArcKnotHolderEntityRY::knot_click(unsigned int state)
g_assert(ge != NULL);
if (state & GDK_CONTROL_MASK) {
- ge->rx.computed = ge->ry.computed;
+ ge->rx = ge->ry.computed;
ge->updateRepr();
}
}
diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp
index 49c949107..23640456e 100644
--- a/src/ui/tool/curve-drag-point.cpp
+++ b/src/ui/tool/curve-drag-point.cpp
@@ -54,7 +54,7 @@ bool CurveDragPoint::grabbed(GdkEventMotion */*event*/)
// delta is a vector equal 1/3 of distance from first to second
Geom::Point delta = (second->position() - first->position()) / 3.0;
// only update the nodes if the mode is bspline
- if(!_pm.isBSpline(false)){
+ if(!_pm._isBSpline()){
first->front()->move(first->front()->position() + delta);
second->back()->move(second->back()->position() - delta);
}
@@ -91,7 +91,7 @@ void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
//modified so that, if the trace is bspline, it only acts if the SHIFT key is pressed
- if(!_pm.isBSpline(false)){
+ if(!_pm._isBSpline()){
first->front()->move(first->front()->position() + offset0);
second->back()->move(second->back()->position() + offset1);
}else if(weight>=0.8){
diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h
index cdbf34e9d..1bbcdd7ec 100644
--- a/src/ui/tool/multi-path-manipulator.h
+++ b/src/ui/tool/multi-path-manipulator.h
@@ -39,7 +39,7 @@ public:
virtual bool event(Inkscape::UI::Tools::ToolBase *, GdkEvent *event);
bool empty() { return _mmap.empty(); }
- unsigned size() { return _mmap.empty(); }
+ unsigned size() { return _mmap.size(); }
void setItems(std::set<ShapeRecord> const &);
void clear() { _mmap.clear(); }
void cleanup();
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index eeea47e4d..aa5365265 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -175,9 +175,9 @@ void Handle::move(Geom::Point const &new_pos)
setPosition(new_pos);
//move the handler and its oposite the same proportion
- if(_pm().isBSpline()){
- setPosition(_pm().BSplineHandleReposition(this,this));
- this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ if(_pm()._isBSpline()){
+ setPosition(_pm()._bsplineHandleReposition(this,this));
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
}
return;
}
@@ -192,9 +192,9 @@ void Handle::move(Geom::Point const &new_pos)
setRelativePos(new_delta);
//move the handler and its oposite the same proportion
- if(_pm().isBSpline()){
- setPosition(_pm().BSplineHandleReposition(this,this));
- this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ if(_pm()._isBSpline()){
+ setPosition(_pm()._bsplineHandleReposition(this,this));
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
}
return;
@@ -218,11 +218,10 @@ void Handle::move(Geom::Point const &new_pos)
setPosition(new_pos);
// moves the handler and its oposite the same proportion
- if(_pm().isBSpline()){
- setPosition(_pm().BSplineHandleReposition(this,this));
- this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ if(_pm()._isBSpline()){
+ setPosition(_pm()._bsplineHandleReposition(this,this));
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
}
-
}
void Handle::setPosition(Geom::Point const &p)
@@ -313,9 +312,9 @@ bool Handle::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEven
//this function moves the handler and its oposite to the default proportion of defaultStartPower
void Handle::handle_2button_press(){
- if(_pm().isBSpline()){
- setPosition(_pm().BSplineHandleReposition(this,defaultStartPower));
- this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),defaultStartPower));
+ if(_pm()._isBSpline()){
+ setPosition(_pm()._bsplineHandleReposition(this,defaultStartPower));
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),defaultStartPower));
_pm().update();
}
}
@@ -373,16 +372,16 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
new_pos = result;
// moves the handler and its oposite in X fixed positions depending on parameter "steps with control"
// by default in live BSpline
- if(_pm().isBSpline()){
+ if(_pm()._isBSpline()){
setPosition(new_pos);
- int steps = _pm().BSplineGetSteps();
- new_pos=_pm().BSplineHandleReposition(this,ceilf(_pm().BSplineHandlePosition(this,this)*steps)/steps);
+ int steps = _pm()._bsplineGetSteps();
+ new_pos=_pm()._bsplineHandleReposition(this,ceilf(_pm()._bsplineHandlePosition(this,this)*steps)/steps);
}
}
std::vector<Inkscape::SnapCandidatePoint> unselected;
//if the snap adjustment is activated and it is not bspline
- if (snap && !_pm().isBSpline(false)) {
+ if (snap && !_pm()._isBSpline()) {
ControlPointSelection::Set &nodes = _parent->_selection.allPoints();
for (ControlPointSelection::Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
Node *n = static_cast<Node*>(*i);
@@ -423,7 +422,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
}
}
//if it is bspline but SHIFT or CONTROL are not pressed it fixes it in the original position
- if(_pm().isBSpline() && !held_shift(*event) && !held_control(*event)){
+ if(_pm()._isBSpline() && !held_shift(*event) && !held_control(*event)){
new_pos=_last_drag_origin();
}
move(new_pos); // needed for correct update, even though it's redundant
@@ -486,8 +485,8 @@ Glib::ustring Handle::_getTip(unsigned state) const
char const *more;
// a trick to mark as bspline if the node has no strength, we are going to use it later
// to show the appropiate messages. We cannot do it in any different way becasue the function is constant
-
- bool isBSpline = _pm().isBSpline();
+ Handle *h = const_cast<Handle *>(this);
+ bool isBSpline = _pm()._isBSpline();
bool can_shift_rotate = _parent->type() == NODE_CUSP && !other()->isDegenerate();
if (can_shift_rotate && !isBSpline) {
more = C_("Path handle tip", "more: Shift, Ctrl, Alt");
@@ -550,7 +549,7 @@ Glib::ustring Handle::_getTip(unsigned state) const
"<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
}else{
return format_tip(C_("Path handle tip",
- "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s)"), more);
+ "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s). %g power"),more,_pm()._bsplineHandlePosition(h,NULL));
}
}
}
@@ -634,15 +633,15 @@ void Node::move(Geom::Point const &new_pos)
Node *n = this;
Node * nextNode = n->nodeToward(n->front());
Node * prevNode = n->nodeToward(n->back());
- nodeWeight = fmax(_pm().BSplineHandlePosition(n->front()),_pm().BSplineHandlePosition(n->back()));
+ nodeWeight = fmax(_pm()._bsplineHandlePosition(n->front()),_pm()._bsplineHandlePosition(n->back()));
if(prevNode){
if(prevNode->isEndNode()){
- prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front(),prevNode->front());
}
}
if(nextNode){
if(nextNode->isEndNode()){
- nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back(),nextNode->back());
}
}
@@ -656,21 +655,21 @@ void Node::move(Geom::Point const &new_pos)
_fixNeighbors(old_pos, new_pos);
// move the affected handlers. First the node ones, later the adjoining ones.
- if(_pm().isBSpline()){
- _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
- _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(_pm()._isBSpline()){
+ _front.setPosition(_pm()._bsplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm()._bsplineHandleReposition(this->back(),nodeWeight));
if(prevNode){
if(prevNode->isEndNode()){
- prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNodeWeight));
}else{
- prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNode->back()));
}
}
if(nextNode){
if(nextNode->isEndNode()){
- nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNodeWeight));
}else{
- nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNode->front()));
}
}
}
@@ -688,15 +687,15 @@ void Node::transform(Geom::Affine const &m)
Node *n = this;
Node * nextNode = n->nodeToward(n->front());
Node * prevNode = n->nodeToward(n->back());
- nodeWeight = _pm().BSplineHandlePosition(n->front());
+ nodeWeight = _pm()._bsplineHandlePosition(n->front());
if(prevNode){
if(prevNode->isEndNode()){
- prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front(),prevNode->front());
}
}
if(nextNode){
if(nextNode->isEndNode()){
- nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back(),nextNode->back());
}
}
@@ -709,21 +708,21 @@ void Node::transform(Geom::Affine const &m)
_fixNeighbors(old_pos, position());
// move the involved handlers, first the node ones, later the adjoining ones
- if(_pm().isBSpline()){
- _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
- _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(_pm()._isBSpline()){
+ _front.setPosition(_pm()._bsplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm()._bsplineHandleReposition(this->back(),nodeWeight));
if(prevNode){
if(prevNode->isEndNode()){
- prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNodeWeight));
}else{
- prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNode->back()));
}
}
if(nextNode){
if(nextNode->isEndNode()){
- nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNodeWeight));
}else{
- nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNode->front()));
}
}
}
@@ -916,13 +915,13 @@ void Node::setType(NodeType type, bool update_handles)
}
/* in node type changes, about bspline traces, we can mantain them with noPower power in border mode,
or we give them the default power in curve mode */
- if(_pm().isBSpline()){
+ if(_pm()._isBSpline()){
double weight = noPower;
- if(_pm().BSplineHandlePosition(this->front()) != noPower ){
+ if(_pm()._bsplineHandlePosition(this->front()) != noPower ){
weight = defaultStartPower;
}
- _front.setPosition(_pm().BSplineHandleReposition(this->front(),weight));
- _back.setPosition(_pm().BSplineHandleReposition(this->back(),weight));
+ _front.setPosition(_pm()._bsplineHandleReposition(this->front(),weight));
+ _back.setPosition(_pm()._bsplineHandleReposition(this->back(),weight));
}
}
_type = type;
@@ -1172,9 +1171,9 @@ void Node::_setState(State state)
mgr.setActive(_canvas_item, true);
mgr.setPrelight(_canvas_item, false);
//this shows the handlers when selecting the nodes
- if(_pm().isBSpline()){
- this->front()->setPosition(_pm().BSplineHandleReposition(this->front()));
- this->back()->setPosition(_pm().BSplineHandleReposition(this->back()));
+ if(_pm()._isBSpline()){
+ this->front()->setPosition(_pm()._bsplineHandleReposition(this->front()));
+ this->back()->setPosition(_pm()._bsplineHandleReposition(this->back()));
}
break;
}
@@ -1434,7 +1433,9 @@ Node *Node::nodeAwayFrom(Handle *h)
Glib::ustring Node::_getTip(unsigned state) const
{
- bool isBSpline = _pm().isBSpline();
+ bool isBSpline = _pm()._isBSpline();
+ Handle *h = const_cast<Handle *>(&_front);
+ Handle *h2 = const_cast<Handle *>(&_back);
if (state_held_shift(state)) {
bool can_drag_out = (_next() && _front.isDegenerate()) || (_prev() && _back.isDegenerate());
if (can_drag_out) {
@@ -1469,7 +1470,7 @@ Glib::ustring Node::_getTip(unsigned state) const
"<b>%s</b>: drag to shape the path (more: Shift, Ctrl, Alt)"), nodetype);
}else if(_selection.size() == 1){
return format_tip(C_("Path node tip",
- "<b>BSpline node</b>: %g weight, drag to shape the path (more: Shift, Ctrl, Alt)"),noPower/*this->bsplineWeight*/);
+ "<b>BSpline node</b>: drag to shape the path (more: Shift, Ctrl, Alt). %g power"),_pm()._bsplineHandlePosition(h,h2));
}
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path, click to toggle scale/rotation handles (more: Shift, Ctrl, Alt)"), nodetype);
@@ -1479,7 +1480,7 @@ Glib::ustring Node::_getTip(unsigned state) const
"<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
}else{
return format_tip(C_("Path node tip",
- "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"));
+ "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt). %g power"),_pm()._bsplineHandlePosition(h,h2));
}
}
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index c8b986824..6b0c95f68 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -11,6 +11,7 @@
*/
#include "live_effects/lpe-powerstroke.h"
+#include "live_effects/lpe-bspline.h"
#include "live_effects/lpe-fillet-chamfer.h"
#include <string>
#include <sstream>
@@ -43,7 +44,6 @@
#include "ui/tool/multi-path-manipulator.h"
#include "xml/node.h"
#include "xml/node-observer.h"
-#include "live_effects/lpe-bspline.h"
namespace Inkscape {
namespace UI {
@@ -56,8 +56,8 @@ enum PathChange {
};
} // anonymous namespace
-const double handleCubicGap = 0.01;
-const double noPower = 0.0;
+const double HANDLE_CUBIC_GAP = 0.01;
+const double NO_POWER = 0.0;
const double defaultStartPower = 0.3334;
@@ -124,6 +124,7 @@ PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
, _show_path_direction(false)
, _live_outline(true)
, _live_objects(true)
+ , _is_bspline(false)
, _lpe_key(lpe_key)
{
if (_lpe_key.empty()) {
@@ -151,7 +152,7 @@ PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
_createControlPointsFromGeometry();
//Define if the path is BSpline on construction
- isBSpline(true);
+ _recalculateIsBSpline();
}
PathManipulator::~PathManipulator()
@@ -670,12 +671,12 @@ unsigned PathManipulator::_deleteStretch(NodeList::iterator start, NodeList::ite
start = next;
}
// if we are removing, we readjust the handlers
- if(isBSpline()){
+ if(_isBSpline()){
if(start.prev()){
- start.prev()->front()->setPosition(BSplineHandleReposition(start.prev()->front(),start.prev()->back()));
+ start.prev()->front()->setPosition(_bsplineHandleReposition(start.prev()->front(),start.prev()->back()));
}
if(end){
- end->back()->setPosition(BSplineHandleReposition(end->back(),end->front()));
+ end->back()->setPosition(_bsplineHandleReposition(end->back(),end->front()));
}
}
@@ -999,30 +1000,30 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
// set new handle positions
Node *n = new Node(_multi_path_manipulator._path_data.node_data, seg2[0]);
- if(!isBSpline()){
+ if(!_isBSpline()){
n->back()->setPosition(seg1[2]);
n->front()->setPosition(seg2[1]);
n->setType(NODE_SMOOTH, false);
} else {
- Geom::D2< Geom::SBasis > SBasisInsideNodes;
- SPCurve *lineInsideNodes = new SPCurve();
+ Geom::D2< Geom::SBasis > sbasis_inside_nodes;
+ SPCurve *line_inside_nodes = new SPCurve();
if(second->back()->isDegenerate()){
- lineInsideNodes->moveto(n->position());
- lineInsideNodes->lineto(second->position());
- SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
- Geom::Point next = SBasisInsideNodes.valueAt(defaultStartPower);
- next = Geom::Point(next[Geom::X] + handleCubicGap,next[Geom::Y] + handleCubicGap);
- lineInsideNodes->reset();
+ line_inside_nodes->moveto(n->position());
+ line_inside_nodes->lineto(second->position());
+ sbasis_inside_nodes = line_inside_nodes->first_segment()->toSBasis();
+ Geom::Point next = sbasis_inside_nodes.valueAt(defaultStartPower);
+ next = Geom::Point(next[Geom::X] + HANDLE_CUBIC_GAP,next[Geom::Y] + HANDLE_CUBIC_GAP);
+ line_inside_nodes->reset();
n->front()->setPosition(next);
}else{
n->front()->setPosition(seg2[1]);
}
if(first->front()->isDegenerate()){
- lineInsideNodes->moveto(n->position());
- lineInsideNodes->lineto(first->position());
- SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
- Geom::Point previous = SBasisInsideNodes.valueAt(defaultStartPower);
- previous = Geom::Point(previous[Geom::X] + handleCubicGap,previous[Geom::Y] + handleCubicGap);
+ line_inside_nodes->moveto(n->position());
+ line_inside_nodes->lineto(first->position());
+ sbasis_inside_nodes = line_inside_nodes->first_segment()->toSBasis();
+ Geom::Point previous = sbasis_inside_nodes.valueAt(defaultStartPower);
+ previous = Geom::Point(previous[Geom::X] + HANDLE_CUBIC_GAP,previous[Geom::Y] + HANDLE_CUBIC_GAP);
n->back()->setPosition(previous);
}else{
n->back()->setPosition(seg1[2]);
@@ -1217,14 +1218,17 @@ void PathManipulator::_createControlPointsFromGeometry()
}
//determines if the trace has a bspline effect and the number of steps that it takes
-int PathManipulator::BSplineGetSteps() const {
+int PathManipulator::_bsplineGetSteps() const {
LivePathEffect::LPEBSpline const *lpe_bsp = NULL;
- if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()){
- Inkscape::LivePathEffect::Effect const *thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
- if(thisEffect){
- lpe_bsp = dynamic_cast<LivePathEffect::LPEBSpline const*>(thisEffect->getLPEObj()->get_lpe());
+ SPLPEItem * path = dynamic_cast<SPLPEItem *>(_path);
+ if (path){
+ if(path->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect const *this_effect = path->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
+ if(this_effect){
+ lpe_bsp = dynamic_cast<LivePathEffect::LPEBSpline const*>(this_effect->getLPEObj()->get_lpe());
+ }
}
}
int steps = 0;
@@ -1235,66 +1239,72 @@ int PathManipulator::BSplineGetSteps() const {
}
// determines if the trace has bspline effect
-bool PathManipulator::isBSpline(bool recalculate){
- if(recalculate){
- _is_bspline = this->BSplineGetSteps() > 0;
+void PathManipulator::_recalculateIsBSpline(){
+ if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()) {
+ Inkscape::LivePathEffect::Effect const *this_effect = _path->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
+ if(this_effect){
+ _is_bspline = true;
+ return;
+ }
}
- return _is_bspline;
+ _is_bspline = false;
}
-bool PathManipulator::isBSpline() const {
- return BSplineGetSteps() > 0;
+bool PathManipulator::_isBSpline() const {
+ return _is_bspline;
}
// returns the corresponding strength to the position of the handlers
-double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){
+double PathManipulator::_bsplineHandlePosition(Handle *h, Handle *h2)
+{
using Geom::X;
using Geom::Y;
if(h2){
h = h2;
}
- double pos = noPower;
+ double pos = NO_POWER;
Node *n = h->parent();
- Node * nextNode = NULL;
- nextNode = n->nodeToward(h);
- if(nextNode){
- SPCurve *lineInsideNodes = new SPCurve();
- lineInsideNodes->moveto(n->position());
- lineInsideNodes->lineto(nextNode->position());
+ Node * next_node = NULL;
+ next_node = n->nodeToward(h);
+ if(next_node){
+ SPCurve *line_inside_nodes = new SPCurve();
+ line_inside_nodes->moveto(n->position());
+ line_inside_nodes->lineto(next_node->position());
if(!are_near(h->position(), n->position())){
- pos = Geom::nearest_point(Geom::Point(h->position()[X] - handleCubicGap, h->position()[Y] - handleCubicGap), *lineInsideNodes->first_segment());
+ pos = Geom::nearest_point(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
}
}
- if (pos == noPower && !h2){
- return BSplineHandlePosition(h, h->other());
+ if (pos == NO_POWER && !h2){
+ return _bsplineHandlePosition(h, h->other());
}
return pos;
}
// give the location for the handler in the corresponding position
-Geom::Point PathManipulator::BSplineHandleReposition(Handle *h, Handle *h2){
- double pos = this->BSplineHandlePosition(h, h2);
- return BSplineHandleReposition(h,pos);
+Geom::Point PathManipulator::_bsplineHandleReposition(Handle *h, Handle *h2)
+{
+ double pos = this->_bsplineHandlePosition(h, h2);
+ return _bsplineHandleReposition(h,pos);
}
// give the location for the handler to the specified position
-Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){
+Geom::Point PathManipulator::_bsplineHandleReposition(Handle *h,double pos){
using Geom::X;
using Geom::Y;
Geom::Point ret = h->position();
Node *n = h->parent();
- Geom::D2< Geom::SBasis > SBasisInsideNodes;
- SPCurve *lineInsideNodes = new SPCurve();
- Node * nextNode = NULL;
- nextNode = n->nodeToward(h);
- if(nextNode && pos != noPower){
- lineInsideNodes->moveto(n->position());
- lineInsideNodes->lineto(nextNode->position());
- SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
- ret = SBasisInsideNodes.valueAt(pos);
- ret = Geom::Point(ret[X] + handleCubicGap,ret[Y] + handleCubicGap);
+ Geom::D2< Geom::SBasis > sbasis_inside_nodes;
+ SPCurve *line_inside_nodes = new SPCurve();
+ Node * next_node = NULL;
+ next_node = n->nodeToward(h);
+ if(next_node && pos != NO_POWER){
+ line_inside_nodes->moveto(n->position());
+ line_inside_nodes->lineto(next_node->position());
+ sbasis_inside_nodes = line_inside_nodes->first_segment()->toSBasis();
+ ret = sbasis_inside_nodes.valueAt(pos);
+ ret = Geom::Point(ret[X] + HANDLE_CUBIC_GAP, ret[Y] + HANDLE_CUBIC_GAP);
}else{
- if(pos == noPower){
+ if(pos == NO_POWER){
ret = n->position();
}
}
@@ -1309,7 +1319,7 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
{
Geom::PathBuilder builder;
//Refresh if is bspline some times -think on path change selection, this value get lost
- isBSpline(true);
+ _recalculateIsBSpline();
for (std::list<SubpathPtr>::iterator spi = _subpaths.begin(); spi != _subpaths.end(); ) {
SubpathPtr subpath = *spi;
if (subpath->empty()) {
@@ -1338,17 +1348,17 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
_spcurve->set_pathvector(pathv);
if (alert_LPE) {
/// \todo note that _path can be an Inkscape::LivePathEffect::Effect* too, kind of confusing, rework member naming?
- if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()){
- Inkscape::LivePathEffect::Effect* thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::POWERSTROKE);
- if(thisEffect){
- LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>(thisEffect->getLPEObj()->get_lpe());
+ if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()) {
+ Inkscape::LivePathEffect::Effect* this_effect = _path->getPathEffectOfType(Inkscape::LivePathEffect::POWERSTROKE);
+ if(this_effect){
+ LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>(this_effect->getLPEObj()->get_lpe());
if (lpe_pwr) {
lpe_pwr->adjustForNewPath(pathv);
}
}
- thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::FILLET_CHAMFER);
- if(thisEffect){
- LivePathEffect::LPEFilletChamfer *lpe_fll = dynamic_cast<LivePathEffect::LPEFilletChamfer*>(thisEffect->getLPEObj()->get_lpe());
+ this_effect = _path->getPathEffectOfType(Inkscape::LivePathEffect::FILLET_CHAMFER);
+ if(this_effect){
+ LivePathEffect::LPEFilletChamfer *lpe_fll = dynamic_cast<LivePathEffect::LPEFilletChamfer*>(this_effect->getLPEObj()->get_lpe());
if (lpe_fll) {
lpe_fll->adjustForNewPath(pathv);
}
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 4d2bf4300..2219af849 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -96,7 +96,7 @@ public:
NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected,
bool search_unselected, bool closest);
- int BSplineGetSteps() const;
+ int _bsplineGetSteps() const;
// this is necessary for Tab-selection in MultiPathManipulator
SubpathList &subpathList() { return _subpaths; }
@@ -107,11 +107,11 @@ private:
void _createControlPointsFromGeometry();
- bool isBSpline(bool recalculate = false);
- bool isBSpline() const;
- double BSplineHandlePosition(Handle *h, Handle *h2 = NULL);
- Geom::Point BSplineHandleReposition(Handle *h, Handle *h2 = NULL);
- Geom::Point BSplineHandleReposition(Handle *h, double pos);
+ void _recalculateIsBSpline();
+ bool _isBSpline() const;
+ double _bsplineHandlePosition(Handle *h, Handle *h2 = NULL);
+ Geom::Point _bsplineHandleReposition(Handle *h, Handle *h2 = NULL);
+ Geom::Point _bsplineHandleReposition(Handle *h, double pos);
void _createGeometryFromControlPoints(bool alert_LPE = false);
unsigned _deleteStretch(NodeList::iterator first, NodeList::iterator last, bool keep_shape);
std::string _createTypeString();
diff --git a/src/ui/tools/box3d-tool.h b/src/ui/tools/box3d-tool.h
index 1dd6bb5f8..33ae6d8e7 100644
--- a/src/ui/tools/box3d-tool.h
+++ b/src/ui/tools/box3d-tool.h
@@ -80,7 +80,7 @@ private:
Proj::Pt3 drag_ptC_proj;
bool ctrl_dragged; /* whether we are ctrl-dragging */
- bool extruded; /* whether shift-dragging already occured (i.e. the box is already extruded) */
+ bool extruded; /* whether shift-dragging already occurred (i.e. the box is already extruded) */
sigc::connection sel_changed_connection;
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index 19094e3f7..0a36877ff 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -49,7 +49,7 @@
* Much of the way connectors work for user-defined points has been
* changed so that it no longer defines special attributes to record
* the points. Instead it uses single node paths to define points
- * who are then seperate objects that can be fixed on the canvas,
+ * who are then separate objects that can be fixed on the canvas,
* grouped into objects and take full advantage of all transform, snap
* and align functionality of all other objects.
*
diff --git a/src/ui/tools/dynamic-base.h b/src/ui/tools/dynamic-base.h
index c948fa286..095af8f88 100644
--- a/src/ui/tools/dynamic-base.h
+++ b/src/ui/tools/dynamic-base.h
@@ -47,7 +47,7 @@ protected:
/** accumulated shape which ultimately goes in svg:path */
SPCurve *accumulated;
- /** canvas items for "comitted" segments */
+ /** canvas items for "committed" segments */
GSList *segments;
/** canvas item for red "leading" segment */
diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp
index bb8782dfa..ffd41d97d 100644
--- a/src/ui/tools/flood-tool.cpp
+++ b/src/ui/tools/flood-tool.cpp
@@ -84,6 +84,28 @@ const std::string& FloodTool::getPrefsPath() {
const std::string FloodTool::prefsPath = "/tools/paintbucket";
+// TODO: Replace by C++11 initialization
+// Must match PaintBucketChannels enum
+Glib::ustring ch_init[8] = {
+ _("Visible Colors"),
+ _("Red"),
+ _("Green"),
+ _("Blue"),
+ _("Hue"),
+ _("Saturation"),
+ _("Lightness"),
+ _("Alpha"),
+};
+const std::vector<Glib::ustring> FloodTool::channel_list( ch_init, ch_init+8 );
+
+Glib::ustring gap_init[4] = {
+ C_("Flood autogap", "None"),
+ C_("Flood autogap", "Small"),
+ C_("Flood autogap", "Medium"),
+ C_("Flood autogap", "Large")
+};
+const std::vector<Glib::ustring> FloodTool::gap_list( gap_init, gap_init+4 );
+
FloodTool::FloodTool()
: ToolBase(cursor_paintbucket_xpm, 11, 30)
, item(NULL)
@@ -174,38 +196,6 @@ inline unsigned char * get_trace_pixel(guchar *trace_px, int x, int y, int width
}
/**
- * Generate the list of trace channel selection entries.
- */
-GList * flood_channels_dropdown_items_list() {
- GList *glist = NULL;
-
- glist = g_list_append (glist, _("Visible Colors"));
- glist = g_list_append (glist, _("Red"));
- glist = g_list_append (glist, _("Green"));
- glist = g_list_append (glist, _("Blue"));
- glist = g_list_append (glist, _("Hue"));
- glist = g_list_append (glist, _("Saturation"));
- glist = g_list_append (glist, _("Lightness"));
- glist = g_list_append (glist, _("Alpha"));
-
- return glist;
-}
-
-/**
- * Generate the list of autogap selection entries.
- */
-GList * flood_autogap_dropdown_items_list() {
- GList *glist = NULL;
-
- glist = g_list_append (glist, (void*) C_("Flood autogap", "None"));
- glist = g_list_append (glist, (void*) C_("Flood autogap", "Small"));
- glist = g_list_append (glist, (void*) C_("Flood autogap", "Medium"));
- glist = g_list_append (glist, (void*) C_("Flood autogap", "Large"));
-
- return glist;
-}
-
-/**
* Compare a pixel in a pixel buffer with another pixel to determine if a point should be included in the fill operation.
* @param check The pixel in the pixel buffer to check.
* @param orig The original selected pixel to use as the fill target color.
diff --git a/src/ui/tools/flood-tool.h b/src/ui/tools/flood-tool.h
index 5104a42e9..100875f22 100644
--- a/src/ui/tools/flood-tool.h
+++ b/src/ui/tools/flood-tool.h
@@ -13,6 +13,7 @@
#include <sigc++/connection.h>
#include "ui/tools/tool-base.h"
+#include <vector>
#define SP_FLOOD_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::FloodTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_FLOOD_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::FloodTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
@@ -39,15 +40,14 @@ public:
virtual const std::string& getPrefsPath();
static void set_channels(gint channels);
+ static const std::vector<Glib::ustring> channel_list;
+ static const std::vector<Glib::ustring> gap_list;
private:
void selection_changed(Inkscape::Selection* selection);
void finishItem();
};
-GList* flood_channels_dropdown_items_list (void);
-GList* flood_autogap_dropdown_items_list (void);
-
enum PaintBucketChannels {
FLOOD_CHANNELS_RGB,
FLOOD_CHANNELS_R,
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 0f14d7534..e8cbfcdbf 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -92,7 +92,7 @@ FreehandBase::FreehandBase(gchar const *const *cursor_shape, gint hot_x, gint ho
, white_item(NULL)
, white_curves(NULL)
, white_anchors(NULL)
- , overwriteCurve(NULL)
+ , overwrite_curve(NULL)
, sa(NULL)
, ea(NULL)
, waiting_LPE_type(Inkscape::LivePathEffect::INVALID_LPE)
@@ -149,7 +149,7 @@ void FreehandBase::setup() {
this->green_closed = FALSE;
// Create start anchor alternative curve
- this->overwriteCurve = new SPCurve();
+ this->overwrite_curve = new SPCurve();
this->attach = TRUE;
spdc_attach_selection(this, this->selection);
@@ -575,12 +575,12 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
}
if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
- dc->overwriteCurve->append_continuous(c, 0.0625);
+ dc->overwrite_curve->append_continuous(c, 0.0625);
c->unref();
- dc->overwriteCurve->closepath_current();
+ dc->overwrite_curve->closepath_current();
if(dc->sa){
dc->white_curves = g_slist_remove(dc->white_curves, dc->sa->curve);
- dc->white_curves = g_slist_append(dc->white_curves, dc->overwriteCurve);
+ dc->white_curves = g_slist_append(dc->white_curves, dc->overwrite_curve);
}
}else{
dc->sa->curve->append_continuous(c, 0.0625);
@@ -597,7 +597,7 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
dc->white_curves = g_slist_remove(dc->white_curves, s);
if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
- s = dc->overwriteCurve;
+ s = dc->overwrite_curve;
}
if (dc->sa->start) {
s = reverse_then_unref(s);
diff --git a/src/ui/tools/freehand-base.h b/src/ui/tools/freehand-base.h
index 6b4265215..a3e7b42f9 100644
--- a/src/ui/tools/freehand-base.h
+++ b/src/ui/tools/freehand-base.h
@@ -78,7 +78,7 @@ public:
//ALternative curve to use on continuing exisiting curve in case of bspline or spirolive
//because usigh anchor curves give memory and random bugs, - and obscure code- in some plataform reported by su_v in mac
- SPCurve *overwriteCurve;
+ SPCurve *overwrite_curve;
// Start anchor
SPDrawAnchor *sa;
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index cae525bfb..bf38b5ca5 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -321,7 +321,7 @@ sp_gradient_context_add_stops_between_selected_stops (GradientTool *rc)
if (d->point_type == POINT_RG_FOCUS) {
/*
* There are 2 draggables at the center (start) of a radial gradient
- * To avoid creating 2 seperate stops, ignore this draggable point type
+ * To avoid creating 2 separate stops, ignore this draggable point type
*/
continue;
}
diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index af341a9aa..0e68af601 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -48,7 +48,7 @@
// Mesh specific
#include "ui/tools/mesh-tool.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "display/sp-ctrlcurve.h"
using Inkscape::DocumentUndo;
@@ -162,9 +162,9 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) {
// if (style && (style->fill.isPaintserver())) {
// SPPaintServer *server = item->style->getFillPaintServer();
- // if ( SP_IS_MESHGRADIENT(server) ) {
+ // if ( SP_IS_MESH(server) ) {
- // SPMeshGradient *mg = SP_MESHGRADIENT(server);
+ // SPMesh *mg = SP_MESH(server);
// guint rows = 0;//mg->array.patches.size();
// for ( guint i = 0; i < rows; ++i ) {
@@ -327,8 +327,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
SPDocument *doc = NULL;
GrDrag *drag = rc->_grdrag;
- std::map<SPMeshGradient*, std::vector<guint> > points;
- std::map<SPMeshGradient*, SPItem*> items;
+ std::map<SPMesh*, std::vector<guint> > points;
+ std::map<SPMesh*, SPItem*> items;
// Get list of selected draggers for each mesh.
// For all selected draggers
@@ -342,7 +342,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
if( d->point_type != POINT_MG_CORNER ) continue;
// Find the gradient
- SPMeshGradient *gradient = SP_MESHGRADIENT( getGradient (d->item, d->fill_or_stroke) );
+ SPMesh *gradient = SP_MESH( getGradient (d->item, d->fill_or_stroke) );
// Collect points together for same gradient
points[gradient].push_back( d->point_i );
@@ -351,8 +351,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
}
// Loop over meshes.
- for( std::map<SPMeshGradient*, std::vector<guint> >::const_iterator iter = points.begin(); iter != points.end(); ++iter) {
- SPMeshGradient *mg = SP_MESHGRADIENT( iter->first );
+ for( std::map<SPMesh*, std::vector<guint> >::const_iterator iter = points.begin(); iter != points.end(); ++iter) {
+ SPMesh *mg = SP_MESH( iter->first );
if( iter->second.size() > 0 ) {
guint noperation = 0;
switch (operation) {
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index 40d54af6e..ef00eaa40 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -75,7 +75,7 @@
* - ControlPointSelection: keeps track of node selection and a set of nodes that can potentially
* be selected. There can be more than one selection. Performs actions that require no
* knowledge about the path, only about the nodes, like dragging and transforms. It is not
- * specific to nodes and can accomodate any control point derived from SelectableControlPoint.
+ * specific to nodes and can accommodate any control point derived from SelectableControlPoint.
* Transforms nodes in response to transform handle events.
* - TransformHandleSet: displays nodeset transform handles and emits transform events. The aim
* is to eventually use a common class for object and control point transforms.
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index d28b7c27a..daffc7032 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -85,7 +85,7 @@ namespace Tools {
static Geom::Point pen_drag_origin_w(0, 0);
static bool pen_within_tolerance = false;
static int pen_last_paraxial_dir = 0; // last used direction in horizontal/vertical mode; 0 = horizontal, 1 = vertical
-const double handleCubicGap = 0.01;
+const double HANDLE_CUBIC_GAP = 0.01;
const std::string& PenTool::getPrefsPath() {
return PenTool::prefsPath;
@@ -165,17 +165,17 @@ void PenTool::setPolylineMode() {
this->polylines_paraxial = (mode == 4);
//we call the function which defines the Spiro modes and the BSpline
//todo: merge to one function only
- this->_pen_context_set_mode(mode);
+ this->_penContextSetMode(mode);
}
/*
*.Set the mode of draw spiro, and bsplines
*/
-void PenTool::_pen_context_set_mode(guint mode) {
+void PenTool::_penContextSetMode(guint mode) {
// define the nodes
this->spiro = (mode == 1);
this->bspline = (mode == 2);
- this->_bspline_spiro_color();
+ this->_bsplineSpiroColor();
}
/**
@@ -429,7 +429,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
// This is allowed, if we just canceled curve
case PenTool::POINT:
if (this->npoints == 0) {
- this->_bspline_spiro_color();
+ this->_bsplineSpiroColor();
Geom::Point p;
if ((bevent.state & GDK_CONTROL_MASK) && (this->polylines_only || this->polylines_paraxial)) {
p = event_dt;
@@ -451,7 +451,7 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
this->sa = anchor;
if(anchor){
- this->_bspline_spiro_start_anchor(bevent.state & GDK_SHIFT_MASK);
+ this->_bsplineSpiroStartAnchor(bevent.state & GDK_SHIFT_MASK);
}
if (anchor && (!this->hasWaitingLPE()|| this->bspline || this->spiro)) {
// Adjust point to anchor if needed; if we have a waiting LPE, we need
@@ -700,10 +700,10 @@ bool PenTool::_handleMotionNotify(GdkEventMotion const &mevent) {
}
// calls the function "bspline_spiro_motion" when the mouse starts or stops moving
if(this->bspline){
- this->_bspline_spiro_motion(mevent.state & GDK_SHIFT_MASK);
+ this->_bsplineSpiroMotion(mevent.state & GDK_SHIFT_MASK);
}else{
if ( Geom::LInfty( event_w - pen_drag_origin_w ) > (tolerance/2) || mevent.time == 0) {
- this->_bspline_spiro_motion(mevent.state & GDK_SHIFT_MASK);
+ this->_bsplineSpiroMotion(mevent.state & GDK_SHIFT_MASK);
pen_drag_origin_w = event_w;
}
}
@@ -742,7 +742,7 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
case PenTool::POINT:
if ( this->npoints == 0 ) {
// Start new thread only with button release
- this->_bspline_spiro_color();
+ this->_bsplineSpiroColor();
if (anchor) {
p = anchor->dp;
}
@@ -750,7 +750,7 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
// continue the existing curve
if (anchor) {
if(this->bspline || this->spiro){
- this->_bspline_spiro_start_anchor(revent.state & GDK_SHIFT_MASK);;
+ this->_bsplineSpiroStartAnchor(revent.state & GDK_SHIFT_MASK);;
}
}
this->_setInitialPoint(p);
@@ -879,11 +879,11 @@ void PenTool::_redrawAll() {
this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
}
// one canvas bpath for all of green_curve
- SPCanvasItem *cshape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve);
- sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
- sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cshape), 0, SP_WIND_RULE_NONZERO);
+ SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(canvas_shape), 0, SP_WIND_RULE_NONZERO);
- this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
+ this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape);
}
if (this->green_anchor)
SP_CTRL(this->green_anchor->ctrl)->moveto(this->green_anchor->dp);
@@ -925,7 +925,7 @@ void PenTool::_redrawAll() {
// simply redraw the spiro. because its a redrawing, we don't call the global function,
// but we call the redrawing at the ending.
- this->_bspline_spiro_build();
+ this->_bsplineSpiroBuild();
}
void PenTool::_lastpointMove(gdouble x, gdouble y) {
@@ -1001,7 +1001,7 @@ void PenTool::_lastpointToCurve() {
}
//if the last node is an union with another curve
if (this->green_curve->is_empty() && this->sa && !this->sa->curve->is_empty()) {
- this->_bspline_spiro_start_anchor(false);
+ this->_bsplineSpiroStartAnchor(false);
}
}
@@ -1048,7 +1048,7 @@ void PenTool::_lastpointToLine() {
}
// if the last node is an union with another curve
if(this->green_curve->is_empty() && this->sa && !this->sa->curve->is_empty()){
- this->_bspline_spiro_start_anchor(true);
+ this->_bsplineSpiroStartAnchor(true);
}
}
@@ -1312,7 +1312,7 @@ void PenTool::_setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_t
}
// this function changes the colors red, green and blue making them transparent or not, depending on if spiro is being used.
-void PenTool::_bspline_spiro_color()
+void PenTool::_bsplineSpiroColor()
{
static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if(this->spiro){
@@ -1346,25 +1346,25 @@ void PenTool::_bspline_spiro_color()
this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
}
// one canvas bpath for all of green_curve
- SPCanvasItem *cshape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve);
- sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
- sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cshape), 0, SP_WIND_RULE_NONZERO);
- this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
+ SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(canvas_shape), 0, SP_WIND_RULE_NONZERO);
+ this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape);
}
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->red_bpath), this->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
}
-void PenTool::_bspline_spiro(bool shift)
+void PenTool::_bsplineSpiro(bool shift)
{
if(!this->spiro && !this->bspline)
return;
- shift?this->_bspline_spiro_off():this->_bspline_spiro_on();
- this->_bspline_spiro_build();
+ shift?this->_bsplineSpiroOff():this->_bsplineSpiroOn();
+ this->_bsplineSpiroBuild();
}
-void PenTool::_bspline_spiro_on()
+void PenTool::_bsplineSpiroOn()
{
if(!this->red_curve->is_empty()){
using Geom::X;
@@ -1373,11 +1373,11 @@ void PenTool::_bspline_spiro_on()
this->p[0] = this->red_curve->first_segment()->initialPoint();
this->p[3] = this->red_curve->first_segment()->finalPoint();
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
+ this->p[2] = Geom::Point(this->p[2][X] + HANDLE_CUBIC_GAP,this->p[2][Y] + HANDLE_CUBIC_GAP);
}
}
-void PenTool::_bspline_spiro_off()
+void PenTool::_bsplineSpiroOff()
{
if(!this->red_curve->is_empty()){
this->npoints = 5;
@@ -1387,7 +1387,7 @@ void PenTool::_bspline_spiro_off()
}
}
-void PenTool::_bspline_spiro_start_anchor(bool shift)
+void PenTool::_bsplineSpiroStartAnchor(bool shift)
{
if(this->sa->curve->is_empty()){
return;
@@ -1423,73 +1423,73 @@ void PenTool::_bspline_spiro_start_anchor(bool shift)
return;
if(shift)
- this->_bspline_spiro_start_anchor_off();
+ this->_bsplineSpiroStartAnchorOff();
else
- this->_bspline_spiro_start_anchor_on();
+ this->_bsplineSpiroStartAnchorOn();
}
-void PenTool::_bspline_spiro_start_anchor_on()
+void PenTool::_bsplineSpiroStartAnchorOn()
{
using Geom::X;
using Geom::Y;
- SPCurve *tmpCurve = new SPCurve();
- tmpCurve = this->sa->curve->copy();
+ SPCurve *tmp_curve = new SPCurve();
+ tmp_curve = this->sa->curve->copy();
if(this->sa->start)
- tmpCurve = tmpCurve->create_reverse();
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
- SPCurve *lastSeg = new SPCurve();
- Geom::Point A = tmpCurve->last_segment()->initialPoint();
- Geom::Point D = tmpCurve->last_segment()->finalPoint();
- Geom::Point C = D + (1./3)*(A - D);
- C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
+ tmp_curve = tmp_curve ->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
+ SPCurve *last_segment = new SPCurve();
+ Geom::Point point_a = tmp_curve ->last_segment()->initialPoint();
+ Geom::Point point_d = tmp_curve ->last_segment()->finalPoint();
+ Geom::Point point_c = point_d + (1./3)*(point_a - point_d);
+ point_c = Geom::Point(point_c[X] + HANDLE_CUBIC_GAP, point_c[Y] + HANDLE_CUBIC_GAP);
if(cubic){
- lastSeg->moveto(A);
- lastSeg->curveto((*cubic)[1],C,D);
+ last_segment->moveto(point_a);
+ last_segment->curveto((*cubic)[1],point_c,point_d);
}else{
- lastSeg->moveto(A);
- lastSeg->curveto(A,C,D);
+ last_segment->moveto(point_a);
+ last_segment->curveto(point_a,point_c,point_d);
}
- if( tmpCurve->get_segment_count() == 1){
- tmpCurve = lastSeg;
+ if( tmp_curve ->get_segment_count() == 1){
+ tmp_curve = last_segment;
}else{
//we eliminate the last segment
- tmpCurve->backspace();
+ tmp_curve ->backspace();
//and we add it again with the recreation
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ tmp_curve ->append_continuous(last_segment, 0.0625);
}
if (this->sa->start) {
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
}
- this->overwriteCurve = tmpCurve;
+ this->overwrite_curve = tmp_curve ;
}
-void PenTool::_bspline_spiro_start_anchor_off()
+void PenTool::_bsplineSpiroStartAnchorOff()
{
- SPCurve *tmpCurve = new SPCurve();
- tmpCurve = this->sa->curve->copy();
+ SPCurve *tmp_curve = new SPCurve();
+ tmp_curve = this->sa->curve->copy();
if(this->sa->start)
- tmpCurve = tmpCurve->create_reverse();
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ tmp_curve = tmp_curve ->create_reverse();
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
if(cubic){
- SPCurve *lastSeg = new SPCurve();
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- if( tmpCurve->get_segment_count() == 1){
- tmpCurve = lastSeg;
+ SPCurve *last_segment = new SPCurve();
+ last_segment->moveto((*cubic)[0]);
+ last_segment->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ if( tmp_curve ->get_segment_count() == 1){
+ tmp_curve = last_segment;
}else{
//we eliminate the last segment
- tmpCurve->backspace();
+ tmp_curve ->backspace();
//and we add it again with the recreation
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ tmp_curve ->append_continuous(last_segment, 0.0625);
}
}
if (this->sa->start) {
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
}
- this->overwriteCurve = tmpCurve;
+ this->overwrite_curve = tmp_curve ;
}
-void PenTool::_bspline_spiro_motion(bool shift){
+void PenTool::_bsplineSpiroMotion(bool shift){
if(!this->spiro && !this->bspline)
return;
@@ -1497,40 +1497,40 @@ void PenTool::_bspline_spiro_motion(bool shift){
using Geom::Y;
if(this->red_curve->is_empty()) return;
this->npoints = 5;
- SPCurve *tmpCurve = new SPCurve();
+ SPCurve *tmp_curve = new SPCurve();
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
+ this->p[2] = Geom::Point(this->p[2][X] + HANDLE_CUBIC_GAP,this->p[2][Y] + HANDLE_CUBIC_GAP);
if(this->green_curve->is_empty() && !this->sa){
this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
- this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
+ this->p[1] = Geom::Point(this->p[1][X] + HANDLE_CUBIC_GAP,this->p[1][Y] + HANDLE_CUBIC_GAP);
if(shift){
this->p[2] = this->p[3];
}
}else if(!this->green_curve->is_empty()){
- tmpCurve = this->green_curve->copy();
+ tmp_curve = this->green_curve->copy();
}else{
- tmpCurve = this->overwriteCurve->copy();
+ tmp_curve = this->overwrite_curve->copy();
if(this->sa->start)
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
}
- if(!tmpCurve->is_empty()){
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ if(!tmp_curve ->is_empty()){
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
if(cubic){
if(this->bspline){
- SPCurve * WPower = new SPCurve();
- Geom::D2< Geom::SBasis > SBasisWPower;
- WPower->moveto(tmpCurve->last_segment()->finalPoint());
- WPower->lineto(tmpCurve->last_segment()->initialPoint());
- float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment());
- WPower->reset();
- WPower->moveto(this->red_curve->last_segment()->initialPoint());
- WPower->lineto(this->red_curve->last_segment()->finalPoint());
- SBasisWPower = WPower->first_segment()->toSBasis();
- WPower->reset();
- this->p[1] = SBasisWPower.valueAt(WP);
+ SPCurve * weight_power = new SPCurve();
+ Geom::D2< Geom::SBasis > SBasisweight_power;
+ weight_power->moveto(tmp_curve ->last_segment()->finalPoint());
+ weight_power->lineto(tmp_curve ->last_segment()->initialPoint());
+ float WP = Geom::nearest_point((*cubic)[2],*weight_power->first_segment());
+ weight_power->reset();
+ weight_power->moveto(this->red_curve->last_segment()->initialPoint());
+ weight_power->lineto(this->red_curve->last_segment()->finalPoint());
+ SBasisweight_power = weight_power->first_segment()->toSBasis();
+ weight_power->reset();
+ this->p[1] = SBasisweight_power.valueAt(WP);
if(!Geom::are_near(this->p[1],this->p[0])){
- this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
+ this->p[1] = Geom::Point(this->p[1][X] + HANDLE_CUBIC_GAP,this->p[1][Y] + HANDLE_CUBIC_GAP);
} else {
this->p[1] = this->p[0];
}
@@ -1548,129 +1548,129 @@ void PenTool::_bspline_spiro_motion(bool shift){
if(this->anchor_statusbar && !this->red_curve->is_empty()){
if(shift){
- this->_bspline_spiro_end_anchor_off();
+ this->_bsplineSpiroEndAnchorOff();
}else{
- this->_bspline_spiro_end_anchor_on();
+ this->_bsplineSpiroEndAnchorOn();
}
}
- this->_bspline_spiro_build();
+ this->_bsplineSpiroBuild();
}
-void PenTool::_bspline_spiro_end_anchor_on()
+void PenTool::_bsplineSpiroEndAnchorOn()
{
using Geom::X;
using Geom::Y;
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
- SPCurve *tmpCurve = new SPCurve();
- SPCurve *lastSeg = new SPCurve();
- Geom::Point C(0,0);
+ this->p[2] = Geom::Point(this->p[2][X] + HANDLE_CUBIC_GAP,this->p[2][Y] + HANDLE_CUBIC_GAP);
+ SPCurve *tmp_curve = new SPCurve();
+ SPCurve *last_segment = new SPCurve();
+ Geom::Point point_c(0,0);
bool reverse = false;
if( this->green_anchor && this->green_anchor->active ){
- tmpCurve = this->green_curve->create_reverse();
+ tmp_curve = this->green_curve->create_reverse();
if(this->green_curve->get_segment_count()==0){
return;
}
reverse = true;
} else if(this->sa){
- tmpCurve = this->overwriteCurve->copy();
+ tmp_curve = this->overwrite_curve->copy();
if(!this->sa->start){
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
reverse = true;
}
}else{
return;
}
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
if(this->bspline){
- C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint());
- C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
+ point_c = tmp_curve ->last_segment()->finalPoint() + (1./3)*(tmp_curve ->last_segment()->initialPoint() - tmp_curve ->last_segment()->finalPoint());
+ point_c = Geom::Point(point_c[X] + HANDLE_CUBIC_GAP, point_c[Y] + HANDLE_CUBIC_GAP);
}else{
- C = this->p[3] + this->p[3] - this->p[2];
+ point_c = this->p[3] + this->p[3] - this->p[2];
}
if(cubic){
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],C,(*cubic)[3]);
+ last_segment->moveto((*cubic)[0]);
+ last_segment->curveto((*cubic)[1],point_c,(*cubic)[3]);
}else{
- lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
- lastSeg->lineto(tmpCurve->last_segment()->finalPoint());
+ last_segment->moveto(tmp_curve ->last_segment()->initialPoint());
+ last_segment->lineto(tmp_curve ->last_segment()->finalPoint());
}
- if( tmpCurve->get_segment_count() == 1){
- tmpCurve = lastSeg;
+ if( tmp_curve ->get_segment_count() == 1){
+ tmp_curve = last_segment;
}else{
//we eliminate the last segment
- tmpCurve->backspace();
+ tmp_curve ->backspace();
//and we add it again with the recreation
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ tmp_curve ->append_continuous(last_segment, 0.0625);
}
if (reverse) {
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
}
if( this->green_anchor && this->green_anchor->active )
{
this->green_curve->reset();
- this->green_curve = tmpCurve;
+ this->green_curve = tmp_curve ;
}else{
- this->overwriteCurve->reset();
- this->overwriteCurve = tmpCurve;
+ this->overwrite_curve->reset();
+ this->overwrite_curve = tmp_curve ;
}
}
-void PenTool::_bspline_spiro_end_anchor_off()
+void PenTool::_bsplineSpiroEndAnchorOff()
{
- SPCurve *tmpCurve = new SPCurve();
- SPCurve *lastSeg = new SPCurve();
+ SPCurve *tmp_curve = new SPCurve();
+ SPCurve *last_segment = new SPCurve();
bool reverse = false;
this->p[2] = this->p[3];
if( this->green_anchor && this->green_anchor->active ){
- tmpCurve = this->green_curve->create_reverse();
+ tmp_curve = this->green_curve->create_reverse();
if(this->green_curve->get_segment_count()==0){
return;
}
reverse = true;
} else if(this->sa){
- tmpCurve = this->overwriteCurve->copy();
+ tmp_curve = this->overwrite_curve->copy();
if(!this->sa->start){
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
reverse = true;
}
}else{
return;
}
- Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
+ Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmp_curve ->last_segment());
if(cubic){
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
+ last_segment->moveto((*cubic)[0]);
+ last_segment->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
}else{
- lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
- lastSeg->lineto(tmpCurve->last_segment()->finalPoint());
+ last_segment->moveto(tmp_curve ->last_segment()->initialPoint());
+ last_segment->lineto(tmp_curve ->last_segment()->finalPoint());
}
- if( tmpCurve->get_segment_count() == 1){
- tmpCurve = lastSeg;
+ if( tmp_curve ->get_segment_count() == 1){
+ tmp_curve = last_segment;
}else{
//we eliminate the last segment
- tmpCurve->backspace();
+ tmp_curve ->backspace();
//and we add it again with the recreation
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ tmp_curve ->append_continuous(last_segment, 0.0625);
}
if (reverse) {
- tmpCurve = tmpCurve->create_reverse();
+ tmp_curve = tmp_curve ->create_reverse();
}
if( this->green_anchor && this->green_anchor->active )
{
this->green_curve->reset();
- this->green_curve = tmpCurve;
+ this->green_curve = tmp_curve ;
}else{
- this->overwriteCurve->reset();
- this->overwriteCurve = tmpCurve;
+ this->overwrite_curve->reset();
+ this->overwrite_curve = tmp_curve ;
}
}
//prepares the curves for its transformation into BSpline curve.
-void PenTool::_bspline_spiro_build()
+void PenTool::_bsplineSpiroBuild()
{
if(!this->spiro && !this->bspline){
return;
@@ -1680,7 +1680,7 @@ void PenTool::_bspline_spiro_build()
SPCurve *curve = new SPCurve();
//If we continuate the existing curve we add it at the start
if(this->sa && !this->sa->curve->is_empty()){
- curve = this->overwriteCurve->copy();
+ curve = this->overwrite_curve->copy();
if (this->sa->start) {
curve = curve->create_reverse();
}
@@ -1715,9 +1715,9 @@ void PenTool::_bspline_spiro_build()
//Effect *spr = static_cast<Effect*> ( new LPEbspline(lpeobj) );
//spr->doEffect(curve);
if(this->bspline){
- this->_bspline_doEffect(curve);
+ this->_bsplineDoEffect(curve);
}else{
- this->_spiro_doEffect(curve);
+ this->_spiroDoEffect(curve);
}
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->blue_bpath), curve);
@@ -1741,66 +1741,73 @@ void PenTool::_bspline_spiro_build()
}
}
-void PenTool::_bspline_doEffect(SPCurve * curve)
+//from LPE BSPLINE:
+void PenTool::_bsplineDoEffect(SPCurve * curve)
{
- // commenting the function doEffect in src/live_effects/lpe-bspline.cpp
- if (curve->get_segment_count() < 1){
+ const double NO_POWER = 0.0;
+ const double DEFAULT_START_POWER = 0.3334;
+ const double DEFAULT_END_POWER = 0.6667;
+ if (curve->get_segment_count() < 1) {
return;
}
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
+
curve->reset();
- //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el
- //penúltimo
for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
path_it != original_pathv.end(); ++path_it) {
- //Si está vacío...
- if (path_it->empty())
+ if (path_it->empty()) {
continue;
- //Itreadores
-
+ }
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();
- SPCurve *nCurve = new SPCurve();
+ Geom::Path::const_iterator curve_endit = path_it->end_default();
+ SPCurve *curve_n = new SPCurve();
Geom::Point previousNode(0, 0);
Geom::Point node(0, 0);
- Geom::Point pointAt1(0, 0);
- Geom::Point pointAt2(0, 0);
- Geom::Point nextPointAt1(0, 0);
- Geom::D2<Geom::SBasis> SBasisIn;
- Geom::D2<Geom::SBasis> SBasisOut;
- Geom::D2<Geom::SBasis> SBasisHelper;
+ Geom::Point point_at1(0, 0);
+ Geom::Point point_at2(0, 0);
+ Geom::Point next_point_at1(0, 0);
+ Geom::D2<Geom::SBasis> sbasis_in;
+ Geom::D2<Geom::SBasis> sbasis_out;
+ Geom::D2<Geom::SBasis> sbasis_helper;
Geom::CubicBezier const *cubic = NULL;
if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
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();
}
}
- nCurve->moveto(curve_it1->initialPoint());
+ curve_n->moveto(curve_it1->initialPoint());
while (curve_it1 != curve_endit) {
SPCurve *in = new SPCurve();
in->moveto(curve_it1->initialPoint());
in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
- SBasisIn = in->first_segment()->toSBasis();
+ sbasis_in = in->first_segment()->toSBasis();
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- pointAt1 = SBasisIn.valueAt(0.3334);
+ point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ point_at1 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
}
if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
- pointAt2 = SBasisIn.valueAt(0.6667);
+ point_at2 = sbasis_in.valueAt(DEFAULT_END_POWER);
} else {
- pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ point_at2 = sbasis_in.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
}
} else {
- pointAt1 = in->first_segment()->initialPoint();
- pointAt2 = in->first_segment()->finalPoint();
+ point_at1 = in->first_segment()->initialPoint();
+ point_at2 = in->first_segment()->finalPoint();
}
in->reset();
delete in;
@@ -1810,31 +1817,30 @@ void PenTool::_bspline_doEffect(SPCurve * curve)
out->lineto(curve_it2->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
if (cubic) {
- SBasisOut = out->first_segment()->toSBasis();
+ sbasis_out = out->first_segment()->toSBasis();
if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- nextPointAt1 = SBasisIn.valueAt(0.3334);
+ next_point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
} else {
- nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ next_point_at1 = sbasis_out.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
}
} else {
- nextPointAt1 = out->first_segment()->initialPoint();
+ next_point_at1 = out->first_segment()->initialPoint();
}
out->reset();
delete out;
}
- Geom::Point startNode = path_it->begin()->initialPoint();
if (path_it->closed() && curve_it2 == curve_endit) {
SPCurve *start = new SPCurve();
start->moveto(path_it->begin()->initialPoint());
start->lineto(path_it->begin()->finalPoint());
- Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
- SPCurve *lineHelper = new SPCurve();
+ Geom::D2<Geom::SBasis> sbasis_start = start->first_segment()->toSBasis();
+ SPCurve *line_helper = new SPCurve();
cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
if (cubic) {
- lineHelper->moveto(SBasisStart.valueAt(
+ line_helper->moveto(sbasis_start.valueAt(
Geom::nearest_point((*cubic)[1], *start->first_segment())));
} else {
- lineHelper->moveto(start->first_segment()->initialPoint());
+ line_helper->moveto(start->first_segment()->initialPoint());
}
start->reset();
delete start;
@@ -1842,55 +1848,56 @@ void PenTool::_bspline_doEffect(SPCurve * curve)
SPCurve *end = new SPCurve();
end->moveto(curve_it1->initialPoint());
end->lineto(curve_it1->finalPoint());
- Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ Geom::D2<Geom::SBasis> sbasis_end = end->first_segment()->toSBasis();
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
- lineHelper->lineto(SBasisEnd.valueAt(
+ line_helper->lineto(sbasis_end.valueAt(
Geom::nearest_point((*cubic)[2], *end->first_segment())));
} else {
- lineHelper->lineto(end->first_segment()->finalPoint());
+ line_helper->lineto(end->first_segment()->finalPoint());
}
end->reset();
delete end;
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- startNode = SBasisHelper.valueAt(0.5);
- nCurve->curveto(pointAt1, pointAt2, startNode);
- nCurve->move_endpoints(startNode, startNode);
+ sbasis_helper = line_helper->first_segment()->toSBasis();
+ line_helper->reset();
+ delete line_helper;
+ node = sbasis_helper.valueAt(0.5);
+ curve_n->curveto(point_at1, point_at2, node);
+ curve_n->move_endpoints(node, node);
} else if ( curve_it2 == curve_endit) {
- nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
- nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
+ curve_n->curveto(point_at1, point_at2, curve_it1->finalPoint());
+ curve_n->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
} else {
- SPCurve *lineHelper = new SPCurve();
- lineHelper->moveto(pointAt2);
- lineHelper->lineto(nextPointAt1);
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
+ SPCurve *line_helper = new SPCurve();
+ line_helper->moveto(point_at2);
+ line_helper->lineto(next_point_at1);
+ sbasis_helper = line_helper->first_segment()->toSBasis();
+ line_helper->reset();
+ delete line_helper;
previousNode = node;
- node = SBasisHelper.valueAt(0.5);
+ node = sbasis_helper.valueAt(0.5);
Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
node = curve_it1->finalPoint();
}
- nCurve->curveto(pointAt1, pointAt2, node);
+ curve_n->curveto(point_at1, point_at2, node);
}
++curve_it1;
++curve_it2;
}
+ //y cerramos la curva
if (path_it->closed()) {
- nCurve->closepath_current();
+ curve_n->closepath_current();
}
- curve->append(nCurve, false);
- nCurve->reset();
- delete nCurve;
+ curve->append(curve_n, false);
+ curve_n->reset();
+ delete curve_n;
}
}
//Spiro function cloned from lpe-spiro.cpp
// commenting the function "doEffect" from src/live_effects/lpe-spiro.cpp
-void PenTool::_spiro_doEffect(SPCurve * curve)
+void PenTool::_spiroDoEffect(SPCurve * curve)
{
using Geom::X;
using Geom::Y;
@@ -2087,16 +2094,16 @@ void PenTool::_finishSegment(Geom::Point const p, guint const state) {
if (!this->red_curve->is_empty()) {
- this->_bspline_spiro(state & GDK_SHIFT_MASK);
+ this->_bsplineSpiro(state & GDK_SHIFT_MASK);
this->green_curve->append_continuous(this->red_curve, 0.0625);
SPCurve *curve = this->red_curve->copy();
/// \todo fixme:
- SPCanvasItem *cshape = sp_canvas_bpath_new(this->desktop->getSketch(), curve);
+ SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), curve);
curve->unref();
- sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+ sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
- this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape);
+ this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape);
this->p[0] = this->p[3];
this->p[1] = this->p[4];
@@ -2143,7 +2150,7 @@ bool PenTool::_undoLastPoint() {
this->p[1] = this->p[0];
}
- // asign the value in a third of the distance of the last segment.
+ // assign the value in a third of the distance of the last segment.
if (this->bspline){
this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
}
@@ -2165,7 +2172,7 @@ bool PenTool::_undoLastPoint() {
this->green_curve->backspace();
}
- // assign the value of this->p[1] to the oposite of the green line last segment
+ // assign the value of this->p[1] to the opposite of the green line last segment
if (this->spiro){
Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(this->green_curve->last_segment());
if ( cubic ) {
@@ -2185,7 +2192,7 @@ bool PenTool::_undoLastPoint() {
pen_last_paraxial_dir = !pen_last_paraxial_dir;
//redraw
- this->_bspline_spiro_build();
+ this->_bsplineSpiroBuild();
ret = true;
}
@@ -2210,7 +2217,7 @@ void PenTool::_finish(gboolean const closed) {
// cancelate line without a created segment
this->red_curve->reset();
spdc_concat_colors_and_flush(this, closed);
- this->overwriteCurve = NULL;
+ this->overwrite_curve = NULL;
this->sa = NULL;
this->ea = NULL;
diff --git a/src/ui/tools/pen-tool.h b/src/ui/tools/pen-tool.h
index 2208005c5..0ae16caf0 100644
--- a/src/ui/tools/pen-tool.h
+++ b/src/ui/tools/pen-tool.h
@@ -89,33 +89,33 @@ private:
bool _handle2ButtonPress(GdkEventButton const &bevent);
bool _handleKeyPress(GdkEvent *event);
//adds spiro & bspline modes
- void _pen_context_set_mode(guint mode);
+ void _penContextSetMode(guint mode);
//this function changes the colors red, green and blue making them transparent or not depending on if the function uses spiro
- void _bspline_spiro_color();
+ void _bsplineSpiroColor();
//creates a node in bspline or spiro modes
- void _bspline_spiro(bool shift);
+ void _bsplineSpiro(bool shift);
//creates a node in bspline or spiro modes
- void _bspline_spiro_on();
+ void _bsplineSpiroOn();
//creates a CUSP node
- void _bspline_spiro_off();
+ void _bsplineSpiroOff();
//continues the existing curve in bspline or spiro mode
- void _bspline_spiro_start_anchor(bool shift);
+ void _bsplineSpiroStartAnchor(bool shift);
//continues the existing curve with the union node in bspline or spiro modes
- void _bspline_spiro_start_anchor_on();
+ void _bsplineSpiroStartAnchorOn();
//continues an existing curve with the union node in CUSP mode
- void _bspline_spiro_start_anchor_off();
+ void _bsplineSpiroStartAnchorOff();
//modifies the "red_curve" when it detects movement
- void _bspline_spiro_motion(bool shift);
+ void _bsplineSpiroMotion(bool shift);
//closes the curve with the last node in bspline or spiro mode
- void _bspline_spiro_end_anchor_on();
+ void _bsplineSpiroEndAnchorOn();
//closes the curve with the last node in CUSP mode
- void _bspline_spiro_end_anchor_off();
+ void _bsplineSpiroEndAnchorOff();
//CHECK: join all the curves "in game" and we call doEffect function
- void _bspline_spiro_build();
+ void _bsplineSpiroBuild();
//function bspline cloned from lpe-bspline.cpp
- void _bspline_doEffect(SPCurve * curve);
+ void _bsplineDoEffect(SPCurve * curve);
//function spiro cloned from lpe-spiro.cpp
- void _spiro_doEffect(SPCurve * curve);
+ void _spiroDoEffect(SPCurve * curve);
void _setInitialPoint(Geom::Point const p);
void _setSubsequentPoint(Geom::Point const p, bool statusbar, guint status = 0);
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index db24c7432..008804162 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -191,7 +191,7 @@ bool PencilTool::_handleButtonPress(GdkEventButton const &bevent) {
}
if (anchor) {
p = anchor->dp;
- this->overwriteCurve = anchor->curve;
+ this->overwrite_curve = anchor->curve;
desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Continuing selected path"));
} else {
m.setup(desktop);
@@ -663,11 +663,11 @@ void PencilTool::_interpolate() {
for (int c = 0; c < n_segs; c++) {
// if we are in BSpline we modify the trace to create adhoc nodes
if(mode == 2){
- Geom::Point BP = b[4*c+0] + (1./3)*(b[4*c+3] - b[4*c+0]);
- BP = Geom::Point(BP[X] + 0.0001,BP[Y] + 0.0001);
- Geom::Point CP = b[4*c+3] + (1./3)*(b[4*c+0] - b[4*c+3]);
- CP = Geom::Point(CP[X] + 0.0001,CP[Y] + 0.0001);
- this->green_curve->curveto(BP,CP,b[4*c+3]);
+ Geom::Point point_at1 = b[4*c+0] + (1./3)*(b[4*c+3] - b[4*c+0]);
+ point_at1 = Geom::Point(point_at1[X] + 0.0001,point_at1[Y] + 0.0001);
+ Geom::Point point_at2 = b[4*c+3] + (1./3)*(b[4*c+0] - b[4*c+3]);
+ point_at2 = Geom::Point(point_at2[X] + 0.0001,point_at2[Y] + 0.0001);
+ this->green_curve->curveto(point_at1,point_at2,b[4*c+3]);
}else{
this->green_curve->curveto(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
}
@@ -810,11 +810,11 @@ void PencilTool::_fitAndSplit() {
// if we are in BSpline we modify the trace to create adhoc nodes
guint mode = prefs->getInt("/tools/freehand/pencil/freehand-mode", 0);
if(mode == 2){
- Geom::Point B = b[0] + (1./3)*(b[3] - b[0]);
- B = Geom::Point(B[X] + 0.0001,B[Y] + 0.0001);
- Geom::Point C = b[3] + (1./3)*(b[0] - b[3]);
- C = Geom::Point(C[X] + 0.0001,C[Y] + 0.0001);
- this->red_curve->curveto(B,C,b[3]);
+ Geom::Point point_at1 = b[0] + (1./3)*(b[3] - b[0]);
+ point_at1 = Geom::Point(point_at1[X] + 0.0001,point_at1[Y] + 0.0001);
+ Geom::Point point_at2 = b[3] + (1./3)*(b[0] - b[3]);
+ point_at2 = Geom::Point(point_at2[X] + 0.0001,point_at2[Y] + 0.0001);
+ this->red_curve->curveto(point_at1,point_at2,b[3]);
}else{
this->red_curve->curveto(b[1], b[2], b[3]);
}
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 39321ff21..26d74733a 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -406,7 +406,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
parent->appendChild(copy);
SPObject *new_obj = doc->getObjectByRepr(copy);
- item_copied = dynamic_cast<SPItem *>(new_obj); // Convertion object->item
+ item_copied = dynamic_cast<SPItem *>(new_obj); // Conversion object->item
Geom::Point center=item->getCenter();
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale,_scale));
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale,scale));
@@ -437,39 +437,41 @@ static bool sp_spray_recursive(SPDesktop *desktop,
}
i++;
}
- SPDocument *doc = parent_item->document;
- Inkscape::XML::Document* xml_doc = doc->getReprDoc();
- Inkscape::XML::Node *old_repr = parent_item->getRepr();
- Inkscape::XML::Node *parent = old_repr->parent();
-
- Geom::OptRect a = parent_item->documentVisualBounds();
- if (a) {
- if (_fid <= population) { // Rules the population of objects sprayed
- // Duplicates the parent item
- Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
- parent->appendChild(copy);
- SPObject *new_obj = doc->getObjectByRepr(copy);
- item_copied = dynamic_cast<SPItem *>(new_obj);
-
- // Move around the cursor
- Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
-
- Geom::Point center = parent_item->getCenter();
- sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
- sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale));
- sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle));
- sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
-
- // Union and duplication
- selection->clear();
- selection->add(item_copied);
- if (unionResult) { // No need to add the very first item (initialized with NULL).
- selection->add(unionResult);
+ if (parent_item) {
+ SPDocument *doc = parent_item->document;
+ Inkscape::XML::Document* xml_doc = doc->getReprDoc();
+ Inkscape::XML::Node *old_repr = parent_item->getRepr();
+ Inkscape::XML::Node *parent = old_repr->parent();
+
+ Geom::OptRect a = parent_item->documentVisualBounds();
+ if (a) {
+ if (_fid <= population) { // Rules the population of objects sprayed
+ // Duplicates the parent item
+ Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy);
+ SPObject *new_obj = doc->getObjectByRepr(copy);
+ item_copied = dynamic_cast<SPItem *>(new_obj);
+
+ // Move around the cursor
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
+
+ Geom::Point center = parent_item->getCenter();
+ sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
+ sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale));
+ sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle));
+ sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+
+ // Union and duplication
+ selection->clear();
+ selection->add(item_copied);
+ if (unionResult) { // No need to add the very first item (initialized with NULL).
+ selection->add(unionResult);
+ }
+ sp_selected_path_union_skip_undo(selection, selection->desktop());
+ selection->add(parent_item);
+ Inkscape::GC::release(copy);
+ did = true;
}
- sp_selected_path_union_skip_undo(selection, selection->desktop());
- selection->add(parent_item);
- Inkscape::GC::release(copy);
- did = true;
}
}
#endif
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
index 8c3b44bf5..0a5697661 100644
--- a/src/ui/widget/page-sizer.cpp
+++ b/src/ui/widget/page-sizer.cpp
@@ -26,6 +26,7 @@
#include <cmath>
#include <string>
#include <string.h>
+#include <sstream>
#include <vector>
#include <glibmm/i18n.h>
@@ -240,6 +241,14 @@ PageSizer::PageSizer(Registry & _wr)
_marginRight( _("Ri_ght:"), _("Right margin"), "fit-margin-right", _wr),
_marginBottom( _("Botto_m:"), _("Bottom margin"), "fit-margin-bottom", _wr),
_lockMarginUpdate(false),
+ _scaleX(_("Scale _x:"), _("Scale X"), "scale-x", _wr),
+ _scaleY(_("Scale _y:"), _("Scale Y"), "scale-y", _wr),
+ _lockScaleUpdate(false),
+ _viewboxX(_("X:"), _("X"), "viewbox-x", _wr),
+ _viewboxY(_("Y:"), _("Y"), "viewbox-y", _wr),
+ _viewboxW(_("Width:"), _("Width"), "viewbox-width", _wr),
+ _viewboxH(_("Height:"), _("Height"), "viewbox-height", _wr),
+ _lockViewboxUpdate(false),
_widgetRegistry(&_wr)
{
// set precision of scalar entry boxes
@@ -250,6 +259,22 @@ PageSizer::PageSizer(Registry & _wr)
_marginLeft.setDigits(5);
_marginRight.setDigits(5);
_marginBottom.setDigits(5);
+ _scaleX.setDigits(5);
+ _scaleY.setDigits(5);
+ _viewboxX.setDigits(2);
+ _viewboxY.setDigits(2);
+ _viewboxW.setDigits(2);
+ _viewboxH.setDigits(2);
+
+ _scaleX.setRange( 0.00001, 100000 );
+ _scaleY.setRange( 0.00001, 100000 );
+ _viewboxX.setRange( -100000, 100000 );
+ _viewboxY.setRange( -100000, 100000 );
+ _viewboxW.setRange( 0, 200000 );
+ _viewboxH.setRange( 0, 200000 );
+
+ _scaleY.set_sensitive (false); // We only want to display Y scale.
+
_wr.setUpdating (false);
//# Set up the Paper Size combo box
@@ -318,6 +343,7 @@ PageSizer::PageSizer(Registry & _wr)
}
_wr.setUpdating (false);
+
//## Set up custom size frame
_customFrame.set_label(_("Custom size"));
pack_start (_customFrame, false, false, 0);
@@ -419,6 +445,75 @@ PageSizer::PageSizer(Registry & _wr)
_fitPageButton.set_label(_("_Resize page to drawing or selection"));
_fitPageButton.set_tooltip_text(_("Resize the page to fit the current selection, or the entire drawing if there is no selection"));
+ _scaleFrame.set_label(_("Scale"));
+ pack_start (_scaleFrame, false, false, 0);
+ _scaleFrame.add(_scaleTable);
+
+ _scaleTable.set_border_width(4);
+
+#if WITH_GTKMM_3_0
+ _scaleTable.set_row_spacing(4);
+ _scaleTable.set_column_spacing(4);
+
+ _scaleTable.attach(_scaleX, 0, 0, 1, 1);
+ _scaleTable.attach(_scaleY, 1, 0, 1, 1);
+
+ _scaleTable.attach(_scaleLabel, 2, 0, 1, 1);
+ _scaleTable.attach(_scaleWarning, 0, 1, 2, 1);
+ _viewboxExpander.set_hexpand();
+ _viewboxExpander.set_vexpand();
+ _scaleTable.attach(_viewboxExpander, 0, 2, 2, 1);
+#else
+ _scaleTable.resize(3, 2);
+ _scaleTable.set_row_spacings(4);
+ _scaleTable.set_col_spacings(4);
+ _scaleTable.attach(_scaleX, 0,1, 0,1);
+ _scaleTable.attach(_scaleY, 1,2, 0,1);
+ _scaleTable.attach(_scaleLabel, 2,3, 0,1);
+ _scaleTable.attach(_scaleWarning, 0,3, 1,2, Gtk::FILL);
+ _scaleTable.attach(_viewboxExpander, 0,3, 2,3);
+#endif
+
+ _scaleWarning.set_label(_("While SVG allows non-uniform scaling it is recommended to use only uniform scaling in Inkscape. To set a non-uniform scaling, set the 'viewBox' directly."));
+ _scaleWarning.set_line_wrap( true );
+
+ _viewboxExpander.set_use_underline();
+ _viewboxExpander.set_label(_("_Viewbox..."));
+ _viewboxExpander.add(_viewboxTable);
+
+#if WITH_GTKMM_3_0
+ _viewboxTable.set_row_spacing(2);
+ _viewboxTable.set_column_spacing(2);
+
+ _viewboxX.set_hexpand();
+ _viewboxX.set_vexpand();
+ _viewboxTable.attach(_viewboxX, 0, 0, 1, 1);
+
+ _viewboxY.set_hexpand();
+ _viewboxY.set_vexpand();
+ _viewboxTable.attach(_viewboxY, 1, 0, 1, 1);
+
+ _viewboxW.set_hexpand();
+ _viewboxW.set_vexpand();
+ _viewboxTable.attach(_viewboxW, 0, 1, 1, 1);
+
+ _viewboxH.set_hexpand();
+ _viewboxH.set_vexpand();
+ _viewboxTable.attach(_viewboxH, 1, 1, 1, 1);
+
+#else
+ _viewboxTable.set_border_width(4);
+ _viewboxTable.set_row_spacings(2);
+ _viewboxTable.set_col_spacings(2);
+ _viewboxTable.attach(_viewboxX, 0,1, 0,1);
+ _viewboxTable.attach(_viewboxY, 1,2, 0,1);
+ _viewboxTable.attach(_viewboxW, 0,1, 1,2);
+ _viewboxTable.attach(_viewboxH, 1,2, 1,2);
+#endif
+
+ _wr.setUpdating (true);
+ updateScaleUI();
+ _wr.setUpdating (false);
}
@@ -444,7 +539,11 @@ PageSizer::init ()
_changedh_connection = _dimensionHeight.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed));
_changedu_connection = _dimensionUnits.getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &PageSizer::on_units_changed));
_fitPageButton.signal_clicked().connect(sigc::mem_fun(*this, &PageSizer::fire_fit_canvas_to_selection_or_drawing));
-
+ _changeds_connection = _scaleX.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_scale_changed));
+ _changedvx_connection = _viewboxX.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed));
+ _changedvy_connection = _viewboxY.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed));
+ _changedvw_connection = _viewboxW.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed));
+ _changedvh_connection = _viewboxH.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_viewbox_changed));
show_all_children();
}
@@ -512,6 +611,7 @@ PageSizer::setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool
_dimensionHeight.setUnit(h.unit->abbr);
_dimensionHeight.setValue (h.quantity);
+
_paper_size_list_connection.unblock();
_landscape_connection.unblock();
_portrait_connection.unblock();
@@ -701,6 +801,88 @@ PageSizer::on_landscape()
}
}
+
+/**
+ * Update scale widgets
+ */
+void
+PageSizer::updateScaleUI()
+{
+
+ static bool _called = false;
+ if (_called) {
+ return;
+ }
+
+ _called = true;
+
+ _changeds_connection.block();
+ _changedvx_connection.block();
+ _changedvy_connection.block();
+ _changedvw_connection.block();
+ _changedvh_connection.block();
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (dt) {
+ SPDocument *doc = dt->getDocument();
+
+ // Update scale
+ Geom::Scale scale = doc->getDocumentScale();
+ SPNamedView *nv = dt->getNamedView();
+
+ std::stringstream ss;
+ ss << _("User units per ") << nv->display_units->abbr << "." ;
+ _scaleLabel.set_text( ss.str() );
+
+ if( !_lockScaleUpdate ) {
+
+ double scaleX_inv =
+ Inkscape::Util::Quantity::convert( scale[Geom::X], "px", nv->display_units );
+ if( scaleX_inv > 0 ) {
+ _scaleX.setValue(1.0/scaleX_inv);
+ } else {
+ // Should never happen
+ std::cerr << "PageSizer::updateScaleUI(): Invalid scale value: " << scaleX_inv << std::endl;
+ _scaleX.setValue(1.0);
+ }
+ }
+
+ { // Don't need to lock as scaleY widget not linked to callback.
+ double scaleY_inv =
+ Inkscape::Util::Quantity::convert( scale[Geom::Y], "px", nv->display_units );
+ if( scaleY_inv > 0 ) {
+ _scaleY.setValue(1.0/scaleY_inv);
+ } else {
+ // Should never happen
+ std::cerr << "PageSizer::updateScaleUI(): Invalid scale value: " << scaleY_inv << std::endl;
+ _scaleY.setValue(1.0);
+ }
+ }
+
+ if( !_lockViewboxUpdate ) {
+ Geom::Rect viewBox = doc->getViewBox();
+ _viewboxX.setValue( viewBox.min()[Geom::X] );
+ _viewboxY.setValue( viewBox.min()[Geom::Y] );
+ _viewboxW.setValue( viewBox.width() );
+ _viewboxH.setValue( viewBox.height() );
+ }
+
+ } else {
+ // Should never happen
+ std::cerr << "PageSizer::updateScaleUI(): No active desktop." << std::endl;
+ _scaleLabel.set_text( "Unknown scale" );
+ }
+
+ _changeds_connection.unblock();
+ _changedvx_connection.unblock();
+ _changedvy_connection.unblock();
+ _changedvw_connection.unblock();
+ _changedvh_connection.unblock();
+
+ _called = false;
+}
+
+
/**
* Callback for the dimension widgets
*/
@@ -712,6 +894,7 @@ PageSizer::on_value_changed()
setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()),
Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit()));
}
+
void
PageSizer::on_units_changed()
{
@@ -722,6 +905,63 @@ PageSizer::on_units_changed()
true, false);
}
+/**
+ * Callback for scale widgets
+ */
+void
+PageSizer::on_scale_changed()
+{
+ if (_widgetRegistry->isUpdating()) return;
+
+ double value = _scaleX.getValue();
+ if( value > 0 ) {
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (dt) {
+ SPDocument *doc = dt->getDocument();
+ SPNamedView *nv = dt->getNamedView();
+
+ double scaleX_inv = Inkscape::Util::Quantity(1.0/value, nv->display_units ).value("px");
+
+ _lockScaleUpdate = true;
+ doc->setDocumentScale( 1.0/scaleX_inv );
+ updateScaleUI();
+ _lockScaleUpdate = false;
+ DocumentUndo::done(doc, SP_VERB_NONE, _("Set page scale"));
+ }
+ }
+}
+
+/**
+ * Callback for viewbox widgets
+ */
+void
+PageSizer::on_viewbox_changed()
+{
+ if (_widgetRegistry->isUpdating()) return;
+
+ double viewboxX = _viewboxX.getValue();
+ double viewboxY = _viewboxY.getValue();
+ double viewboxW = _viewboxW.getValue();
+ double viewboxH = _viewboxH.getValue();
+
+ if( viewboxW > 0 && viewboxH > 0) {
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (dt) {
+ SPDocument *doc = dt->getDocument();
+ _lockViewboxUpdate = true;
+ doc->setViewBox( Geom::Rect::from_xywh( viewboxX, viewboxY, viewboxW, viewboxH ) );
+ updateScaleUI();
+ _lockViewboxUpdate = false;
+ DocumentUndo::done(doc, SP_VERB_NONE, _("Set 'viewBox'"));
+ }
+ } else {
+ std::cerr
+ << "PageSizer::on_viewbox_changed(): width and height must both be greater than zero."
+ << std::endl;
+ }
+}
+
} // namespace Widget
} // namespace UI
} // namespace Inkscape
diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h
index bed117e5a..0eea28e61 100644
--- a/src/ui/widget/page-sizer.h
+++ b/src/ui/widget/page-sizer.h
@@ -169,6 +169,11 @@ public:
*/
void updateFitMarginsUI(Inkscape::XML::Node *nv_repr);
+ /**
+ * Updates the scale widgets. (Just changes the values of the ui widgets.)
+ */
+ void updateScaleUI();
+
protected:
/**
@@ -250,12 +255,47 @@ protected:
Gtk::Button _fitPageButton;
bool _lockMarginUpdate;
+ // Document scale
+ Gtk::Frame _scaleFrame;
+#if WITH_GTKMM_3_0
+ Gtk::Grid _scaleTable;
+#else
+ Gtk::Table _scaleTable;
+#endif
+
+ Gtk::Label _scaleLabel;
+ Gtk::Label _scaleWarning;
+ RegisteredScalar _scaleX;
+ RegisteredScalar _scaleY;
+ bool _lockScaleUpdate;
+
+ // Viewbox
+ Gtk::Expander _viewboxExpander;
+#if WITH_GTKMM_3_0
+ Gtk::Grid _viewboxTable;
+#else
+ Gtk::Table _viewboxTable;
+#endif
+
+ RegisteredScalar _viewboxX;
+ RegisteredScalar _viewboxY;
+ RegisteredScalar _viewboxW;
+ RegisteredScalar _viewboxH;
+ bool _lockViewboxUpdate;
+
//callback
void on_value_changed();
void on_units_changed();
+ void on_scale_changed();
+ void on_viewbox_changed();
sigc::connection _changedw_connection;
sigc::connection _changedh_connection;
sigc::connection _changedu_connection;
+ sigc::connection _changeds_connection;
+ sigc::connection _changedvx_connection;
+ sigc::connection _changedvy_connection;
+ sigc::connection _changedvw_connection;
+ sigc::connection _changedvh_connection;
Registry *_widgetRegistry;
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index 1fc67dcef..9e283fc64 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -25,8 +25,8 @@
#include "desktop-style.h"
#include "sp-namedview.h"
#include "sp-linear-gradient.h"
-#include "sp-mesh-gradient.h"
#include "sp-radial-gradient.h"
+#include "sp-mesh.h"
#include "sp-pattern.h"
#include "ui/dialog/dialog-manager.h"
#include "ui/dialog/fill-and-stroke.h"
@@ -1045,7 +1045,7 @@ SelectedStyle::update()
place->set_tooltip_text(__rgradient[i]);
_mode[i] = SS_RGRADIENT;
#ifdef WITH_MESH
- } else if (SP_IS_MESHGRADIENT(server)) {
+ } else if (SP_IS_MESH(server)) {
SPGradient *vector = SP_GRADIENT(server)->getVector();
sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(_gradient_preview_m[i]), vector);
place->add(_gradient_box_m[i]);
diff --git a/src/uri-references.cpp b/src/uri-references.cpp
index b23bed74a..2518c173e 100644
--- a/src/uri-references.cpp
+++ b/src/uri-references.cpp
@@ -65,7 +65,7 @@ void URIReference::attach(const URI &uri) throw(BadURIException)
skip = true;
}
- // The path contains references to seperate document files to load.
+ // The path contains references to separate document files to load.
if(document && uri.getPath() && !skip ) {
std::string base = document->getBase() ? document->getBase() : "";
std::string path = uri.getFullPath(base);
diff --git a/src/widgets/box3d-toolbar.cpp b/src/widgets/box3d-toolbar.cpp
index 26e914070..31b897ced 100644
--- a/src/widgets/box3d-toolbar.cpp
+++ b/src/widgets/box3d-toolbar.cpp
@@ -193,15 +193,15 @@ static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObj
Inkscape::GC::anchor(persp_repr);
sp_repr_add_listener(persp_repr, &box3d_persp_tb_repr_events, tbl);
sp_repr_synthesize_events(persp_repr, &box3d_persp_tb_repr_events, tbl);
- }
- SP_ACTIVE_DOCUMENT->setCurrentPersp3D(persp3d_get_from_repr(persp_repr));
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setString("/tools/shapes/3dbox/persp", persp_repr->attribute("id"));
+ SP_ACTIVE_DOCUMENT->setCurrentPersp3D(persp3d_get_from_repr(persp_repr));
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setString("/tools/shapes/3dbox/persp", persp_repr->attribute("id"));
- g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
- box3d_resync_toolbar(persp_repr, tbl);
- g_object_set_data(tbl, "freeze", GINT_TO_POINTER(FALSE));
+ g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
+ box3d_resync_toolbar(persp_repr, tbl);
+ g_object_set_data(tbl, "freeze", GINT_TO_POINTER(FALSE));
+ }
}
}
diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp
index 49fc7b67c..1af55d9cd 100644
--- a/src/widgets/mesh-toolbar.cpp
+++ b/src/widgets/mesh-toolbar.cpp
@@ -44,7 +44,7 @@
#include "ui/tools/gradient-tool.h"
#include "ui/tools/mesh-tool.h"
#include "gradient-drag.h"
-#include "sp-mesh-gradient.h"
+#include "sp-mesh.h"
#include "gradient-chemistry.h"
#include "gradient-selector.h"
#include "selection.h"
@@ -77,15 +77,15 @@ static bool blocked = false;
* Get the current selection and dragger status from the desktop
*/
void ms_read_selection( Inkscape::Selection *selection,
- SPMeshGradient *&ms_selected,
+ SPMesh *&ms_selected,
bool &ms_selected_multi,
- SPMeshSmooth &ms_smooth,
- bool &ms_smooth_multi )
+ SPMeshType &ms_type,
+ bool &ms_type_multi )
{
// Read desktop selection
bool first = true;
- ms_smooth = SP_MESH_SMOOTH_NONE;
+ ms_type = SP_MESH_TYPE_COONS;
std::vector<SPItem*> itemlist=selection->itemList();
for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
@@ -94,10 +94,10 @@ void ms_read_selection( Inkscape::Selection *selection,
if (style && (style->fill.isPaintserver())) {
SPPaintServer *server = item->style->getFillPaintServer();
- if ( SP_IS_MESHGRADIENT(server) ) {
+ if ( SP_IS_MESH(server) ) {
- SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector();
- SPMeshSmooth smooth = gradient->smooth;
+ SPMesh *gradient = SP_MESH(server); // ->getVector();
+ SPMeshType type = gradient->type;
if (gradient != ms_selected) {
if (ms_selected) {
@@ -106,11 +106,11 @@ void ms_read_selection( Inkscape::Selection *selection,
ms_selected = gradient;
}
}
- if( smooth != ms_smooth ) {
- if (ms_smooth != SP_MESH_SMOOTH_NONE && !first) {
- ms_smooth_multi = true;
+ if( type != ms_type ) {
+ if (ms_type != SP_MESH_TYPE_COONS && !first) {
+ ms_type_multi = true;
} else {
- ms_smooth = smooth;
+ ms_type = type;
}
}
first = false;
@@ -119,10 +119,10 @@ void ms_read_selection( Inkscape::Selection *selection,
if (style && (style->stroke.isPaintserver())) {
SPPaintServer *server = item->style->getStrokePaintServer();
- if ( SP_IS_MESHGRADIENT(server) ) {
+ if ( SP_IS_MESH(server) ) {
- SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector();
- SPMeshSmooth smooth = gradient->smooth;
+ SPMesh *gradient = SP_MESH(server); // ->getVector();
+ SPMeshType type = gradient->type;
if (gradient != ms_selected) {
if (ms_selected) {
@@ -131,11 +131,11 @@ void ms_read_selection( Inkscape::Selection *selection,
ms_selected = gradient;
}
}
- if( smooth != ms_smooth ) {
- if (ms_smooth != SP_MESH_SMOOTH_NONE && !first) {
- ms_smooth_multi = true;
+ if( type != ms_type ) {
+ if (ms_type != SP_MESH_TYPE_COONS && !first) {
+ ms_type_multi = true;
} else {
- ms_smooth = smooth;
+ ms_type = type;
}
}
first = false;
@@ -171,18 +171,18 @@ static void ms_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe
// // Hide/show handles?
// }
- SPMeshGradient *ms_selected = 0;
- SPMeshSmooth ms_smooth = SP_MESH_SMOOTH_NONE;
+ SPMesh *ms_selected = 0;
+ SPMeshType ms_type = SP_MESH_TYPE_COONS;
bool ms_selected_multi = false;
- bool ms_smooth_multi = false;
- ms_read_selection( selection, ms_selected, ms_selected_multi, ms_smooth, ms_smooth_multi );
- // std::cout << " smooth: " << ms_smooth << std::endl;
+ bool ms_type_multi = false;
+ ms_read_selection( selection, ms_selected, ms_selected_multi, ms_type, ms_type_multi );
+ // std::cout << " type: " << ms_type << std::endl;
- EgeSelectOneAction* smooth = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "mesh_select_smooth_action");
- gtk_action_set_sensitive( GTK_ACTION(smooth), (ms_selected && !ms_selected_multi) );
+ EgeSelectOneAction* type = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "mesh_select_type_action");
+ gtk_action_set_sensitive( GTK_ACTION(type), (ms_selected && !ms_selected_multi) );
if (ms_selected) {
blocked = TRUE;
- ege_select_one_action_set_active( smooth, ms_smooth );
+ ege_select_one_action_set_active( type, ms_type );
blocked = FALSE;
}
}
@@ -210,9 +210,9 @@ static void ms_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject *widg
ms_tb_selection_changed(NULL, widget);
}
-void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient *&ms_selected)
+void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMesh *&ms_selected)
{
- SPMeshGradient *gradient = 0;
+ SPMesh *gradient = 0;
std::vector<SPItem*> itemlist=selection->itemList();
for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
@@ -227,8 +227,8 @@ void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient
server = item->style->getStrokePaintServer();
}
- if ( SP_IS_MESHGRADIENT(server) ) {
- gradient = SP_MESHGRADIENT(server);
+ if ( SP_IS_MESH(server) ) {
+ gradient = SP_MESH(server);
}
}
@@ -242,11 +242,11 @@ void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient
* Callback functions for user actions
*/
-static void ms_new_type_changed( EgeSelectOneAction *act, GObject * /*tbl*/ )
+static void ms_new_geometry_changed( EgeSelectOneAction *act, GObject * /*tbl*/ )
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gint typemode = ege_select_one_action_get_active( act ) == 0 ? SP_GRADIENT_MESH_TYPE_NORMAL : SP_GRADIENT_MESH_TYPE_CONICAL;
- prefs->setInt("/tools/mesh/mesh_type", typemode);
+ gint geometrymode = ege_select_one_action_get_active( act ) == 0 ? SP_MESH_GEOMETRY_NORMAL : SP_MESH_GEOMETRY_CONICAL;
+ prefs->setInt("/tools/mesh/mesh_geometry", geometrymode);
}
static void ms_new_fillstroke_changed( EgeSelectOneAction *act, GObject * /*tbl*/ )
@@ -290,27 +290,27 @@ static void ms_col_changed(GtkAdjustment *adj, GObject * /*tbl*/ )
blocked = FALSE;
}
-static void ms_smooth_changed(EgeSelectOneAction *act, GtkWidget *widget)
+static void ms_type_changed(EgeSelectOneAction *act, GtkWidget *widget)
{
- // std::cout << "ms_smooth_changed" << std::endl;
+ // std::cout << "ms_type_changed" << std::endl;
if (blocked) {
return;
}
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(widget), "desktop"));
Inkscape::Selection *selection = desktop->getSelection();
- SPMeshGradient *gradient = 0;
+ SPMesh *gradient = 0;
ms_get_dt_selected_gradient(selection, gradient);
if (gradient) {
- SPMeshSmooth smooth = (SPMeshSmooth) ege_select_one_action_get_active(act);
- // std::cout << " smooth: " << smooth << std::endl;
- gradient->smooth = smooth;
- gradient->smooth_set = true;
+ SPMeshType type = (SPMeshType) ege_select_one_action_get_active(act);
+ // std::cout << " type: " << type << std::endl;
+ gradient->type = type;
+ gradient->type_set = true;
gradient->updateRepr();
DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_GRADIENT,
- _("Set mesh smoothing"));
+ _("Set mesh type"));
}
}
@@ -351,9 +351,9 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj
ege_select_one_action_set_tooltip_column( act, 1 );
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gint mode = prefs->getInt("/tools/mesh/mesh_type", SP_GRADIENT_MESH_TYPE_NORMAL) != SP_GRADIENT_MESH_TYPE_NORMAL;
+ gint mode = prefs->getInt("/tools/mesh/mesh_geometry", SP_MESH_GEOMETRY_NORMAL) != SP_MESH_GEOMETRY_NORMAL;
ege_select_one_action_set_active( act, mode );
- g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(ms_new_type_changed), holder );
+ g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(ms_new_geometry_changed), holder );
}
/* New gradient on fill or stroke*/
@@ -462,51 +462,30 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj
/* Warning */
{
GtkAction* act = gtk_action_new( "MeshWarningAction",
- _("WARNING: Mesh SVG Syntax Subject to Change, Smoothing Experimental"), NULL, NULL );
+ _("WARNING: Mesh SVG Syntax Subject to Change"), NULL, NULL );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
}
- /* Smoothing method */
+ /* Typeing method */
{
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
GtkTreeIter iter;
gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, C_("Smoothing", "None"), 1, SP_MESH_SMOOTH_NONE, -1 );
+ gtk_list_store_set( model, &iter, 0, C_("Type", "Coons"), 1, SP_MESH_TYPE_COONS, -1 );
gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Default"), 1, SP_MESH_SMOOTH_SMOOTH, -1 );
+ gtk_list_store_set( model, &iter, 0, _("Bicubic"), 1, SP_MESH_TYPE_BICUBIC, -1 );
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth1"), 1, SP_MESH_SMOOTH_SMOOTH1, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth2"), 1, SP_MESH_SMOOTH_SMOOTH2, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth3"), 1, SP_MESH_SMOOTH_SMOOTH3, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth4"), 1, SP_MESH_SMOOTH_SMOOTH4, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth5"), 1, SP_MESH_SMOOTH_SMOOTH5, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth6"), 1, SP_MESH_SMOOTH_SMOOTH6, -1 );
-
- gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, _("Smooth7"), 1, SP_MESH_SMOOTH_SMOOTH7, -1 );
-
- EgeSelectOneAction* act = ege_select_one_action_new( "MeshSmoothAction", _("None"),
- _("If the mesh should be smoothed across patch boundaries."),
+ EgeSelectOneAction* act = ege_select_one_action_new( "MeshSmoothAction", _("Coons"),
+ _("Coons: no smoothing. Bicubic: smoothing across patch boundaries."),
NULL, GTK_TREE_MODEL(model) );
g_object_set( act, "short_label", _("Smoothing:"), NULL );
ege_select_one_action_set_appearance( act, "compact" );
gtk_action_set_sensitive( GTK_ACTION(act), FALSE );
- g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(ms_smooth_changed), holder );
+ g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(ms_type_changed), holder );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
- g_object_set_data( holder, "mesh_select_smooth_action", act );
+ g_object_set_data( holder, "mesh_select_type_action", act );
}
}
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index 6ef910f61..948c80db3 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -37,8 +37,8 @@
#include "sp-color-notebook.h"
#include "sp-linear-gradient.h"
-#include "sp-mesh-gradient.h"
#include "sp-radial-gradient.h"
+#include "sp-mesh.h"
/* fixme: Move it from dialogs to here */
#include "gradient-selector.h"
#include <inkscape.h>
@@ -777,7 +777,7 @@ static void sp_paint_selector_set_mode_gradient(SPPaintSelector *psel, SPPaintSe
}
#ifdef WITH_MESH
else {
- SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_RADIAL);
+ SP_GRADIENT_SELECTOR(gsel)->setMode(SPGradientSelector::MODE_MESH);
gtk_label_set_markup(GTK_LABEL(psel->label), _("<b>Mesh gradient</b>"));
}
#endif
@@ -1244,7 +1244,7 @@ SPPaintSelector::Mode SPPaintSelector::getModeForStyle(SPStyle const & style, Fi
} else if (SP_IS_RADIALGRADIENT(server)) {
mode = MODE_GRADIENT_RADIAL;
#ifdef WITH_MESH
- } else if (SP_IS_MESHGRADIENT(server)) {
+ } else if (SP_IS_MESH(server)) {
mode = MODE_GRADIENT_MESH;
#endif
} else if (SP_IS_PATTERN(server)) {
diff --git a/src/widgets/paintbucket-toolbar.cpp b/src/widgets/paintbucket-toolbar.cpp
index d8edeb9f6..eb55287c4 100644
--- a/src/widgets/paintbucket-toolbar.cpp
+++ b/src/widgets/paintbucket-toolbar.cpp
@@ -121,17 +121,16 @@ void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
{
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
- GList* items = 0;
gint count = 0;
- for ( items = Inkscape::UI::Tools::flood_channels_dropdown_items_list(); items ; items = g_list_next(items) )
- {
+ const std::vector<Glib::ustring>& channel_list = Inkscape::UI::Tools::FloodTool::channel_list;
+ for (std::vector<Glib::ustring>::const_iterator iterator = channel_list.begin();
+ iterator != channel_list.end(); ++iterator ) {
GtkTreeIter iter;
gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
+ gtk_list_store_set( model, &iter, 0, (*iterator).c_str(), 1, count, -1 );
count++;
}
- g_list_free( items );
- items = 0;
+
EgeSelectOneAction* act1 = ege_select_one_action_new( "ChannelsAction", _("Fill by"), (""), NULL, GTK_TREE_MODEL(model) );
g_object_set( act1, "short_label", _("Fill by:"), NULL );
ege_select_one_action_set_appearance( act1, "compact" );
@@ -188,17 +187,15 @@ void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
{
GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
- GList* items = 0;
gint count = 0;
- for ( items = Inkscape::UI::Tools::flood_autogap_dropdown_items_list(); items ; items = g_list_next(items) )
- {
+ const std::vector<Glib::ustring>& gap_list = Inkscape::UI::Tools::FloodTool::gap_list;
+ for (std::vector<Glib::ustring>::const_iterator iterator = gap_list.begin();
+ iterator != gap_list.end(); ++iterator ) {
GtkTreeIter iter;
gtk_list_store_append( model, &iter );
- gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
+ gtk_list_store_set( model, &iter, 0, (*iterator).c_str(), 1, count, -1 );
count++;
}
- g_list_free( items );
- items = 0;
EgeSelectOneAction* act2 = ege_select_one_action_new( "AutoGapAction", _("Close gaps"), (""), NULL, GTK_TREE_MODEL(model) );
g_object_set( act2, "short_label", _("Close gaps:"), NULL );
ege_select_one_action_set_appearance( act2, "compact" );
diff --git a/src/widgets/rect-toolbar.cpp b/src/widgets/rect-toolbar.cpp
index 018ebbcdf..29a10a534 100644
--- a/src/widgets/rect-toolbar.cpp
+++ b/src/widgets/rect-toolbar.cpp
@@ -110,7 +110,7 @@ static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *
for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
if (SP_IS_RECT(*i)) {
if (gtk_adjustment_get_value(adj) != 0) {
- (SP_RECT(*i)->*setter)(Quantity::convert(gtk_adjustment_get_value(adj), unit, desktop->getNamedView()->svg_units));
+ (SP_RECT(items->data)->*setter)(Quantity::convert(gtk_adjustment_get_value(adj), unit, "px"));
} else {
(*i)->getRepr()->setAttribute(value_name, NULL);
}
@@ -182,7 +182,6 @@ static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar con
UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) );
Unit const *unit = tracker->getActiveUnit();
- Unit const *svg_unit = SP_ACTIVE_DESKTOP->getNamedView()->svg_units;
g_return_if_fail(unit != NULL);
gpointer item = g_object_get_data( tbl, "item" );
@@ -191,28 +190,28 @@ static void rect_tb_event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar con
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "rx" ) );
gdouble rx = SP_RECT(item)->getVisibleRx();
- gtk_adjustment_set_value(adj, Quantity::convert(rx, svg_unit, unit));
+ gtk_adjustment_set_value(adj, Quantity::convert(rx, "px", unit));
}
{
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "ry" ) );
gdouble ry = SP_RECT(item)->getVisibleRy();
- gtk_adjustment_set_value(adj, Quantity::convert(ry, svg_unit, unit));
+ gtk_adjustment_set_value(adj, Quantity::convert(ry, "px", unit));
}
{
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "width" ) );
gdouble width = SP_RECT(item)->getVisibleWidth();
- gtk_adjustment_set_value(adj, Quantity::convert(width, svg_unit, unit));
+ gtk_adjustment_set_value(adj, Quantity::convert(width, "px", unit));
}
{
GtkAdjustment *adj = GTK_ADJUSTMENT( g_object_get_data( tbl, "height" ) );
gdouble height = SP_RECT(item)->getVisibleHeight();
- gtk_adjustment_set_value(adj, Quantity::convert(height, svg_unit, unit));
+ gtk_adjustment_set_value(adj, Quantity::convert(height, "px", unit));
}
}
diff --git a/src/xml/repr-util.cpp b/src/xml/repr-util.cpp
index 447f2ff40..3858f08a7 100644
--- a/src/xml/repr-util.cpp
+++ b/src/xml/repr-util.cpp
@@ -32,6 +32,7 @@
#include <2geom/point.h>
#include "svg/stringstream.h"
#include "svg/css-ostringstream.h"
+#include "svg/svg-length.h"
#include "xml/repr.h"
#include "xml/repr-sorting.h"
@@ -502,6 +503,20 @@ unsigned int sp_repr_set_svg_double(Inkscape::XML::Node *repr, gchar const *key,
return true;
}
+/**
+ * For attributes where an exponent is allowed.
+ *
+ * Not suitable for property attributes.
+ */
+unsigned int sp_repr_set_svg_length(Inkscape::XML::Node *repr, gchar const *key, SVGLength &val)
+{
+ g_return_val_if_fail(repr != NULL, FALSE);
+ g_return_val_if_fail(key != NULL, FALSE);
+
+ repr->setAttribute(key, val.write());
+ return true;
+}
+
unsigned sp_repr_set_point(Inkscape::XML::Node *repr, gchar const *key, Geom::Point const & val)
{
g_return_val_if_fail(repr != NULL, FALSE);
diff --git a/src/xml/repr.h b/src/xml/repr.h
index c96560a98..fbe25ec12 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -30,6 +30,7 @@
#define SP_DC_NS_URI "http://purl.org/dc/elements/1.1/"
class SPCSSAttr;
+class SVGLength;
namespace Inkscape {
namespace IO {
@@ -115,6 +116,7 @@ unsigned sp_repr_set_boolean(Inkscape::XML::Node *repr, char const *key, unsigne
unsigned sp_repr_set_int(Inkscape::XML::Node *repr, char const *key, int val);
unsigned sp_repr_set_css_double(Inkscape::XML::Node *repr, char const *key, double val);
unsigned sp_repr_set_svg_double(Inkscape::XML::Node *repr, char const *key, double val);
+unsigned sp_repr_set_svg_length(Inkscape::XML::Node *repr, char const *key, SVGLength &val);
unsigned sp_repr_set_point(Inkscape::XML::Node *repr, char const *key, Geom::Point const & val);
unsigned sp_repr_get_point(Inkscape::XML::Node *repr, char const *key, Geom::Point *val);