LibreOffice Module vcl (master)  1
transparent.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 <tools/helpers.hxx>
24 #include <rtl/math.hxx>
25 
26 #include <memory>
27 
28 #include <vcl/gdimtf.hxx>
29 #include <vcl/metaact.hxx>
30 #include <vcl/outdev.hxx>
31 #include <vcl/settings.hxx>
32 #include <vcl/virdev.hxx>
33 
34 #include <salgdi.hxx>
36 
37 namespace
38 {
44  tools::Polygon toPolygon( const basegfx::B2DPolygon& rPoly )
45  {
46  basegfx::B2DRange aRange = rPoly.getB2DRange();
47  double fW = aRange.getWidth(), fH = aRange.getHeight();
48  if (0.0 < fW && 0.0 < fH && (fW <= 1.0 || fH <= 1.0))
49  {
50  // This polygon not empty but is too small to display. Approximate it
51  // with a rectangle large enough to be displayed.
52  double nX = aRange.getMinX(), nY = aRange.getMinY();
53  double nW = std::max<double>(1.0, rtl::math::round(fW));
54  double nH = std::max<double>(1.0, rtl::math::round(fH));
55 
56  tools::Polygon aTarget;
57  aTarget.Insert(0, Point(nX, nY));
58  aTarget.Insert(1, Point(nX+nW, nY));
59  aTarget.Insert(2, Point(nX+nW, nY+nH));
60  aTarget.Insert(3, Point(nX, nY+nH));
61  aTarget.Insert(4, Point(nX, nY));
62  return aTarget;
63  }
64  return tools::Polygon(rPoly);
65  }
66 
67  tools::PolyPolygon toPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly )
68  {
69  tools::PolyPolygon aTarget;
70  for (auto const& rB2DPolygon : rPolyPoly)
71  aTarget.Insert(toPolygon(rB2DPolygon));
72 
73  return aTarget;
74  }
75 }
76 
78 {
79  Color aColor( rColor );
80  DrawModeFlags nDrawMode = GetDrawMode();
81 
85  {
86  if( !aColor.IsTransparent() )
87  {
88  if( nDrawMode & DrawModeFlags::BlackLine )
89  {
90  aColor = COL_BLACK;
91  }
92  else if( nDrawMode & DrawModeFlags::WhiteLine )
93  {
94  aColor = COL_WHITE;
95  }
96  else if( nDrawMode & DrawModeFlags::GrayLine )
97  {
98  const sal_uInt8 cLum = aColor.GetLuminance();
99  aColor = Color( cLum, cLum, cLum );
100  }
101  else if( nDrawMode & DrawModeFlags::SettingsLine )
102  {
104  }
105  }
106  }
107  return aColor;
108 }
109 
110 // Caution: This method is nearly the same as
111 // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
112 // so when changes are made here do not forget to make changes there, too
113 
115  const basegfx::B2DHomMatrix& rObjectTransform,
116  const basegfx::B2DPolyPolygon& rB2DPolyPoly,
117  double fTransparency)
118 {
120 
121  // AW: Do NOT paint empty PolyPolygons
122  if(!rB2DPolyPoly.count())
123  return;
124 
125  // we need a graphics
126  if( !mpGraphics && !AcquireGraphics() )
127  return;
128 
129  if( mbInitClipRegion )
130  InitClipRegion();
131 
132  if( mbOutputClipped )
133  return;
134 
135  if( mbInitLineColor )
136  InitLineColor();
137 
138  if( mbInitFillColor )
139  InitFillColor();
140 
143  {
144  // b2dpolygon support not implemented yet on non-UNX platforms
145  basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
146 
147  // ensure it is closed
148  if(!aB2DPolyPolygon.isClosed())
149  {
150  // maybe assert, prevents buffering due to making a copy
151  aB2DPolyPolygon.setClosed( true );
152  }
153 
154  // create ObjectToDevice transformation
155  const basegfx::B2DHomMatrix aFullTransform(ImplGetDeviceTransformation() * rObjectTransform);
156  // TODO: this must not drop transparency for mpAlphaVDev case, but instead use premultiplied
157  // alpha... but that requires using premultiplied alpha also for already drawn data
158  const double fAdjustedTransparency = mpAlphaVDev ? 0 : fTransparency;
159  bool bDrawnOk(true);
160 
161  if( IsFillColor() )
162  {
163  bDrawnOk = mpGraphics->DrawPolyPolygon(
164  aFullTransform,
165  aB2DPolyPolygon,
166  fAdjustedTransparency,
167  *this);
168  }
169 
170  if( bDrawnOk && IsLineColor() )
171  {
172  const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
173 
174  for(auto const& rPolygon : aB2DPolyPolygon)
175  {
177  aFullTransform,
178  rPolygon,
179  fAdjustedTransparency,
180  0.0, // tdf#124848 hairline
181  nullptr, // MM01
183  css::drawing::LineCap_BUTT,
184  basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
185  bPixelSnapHairline,
186  *this );
187  }
188  }
189 
190  if( bDrawnOk )
191  {
192  if( mpMetaFile )
193  {
194  // tdf#119843 need transformed Polygon here
195  basegfx::B2DPolyPolygon aB2DPolyPoly(rB2DPolyPoly);
196  aB2DPolyPoly.transform(rObjectTransform);
199  tools::PolyPolygon(aB2DPolyPoly),
200  static_cast< sal_uInt16 >(fTransparency * 100.0)));
201  }
202 
203  if (mpAlphaVDev)
204  mpAlphaVDev->DrawTransparent(rObjectTransform, rB2DPolyPoly, fTransparency);
205 
206  return;
207  }
208  }
209 
210  // fallback to old polygon drawing if needed
211  // tdf#119843 need transformed Polygon here
212  basegfx::B2DPolyPolygon aB2DPolyPoly(rB2DPolyPoly);
213  aB2DPolyPoly.transform(rObjectTransform);
215  toPolyPolygon(aB2DPolyPoly),
216  static_cast<sal_uInt16>(fTransparency * 100.0));
217 }
218 
220 {
222 
223  // short circuit if the polygon border is invisible too
224  if( !mbLineColor )
225  return;
226 
227  // we assume that the border is NOT to be drawn transparently???
229  SetFillColor();
230  DrawPolyPolygon( rPolyPoly );
231  Pop();
232 }
233 
235  sal_uInt16 nTransparencePercent )
236 {
238 
239  bool bDrawn = false;
240 
242 #if defined UNX && ! defined MACOSX && ! defined IOS
243  && GetBitCount() > 8
244 #endif
245 #ifdef _WIN32
246  // workaround bad dithering on remote displaying when using GDI+ with toolbar button highlighting
247  && !rPolyPoly.IsRect()
248 #endif
249  )
250  {
251  // prepare the graphics device
252  if( mbInitClipRegion )
253  InitClipRegion();
254 
255  if( mbOutputClipped )
256  return false;
257 
258  if( mbInitLineColor )
259  InitLineColor();
260 
261  if( mbInitFillColor )
262  InitFillColor();
263 
264  // get the polygon in device coordinates
265  basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
267 
268  const double fTransparency = 0.01 * nTransparencePercent;
269  if( mbFillColor )
270  {
271  // #i121591#
272  // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
273  // should be used when printing. Normally this is avoided by the printer being
274  // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
275  // to figure out a way of moving this code to its own function that is
276  // overridden by the Print class, which will mean we deliberately override the
277  // functionality and we use the fallback some lines below (which is not very good,
278  // though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
279  // correct the wrong mapping (see there for details)
280  bDrawn = mpGraphics->DrawPolyPolygon(
281  aTransform,
282  aB2DPolyPolygon,
283  fTransparency,
284  *this);
285  }
286 
287  if( mbLineColor )
288  {
289  // disable the fill color for now
291 
292  // draw the border line
293  const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
294 
295  for(auto const& rPolygon : aB2DPolyPolygon)
296  {
297  bDrawn = mpGraphics->DrawPolyLine(
298  aTransform,
299  rPolygon,
300  fTransparency,
301  0.0, // tdf#124848 hairline
302  nullptr, // MM01
304  css::drawing::LineCap_BUTT,
305  basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
306  bPixelSnapHairline,
307  *this );
308  }
309 
310  // prepare to restore the fill color
312  }
313  }
314 
315  return bDrawn;
316 }
317 
319  sal_uInt16 nTransparencePercent )
320 {
321  // #110958# Disable alpha VDev, we perform the necessary
322  VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
323 
324  // operation explicitly further below.
325  if( mpAlphaVDev )
326  mpAlphaVDev = nullptr;
327 
328  GDIMetaFile* pOldMetaFile = mpMetaFile;
329  mpMetaFile = nullptr;
330 
331  tools::PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
332  tools::Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
333  tools::Rectangle aDstRect( Point(), GetOutputSizePixel() );
334 
335  aDstRect.Intersection( aPolyRect );
336 
337  ClipToPaintRegion( aDstRect );
338 
339  if( !aDstRect.IsEmpty() )
340  {
341  bool bDrawn = false;
342 
343  // #i66849# Added fast path for exactly rectangular
344  // polygons
345  // #i83087# Naturally, system alpha blending cannot
346  // work with separate alpha VDev
347  if( !mpAlphaVDev && aPolyPoly.IsRect() )
348  {
349  // setup Graphics only here (other cases delegate
350  // to basic OutDev methods)
351  if ( mbInitClipRegion )
352  InitClipRegion();
353 
354  if ( mbInitLineColor )
355  InitLineColor();
356 
357  if ( mbInitFillColor )
358  InitFillColor();
359 
360  tools::Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
361  tools::Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
362 
363  if( !mbOutputClipped )
364  {
365  bDrawn = mpGraphics->DrawAlphaRect( aPixelRect.Left(), aPixelRect.Top(),
366  // #i98405# use methods with small g, else one pixel too much will be painted.
367  // This is because the source is a polygon which when painted would not paint
368  // the rightmost and lowest pixel line(s), so use one pixel less for the
369  // rectangle, too.
370  aPixelRect.getWidth(), aPixelRect.getHeight(),
371  sal::static_int_cast<sal_uInt8>(nTransparencePercent),
372  *this );
373  }
374  else
375  {
376  bDrawn = true;
377  }
378  }
379 
380  if( !bDrawn )
381  {
383  const Size aDstSz( aDstRect.GetSize() );
384  const sal_uInt8 cTrans = static_cast<sal_uInt8>(MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 ));
385 
386  if( aDstRect.Left() || aDstRect.Top() )
387  aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
388 
389  if( aVDev->SetOutputSizePixel( aDstSz ) )
390  {
391  const bool bOldMap = mbMap;
392 
393  EnableMapMode( false );
394 
395  aVDev->SetLineColor( COL_BLACK );
396  aVDev->SetFillColor( COL_BLACK );
397  aVDev->DrawPolyPolygon( aPolyPoly );
398 
399  Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
400  Bitmap aPolyMask( aVDev->GetBitmap( Point(), aDstSz ) );
401 
402  // #107766# check for non-empty bitmaps before accessing them
403  if( !!aPaint && !!aPolyMask )
404  {
405  BitmapScopedWriteAccess pW(aPaint);
406  Bitmap::ScopedReadAccess pR(aPolyMask);
407 
408  if( pW && pR )
409  {
410  BitmapColor aPixCol;
411  const BitmapColor aFillCol( GetFillColor() );
412  const BitmapColor aBlack( pR->GetBestMatchingColor( COL_BLACK ) );
413  const tools::Long nWidth = pW->Width();
414  const tools::Long nHeight = pW->Height();
415  const tools::Long nR = aFillCol.GetRed();
416  const tools::Long nG = aFillCol.GetGreen();
417  const tools::Long nB = aFillCol.GetBlue();
418  tools::Long nX, nY;
419 
420  if( aPaint.GetBitCount() <= 8 )
421  {
422  const BitmapPalette& rPal = pW->GetPalette();
423  const sal_uInt16 nCount = rPal.GetEntryCount();
424  BitmapColor* pMap = reinterpret_cast<BitmapColor*>(new sal_uInt8[ nCount * sizeof( BitmapColor ) ]);
425 
426  for( sal_uInt16 i = 0; i < nCount; i++ )
427  {
428  BitmapColor aCol( rPal[ i ] );
429  aCol.Merge( aFillCol, cTrans );
430  pMap[ i ] = BitmapColor( static_cast<sal_uInt8>(rPal.GetBestIndex( aCol )) );
431  }
432 
435  {
436  const sal_uInt8 cBlack = aBlack.GetIndex();
437 
438  for( nY = 0; nY < nHeight; nY++ )
439  {
440  Scanline pWScan = pW->GetScanline( nY );
441  Scanline pRScan = pR->GetScanline( nY );
442  sal_uInt8 cBit = 128;
443 
444  for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
445  {
446  if( !cBit )
447  {
448  cBit = 128;
449  pRScan += 1;
450  }
451  if( ( *pRScan & cBit ) == cBlack )
452  {
453  *pWScan = pMap[ *pWScan ].GetIndex();
454  }
455  }
456  }
457  }
458  else
459  {
460  for( nY = 0; nY < nHeight; nY++ )
461  {
462  Scanline pScanline = pW->GetScanline(nY);
463  Scanline pScanlineRead = pR->GetScanline(nY);
464  for( nX = 0; nX < nWidth; nX++ )
465  {
466  if( pR->GetPixelFromData( pScanlineRead, nX ) == aBlack )
467  {
468  pW->SetPixelOnData( pScanline, nX, pMap[ pW->GetIndexFromData( pScanline, nX ) ] );
469  }
470  }
471  }
472  }
473  delete[] reinterpret_cast<sal_uInt8*>(pMap);
474  }
475  else
476  {
479  {
480  const sal_uInt8 cBlack = aBlack.GetIndex();
481 
482  for( nY = 0; nY < nHeight; nY++ )
483  {
484  Scanline pWScan = pW->GetScanline( nY );
485  Scanline pRScan = pR->GetScanline( nY );
486  sal_uInt8 cBit = 128;
487 
488  for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
489  {
490  if( !cBit )
491  {
492  cBit = 128;
493  pRScan += 1;
494  }
495  if( ( *pRScan & cBit ) == cBlack )
496  {
497  pWScan[ 0 ] = color::ColorChannelMerge( pWScan[ 0 ], nB, cTrans );
498  pWScan[ 1 ] = color::ColorChannelMerge( pWScan[ 1 ], nG, cTrans );
499  pWScan[ 2 ] = color::ColorChannelMerge( pWScan[ 2 ], nR, cTrans );
500  }
501  }
502  }
503  }
504  else
505  {
506  for( nY = 0; nY < nHeight; nY++ )
507  {
508  Scanline pScanline = pW->GetScanline(nY);
509  Scanline pScanlineRead = pR->GetScanline(nY);
510  for( nX = 0; nX < nWidth; nX++ )
511  {
512  if( pR->GetPixelFromData( pScanlineRead, nX ) == aBlack )
513  {
514  aPixCol = pW->GetColor( nY, nX );
515  aPixCol.Merge(aFillCol, cTrans);
516  pW->SetPixelOnData(pScanline, nX, aPixCol);
517  }
518  }
519  }
520  }
521  }
522  }
523 
524  pR.reset();
525  pW.reset();
526 
527  DrawBitmap( aDstRect.TopLeft(), aPaint );
528 
529  EnableMapMode( bOldMap );
530 
531  if( mbLineColor )
532  {
534  SetFillColor();
535  DrawPolyPolygon( rPolyPoly );
536  Pop();
537  }
538  }
539  }
540  else
541  {
542  DrawPolyPolygon( rPolyPoly );
543  }
544  }
545  }
546 
547  mpMetaFile = pOldMetaFile;
548 
549  // #110958# Restore disabled alpha VDev
550  mpAlphaVDev = pOldAlphaVDev;
551 }
552 
554  sal_uInt16 nTransparencePercent )
555 {
557 
558  // short circuit for drawing an opaque polygon
559  if( (nTransparencePercent < 1) || (mnDrawMode & DrawModeFlags::NoTransparency) )
560  {
561  DrawPolyPolygon( rPolyPoly );
562  return;
563  }
564 
565  // short circuit for drawing an invisible polygon
566  if( !mbFillColor || (nTransparencePercent >= 100) )
567  {
568  DrawInvisiblePolygon( rPolyPoly );
569  return; // tdf#84294: do not record it in metafile
570  }
571 
572  // handle metafile recording
573  if( mpMetaFile )
574  mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
575 
576  bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
577  if( bDrawn )
578  return;
579 
580  // get the device graphics as drawing target
581  if( !mpGraphics && !AcquireGraphics() )
582  return;
583 
584  // try hard to draw it directly, because the emulation layers are slower
585  bDrawn = DrawTransparentNatively( rPolyPoly, nTransparencePercent );
586 
587  if (!bDrawn)
588  EmulateDrawTransparent( rPolyPoly, nTransparencePercent );
589 
590  // #110958# Apply alpha value also to VDev alpha channel
591  if( mpAlphaVDev )
592  {
593  const Color aFillCol( mpAlphaVDev->GetFillColor() );
594  mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
595  sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
596  sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
597 
598  mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
599 
600  mpAlphaVDev->SetFillColor( aFillCol );
601  }
602 }
603 
604 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
605  const Size& rSize, const Gradient& rTransparenceGradient )
606 {
608 
609  const Color aBlack( COL_BLACK );
610 
611  if( mpMetaFile )
612  {
613  // missing here is to map the data using the DeviceTransformation
614  mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
615  }
616 
617  if ( !IsDeviceOutputNecessary() )
618  return;
619 
620  if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
622  {
623  const_cast<GDIMetaFile&>(rMtf).WindStart();
624  const_cast<GDIMetaFile&>(rMtf).Play( this, rPos, rSize );
625  const_cast<GDIMetaFile&>(rMtf).WindStart();
626  }
627  else
628  {
629  GDIMetaFile* pOldMetaFile = mpMetaFile;
630  tools::Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
631  Point aPoint;
632  tools::Rectangle aDstRect( aPoint, GetOutputSizePixel() );
633 
634  mpMetaFile = nullptr;
635  aDstRect.Intersection( aOutRect );
636 
637  ClipToPaintRegion( aDstRect );
638 
639  if( !aDstRect.IsEmpty() )
640  {
641  // Create transparent buffer
643 
644  xVDev->mnDPIX = mnDPIX;
645  xVDev->mnDPIY = mnDPIY;
646 
647  if( xVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
648  {
650  {
651  // #i102109#
652  // For MetaFile replay (see task) it may now be necessary to take
653  // into account that the content is AntiAlialiased and needs to be masked
654  // like that. Instead of masking, i will use a copy-modify-paste cycle
655  // here (as i already use in the VclPrimiziveRenderer with success)
656  xVDev->SetAntialiasing(GetAntialiasing());
657 
658  // create MapMode for buffer (offset needed) and set
660  const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
661  aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
662  xVDev->SetMapMode(aMap);
663 
664  // copy MapMode state and disable for target
665  const bool bOrigMapModeEnabled(IsMapModeEnabled());
666  EnableMapMode(false);
667 
668  // copy MapMode state and disable for buffer
669  const bool bBufferMapModeEnabled(xVDev->IsMapModeEnabled());
670  xVDev->EnableMapMode(false);
671 
672  // copy content from original to buffer
673  xVDev->DrawOutDev( aPoint, xVDev->GetOutputSizePixel(), // dest
674  aDstRect.TopLeft(), xVDev->GetOutputSizePixel(), // source
675  *this);
676 
677  // draw MetaFile to buffer
678  xVDev->EnableMapMode(bBufferMapModeEnabled);
679  const_cast<GDIMetaFile&>(rMtf).WindStart();
680  const_cast<GDIMetaFile&>(rMtf).Play(xVDev.get(), rPos, rSize);
681  const_cast<GDIMetaFile&>(rMtf).WindStart();
682 
683  // get content bitmap from buffer
684  xVDev->EnableMapMode(false);
685 
686  const Bitmap aPaint(xVDev->GetBitmap(aPoint, xVDev->GetOutputSizePixel()));
687 
688  // create alpha mask from gradient and get as Bitmap
689  xVDev->EnableMapMode(bBufferMapModeEnabled);
690  xVDev->SetDrawMode(DrawModeFlags::GrayGradient);
691  xVDev->DrawGradient(tools::Rectangle(rPos, rSize), rTransparenceGradient);
692  xVDev->SetDrawMode(DrawModeFlags::Default);
693  xVDev->EnableMapMode(false);
694 
695  const AlphaMask aAlpha(xVDev->GetBitmap(aPoint, xVDev->GetOutputSizePixel()));
696 
697  xVDev.disposeAndClear();
698 
699  // draw masked content to target and restore MapMode
700  DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
701  EnableMapMode(bOrigMapModeEnabled);
702  }
703  else
704  {
705  MapMode aMap( GetMapMode() );
706  Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
707  const bool bOldMap = mbMap;
708 
709  aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
710  xVDev->SetMapMode( aMap );
711  const bool bVDevOldMap = xVDev->IsMapModeEnabled();
712 
713  // create paint bitmap
714  const_cast<GDIMetaFile&>(rMtf).WindStart();
715  const_cast<GDIMetaFile&>(rMtf).Play( xVDev.get(), rPos, rSize );
716  const_cast<GDIMetaFile&>(rMtf).WindStart();
717  xVDev->EnableMapMode( false );
718  BitmapEx aPaint = xVDev->GetBitmapEx(Point(), xVDev->GetOutputSizePixel());
719  xVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
720 
721  // create alpha mask from gradient
722  xVDev->SetDrawMode( DrawModeFlags::GrayGradient );
723  xVDev->DrawGradient( tools::Rectangle( rPos, rSize ), rTransparenceGradient );
724  xVDev->SetDrawMode( DrawModeFlags::Default );
725  xVDev->EnableMapMode( false );
726 
727  AlphaMask aAlpha(xVDev->GetBitmap(Point(), xVDev->GetOutputSizePixel()));
728  aAlpha.BlendWith(aPaint.GetAlpha());
729 
730  xVDev.disposeAndClear();
731 
732  EnableMapMode( false );
733  DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint.GetBitmap(), aAlpha));
734  EnableMapMode( bOldMap );
735  }
736  }
737  }
738 
739  mpMetaFile = pOldMetaFile;
740  }
741 }
742 
743 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:58
tools::Long Height() const
sal_uInt8 GetRed() const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:640
double getHeight() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
DrawModeFlags
Definition: outdev.hxx:199
virtual void ClipToPaintRegion(tools::Rectangle &rDstRect)
void Merge(const Color &rMergeColor, sal_uInt8 cTransparency)
bool IsTransparent() const
void setClosed(bool bNew)
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual bool supportsOperation(OutDevSupportType) const =0
DrawModeFlags mnDrawMode
Definition: outdev.hxx:354
long Long
void disposeAndClear()
Definition: vclptr.hxx:200
const StyleSettings & GetStyleSettings() const
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
sal_uInt8 GetLuminance() const
bool IsMapModeEnabled() const
Definition: outdev.hxx:1667
bool mbOutputClipped
Definition: outdev.hxx:379
void DrawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32 *pPoints, const Point **pPtAry, const OutputDevice &rOutDev)
SAL_DLLPRIVATE bool is_double_buffered_window() const
const MapMode & GetMapMode() const
Definition: outdev.hxx:1673
sal_Int32 mnDPIY
Definition: outdev.hxx:347
bool DrawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency, const OutputDevice &rOutDev)
SAL_DLLPRIVATE Color ImplDrawModeToColor(const Color &rColor) const
Definition: transparent.cxx:77
sal_Int32 mnDPIX
Definition: outdev.hxx:346
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:538
bool mbMap
Definition: outdev.hxx:374
AntialiasingFlags GetAntialiasing() const
Definition: outdev.hxx:604
bool IsEmpty() const
HashMap_OWString_Interface aMap
void SetPixelOnData(sal_uInt8 *pData, tools::Long nX, const BitmapColor &rBitmapColor)
SAL_DLLPRIVATE void InitLineColor()
double getWidth() const
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
Scanline GetScanline(tools::Long nY) const
int nCount
AntialiasingFlags mnAntialiasing
Definition: outdev.hxx:371
virtual Bitmap GetBitmap(const Point &rSrcPt, const Size &rSize) const
void Insert(const tools::Polygon &rPoly, sal_uInt16 nPos=POLYPOLY_APPEND)
void DrawInvisiblePolygon(const tools::PolyPolygon &rPolyPoly)
sal_uInt8 GetBlue() const
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:315
SAL_DLLPRIVATE bool DrawTransparentNatively(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
SAL_DLLPRIVATE basegfx::B2DHomMatrix ImplGetDeviceTransformation() const
Get device transformation.
Definition: map.cxx:819
virtual void SetFillColor()=0
void BlendWith(const Bitmap &rOther)
Definition: alpha.cxx:144
sal_uInt16 GetEntryCount() const
virtual void EmulateDrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
SAL_DLLPRIVATE void InitFillColor()
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
bool isClosed() const
int i
ScanlineFormat GetScanlineFormat() const
bool IsLineColor() const
Definition: outdev.hxx:631
tools::Long FRound(double fVal)
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
bool IsRect() const
void DrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:102
bool mbInitLineColor
Definition: outdev.hxx:382
void SetFillColor()
const Color & GetFontColor() const
tools::Long Width() const
void Move(tools::Long nHorzMove, tools::Long nVertMove)
void transform(const basegfx::B2DHomMatrix &rMatrix)
void DrawPolyLine(sal_uInt32 nPoints, Point const *pPtAry, const OutputDevice &rOutDev)
bool mbLineColor
Definition: outdev.hxx:380
constexpr double deg2rad(double v)
const AllSettings & GetSettings() const
Definition: outdev.hxx:418
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
virtual sal_uInt16 GetBitCount() const
Definition: outdev.cxx:302
DrawModeFlags GetDrawMode() const
Definition: outdev.hxx:607
void DrawBitmap(const Point &rDestPt, const Bitmap &rBitmap)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Size GetSize() const
sal_uInt16 GetBestIndex(const BitmapColor &rCol) const
const Color & GetStartColor() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:231
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1049
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:828
sal_uInt8 GetGreen() const
B2DRange const & getB2DRange() const
bool mbFillColor
Definition: outdev.hxx:381
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:330
double getMinY() const
sal_uInt32 count() const
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:263
::basegfx::B2DPolyPolygon getB2DPolyPolygon() const
unsigned char sal_uInt8
constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans)
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:564
bool mbInitClipRegion
Definition: outdev.hxx:386
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
const BitmapPalette & GetPalette() const
const Color & GetEndColor() const
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Render the given poly-polygon.
Definition: polygon.cxx:36
virtual void InitClipRegion()
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
RasterOp GetRasterOp() const
Definition: outdev.hxx:616
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
bool mbInitFillColor
Definition: outdev.hxx:383
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:406
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
tools::Rectangle GetBoundRect() const
double getMinX() const
bool IsFillColor() const
Definition: outdev.hxx:636
sal_uInt16 GetBitCount() const
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:601
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:59
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
const Color & GetFillColor() const
Definition: outdev.hxx:635
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:318
void Insert(sal_uInt16 nPos, const Point &rPt)