summaryrefslogtreecommitdiff
path: root/svx
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@collabora.co.uk>2024-05-30 13:31:28 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2024-06-01 10:22:55 +0200
commit302a221856809e2b046cb9fb1675bfff4d86a37d (patch)
tree2abff3b0e3aec374b9f2e5b0fd8a9e5215144572 /svx
parent0a0d3d1f8a34e0b8542c71fe9c3bd3b75d974e7c (diff)
tdf#161198 tdf#161322 fix selection overlays
revert commit 7b1405689d4246e0e37e8759f03e1962af964cec Author: Noel Grandin <noelgrandin@gmail.com> Date: Fri Apr 19 22:56:04 2024 +0200 reduce the number of drawing primitives we create in OverlaySelection Change-Id: I868540aadb3a75582990ae4491807991617215b1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168253 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'svx')
-rw-r--r--svx/source/sdr/overlay/overlayselection.cxx233
1 files changed, 60 insertions, 173 deletions
diff --git a/svx/source/sdr/overlay/overlayselection.cxx b/svx/source/sdr/overlay/overlayselection.cxx
index a5598c1d2125..49418ae906e9 100644
--- a/svx/source/sdr/overlay/overlayselection.cxx
+++ b/svx/source/sdr/overlay/overlayselection.cxx
@@ -34,137 +34,31 @@
#include <o3tl/sorted_vector.hxx>
#include <map>
-namespace
-{
-struct B2DPointCompare
-{
- bool operator()(const basegfx::B2DPoint& lhs, const basegfx::B2DPoint& rhs) const
- {
- return std::make_pair(lhs.getX(), lhs.getY()) < std::make_pair(rhs.getX(), rhs.getY());
- }
-};
-
-struct B2DPointCompareYThenX
-{
- bool operator()(const basegfx::B2DPoint& lhs, const basegfx::B2DPoint& rhs) const
- {
- return std::make_pair(lhs.getY(), lhs.getX()) < std::make_pair(rhs.getY(), rhs.getX());
- }
-};
-
-}
-
namespace sdr::overlay
{
- // Combine rectangles geometrically to a single OR'ed polygon.
- // Algorithm is from
- // "Uniqueness of orthogonal connect-the-dots" Joseph O'Rourke 1988
- // The basic algorithm is:
- // Sort points by lowest x, lowest y
- // Go through each column and create edges between the vertices 2i and 2i + 1 in that column
- // Sort points by lowest y, lowest x
- // Go through each row and create edges between the vertices 2i and 2i + 1 in that row.
- //
- static basegfx::B2DPolyPolygon impCombineRectanglesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRectangles)
- {
- o3tl::sorted_vector<basegfx::B2DPoint, B2DPointCompare> sort_x;
- for (auto const & rRect : rRectangles)
+ // combine rages geometrically to a single, ORed polygon
+ static basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRanges)
{
- auto checkPoint = [&sort_x](double x, double y)
- {
- basegfx::B2DPoint pt(x, y);
- auto it = sort_x.find(pt);
- if (it != sort_x.end()) // Shared vertice, remove it.
- sort_x.erase(it);
- else
- sort_x.insert(pt);
- };
- checkPoint(rRect.getMinX(), rRect.getMinY());
- checkPoint(rRect.getMinX(), rRect.getMaxY());
- checkPoint(rRect.getMaxX(), rRect.getMinY());
- checkPoint(rRect.getMaxX(), rRect.getMaxY());
- }
-
-
- o3tl::sorted_vector<basegfx::B2DPoint, B2DPointCompareYThenX> sort_y;
- for (auto const & i : sort_x)
- sort_y.insert(i);
-
- std::map<basegfx::B2DPoint, basegfx::B2DPoint, B2DPointCompare> edges_h;
- std::map<basegfx::B2DPoint, basegfx::B2DPoint, B2DPointCompare> edges_v;
+ const sal_uInt32 nCount(rRanges.size());
+ basegfx::B2DPolyPolygon aRetval;
- size_t i = 0;
- while (i < sort_x.size())
- {
- auto curr_y = sort_y[i].getY();
- while (i < sort_x.size() && sort_y[i].getY() == curr_y)
- {
- edges_h[sort_y[i]] = sort_y[i + 1];
- edges_h[sort_y[i + 1]] = sort_y[i];
- i += 2;
- }
- }
- i = 0;
- while (i < sort_x.size())
- {
- auto curr_x = sort_x[i].getX();
- while (i < sort_x.size() && sort_x[i].getX() == curr_x)
+ for(sal_uInt32 a(0); a < nCount; a++)
{
- edges_v[sort_x[i]] = sort_x[i + 1];
- edges_v[sort_x[i + 1]] = sort_x[i];
- i += 2;
- }
- }
+ const basegfx::B2DPolygon aDiscretePolygon(basegfx::utils::createPolygonFromRect(rRanges[a]));
- // Get all the polygons.
- basegfx::B2DPolyPolygon aPolyPolygon;
- std::vector<std::tuple<basegfx::B2DPoint, bool>> tmpPolygon;
- while (!edges_h.empty())
- {
- tmpPolygon.clear();
- // We can start with any point.
- basegfx::B2DPoint pt = edges_h.begin()->first;
- edges_h.erase(edges_h.begin());
- tmpPolygon.push_back({pt, false});
- for (;;)
- {
- auto [curr, e] = tmpPolygon.back();
- if (!e)
+ if(0 == a)
{
- auto it = edges_v.find(curr);
- auto next_vertex = it->second;
- edges_v.erase(it);
- tmpPolygon.push_back({next_vertex, true});
+ aRetval.append(aDiscretePolygon);
}
else
{
- auto it = edges_h.find(curr);
- auto next_vertex = it->second;
- edges_h.erase(it);
- tmpPolygon.push_back({next_vertex, false});
- }
- if (tmpPolygon.back() == tmpPolygon.front())
- {
- // Closed polygon
- break;
+ aRetval = basegfx::utils::solvePolygonOperationOr(aRetval, basegfx::B2DPolyPolygon(aDiscretePolygon));
}
}
- for (auto const & pair : tmpPolygon)
- {
- auto const & vertex = std::get<0>(pair);
- edges_h.erase(vertex);
- edges_v.erase(vertex);
- }
- basegfx::B2DPolygon aPoly;
- aPoly.reserve(tmpPolygon.size());
- for (auto const & pair : tmpPolygon)
- aPoly.append(std::get<0>(pair));
- aPolyPolygon.append(std::move(aPoly));
- }
- return aPolyPolygon;
- }
+ return aRetval;
+ }
// check if wanted type OverlayType::Transparent or OverlayType::Solid
// is possible. If not, fallback to invert mode (classic mode)
@@ -200,70 +94,63 @@ namespace sdr::overlay
drawinglayer::primitive2d::Primitive2DContainer OverlaySelection::createOverlayObjectPrimitive2DSequence()
{
drawinglayer::primitive2d::Primitive2DContainer aRetval;
- const sal_uInt32 nCount(maRanges.size());
-
- if(!nCount)
- return aRetval;
+ const sal_uInt32 nCount(getRanges().size());
- // create range primitives
- const bool bInvert(OverlayType::Invert == maLastOverlayType);
- basegfx::BColor aRGBColor(getBaseColor().getBColor());
- if(bInvert)
+ if(nCount)
{
- // force color to white for invert to get a full invert
- aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
- }
-
- aRetval.resize(nCount);
- for(sal_uInt32 a(0);a < nCount; a++)
- {
- basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
- aRetval[a] =
- new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
- basegfx::B2DPolyPolygon(std::move(aPolygon)),
- aRGBColor);
- }
-
- basegfx::B2DPolyPolygon aPolyPolygon;
- aPolyPolygon.reserve(nCount);
- for(sal_uInt32 a(0);a < nCount; a++)
- aPolyPolygon.append(basegfx::utils::createPolygonFromRect(maRanges[a]));
- aRetval.append(
- new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
- std::move(aPolyPolygon),
- aRGBColor));
+ // create range primitives
+ const bool bInvert(OverlayType::Invert == maLastOverlayType);
+ basegfx::BColor aRGBColor(getBaseColor().getBColor());
+ aRetval.resize(nCount);
- if(bInvert)
- {
- // embed all in invert primitive
- aRetval = drawinglayer::primitive2d::Primitive2DContainer {
- new drawinglayer::primitive2d::InvertPrimitive2D(
- std::move(aRetval))
- };
- }
- else if(OverlayType::Transparent == maLastOverlayType)
- {
- // embed all rectangles in transparent paint
- const double fTransparence(mnLastTransparence / 100.0);
- drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
- new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
- std::move(aRetval),
- fTransparence));
+ if(bInvert)
+ {
+ // force color to white for invert to get a full invert
+ aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
+ }
- if(mbBorder)
+ for(sal_uInt32 a(0);a < nCount; a++)
{
- drawinglayer::primitive2d::Primitive2DReference aSelectionOutline(
- new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
- impCombineRectanglesToPolyPolygon(maRanges),
- aRGBColor));
+ const basegfx::B2DPolygon aPolygon(basegfx::utils::createPolygonFromRect(maRanges[a]));
+ aRetval[a] =
+ new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+ basegfx::B2DPolyPolygon(aPolygon),
+ aRGBColor);
+ }
- // add both to result
- aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence, aSelectionOutline };
+ if(bInvert)
+ {
+ // embed all in invert primitive
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer {
+ new drawinglayer::primitive2d::InvertPrimitive2D(
+ std::move(aRetval))
+ };
}
- else
+ else if(OverlayType::Transparent == maLastOverlayType)
{
- // just add transparent part
- aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+ // embed all rectangles in transparent paint
+ const double fTransparence(mnLastTransparence / 100.0);
+ const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
+ new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+ std::move(aRetval),
+ fTransparence));
+
+ if(mbBorder)
+ {
+ basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges()));
+ const drawinglayer::primitive2d::Primitive2DReference aSelectionOutline(
+ new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
+ std::move(aPolyPolygon),
+ aRGBColor));
+
+ // add both to result
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence, aSelectionOutline };
+ }
+ else
+ {
+ // just add transparent part
+ aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence };
+ }
}
}