summaryrefslogtreecommitdiffstats
path: root/src/knot-holder-entity.cpp
diff options
context:
space:
mode:
authorThomas Holder <thomas@thomas-holder.de>2018-09-12 14:43:47 +0000
committerThomas Holder <thomas@thomas-holder.de>2018-09-12 14:43:47 +0000
commit1fa0c72b664afa4803dffd463ed11ce01632ab76 (patch)
treec1f746d4e8f7a5d65541cf6c05d3cdc79b3f9c10 /src/knot-holder-entity.cpp
parentFix preferences crash (diff)
downloadinkscape-1fa0c72b664afa4803dffd463ed11ce01632ab76.tar.gz
inkscape-1fa0c72b664afa4803dffd463ed11ce01632ab76.zip
New option to invert y-axis
Replaces all hard coded or implicit desktop coordinate usage with doc2dt multiplication. New global preference: Interface > Origin at upper left https://bugs.launchpad.net/inkscape/+bug/170049
Diffstat (limited to 'src/knot-holder-entity.cpp')
-rw-r--r--src/knot-holder-entity.cpp90
1 files changed, 27 insertions, 63 deletions
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 3d34cdf01..83cc3d772 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -142,28 +142,9 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape:
/* TODO: this pattern manipulation is not able to handle general transformation matrices. Only matrices that are the result of a pure scale times a pure rotation. */
-static gdouble sp_pattern_extract_theta(SPPattern const *pat)
-{
- Geom::Affine transf = pat->getTransform();
- return Geom::atan2(transf.xAxis());
-}
-
-static Geom::Point sp_pattern_extract_scale(SPPattern const *pat)
-{
- Geom::Affine transf = pat->getTransform();
- return Geom::Point( transf.expansionX(), transf.expansionY() );
-}
-
-static Geom::Point sp_pattern_extract_trans(SPPattern const *pat)
-{
- return Geom::Point(pat->getTransform()[4], pat->getTransform()[5]);
-}
-
void
PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
{
- SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
-
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
@@ -176,18 +157,23 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
}
if (state) {
- Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat);
+ Geom::Point const q = p_snapped - knot_get();
item->adjust_pattern(Geom::Translate(q), false, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
+static Geom::Point sp_pattern_knot_get(SPPattern const *pat, gdouble x, gdouble y)
+{
+ return Geom::Point(x, y) * pat->getTransform();
+}
+
Geom::Point
PatternKnotHolderEntityXY::knot_get() const
{
SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
- return sp_pattern_extract_trans(pat);
+ return sp_pattern_knot_get(pat, 0, 0);
}
Geom::Point
@@ -195,14 +181,7 @@ PatternKnotHolderEntityAngle::knot_get() const
{
SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
- gdouble x = pat->width();
- gdouble y = 0;
- Geom::Point delta = Geom::Point(x,y);
- Geom::Point scale = sp_pattern_extract_scale(pat);
- gdouble theta = sp_pattern_extract_theta(pat);
- delta = delta * Geom::Affine(Geom::Scale(scale))*Geom::Affine(Geom::Rotate(theta));
- delta = delta + sp_pattern_extract_trans(pat);
- return delta;
+ return sp_pattern_knot_get(pat, pat->width(), 0);
}
void
@@ -214,53 +193,47 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// get the angle from pattern 0,0 to the cursor pos
- Geom::Point delta = p - sp_pattern_extract_trans(pat);
- gdouble theta = atan2(delta);
+ Geom::Point transform_origin = sp_pattern_knot_get(pat, 0, 0);
+ gdouble theta = atan2(p - transform_origin);
+ gdouble theta_old = atan2(knot_get() - transform_origin);
if ( state & GDK_CONTROL_MASK ) {
theta = sp_round(theta, M_PI/snaps);
}
- // get the scale from the current transform so we can keep it.
- Geom::Point scl = sp_pattern_extract_scale(pat);
- Geom::Affine rot = Geom::Affine(Geom::Scale(scl)) * Geom::Affine(Geom::Rotate(theta));
- Geom::Point const t = sp_pattern_extract_trans(pat);
- rot[4] = t[Geom::X];
- rot[5] = t[Geom::Y];
- item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
+ Geom::Affine rot = Geom::Translate(-transform_origin)
+ * Geom::Rotate(theta - theta_old)
+ * Geom::Translate(transform_origin);
+ item->adjust_pattern(rot, false, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
-PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
{
SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
- // get angle from current transform
- gdouble theta = sp_pattern_extract_theta(pat);
-
// Get the new scale from the position of the knotholder
- Geom::Point d = p_snapped - sp_pattern_extract_trans(pat);
+ Geom::Affine transform = pat->getTransform();
+ Geom::Affine transform_inverse = transform.inverse();
+ Geom::Point d = p_snapped * transform_inverse;
+ Geom::Point d_origin = origin * transform_inverse;
+ Geom::Point origin_dt;
gdouble pat_x = pat->width();
gdouble pat_y = pat->height();
- Geom::Scale scl(1);
if ( state & GDK_CONTROL_MASK ) {
// if ctrl is pressed: use 1:1 scaling
- gdouble pat_h = hypot(pat_x, pat_y);
- scl = Geom::Scale(d.length() / pat_h);
- } else {
- d *= Geom::Rotate(-theta);
- scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y);
+ d = d_origin * (d.length() / d_origin.length());
}
- Geom::Affine rot = (Geom::Affine)scl * Geom::Rotate(theta);
+ Geom::Affine rot = Geom::Translate(-origin_dt)
+ * Geom::Scale(d.x() / pat_x, d.y() / pat_y)
+ * Geom::Translate(origin_dt)
+ * transform;
- Geom::Point const t = sp_pattern_extract_trans(pat);
- rot[4] = t[Geom::X];
- rot[5] = t[Geom::Y];
item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
@@ -270,16 +243,7 @@ Geom::Point
PatternKnotHolderEntityScale::knot_get() const
{
SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
-
- gdouble x = pat->width();
- gdouble y = pat->height();
- Geom::Point delta = Geom::Point(x,y);
- Geom::Affine a = pat->getTransform();
- a[4] = 0;
- a[5] = 0;
- delta = delta * a;
- delta = delta + sp_pattern_extract_trans(pat);
- return delta;
+ return sp_pattern_knot_get(pat, pat->width(), pat->height());
}
/* Filter manipulation */