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;
129 
130  if( mbInitClipRegion )
131  InitClipRegion();
132 
133  if( mbOutputClipped )
134  return;
135 
136  if( mbInitLineColor )
137  InitLineColor();
138 
139  if( mbInitFillColor )
140  InitFillColor();
141 
144  {
145  // b2dpolygon support not implemented yet on non-UNX platforms
146  basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
147 
148  // ensure it is closed
149  if(!aB2DPolyPolygon.isClosed())
150  {
151  // maybe assert, prevents buffering due to making a copy
152  aB2DPolyPolygon.setClosed( true );
153  }
154 
155  // create ObjectToDevice transformation
156  const basegfx::B2DHomMatrix aFullTransform(ImplGetDeviceTransformation() * rObjectTransform);
157  // TODO: this must not drop transparency for mpAlphaVDev case, but instead use premultiplied
158  // alpha... but that requires using premultiplied alpha also for already drawn data
159  const double fAdjustedTransparency = mpAlphaVDev ? 0 : fTransparency;
160  bool bDrawnOk(true);
161 
162  if( IsFillColor() )
163  {
164  bDrawnOk = mpGraphics->DrawPolyPolygon(
165  aFullTransform,
166  aB2DPolyPolygon,
167  fAdjustedTransparency,
168  *this);
169  }
170 
171  if( bDrawnOk && IsLineColor() )
172  {
173  const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
174 
175  for(auto const& rPolygon : aB2DPolyPolygon)
176  {
178  aFullTransform,
179  rPolygon,
180  fAdjustedTransparency,
181  0.0, // tdf#124848 hairline
182  nullptr, // MM01
184  css::drawing::LineCap_BUTT,
185  basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
186  bPixelSnapHairline,
187  *this );
188  }
189  }
190 
191  if( bDrawnOk )
192  {
193  if( mpMetaFile )
194  {
195  // tdf#119843 need transformed Polygon here
196  basegfx::B2DPolyPolygon aB2DPolyPoly(rB2DPolyPoly);
197  aB2DPolyPoly.transform(rObjectTransform);
200  tools::PolyPolygon(aB2DPolyPoly),
201  static_cast< sal_uInt16 >(fTransparency * 100.0)));
202  }
203 
204  if (mpAlphaVDev)
205  mpAlphaVDev->DrawTransparent(rObjectTransform, rB2DPolyPoly, fTransparency);
206 
207  return;
208  }
209  }
210 
211  // fallback to old polygon drawing if needed
212  // tdf#119843 need transformed Polygon here
213  basegfx::B2DPolyPolygon aB2DPolyPoly(rB2DPolyPoly);
214  aB2DPolyPoly.transform(rObjectTransform);
216  toPolyPolygon(aB2DPolyPoly),
217  static_cast<sal_uInt16>(fTransparency * 100.0));
218 }
219 
221 {
223 
224  // short circuit if the polygon border is invisible too
225  if( !mbLineColor )
226  return;
227 
228  // we assume that the border is NOT to be drawn transparently???
230  SetFillColor();
231  DrawPolyPolygon( rPolyPoly );
232  Pop();
233 }
234 
236  sal_uInt16 nTransparencePercent )
237 {
239 
240  bool bDrawn = false;
241 
243 #if defined UNX && ! defined MACOSX && ! defined IOS
244  && GetBitCount() > 8
245 #endif
246 #ifdef _WIN32
247  // workaround bad dithering on remote displaying when using GDI+ with toolbar button highlighting
248  && !rPolyPoly.IsRect()
249 #endif
250  )
251  {
252  // prepare the graphics device
253  if( mbInitClipRegion )
254  InitClipRegion();
255 
256  if( mbOutputClipped )
257  return false;
258 
259  if( mbInitLineColor )
260  InitLineColor();
261 
262  if( mbInitFillColor )
263  InitFillColor();
264 
265  // get the polygon in device coordinates
266  basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
268 
269  const double fTransparency = 0.01 * nTransparencePercent;
270  if( mbFillColor )
271  {
272  // #i121591#
273  // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
274  // should be used when printing. Normally this is avoided by the printer being
275  // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
276  // to figure out a way of moving this code to its own function that is
277  // overridden by the Print class, which will mean we deliberately override the
278  // functionality and we use the fallback some lines below (which is not very good,
279  // though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
280  // correct the wrong mapping (see there for details)
281  bDrawn = mpGraphics->DrawPolyPolygon(
282  aTransform,
283  aB2DPolyPolygon,
284  fTransparency,
285  *this);
286  }
287 
288  if( mbLineColor )
289  {
290  // disable the fill color for now
292 
293  // draw the border line
294  const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline);
295 
296  for(auto const& rPolygon : aB2DPolyPolygon)
297  {
298  bDrawn = mpGraphics->DrawPolyLine(
299  aTransform,
300  rPolygon,
301  fTransparency,
302  0.0, // tdf#124848 hairline
303  nullptr, // MM01
305  css::drawing::LineCap_BUTT,
306  basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default
307  bPixelSnapHairline,
308  *this );
309  }
310 
311  // prepare to restore the fill color
313  }
314  }
315 
316  return bDrawn;
317 }
318 
320  sal_uInt16 nTransparencePercent )
321 {
322  // #110958# Disable alpha VDev, we perform the necessary
323  VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
324 
325  // operation explicitly further below.
326  if( mpAlphaVDev )
327  mpAlphaVDev = nullptr;
328 
329  GDIMetaFile* pOldMetaFile = mpMetaFile;
330  mpMetaFile = nullptr;
331 
332  tools::PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
333  tools::Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
334  tools::Rectangle aDstRect( Point(), GetOutputSizePixel() );
335 
336  aDstRect.Intersection( aPolyRect );
337 
338  ClipToPaintRegion( aDstRect );
339 
340  if( !aDstRect.IsEmpty() )
341  {
342  bool bDrawn = false;
343 
344  // #i66849# Added fast path for exactly rectangular
345  // polygons
346  // #i83087# Naturally, system alpha blending cannot
347  // work with separate alpha VDev
348  if( !mpAlphaVDev && aPolyPoly.IsRect() )
349  {
350  // setup Graphics only here (other cases delegate
351  // to basic OutDev methods)
352  if ( mbInitClipRegion )
353  InitClipRegion();
354 
355  if ( mbInitLineColor )
356  InitLineColor();
357 
358  if ( mbInitFillColor )
359  InitFillColor();
360 
361  tools::Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
362  tools::Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
363 
364  if( !mbOutputClipped )
365  {
366  bDrawn = mpGraphics->DrawAlphaRect( aPixelRect.Left(), aPixelRect.Top(),
367  // #i98405# use methods with small g, else one pixel too much will be painted.
368  // This is because the source is a polygon which when painted would not paint
369  // the rightmost and lowest pixel line(s), so use one pixel less for the
370  // rectangle, too.
371  aPixelRect.getWidth(), aPixelRect.getHeight(),
372  sal::static_int_cast<sal_uInt8>(nTransparencePercent),
373  *this );
374  }
375  else
376  {
377  bDrawn = true;
378  }
379  }
380 
381  if( !bDrawn )
382  {
384  const Size aDstSz( aDstRect.GetSize() );
385  const sal_uInt8 cTrans = static_cast<sal_uInt8>(MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 ));
386 
387  if( aDstRect.Left() || aDstRect.Top() )
388  aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
389 
390  if( aVDev->SetOutputSizePixel( aDstSz ) )
391  {
392  const bool bOldMap = mbMap;
393 
394  EnableMapMode( false );
395 
396  aVDev->SetLineColor( COL_BLACK );
397  aVDev->SetFillColor( COL_BLACK );
398  aVDev->DrawPolyPolygon( aPolyPoly );
399 
400  Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
401  Bitmap aPolyMask( aVDev->GetBitmap( Point(), aDstSz ) );
402 
403  // #107766# check for non-empty bitmaps before accessing them
404  if( !aPaint.IsEmpty() && !aPolyMask.IsEmpty() )
405  {
406  BitmapScopedWriteAccess pW(aPaint);
407  Bitmap::ScopedReadAccess pR(aPolyMask);
408 
409  if( pW && pR )
410  {
411  BitmapColor aPixCol;
412  const BitmapColor aFillCol( GetFillColor() );
413  const BitmapColor aBlack( pR->GetBestMatchingColor( COL_BLACK ) );
414  const tools::Long nWidth = pW->Width();
415  const tools::Long nHeight = pW->Height();
416  const tools::Long nR = aFillCol.GetRed();
417  const tools::Long nG = aFillCol.GetGreen();
418  const tools::Long nB = aFillCol.GetBlue();
419  tools::Long nX, nY;
420 
422  {
423  const BitmapPalette& rPal = pW->GetPalette();
424  const sal_uInt16 nCount = rPal.GetEntryCount();
425  std::unique_ptr<sal_uInt8[]> xMap(new sal_uInt8[ nCount * sizeof( BitmapColor )]);
426  BitmapColor* pMap = reinterpret_cast<BitmapColor*>(xMap.get());
427 
428  for( sal_uInt16 i = 0; i < nCount; i++ )
429  {
430  BitmapColor aCol( rPal[ i ] );
431  aCol.Merge( aFillCol, cTrans );
432  pMap[ i ] = BitmapColor( static_cast<sal_uInt8>(rPal.GetBestIndex( aCol )) );
433  }
434 
436  pW->GetScanlineFormat() == ScanlineFormat::N8BitPal )
437  {
438  const sal_uInt8 cBlack = aBlack.GetIndex();
439 
440  for( nY = 0; nY < nHeight; nY++ )
441  {
442  Scanline pWScan = pW->GetScanline( nY );
443  Scanline pRScan = pR->GetScanline( nY );
444  sal_uInt8 cBit = 128;
445 
446  for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
447  {
448  if( !cBit )
449  {
450  cBit = 128;
451  pRScan += 1;
452  }
453  if( ( *pRScan & cBit ) == cBlack )
454  {
455  *pWScan = pMap[ *pWScan ].GetIndex();
456  }
457  }
458  }
459  }
460  else
461  {
462  for( nY = 0; nY < nHeight; nY++ )
463  {
464  Scanline pScanline = pW->GetScanline(nY);
465  Scanline pScanlineRead = pR->GetScanline(nY);
466  for( nX = 0; nX < nWidth; nX++ )
467  {
468  if( pR->GetPixelFromData( pScanlineRead, nX ) == aBlack )
469  {
470  pW->SetPixelOnData( pScanline, nX, pMap[ pW->GetIndexFromData( pScanline, nX ) ] );
471  }
472  }
473  }
474  }
475  }
476  else
477  {
479  pW->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr )
480  {
481  const sal_uInt8 cBlack = aBlack.GetIndex();
482 
483  for( nY = 0; nY < nHeight; nY++ )
484  {
485  Scanline pWScan = pW->GetScanline( nY );
486  Scanline pRScan = pR->GetScanline( nY );
487  sal_uInt8 cBit = 128;
488 
489  for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
490  {
491  if( !cBit )
492  {
493  cBit = 128;
494  pRScan += 1;
495  }
496  if( ( *pRScan & cBit ) == cBlack )
497  {
498  pWScan[ 0 ] = color::ColorChannelMerge( pWScan[ 0 ], nB, cTrans );
499  pWScan[ 1 ] = color::ColorChannelMerge( pWScan[ 1 ], nG, cTrans );
500  pWScan[ 2 ] = color::ColorChannelMerge( pWScan[ 2 ], nR, cTrans );
501  }
502  }
503  }
504  }
505  else
506  {
507  for( nY = 0; nY < nHeight; nY++ )
508  {
509  Scanline pScanline = pW->GetScanline(nY);
510  Scanline pScanlineRead = pR->GetScanline(nY);
511  for( nX = 0; nX < nWidth; nX++ )
512  {
513  if( pR->GetPixelFromData( pScanlineRead, nX ) == aBlack )
514  {
515  aPixCol = pW->GetColor( nY, nX );
516  aPixCol.Merge(aFillCol, cTrans);
517  pW->SetPixelOnData(pScanline, nX, aPixCol);
518  }
519  }
520  }
521  }
522  }
523  }
524 
525  pR.reset();
526  pW.reset();
527 
528  DrawBitmap( aDstRect.TopLeft(), aPaint );
529 
530  EnableMapMode( bOldMap );
531 
532  if( mbLineColor )
533  {
535  SetFillColor();
536  DrawPolyPolygon( rPolyPoly );
537  Pop();
538  }
539  }
540  }
541  else
542  {
543  DrawPolyPolygon( rPolyPoly );
544  }
545  }
546  }
547 
548  mpMetaFile = pOldMetaFile;
549 
550  // #110958# Restore disabled alpha VDev
551  mpAlphaVDev = pOldAlphaVDev;
552 }
553 
555  sal_uInt16 nTransparencePercent )
556 {
558 
559  // short circuit for drawing an opaque polygon
560  if( (nTransparencePercent < 1) || (mnDrawMode & DrawModeFlags::NoTransparency) )
561  {
562  DrawPolyPolygon( rPolyPoly );
563  return;
564  }
565 
566  // short circuit for drawing an invisible polygon
567  if( !mbFillColor || (nTransparencePercent >= 100) )
568  {
569  DrawInvisiblePolygon( rPolyPoly );
570  return; // tdf#84294: do not record it in metafile
571  }
572 
573  // handle metafile recording
574  if( mpMetaFile )
575  mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
576 
577  bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
578  if( bDrawn )
579  return;
580 
581  // get the device graphics as drawing target
582  if( !mpGraphics && !AcquireGraphics() )
583  return;
585 
586  // try hard to draw it directly, because the emulation layers are slower
587  bDrawn = DrawTransparentNatively( rPolyPoly, nTransparencePercent );
588 
589  if (!bDrawn)
590  EmulateDrawTransparent( rPolyPoly, nTransparencePercent );
591 
592  // #110958# Apply alpha value also to VDev alpha channel
593  if( mpAlphaVDev )
594  {
595  const Color aFillCol( mpAlphaVDev->GetFillColor() );
596  mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
597  sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
598  sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
599 
600  mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
601 
602  mpAlphaVDev->SetFillColor( aFillCol );
603  }
604 }
605 
606 void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
607  const Size& rSize, const Gradient& rTransparenceGradient )
608 {
610 
611  const Color aBlack( COL_BLACK );
612 
613  if( mpMetaFile )
614  {
615  // missing here is to map the data using the DeviceTransformation
616  mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
617  }
618 
619  if ( !IsDeviceOutputNecessary() )
620  return;
621 
622  if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
624  {
625  const_cast<GDIMetaFile&>(rMtf).WindStart();
626  const_cast<GDIMetaFile&>(rMtf).Play( this, rPos, rSize );
627  const_cast<GDIMetaFile&>(rMtf).WindStart();
628  }
629  else
630  {
631  GDIMetaFile* pOldMetaFile = mpMetaFile;
632  tools::Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
633  Point aPoint;
634  tools::Rectangle aDstRect( aPoint, GetOutputSizePixel() );
635 
636  mpMetaFile = nullptr;
637  aDstRect.Intersection( aOutRect );
638 
639  ClipToPaintRegion( aDstRect );
640 
641  if( !aDstRect.IsEmpty() )
642  {
643  // Create transparent buffer
645 
646  xVDev->mnDPIX = mnDPIX;
647  xVDev->mnDPIY = mnDPIY;
648 
649  if( xVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
650  {
652  {
653  // #i102109#
654  // For MetaFile replay (see task) it may now be necessary to take
655  // into account that the content is AntiAlialiased and needs to be masked
656  // like that. Instead of masking, i will use a copy-modify-paste cycle
657  // here (as i already use in the VclPrimiziveRenderer with success)
658  xVDev->SetAntialiasing(GetAntialiasing());
659 
660  // create MapMode for buffer (offset needed) and set
662  const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
663  aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
664  xVDev->SetMapMode(aMap);
665 
666  // copy MapMode state and disable for target
667  const bool bOrigMapModeEnabled(IsMapModeEnabled());
668  EnableMapMode(false);
669 
670  // copy MapMode state and disable for buffer
671  const bool bBufferMapModeEnabled(xVDev->IsMapModeEnabled());
672  xVDev->EnableMapMode(false);
673 
674  // copy content from original to buffer
675  xVDev->DrawOutDev( aPoint, xVDev->GetOutputSizePixel(), // dest
676  aDstRect.TopLeft(), xVDev->GetOutputSizePixel(), // source
677  *this);
678 
679  // draw MetaFile to buffer
680  xVDev->EnableMapMode(bBufferMapModeEnabled);
681  const_cast<GDIMetaFile&>(rMtf).WindStart();
682  const_cast<GDIMetaFile&>(rMtf).Play(xVDev.get(), rPos, rSize);
683  const_cast<GDIMetaFile&>(rMtf).WindStart();
684 
685  // get content bitmap from buffer
686  xVDev->EnableMapMode(false);
687 
688  const Bitmap aPaint(xVDev->GetBitmap(aPoint, xVDev->GetOutputSizePixel()));
689 
690  // create alpha mask from gradient and get as Bitmap
691  xVDev->EnableMapMode(bBufferMapModeEnabled);
692  xVDev->SetDrawMode(DrawModeFlags::GrayGradient);
693  xVDev->DrawGradient(tools::Rectangle(rPos, rSize), rTransparenceGradient);
694  xVDev->SetDrawMode(DrawModeFlags::Default);
695  xVDev->EnableMapMode(false);
696 
697  const AlphaMask aAlpha(xVDev->GetBitmap(aPoint, xVDev->GetOutputSizePixel()));
698 
699  xVDev.disposeAndClear();
700 
701  // draw masked content to target and restore MapMode
702  DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
703  EnableMapMode(bOrigMapModeEnabled);
704  }
705  else
706  {
707  MapMode aMap( GetMapMode() );
708  Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
709  const bool bOldMap = mbMap;
710 
711  aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
712  xVDev->SetMapMode( aMap );
713  const bool bVDevOldMap = xVDev->IsMapModeEnabled();
714 
715  // create paint bitmap
716  const_cast<GDIMetaFile&>(rMtf).WindStart();
717  const_cast<GDIMetaFile&>(rMtf).Play( xVDev.get(), rPos, rSize );
718  const_cast<GDIMetaFile&>(rMtf).WindStart();
719  xVDev->EnableMapMode( false );
720  BitmapEx aPaint = xVDev->GetBitmapEx(Point(), xVDev->GetOutputSizePixel());
721  xVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
722 
723  // create alpha mask from gradient
724  xVDev->SetDrawMode( DrawModeFlags::GrayGradient );
725  xVDev->DrawGradient( tools::Rectangle( rPos, rSize ), rTransparenceGradient );
726  xVDev->SetDrawMode( DrawModeFlags::Default );
727  xVDev->EnableMapMode( false );
728 
729  AlphaMask aAlpha(xVDev->GetBitmap(Point(), xVDev->GetOutputSizePixel()));
730  aAlpha.BlendWith(aPaint.GetAlpha());
731 
732  xVDev.disposeAndClear();
733 
734  EnableMapMode( false );
735  DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint.GetBitmap(), aAlpha));
736  EnableMapMode( bOldMap );
737  }
738  }
739  }
740 
741  mpMetaFile = pOldMetaFile;
742  }
743 }
744 
745 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
sal_uInt8 GetRed() const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:644
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)
constexpr bool isPalettePixelFormat(PixelFormat ePixelFormat)
Is it a pixel format that forces creation of a palette.
Definition: BitmapTypes.hxx:29
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:1684
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:1690
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
This template handles BitmapAccess the RAII way.
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:508
bool mbMap
Definition: outdev.hxx:374
AntialiasingFlags GetAntialiasing() const
Definition: outdev.hxx:608
bool IsEmpty() const
HashMap_OWString_Interface aMap
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:791
virtual void SetFillColor()=0
void BlendWith(const Bitmap &rOther)
Definition: alpha.cxx:121
sal_uInt16 GetEntryCount() const
virtual void EmulateDrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
SAL_DLLPRIVATE void InitFillColor()
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
vcl::PixelFormat getPixelFormat() const
bool isClosed() const
int i
ScanlineFormat GetScanlineFormat() const
bool IsLineColor() const
Definition: outdev.hxx:635
tools::Long FRound(double fVal)
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
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
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:308
DrawModeFlags GetDrawMode() const
Definition: outdev.hxx:611
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:229
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1021
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:800
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:256
::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 Color & GetEndColor() const
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Render the given poly-polygon.
Definition: polygon.cxx:36
virtual void InitClipRegion()
bool IsEmpty() const
Definition: bitmap.hxx:547
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
RasterOp GetRasterOp() const
Definition: outdev.hxx:620
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:376
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
tools::Rectangle GetBoundRect() const
double getMinX() const
bool IsFillColor() const
Definition: outdev.hxx:640
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:605
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:59
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
const Color & GetFillColor() const
Definition: outdev.hxx:639
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:318
void Insert(sal_uInt16 nPos, const Point &rPt)