41#define UNDERLINE_LAST LINESTYLE_BOLDWAVE
42#define STRIKEOUT_LAST STRIKEOUT_X
45 struct WavyLineCache final
47 WavyLineCache () : m_aItems( 10 ) {}
51 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
52 auto item = m_aItems.find( aKey );
53 if ( item == m_aItems.end() )
56 if ( item->second.m_aLineWidth !=
nLineWidth || item->second.m_aWordWidth < nWordWidth )
60 rOutput = item->second.m_Bitmap;
64 void insert(
const BitmapEx& aBitmap,
const Color& aLineColor,
const size_t nLineWidth,
const size_t nWaveHeight,
const size_t nWordWidth,
BitmapEx& rOutput )
66 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
67 m_aItems.insert( std::pair< Key, WavyLineCacheItem>( aKey, {
nLineWidth, nWordWidth, aBitmap } ) );
72 struct WavyLineCacheItem
85 return ( m_aFirst == rOther.m_aFirst && m_aSecond == rOther.m_aSecond );
91 size_t operator() (
const Key& rKey )
const
124 Point aPoint( nOriginX, nOriginY );
125 aPoint.RotateAround( nCurX, nCurY, nOrientation );
130 pGraphics->
DrawRect( nCurX, nCurY, nPixWidth, nPixHeight, rOutDev );
134 pGraphics->
DrawPixel( nCurX, nCurY, rOutDev );
179 const Color& rColor )
197 Point aOriginPt( nBaseX, nBaseY );
198 aOriginPt.RotateAround( nStartX, nStartY, nOrientation );
199 aOriginPt.RotateAround( nEndX, nEndY, nOrientation );
224 nPixWidth, nPixHeight );
239 nPixWidth, nPixHeight );
247 nPixWidth, nPixHeight );
252 nFreq =
nCount % (nDiffX+nDiffY);
259 nPixWidth, nPixHeight );
268 nPixWidth, nPixHeight );
288 nLineHeight = pFontInstance->
mxFontMetric->GetAboveWavelineUnderlineSize();
289 nLinePos = pFontInstance->
mxFontMetric->GetAboveWavelineUnderlineOffset();
293 nLineHeight = pFontInstance->
mxFontMetric->GetWavelineUnderlineSize();
294 nLinePos = pFontInstance->
mxFontMetric->GetWavelineUnderlineOffset();
306 nLinePos += nDistY - (nLineHeight / 2);
313 if ( nLineHeight < 2 )
315 if ( nOrgLineHeight > 1 )
321 tools::Long nLineDY = nOrgLineHeight-(nLineHeight*2);
322 if ( nLineDY < nLineWidthHeight )
323 nLineDY = nLineWidthHeight;
329 nLinePos -= nLineWidthHeight-nLineDY2;
332 nLinePos += nLineWidthHeight+nLineDY;
338 nLinePos -= nLineWidthHeight/2;
370 nLineHeight = pFontInstance->
mxFontMetric->GetAboveUnderlineSize();
371 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveUnderlineOffset();
375 nLineHeight = pFontInstance->
mxFontMetric->GetUnderlineSize();
376 nLinePos = nY + pFontInstance->
mxFontMetric->GetUnderlineOffset();
387 nLineHeight = pFontInstance->
mxFontMetric->GetAboveBoldUnderlineSize();
388 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveBoldUnderlineOffset();
392 nLineHeight = pFontInstance->
mxFontMetric->GetBoldUnderlineSize();
393 nLinePos = nY + pFontInstance->
mxFontMetric->GetBoldUnderlineOffset();
399 nLineHeight = pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineSize();
400 nLinePos = nY + pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineOffset1();
401 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetAboveDoubleUnderlineOffset2();
405 nLineHeight = pFontInstance->
mxFontMetric->GetDoubleUnderlineSize();
406 nLinePos = nY + pFontInstance->
mxFontMetric->GetDoubleUnderlineOffset1();
407 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetDoubleUnderlineOffset2();
446 while ( nLeft < nEnd )
448 if ( nLeft+nTempWidth > nEnd )
449 nTempWidth = nEnd-nLeft;
451 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
452 nLeft += nDotWidth*2;
472 nMinDashWidth = nDotWidth*6;
473 nMinSpaceWidth = nDotWidth*2;
479 nMinDashWidth = nDotWidth*4;
480 nMinSpaceWidth = (nDotWidth*150)/100;
484 nDashWidth = ((nDashWidth*
mnDPIX)+1270)/2540;
485 nSpaceWidth = ((nSpaceWidth*
mnDPIX)+1270)/2540;
488 if ( nDashWidth < nMinDashWidth )
489 nDashWidth = nMinDashWidth;
490 if ( nSpaceWidth < nMinSpaceWidth )
491 nSpaceWidth = nMinSpaceWidth;
495 while ( nLeft < nEnd )
497 if ( nLeft+nTempWidth > nEnd )
498 nTempWidth = nEnd-nLeft;
499 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
500 nLeft += nDashWidth+nSpaceWidth;
515 if ( nDashWidth < nMinDashWidth )
516 nDashWidth = nMinDashWidth;
521 while ( nLeft < nEnd )
523 if ( nLeft+nTempDotWidth > nEnd )
524 nTempDotWidth = nEnd-nLeft;
526 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
527 nLeft += nDotWidth*2;
531 if ( nLeft+nTempDashWidth > nEnd )
532 nTempDashWidth = nEnd-nLeft;
534 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
535 nLeft += nDashWidth+nDotWidth;
550 if ( nDashWidth < nMinDashWidth )
551 nDashWidth = nMinDashWidth;
556 while ( nLeft < nEnd )
558 if ( nLeft+nTempDotWidth > nEnd )
559 nTempDotWidth = nEnd-nLeft;
561 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
562 nLeft += nDotWidth*2;
566 if ( nLeft+nTempDotWidth > nEnd )
567 nTempDotWidth = nEnd-nLeft;
569 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
570 nLeft += nDotWidth*2;
574 if ( nLeft+nTempDashWidth > nEnd )
575 nTempDashWidth = nEnd-nLeft;
577 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
578 nLeft += nDashWidth+nDotWidth;
602 switch ( eStrikeout )
605 nLineHeight = pFontInstance->
mxFontMetric->GetStrikeoutSize();
606 nLinePos = nY + pFontInstance->
mxFontMetric->GetStrikeoutOffset();
609 nLineHeight = pFontInstance->
mxFontMetric->GetBoldStrikeoutSize();
610 nLinePos = nY + pFontInstance->
mxFontMetric->GetBoldStrikeoutOffset();
613 nLineHeight = pFontInstance->
mxFontMetric->GetDoubleStrikeoutSize();
614 nLinePos = nY + pFontInstance->
mxFontMetric->GetDoubleStrikeoutOffset1();
615 nLinePos2 = nY + pFontInstance->
mxFontMetric->GetDoubleStrikeoutOffset2();
634 switch ( eStrikeout )
661 static const int nTestStrLen = 4;
662 static const int nMaxStrikeStrLen = 2048;
665 for(
int i = 0;
i < nTestStrLen; ++
i)
666 aChars[
i] = cStrikeoutChar;
668 const OUString aStrikeoutTest(aChars, nTestStrLen);
672 std::unique_ptr<SalLayout> pLayout =
ImplLayout( aStrikeoutTest, 0, nTestStrLen );
675 nStrikeoutWidth = pLayout->GetTextWidth() / (nTestStrLen * pLayout->GetUnitsPerPixel());
677 if( nStrikeoutWidth <= 0 )
680 int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
681 if( nStrikeStrLen > nMaxStrikeStrLen )
682 nStrikeStrLen = nMaxStrikeStrLen;
683 else if (nStrikeStrLen < 0)
687 for(
int i = nTestStrLen;
i < nStrikeStrLen; ++
i)
688 aChars[
i] = cStrikeoutChar;
690 const OUString aStrikeoutText(aChars, nStrikeStrLen);
694 Point aOriginPt(0, 0);
695 aOriginPt.RotateAround( nDistX, nDistY,
mpFontInstance->mnOrientation );
704 pLayout =
ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
748 bool bUnderlineAbove )
756 bool bStrikeoutDone =
false;
757 bool bUnderlineDone =
false;
758 bool bOverlineDone =
false;
780 ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
781 bUnderlineDone =
true;
789 bOverlineDone =
true;
796 bStrikeoutDone =
true;
799 if ( !bUnderlineDone )
802 if ( !bOverlineDone )
805 if ( !bStrikeoutDone )
811 bool bWordLine,
bool bUnderlineAbove )
832 nDist = aPos.
getX() - aStartPt.
getX();
837 nDist =
FRound( nDist*cos(fRad) - nDY*sin(fRad) );
844 else if( nWidth > 0 )
848 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
857 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
865 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
877 nX = nBaseX - nWidth - (nX - nBaseX - 1);
937 bool bUnderlineAbove )
968 ImplDrawTextLine( aPos.X(), aPos.X(), 0, fWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
1002 double fOrientation = 0.0;
1005 if (nStartY != nEndY || nStartX > nEndX)
1007 fOrientation =
basegfx::rad2deg(std::atan2(nStartY - nEndY, nEndX - nStartX));
1009 aStartPt.RotateAround(nEndX, nEndY,
Degree10(
static_cast<sal_Int16
>(-fOrientation * 10.0)));
1014 if (fScaleFactor > 1.0f)
1016 nWaveHeight *= fScaleFactor;
1018 nStartY += fScaleFactor - 1;
1021 if (nWaveHeight % 2 == 0)
1029 if (nWaveHeight > pFontInstance->
mxFontMetric->GetWavelineUnderlineSize())
1031 nWaveHeight = pFontInstance->
mxFontMetric->GetWavelineUnderlineSize();
1036 if ( fOrientation == 0.0 )
1039 if ( !snLineCache.get() )
1041 WavyLineCache& rLineCache = *snLineCache.
get();
1045 size_t nWordLength = nEndX - nStartX;
1047 nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
1050 pVirtDev->SetOutputSizePixel(
Size( nWordLength, nWaveHeight * 2 ),
false );
1055 pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, nWaveHeight, fOrientation,
nLineWidth );
1056 BitmapEx aBitmapEx(pVirtDev->GetBitmapEx(
Point(0, 0), pVirtDev->GetOutputSize()));
1108 css::drawing::LineCap_BUTT,
AlphaMask GetAlpha() 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.
DeviceCoordinate newWidth() const
ImplFontMetricDataRef 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
bool IsRTLEnabled() const
SAL_DLLPRIVATE DeviceCoordinate LogicWidthToDeviceCoordinate(tools::Long nWidth) const
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 ImplDrawTextLine(tools::Long nBaseX, tools::Long nX, tools::Long nY, DeviceCoordinate nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove)
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)
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
std::unique_ptr< SalLayout > ImplLayout(const OUString &, sal_Int32 nIndex, sal_Int32 nLen, const Point &rLogicPos=Point(0, 0), tools::Long nLogicWidth=0, o3tl::span< const sal_Int32 > pLogicDXArray={}, SalLayoutFlags flags=SalLayoutFlags::NONE, vcl::text::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) 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)
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)
DevicePoint GetDrawPosition(const DevicePoint &rRelative=DevicePoint(0, 0)) const
int GetUnitsPerPixel() const
virtual bool GetNextGlyph(const GlyphItem **pGlyph, DevicePoint &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr, const vcl::font::PhysicalFontFace **pFallbackFont=nullptr) const =0
virtual DeviceCoordinate GetTextWidth() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
sal_Int32 DeviceCoordinate
basegfx::B2DPoint DevicePoint
tools::Long FRound(double fVal)
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)