LibreOffice Module vcl (master) 1
textline.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/types.h>
23#include <tools/helpers.hxx>
24#include <o3tl/hash_combine.hxx>
25#include <o3tl/lru_map.hxx>
27#include <vcl/lazydelete.hxx>
28#include <vcl/metaact.hxx>
29#include <vcl/settings.hxx>
30#include <vcl/virdev.hxx>
31
32#include <drawmode.hxx>
33#include <salgdi.hxx>
34#include <impglyphitem.hxx>
35
36#include <cassert>
37
38#define UNDERLINE_LAST LINESTYLE_BOLDWAVE
39#define STRIKEOUT_LAST STRIKEOUT_X
40
41namespace {
42 struct WavyLineCache final
43 {
44 WavyLineCache () : m_aItems( 10 ) {}
45
46 bool find( Color aLineColor, size_t nLineWidth, size_t nWaveHeight, size_t nWordWidth, BitmapEx& rOutput )
47 {
48 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
49 auto item = m_aItems.find( aKey );
50 if ( item == m_aItems.end() )
51 return false;
52 // needs update
53 if ( item->second.m_aLineWidth != nLineWidth || item->second.m_aWordWidth < nWordWidth )
54 {
55 return false;
56 }
57 rOutput = item->second.m_Bitmap;
58 return true;
59 }
60
61 void insert( const BitmapEx& aBitmap, const Color& aLineColor, const size_t nLineWidth, const size_t nWaveHeight, const size_t nWordWidth, BitmapEx& rOutput )
62 {
63 Key aKey = { nWaveHeight, sal_uInt32(aLineColor) };
64 m_aItems.insert( std::pair< Key, WavyLineCacheItem>( aKey, { nLineWidth, nWordWidth, aBitmap } ) );
65 rOutput = aBitmap;
66 }
67
68 private:
69 struct WavyLineCacheItem
70 {
71 size_t m_aLineWidth;
72 size_t m_aWordWidth;
73 BitmapEx m_Bitmap;
74 };
75
76 struct Key
77 {
78 size_t m_aFirst;
79 size_t m_aSecond;
80 bool operator ==( const Key& rOther ) const
81 {
82 return ( m_aFirst == rOther.m_aFirst && m_aSecond == rOther.m_aSecond );
83 }
84 };
85
86 struct Hash
87 {
88 size_t operator() ( const Key& rKey ) const
89 {
90 size_t aSeed = 0;
91 o3tl::hash_combine(aSeed, rKey.m_aFirst);
92 o3tl::hash_combine(aSeed, rKey.m_aSecond);
93 return aSeed;
94 }
95 };
96
98 };
99}
100
102{
103 mpFontInstance->mxFontMetric->ImplInitTextLineSize( this );
104}
105
107{
108 mpFontInstance->mxFontMetric->ImplInitAboveTextLineSize( this );
109}
110
112 tools::Long nCurX, tools::Long nCurY,
113 tools::Long nWidth,
114 Degree10 nOrientation,
115 SalGraphics* pGraphics,
116 const OutputDevice& rOutDev,
117 tools::Long nPixWidth, tools::Long nPixHeight )
118{
119 if (nOrientation)
120 {
121 Point aPoint( nOriginX, nOriginY );
122 aPoint.RotateAround( nCurX, nCurY, nOrientation );
123 }
124
125 if (shouldDrawWavePixelAsRect(nWidth))
126 {
127 pGraphics->DrawRect( nCurX, nCurY, nPixWidth, nPixHeight, rOutDev );
128 }
129 else
130 {
131 pGraphics->DrawPixel( nCurX, nCurY, rOutDev );
132 }
133}
134
136{
137 if (nLineWidth > 1)
138 return true;
139
140 return false;
141}
142
143void OutputDevice::SetWaveLineColors(Color const& rColor, tools::Long nLineWidth)
144{
145 // On printers that output pixel via DrawRect()
146 if (nLineWidth > 1)
147 {
149 {
151 mbInitLineColor = true;
152 }
153
154 mpGraphics->SetFillColor( rColor );
155 mbInitFillColor = true;
156 }
157 else
158 {
159 mpGraphics->SetLineColor( rColor );
160 mbInitLineColor = true;
161 }
162}
163
165{
166 if (nLineWidth > 1)
167 return Size(nLineWidth, ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY);
168
169 return Size(1, 1);
170}
171
173 tools::Long nDistX, tools::Long nDistY,
174 tools::Long nWidth, tools::Long nHeight,
175 tools::Long nLineWidth, Degree10 nOrientation,
176 const Color& rColor )
177{
178 if ( !nHeight )
179 return;
180
181 tools::Long nStartX = nBaseX + nDistX;
182 tools::Long nStartY = nBaseY + nDistY;
183
184 // If the height is 1 pixel, it's enough output a line
185 if ( (nLineWidth == 1) && (nHeight == 1) )
186 {
187 mpGraphics->SetLineColor( rColor );
188 mbInitLineColor = true;
189
190 tools::Long nEndX = nStartX+nWidth;
191 tools::Long nEndY = nStartY;
192 if ( nOrientation )
193 {
194 Point aOriginPt( nBaseX, nBaseY );
195 aOriginPt.RotateAround( nStartX, nStartY, nOrientation );
196 aOriginPt.RotateAround( nEndX, nEndY, nOrientation );
197 }
198 mpGraphics->DrawLine( nStartX, nStartY, nEndX, nEndY, *this );
199 }
200 else
201 {
202 tools::Long nCurX = nStartX;
203 tools::Long nCurY = nStartY;
204 tools::Long nDiffX = 2;
205 tools::Long nDiffY = nHeight-1;
206 tools::Long nCount = nWidth;
207 tools::Long nOffY = -1;
208
211
212 tools::Long nPixWidth = aSize.Width();
213 tools::Long nPixHeight = aSize.Height();
214
215 if ( !nDiffY )
216 {
217 while ( nWidth )
218 {
219 ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nLineWidth, nOrientation,
220 mpGraphics, *this,
221 nPixWidth, nPixHeight );
222 nCurX++;
223 nWidth--;
224 }
225 }
226 else
227 {
228 nCurY += nDiffY;
229 tools::Long nFreq = nCount / (nDiffX+nDiffY);
230 while ( nFreq-- )
231 {
232 for( tools::Long i = nDiffY; i; --i )
233 {
234 ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nLineWidth, nOrientation,
235 mpGraphics, *this,
236 nPixWidth, nPixHeight );
237 nCurX++;
238 nCurY += nOffY;
239 }
240 for( tools::Long i = nDiffX; i; --i )
241 {
242 ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nLineWidth, nOrientation,
243 mpGraphics, *this,
244 nPixWidth, nPixHeight );
245 nCurX++;
246 }
247 nOffY = -nOffY;
248 }
249 nFreq = nCount % (nDiffX+nDiffY);
250 if ( nFreq )
251 {
252 for( tools::Long i = nDiffY; i && nFreq; --i, --nFreq )
253 {
254 ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nLineWidth, nOrientation,
255 mpGraphics, *this,
256 nPixWidth, nPixHeight );
257 nCurX++;
258 nCurY += nOffY;
259
260 }
261 for( tools::Long i = nDiffX; i && nFreq; --i, --nFreq )
262 {
263 ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nLineWidth, nOrientation,
264 mpGraphics, *this,
265 nPixWidth, nPixHeight );
266 nCurX++;
267 }
268 }
269 }
270 }
271}
272
274 tools::Long nDistX, tools::Long nDistY, tools::Long nWidth,
275 FontLineStyle eTextLine,
276 Color aColor,
277 bool bIsAbove )
278{
279 static bool bFuzzing = utl::ConfigManager::IsFuzzing();
280 if (bFuzzing && nWidth > 20000)
281 {
282 SAL_WARN("vcl.gdi", "drawLine, skipping suspicious WaveTextLine of length: "
283 << nWidth << " for fuzzing performance");
284 return;
285 }
286
287 LogicalFontInstance* pFontInstance = mpFontInstance.get();
288 tools::Long nLineHeight;
289 tools::Long nLinePos;
290
291 if ( bIsAbove )
292 {
293 nLineHeight = pFontInstance->mxFontMetric->GetAboveWavelineUnderlineSize();
294 nLinePos = pFontInstance->mxFontMetric->GetAboveWavelineUnderlineOffset();
295 }
296 else
297 {
298 nLineHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
299 nLinePos = pFontInstance->mxFontMetric->GetWavelineUnderlineOffset();
300 }
301 if ( (eTextLine == LINESTYLE_SMALLWAVE) && (nLineHeight > 3) )
302 nLineHeight = 3;
303
305 if ( !nLineWidth )
306 nLineWidth = 1;
307
308 if ( eTextLine == LINESTYLE_BOLDWAVE )
309 nLineWidth *= 2;
310
311 nLinePos += nDistY - (nLineHeight / 2);
312
313 tools::Long nLineWidthHeight = ((nLineWidth * mnDPIX) + (mnDPIY / 2)) / mnDPIY;
314 if ( eTextLine == LINESTYLE_DOUBLEWAVE )
315 {
316 tools::Long nOrgLineHeight = nLineHeight;
317 nLineHeight /= 3;
318 if ( nLineHeight < 2 )
319 {
320 if ( nOrgLineHeight > 1 )
321 nLineHeight = 2;
322 else
323 nLineHeight = 1;
324 }
325
326 tools::Long nLineDY = nOrgLineHeight-(nLineHeight*2);
327 if ( nLineDY < nLineWidthHeight )
328 nLineDY = nLineWidthHeight;
329
330 tools::Long nLineDY2 = nLineDY/2;
331 if ( !nLineDY2 )
332 nLineDY2 = 1;
333
334 nLinePos -= nLineWidthHeight-nLineDY2;
335 ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
336 nLineWidth, mpFontInstance->mnOrientation, aColor );
337 nLinePos += nLineWidthHeight+nLineDY;
338 ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
339 nLineWidth, mpFontInstance->mnOrientation, aColor );
340 }
341 else
342 {
343 nLinePos -= nLineWidthHeight/2;
344 ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
345 nLineWidth, mpFontInstance->mnOrientation, aColor );
346 }
347}
348
350 tools::Long nDistX, tools::Long nDistY, tools::Long nWidth,
351 FontLineStyle eTextLine,
352 Color aColor,
353 bool bIsAbove )
354{
355 static bool bFuzzing = utl::ConfigManager::IsFuzzing();
356 if (bFuzzing && nWidth > 100000)
357 {
358 SAL_WARN("vcl.gdi", "drawLine, skipping suspicious TextLine of length: "
359 << nWidth << " for fuzzing performance");
360 return;
361 }
362
363 LogicalFontInstance* pFontInstance = mpFontInstance.get();
364 tools::Long nLineHeight = 0;
365 tools::Long nLinePos = 0;
366 tools::Long nLinePos2 = 0;
367
368 const tools::Long nY = nDistY;
369
370 if ( eTextLine > UNDERLINE_LAST )
371 eTextLine = LINESTYLE_SINGLE;
372
373 switch ( eTextLine )
374 {
375 case LINESTYLE_SINGLE:
376 case LINESTYLE_DOTTED:
377 case LINESTYLE_DASH:
381 if ( bIsAbove )
382 {
383 nLineHeight = pFontInstance->mxFontMetric->GetAboveUnderlineSize();
384 nLinePos = nY + pFontInstance->mxFontMetric->GetAboveUnderlineOffset();
385 }
386 else
387 {
388 nLineHeight = pFontInstance->mxFontMetric->GetUnderlineSize();
389 nLinePos = nY + pFontInstance->mxFontMetric->GetUnderlineOffset();
390 }
391 break;
392 case LINESTYLE_BOLD:
398 if ( bIsAbove )
399 {
400 nLineHeight = pFontInstance->mxFontMetric->GetAboveBoldUnderlineSize();
401 nLinePos = nY + pFontInstance->mxFontMetric->GetAboveBoldUnderlineOffset();
402 }
403 else
404 {
405 nLineHeight = pFontInstance->mxFontMetric->GetBoldUnderlineSize();
406 nLinePos = nY + pFontInstance->mxFontMetric->GetBoldUnderlineOffset();
407 }
408 break;
409 case LINESTYLE_DOUBLE:
410 if ( bIsAbove )
411 {
412 nLineHeight = pFontInstance->mxFontMetric->GetAboveDoubleUnderlineSize();
413 nLinePos = nY + pFontInstance->mxFontMetric->GetAboveDoubleUnderlineOffset1();
414 nLinePos2 = nY + pFontInstance->mxFontMetric->GetAboveDoubleUnderlineOffset2();
415 }
416 else
417 {
418 nLineHeight = pFontInstance->mxFontMetric->GetDoubleUnderlineSize();
419 nLinePos = nY + pFontInstance->mxFontMetric->GetDoubleUnderlineOffset1();
420 nLinePos2 = nY + pFontInstance->mxFontMetric->GetDoubleUnderlineOffset2();
421 }
422 break;
423 default:
424 break;
425 }
426
427 if ( !nLineHeight )
428 return;
429
431 {
433 mbInitLineColor = true;
434 }
435 mpGraphics->SetFillColor( aColor );
436 mbInitFillColor = true;
437
438 tools::Long nLeft = nDistX;
439
440 switch ( eTextLine )
441 {
442 case LINESTYLE_SINGLE:
443 case LINESTYLE_BOLD:
444 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
445 break;
446 case LINESTYLE_DOUBLE:
447 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
448 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
449 break;
450 case LINESTYLE_DOTTED:
452 {
453 tools::Long nDotWidth = nLineHeight*mnDPIY;
454 nDotWidth += mnDPIY/2;
455 nDotWidth /= mnDPIY;
456
457 tools::Long nTempWidth = nDotWidth;
458 tools::Long nEnd = nLeft+nWidth;
459 while ( nLeft < nEnd )
460 {
461 if ( nLeft+nTempWidth > nEnd )
462 nTempWidth = nEnd-nLeft;
463
464 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
465 nLeft += nDotWidth*2;
466 }
467 }
468 break;
469 case LINESTYLE_DASH:
473 {
474 tools::Long nDotWidth = nLineHeight*mnDPIY;
475 nDotWidth += mnDPIY/2;
476 nDotWidth /= mnDPIY;
477
478 tools::Long nMinDashWidth;
479 tools::Long nMinSpaceWidth;
480 tools::Long nSpaceWidth;
481 tools::Long nDashWidth;
482 if ( (eTextLine == LINESTYLE_LONGDASH) ||
483 (eTextLine == LINESTYLE_BOLDLONGDASH) )
484 {
485 nMinDashWidth = nDotWidth*6;
486 nMinSpaceWidth = nDotWidth*2;
487 nDashWidth = 200;
488 nSpaceWidth = 100;
489 }
490 else
491 {
492 nMinDashWidth = nDotWidth*4;
493 nMinSpaceWidth = (nDotWidth*150)/100;
494 nDashWidth = 100;
495 nSpaceWidth = 50;
496 }
497 nDashWidth = ((nDashWidth*mnDPIX)+1270)/2540;
498 nSpaceWidth = ((nSpaceWidth*mnDPIX)+1270)/2540;
499 // DashWidth will be increased if the line is getting too thick
500 // in proportion to the line's length
501 if ( nDashWidth < nMinDashWidth )
502 nDashWidth = nMinDashWidth;
503 if ( nSpaceWidth < nMinSpaceWidth )
504 nSpaceWidth = nMinSpaceWidth;
505
506 tools::Long nTempWidth = nDashWidth;
507 tools::Long nEnd = nLeft+nWidth;
508 while ( nLeft < nEnd )
509 {
510 if ( nLeft+nTempWidth > nEnd )
511 nTempWidth = nEnd-nLeft;
512 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
513 nLeft += nDashWidth+nSpaceWidth;
514 }
515 }
516 break;
519 {
520 tools::Long nDotWidth = nLineHeight*mnDPIY;
521 nDotWidth += mnDPIY/2;
522 nDotWidth /= mnDPIY;
523
524 tools::Long nDashWidth = ((100*mnDPIX)+1270)/2540;
525 tools::Long nMinDashWidth = nDotWidth*4;
526 // DashWidth will be increased if the line is getting too thick
527 // in proportion to the line's length
528 if ( nDashWidth < nMinDashWidth )
529 nDashWidth = nMinDashWidth;
530
531 tools::Long nTempDotWidth = nDotWidth;
532 tools::Long nTempDashWidth = nDashWidth;
533 tools::Long nEnd = nLeft+nWidth;
534 while ( nLeft < nEnd )
535 {
536 if ( nLeft+nTempDotWidth > nEnd )
537 nTempDotWidth = nEnd-nLeft;
538
539 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
540 nLeft += nDotWidth*2;
541 if ( nLeft > nEnd )
542 break;
543
544 if ( nLeft+nTempDashWidth > nEnd )
545 nTempDashWidth = nEnd-nLeft;
546
547 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
548 nLeft += nDashWidth+nDotWidth;
549 }
550 }
551 break;
554 {
555 tools::Long nDotWidth = nLineHeight*mnDPIY;
556 nDotWidth += mnDPIY/2;
557 nDotWidth /= mnDPIY;
558
559 tools::Long nDashWidth = ((100*mnDPIX)+1270)/2540;
560 tools::Long nMinDashWidth = nDotWidth*4;
561 // DashWidth will be increased if the line is getting too thick
562 // in proportion to the line's length
563 if ( nDashWidth < nMinDashWidth )
564 nDashWidth = nMinDashWidth;
565
566 tools::Long nTempDotWidth = nDotWidth;
567 tools::Long nTempDashWidth = nDashWidth;
568 tools::Long nEnd = nLeft+nWidth;
569 while ( nLeft < nEnd )
570 {
571 if ( nLeft+nTempDotWidth > nEnd )
572 nTempDotWidth = nEnd-nLeft;
573
574 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
575 nLeft += nDotWidth*2;
576 if ( nLeft > nEnd )
577 break;
578
579 if ( nLeft+nTempDotWidth > nEnd )
580 nTempDotWidth = nEnd-nLeft;
581
582 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
583 nLeft += nDotWidth*2;
584 if ( nLeft > nEnd )
585 break;
586
587 if ( nLeft+nTempDashWidth > nEnd )
588 nTempDashWidth = nEnd-nLeft;
589
590 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
591 nLeft += nDashWidth+nDotWidth;
592 }
593 }
594 break;
595 default:
596 break;
597 }
598}
599
601 tools::Long nDistX, tools::Long nDistY, tools::Long nWidth,
602 FontStrikeout eStrikeout,
603 Color aColor )
604{
605 LogicalFontInstance* pFontInstance = mpFontInstance.get();
606 tools::Long nLineHeight = 0;
607 tools::Long nLinePos = 0;
608 tools::Long nLinePos2 = 0;
609
610 tools::Long nY = nDistY;
611
612 if ( eStrikeout > STRIKEOUT_LAST )
613 eStrikeout = STRIKEOUT_SINGLE;
614
615 switch ( eStrikeout )
616 {
617 case STRIKEOUT_SINGLE:
618 nLineHeight = pFontInstance->mxFontMetric->GetStrikeoutSize();
619 nLinePos = nY + pFontInstance->mxFontMetric->GetStrikeoutOffset();
620 break;
621 case STRIKEOUT_BOLD:
622 nLineHeight = pFontInstance->mxFontMetric->GetBoldStrikeoutSize();
623 nLinePos = nY + pFontInstance->mxFontMetric->GetBoldStrikeoutOffset();
624 break;
625 case STRIKEOUT_DOUBLE:
626 nLineHeight = pFontInstance->mxFontMetric->GetDoubleStrikeoutSize();
627 nLinePos = nY + pFontInstance->mxFontMetric->GetDoubleStrikeoutOffset1();
628 nLinePos2 = nY + pFontInstance->mxFontMetric->GetDoubleStrikeoutOffset2();
629 break;
630 default:
631 break;
632 }
633
634 if ( !nLineHeight )
635 return;
636
638 {
640 mbInitLineColor = true;
641 }
642 mpGraphics->SetFillColor( aColor );
643 mbInitFillColor = true;
644
645 const tools::Long& nLeft = nDistX;
646
647 switch ( eStrikeout )
648 {
649 case STRIKEOUT_SINGLE:
650 case STRIKEOUT_BOLD:
651 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
652 break;
653 case STRIKEOUT_DOUBLE:
654 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
655 ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
656 break;
657 default:
658 break;
659 }
660}
661
663 tools::Long nDistX, tools::Long nDistY, tools::Long nWidth,
664 FontStrikeout eStrikeout,
665 Color aColor )
666{
667 // See qadevOOo/testdocs/StrikeThrough.odt for examples if you need
668 // to tweak this
669 if (!nWidth)
670 return;
671
672 // prepare string for strikeout measurement
673 const char cStrikeoutChar = eStrikeout == STRIKEOUT_SLASH ? '/' : 'X';
674 static const int nTestStrLen = 4;
675 static const int nMaxStrikeStrLen = 2048;
676 sal_Unicode aChars[nMaxStrikeStrLen+1]; // +1 for valgrind...
677
678 for( int i = 0; i < nTestStrLen; ++i)
679 aChars[i] = cStrikeoutChar;
680
681 const OUString aStrikeoutTest(aChars, nTestStrLen);
682
683 // calculate approximation of strikeout atom size
684 tools::Long nStrikeoutWidth = 0;
685 std::unique_ptr<SalLayout> pLayout = ImplLayout( aStrikeoutTest, 0, nTestStrLen );
686 if( pLayout )
687 {
688 nStrikeoutWidth = pLayout->GetTextWidth() / nTestStrLen;
689 }
690 if( nStrikeoutWidth <= 0 ) // sanity check
691 return;
692
693 int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
694 if( nStrikeStrLen > nMaxStrikeStrLen )
695 nStrikeStrLen = nMaxStrikeStrLen;
696 else if (nStrikeStrLen < 0)
697 nStrikeStrLen = 0;
698
699 // build the strikeout string
700 for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
701 aChars[i] = cStrikeoutChar;
702
703 const OUString aStrikeoutText(aChars, nStrikeStrLen);
704
705 if( mpFontInstance->mnOrientation )
706 {
707 Point aOriginPt(0, 0);
708 aOriginPt.RotateAround( nDistX, nDistY, mpFontInstance->mnOrientation );
709 }
710
711 nBaseX += nDistX;
712 nBaseY += nDistY;
713
714 // strikeout text has to be left aligned
717 pLayout = ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
718 mnTextLayoutMode = nOrigTLM;
719
720 if( !pLayout )
721 return;
722
723 // draw the strikeout text
724 const Color aOldColor = GetTextColor();
725 SetTextColor( aColor );
727
728 pLayout->DrawBase() = basegfx::B2DPoint(nBaseX + mnTextOffX, nBaseY + mnTextOffY);
729
730 tools::Rectangle aPixelRect;
731 aPixelRect.SetLeft( nBaseX+mnTextOffX );
732 aPixelRect.SetRight( aPixelRect.Left()+nWidth );
733 aPixelRect.SetBottom( nBaseY+mpFontInstance->mxFontMetric->GetDescent() );
734 aPixelRect.SetTop( nBaseY-mpFontInstance->mxFontMetric->GetAscent() );
735
736 if (mpFontInstance->mnOrientation)
737 {
738 tools::Polygon aPoly( aPixelRect );
739 aPoly.Rotate( Point(nBaseX+mnTextOffX, nBaseY+mnTextOffY), mpFontInstance->mnOrientation);
740 aPixelRect = aPoly.GetBoundRect();
741 }
742
744 IntersectClipRegion( PixelToLogic(aPixelRect) );
745 if( mbInitClipRegion )
747
748 pLayout->DrawText( *mpGraphics );
749
750 Pop();
751
752 SetTextColor( aOldColor );
754}
755
757 tools::Long nDistX, double nWidth,
758 FontStrikeout eStrikeout,
759 FontLineStyle eUnderline,
760 FontLineStyle eOverline,
761 bool bUnderlineAbove )
762{
763 if ( !nWidth )
764 return;
765
766 Color aStrikeoutColor = GetTextColor();
767 Color aUnderlineColor = GetTextLineColor();
768 Color aOverlineColor = GetOverlineColor();
769 bool bStrikeoutDone = false;
770 bool bUnderlineDone = false;
771 bool bOverlineDone = false;
772
773 if ( IsRTLEnabled() )
774 {
775 tools::Long nXAdd = nWidth - nDistX;
776 if( mpFontInstance->mnOrientation )
777 nXAdd = FRound( nXAdd * cos( toRadians(mpFontInstance->mnOrientation) ) );
778
779 nX += nXAdd - 1;
780 }
781
782 if ( !IsTextLineColor() )
783 aUnderlineColor = GetTextColor();
784
785 if ( !IsOverlineColor() )
786 aOverlineColor = GetTextColor();
787
788 if ( (eUnderline == LINESTYLE_SMALLWAVE) ||
789 (eUnderline == LINESTYLE_WAVE) ||
790 (eUnderline == LINESTYLE_DOUBLEWAVE) ||
791 (eUnderline == LINESTYLE_BOLDWAVE) )
792 {
793 ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
794 bUnderlineDone = true;
795 }
796 if ( (eOverline == LINESTYLE_SMALLWAVE) ||
797 (eOverline == LINESTYLE_WAVE) ||
798 (eOverline == LINESTYLE_DOUBLEWAVE) ||
799 (eOverline == LINESTYLE_BOLDWAVE) )
800 {
801 ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
802 bOverlineDone = true;
803 }
804
805 if ( (eStrikeout == STRIKEOUT_SLASH) ||
806 (eStrikeout == STRIKEOUT_X) )
807 {
808 ImplDrawStrikeoutChar( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
809 bStrikeoutDone = true;
810 }
811
812 if ( !bUnderlineDone )
813 ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
814
815 if ( !bOverlineDone )
816 ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
817
818 if ( !bStrikeoutDone )
819 ImplDrawStrikeoutLine( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
820}
821
823 FontLineStyle eUnderline, FontLineStyle eOverline,
824 bool bWordLine, bool bUnderlineAbove )
825{
826 if( bWordLine )
827 {
828 // draw everything relative to the layout base point
829 const basegfx::B2DPoint aStartPt = rSalLayout.DrawBase();
830
831 // calculate distance of each word from the base point
833 double nDist = 0;
834 double nWidth = 0;
835 const GlyphItem* pGlyph;
836 int nStart = 0;
837 while (rSalLayout.GetNextGlyph(&pGlyph, aPos, nStart))
838 {
839 // calculate the boundaries of each word
840 if (!pGlyph->IsSpacing())
841 {
842 if( !nWidth )
843 {
844 // get the distance to the base point (as projected to baseline)
845 nDist = aPos.getX() - aStartPt.getX();
846 if( mpFontInstance->mnOrientation )
847 {
848 const double nDY = aPos.getY() - aStartPt.getY();
849 const double fRad = toRadians(mpFontInstance->mnOrientation);
850 nDist = FRound( nDist*cos(fRad) - nDY*sin(fRad) );
851 }
852 }
853
854 // update the length of the textline
855 nWidth += pGlyph->newWidth();
856 }
857 else if( nWidth > 0 )
858 {
859 // draw the textline for each word
860 ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), nDist, nWidth,
861 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
862 nWidth = 0;
863 }
864 }
865
866 // draw textline for the last word
867 if( nWidth > 0 )
868 {
869 ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), nDist, nWidth,
870 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
871 }
872 }
873 else
874 {
875 basegfx::B2DPoint aStartPt = rSalLayout.GetDrawPosition();
876 ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), 0,
877 rSalLayout.GetTextWidth(),
878 eStrikeout, eUnderline, eOverline, bUnderlineAbove );
879 }
880}
881
883{
884 tools::Long nBaseX = nX;
885 if( /*HasMirroredGraphics() &&*/ IsRTLEnabled() )
886 {
887 // revert the hack that will be done later in ImplDrawTextLine
888 nX = nBaseX - nWidth - (nX - nBaseX - 1);
889 }
890
891 ImplDrawTextLine( nX, nY, 0, nWidth, STRIKEOUT_NONE, LINESTYLE_SINGLE, LINESTYLE_NONE, false );
892}
893
895{
896
897 if ( mpMetaFile )
899
901
902 if( mpAlphaVDev )
904}
905
907{
908 Color aColor(vcl::drawmode::GetTextColor(rColor, GetDrawMode(), GetSettings().GetStyleSettings()));
909
910 if ( mpMetaFile )
911 mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, true ) );
912
913 maTextLineColor = aColor;
914
915 if( mpAlphaVDev )
917}
918
920{
921
922 if ( mpMetaFile )
924
926
927 if( mpAlphaVDev )
929}
930
932{
933 Color aColor(vcl::drawmode::GetTextColor(rColor, GetDrawMode(), GetSettings().GetStyleSettings()));
934
935 if ( mpMetaFile )
936 mpMetaFile->AddAction( new MetaOverlineColorAction( aColor, true ) );
937
938 maOverlineColor = aColor;
939
940 if( mpAlphaVDev )
942}
943
945 FontStrikeout eStrikeout,
946 FontLineStyle eUnderline,
947 FontLineStyle eOverline,
948 bool bUnderlineAbove )
949{
950 assert(!is_double_buffered_window());
951
952 if ( mpMetaFile )
953 mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline, eOverline ) );
954
955 if ( ((eUnderline == LINESTYLE_NONE) || (eUnderline == LINESTYLE_DONTKNOW)) &&
956 ((eOverline == LINESTYLE_NONE) || (eOverline == LINESTYLE_DONTKNOW)) &&
957 ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
958 {
959 return;
960 }
962 return;
963
964 if( mbInitClipRegion )
966
967 if( mbOutputClipped )
968 return;
969
970 // initialize font if needed to get text offsets
971 // TODO: only needed for mnTextOff!=(0,0)
972 if (!InitFont())
973 return;
974
975 Point aPos = ImplLogicToDevicePixel( rPos );
976 double fWidth = ImplLogicWidthToDeviceSubPixel(nWidth);
977 aPos += Point( mnTextOffX, mnTextOffY );
978 ImplDrawTextLine( aPos.X(), aPos.X(), 0, fWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
979
980 if( mpAlphaVDev )
981 mpAlphaVDev->DrawTextLine( rPos, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
982}
983
984void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, tools::Long nLineWidth, tools::Long nWaveHeight)
985{
986 assert(!is_double_buffered_window());
987
989 return;
990
991 // we need a graphics
992 if( !mpGraphics && !AcquireGraphics() )
993 return;
994 assert(mpGraphics);
995
996 if ( mbInitClipRegion )
998
999 if ( mbOutputClipped )
1000 return;
1001
1002 if (!InitFont())
1003 return;
1004
1005 Point aStartPt = ImplLogicToDevicePixel(rStartPos);
1006 Point aEndPt = ImplLogicToDevicePixel(rEndPos);
1007
1008 tools::Long nStartX = aStartPt.X();
1009 tools::Long nStartY = aStartPt.Y();
1010 tools::Long nEndX = aEndPt.X();
1011 tools::Long nEndY = aEndPt.Y();
1012 double fOrientation = 0.0;
1013
1014 // handle rotation
1015 if (nStartY != nEndY || nStartX > nEndX)
1016 {
1017 fOrientation = basegfx::rad2deg(std::atan2(nStartY - nEndY, nEndX - nStartX));
1018 // un-rotate the end point
1019 aStartPt.RotateAround(nEndX, nEndY, Degree10(static_cast<sal_Int16>(-fOrientation * 10.0)));
1020 }
1021
1022 // Handle HiDPI
1023 float fScaleFactor = GetDPIScaleFactor();
1024 if (fScaleFactor > 1.0f)
1025 {
1026 nWaveHeight *= fScaleFactor;
1027
1028 nStartY += fScaleFactor - 1; // Shift down additional pixel(s) to create more visual separation.
1029
1030 // odd heights look better than even
1031 if (nWaveHeight % 2 == 0)
1032 {
1033 nWaveHeight--;
1034 }
1035 }
1036
1037 // #109280# make sure the waveline does not exceed the descent to avoid paint problems
1038 LogicalFontInstance* pFontInstance = mpFontInstance.get();
1039 if (nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize())
1040 {
1041 nWaveHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
1042 // tdf#124848 hairline
1043 nLineWidth = 0;
1044 }
1045
1046 if ( fOrientation == 0.0 )
1047 {
1048 static vcl::DeleteOnDeinit< WavyLineCache > snLineCache {};
1049 if ( !snLineCache.get() )
1050 return;
1051 WavyLineCache& rLineCache = *snLineCache.get();
1052 BitmapEx aWavylinebmp;
1053 if ( !rLineCache.find( GetLineColor(), nLineWidth, nWaveHeight, nEndX - nStartX, aWavylinebmp ) )
1054 {
1055 size_t nWordLength = nEndX - nStartX;
1056 // start with something big to avoid updating it frequently
1057 nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
1059 pVirtDev->SetOutputSizePixel( Size( nWordLength, nWaveHeight * 2 ), false );
1060 pVirtDev->SetLineColor( GetLineColor() );
1061 pVirtDev->SetBackground( Wallpaper( COL_TRANSPARENT ) );
1062 pVirtDev->Erase();
1063 pVirtDev->SetAntialiasing( AntialiasingFlags::Enable );
1064 pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, nWaveHeight, fOrientation, nLineWidth );
1065 BitmapEx aBitmapEx(pVirtDev->GetBitmapEx(Point(0, 0), pVirtDev->GetOutputSize()));
1066
1067 // Ideally we don't need this block, but in the split rgb surface + separate alpha surface
1068 // with Antialiasing enabled and the svp/cairo backend we get both surfaces antialiased
1069 // so their combination of aliases merge to overly wash-out the color. Hack it by taking just
1070 // the alpha surface and use it to blend the original solid line color
1071 Bitmap aSolidColor(aBitmapEx.GetBitmap());
1072 aSolidColor.Erase(GetLineColor());
1073 aBitmapEx = BitmapEx(aSolidColor, aBitmapEx.GetAlphaMask());
1074
1075 rLineCache.insert( aBitmapEx, GetLineColor(), nLineWidth, nWaveHeight, nWordLength, aWavylinebmp );
1076 }
1077 if ( aWavylinebmp.ImplGetBitmapSalBitmap() != nullptr )
1078 {
1079 Size _size( nEndX - nStartX, aWavylinebmp.GetSizePixel().Height() );
1080 DrawBitmapEx(Point( rStartPos.X(), rStartPos.Y() ), PixelToLogic( _size ), Point(), _size, aWavylinebmp);
1081 }
1082 return;
1083 }
1084
1085 ImplDrawWaveLineBezier( nStartX, nStartY, nEndX, nEndY, nWaveHeight, fOrientation, nLineWidth );
1086}
1087
1088void OutputDevice::ImplDrawWaveLineBezier(tools::Long nStartX, tools::Long nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long nWaveHeight, double fOrientation, tools::Long nLineWidth)
1089{
1090 // we need a graphics
1091 if( !mpGraphics && !AcquireGraphics() )
1092 return;
1093 assert(mpGraphics);
1094
1095 if ( mbInitClipRegion )
1097
1098 if ( mbOutputClipped )
1099 return;
1100
1101 if (!InitFont())
1102 return;
1103
1104 const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, nEndY + nWaveHeight);
1105 const basegfx::B2DPolygon aWaveLinePolygon = basegfx::createWaveLinePolygon(aWaveLineRectangle);
1106 const basegfx::B2DHomMatrix aRotationMatrix = basegfx::utils::createRotateAroundPoint(nStartX, nStartY, basegfx::deg2rad(-fOrientation));
1107 const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
1108
1111 aRotationMatrix,
1112 aWaveLinePolygon,
1113 0.0,
1114 nLineWidth,
1115 nullptr, // MM01
1117 css::drawing::LineCap_BUTT,
1118 basegfx::deg2rad(15.0),
1119 bPixelSnapHairline,
1120 *this);
1121
1122 if( mpAlphaVDev )
1123 mpAlphaVDev->ImplDrawWaveLineBezier(nStartX, nStartY, nEndX, nEndY, nWaveHeight, fOrientation, nLineWidth);
1124}
1125
1126/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _ADOKey Key
sal_Int32 nLineWidth
const AlphaMask & GetAlphaMask() const
Definition: bitmapex.hxx:71
SAL_DLLPRIVATE std::shared_ptr< SalBitmap > const & ImplGetBitmapSalBitmap() const
Definition: bitmapex.hxx:451
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:217
const Size & GetSizePixel() const
Definition: bitmapex.hxx:73
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:585
bool IsSpacing() const
double newWidth() const
FontMetricDataRef mxFontMetric
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:170
virtual void InitClipRegion()
void ImplDrawTextLines(SalLayout &, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bWordLine, bool bUnderlineAbove)
Definition: textline.cxx:822
SAL_DLLPRIVATE void ImplDrawStrikeoutLine(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor)
Definition: textline.cxx:600
sal_Int32 mnDPIY
Definition: outdev.hxx:213
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
Definition: bitmapex.cxx:33
bool IsOverlineColor() const
Definition: outdev.hxx:1018
SAL_DLLPRIVATE bool is_double_buffered_window() const
tools::Long mnTextOffY
Definition: outdev.hxx:217
float GetDPIScaleFactor() const
Definition: outdev.hxx:396
bool mbOutputClipped
Definition: outdev.hxx:245
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
Definition: map.cxx:334
void DrawWaveLine(const Point &rStartPos, const Point &rEndPos, tools::Long nLineWidth=1, tools::Long nWaveHeight=3)
Definition: textline.cxx:984
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
Definition: map.cxx:1110
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:708
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:185
SAL_DLLPRIVATE void ImplDrawStrikeoutChar(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, FontStrikeout eStrikeout, Color aColor)
Definition: textline.cxx:662
SAL_DLLPRIVATE void ImplDrawWaveLineBezier(tools::Long nStartX, tools::Long nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long nWaveHeight, double fOrientation, tools::Long nLineWidth)
Definition: textline.cxx:1088
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)
Definition: textline.cxx:273
Color maTextLineColor
Definition: outdev.hxx:230
virtual bool shouldDrawWavePixelAsRect(tools::Long nLineWidth) const
Definition: textline.cxx:135
vcl::text::ComplexTextLayoutFlags mnTextLayoutMode
Definition: outdev.hxx:221
virtual Size GetWaveLineSize(tools::Long nLineWidth) const
Definition: textline.cxx:164
const Color & GetOverlineColor() const
Definition: outdev.hxx:1017
bool mbInitLineColor
Definition: outdev.hxx:248
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:182
void SetTextColor(const Color &rColor)
Definition: text.cxx:716
void DrawTextLine(const Point &rPos, tools::Long nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove=false)
Definition: textline.cxx:944
rtl::Reference< LogicalFontInstance > mpFontInstance
Definition: outdev.hxx:186
bool mbInitClipRegion
Definition: outdev.hxx:252
SAL_DLLPRIVATE double ImplLogicWidthToDeviceSubPixel(tools::Long nWidth) const
Definition: map.cxx:1837
bool IsRTLEnabled() const
Definition: outdev.hxx:1269
void ImplDrawTextLine(tools::Long nBaseX, tools::Long nX, tools::Long nY, double nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline, bool bUnderlineAbove)
Definition: textline.cxx:756
virtual void SetWaveLineColors(Color const &rColor, tools::Long nLineWidth)
Definition: textline.cxx:143
AntialiasingFlags mnAntialiasing
Definition: outdev.hxx:237
SAL_DLLPRIVATE void ImplInitTextLineSize()
Definition: textline.cxx:101
const Color & GetLineColor() const
Definition: outdev.hxx:510
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:481
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:196
const Color & GetTextColor() const
Definition: outdev.hxx:1003
SAL_DLLPRIVATE void ImplInitAboveTextLineSize()
Definition: textline.cxx:106
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:32
Color maOverlineColor
Definition: outdev.hxx:231
SAL_DLLPRIVATE void ImplInitTextColor()
Definition: text.cxx:100
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)
Definition: textline.cxx:111
void Pop()
Definition: stack.cxx:91
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
Definition: text.cxx:1292
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)
Definition: textline.cxx:349
tools::Long mnTextOffX
font specific text alignment offsets in pixel units
Definition: outdev.hxx:216
SAL_DLLPRIVATE void ImplDrawTextRect(tools::Long nBaseX, tools::Long nBaseY, tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight)
Definition: text.cxx:111
DrawModeFlags GetDrawMode() const
Definition: outdev.hxx:487
bool IsTextLineColor() const
Definition: outdev.hxx:1013
void SetOverlineColor()
Definition: textline.cxx:919
const AllSettings & GetSettings() const
Definition: outdev.hxx:288
bool mbLineColor
Definition: outdev.hxx:246
void IntersectClipRegion(const tools::Rectangle &rRect)
SAL_DLLPRIVATE void ImplDrawMnemonicLine(tools::Long nX, tools::Long nY, tools::Long nWidth)
Definition: textline.cxx:882
const Color & GetTextLineColor() const
Definition: outdev.hxx:1012
void SetTextLineColor()
Definition: textline.cxx:894
SAL_DLLPRIVATE bool InitFont() const
sal_Int32 mnDPIX
Definition: outdev.hxx:212
bool mbInitFillColor
Definition: outdev.hxx:249
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)
Definition: textline.cxx:172
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
Definition: vcllayout.hxx:98
basegfx::B2DPoint GetDrawPosition(const basegfx::B2DPoint &rRelative=basegfx::B2DPoint(0, 0)) const
Definition: sallayout.cxx:144
basegfx::B2DPoint & DrawBase()
Definition: vcllayout.hxx:72
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
TYPE getX() const
TYPE getY() const
tools::Rectangle GetBoundRect() const
void Rotate(const Point &rCenter, double fSin, double fCos)
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr void SetRight(tools::Long v)
constexpr void SetBottom(tools::Long v)
constexpr tools::Long Left() const
static bool IsFuzzing()
constexpr ::Color COL_ALPHA_OPAQUE(0xff, 0xff, 0xff)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
int nCount
double toRadians(D x)
FontLineStyle
LINESTYLE_BOLDDASHDOT
LINESTYLE_BOLDDASHDOTDOT
LINESTYLE_SINGLE
LINESTYLE_BOLDLONGDASH
LINESTYLE_BOLDWAVE
LINESTYLE_DASHDOTDOT
LINESTYLE_BOLDDASH
LINESTYLE_BOLDDOTTED
LINESTYLE_DOUBLEWAVE
LINESTYLE_DOUBLE
LINESTYLE_NONE
LINESTYLE_DASH
LINESTYLE_DONTKNOW
LINESTYLE_SMALLWAVE
LINESTYLE_DASHDOT
LINESTYLE_DOTTED
LINESTYLE_WAVE
LINESTYLE_LONGDASH
LINESTYLE_BOLD
FontStrikeout
STRIKEOUT_BOLD
STRIKEOUT_DOUBLE
STRIKEOUT_SINGLE
STRIKEOUT_X
STRIKEOUT_SLASH
STRIKEOUT_NONE
STRIKEOUT_DONTKNOW
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)
int i
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
long Long
Color GetTextColor(Color const &rColor, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
Definition: drawmode.cxx:137
ComplexTextLayoutFlags
Definition: State.hxx:76
#define STRIKEOUT_LAST
Definition: textline.cxx:39
#define UNDERLINE_LAST
Definition: textline.cxx:38
sal_uInt16 sal_Unicode
bool operator==(const ItalicMatrix &a, const ItalicMatrix &b)
Definition: vclenum.hxx:175