summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2018-10-25 10:06:05 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2018-10-25 12:43:55 +0200
commit313392119522c21a6ecd14403d6f92c948149df7 (patch)
treefbd1a112a41f83d34c6bb6ea79eeccf73dba3e7b /drawinglayer
parent8dec85a3b3f4cbd46b03f707458347a25cc22c15 (diff)
Reorganize FrameBorderPrimitive creation (II)
Step5: Move the view-dependent decomposition from BorderLinePrimitive2D to SdrFrameBorderPrimitive2D. It is now possible to use discrete sizes before the line and edge matching is done what will look much better. When it was done at BorderLinePrimitive2D and the matching was already done, that match was 'displaced' with the adapted forced scale to discrete units. The space and size used when zooming out for a single discrete unit (pixel) can heavily vary - it just covers a much larger logical area than the 'real' line/poly would do. All this needs to be handled (also for bound ranges) and can only be in a good way using primitives. Adapted to no longer do view-dependent changes in BorderLinePrimitive2D. Adapted to do these now at SdrFrameBorderPrimitive2D. Currently used to force the existing border partial lines (up to three) to not get taller than one logical unit. Adapted to no longer switch off AntiAliased rendering in VclPixelProcessor2D for processBorderLinePrimitive2D, this is problematic with various renderers on various systems (e.g. vcl still falls back to render multiple one-pixel-lines when taller than 3.5 pixels which looks horrible combined with other parts like filled polygons) All this needs fine balancing on - all systems - all renderers - all apps (which all have their own table implementation) - all render targets (pixel/PDF/print/slideshow/...) Done as thorough as possible, but may need additional finetuning. May also be a motivation to move away from vcl and implement these urgetly needed system-dependent primitive renderers... Adapted UnitTest testDoublePixelProcessing with the needed comments. Change-Id: Ie88bb76c2474b6ab3764d45a9cd1669264492acd Reviewed-on: https://gerrit.libreoffice.org/62344 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/qa/unit/border.cxx13
-rw-r--r--drawinglayer/source/primitive2d/borderlineprimitive2d.cxx84
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx25
3 files changed, 36 insertions, 86 deletions
diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx
index 365c90d1691f..30d278a91560 100644
--- a/drawinglayer/qa/unit/border.cxx
+++ b/drawinglayer/qa/unit/border.cxx
@@ -189,7 +189,7 @@ void DrawinglayerBorderTest::testDoublePixelProcessing()
{
auto pMPLAction = static_cast<MetaPolyLineAction*>(pAction);
- if (0 == pMPLAction->GetLineInfo().GetWidth() && LineStyle::Solid == pMPLAction->GetLineInfo().GetStyle())
+ if (0 != pMPLAction->GetLineInfo().GetWidth() && LineStyle::Solid == pMPLAction->GetLineInfo().GetStyle())
{
nPolyLineActionCount++;
}
@@ -198,7 +198,16 @@ void DrawinglayerBorderTest::testDoublePixelProcessing()
// Check if all eight (2x four) simple lines with width == 0 and
// solid were created
- const sal_uInt32 nExpectedNumPolyLineActions = 8;
+ //
+ // This has changed: Now, just the needed 'real' lines get created
+ // which have a width of 1. This are two lines. The former multiple
+ // lines were a combination of view-dependent force to a single-pixel
+ // line width (0 == lineWidth -> hairline) and vcl rendering this
+ // using a (insane) combination of single non-AAed lines. All the
+ // system-dependent part of the BorderLine stuff is now done in
+ // SdrFrameBorderPrimitive2D and svx.
+ // Adapted this test - still useful, breaking it may be a hint :-)
+ const sal_uInt32 nExpectedNumPolyLineActions = 2;
CPPUNIT_ASSERT_EQUAL(nExpectedNumPolyLineActions, nPolyLineActionCount);
}
diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index 4c7bf9743628..e23a48921dc6 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -76,18 +76,6 @@ namespace drawinglayer
&& isGap() == rBorderLine.isGap();
}
- double BorderLine::getAdaptedWidth(double fMinWidth) const
- {
- if(isGap())
- {
- return std::max(getLineAttribute().getWidth(), fMinWidth);
- }
- else
- {
- return getLineAttribute().getWidth();
- }
- }
-
// helper to add a centered, maybe stroked line primitive to rContainer
static void addPolygonStrokePrimitive2D(
Primitive2DContainer& rContainer,
@@ -124,7 +112,7 @@ namespace drawinglayer
for(const auto& candidate : maBorderLines)
{
- fRetval += candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance);
+ fRetval += candidate.getLineAttribute().getWidth();
}
return fRetval;
@@ -143,7 +131,7 @@ namespace drawinglayer
for(const auto& candidate : maBorderLines)
{
- const double fWidth(candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance));
+ const double fWidth(candidate.getLineAttribute().getWidth());
if(!candidate.isGap())
{
@@ -289,8 +277,7 @@ namespace drawinglayer
maStart(rStart),
maEnd(rEnd),
maBorderLines(rBorderLines),
- maStrokeAttribute(rStrokeAttribute),
- mfSmallestAllowedDiscreteGapDistance(0.0)
+ maStrokeAttribute(rStrokeAttribute)
{
}
@@ -320,71 +307,6 @@ namespace drawinglayer
return false;
}
- bool BorderLinePrimitive2D::getSmallestGap(double& rfSmallestGap) const
- {
- bool bGapFound(false);
-
- for(const auto& candidate : maBorderLines)
- {
- if(candidate.isGap())
- {
- if(bGapFound)
- {
- rfSmallestGap = std::min(rfSmallestGap, candidate.getLineAttribute().getWidth());
- }
- else
- {
- bGapFound = true;
- rfSmallestGap = candidate.getLineAttribute().getWidth();
- }
- }
- }
-
- return bGapFound;
- }
-
- void BorderLinePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
- {
- ::osl::MutexGuard aGuard(m_aMutex);
-
- if (!getStart().equal(getEnd()) && getBorderLines().size() > 1)
- {
- // Line with potential gap. In this case, we want to be view-dependent.
- // get the smallest gap
- double fSmallestGap(0.0);
-
- if(getSmallestGap(fSmallestGap))
- {
- // Get the current DiscreteUnit, look at X and Y and use the maximum
- const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
- const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY())));
-
- // When discrete unit is bigger than distance (distance is less than one pixel),
- // force distance to one pixel. Or expressed different, do not let the distance
- // get smaller than one pixel. This is done for screen rendering and compatibility.
- // This can also be done using DiscreteMetricDependentPrimitive2D as base class
- // for this class, but specialization is better here for later buffering (only
- // do this when 'double line with gap')
- const double fNewDiscreteDistance(std::max(fDiscreteUnit, fSmallestGap));
-
- if (!rtl::math::approxEqual(fNewDiscreteDistance, mfSmallestAllowedDiscreteGapDistance))
- {
- if (!getBuffered2DDecomposition().empty())
- {
- // conditions of last local decomposition have changed, delete
- const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
- }
-
- // remember value for usage in create2DDecomposition
- const_cast< BorderLinePrimitive2D* >(this)->mfSmallestAllowedDiscreteGapDistance = fNewDiscreteDistance;
- }
- }
- }
-
- // call base implementation
- BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation);
- }
-
// provide unique ID
ImplPrimitive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 4a891166f295..ad70cec45135 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -879,17 +879,36 @@ namespace drawinglayer
void VclPixelProcessor2D::processBorderLinePrimitive2D(const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder)
{
- // process recursively, but switch off AntiAliasing for
+ // Process recursively, but switch off AntiAliasing for
// horizontal/vertical lines (*not* diagonal lines).
// Checked using AntialiasingFlags::PixelSnapHairline instead,
// but with AntiAliasing on the display really is too 'ghosty' when
// using fine stroking. Correct, but 'ghosty'.
- if (rBorder.isHorizontalOrVertical(getViewInformation2D()))
+ // It has shown that there are quite some problems here:
+ // - vcl OutDev renderer methods stuill use fallbacks to paint
+ // multiple single lines between discrete sizes of < 3.5 what
+ // looks bad and does not matzch
+ // - mix of filled Polygons and Lines is bad when AA switched off
+ // - Alignment of AA with non-AA may be bad in diverse different
+ // renderers
+ //
+ // Due to these reasons I change the strategy: Always draw AAed, but
+ // allow fallback to test/check and if needed. The normal case
+ // where BorderLines will be system-depenently snapped to have at
+ // least a single discrete width per partial line (there may be up to
+ // three) works well nowadays due to most renderers moving the AA stuff
+ // by 0.5 pixels (discrete units) to match well with the non-AAed parts.
+ //
+ // Env-Switch for steering this, default is off.
+ // Enable by setting at all (and to something)
+ static const char* pSwitchOffAntiAliasingForHorVerBorderlines(getenv("SAL_SWITCH_OFF_ANTIALIASING_FOR_HOR_VER_BORTDERLINES"));
+ static bool bSwitchOffAntiAliasingForHorVerBorderlines(nullptr != pSwitchOffAntiAliasingForHorVerBorderlines);
+
+ if (bSwitchOffAntiAliasingForHorVerBorderlines && rBorder.isHorizontalOrVertical(getViewInformation2D()))
{
AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing();
mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
-
process(rBorder);
mpOutputDevice->SetAntialiasing(nAntiAliasing);
}