38#define UNDERLINE_LAST LINESTYLE_BOLDWAVE
39#define STRIKEOUT_LAST STRIKEOUT_X
42 struct WavyLineCache final
44 WavyLineCache () : m_aItems( 10 ) {}
48 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
49 auto item = m_aItems.find( aKey );
50 if ( item == m_aItems.end() )
53 if ( item->second.m_aLineWidth !=
nLineWidth || item->second.m_aWordWidth < nWordWidth )
57 rOutput = item->second.m_Bitmap;
61 void insert(
const BitmapEx& aBitmap,
const Color& aLineColor,
const size_t nLineWidth,
const size_t nWaveHeight,
const size_t nWordWidth,
BitmapEx& rOutput )
63 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
64 m_aItems.insert( std::pair< Key, WavyLineCacheItem>( aKey, {
nLineWidth, nWordWidth, aBitmap } ) );
69 struct WavyLineCacheItem
82 return ( m_aFirst == rOther.m_aFirst && m_aSecond == rOther.m_aSecond );
88 size_t operator() (
const Key& rKey )
const
121 Point aPoint( nOriginX, nOriginY );
127 pGraphics->
DrawRect( nCurX, nCurY, nPixWidth, nPixHeight, rOutDev );
131 pGraphics->
DrawPixel( nCurX, nCurY, rOutDev );
176 const Color& rColor )
194 Point aOriginPt( nBaseX, nBaseY );
195 aOriginPt.
RotateAround( nStartX, nStartY, nOrientation );
221 nPixWidth, nPixHeight );
236 nPixWidth, nPixHeight );
244 nPixWidth, nPixHeight );
249 nFreq =
nCount % (nDiffX+nDiffY);
256 nPixWidth, nPixHeight );
265 nPixWidth, nPixHeight );
280 if (bFuzzing && nWidth > 20000)
282 SAL_WARN(
"vcl.gdi",
"drawLine, skipping suspicious WaveTextLine of length: "
283 << nWidth <<
" for fuzzing performance");
293 nLineHeight = pFontInstance->
mxFontMetric->GetAboveWavelineUnderlineSize();
294 nLinePos = pFontInstance->
mxFontMetric->GetAboveWavelineUnderlineOffset();
298 nLineHeight = pFontInstance->
mxFontMetric->GetWavelineUnderlineSize();
299 nLinePos = pFontInstance->
mxFontMetric->GetWavelineUnderlineOffset();
311 nLinePos += nDistY - (nLineHeight / 2);
318 if ( nLineHeight < 2 )
320 if ( nOrgLineHeight > 1 )
326 tools::Long nLineDY = nOrgLineHeight-(nLineHeight*2);
327 if ( nLineDY < nLineWidthHeight )
328 nLineDY = nLineWidthHeight;
334 nLinePos -= nLineWidthHeight-nLineDY2;
337 nLinePos += nLineWidthHeight+nLineDY;
343 nLinePos -= nLineWidthHeight/2;
356 if (bFuzzing && nWidth > 100000)
358 SAL_WARN(
"vcl.gdi",
"drawLine, skipping suspicious TextLine of length: "
359 << nWidth <<
" for fuzzing performance");
383 nLineHeight = pFontInstance->
mxFontMetric->GetAboveUnderlineSize();
384 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveUnderlineOffset();
388 nLineHeight = pFontInstance->
mxFontMetric->GetUnderlineSize();
389 nLinePos = nY + pFontInstance->
mxFontMetric->GetUnderlineOffset();
400 nLineHeight = pFontInstance->
mxFontMetric->GetAboveBoldUnderlineSize();
401 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveBoldUnderlineOffset();
405 nLineHeight = pFontInstance->
mxFontMetric->GetBoldUnderlineSize();
406 nLinePos = nY + pFontInstance->
mxFontMetric->GetBoldUnderlineOffset();
412 nLineHeight = pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineSize();
413 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineOffset1();
414 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineOffset2();
418 nLineHeight = pFontInstance->
mxFontMetric->GetDoubleUnderlineSize();
419 nLinePos = nY + pFontInstance->
mxFontMetric->GetDoubleUnderlineOffset1();
420 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetDoubleUnderlineOffset2();
459 while ( nLeft < nEnd )
461 if ( nLeft+nTempWidth > nEnd )
462 nTempWidth = nEnd-nLeft;
464 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
465 nLeft += nDotWidth*2;
485 nMinDashWidth = nDotWidth*6;
486 nMinSpaceWidth = nDotWidth*2;
492 nMinDashWidth = nDotWidth*4;
493 nMinSpaceWidth = (nDotWidth*150)/100;
497 nDashWidth = ((nDashWidth*
mnDPIX)+1270)/2540;
498 nSpaceWidth = ((nSpaceWidth*
mnDPIX)+1270)/2540;
501 if ( nDashWidth < nMinDashWidth )
502 nDashWidth = nMinDashWidth;
503 if ( nSpaceWidth < nMinSpaceWidth )
504 nSpaceWidth = nMinSpaceWidth;
508 while ( nLeft < nEnd )
510 if ( nLeft+nTempWidth > nEnd )
511 nTempWidth = nEnd-nLeft;
512 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
513 nLeft += nDashWidth+nSpaceWidth;
528 if ( nDashWidth < nMinDashWidth )
529 nDashWidth = nMinDashWidth;
534 while ( nLeft < nEnd )
536 if ( nLeft+nTempDotWidth > nEnd )
537 nTempDotWidth = nEnd-nLeft;
539 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
540 nLeft += nDotWidth*2;
544 if ( nLeft+nTempDashWidth > nEnd )
545 nTempDashWidth = nEnd-nLeft;
547 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
548 nLeft += nDashWidth+nDotWidth;
563 if ( nDashWidth < nMinDashWidth )
564 nDashWidth = nMinDashWidth;
569 while ( nLeft < nEnd )
571 if ( nLeft+nTempDotWidth > nEnd )
572 nTempDotWidth = nEnd-nLeft;
574 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
575 nLeft += nDotWidth*2;
579 if ( nLeft+nTempDotWidth > nEnd )
580 nTempDotWidth = nEnd-nLeft;
582 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
583 nLeft += nDotWidth*2;
587 if ( nLeft+nTempDashWidth > nEnd )
588 nTempDashWidth = nEnd-nLeft;
590 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
591 nLeft += nDashWidth+nDotWidth;
615 switch ( eStrikeout )
618 nLineHeight = pFontInstance->
mxFontMetric->GetStrikeoutSize();
619 nLinePos = nY + pFontInstance->
mxFontMetric->GetStrikeoutOffset();
622 nLineHeight = pFontInstance->
mxFontMetric->GetBoldStrikeoutSize();
623 nLinePos = nY + pFontInstance->
mxFontMetric->GetBoldStrikeoutOffset();
626 nLineHeight = pFontInstance->
mxFontMetric->GetDoubleStrikeoutSize();
627 nLinePos = nY + pFontInstance->
mxFontMetric->GetDoubleStrikeoutOffset1();
628 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetDoubleStrikeoutOffset2();
647 switch ( eStrikeout )
674 static const int nTestStrLen = 4;
675 static const int nMaxStrikeStrLen = 2048;
678 for(
int i = 0;
i < nTestStrLen; ++
i)
679 aChars[
i] = cStrikeoutChar;
681 const OUString aStrikeoutTest(aChars, nTestStrLen);
685 std::unique_ptr<SalLayout> pLayout =
ImplLayout( aStrikeoutTest, 0, nTestStrLen );
688 nStrikeoutWidth = pLayout->GetTextWidth() / nTestStrLen;
690 if( nStrikeoutWidth <= 0 )
693 int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
694 if( nStrikeStrLen > nMaxStrikeStrLen )
695 nStrikeStrLen = nMaxStrikeStrLen;
696 else if (nStrikeStrLen < 0)
700 for(
int i = nTestStrLen;
i < nStrikeStrLen; ++
i)
701 aChars[
i] = cStrikeoutChar;
703 const OUString aStrikeoutText(aChars, nStrikeStrLen);
707 Point aOriginPt(0, 0);
717 pLayout =
ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
761 bool bUnderlineAbove )
769 bool bStrikeoutDone =
false;
770 bool bUnderlineDone =
false;
771 bool bOverlineDone =
false;
793 ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
794 bUnderlineDone =
true;
802 bOverlineDone =
true;
809 bStrikeoutDone =
true;
812 if ( !bUnderlineDone )
815 if ( !bOverlineDone )
818 if ( !bStrikeoutDone )
824 bool bWordLine,
bool bUnderlineAbove )
845 nDist = aPos.
getX() - aStartPt.
getX();
848 const double nDY = aPos.
getY() - aStartPt.
getY();
850 nDist =
FRound( nDist*cos(fRad) - nDY*sin(fRad) );
857 else if( nWidth > 0 )
861 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
870 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
878 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
888 nX = nBaseX - nWidth - (nX - nBaseX - 1);
948 bool bUnderlineAbove )
978 ImplDrawTextLine( aPos.
X(), aPos.
X(), 0, fWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
1012 double fOrientation = 0.0;
1015 if (nStartY != nEndY || nStartX > nEndX)
1017 fOrientation =
basegfx::rad2deg(std::atan2(nStartY - nEndY, nEndX - nStartX));
1024 if (fScaleFactor > 1.0f)
1026 nWaveHeight *= fScaleFactor;
1028 nStartY += fScaleFactor - 1;
1031 if (nWaveHeight % 2 == 0)
1039 if (nWaveHeight > pFontInstance->
mxFontMetric->GetWavelineUnderlineSize())
1041 nWaveHeight = pFontInstance->
mxFontMetric->GetWavelineUnderlineSize();
1046 if ( fOrientation == 0.0 )
1049 if ( !snLineCache.get() )
1051 WavyLineCache& rLineCache = *snLineCache.
get();
1055 size_t nWordLength = nEndX - nStartX;
1057 nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
1059 pVirtDev->SetOutputSizePixel(
Size( nWordLength, nWaveHeight * 2 ),
false );
1064 pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, nWaveHeight, fOrientation,
nLineWidth );
1065 BitmapEx aBitmapEx(pVirtDev->GetBitmapEx(
Point(0, 0), pVirtDev->GetOutputSize()));
1117 css::drawing::LineCap_BUTT,
const AlphaMask & GetAlphaMask() const
SAL_DLLPRIVATE std::shared_ptr< SalBitmap > const & ImplGetBitmapSalBitmap() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const Size & GetSizePixel() const
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
FontMetricDataRef mxFontMetric
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
virtual void InitClipRegion()
void ImplDrawTextLines(SalLayout &, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bWordLine, bool bUnderlineAbove)
SAL_DLLPRIVATE void ImplDrawStrikeoutLine(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor)
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
bool IsOverlineColor() const
SAL_DLLPRIVATE bool is_double_buffered_window() const
float GetDPIScaleFactor() const
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
void DrawWaveLine(const Point &rStartPos, const Point &rEndPos, tools::Long nLineWidth=1, tools::Long nWaveHeight=3)
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
SAL_DLLPRIVATE void ImplDrawStrikeoutChar(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor)
SAL_DLLPRIVATE void ImplDrawWaveLineBezier(tools::Long nStartX, tools::Long nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long nWaveHeight, double fOrientation, tools::Long nLineWidth)
SAL_DLLPRIVATE void ImplDrawWaveTextLine(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove)
virtual bool shouldDrawWavePixelAsRect(tools::Long nLineWidth) const
vcl::text::ComplexTextLayoutFlags mnTextLayoutMode
virtual Size GetWaveLineSize(tools::Long nLineWidth) const
const Color & GetOverlineColor() const
SalGraphics * mpGraphics
Graphics context to draw on.
void SetTextColor(const Color &rColor)
void DrawTextLine(const Point &rPos, tools::Long nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove=false)
rtl::Reference< LogicalFontInstance > mpFontInstance
SAL_DLLPRIVATE double ImplLogicWidthToDeviceSubPixel(tools::Long nWidth) const
bool IsRTLEnabled() const
void ImplDrawTextLine(tools::Long nBaseX, tools::Long nX, tools::Long nY, double nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove)
virtual void SetWaveLineColors(Color const &rColor, tools::Long nLineWidth)
AntialiasingFlags mnAntialiasing
SAL_DLLPRIVATE void ImplInitTextLineSize()
const Color & GetLineColor() const
bool IsDeviceOutputNecessary() const
VclPtr< VirtualDevice > mpAlphaVDev
const Color & GetTextColor() const
SAL_DLLPRIVATE void ImplInitAboveTextLineSize()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
SAL_DLLPRIVATE void ImplInitTextColor()
SAL_DLLPRIVATE void ImplDrawWavePixel(tools::Long nOriginX, tools::Long nOriginY, tools::Long nCurX, tools::Long nCurY, tools::Long nWidth, Degree10 nOrientation, SalGraphics *pGraphics, const OutputDevice &rOutDev, tools::Long nPixWidth, tools::Long nPixHeight)
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, KernArraySpan aKernArray=KernArraySpan(), o3tl::span< const sal_Bool > pKashidaArray={}, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::text::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
SAL_DLLPRIVATE void ImplDrawStraightTextLine(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontLineStyle eTextLine, Color aColor, bool bIsAbove)
tools::Long mnTextOffX
font specific text alignment offsets in pixel units
SAL_DLLPRIVATE void ImplDrawTextRect(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight)
DrawModeFlags GetDrawMode() const
bool IsTextLineColor() const
const AllSettings & GetSettings() const
void IntersectClipRegion(const tools::Rectangle &rRect)
SAL_DLLPRIVATE void ImplDrawMnemonicLine(tools::Long nX, tools::Long nY, tools::Long nWidth)
const Color & GetTextLineColor() const
SAL_DLLPRIVATE bool InitFont() const
SAL_DLLPRIVATE void ImplDrawWaveLine(tools::Long nBaseX, tools::Long nBaseY, tools::Long nStartX, tools::Long nStartY, tools::Long nWidth, tools::Long nHeight, tools::Long nLineWidth, Degree10 nOrientation, const Color &rColor)
constexpr tools::Long Y() const
void RotateAround(tools::Long &rX, tools::Long &rY, Degree10 nOrientation) const
constexpr tools::Long X() const
void DrawPixel(tools::Long nX, tools::Long nY, const OutputDevice &rOutDev)
virtual void SetLineColor()=0
virtual void SetFillColor()=0
void DrawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2, const OutputDevice &rOutDev)
void DrawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, const OutputDevice &rOutDev)
void DrawPolyLine(sal_uInt32 nPoints, Point const *pPtAry, const OutputDevice &rOutDev)
virtual double GetTextWidth() const
basegfx::B2DPoint GetDrawPosition(const basegfx::B2DPoint &rRelative=basegfx::B2DPoint(0, 0)) const
basegfx::B2DPoint & DrawBase()
virtual bool GetNextGlyph(const GlyphItem **pGlyph, basegfx::B2DPoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr) const =0
constexpr tools::Long Height() const
constexpr tools::Long Width() const
constexpr ::Color COL_ALPHA_OPAQUE(0xff, 0xff, 0xff)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
tools::Long FRound(double fVal)
#define SAL_WARN(area, stream)
B2DHomMatrix createRotateAroundPoint(double fPointX, double fPointY, double fRadiant)
constexpr double rad2deg(double v)
BASEGFX_DLLPUBLIC B2DPolygon createWaveLinePolygon(basegfx::B2DRectangle const &rRectangle)
constexpr double deg2rad(double v)
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
Color GetTextColor(Color const &rColor, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
bool operator==(const ItalicMatrix &a, const ItalicMatrix &b)