inkscape/inkscape-1.3.2-lib2geom-1.4.patch

336 lines
12 KiB
Diff

From ab2650a48473cff0175c8efab2444857f9ecbb20 Mon Sep 17 00:00:00 2001
From: PBS <pbs3141@gmail.com>
Date: Thu, 20 Jul 2023 13:03:34 +0900
Subject: [PATCH] Update 2geom and migrate code
Fixes https://gitlab.com/inkscape/inkscape/-/issues/4445
Fixes https://gitlab.com/inkscape/inkscape/-/issues/4341
Also 'fixes' these pseudo non-bugs
Fixes https://gitlab.com/inkscape/lib2geom/-/issues/65
Fixes https://gitlab.com/inkscape/inbox/-/issues/8912
---
src/3rdparty/2geom | 2 +-
src/display/control/canvas-item.h | 6 ---
src/helper/geom.cpp | 61 ---------------------
src/helper/geom.h | 1 -
src/live_effects/lpe-tiling.cpp | 2 +-
src/trace/potrace/inkscape-potrace.cpp | 4 +-
src/trace/potrace/inkscape-potrace.h | 14 +----
src/ui/widget/canvas.cpp | 1 -
src/ui/widget/canvas/stores.cpp | 9 ++--
testfiles/CMakeLists.txt | 1 -
testfiles/src/min-bbox-test.cpp | 73 --------------------------
11 files changed, 10 insertions(+), 164 deletions(-)
delete mode 100644 testfiles/src/min-bbox-test.cpp
diff --git a/src/display/control/canvas-item.h b/src/display/control/canvas-item.h
index 3a5387d9e91..205234ff787 100644
--- a/src/display/control/canvas-item.h
+++ b/src/display/control/canvas-item.h
@@ -148,12 +148,6 @@ protected:
} // namespace Inkscape
-// Todo: Move to lib2geom.
-inline auto &operator<<(std::ostream &s, Geom::OptRect const &rect)
-{
- return rect ? (s << *rect) : (s << "(empty)");
-}
-
#endif // SEEN_CANVAS_ITEM_H
/*
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index 30111cb8d9d..6a282a18433 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -1010,67 +1010,6 @@ bool approx_dihedral(Geom::Affine const &affine, double eps)
return arr == std::array {1, 0, 0, 1 } || arr == std::array{ 0, 1, 1, 0 };
}
-/**
- * Computes the rotation which puts a set of points in a position where they can be wrapped in the
- * smallest possible axis-aligned rectangle, and returns it along with the rectangle.
- */
-std::pair<Geom::Affine, Geom::Rect> min_bounding_box(std::vector<Geom::Point> const &pts)
-{
- // Compute the convex hull.
- auto const hull = Geom::ConvexHull(pts);
-
- // Move the point i along until it maximises distance in the direction n.
- auto advance = [&] (int &i, Geom::Point const &n) {
- auto ih = Geom::dot(hull[i], n);
- while (true) {
- int j = (i + 1) % hull.size();
- auto jh = Geom::dot(hull[j], n);
- if (ih >= jh) break;
- i = j;
- ih = jh;
- }
- };
-
- double mina = std::numeric_limits<double>::max();
- std::pair<Geom::Affine, Geom::Rect> result;
-
- // Run rotating callipers.
- int j, k, l;
- for (int i = 0; i < hull.size(); i++) {
- // Get the current segment.
- auto &p1 = hull[i];
- auto &p2 = hull[(i + 1) % hull.size()];
- auto v = (p2 - p1).normalized();
- auto n = Geom::Point(-v.y(), v.x());
-
- if (i == 0) {
- // Initialise the points.
- j = 0; advance(j, v);
- k = j; advance(k, n);
- l = k; advance(l, -v);
- } else {
- // Advance the points.
- advance(j, v);
- advance(k, n);
- advance(l, -v);
- }
-
- // Compute the dimensions of the unconstrained rectangle.
- auto w = Geom::dot(hull[j] - hull[l], v);
- auto h = Geom::dot(hull[k] - hull[i], n);
- auto a = w * h;
-
- // Track the minimum.
- if (a < mina) {
- mina = a;
- result = std::make_pair(Geom::Affine(v.x(), -v.y(), v.y(), v.x(), 0.0, 0.0),
- Geom::Rect::from_xywh(Geom::dot(hull[l], v), Geom::dot(hull[i], n), w, h));
- }
- }
-
- return result;
-}
-
/*
Local Variables:
mode:c++
diff --git a/src/helper/geom.h b/src/helper/geom.h
index 50e434da780..59542e7d44f 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -45,7 +45,6 @@ void recursive_bezier4(const double x1, const double y1, const double x2, const
std::vector<Geom::Point> &pointlist,
int level);
bool approx_dihedral(Geom::Affine const &affine, double eps = 0.0001);
-std::pair<Geom::Affine, Geom::Rect> min_bounding_box(std::vector<Geom::Point> const &pts);
/// Returns signed area of triangle given by points; may be negative.
inline Geom::Coord triangle_area(Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3)
diff --git a/src/live_effects/lpe-tiling.cpp b/src/live_effects/lpe-tiling.cpp
index b4913c79b2d..5bd88801475 100644
--- a/src/live_effects/lpe-tiling.cpp
+++ b/src/live_effects/lpe-tiling.cpp
@@ -442,7 +442,7 @@ LPETiling::doAfterEffect (SPLPEItem const* lpeitem, SPCurve *curve)
auto p = Geom::Point(xset + offset_x - random_x[counter], yset + offset_y - random_y[counter]);
auto translate = p * gap.inverse();
Geom::Affine finalit = (transformoriginal * Geom::Translate(spcenter_base).inverse() * mirror * Geom::Translate(spcenter_base));
- finalit *= gapp.inverse() * Geom::Translate(spcenter).inverse() * originatrans.withoutTranslation().inverse() * r * translate * Geom::Translate(spcenter) ;
+ finalit *= gapp.inverse() * Geom::Translate(spcenter).inverse() * originatrans.withoutTranslation().inverse() * r * Geom::Translate(translate) * Geom::Translate(spcenter);
item->doWriteTransform(finalit);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
forcewrite = forcewrite || write;
diff --git a/src/trace/potrace/inkscape-potrace.cpp b/src/trace/potrace/inkscape-potrace.cpp
index a6c7f65f92a..e51a5afb104 100644
--- a/src/trace/potrace/inkscape-potrace.cpp
+++ b/src/trace/potrace/inkscape-potrace.cpp
@@ -93,7 +93,7 @@ void PotraceTracingEngine::setTurdSize(int turdsize)
* Recursively descend the potrace_path_t node tree \a paths, writing paths to \a builder.
* The \a points set is used to prevent redundant paths.
*/
-void PotraceTracingEngine::writePaths(potrace_path_t *paths, Geom::PathBuilder &builder, std::unordered_set<Geom::Point, geom_point_hash> &points, Async::Progress<double> &progress) const
+void PotraceTracingEngine::writePaths(potrace_path_t *paths, Geom::PathBuilder &builder, std::unordered_set<Geom::Point> &points, Async::Progress<double> &progress) const
{
auto to_geom = [] (potrace_dpoint_t const &c) {
return Geom::Point(c.x, c.y);
@@ -280,7 +280,7 @@ Geom::PathVector PotraceTracingEngine::grayMapToPath(GrayMap const &grayMap, Asy
// Extract the paths into a pathvector and return it.
Geom::PathBuilder builder;
- std::unordered_set<Geom::Point, geom_point_hash> points;
+ std::unordered_set<Geom::Point> points;
writePaths(potraceState->plist, builder, points, progress);
return builder.peek();
}
diff --git a/src/trace/potrace/inkscape-potrace.h b/src/trace/potrace/inkscape-potrace.h
index 0e4a9c62eeb..f30568369b2 100644
--- a/src/trace/potrace/inkscape-potrace.h
+++ b/src/trace/potrace/inkscape-potrace.h
@@ -45,18 +45,6 @@ enum class TraceType
AUTOTRACE_CENTERLINE
};
-// Todo: Make lib2geom types hashable.
-struct geom_point_hash
-{
- std::size_t operator()(Geom::Point const &pt) const
- {
- std::size_t hash = 0;
- boost::hash_combine(hash, pt.x());
- boost::hash_combine(hash, pt.y());
- return hash;
- }
-};
-
class PotraceTracingEngine final
: public TracingEngine
{
@@ -119,7 +107,7 @@ private:
Geom::PathVector grayMapToPath(GrayMap const &gm, Async::Progress<double> &progress);
- void writePaths(potrace_path_t *paths, Geom::PathBuilder &builder, std::unordered_set<Geom::Point, geom_point_hash> &points, Async::Progress<double> &progress) const;
+ void writePaths(potrace_path_t *paths, Geom::PathBuilder &builder, std::unordered_set<Geom::Point> &points, Async::Progress<double> &progress) const;
};
} // namespace Potrace
diff --git a/src/ui/widget/canvas.cpp b/src/ui/widget/canvas.cpp
index 7274d0a30f5..86fb95a54c7 100644
--- a/src/ui/widget/canvas.cpp
+++ b/src/ui/widget/canvas.cpp
@@ -18,7 +18,6 @@
#include <cassert>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/post.hpp>
-#include <2geom/convex-hull.h>
#include "canvas.h"
diff --git a/src/ui/widget/canvas/stores.cpp b/src/ui/widget/canvas/stores.cpp
index 70327f5a48b..e51598de456 100644
--- a/src/ui/widget/canvas/stores.cpp
+++ b/src/ui/widget/canvas/stores.cpp
@@ -4,6 +4,7 @@
#include <2geom/transforms.h>
#include <2geom/parallelogram.h>
#include <2geom/point.h>
+#include <2geom/convex-hull.h>
#include "helper/geom.h"
#include "ui/util.h"
#include "stores.h"
@@ -61,8 +62,7 @@ auto region_affine_approxinwards(Cairo::RefPtr<Cairo::Region> const &reg, Geom::
double fx = min(absolute(Geom::Point(1.0, 0.0) * affine.withoutTranslation()));
double fy = min(absolute(Geom::Point(0.0, 1.0) * affine.withoutTranslation()));
- for (int i = 0; i < regsrc->get_num_rectangles(); i++)
- {
+ for (int i = 0; i < regsrc->get_num_rectangles(); i++) {
auto rect = cairo_to_geom(regsrc->get_rectangle(i));
int nx = std::ceil(rect.width() * fx / d);
int ny = std::ceil(rect.height() * fy / d);
@@ -147,8 +147,9 @@ void Stores::snapshot_combine(Fragment const &view)
add_rect(Geom::Parallelogram(_snapshot.rect) * _snapshot.affine.inverse() * view.affine);
// Compute their minimum-area bounding box as a fragment - an (affine, rect) pair.
- auto [affine, rect] = min_bounding_box(pts);
- affine = view.affine * affine;
+ auto const [rot, optrect] = Geom::ConvexHull(pts).minAreaRotation();
+ auto rect = *optrect; // non-empty since pts is non-empty
+ auto affine = view.affine * rot;
// Check if the paste transform takes the snapshot store exactly onto the new fragment, possibly with a dihedral transformation.
auto paste = Geom::Scale(_snapshot.rect.dimensions())
diff --git a/testfiles/CMakeLists.txt b/testfiles/CMakeLists.txt
index dc0cbd6ac45..15f68eb439d 100644
--- a/testfiles/CMakeLists.txt
+++ b/testfiles/CMakeLists.txt
@@ -69,7 +69,6 @@ set(TEST_SOURCES
attributes-test
color-profile-test
dir-util-test
- min-bbox-test
oklab-color-test
sp-object-test
sp-object-tags-test
diff --git a/testfiles/src/min-bbox-test.cpp b/testfiles/src/min-bbox-test.cpp
deleted file mode 100644
index ccacd625a83..00000000000
--- a/testfiles/src/min-bbox-test.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-#include <2geom/convex-hull.h>
-#include <2geom/transforms.h>
-#include <gtest/gtest.h>
-#include <helper/geom.h>
-
-// Get the axis-aligned bouding box of a set of points, transforming by affine first.
-auto aligned_bbox(std::vector<Geom::Point> const &pts, Geom::Affine const &affine = Geom::identity())
-{
- Geom::OptRect rect;
- for (auto &pt : pts) {
- rect.expandTo(pt * affine);
- }
- return rect;
-}
-
-double area(Geom::OptRect const &rect)
-{
- return rect ? rect->area() : 0.0;
-}
-
-// Get an approximation to the minimum bouding box area.
-double approx_min(std::vector<Geom::Point> const &pts)
-{
- int constexpr N = 100;
-
- double min = std::numeric_limits<double>::max();
-
- for (int i = 0; i < N; i++) {
- auto t = (double)i / N * M_PI * 0.5;
- min = std::min(min, area(aligned_bbox(pts, Geom::Rotate(t))));
- }
-
- return min;
-}
-
-// Get a crude random double.
-double ranf()
-{
- int constexpr N = 1000;
- return (double)(rand() % N) / N;
-}
-
-// Get a random collection of points.
-auto randpts()
-{
- std::vector<Geom::Point> pts;
-
- int count = 5 + (rand() % 10);
- for (int i = 0; i < count; i++) {
- pts.emplace_back(ranf(), ranf());
- }
-
- return pts;
-}
-
-TEST(MinBBoxTest, random)
-{
- for (int i = 0; i < 100; i++) {
- auto const pts = randpts();
- auto [affine, rect] = min_bounding_box(pts);
-
- ASSERT_TRUE(affine.isRotation());
-
- auto rect2 = aligned_bbox(pts, affine);
- for (int i = 0; i < 2; i++) {
- ASSERT_NEAR(rect.min()[i], rect2->min()[i], 1e-5);
- ASSERT_NEAR(rect.max()[i], rect2->max()[i], 1e-5);
- }
-
- ASSERT_LE(rect.area(), approx_min(pts));
- }
-}
--
GitLab