LibreOffice Module vcl (master)  1
outdev/bitmap.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <config_features.h>
21 
22 #include <osl/diagnose.h>
23 #include <tools/debug.hxx>
24 #include <tools/helpers.hxx>
25 
26 #include <vcl/image.hxx>
27 #include <vcl/metaact.hxx>
28 #include <vcl/skia/SkiaHelper.hxx>
29 #include <vcl/virdev.hxx>
30 
32 #include <bitmap/bmpfast.hxx>
33 #include <drawmode.hxx>
34 #include <salbmp.hxx>
35 #include <salgdi.hxx>
36 
37 void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
38 {
39  assert(!is_double_buffered_window());
40 
41  const Size aSizePix( rBitmap.GetSizePixel() );
42  DrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, MetaActionType::BMP );
43 }
44 
45 void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
46 {
47  assert(!is_double_buffered_window());
48 
49  DrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, MetaActionType::BMPSCALE );
50 }
51 
52 void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
53  const Point& rSrcPtPixel, const Size& rSrcSizePixel,
54  const Bitmap& rBitmap)
55 {
56  assert(!is_double_buffered_window());
57 
58  DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, MetaActionType::BMPSCALEPART );
59 }
60 
61 void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
62  const Point& rSrcPtPixel, const Size& rSrcSizePixel,
63  const Bitmap& rBitmap, const MetaActionType nAction )
64 {
65  assert(!is_double_buffered_window());
66 
67  if( ImplIsRecordLayout() )
68  return;
69 
71  {
72  DrawRect( tools::Rectangle( rDestPt, rDestSize ) );
73  return;
74  }
75 
76  Bitmap aBmp( rBitmap );
77 
80  {
82  {
83  sal_uInt8 cCmpVal;
84 
86  cCmpVal = 0;
87  else
88  cCmpVal = 255;
89 
90  Color aCol( cCmpVal, cCmpVal, cCmpVal );
92  SetLineColor( aCol );
93  SetFillColor( aCol );
94  DrawRect( tools::Rectangle( rDestPt, rDestSize ) );
95  Pop();
96  return;
97  }
98  else if( !aBmp.IsEmpty() )
99  {
102  }
103  }
104 
105  if ( mpMetaFile )
106  {
107  switch( nAction )
108  {
109  case MetaActionType::BMP:
110  mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
111  break;
112 
114  mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
115  break;
116 
118  mpMetaFile->AddAction( new MetaBmpScalePartAction(
119  rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
120  break;
121 
122  default: break;
123  }
124  }
125 
126  if ( !IsDeviceOutputNecessary() )
127  return;
128 
129  if (!mpGraphics && !AcquireGraphics())
130  return;
131  assert(mpGraphics);
132 
133  if ( mbInitClipRegion )
134  InitClipRegion();
135 
136  if ( mbOutputClipped )
137  return;
138 
139  if( !aBmp.IsEmpty() )
140  {
141  SalTwoRect aPosAry(rSrcPtPixel.X(), rSrcPtPixel.Y(), rSrcSizePixel.Width(), rSrcSizePixel.Height(),
142  ImplLogicXToDevicePixel(rDestPt.X()), ImplLogicYToDevicePixel(rDestPt.Y()),
143  ImplLogicWidthToDevicePixel(rDestSize.Width()),
144  ImplLogicHeightToDevicePixel(rDestSize.Height()));
145 
146  if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
147  {
148  const BmpMirrorFlags nMirrFlags = AdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
149 
150  if ( nMirrFlags != BmpMirrorFlags::NONE )
151  aBmp.Mirror( nMirrFlags );
152 
153  if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
154  {
155  if (nAction == MetaActionType::BMPSCALE && CanSubsampleBitmap())
156  {
157  const double nScaleX = aPosAry.mnDestWidth / static_cast<double>(aPosAry.mnSrcWidth);
158  const double nScaleY = aPosAry.mnDestHeight / static_cast<double>(aPosAry.mnSrcHeight);
159 
160  // If subsampling, use Bitmap::Scale() for subsampling of better quality.
161  if ( nScaleX < 1.0 || nScaleY < 1.0 )
162  {
163  aBmp.Scale(nScaleX, nScaleY);
164  aPosAry.mnSrcWidth = aPosAry.mnDestWidth;
165  aPosAry.mnSrcHeight = aPosAry.mnDestHeight;
166  }
167  }
168 
169  mpGraphics->DrawBitmap( aPosAry, *aBmp.ImplGetSalBitmap(), *this );
170  }
171  }
172  }
173 
174  if( mpAlphaVDev )
175  {
176  // #i32109#: Make bitmap area opaque
177  mpAlphaVDev->ImplFillOpaqueRectangle( tools::Rectangle(rDestPt, rDestSize) );
178  }
179 }
180 
181 Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
182 {
183  Bitmap aBmp;
184  tools::Long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
185  tools::Long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
186  tools::Long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
187  tools::Long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
188 
189  if ( mpGraphics || AcquireGraphics() )
190  {
191  assert(mpGraphics);
192 
193  if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
194  {
195  tools::Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
196  bool bClipped = false;
197 
198  // X-Coordinate outside of draw area?
199  if ( nX < mnOutOffX )
200  {
201  nWidth -= ( mnOutOffX - nX );
202  nX = mnOutOffX;
203  bClipped = true;
204  }
205 
206  // Y-Coordinate outside of draw area?
207  if ( nY < mnOutOffY )
208  {
209  nHeight -= ( mnOutOffY - nY );
210  nY = mnOutOffY;
211  bClipped = true;
212  }
213 
214  // Width outside of draw area?
215  if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
216  {
217  nWidth = mnOutOffX + mnOutWidth - nX;
218  bClipped = true;
219  }
220 
221  // Height outside of draw area?
222  if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
223  {
224  nHeight = mnOutOffY + mnOutHeight - nY;
225  bClipped = true;
226  }
227 
228  if ( bClipped )
229  {
230  // If the visible part has been clipped, we have to create a
231  // Bitmap with the correct size in which we copy the clipped
232  // Bitmap to the correct position.
234 
235  if ( aVDev->SetOutputSizePixel( aRect.GetSize() ) )
236  {
237  if ( aVDev->mpGraphics || aVDev->AcquireGraphics() )
238  {
239  if ( (nWidth > 0) && (nHeight > 0) )
240  {
241  SalTwoRect aPosAry(nX, nY, nWidth, nHeight,
242  (aRect.Left() < mnOutOffX) ? (mnOutOffX - aRect.Left()) : 0L,
243  (aRect.Top() < mnOutOffY) ? (mnOutOffY - aRect.Top()) : 0L,
244  nWidth, nHeight);
245  aVDev->mpGraphics->CopyBits(aPosAry, *mpGraphics, *this, *this);
246  }
247  else
248  {
249  OSL_ENSURE(false, "CopyBits with zero or negative width or height");
250  }
251 
252  aBmp = aVDev->GetBitmap( Point(), aVDev->GetOutputSizePixel() );
253  }
254  else
255  bClipped = false;
256  }
257  else
258  bClipped = false;
259  }
260 
261  if ( !bClipped )
262  {
263  std::shared_ptr<SalBitmap> pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, *this );
264 
265  if( pSalBmp )
266  {
267  aBmp.ImplSetSalBitmap(pSalBmp);
268  }
269  }
270  }
271  }
272 
273  return aBmp;
274 }
275 
276 void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& rAlpha,
277  const Point& rDestPt, const Size& rDestSize,
278  const Point& rSrcPtPixel, const Size& rSrcSizePixel )
279 {
280  assert(!is_double_buffered_window());
281 
282  Point aOutPt(LogicToPixel(rDestPt));
283  Size aOutSz(LogicToPixel(rDestSize));
285 
286  const bool bHMirr = aOutSz.Width() < 0;
287  const bool bVMirr = aOutSz.Height() < 0;
288 
289  ClipToPaintRegion(aDstRect);
290 
291  BmpMirrorFlags mirrorFlags = BmpMirrorFlags::NONE;
292  if (bHMirr)
293  {
294  aOutSz.setWidth( -aOutSz.Width() );
295  aOutPt.AdjustX( -(aOutSz.Width() - 1) );
296  mirrorFlags |= BmpMirrorFlags::Horizontal;
297  }
298 
299  if (bVMirr)
300  {
301  aOutSz.setHeight( -aOutSz.Height() );
302  aOutPt.AdjustY( -(aOutSz.Height() - 1) );
303  mirrorFlags |= BmpMirrorFlags::Vertical;
304  }
305 
306  if (aDstRect.Intersection(tools::Rectangle(aOutPt, aOutSz)).IsEmpty())
307  return;
308 
309  {
310  Point aRelPt = aOutPt + Point(mnOutOffX, mnOutOffY);
311  SalTwoRect aTR(
312  rSrcPtPixel.X(), rSrcPtPixel.Y(),
313  rSrcSizePixel.Width(), rSrcSizePixel.Height(),
314  aRelPt.X(), aRelPt.Y(),
315  aOutSz.Width(), aOutSz.Height());
316 
317  Bitmap bitmap(rBmp);
318  AlphaMask alpha(rAlpha);
319  if(bHMirr || bVMirr)
320  {
321  bitmap.Mirror(mirrorFlags);
322  alpha.Mirror(mirrorFlags);
323  }
324  SalBitmap* pSalSrcBmp = bitmap.ImplGetSalBitmap().get();
325  SalBitmap* pSalAlphaBmp = alpha.ImplGetSalBitmap().get();
326 
327  // #i83087# Naturally, system alpha blending (SalGraphics::DrawAlphaBitmap) cannot work
328  // with separate alpha VDev
329 
330  // try to blend the alpha bitmap with the alpha virtual device
331  if (mpAlphaVDev)
332  {
333  Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aRelPt, aOutSz ) );
334  if (SalBitmap* pSalAlphaBmp2 = aAlphaBitmap.ImplGetSalBitmap().get())
335  {
336  if (mpGraphics->BlendAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, *pSalAlphaBmp2, *this))
337  {
338  mpAlphaVDev->BlendBitmap(aTR, rAlpha);
339  return;
340  }
341  }
342  }
343  else
344  {
345  if (mpGraphics->DrawAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, *this))
346  return;
347  }
348 
349  // we need to make sure Skia never reaches this slow code path
350  assert(!SkiaHelper::isVCLSkiaEnabled());
351  }
352 
353  tools::Rectangle aBmpRect(Point(), rBmp.GetSizePixel());
354  if (aBmpRect.Intersection(tools::Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty())
355  return;
356 
357  Point auxOutPt(LogicToPixel(rDestPt));
358  Size auxOutSz(LogicToPixel(rDestSize));
359 
360  // HACK: The function is broken with alpha vdev and mirroring, mirror here.
361  Bitmap bitmap(rBmp);
362  AlphaMask alpha(rAlpha);
363  if(mpAlphaVDev && (bHMirr || bVMirr))
364  {
365  bitmap.Mirror(mirrorFlags);
366  alpha.Mirror(mirrorFlags);
367  auxOutPt = aOutPt;
368  auxOutSz = aOutSz;
369  }
370  DrawDeviceAlphaBitmapSlowPath(bitmap, alpha, aDstRect, aBmpRect, auxOutSz, auxOutPt);
371 }
372 
373 namespace
374 {
375 
376 struct LinearScaleContext
377 {
378  std::unique_ptr<tools::Long[]> mpMapX;
379  std::unique_ptr<tools::Long[]> mpMapY;
380 
381  std::unique_ptr<tools::Long[]> mpMapXOffset;
382  std::unique_ptr<tools::Long[]> mpMapYOffset;
383 
384  LinearScaleContext(tools::Rectangle const & aDstRect, tools::Rectangle const & aBitmapRect,
385  Size const & aOutSize, tools::Long nOffX, tools::Long nOffY)
386 
387  : mpMapX(new tools::Long[aDstRect.GetWidth()])
388  , mpMapY(new tools::Long[aDstRect.GetHeight()])
389  , mpMapXOffset(new tools::Long[aDstRect.GetWidth()])
390  , mpMapYOffset(new tools::Long[aDstRect.GetHeight()])
391  {
392  const tools::Long nSrcWidth = aBitmapRect.GetWidth();
393  const tools::Long nSrcHeight = aBitmapRect.GetHeight();
394 
395  generateSimpleMap(
396  nSrcWidth, aDstRect.GetWidth(), aBitmapRect.Left(),
397  aOutSize.Width(), nOffX, mpMapX.get(), mpMapXOffset.get());
398 
399  generateSimpleMap(
400  nSrcHeight, aDstRect.GetHeight(), aBitmapRect.Top(),
401  aOutSize.Height(), nOffY, mpMapY.get(), mpMapYOffset.get());
402  }
403 
404 private:
405 
406  static void generateSimpleMap(tools::Long nSrcDimension, tools::Long nDstDimension, tools::Long nDstLocation,
407  tools::Long nOutDimension, tools::Long nOffset, tools::Long* pMap, tools::Long* pMapOffset)
408  {
409 
410  const double fReverseScale = (std::abs(nOutDimension) > 1) ? (nSrcDimension - 1) / double(std::abs(nOutDimension) - 1) : 0.0;
411 
412  tools::Long nSampleRange = std::max(tools::Long(0), nSrcDimension - 2);
413 
414  for (tools::Long i = 0; i < nDstDimension; i++)
415  {
416  double fTemp = std::abs((nOffset + i) * fReverseScale);
417 
418  pMap[i] = MinMax(nDstLocation + tools::Long(fTemp), 0, nSampleRange);
419  pMapOffset[i] = static_cast<tools::Long>((fTemp - pMap[i]) * 128.0);
420  }
421  }
422 
423 public:
424  bool blendBitmap(
425  const BitmapWriteAccess* pDestination,
426  const BitmapReadAccess* pSource,
427  const BitmapReadAccess* pSourceAlpha,
428  const tools::Long nDstWidth,
429  const tools::Long nDstHeight)
430  {
431  if (pSource && pSourceAlpha && pDestination)
432  {
433  ScanlineFormat nSourceFormat = pSource->GetScanlineFormat();
434  ScanlineFormat nDestinationFormat = pDestination->GetScanlineFormat();
435 
436  switch (nSourceFormat)
437  {
440  {
441  if ( (nSourceFormat == ScanlineFormat::N24BitTcBgr && nDestinationFormat == ScanlineFormat::N32BitTcBgra)
442  || (nSourceFormat == ScanlineFormat::N24BitTcRgb && nDestinationFormat == ScanlineFormat::N32BitTcRgba))
443  {
444  blendBitmap24(pDestination, pSource, pSourceAlpha, nDstWidth, nDstHeight);
445  return true;
446  }
447  }
448  break;
449  default: break;
450  }
451  }
452  return false;
453  }
454 
455  void blendBitmap24(
456  const BitmapWriteAccess* pDestination,
457  const BitmapReadAccess* pSource,
458  const BitmapReadAccess* pSourceAlpha,
459  const tools::Long nDstWidth,
460  const tools::Long nDstHeight)
461  {
462  Scanline pLine0, pLine1;
463  Scanline pLineAlpha0, pLineAlpha1;
464  Scanline pColorSample1, pColorSample2;
465  Scanline pDestScanline;
466 
467  tools::Long nColor1Line1, nColor2Line1, nColor3Line1;
468  tools::Long nColor1Line2, nColor2Line2, nColor3Line2;
469  tools::Long nAlphaLine1, nAlphaLine2;
470 
471  sal_uInt8 nColor1, nColor2, nColor3, nAlpha;
472 
473  for (tools::Long nY = 0; nY < nDstHeight; nY++)
474  {
475  const tools::Long nMapY = mpMapY[nY];
476  const tools::Long nMapFY = mpMapYOffset[nY];
477 
478  pLine0 = pSource->GetScanline(nMapY);
479  // tdf#95481 guard nMapY + 1 to be within bounds
480  pLine1 = (nMapY + 1 < pSource->Height()) ? pSource->GetScanline(nMapY + 1) : pLine0;
481 
482  pLineAlpha0 = pSourceAlpha->GetScanline(nMapY);
483  // tdf#95481 guard nMapY + 1 to be within bounds
484  pLineAlpha1 = (nMapY + 1 < pSourceAlpha->Height()) ? pSourceAlpha->GetScanline(nMapY + 1) : pLineAlpha0;
485 
486  pDestScanline = pDestination->GetScanline(nY);
487 
488  for (tools::Long nX = 0; nX < nDstWidth; nX++)
489  {
490  const tools::Long nMapX = mpMapX[nX];
491  const tools::Long nMapFX = mpMapXOffset[nX];
492 
493  pColorSample1 = pLine0 + 3 * nMapX;
494  pColorSample2 = (nMapX + 1 < pSource->Width()) ? pColorSample1 + 3 : pColorSample1;
495  nColor1Line1 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
496 
497  pColorSample1++;
498  pColorSample2++;
499  nColor2Line1 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
500 
501  pColorSample1++;
502  pColorSample2++;
503  nColor3Line1 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
504 
505  pColorSample1 = pLine1 + 3 * nMapX;
506  pColorSample2 = (nMapX + 1 < pSource->Width()) ? pColorSample1 + 3 : pColorSample1;
507  nColor1Line2 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
508 
509  pColorSample1++;
510  pColorSample2++;
511  nColor2Line2 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
512 
513  pColorSample1++;
514  pColorSample2++;
515  nColor3Line2 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
516 
517  pColorSample1 = pLineAlpha0 + nMapX;
518  pColorSample2 = (nMapX + 1 < pSourceAlpha->Width()) ? pColorSample1 + 1 : pColorSample1;
519  nAlphaLine1 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
520 
521  pColorSample1 = pLineAlpha1 + nMapX;
522  pColorSample2 = (nMapX + 1 < pSourceAlpha->Width()) ? pColorSample1 + 1 : pColorSample1;
523  nAlphaLine2 = (static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
524 
525  nColor1 = (nColor1Line1 + nMapFY * ((nColor1Line2 >> 7) - (nColor1Line1 >> 7))) >> 7;
526  nColor2 = (nColor2Line1 + nMapFY * ((nColor2Line2 >> 7) - (nColor2Line1 >> 7))) >> 7;
527  nColor3 = (nColor3Line1 + nMapFY * ((nColor3Line2 >> 7) - (nColor3Line1 >> 7))) >> 7;
528 
529  nAlpha = (nAlphaLine1 + nMapFY * ((nAlphaLine2 >> 7) - (nAlphaLine1 >> 7))) >> 7;
530 
531  *pDestScanline = color::ColorChannelMerge(*pDestScanline, nColor1, nAlpha);
532  pDestScanline++;
533  *pDestScanline = color::ColorChannelMerge(*pDestScanline, nColor2, nAlpha);
534  pDestScanline++;
535  *pDestScanline = color::ColorChannelMerge(*pDestScanline, nColor3, nAlpha);
536  pDestScanline++;
537  pDestScanline++;
538  }
539  }
540  }
541 };
542 
543 struct TradScaleContext
544 {
545  std::unique_ptr<tools::Long[]> mpMapX;
546  std::unique_ptr<tools::Long[]> mpMapY;
547 
548  TradScaleContext(tools::Rectangle const & aDstRect, tools::Rectangle const & aBitmapRect,
549  Size const & aOutSize, tools::Long nOffX, tools::Long nOffY)
550 
551  : mpMapX(new tools::Long[aDstRect.GetWidth()])
552  , mpMapY(new tools::Long[aDstRect.GetHeight()])
553  {
554  const tools::Long nSrcWidth = aBitmapRect.GetWidth();
555  const tools::Long nSrcHeight = aBitmapRect.GetHeight();
556 
557  const bool bHMirr = aOutSize.Width() < 0;
558  const bool bVMirr = aOutSize.Height() < 0;
559 
560  generateSimpleMap(
561  nSrcWidth, aDstRect.GetWidth(), aBitmapRect.Left(),
562  aOutSize.Width(), nOffX, bHMirr, mpMapX.get());
563 
564  generateSimpleMap(
565  nSrcHeight, aDstRect.GetHeight(), aBitmapRect.Top(),
566  aOutSize.Height(), nOffY, bVMirr, mpMapY.get());
567  }
568 
569 private:
570 
571  static void generateSimpleMap(tools::Long nSrcDimension, tools::Long nDstDimension, tools::Long nDstLocation,
572  tools::Long nOutDimension, tools::Long nOffset, bool bMirror, tools::Long* pMap)
573  {
574  tools::Long nMirrorOffset = 0;
575 
576  if (bMirror)
577  nMirrorOffset = (nDstLocation << 1) + nSrcDimension - 1;
578 
579  for (tools::Long i = 0; i < nDstDimension; ++i, ++nOffset)
580  {
581  pMap[i] = nDstLocation + nOffset * nSrcDimension / nOutDimension;
582  if (bMirror)
583  pMap[i] = nMirrorOffset - pMap[i];
584  }
585  }
586 };
587 
588 
589 } // end anonymous namespace
590 
592  const AlphaMask& rAlpha, tools::Rectangle aDstRect, tools::Rectangle aBmpRect, Size const & aOutSize, Point const & aOutPoint)
593 {
594  assert(!is_double_buffered_window());
595 
596  VirtualDevice* pOldVDev = mpAlphaVDev;
597 
598  const bool bHMirr = aOutSize.Width() < 0;
599  const bool bVMirr = aOutSize.Height() < 0;
600 
601  // The scaling in this code path produces really ugly results - it
602  // does the most trivial scaling with no smoothing.
603  GDIMetaFile* pOldMetaFile = mpMetaFile;
604  const bool bOldMap = mbMap;
605 
606  mpMetaFile = nullptr; // fdo#55044 reset before GetBitmap!
607  mbMap = false;
608 
609  Bitmap aBmp(GetBitmap(aDstRect.TopLeft(), aDstRect.GetSize()));
610 
611  // #109044# The generated bitmap need not necessarily be
612  // of aDstRect dimensions, it's internally clipped to
613  // window bounds. Thus, we correct the dest size here,
614  // since we later use it (in nDstWidth/Height) for pixel
615  // access)
616  // #i38887# reading from screen may sometimes fail
617  if (aBmp.ImplGetSalBitmap())
618  {
619  aDstRect.SetSize(aBmp.GetSizePixel());
620  }
621 
622  const tools::Long nDstWidth = aDstRect.GetWidth();
623  const tools::Long nDstHeight = aDstRect.GetHeight();
624 
625  // calculate offset in original bitmap
626  // in RTL case this is a little more complicated since the contents of the
627  // bitmap is not mirrored (it never is), however the paint region and bmp region
628  // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
629  // is content wise somewhere else and needs to take mirroring into account
630  const tools::Long nOffX = IsRTLEnabled()
631  ? aOutSize.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPoint.X())
632  : aDstRect.Left() - aOutPoint.X();
633 
634  const tools::Long nOffY = aDstRect.Top() - aOutPoint.Y();
635 
636  TradScaleContext aTradContext(aDstRect, aBmpRect, aOutSize, nOffX, nOffY);
637 
638  Bitmap::ScopedReadAccess pBitmapReadAccess(const_cast<Bitmap&>(rBitmap));
639  AlphaMask::ScopedReadAccess pAlphaReadAccess(const_cast<AlphaMask&>(rAlpha));
640 
641  DBG_ASSERT( pAlphaReadAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal,
642  "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
643 
644  // #i38887# reading from screen may sometimes fail
645  if (aBmp.ImplGetSalBitmap())
646  {
647  Bitmap aNewBitmap;
648 
649  if (mpAlphaVDev)
650  {
651  aNewBitmap = BlendBitmapWithAlpha(
652  aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(),
653  aDstRect,
654  nOffY, nDstHeight,
655  nOffX, nDstWidth,
656  aTradContext.mpMapX.get(), aTradContext.mpMapY.get() );
657  }
658  else
659  {
660  LinearScaleContext aLinearContext(aDstRect, aBmpRect, aOutSize, nOffX, nOffY);
661 
662  if (aLinearContext.blendBitmap( BitmapScopedWriteAccess(aBmp).get(), pBitmapReadAccess.get(), pAlphaReadAccess.get(),
663  nDstWidth, nDstHeight))
664  {
665  aNewBitmap = aBmp;
666  }
667  else
668  {
669  aNewBitmap = BlendBitmap(
670  aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(),
671  nOffY, nDstHeight,
672  nOffX, nDstWidth,
673  aBmpRect, aOutSize,
674  bHMirr, bVMirr,
675  aTradContext.mpMapX.get(), aTradContext.mpMapY.get() );
676  }
677  }
678 
679  // #110958# Disable alpha VDev, we're doing the necessary
680  // stuff explicitly further below
681  if (mpAlphaVDev)
682  mpAlphaVDev = nullptr;
683 
684  DrawBitmap(aDstRect.TopLeft(), aNewBitmap);
685 
686  // #110958# Enable alpha VDev again
687  mpAlphaVDev = pOldVDev;
688  }
689 
690  mbMap = bOldMap;
691  mpMetaFile = pOldMetaFile;
692 }
693 
695 {
696  if( ImplIsRecordLayout() )
697  return false;
698 
699  if (!mpGraphics && !AcquireGraphics())
700  return false;
701  assert(mpGraphics);
702 
704 }
705 
706 void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, DrawImageFlags nStyle )
707 {
708  assert(!is_double_buffered_window());
709 
710  DrawImage( rPos, Size(), rImage, nStyle );
711 }
712 
713 void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
714  const Image& rImage, DrawImageFlags nStyle )
715 {
716  assert(!is_double_buffered_window());
717 
718  bool bIsSizeValid = !rSize.IsEmpty();
719 
720  if (!ImplIsRecordLayout())
721  {
722  Image& rNonConstImage = const_cast<Image&>(rImage);
723  if (bIsSizeValid)
724  rNonConstImage.Draw(this, rPos, nStyle, &rSize);
725  else
726  rNonConstImage.Draw(this, rPos, nStyle);
727  }
728 }
729 
730 namespace
731 {
732  // Co = Cs + Cd*(1-As) premultiplied alpha -or-
733  // Co = (AsCs + AdCd*(1-As)) / Ao
734  sal_uInt8 CalcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceAlpha,
735  const sal_uInt8 nDstAlpha, const sal_uInt8 nResAlpha, const sal_uInt8 nDestColor )
736  {
737  int c = nResAlpha ? ( static_cast<int>(nSourceAlpha)*nSourceColor + static_cast<int>(nDstAlpha)*nDestColor -
738  static_cast<int>(nDstAlpha)*nDestColor*nSourceAlpha/255 ) / static_cast<int>(nResAlpha) : 0;
739  return sal_uInt8( c );
740  }
741 
742  BitmapColor AlphaBlend( int nX, int nY,
743  const tools::Long nMapX,
744  const tools::Long nMapY,
745  BitmapReadAccess const * pP,
746  BitmapReadAccess const * pA,
747  BitmapReadAccess const * pB,
748  BitmapWriteAccess const * pAlphaW,
749  sal_uInt8& nResAlpha )
750  {
751  BitmapColor aDstCol,aSrcCol;
752  aSrcCol = pP->GetColor( nMapY, nMapX );
753  aDstCol = pB->GetColor( nY, nX );
754 
755  // vcl stores transparency, not alpha - invert it
756  const sal_uInt8 nSrcAlpha = 255 - pA->GetPixelIndex( nMapY, nMapX );
757  const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixelIndex( nY, nX );
758 
759  // Perform porter-duff compositing 'over' operation
760 
761  // Co = Cs + Cd*(1-As)
762  // Ad = As + Ad*(1-As)
763  nResAlpha = static_cast<int>(nSrcAlpha) + static_cast<int>(nDstAlpha) - static_cast<int>(nDstAlpha)*nSrcAlpha/255;
764 
765  aDstCol.SetRed( CalcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) );
766  aDstCol.SetBlue( CalcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) );
767  aDstCol.SetGreen( CalcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) );
768 
769  return aDstCol;
770  }
771 }
772 
774  const SalTwoRect& rPosAry,
775  const Bitmap& rBmp )
776 {
777  mpGraphics->BlendBitmap( rPosAry, *rBmp.ImplGetSalBitmap(), *this );
778 }
779 
781  Bitmap& aBmp,
782  BitmapReadAccess const * pP,
783  BitmapReadAccess const * pA,
784  const tools::Rectangle& aDstRect,
785  const sal_Int32 nOffY,
786  const sal_Int32 nDstHeight,
787  const sal_Int32 nOffX,
788  const sal_Int32 nDstWidth,
789  const tools::Long* pMapX,
790  const tools::Long* pMapY )
791 
792 {
793  BitmapColor aDstCol;
794  Bitmap res;
795  int nX, nY;
796  sal_uInt8 nResAlpha;
797 
798  SAL_WARN_IF( !mpAlphaVDev, "vcl.gdi", "BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
799 
800  bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
801  mpAlphaVDev->EnableMapMode(false);
802 
803  Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
804  BitmapScopedWriteAccess pAlphaW(aAlphaBitmap);
805 
806  if( GetBitCount() <= 8 )
807  {
809  BitmapColor aIndex( 0 );
810  Bitmap::ScopedReadAccess pB(aBmp);
811  BitmapScopedWriteAccess pW(aDither);
812 
813  if (pB && pP && pA && pW && pAlphaW)
814  {
815  int nOutY;
816 
817  for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
818  {
819  const tools::Long nMapY = pMapY[ nY ];
820  const tools::Long nModY = ( nOutY & 0x0FL ) << 4;
821  int nOutX;
822 
823  Scanline pScanline = pW->GetScanline(nY);
824  Scanline pScanlineAlpha = pAlphaW->GetScanline(nY);
825  for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
826  {
827  const tools::Long nMapX = pMapX[ nX ];
828  const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
829 
830  aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB.get(), pAlphaW.get(), nResAlpha );
831 
832  aIndex.SetIndex( static_cast<sal_uInt8>( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16 ] +
833  nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16 ] +
834  nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16 ] ) );
835  pW->SetPixelOnData( pScanline, nX, aIndex );
836 
837  aIndex.SetIndex( static_cast<sal_uInt8>( nVCLRLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16 ] +
838  nVCLGLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16 ] +
839  nVCLBLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16 ] ) );
840  pAlphaW->SetPixelOnData( pScanlineAlpha, nX, aIndex );
841  }
842  }
843  }
844  pB.reset();
845  pW.reset();
846  res = aDither;
847  }
848  else
849  {
850  BitmapScopedWriteAccess pB(aBmp);
851  if (pB && pP && pA && pAlphaW)
852  {
853  for( nY = 0; nY < nDstHeight; nY++ )
854  {
855  const tools::Long nMapY = pMapY[ nY ];
856  Scanline pScanlineB = pB->GetScanline(nY);
857  Scanline pScanlineAlpha = pAlphaW->GetScanline(nY);
858 
859  for( nX = 0; nX < nDstWidth; nX++ )
860  {
861  const tools::Long nMapX = pMapX[ nX ];
862  aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB.get(), pAlphaW.get(), nResAlpha );
863 
864  pB->SetPixelOnData(pScanlineB, nX, pB->GetBestMatchingColor(aDstCol));
865  pAlphaW->SetPixelOnData(pScanlineAlpha, nX, pB->GetBestMatchingColor(Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha)));
866  }
867  }
868  }
869  pB.reset();
870  res = aBmp;
871  }
872 
873  pAlphaW.reset();
874  mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
875  mpAlphaVDev->EnableMapMode( bOldMapMode );
876 
877  return res;
878 }
879 
881  Bitmap& aBmp,
882  BitmapReadAccess const * pP,
883  BitmapReadAccess const * pA,
884  const sal_Int32 nOffY,
885  const sal_Int32 nDstHeight,
886  const sal_Int32 nOffX,
887  const sal_Int32 nDstWidth,
888  const tools::Rectangle& aBmpRect,
889  const Size& aOutSz,
890  const bool bHMirr,
891  const bool bVMirr,
892  const tools::Long* pMapX,
893  const tools::Long* pMapY )
894 {
895  BitmapColor aDstCol;
896  Bitmap res;
897  int nX, nY;
898 
899  if( GetBitCount() <= 8 )
900  {
902  BitmapColor aIndex( 0 );
903  Bitmap::ScopedReadAccess pB(aBmp);
904  BitmapScopedWriteAccess pW(aDither);
905 
906  if( pB && pP && pA && pW )
907  {
908  int nOutY;
909 
910  for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
911  {
912  tools::Long nMapY = pMapY[ nY ];
913  if (bVMirr)
914  {
915  nMapY = aBmpRect.Bottom() - nMapY;
916  }
917  const tools::Long nModY = ( nOutY & 0x0FL ) << 4;
918  int nOutX;
919 
920  Scanline pScanline = pW->GetScanline(nY);
921  Scanline pScanlineAlpha = pA->GetScanline(nMapY);
922  for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
923  {
924  tools::Long nMapX = pMapX[ nX ];
925  if (bHMirr)
926  {
927  nMapX = aBmpRect.Right() - nMapX;
928  }
929  const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
930 
931  aDstCol = pB->GetColor( nY, nX );
932  aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pA->GetIndexFromData( pScanlineAlpha, nMapX ) );
933  aIndex.SetIndex( static_cast<sal_uInt8>( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16 ] +
934  nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16 ] +
935  nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16 ] ) );
936  pW->SetPixelOnData( pScanline, nX, aIndex );
937  }
938  }
939  }
940 
941  pB.reset();
942  pW.reset();
943  res = aDither;
944  }
945  else
946  {
947  BitmapScopedWriteAccess pB(aBmp);
948 
949  bool bFastBlend = false;
950  if( pP && pA && pB && !bHMirr && !bVMirr )
951  {
952  SalTwoRect aTR(aBmpRect.Left(), aBmpRect.Top(), aBmpRect.GetWidth(), aBmpRect.GetHeight(),
953  nOffX, nOffY, aOutSz.Width(), aOutSz.Height());
954 
955  bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
956  }
957 
958  if( pP && pA && pB && !bFastBlend )
959  {
960  switch( pP->GetScanlineFormat() )
961  {
963  {
964  for( nY = 0; nY < nDstHeight; nY++ )
965  {
966  tools::Long nMapY = pMapY[ nY ];
967  if ( bVMirr )
968  {
969  nMapY = aBmpRect.Bottom() - nMapY;
970  }
971  Scanline pPScan = pP->GetScanline( nMapY );
972  Scanline pAScan = pA->GetScanline( nMapY );
973  Scanline pBScan = pB->GetScanline( nY );
974 
975  for( nX = 0; nX < nDstWidth; nX++ )
976  {
977  tools::Long nMapX = pMapX[ nX ];
978 
979  if ( bHMirr )
980  {
981  nMapX = aBmpRect.Right() - nMapX;
982  }
983  aDstCol = pB->GetPixelFromData( pBScan, nX );
984  aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ), pAScan[ nMapX ] );
985  pB->SetPixelOnData( pBScan, nX, aDstCol );
986  }
987  }
988  }
989  break;
990 
991  default:
992  {
993 
994  for( nY = 0; nY < nDstHeight; nY++ )
995  {
996  tools::Long nMapY = pMapY[ nY ];
997 
998  if ( bVMirr )
999  {
1000  nMapY = aBmpRect.Bottom() - nMapY;
1001  }
1002  Scanline pAScan = pA->GetScanline( nMapY );
1003  Scanline pBScan = pB->GetScanline(nY);
1004  for( nX = 0; nX < nDstWidth; nX++ )
1005  {
1006  tools::Long nMapX = pMapX[ nX ];
1007 
1008  if ( bHMirr )
1009  {
1010  nMapX = aBmpRect.Right() - nMapX;
1011  }
1012  aDstCol = pB->GetPixelFromData( pBScan, nX );
1013  aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pAScan[ nMapX ] );
1014  pB->SetPixelOnData( pBScan, nX, aDstCol );
1015  }
1016  }
1017  }
1018  break;
1019  }
1020  }
1021 
1022  pB.reset();
1023  res = aBmp;
1024  }
1025 
1026  return res;
1027 }
1028 
1029 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
tools::Long Height() const
sal_uInt8 GetPixelIndex(tools::Long nY, tools::Long nX) const
bool BlendBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, const OutputDevice &rOutDev)
sal_uInt8 GetRed() const
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:702
void SetBlue(sal_uInt8 nBlue)
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool HasFastDrawTransformedBitmap() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
void setWidth(tools::Long nWidth)
virtual void ClipToPaintRegion(tools::Rectangle &rDstRect)
void Merge(const Color &rMergeColor, sal_uInt8 cTransparency)
constexpr tools::Long Left() const
DrawModeFlags mnDrawMode
Definition: outdev.hxx:219
const std::shared_ptr< SalBitmap > & ImplGetSalBitmap() const
sal_uIntPtr sal_uLong
long Long
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
BmpMirrorFlags AdjustTwoRect(SalTwoRect &rTwoRect, const Size &rSizePix)
Definition: rect.cxx:341
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)
bool IsMapModeEnabled() const
Definition: outdev.hxx:1526
bool mbOutputClipped
Definition: outdev.hxx:244
tools::Long mnOutOffY
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
Definition: outdev.hxx:208
SAL_DLLPRIVATE bool is_double_buffered_window() const
tools::Long mnSrcHeight
Definition: salgtype.hxx:43
tools::Long mnSrcWidth
Definition: salgtype.hxx:42
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:586
Size GetSizePixel() const
bool mbMap
Definition: outdev.hxx:239
tools::Long mnDestWidth
Definition: salgtype.hxx:46
void Draw(OutputDevice *pOutDev, const Point &rPos, DrawImageFlags nStyle, const Size *pSize=nullptr)
Definition: Image.cxx:116
constexpr tools::Long Width() const
ScanlineFormat
Definition: Scanline.hxx:29
SAL_DLLPRIVATE void DrawDeviceAlphaBitmapSlowPath(const Bitmap &rBitmap, const AlphaMask &rAlpha, tools::Rectangle aDstRect, tools::Rectangle aBmpRect, Size const &aOutSz, Point const &aOutPt)
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
SAL_DLLPRIVATE tools::Long ImplLogicXToDevicePixel(tools::Long nX) const
Convert a logical X coordinate to a device pixel's X coordinate.
Definition: map.cxx:306
DrawImageFlags
Scanline GetScanline(tools::Long nY) const
virtual bool CanSubsampleBitmap() const
Definition: outdev.hxx:1361
SAL_DLLPRIVATE void BlendBitmap(const SalTwoRect &rPosAry, const Bitmap &rBmp)
void DrawBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, const OutputDevice &rOutDev)
virtual Bitmap GetBitmap(const Point &rSrcPt, const Size &rSize) const
constexpr tools::Long GetWidth() const
void Pop()
Definition: stack.cxx:92
MetaActionType
const sal_uLong nVCLLut[256]
SAL_DLLPRIVATE Bitmap BlendBitmapWithAlpha(Bitmap &aBmp, BitmapReadAccess const *pP, BitmapReadAccess const *pA, const tools::Rectangle &aDstRect, const sal_Int32 nOffY, const sal_Int32 nDstHeight, const sal_Int32 nOffX, const sal_Int32 nDstWidth, const tools::Long *pMapX, const tools::Long *pMapY)
sal_uInt8 GetBlue() const
bool BlendAlphaBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalSrcBitmap, const SalBitmap &rSalMaskBitmap, const SalBitmap &rSalAlphaBitmap, const OutputDevice &rOutDev)
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:51
constexpr bool IsEmpty() const
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:181
tools::Long mnDestHeight
Definition: salgtype.hxx:47
void SetLineColor()
Definition: line.cxx:36
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
const sal_uLong nVCLBLut[6]
bool IsRTLEnabled() const
Definition: outdev.hxx:1243
bool IsEmpty() const
#define DBG_ASSERT(sCon, aError)
int i
ScanlineFormat GetScanlineFormat() const
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
void SetSize(const Size &rSize)
constexpr tools::Long Right() const
tools::Long mnOutHeight
Definition: outdev.hxx:210
void SetFillColor()
Definition: fill.cxx:29
tools::Long Width() const
SAL_DLLPRIVATE tools::Long ImplLogicWidthToDevicePixel(tools::Long nWidth) const
Convert a logical width to a width in units of device pixels.
Definition: map.cxx:324
SAL_DLLPRIVATE void ImplFillOpaqueRectangle(const tools::Rectangle &rRect)
Used for alpha VDev, to set areas to opaque.
Definition: virdev.cxx:341
void SetRed(sal_uInt8 nRed)
bool ImplFastBitmapBlending(BitmapWriteAccess const &rDstWA, const BitmapReadAccess &rSrcRA, const BitmapReadAccess &rMskRA, const SalTwoRect &rTR)
Definition: bmpfast.cxx:671
constexpr tools::Long Top() const
RasterOp meRasterOp
Definition: outdev.hxx:231
Size GetOutputSizePixel() const
Definition: outdev.hxx:310
virtual sal_uInt16 GetBitCount() const
Definition: outdev.cxx:366
void DrawBitmap(const Point &rDestPt, const Bitmap &rBitmap)
SAL_DLLPRIVATE void DrawDeviceAlphaBitmap(const Bitmap &rBmp, const AlphaMask &rAlpha, const Point &rDestPt, const Size &rDestSize, const Point &rSrcPtPixel, const Size &rSrcSizePixel)
constexpr Point TopLeft() const
bool DrawAlphaBitmap(const SalTwoRect &, const SalBitmap &rSourceBitmap, const SalBitmap &rAlphaBitmap, const OutputDevice &rOutDev)
void SetIndex(sal_uInt8 cIndex)
Definition: BitmapColor.hxx:75
constexpr tools::Long Bottom() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1109
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:878
const sal_uLong nVCLGLut[6]
sal_uInt8 GetGreen() const
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:195
constexpr Size GetSize() const
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
std::deque< AttacherIndex_Impl > aIndex
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
unsigned char sal_uInt8
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
bool Convert(BmpConversion eConversion)
Convert bitmap format.
constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans)
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:562
void SetGreen(sal_uInt8 nGreen)
bool mbInitClipRegion
Definition: outdev.hxx:251
Definition: image.hxx:39
virtual void InitClipRegion()
bool IsEmpty() const
tools::Long mnOutWidth
Definition: outdev.hxx:209
void setHeight(tools::Long nHeight)
tools::Long mnOutOffX
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
Definition: outdev.hxx:206
const sal_uLong nVCLRLut[6]
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
SAL_DLLPRIVATE tools::Long ImplLogicYToDevicePixel(tools::Long nY) const
Convert a logical Y coordinate to a device pixel's Y coordinate.
Definition: map.cxx:315
const sal_uLong nVCLDitherLut[256]
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:477
SAL_DLLPRIVATE tools::Long ImplLogicHeightToDevicePixel(tools::Long nHeight) const
Convert a logical height to a height in units of device pixels.
Definition: map.cxx:332
bool HasFastDrawTransformedBitmap() const
Return true if DrawTransformedBitmapEx() is fast.
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:184
std::shared_ptr< SalBitmap > GetBitmap(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, const OutputDevice &rOutDev)
constexpr tools::Long GetHeight() const
SAL_DLLPRIVATE void ImplSetSalBitmap(const std::shared_ptr< SalBitmap > &xImpBmp)
BmpMirrorFlags