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