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