Rebased ref, commits from common ancestor:
commit 10b19636c8466edb5e5147156ffcd6b69e9d1416
Author: Tamás Zolnai <[email protected]>
AuthorDate: Mon Oct 27 13:37:22 2025 +0100
Commit: Tamás Zolnai <[email protected]>
CommitDate: Tue Oct 28 12:09:26 2025 +0100
POC: Better grid in Impress / Draw
Change-Id: I10f6bcdfed296876789f2b1ac89f6f218227ae2e
diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx
b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
index dd6cca55fad6..c15dc879b5d2 100644
--- a/drawinglayer/source/primitive2d/gridprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
@@ -24,7 +24,10 @@
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <utility>
+#include <sal/log.hxx>
+
using namespace com::sun::star;
@@ -34,6 +37,7 @@ namespace drawinglayer::primitive2d
{
Primitive2DReference GridPrimitive2D::create2DDecomposition(const
geometry::ViewInformation2D& rViewInformation) const
{
+ SAL_WARN("GridPrimitive2D", "create2DDecomposition" );
if(!(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0
&& getHeight() > 0.0))
return nullptr;
@@ -144,7 +148,7 @@ namespace drawinglayer::primitive2d
aExtendedViewport.transform(aTrans);
// crop start/end in X/Y to multiples of logical step width
- const double
fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() *
basegfx::B2DVector(3.0, 0.0)).getLength());
+ const double
fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() *
basegfx::B2DVector(20.0, 0.0)).getLength());
const double fMinX(floor((aExtendedViewport.getMinX() -
fHalfCrossSize) / fStepX) * fStepX);
const double fMaxX(ceil((aExtendedViewport.getMaxX() +
fHalfCrossSize) / fStepX) * fStepX);
const double fMinY(floor((aExtendedViewport.getMinY() -
fHalfCrossSize) / fStepY) * fStepY);
@@ -168,17 +172,20 @@ namespace drawinglayer::primitive2d
for(double fX(aExtendedViewport.getMinX()); fX <
aExtendedViewport.getMaxX(); fX += fStepX)
{
+ SAL_WARN("GridPrimitive2D", "for(double
fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX +=
fStepX)" );
const bool bXZero(basegfx::fTools::equalZero(fX));
for(double fY(aExtendedViewport.getMinY()); fY <
aExtendedViewport.getMaxY(); fY += fStepY)
{
+ SAL_WARN("GridPrimitive2D", "for(double
fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY +=
fStepY)" );
const bool bYZero(basegfx::fTools::equalZero(fY));
if(!bXZero && !bYZero)
{
+ SAL_WARN("GridPrimitive2D", "if(!bXZero && !bYZero)" );
// get discrete position and test against 3x3 area
surrounding it
// since it's a cross
- const double fHalfCrossSize(3.0 * 0.5);
+ const double fHalfCrossSize(20.0 * 0.5);
const basegfx::B2DPoint aViewPos(aRST *
basegfx::B2DPoint(fX, fY));
const basegfx::B2DRange aDiscreteRangeCross(
aViewPos.getX() - fHalfCrossSize, aViewPos.getY()
- fHalfCrossSize,
@@ -202,7 +209,7 @@ namespace drawinglayer::primitive2d
if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
{
const basegfx::B2DPoint
aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
- aPositionsPoint.push_back(aLogicPos);
+ aPositionsCross.push_back(aLogicPos);
}
}
}
@@ -218,7 +225,7 @@ namespace drawinglayer::primitive2d
if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
{
const basegfx::B2DPoint
aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
- aPositionsPoint.push_back(aLogicPos);
+ aPositionsCross.push_back(aLogicPos);
}
}
}
@@ -226,29 +233,35 @@ namespace drawinglayer::primitive2d
}
// prepare return value
- const sal_uInt32 nCountPoint(aPositionsPoint.size());
const sal_uInt32 nCountCross(aPositionsCross.size());
// add PointArrayPrimitive2D if point markers were added
Primitive2DContainer aContainer;
- if(nCountPoint)
{
- aContainer.push_back(new
PointArrayPrimitive2D(std::move(aPositionsPoint), getBColor()));
- }
+ SAL_WARN("GridPrimitive2D", "MarkerArrayPrimitive2D" );
+ for (const basegfx::B2DPoint &aPoint : aPositionsCross)
+ {
+ SAL_WARN("GridPrimitive2D", "aPoint" );
+ SAL_WARN("GridPrimitive2D", "fStepX: " << fStepX );
+ double fHalfCrossSize(std::min(fStepX, fStepY) / 4 / 2);
+ if(getSubdivisionsX())
+ {
+ fHalfCrossSize = std::min(fHalfCrossSize, fSmallStepX
/ 4 / 2);
+ }
+ if(getSubdivisionsY())
+ {
+ fHalfCrossSize = std::min(fHalfCrossSize, fSmallStepY
/ 4 / 2);
+ }
- // add MarkerArrayPrimitive2D if cross markers were added
- if(!nCountCross)
- return new GroupPrimitive2D(std::move(aContainer));
+ aContainer.push_back(new
SingleLinePrimitive2D(basegfx::B2DPoint(aPoint.getX() - fHalfCrossSize,
aPoint.getY()),
+ basegfx::B2DPoint(aPoint.getX() + fHalfCrossSize,
aPoint.getY()),
+ getBColor()));
- if(!getSubdivisionsX() && !getSubdivisionsY())
- {
- // no subdivisions, so fall back to points at grid positions,
no need to
- // visualize a difference between divisions and sub-divisions
- aContainer.push_back(new
PointArrayPrimitive2D(std::move(aPositionsCross), getBColor()));
- }
- else
- {
- aContainer.push_back(new
MarkerArrayPrimitive2D(std::move(aPositionsCross), getCrossMarker()));
+
+ aContainer.push_back(new
SingleLinePrimitive2D(basegfx::B2DPoint(aPoint.getX(), aPoint.getY() -
fHalfCrossSize),
+ basegfx::B2DPoint(aPoint.getX(), aPoint.getY() +
fHalfCrossSize),
+ getBColor()));
+ }
}
return new GroupPrimitive2D(std::move(aContainer));
}
commit be85ad2a3f7efd534f75ba977139cf403e4be21e
Author: Tamás Zolnai <[email protected]>
AuthorDate: Thu Oct 23 10:41:11 2025 +0200
Commit: Tamás Zolnai <[email protected]>
CommitDate: Tue Oct 28 12:09:25 2025 +0100
POC: Better grid in Writer and Calc.
Change-Id: I34905cc2705bb53deb51cfa8cb4b5058c9b21208
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 3cc7d153a53f..3aeb1cd08e47 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -612,6 +612,8 @@ public:
void DrawGrid( const tools::Rectangle& rRect, const
Size& rDist, DrawGridFlags nFlags );
+ void DrawGridOfCrosses( const tools::Rectangle&
rRect, const Size& rDist, const tools::Rectangle& rCutRect, const Size&
rCrossSize);
+
///@}
/** @name Invert functions
diff --git a/include/vcl/rendercontext/DrawGridFlags.hxx
b/include/vcl/rendercontext/DrawGridFlags.hxx
index 4d783e780976..e90c8f05d348 100644
--- a/include/vcl/rendercontext/DrawGridFlags.hxx
+++ b/include/vcl/rendercontext/DrawGridFlags.hxx
@@ -26,11 +26,12 @@ enum class DrawGridFlags
NONE = 0x0000,
Dots = 0x0001,
HorzLines = 0x0002,
- VertLines = 0x0004
+ VertLines = 0x0004,
+ Crosses = 0x0008
};
namespace o3tl
{
-template <> struct typed_flags<DrawGridFlags> : is_typed_flags<DrawGridFlags,
0x0007>
+template <> struct typed_flags<DrawGridFlags> : is_typed_flags<DrawGridFlags,
0x00f>
{
};
}
diff --git a/svx/source/svdraw/svdpagv.cxx b/svx/source/svdraw/svdpagv.cxx
index 41419bc113f1..7e355cb8c8ce 100644
--- a/svx/source/svdraw/svdpagv.cxx
+++ b/svx/source/svdraw/svdpagv.cxx
@@ -461,6 +461,7 @@ void SdrPageView::DrawPageViewGrid(OutputDevice& rOut,
const tools::Rectangle& r
sal_uInt16 nGridPaintCnt=1;
if (pFrames!=nullptr) nGridPaintCnt=pFrames->GetCount();
for (sal_uInt16 nGridPaintNum=0; nGridPaintNum<nGridPaintCnt;
nGridPaintNum++) {
+ tools::Rectangle aDrawArea;
if (pFrames!=nullptr) {
const SdrPageGridFrame& rGF=(*pFrames)[nGridPaintNum];
nWrX=rGF.GetPaperRect().Left();
@@ -471,6 +472,11 @@ void SdrPageView::DrawPageViewGrid(OutputDevice& rOut,
const tools::Rectangle& r
y2=rGF.GetUserArea().Bottom();
aOrg=rGF.GetUserArea().TopLeft();
aOrg-=rGF.GetPaperRect().TopLeft();
+ aDrawArea=rGF.GetUserArea();
+ }
+ else
+ {
+ aDrawArea=tools::Rectangle{maPageOrigin, GetPage()->GetSize()};
}
if (!rRect.IsEmpty()) {
Size a1PixSiz(rOut.PixelToLogic(Size(1,1)));
@@ -500,18 +506,32 @@ void SdrPageView::DrawPageViewGrid(OutputDevice& rOut,
const tools::Rectangle& r
{
if( bHoriLines )
{
- DrawGridFlags nGridFlags = ( bHoriSolid ?
DrawGridFlags::HorzLines : DrawGridFlags::Dots );
sal_uInt16 nSteps = sal_uInt16(nx1 / nx2);
sal_uInt32 nRestPerStepMul1000 = nSteps ? ( ((nx1 * 1000)/
nSteps) - (nx2 * 1000) ) : 0;
sal_uInt32 nStepOffset = 0;
sal_uInt16 nPointOffset = 0;
+ SAL_WARN("drawGrid", "bHoriSolid: " << (bHoriSolid ? "true" :
"false"));
+ SAL_WARN("drawGrid", "nSteps: " << nSteps);
+ SAL_WARN("drawGrid", "nRestPerStepMul1000: " <<
nRestPerStepMul1000);
+ SAL_WARN("drawGrid", "nStepOffset: " << nStepOffset);
+ SAL_WARN("drawGrid", "nPointOffset: " << nPointOffset);
for(sal_uInt16 a=0;a<nSteps;a++)
{
// draw
- rOut.DrawGrid(
- tools::Rectangle( xFinOrg + (a * nx2) + nPointOffset,
yBigOrg, x2, y2 ),
- Size( nx1, ny1 ), nGridFlags );
+ if (false)
+ {
+ rOut.DrawGrid(
+ tools::Rectangle( xFinOrg + (a * nx2) +
nPointOffset, yBigOrg, x2, y2 ),
+ Size( nx1, ny1 ), DrawGridFlags::HorzLines );
+ }
+ else
+ {
+ const tools::Long nCrossSize =
std::min(GetView().maGridFin.Width(), GetView().maGridFin.Height()) / 4;
+ rOut.DrawGridOfCrosses(
+ tools::Rectangle( xFinOrg + (a * nx2) +
nPointOffset, yBigOrg, x2, y2 ),
+ Size( nx1, ny1 ), aDrawArea, Size(nCrossSize,
nCrossSize) );
+ }
// do a step
nStepOffset += nRestPerStepMul1000;
@@ -525,7 +545,6 @@ void SdrPageView::DrawPageViewGrid(OutputDevice& rOut,
const tools::Rectangle& r
if( bVertLines )
{
- DrawGridFlags nGridFlags = ( bVertSolid ?
DrawGridFlags::VertLines : DrawGridFlags::Dots );
sal_uInt16 nSteps = sal_uInt16(ny1 / ny2);
sal_uInt32 nRestPerStepMul1000 = nSteps ? ( ((ny1 * 1000L)/
nSteps) - (ny2 * 1000L) ) : 0;
sal_uInt32 nStepOffset = 0;
@@ -534,9 +553,19 @@ void SdrPageView::DrawPageViewGrid(OutputDevice& rOut,
const tools::Rectangle& r
for(sal_uInt16 a=0;a<nSteps;a++)
{
// draw
- rOut.DrawGrid(
- tools::Rectangle( xBigOrg, yFinOrg + (a * ny2) +
nPointOffset, x2, y2 ),
- Size( nx1, ny1 ), nGridFlags );
+ if (false)
+ {
+ rOut.DrawGrid(
+ tools::Rectangle( xBigOrg, yFinOrg + (a * ny2) +
nPointOffset, x2, y2 ),
+ Size( nx1, ny1 ), DrawGridFlags::VertLines );
+ }
+ else
+ {
+ const tools::Long nCrossSize =
std::min(GetView().maGridFin.Width(), GetView().maGridFin.Height()) / 4;
+ rOut.DrawGridOfCrosses(
+ tools::Rectangle( xBigOrg, yFinOrg + (a * ny2) +
nPointOffset, x2, y2 ),
+ Size( nx1, ny1 ), aDrawArea, Size(nCrossSize,
nCrossSize) );
+ }
// do a step
nStepOffset += nRestPerStepMul1000;
diff --git a/vcl/source/outdev/rect.cxx b/vcl/source/outdev/rect.cxx
index c2731237d1cf..2c98faea1f27 100644
--- a/vcl/source/outdev/rect.cxx
+++ b/vcl/source/outdev/rect.cxx
@@ -263,7 +263,7 @@ void OutputDevice::DrawGrid( const tools::Rectangle& rRect,
const Size& rDist, D
std::vector< sal_Int32 > aVertBuf;
std::vector< sal_Int32 > aHorzBuf;
- if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags &
DrawGridFlags::HorzLines ) )
+ if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::Crosses
) ||( nFlags & DrawGridFlags::HorzLines ) )
{
aVertBuf.resize( aDstRect.GetHeight() / nDistY + 2 );
aVertBuf[ nVertCount++ ] = nStartY;
@@ -273,7 +273,7 @@ void OutputDevice::DrawGrid( const tools::Rectangle& rRect,
const Size& rDist, D
}
}
- if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags &
DrawGridFlags::VertLines ) )
+ if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::Crosses
) || ( nFlags & DrawGridFlags::VertLines ) )
{
aHorzBuf.resize( aDstRect.GetWidth() / nDistX + 2 );
aHorzBuf[ nHorzCount++ ] = nStartX;
@@ -302,6 +302,20 @@ void OutputDevice::DrawGrid( const tools::Rectangle&
rRect, const Size& rDist, D
}
}
}
+ else if( nFlags & DrawGridFlags::Crosses )
+ {
+ for( tools::Long i = 0; i < nVertCount; i++ )
+ {
+ for( tools::Long j = 0, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
+ {
+ tools::Long X = aHorzBuf[ j ];
+ tools::Long crossSizeX = ImplLogicXToDevicePixel( 10 );
+ tools::Long crossSizeY = ImplLogicYToDevicePixel( 10 );
+ mpGraphics->DrawLine( X - crossSizeX, Y, X + crossSizeX, Y,
*this );
+ mpGraphics->DrawLine( X, Y - crossSizeY, X, Y + crossSizeY,
*this );
+ }
+ }
+ }
else
{
if( nFlags & DrawGridFlags::HorzLines )
@@ -326,6 +340,95 @@ void OutputDevice::DrawGrid( const tools::Rectangle&
rRect, const Size& rDist, D
EnableMapMode( bOldMap );
}
+void OutputDevice::DrawGridOfCrosses( const tools::Rectangle& rRect, const
Size& rDist, const tools::Rectangle& rCutRect, const Size& rCrossSize )
+{
+ SAL_WARN("drawGrid", "DrawGridOfCrosses");
+ assert(!is_double_buffered_window());
+
+ tools::Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
+ aDstRect.Intersection( rRect );
+
+ if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
+ return;
+
+ if( !mpGraphics && !AcquireGraphics() )
+ return;
+ assert(mpGraphics);
+
+ if( mbInitClipRegion )
+ InitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+
+ const tools::Long nDistX = std::max( rDist.Width(), tools::Long(1) );
+ const tools::Long nDistY = std::max( rDist.Height(), tools::Long(1) );
+ tools::Long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : (
rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
+ tools::Long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : (
rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
+ const tools::Long nRight = aDstRect.Right();
+ const tools::Long nBottom = aDstRect.Bottom();
+
+ std::vector< sal_Int32 > aVertBuf;
+ tools::Long nVertCount = 0;
+ aVertBuf.resize( aDstRect.GetHeight() / nDistY + 2 );
+ aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
+ while( ( nY += nDistY ) <= nBottom )
+ {
+ aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
+ }
+
+ std::vector< sal_Int32 > aHorzBuf;
+ tools::Long nHorzCount = 0;
+ aHorzBuf.resize( aDstRect.GetWidth() / nDistX + 2 );
+ aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
+ while( ( nX += nDistX ) <= nRight )
+ {
+ aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
+ }
+
+ if( mbInitLineColor )
+ InitLineColor();
+
+ if( mbInitFillColor )
+ InitFillColor();
+
+ for( tools::Long i = 0; i < nVertCount; i++ )
+ {
+ for( tools::Long j = 0; j < nHorzCount; j++ )
+ {
+ const tools::Long nXPixel = aHorzBuf[ j ];
+ const tools::Long nYPixel = aVertBuf[ i ];
+ if (nXPixel < ImplLogicXToDevicePixel(rCutRect.Left()) || nYPixel
< ImplLogicYToDevicePixel(rCutRect.Top()) ||
+ nXPixel > ImplLogicXToDevicePixel(rCutRect.Right()) || nYPixel
> ImplLogicYToDevicePixel(rCutRect.Bottom()))
+ continue;
+
+ const tools::Long crossSizeX =
ImplLogicWidthToDevicePixel(rCrossSize.Width() / 2);
+ const tools::Long crossSizeY =
ImplLogicHeightToDevicePixel(rCrossSize.Height() / 2);
+ const tools::Long nStartX = std::max(nXPixel - crossSizeX,
ImplLogicXToDevicePixel(rCutRect.Left()));
+ const tools::Long nEndX = std::min(nXPixel + crossSizeX + 1,
ImplLogicXToDevicePixel(rCutRect.Right()));
+ const tools::Long nStartY = std::max(nYPixel - crossSizeY,
ImplLogicYToDevicePixel(rCutRect.Top()));
+ const tools::Long nEndY = std::min(nYPixel + crossSizeY + 1,
ImplLogicYToDevicePixel(rCutRect.Bottom()));
+
+ const bool bOldMap = mbMap;
+ EnableMapMode( false );
+
+ mpGraphics->DrawLine( nStartX,
+ nYPixel,
+ nEndX,
+ nYPixel, *this );
+ mpGraphics->DrawLine( nXPixel,
+ nStartY,
+ nXPixel,
+ nEndY, *this );
+
+ mpGraphics->DrawPixel( nXPixel, nYPixel, *this );
+
+ EnableMapMode( bOldMap );
+ }
+ }
+
+}
+
BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
{
BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE;