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 
44 namespace {
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 
146 void 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 
212  SetWaveLineColors(rColor, nLineWidth);
213  Size aSize(GetWaveLineSize(nLineWidth));
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 
299  tools::Long nLineWidth = mnDPIX / 300;
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:
365  case LINESTYLE_LONGDASH:
366  case LINESTYLE_DASHDOT:
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:
381  case LINESTYLE_BOLDDASH:
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 
417  if ( mbLineColor || mbInitLineColor )
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:
457  case LINESTYLE_LONGDASH:
458  case LINESTYLE_BOLDDASH:
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;
504  case LINESTYLE_DASHDOT:
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 
624  if ( mbLineColor || mbInitLineColor )
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 
684  // build the strikeout string
685  for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
686  aChars[i] = cStrikeoutChar;
687 
688  const OUString aStrikeoutText(aChars, nStrikeStrLen);
689 
690  if( mpFontInstance->mnOrientation )
691  {
692  Point aOriginPt(0, 0);
693  aOriginPt.RotateAround( nDistX, nDistY, mpFontInstance->mnOrientation );
694  }
695 
696  nBaseX += nDistX;
697  nBaseY += nDistY;
698 
699  // strikeout text has to be left aligned
702  pLayout = ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
703  mnTextLayoutMode = nOrigTLM;
704 
705  if( !pLayout )
706  return;
707 
708  // draw the strikeout text
709  const Color aOldColor = GetTextColor();
710  SetTextColor( aColor );
712 
713  pLayout->DrawBase() = Point( nBaseX+mnTextOffX, nBaseY+mnTextOffY );
714 
715  tools::Rectangle aPixelRect;
716  aPixelRect.SetLeft( nBaseX+mnTextOffX );
717  aPixelRect.SetRight( aPixelRect.Left()+nWidth );
718  aPixelRect.SetBottom( nBaseY+mpFontInstance->mxFontMetric->GetDescent() );
719  aPixelRect.SetTop( nBaseY-mpFontInstance->mxFontMetric->GetAscent() );
720 
721  if (mpFontInstance->mnOrientation)
722  {
723  tools::Polygon aPoly( aPixelRect );
724  aPoly.Rotate( Point(nBaseX+mnTextOffX, nBaseY+mnTextOffY), mpFontInstance->mnOrientation);
725  aPixelRect = aPoly.GetBoundRect();
726  }
727 
729  IntersectClipRegion( PixelToLogic(aPixelRect) );
730  if( mbInitClipRegion )
731  InitClipRegion();
732 
733  pLayout->DrawText( *mpGraphics );
734 
735  Pop();
736 
737  SetTextColor( aOldColor );
739 }
740 
742  tools::Long nDistX, DeviceCoordinate nWidth,
743  FontStrikeout eStrikeout,
744  FontLineStyle eUnderline,
745  FontLineStyle eOverline,
746  bool bUnderlineAbove )
747 {
748  if ( !nWidth )
749  return;
750 
751  Color aStrikeoutColor = GetTextColor();
752  Color aUnderlineColor = GetTextLineColor();
753  Color aOverlineColor = GetOverlineColor();
754  bool bStrikeoutDone = false;
755  bool bUnderlineDone = false;
756  bool bOverlineDone = false;
757 
758  if ( IsRTLEnabled() )
759  {
760  tools::Long nXAdd = nWidth - nDistX;
761  if( mpFontInstance->mnOrientation )
762  nXAdd = FRound( nXAdd * cos( mpFontInstance->mnOrientation.get() * F_PI1800 ) );
763 
764  nX += nXAdd - 1;
765  }
766 
767  if ( !IsTextLineColor() )
768  aUnderlineColor = GetTextColor();
769 
770  if ( !IsOverlineColor() )
771  aOverlineColor = GetTextColor();
772 
773  if ( (eUnderline == LINESTYLE_SMALLWAVE) ||
774  (eUnderline == LINESTYLE_WAVE) ||
775  (eUnderline == LINESTYLE_DOUBLEWAVE) ||
776  (eUnderline == LINESTYLE_BOLDWAVE) )
777  {
778  ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
779  bUnderlineDone = true;
780  }
781  if ( (eOverline == LINESTYLE_SMALLWAVE) ||
782  (eOverline == LINESTYLE_WAVE) ||
783  (eOverline == LINESTYLE_DOUBLEWAVE) ||
784  (eOverline == LINESTYLE_BOLDWAVE) )
785  {
786  ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
787  bOverlineDone = true;
788  }
789 
790  if ( (eStrikeout == STRIKEOUT_SLASH) ||
791  (eStrikeout == STRIKEOUT_X) )
792  {
793  ImplDrawStrikeoutChar( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
794  bStrikeoutDone = true;
795  }
796 
797  if ( !bUnderlineDone )
798  ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
799 
800  if ( !bOverlineDone )
801  ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
802 
803  if ( !bStrikeoutDone )
804  ImplDrawStrikeoutLine( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
805 }
806 
808  FontLineStyle eUnderline, FontLineStyle eOverline,
809  bool bWordLine, bool bUnderlineAbove )
810 {
811  if( bWordLine )
812  {
813  // draw everything relative to the layout base point
814  const Point aStartPt = rSalLayout.DrawBase();
815 
816  // calculate distance of each word from the base point
817  Point aPos;
818  DeviceCoordinate nDist = 0;
819  DeviceCoordinate nWidth = 0;
820  const GlyphItem* pGlyph;
821  int nStart = 0;
822  while (rSalLayout.GetNextGlyph(&pGlyph, aPos, nStart))
823  {
824  // calculate the boundaries of each word
825  if (!pGlyph->IsSpacing())
826  {
827  if( !nWidth )
828  {
829  // get the distance to the base point (as projected to baseline)
830  nDist = aPos.X() - aStartPt.X();
831  if( mpFontInstance->mnOrientation )
832  {
833  const tools::Long nDY = aPos.Y() - aStartPt.Y();
834  const double fRad = mpFontInstance->mnOrientation.get() * F_PI1800;
835  nDist = FRound( nDist*cos(fRad) - nDY*sin(fRad) );
836  }
837  }
838 
839  // update the length of the textline
840  nWidth += pGlyph->m_nNewWidth;
841  }
842  else if( nWidth > 0 )
843  {
844  // draw the textline for each word
845  ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
846  eStrikeout, eUnderline, eOverline, bUnderlineAbove );
847  nWidth = 0;
848  }
849  }
850 
851  // draw textline for the last word
852  if( nWidth > 0 )
853  {
854  ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
855  eStrikeout, eUnderline, eOverline, bUnderlineAbove );
856  }
857  }
858  else
859  {
860  Point aStartPt = rSalLayout.GetDrawPosition();
861  ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), 0,
862  rSalLayout.GetTextWidth() / rSalLayout.GetUnitsPerPixel(),
863  eStrikeout, eUnderline, eOverline, bUnderlineAbove );
864  }
865 }
866 
868 {
869  tools::Long nBaseX = nX;
870  if( /*HasMirroredGraphics() &&*/ IsRTLEnabled() )
871  {
872  // add some strange offset
873  nX += 2;
874  // revert the hack that will be done later in ImplDrawTextLine
875  nX = nBaseX - nWidth - (nX - nBaseX - 1);
876  }
877 
878  ImplDrawTextLine( nX, nY, 0, nWidth, STRIKEOUT_NONE, LINESTYLE_SINGLE, LINESTYLE_NONE, false );
879 }
880 
882 {
883 
884  if ( mpMetaFile )
886 
888 
889  if( mpAlphaVDev )
891 }
892 
894 {
895  Color aColor(vcl::drawmode::GetTextColor(rColor, GetDrawMode(), GetSettings().GetStyleSettings()));
896 
897  if ( mpMetaFile )
898  mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, true ) );
899 
900  maTextLineColor = aColor;
901 
902  if( mpAlphaVDev )
904 }
905 
907 {
908 
909  if ( mpMetaFile )
911 
913 
914  if( mpAlphaVDev )
916 }
917 
919 {
920  Color aColor(vcl::drawmode::GetTextColor(rColor, GetDrawMode(), GetSettings().GetStyleSettings()));
921 
922  if ( mpMetaFile )
923  mpMetaFile->AddAction( new MetaOverlineColorAction( aColor, true ) );
924 
925  maOverlineColor = aColor;
926 
927  if( mpAlphaVDev )
929 }
930 
931 void OutputDevice::DrawTextLine( const Point& rPos, tools::Long nWidth,
932  FontStrikeout eStrikeout,
933  FontLineStyle eUnderline,
934  FontLineStyle eOverline,
935  bool bUnderlineAbove )
936 {
937  assert(!is_double_buffered_window());
938 
939  if ( mpMetaFile )
940  mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline, eOverline ) );
941 
942  if ( ((eUnderline == LINESTYLE_NONE) || (eUnderline == LINESTYLE_DONTKNOW)) &&
943  ((eOverline == LINESTYLE_NONE) || (eOverline == LINESTYLE_DONTKNOW)) &&
944  ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
945  {
946  return;
947  }
949  return;
950 
951  if( mbInitClipRegion )
952  InitClipRegion();
953 
954  if( mbOutputClipped )
955  return;
956 
957  // initialize font if needed to get text offsets
958  // TODO: only needed for mnTextOff!=(0,0)
959  if (!InitFont())
960  return;
961 
962  Point aPos = ImplLogicToDevicePixel( rPos );
963  DeviceCoordinate fWidth;
964  fWidth = LogicWidthToDeviceCoordinate( nWidth );
965  aPos += Point( mnTextOffX, mnTextOffY );
966  ImplDrawTextLine( aPos.X(), aPos.X(), 0, fWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
967 
968  if( mpAlphaVDev )
969  mpAlphaVDev->DrawTextLine( rPos, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
970 }
971 
972 void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, tools::Long nLineWidth)
973 {
974  assert(!is_double_buffered_window());
975 
977  return;
978 
979  // we need a graphics
980  if( !mpGraphics && !AcquireGraphics() )
981  return;
982  assert(mpGraphics);
983 
984  if ( mbInitClipRegion )
985  InitClipRegion();
986 
987  if ( mbOutputClipped )
988  return;
989 
990  if (!InitFont())
991  return;
992 
993  Point aStartPt = ImplLogicToDevicePixel(rStartPos);
994  Point aEndPt = ImplLogicToDevicePixel(rEndPos);
995 
996  tools::Long nStartX = aStartPt.X();
997  tools::Long nStartY = aStartPt.Y();
998  tools::Long nEndX = aEndPt.X();
999  tools::Long nEndY = aEndPt.Y();
1000  double fOrientation = 0.0;
1001 
1002  // handle rotation
1003  if (nStartY != nEndY || nStartX > nEndX)
1004  {
1005  fOrientation = std::atan2(nStartY - nEndY, nEndX - nStartX);
1006  fOrientation /= F_PI180;
1007  // un-rotate the end point
1008  aStartPt.RotateAround(nEndX, nEndY, Degree10(static_cast<sal_Int16>(-fOrientation * 10.0)));
1009  }
1010 
1011  tools::Long nWaveHeight = 3;
1012 
1013  // Handle HiDPI
1014  float fScaleFactor = GetDPIScaleFactor();
1015  if (fScaleFactor > 1.0f)
1016  {
1017  nWaveHeight *= fScaleFactor;
1018 
1019  nStartY += fScaleFactor - 1; // Shift down additional pixel(s) to create more visual separation.
1020 
1021  // odd heights look better than even
1022  if (nWaveHeight % 2 == 0)
1023  {
1024  nWaveHeight--;
1025  }
1026  }
1027 
1028  // #109280# make sure the waveline does not exceed the descent to avoid paint problems
1029  LogicalFontInstance* pFontInstance = mpFontInstance.get();
1030  if (nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize())
1031  {
1032  nWaveHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
1033  // tdf#124848 hairline
1034  nLineWidth = 0;
1035  }
1036 
1037  if ( fOrientation == 0.0 )
1038  {
1039  static vcl::DeleteOnDeinit< WavyLineCache > snLineCache {};
1040  if ( !snLineCache.get() )
1041  return;
1042  WavyLineCache& rLineCache = *snLineCache.get();
1043  BitmapEx aWavylinebmp;
1044  if ( !rLineCache.find( GetLineColor(), nLineWidth, nWaveHeight, nEndX - nStartX, aWavylinebmp ) )
1045  {
1046  size_t nWordLength = nEndX - nStartX;
1047  // start with something big to avoid updating it frequently
1048  nWordLength = nWordLength < 1024 ? 1024 : nWordLength;
1051  pVirtDev->SetOutputSizePixel( Size( nWordLength, nWaveHeight * 2 ), false );
1052  pVirtDev->SetLineColor( GetLineColor() );
1053  pVirtDev->SetBackground( Wallpaper( COL_TRANSPARENT ) );
1054  pVirtDev->Erase();
1055  pVirtDev->SetAntialiasing( AntialiasingFlags::Enable );
1056  pVirtDev->ImplDrawWaveLineBezier( 0, 0, nWordLength, 0, nWaveHeight, fOrientation, nLineWidth );
1057  BitmapEx aBitmapEx(pVirtDev->GetBitmapEx(Point(0, 0), pVirtDev->GetOutputSize()));
1058 
1059  // Ideally we don't need this block, but in the split rgb surface + separate alpha surface
1060  // with Antialiasing enabled and the svp/cairo backend we get both surfaces antialiased
1061  // so their combination of aliases merge to overly wash-out the color. Hack it by taking just
1062  // the alpha surface and use it to blend the original solid line color
1063  Bitmap aSolidColor(aBitmapEx.GetBitmap());
1064  aSolidColor.Erase(GetLineColor());
1065  aBitmapEx = BitmapEx(aSolidColor, aBitmapEx.GetAlpha());
1066 
1067  rLineCache.insert( aBitmapEx, GetLineColor(), nLineWidth, nWaveHeight, nWordLength, aWavylinebmp );
1068  }
1069  if ( aWavylinebmp.ImplGetBitmapSalBitmap() != nullptr )
1070  {
1071  Size _size( nEndX - nStartX, aWavylinebmp.GetSizePixel().Height() );
1072  DrawBitmapEx(Point( rStartPos.X(), rStartPos.Y() ), PixelToLogic( _size ), Point(), _size, aWavylinebmp);
1073  }
1074  return;
1075  }
1076 
1077  ImplDrawWaveLineBezier( nStartX, nStartY, nEndX, nEndY, nWaveHeight, fOrientation, nLineWidth );
1078 }
1079 
1080 void OutputDevice::ImplDrawWaveLineBezier(tools::Long nStartX, tools::Long nStartY, tools::Long nEndX, tools::Long nEndY, tools::Long nWaveHeight, double fOrientation, tools::Long nLineWidth)
1081 {
1082  // we need a graphics
1083  if( !mpGraphics && !AcquireGraphics() )
1084  return;
1085  assert(mpGraphics);
1086 
1087  if ( mbInitClipRegion )
1088  InitClipRegion();
1089 
1090  if ( mbOutputClipped )
1091  return;
1092 
1093  if (!InitFont())
1094  return;
1095 
1096  const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, nEndY + nWaveHeight);
1097  const basegfx::B2DPolygon aWaveLinePolygon = basegfx::createWaveLinePolygon(aWaveLineRectangle);
1098  const basegfx::B2DHomMatrix aRotationMatrix = basegfx::utils::createRotateAroundPoint(nStartX, nStartY, basegfx::deg2rad(-fOrientation));
1099  const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
1100 
1103  aRotationMatrix,
1104  aWaveLinePolygon,
1105  0.0,
1106  nLineWidth,
1107  nullptr, // MM01
1109  css::drawing::LineCap_BUTT,
1110  basegfx::deg2rad(15.0),
1111  bPixelSnapHairline,
1112  *this);
1113 
1114  if( mpAlphaVDev )
1115  mpAlphaVDev->ImplDrawWaveLineBezier(nStartX, nStartY, nEndX, nEndY, nWaveHeight, fOrientation, nLineWidth);
1116 }
1117 
1118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const Color & GetTextColor() const
Definition: outdev.hxx:1011
void DrawPixel(tools::Long nX, tools::Long nY, const OutputDevice &rOutDev)
tools::Long GetAboveBoldUnderlineSize() const
SAL_DLLPRIVATE DeviceCoordinate LogicWidthToDeviceCoordinate(tools::Long nWidth) const
Definition: map.cxx:1821
tools::Long GetUnderlineSize() const
virtual void SetWaveLineColors(Color const &rColor, tools::Long nLineWidth)
Definition: textline.cxx:146
tools::Long mnTextOffX
font specific text alignment offsets in pixel units
Definition: outdev.hxx:215
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:702
int GetUnitsPerPixel() const
Definition: vcllayout.hxx:84
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:1020
constexpr tools::Long Left() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
Definition: bitmapex.cxx:33
tools::Long GetBoldStrikeoutSize() const
tools::Long GetAboveWavelineUnderlineSize() const
LINESTYLE_BOLD
tools::Long GetAboveUnderlineOffset() const
long Long
tools::Long GetWavelineUnderlineSize() const
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
#define F_PI1800
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
Color GetTextColor(Color const &rColor, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
Definition: drawmode.cxx:128
bool IsTextLineColor() const
Definition: outdev.hxx:1021
virtual DeviceCoordinate GetTextWidth() const
Definition: vcllayout.hxx:90
bool mbOutputClipped
Definition: outdev.hxx:244
LINESTYLE_BOLDWAVE
SAL_DLLPRIVATE void ImplInitTextColor()
Definition: text.cxx:97
SAL_DLLPRIVATE bool is_double_buffered_window() const
sal_Int32 mnDPIY
Definition: outdev.hxx:212
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:931
sal_Int32 mnDPIX
Definition: outdev.hxx:211
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:175
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
tools::Long GetStrikeoutOffset() const
tools::Long GetAboveDoubleUnderlineOffset1() const
LINESTYLE_DASH
constexpr tools::Long Width() const
const Color & GetOverlineColor() const
Definition: outdev.hxx:1025
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
LINESTYLE_DASHDOT
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::text::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
Definition: text.cxx:1223
sal_uInt16 sal_Unicode
Color maOverlineColor
Definition: outdev.hxx:230
LINESTYLE_BOLDDASHDOTDOT
LINESTYLE_NONE
tools::Long GetUnderlineOffset() const
#define UNDERLINE_LAST
Definition: textline.cxx:41
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
vcl::text::ComplexTextLayoutFlags mnTextLayoutMode
Definition: outdev.hxx:220
int nCount
virtual Size GetWaveLineSize(tools::Long nLineWidth) const
Definition: textline.cxx:167
AntialiasingFlags mnAntialiasing
Definition: outdev.hxx:236
void Pop()
Definition: stack.cxx:92
STRIKEOUT_SINGLE
void SetTextLineColor()
Definition: textline.cxx:881
SAL_DLLPRIVATE void ImplDrawMnemonicLine(tools::Long nX, tools::Long nY, tools::Long nWidth)
Definition: textline.cxx:867
void Rotate(const Point &rCenter, double fSin, double fCos)
constexpr void SetLeft(tools::Long v)
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:181
bool operator==(const ItalicMatrix &a, const ItalicMatrix &b)
Definition: vclenum.hxx:202
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:1243
int i
ComplexTextLayoutFlags
Definition: State.hxx:76
virtual void SetLineColor()=0
tools::Long FRound(double fVal)
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:109
tools::Long GetBoldStrikeoutOffset() const
bool mbInitLineColor
Definition: outdev.hxx:247
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:108
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:168
const Color & GetLineColor() const
Definition: outdev.hxx:506
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:741
tools::Long GetDoubleUnderlineSize() const
void SetTextColor(const Color &rColor)
Definition: text.cxx:688
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 DeviceCoordinate
tools::Long GetAboveDoubleUnderlineOffset2() const
sal_Int32 m_nNewWidth
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:151
bool mbLineColor
Definition: outdev.hxx:245
constexpr double deg2rad(double v)
LINESTYLE_SMALLWAVE
void SetOverlineColor()
Definition: textline.cxx:906
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
constexpr void SetRight(tools::Long v)
const AllSettings & GetSettings() const
Definition: outdev.hxx:287
tools::Long GetDoubleUnderlineOffset2() const
constexpr void SetBottom(tools::Long v)
Color maTextLineColor
Definition: outdev.hxx:229
DrawModeFlags GetDrawMode() const
Definition: outdev.hxx:483
LINESTYLE_DONTKNOW
sal_Int32 nLineWidth
constexpr void SetTop(tools::Long v)
STRIKEOUT_X
tools::Long GetAboveWavelineUnderlineOffset() const
tools::Long GetAboveUnderlineSize() const
Point & DrawBase()
Definition: vcllayout.hxx:73
float GetDPIScaleFactor() const
Definition: outdev.hxx:392
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
tools::Long GetStrikeoutSize() const
LINESTYLE_LONGDASH
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1109
SAL_DLLPRIVATE std::shared_ptr< SalBitmap > const & ImplGetBitmapSalBitmap() const
Definition: bitmapex.hxx:451
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:195
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:1080
BASEGFX_DLLPUBLIC B2DPolygon createWaveLinePolygon(basegfx::B2DRectangle const &rRectangle)
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
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
tools::Long GetAboveDoubleUnderlineSize() const
#define F_PI180
STRIKEOUT_DOUBLE
virtual bool GetNextGlyph(const GlyphItem **pGlyph, Point &rPos, int &nStart, const LogicalFontInstance **ppGlyphFont=nullptr, const vcl::font::PhysicalFontFace **pFallbackFont=nullptr) const =0
LINESTYLE_DASHDOTDOT
constexpr tools::Long Height() const
LINESTYLE_DOTTED
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:562
bool mbInitClipRegion
Definition: outdev.hxx:251
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:42
void DrawWaveLine(const Point &rStartPos, const Point &rEndPos, tools::Long nLineWidth=1)
Definition: textline.cxx:972
rtl::Reference< LogicalFontInstance > mpFontInstance
Definition: outdev.hxx:185
virtual bool shouldDrawWavePixelAsRect(tools::Long nLineWidth) const
Definition: textline.cxx:138
bool mbInitFillColor
Definition: outdev.hxx:248
LINESTYLE_BOLDDOTTED
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
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
STRIKEOUT_DONTKNOW
tools::Long GetWavelineUnderlineOffset() const
LINESTYLE_BOLDDASH
void(* f)(TrueTypeTable *)
Definition: ttcr.cxx:482
struct _ADOKey Key
SAL_DLLPRIVATE void ImplInitTextLineSize()
Definition: textline.cxx:104
tools::Rectangle GetBoundRect() const
tools::Long GetAboveBoldUnderlineOffset() const
LINESTYLE_DOUBLE
bool IsOverlineColor() const
Definition: outdev.hxx:1026
STRIKEOUT_NONE
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:807
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:477
tools::Long mnTextOffY
Definition: outdev.hxx:216
FontStrikeout
tools::Long GetDoubleUnderlineOffset1() const
LINESTYLE_BOLDDASHDOT
STRIKEOUT_BOLD
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:184
SAL_DLLPRIVATE bool InitFont() const