summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2015-03-18 18:10:06 +0000
committerJabiertxof <jtx@jtx.marker.es>2015-03-18 18:10:06 +0000
commitb4e2b53ff72280b9b3f1d902bd6a39dcb2761baf (patch)
tree90ccefcb9b692d95c4837de089ed2d154f7677fa /src
parentUpdate to new simplify (diff)
parentLatvian translation update (diff)
downloadinkscape-b4e2b53ff72280b9b3f1d902bd6a39dcb2761baf.tar.gz
inkscape-b4e2b53ff72280b9b3f1d902bd6a39dcb2761baf.zip
update to trunk
(bzr r13973.1.10)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/sbasis-to-bezier.cpp21
-rw-r--r--src/document.cpp24
-rw-r--r--src/document.h2
-rw-r--r--src/extension/internal/cairo-renderer.cpp2
-rw-r--r--src/helper/geom.cpp49
-rw-r--r--src/helper/geom.h1
-rw-r--r--src/knotholder.cpp3
-rw-r--r--src/live_effects/effect.cpp12
-rw-r--r--src/live_effects/lpe-lattice.cpp30
-rw-r--r--src/live_effects/lpe-lattice2.cpp349
-rw-r--r--src/live_effects/lpe-lattice2.h13
-rw-r--r--src/live_effects/lpe-offset.cpp2
-rw-r--r--src/live_effects/lpe-parallel.cpp2
-rw-r--r--src/live_effects/lpe-perspective-envelope.cpp17
-rw-r--r--src/live_effects/lpe-test-doEffect-stack.cpp2
-rw-r--r--src/live_effects/parameter/point.cpp82
-rw-r--r--src/live_effects/parameter/point.h11
-rw-r--r--src/sp-ellipse.cpp83
-rw-r--r--src/sp-item-group.cpp2
-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-rect.cpp94
-rw-r--r--src/splivarot.cpp2
-rw-r--r--src/svg/svg-length.cpp52
-rw-r--r--src/svg/svg-length.h8
-rw-r--r--src/ui/dialog/document-properties.cpp5
-rw-r--r--src/ui/object-edit.cpp96
-rw-r--r--src/ui/tools/spray-tool.cpp66
-rw-r--r--src/ui/widget/page-sizer.cpp117
-rw-r--r--src/ui/widget/page-sizer.h19
-rw-r--r--src/widgets/box3d-toolbar.cpp14
-rw-r--r--src/xml/repr-util.cpp15
-rw-r--r--src/xml/repr.h2
34 files changed, 825 insertions, 444 deletions
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/document.cpp b/src/document.cpp
index 2a50d00bd..62e2f5b46 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();
}
diff --git a/src/document.h b/src/document.h
index a33b476cc..ed19d123b 100644
--- a/src/document.h
+++ b/src/document.h
@@ -242,6 +242,8 @@ 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;
diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp
index 1f48d2097..7fbdc4296 100644
--- a/src/extension/internal/cairo-renderer.cpp
+++ b/src/extension/internal/cairo-renderer.cpp
@@ -517,7 +517,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/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/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/live_effects/effect.cpp b/src/live_effects/effect.cpp
index aab64fe64..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
{
@@ -461,9 +465,11 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
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/lpe-lattice.cpp b/src/live_effects/lpe-lattice.cpp
index ce0e4941b..c05bae7e1 100644
--- a/src/live_effects/lpe-lattice.cpp
+++ b/src/live_effects/lpe-lattice.cpp
@@ -236,21 +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_set_and_write_new_value(grid_point1);
- grid_point2.param_set_and_write_new_value(grid_point2);
- grid_point3.param_set_and_write_new_value(grid_point3);
- grid_point4.param_set_and_write_new_value(grid_point4);
- grid_point5.param_set_and_write_new_value(grid_point5);
- grid_point6.param_set_and_write_new_value(grid_point6);
- grid_point7.param_set_and_write_new_value(grid_point7);
- grid_point8.param_set_and_write_new_value(grid_point8);
- grid_point9.param_set_and_write_new_value(grid_point9);
- grid_point10.param_set_and_write_new_value(grid_point10);
- grid_point11.param_set_and_write_new_value(grid_point11);
- grid_point12.param_set_and_write_new_value(grid_point12);
- grid_point13.param_set_and_write_new_value(grid_point13);
- grid_point14.param_set_and_write_new_value(grid_point14);
- grid_point15.param_set_and_write_new_value(grid_point15);
+ 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 1bcbe286f..08bbbd504 100644
--- a/src/live_effects/lpe-lattice2.cpp
+++ b/src/live_effects/lpe-lattice2.cpp
@@ -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 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint0", &wr, this),
- grid_point1(_("Control handle 1:"), _("Control handle 1 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint1", &wr, this),
- grid_point2(_("Control handle 2:"), _("Control handle 2 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint2", &wr, this),
- grid_point3(_("Control handle 3:"), _("Control handle 3 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint3", &wr, this),
- grid_point4(_("Control handle 4:"), _("Control handle 4 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint4", &wr, this),
- grid_point5(_("Control handle 5:"), _("Control handle 5 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint5", &wr, this),
- grid_point6(_("Control handle 6:"), _("Control handle 6 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint6", &wr, this),
- grid_point7(_("Control handle 7:"), _("Control handle 7 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint7", &wr, this),
- grid_point8x9(_("Control handle 8x9:"), _("Control handle 8x9 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint8x9", &wr, this),
- grid_point10x11(_("Control handle 10x11:"), _("Control handle 10x11 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint10x11", &wr, this),
- grid_point12(_("Control handle 12:"), _("Control handle 12 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint12", &wr, this),
- grid_point13(_("Control handle 13:"), _("Control handle 13 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint13", &wr, this),
- grid_point14(_("Control handle 14:"), _("Control handle 14 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint14", &wr, this),
- grid_point15(_("Control handle 15:"), _("Control handle 15 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint15", &wr, this),
- grid_point16(_("Control handle 16:"), _("Control handle 16 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint16", &wr, this),
- grid_point17(_("Control handle 17:"), _("Control handle 17 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint17", &wr, this),
- grid_point18(_("Control handle 18:"), _("Control handle 18 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint18", &wr, this),
- grid_point19(_("Control handle 19:"), _("Control handle 19 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint19", &wr, this),
- grid_point20x21(_("Control handle 20x21:"), _("Control handle 20x21 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint20x21", &wr, this),
- grid_point22x23(_("Control handle 22x23:"), _("Control handle 22x23 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint22x23", &wr, this),
- grid_point24x26(_("Control handle 24x26:"), _("Control handle 24x26 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint24x26", &wr, this),
- grid_point25x27(_("Control handle 25x27:"), _("Control handle 25x27 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint25x27", &wr, this),
- grid_point28x30(_("Control handle 28x30:"), _("Control handle 28x30 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint28x30", &wr, this),
- grid_point29x31(_("Control handle 29x31:"), _("Control handle 29x31 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint29x31", &wr, this),
- grid_point32x33x34x35(_("Control handle 32x33x34x35:"), _("Control handle 32x33x34x35 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint32x33x34x35", &wr, this)
-
-
+ horizontalMirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontalMirror", &wr, this, false),
+ verticalMirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "verticalMirror", &wr, this, false),
+ grid_point0(_("Control 0:"), _("Control 0 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint0", &wr, this),
+ grid_point1(_("Control 1:"), _("Control 1 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint1", &wr, this),
+ grid_point2(_("Control 2:"), _("Control 2 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint2", &wr, this),
+ grid_point3(_("Control 3:"), _("Control 3 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint3", &wr, this),
+ grid_point4(_("Control 4:"), _("Control 4 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint4", &wr, this),
+ grid_point5(_("Control 5:"), _("Control 5 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint5", &wr, this),
+ grid_point6(_("Control 6:"), _("Control 6 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint6", &wr, this),
+ grid_point7(_("Control 7:"), _("Control 7 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint7", &wr, this),
+ grid_point8x9(_("Control 8x9:"), _("Control 8x9 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint8x9", &wr, this),
+ grid_point10x11(_("Control 10x11:"), _("Control 10x11 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint10x11", &wr, this),
+ grid_point12(_("Control 12:"), _("Control 12 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint12", &wr, this),
+ grid_point13(_("Control 13:"), _("Control 13 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint13", &wr, this),
+ grid_point14(_("Control 14:"), _("Control 14 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint14", &wr, this),
+ grid_point15(_("Control 15:"), _("Control 15 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint15", &wr, this),
+ grid_point16(_("Control 16:"), _("Control 16 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint16", &wr, this),
+ grid_point17(_("Control 17:"), _("Control 17 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint17", &wr, this),
+ grid_point18(_("Control 18:"), _("Control 18 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint18", &wr, this),
+ grid_point19(_("Control 19:"), _("Control 19 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint19", &wr, this),
+ grid_point20x21(_("Control 20x21:"), _("Control 20x21 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint20x21", &wr, this),
+ grid_point22x23(_("Control 22x23:"), _("Control 22x23 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint22x23", &wr, this),
+ grid_point24x26(_("Control 24x26:"), _("Control 24x26 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint24x26", &wr, this),
+ grid_point25x27(_("Control 25x27:"), _("Control 25x27 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint25x27", &wr, this),
+ grid_point28x30(_("Control 28x30:"), _("Control 28x30 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint28x30", &wr, this),
+ grid_point29x31(_("Control 29x31:"), _("Control 29x31 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint29x31", &wr, this),
+ grid_point32x33x34x35(_("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(&horizontalMirror);
+ registerParameter(&verticalMirror);
+ registerParameter(&grid_point0);
+ registerParameter(&grid_point1);
+ registerParameter(&grid_point2);
+ registerParameter(&grid_point3);
+ registerParameter(&grid_point4);
+ registerParameter(&grid_point5);
+ registerParameter(&grid_point6);
+ registerParameter(&grid_point7);
+ registerParameter(&grid_point8x9);
+ registerParameter(&grid_point10x11);
+ registerParameter(&grid_point12);
+ registerParameter(&grid_point13);
+ registerParameter(&grid_point14);
+ registerParameter(&grid_point15);
+ registerParameter(&grid_point16);
+ registerParameter(&grid_point17);
+ registerParameter(&grid_point18);
+ registerParameter(&grid_point19);
+ registerParameter(&grid_point20x21);
+ registerParameter(&grid_point22x23);
+ registerParameter(&grid_point24x26);
+ registerParameter(&grid_point25x27);
+ registerParameter(&grid_point28x30);
+ registerParameter(&grid_point29x31);
+ registerParameter(&grid_point32x33x34x35);
}
LPELattice2::~LPELattice2()
@@ -107,6 +108,10 @@ 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
@@ -118,44 +123,45 @@ 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);
+
+ 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;
+ 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;
Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
@@ -185,7 +191,7 @@ LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
// 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);
}
}
@@ -195,8 +201,8 @@ LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
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()
{
@@ -221,7 +228,10 @@ LPELattice2::newWidget()
vbox->set_homogeneous(false);
vbox->set_spacing(6);
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
- Gtk::Button* resetButton = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
+ Gtk::VBox * vboxExpander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+ vboxExpander->set_border_width(0);
+ vboxExpander->set_spacing(2);
+ Gtk::Button * resetButton = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
resetButton->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
resetButton->set_size_request(140,30);
vbox->pack_start(*hbox, true,true,2);
@@ -236,7 +246,11 @@ LPELattice2::newWidget()
}
Glib::ustring * tip = param->param_getTooltip();
if (widg) {
- vbox->pack_start(*widg, true, true, 2);
+ if (param->param_key == "horizontalMirror" || param->param_key == "verticalMirror") {
+ vbox->pack_start(*widg, true, true, 2);
+ } else {
+ vboxExpander->pack_start(*widg, true, true, 2);
+ }
if (tip) {
widg->set_tooltip_text(*tip);
} else {
@@ -248,14 +262,96 @@ LPELattice2::newWidget()
++it;
}
+
+ expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show Points"))));
+ expander->add(*vboxExpander);
+ expander->set_expanded(expanded);
+ vbox->pack_start(*expander, true, true, 2);
+ expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPELattice2::on_expander_changed) );
return dynamic_cast<Gtk::Widget *>(vbox);
}
void
+LPELattice2::on_expander_changed()
+{
+ 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 &paramA, PointParam &paramB, Geom::Line vert){
+ Geom::Point A = paramA;
+ Geom::Point B = paramB;
+ 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 distA = Geom::distance(A,nearest);
+ double distB = Geom::distance(B,nearest);
+ double distanceMed = (distA + distB)/2;
+ if(A[Geom::X] > B[Geom::X]){
+ distanceMed *= -1;
+ }
+ A[Geom::X] = nearest[Geom::X] - distanceMed;
+ B[Geom::X] = nearest[Geom::X] + distanceMed;
+ paramA.param_setValue(A, true);
+ paramB.param_setValue(B, true);
+}
+
+void
+LPELattice2::horizontal(PointParam &paramA, PointParam &paramB, Geom::Line horiz){
+ Geom::Point A = paramA;
+ Geom::Point B = paramB;
+ 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 distA = Geom::distance(A,nearest);
+ double distB = Geom::distance(B,nearest);
+ double distanceMed = (distA + distB)/2;
+ if(A[Geom::Y] > B[Geom::Y]){
+ distanceMed *= -1;
+ }
+ A[Geom::Y] = nearest[Geom::Y] - distanceMed;
+ B[Geom::Y] = nearest[Geom::Y] + distanceMed;
+ paramA.param_setValue(A, true);
+ paramB.param_setValue(B, true);
+}
+
+void
LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
{
original_bbox(lpeitem);
setDefaults();
+ Geom::Line vert(grid_point8x9.param_get_default(),grid_point10x11.param_get_default());
+ Geom::Line horiz(grid_point24x26.param_get_default(),grid_point25x27.param_get_default());
+ if(verticalMirror){
+ vertical(grid_point0, grid_point1,vert);
+ vertical(grid_point2, grid_point3,vert);
+ vertical(grid_point4, grid_point5,vert);
+ vertical(grid_point6, grid_point7,vert);
+ vertical(grid_point12, grid_point13,vert);
+ vertical(grid_point14, grid_point15,vert);
+ vertical(grid_point16, grid_point17,vert);
+ vertical(grid_point18, grid_point19,vert);
+ vertical(grid_point24x26, grid_point25x27,vert);
+ vertical(grid_point28x30, grid_point29x31,vert);
+ }
+ if(horizontalMirror){
+ horizontal(grid_point0, grid_point2,horiz);
+ horizontal(grid_point1, grid_point3,horiz);
+ horizontal(grid_point4, grid_point6,horiz);
+ horizontal(grid_point5, grid_point7,horiz);
+ horizontal(grid_point8x9, grid_point10x11,horiz);
+ horizontal(grid_point12, grid_point14,horiz);
+ horizontal(grid_point13, grid_point15,horiz);
+ horizontal(grid_point16, grid_point18,horiz);
+ horizontal(grid_point17, grid_point19,horiz);
+ horizontal(grid_point20x21, grid_point22x23,horiz);
+ }
SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem);
item->apply_to_clippath(item);
item->apply_to_mask(item);
@@ -369,36 +465,31 @@ LPELattice2::setDefaults()
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_point0.param_set_default();
+ grid_point1.param_set_default();
+ grid_point2.param_set_default();
+ grid_point3.param_set_default();
+ grid_point4.param_set_default();
+ grid_point5.param_set_default();
+ grid_point6.param_set_default();
+ grid_point7.param_set_default();
+ grid_point8x9.param_set_default();
+ grid_point10x11.param_set_default();
+ grid_point12.param_set_default();
+ grid_point13.param_set_default();
+ grid_point14.param_set_default();
+ grid_point15.param_set_default();
+ grid_point16.param_set_default();
+ grid_point17.param_set_default();
+ grid_point18.param_set_default();
+ grid_point19.param_set_default();
+ grid_point20x21.param_set_default();
+ grid_point22x23.param_set_default();
+ grid_point24x26.param_set_default();
+ grid_point25x27.param_set_default();
+ grid_point28x30.param_set_default();
+ grid_point29x31.param_set_default();
+ grid_point32x33x34x35.param_set_default();
}
void
diff --git a/src/live_effects/lpe-lattice2.h b/src/live_effects/lpe-lattice2.h
index 5084ceead..086bdab7e 100644
--- a/src/live_effects/lpe-lattice2.h
+++ b/src/live_effects/lpe-lattice2.h
@@ -18,7 +18,7 @@
*
* 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/point.h"
@@ -43,8 +43,14 @@ public:
virtual void calculateCurve(Geom::Point a,Geom::Point b, SPCurve *c, bool horizontal, bool move);
+ virtual void vertical(PointParam &paramA,PointParam &paramB, Geom::Line vert);
+
+ virtual void horizontal(PointParam &paramA,PointParam &paramB,Geom::Line horiz);
+
virtual void setDefaults();
+ virtual void on_expander_changed();
+
virtual void resetGrid();
//virtual void original_bbox(SPLPEItem const* lpeitem, bool absolute = false);
@@ -56,6 +62,8 @@ protected:
void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec);
private:
+ BoolParam horizontalMirror;
+ BoolParam verticalMirror;
PointParam grid_point0;
PointParam grid_point1;
PointParam grid_point2;
@@ -82,6 +90,9 @@ private:
PointParam grid_point29x31;
PointParam grid_point32x33x34x35;
+ 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 232f1c9db..ba7179476 100644
--- a/src/live_effects/lpe-offset.cpp
+++ b/src/live_effects/lpe-offset.cpp
@@ -44,7 +44,7 @@ LPEOffset::doOnApply(SPLPEItem const* lpeitem)
{
Geom::Point offset = *(SP_SHAPE(lpeitem)->_curve->first_point());
offset_pt.param_update_default(offset);
- offset_pt.param_set_and_write_new_value(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 a1e713fe2..aa7405607 100644
--- a/src/live_effects/lpe-parallel.cpp
+++ b/src/live_effects/lpe-parallel.cpp
@@ -74,7 +74,7 @@ LPEParallel::doOnApply (SPLPEItem const* lpeitem)
dir = unit_vector(B - A);
Geom::Point offset = (A + B)/2 + dir.ccw() * 100;
offset_pt.param_update_default(offset);
- offset_pt.param_set_and_write_new_value(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 d38427d0a..d60a13c23 100644
--- a/src/live_effects/lpe-perspective-envelope.cpp
+++ b/src/live_effects/lpe-perspective-envelope.cpp
@@ -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;
@@ -331,15 +329,10 @@ LPEPerspectiveEnvelope::setDefaults()
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
@@ -347,8 +340,8 @@ LPEPerspectiveEnvelope::resetDefaults(SPItem const* item)
{
Effect::resetDefaults(item);
original_bbox(SP_LPE_ITEM(item));
- setDefaults();
resetGrid();
+ setDefaults();
}
void
diff --git a/src/live_effects/lpe-test-doEffect-stack.cpp b/src/live_effects/lpe-test-doEffect-stack.cpp
index 36ab6b547..c6787aae1 100644
--- a/src/live_effects/lpe-test-doEffect-stack.cpp
+++ b/src/live_effects/lpe-test-doEffect-stack.cpp
@@ -28,7 +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_set_and_write_new_value(point);
+ point.param_setValue(point,true);
}
LPEdoEffectStackTest::~LPEdoEffectStackTest()
diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp
index 1d48bda8d..4c4d2cd9c 100644
--- a/src/live_effects/parameter/point.cpp
+++ b/src/live_effects/parameter/point.cpp
@@ -15,8 +15,6 @@
#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"
@@ -28,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;
@@ -45,19 +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_set_and_write_default()
+PointParam::param_update_default(Geom::Point newpoint)
{
- param_set_and_write_new_value(defvalue);
+ defvalue = newpoint;
}
void
-PointParam::param_update_default(Geom::Point newpoint)
+PointParam::param_setValue(Geom::Point newpoint, bool write)
{
- this->defvalue = newpoint;
+ *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
@@ -84,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()
{
@@ -110,36 +131,6 @@ PointParam::param_newWidget()
}
void
-PointParam::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
-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;
@@ -150,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;
@@ -175,8 +166,11 @@ PointParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &or
s = A;
}
}
- pparam->param_setValue(s);
- sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ pparam->param_setValue(s, true);
+ SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item);
+ if(splpeitem){
+ sp_lpe_item_update_patheffect(splpeitem, false, false);
+ }
}
Geom::Point
@@ -191,7 +185,10 @@ PointParamKnotHolderEntity::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);
+ SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item);
+ if(splpeitem){
+ sp_lpe_item_update_patheffect(splpeitem, false, false);
+ }
}
}
}
@@ -199,6 +196,7 @@ PointParamKnotHolderEntity::knot_click(guint state)
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);
diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h
index 95854ea52..471fbc993 100644
--- a/src/live_effects/parameter/point.h
+++ b/src/live_effects/parameter/point.h
@@ -38,14 +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_default();
+ Geom::Point param_get_default() const;
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);
@@ -57,9 +53,8 @@ public:
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/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-item-group.cpp b/src/sp-item-group.cpp
index 0c65bbaed..55857dacf 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -843,7 +843,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.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 f059ab531..12d85b3ed 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-rect.cpp b/src/sp-rect.cpp
index 30571a8dd..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->i2doc_affine());
-
- this->rx._set = true;
}
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->i2doc_affine());
-
- this->ry._set = true;
}
this->updateRepr();
@@ -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->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->i2doc_affine());
- this->height._set = true;
this->updateRepr();
}
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index 8bb3e9897..46279cbce 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -1727,7 +1727,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/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/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/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/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 790270d91..ec7d10e13 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -439,39 +439,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..8e647ebb4 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,8 @@ 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),
+ _lockScaleUpdate(false),
_widgetRegistry(&_wr)
{
// set precision of scalar entry boxes
@@ -250,6 +253,8 @@ PageSizer::PageSizer(Registry & _wr)
_marginLeft.setDigits(5);
_marginRight.setDigits(5);
_marginBottom.setDigits(5);
+ _scaleX.setDigits(5);
+ _scaleX.setRange( 0.00001, 100000 );
_wr.setUpdating (false);
//# Set up the Paper Size combo box
@@ -318,6 +323,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 +425,34 @@ 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);
+
+ _dimensionWidth.set_hexpand();
+ _dimensionWidth.set_vexpand();
+ _scaleTable.attach(_scaleX, 0, 0, 1, 1);
+
+ _dimensionUnits.set_hexpand();
+ _dimensionUnits.set_vexpand();
+ _scaleTable.attach(_scaleLabel, 1, 0, 1, 1);
+#else
+ _scaleTable.resize(2, 1);
+ _scaleTable.set_row_spacings(4);
+ _scaleTable.set_col_spacings(4);
+ _scaleTable.attach(_scaleX, 0,1, 0,1);
+ _scaleTable.attach(_scaleLabel, 1,2, 0,1);
+#endif
+
+ _wr.setUpdating (true);
+ updateScaleUI();
+ _wr.setUpdating (false);
}
@@ -444,7 +478,7 @@ 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));
show_all_children();
}
@@ -512,6 +546,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 +736,60 @@ PageSizer::on_landscape()
}
}
+
+/**
+ * Update scale widgets
+ */
+void
+PageSizer::updateScaleUI()
+{
+
+ if (_lockScaleUpdate) {
+ return;
+ }
+
+ static bool _called = false;
+ if (_called) {
+ return;
+ }
+
+ _called = true;
+
+ _changeds_connection.block();
+
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ if (dt) {
+ SPDocument *doc = dt->getDocument();
+ 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() );
+
+ 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);
+ }
+
+ } else {
+ // Should never happen
+ std::cerr << "PageSizer::updateScaleUI(): No active desktop." << std::endl;
+ _scaleLabel.set_text( "Unknown scale" );
+ }
+
+ _changeds_connection.unblock();
+
+ _called = false;
+}
+
+
/**
* Callback for the dimension widgets
*/
@@ -722,6 +811,32 @@ 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 );
+ _lockScaleUpdate = false;
+ DocumentUndo::done(doc, SP_VERB_NONE, _("Set page scale"));
+ }
+ }
+}
+
} // namespace Widget
} // namespace UI
} // namespace Inkscape
diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h
index bed117e5a..f9a72d9f3 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,26 @@ 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;
+ RegisteredScalar _scaleX;
+ bool _lockScaleUpdate;
+
//callback
void on_value_changed();
void on_units_changed();
+ void on_scale_changed();
sigc::connection _changedw_connection;
sigc::connection _changedh_connection;
sigc::connection _changedu_connection;
+ sigc::connection _changeds_connection;
Registry *_widgetRegistry;
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/xml/repr-util.cpp b/src/xml/repr-util.cpp
index 12280ea5a..7c5d2d6fc 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 e1d7fdfd6..c3ba40e45 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);