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