23 #include <osl/diagnose.h>
40 #define HATCH_MAXPOINTS 1024
51 return ( nX1 > nX2 ? 1 : nX1 == nX2 ? nY1 > nY2 ? 1: nY1 == nY2 ? 0 : -1 : -1 );
60 Hatch aHatch( rHatch );
79 if( rPolyPoly.
Count() )
85 aPolyPoly.
Optimize( PolyOptimizeFlags::NO_SAME );
108 aPolyPoly.
Optimize( PolyOptimizeFlags::NO_SAME | PolyOptimizeFlags::CLOSE );
110 if( aPolyPoly.
Count() )
130 nVertSteps = std::numeric_limits<tools::Long>::max();
132 nVertSteps = nVertSteps / rInc.
Height();
139 nHorzSteps = std::numeric_limits<tools::Long>::max();
141 nHorzSteps = nHorzSteps / rInc.
Width();
143 auto nSteps = std::max(nVertSteps, nHorzSteps);
146 SAL_WARN(
"vcl.gdi",
"skipping slow hatch with " << nSteps <<
" steps");
156 if(!rPolyPoly.
Count())
160 bool bIsCurve(
false);
162 for(sal_uInt16
a(0); !bIsCurve &&
a < rPolyPoly.
Count();
a++)
164 if(rPolyPoly[
a].HasFlags())
172 OSL_ENSURE(
false,
"DrawHatch does *not* support curves, falling back to AdaptiveSubdivide()...");
184 Point aPt1, aPt2, aEndPt1;
188 aRect.AdjustLeft( -nLogPixelWidth ); aRect.AdjustTop( -nLogPixelWidth ); aRect.AdjustRight(nLogPixelWidth ); aRect.AdjustBottom(nLogPixelWidth );
193 if (aInc.Width() <= 0 && aInc.Height() <= 0)
194 SAL_WARN(
"vcl.gdi",
"invalid increment");
200 aPt1.AdjustX(aInc.Width() ); aPt1.AdjustY(aInc.Height() );
201 aPt2.AdjustX(aInc.Width() ); aPt2.AdjustY(aInc.Height() );
203 while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
206 if( ( rHatch.
GetStyle() == HatchStyle::Double ) || ( rHatch.
GetStyle() == HatchStyle::Triple ) )
216 aPt1.AdjustX(aInc.Width() ); aPt1.AdjustY(aInc.Height() );
217 aPt2.AdjustX(aInc.Width() ); aPt2.AdjustY(aInc.Height() );
219 while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
221 if( rHatch.
GetStyle() == HatchStyle::Triple )
231 aPt1.AdjustX(aInc.Width() ); aPt1.AdjustY(aInc.Height() );
232 aPt2.AdjustX(aInc.Width() ); aPt2.AdjustY(aInc.Height() );
234 while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
241 Point& rPt1, Point& rPt2,
Size& rInc, Point& rEndPt1 )
244 Degree10 nAngle = nAngle10 % 1800_deg10;
247 if( nAngle > 900_deg10 )
248 nAngle -= 1800_deg10;
252 if( 0_deg10 == nAngle )
254 rInc =
Size( 0, nDist );
259 if( aRef.Y() <= rRect.
Top() )
260 nOffset = ( ( rRect.
Top() - aRef.Y() ) % nDist );
262 nOffset = ( nDist - ( ( aRef.Y() - rRect.
Top() ) % nDist ) );
264 rPt1.AdjustY( -nOffset );
265 rPt2.AdjustY( -nOffset );
267 else if( 900_deg10 == nAngle )
269 rInc =
Size( nDist, 0 );
274 if( aRef.X() <= rRect.
Left() )
275 nOffset = ( rRect.
Left() - aRef.X() ) % nDist;
277 nOffset = nDist - ( ( aRef.X() - rRect.
Left() ) % nDist );
279 rPt1.AdjustX( -nOffset );
280 rPt2.AdjustX( -nOffset );
282 else if( nAngle >=
Degree10(-450) && nAngle <= 450_deg10 )
284 const double fAngle = std::abs(
toRadians(nAngle) );
285 const double fTan = tan( fAngle );
289 nDist =
FRound( nDist / cos( fAngle ) );
290 rInc =
Size( 0, nDist );
292 if( nAngle > 0_deg10 )
297 nPY =
FRound( aRef.Y() - ( ( rPt1.X() - aRef.X() ) * fTan ) );
304 nPY =
FRound( aRef.Y() + ( ( rPt1.X() - aRef.X() ) * fTan ) );
307 if( nPY <= rPt1.Y() )
308 nOffset = ( rPt1.Y() - nPY ) % nDist;
310 nOffset = nDist - ( ( nPY - rPt1.Y() ) % nDist );
312 rPt1.AdjustY( -nOffset );
313 rPt2.AdjustY( -nOffset );
317 const double fAngle = std::abs(
toRadians(nAngle) );
318 const double fTan = tan( fAngle );
322 nDist =
FRound( nDist / sin( fAngle ) );
323 rInc =
Size( nDist, 0 );
325 if( nAngle > 0_deg10 )
330 nPX =
FRound( aRef.X() - ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
337 nPX =
FRound( aRef.X() + ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
340 if( nPX <= rPt1.X() )
341 nOffset = ( rPt1.X() - nPX ) % nDist;
343 nOffset = nDist - ( ( nPX - rPt1.X() ) % nDist );
345 rPt1.AdjustX( -nOffset );
346 rPt2.AdjustX( -nOffset );
351 Point* pPtBuffer,
bool bMtf )
358 for(
tools::Long nPoly = 0, nPolyCount = rPolyPoly.
Count(); nPoly < nPolyCount; nPoly++ )
360 const tools::Polygon& rPoly = rPolyPoly[
static_cast<sal_uInt16
>(nPoly) ];
368 aCurSegment.
SetEnd( rPoly[ static_cast<sal_uInt16>(
i %
nCount ) ] );
373 if( ( fabs( fX - aCurSegment.
GetStart().X() ) <= 0.0000001 ) &&
374 ( fabs( fY - aCurSegment.
GetStart().Y() ) <= 0.0000001 ) )
376 const tools::Line aPrevSegment( rPoly[ static_cast<sal_uInt16>( (
i > 1 ) ? (
i - 2 ) : ( nCount - 1 ) ) ], aCurSegment.
GetStart() );
377 const double fPrevDistance = rLine.
GetDistance( aPrevSegment.GetStart() );
380 if( ( fPrevDistance <= 0.0 && fCurDistance > 0.0 ) ||
381 ( fPrevDistance > 0.0 && fCurDistance < 0.0 ) )
386 else if( ( fabs( fX - aCurSegment.
GetEnd().X() ) <= 0.0000001 ) &&
387 ( fabs( fY - aCurSegment.
GetEnd().Y() ) <= 0.0000001 ) )
389 const tools::Line aNextSegment( aCurSegment.
GetEnd(), rPoly[
static_cast<sal_uInt16
>( (
i + 1 ) % nCount ) ] );
391 if( ( fabs( rLine.
GetDistance( aNextSegment.GetEnd() ) ) <= 0.0000001 ) &&
404 SAL_WARN(
"vcl.gdi",
"too many hatch points");
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)
void SetDistance(tools::Long nDistance)
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
static bool HasSaneNSteps(const Point &rPt1, const Point &rEndPt1, const Size &rInc)
void DrawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2, const OutputDevice &rOutDev)
const Point & GetRefPoint() const
SAL_DLLPRIVATE void CalcHatchValues(const tools::Rectangle &rRect, tools::Long nDist, Degree10 nAngle10, Point &rPt1, Point &rPt2, Size &rInc, Point &rEndPt1)
const StyleSettings & GetStyleSettings() const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
SAL_DLLPRIVATE bool is_double_buffered_window() const
void EnableMapMode(bool bEnable=true)
constexpr tools::Long Width() const
SAL_DLLPRIVATE void InitLineColor()
HatchStyle GetStyle() const
static int HatchCmpFnc(const void *p1, const void *p2)
SalGraphics * mpGraphics
Graphics context to draw on.
tools::Long FRound(double fVal)
SAL_DLLPRIVATE void DrawHatchLine(const tools::Line &rLine, const tools::PolyPolygon &rPolyPoly, Point *pPtBuffer, bool bMtf)
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
const Color & GetColor() const
SAL_DLLPRIVATE tools::Long ImplLogicWidthToDevicePixel(tools::Long nWidth) const
Convert a logical width to a width in units of device pixels.
const AllSettings & GetSettings() const
DrawModeFlags GetDrawMode() const
void DrawHatch(const tools::PolyPolygon &rPolyPoly, const Hatch &rHatch)
virtual void DrawHatchLine_DrawLine(const Point &rStartPoint, const Point &rEndPoint)
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
VclPtr< VirtualDevice > mpAlphaVDev
constexpr tools::Long Height() const
virtual void InitClipRegion()
void AddHatchActions(const tools::PolyPolygon &rPolyPoly, const Hatch &rHatch, GDIMetaFile &rMtf)
tools::Long GetDistance() const
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
Color GetHatchColor(Color const &rColor, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
#define SAL_WARN(area, stream)
Degree10 GetAngle() const
SAL_DLLPRIVATE tools::Long ImplDevicePixelToLogicWidth(tools::Long nWidth) const
Convert device pixels to a width in logical units.
bool IsDeviceOutputNecessary() const
void SetColor(const Color &rColor)