Line data Source code
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 <tools/debug.hxx>
21 :
22 : #include <vcl/bitmap.hxx>
23 : #include <vcl/bitmapex.hxx>
24 : #include <vcl/window.hxx>
25 : #include <vcl/metaact.hxx>
26 : #include <vcl/gdimtf.hxx>
27 : #include <vcl/virdev.hxx>
28 : #include <vcl/bmpacc.hxx>
29 : #include <vcl/outdev.hxx>
30 : #include <vcl/window.hxx>
31 : #include <vcl/image.hxx>
32 :
33 : #include <bmpfast.hxx>
34 : #include <salbmp.hxx>
35 : #include <salgdi.hxx>
36 : #include <impbmp.hxx>
37 : #include <sallayout.hxx>
38 : #include <image.h>
39 : #include <outdev.h>
40 : #include <window.h>
41 : #include <region.h>
42 : #include <outdata.hxx>
43 :
44 : DBG_NAMEEX( OutputDevice )
45 :
46 : // =======================================================================
47 :
48 : // -----------
49 : // - Defines -
50 : // -----------
51 :
52 : #define OUTDEV_INIT() \
53 : { \
54 : if ( !IsDeviceOutputNecessary() ) \
55 : return; \
56 : \
57 : if ( !mpGraphics ) \
58 : if ( !ImplGetGraphics() ) \
59 : return; \
60 : \
61 : if ( mbInitClipRegion ) \
62 : ImplInitClipRegion(); \
63 : \
64 : if ( mbOutputClipped ) \
65 : return; \
66 : }
67 :
68 : // -------------
69 : // - externals -
70 : // -------------
71 :
72 : extern const sal_uLong nVCLRLut[ 6 ];
73 : extern const sal_uLong nVCLGLut[ 6 ];
74 : extern const sal_uLong nVCLBLut[ 6 ];
75 : extern const sal_uLong nVCLDitherLut[ 256 ];
76 : extern const sal_uLong nVCLLut[ 256 ];
77 :
78 : // =======================================================================
79 :
80 14 : sal_uLong ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
81 : {
82 14 : sal_uLong nMirrFlags = 0;
83 :
84 14 : if ( rTwoRect.mnDestWidth < 0 )
85 : {
86 0 : rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
87 0 : rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
88 0 : rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
89 0 : nMirrFlags |= BMP_MIRROR_HORZ;
90 : }
91 :
92 14 : if ( rTwoRect.mnDestHeight < 0 )
93 : {
94 0 : rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
95 0 : rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
96 0 : rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
97 0 : nMirrFlags |= BMP_MIRROR_VERT;
98 : }
99 :
100 56 : if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
101 14 : ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
102 14 : ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
103 14 : ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
104 : {
105 : const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
106 0 : Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
107 0 : Rectangle aCropRect( aSourceRect );
108 :
109 0 : aCropRect.Intersection( Rectangle( Point(), rSizePix ) );
110 :
111 0 : if( aCropRect.IsEmpty() )
112 0 : rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
113 : else
114 : {
115 0 : const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
116 0 : const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
117 :
118 0 : const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
119 0 : const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
120 0 : const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
121 0 : const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
122 :
123 0 : rTwoRect.mnSrcX = aCropRect.Left();
124 0 : rTwoRect.mnSrcY = aCropRect.Top();
125 0 : rTwoRect.mnSrcWidth = aCropRect.GetWidth();
126 0 : rTwoRect.mnSrcHeight = aCropRect.GetHeight();
127 0 : rTwoRect.mnDestX = nDstX1;
128 0 : rTwoRect.mnDestY = nDstY1;
129 0 : rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
130 0 : rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
131 : }
132 : }
133 :
134 14 : return nMirrFlags;
135 : }
136 :
137 : // =======================================================================
138 :
139 1705 : void ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Rectangle& rValidSrcRect )
140 : {
141 6830 : if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
142 3410 : ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
143 1705 : ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
144 10 : ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) )
145 : {
146 : const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
147 1695 : Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
148 1695 : Rectangle aCropRect( aSourceRect );
149 :
150 1695 : aCropRect.Intersection( rValidSrcRect );
151 :
152 1695 : if( aCropRect.IsEmpty() )
153 0 : rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
154 : else
155 : {
156 1695 : const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
157 1695 : const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
158 :
159 1695 : const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
160 1695 : const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
161 1695 : const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
162 1695 : const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
163 :
164 1695 : rTwoRect.mnSrcX = aCropRect.Left();
165 1695 : rTwoRect.mnSrcY = aCropRect.Top();
166 1695 : rTwoRect.mnSrcWidth = aCropRect.GetWidth();
167 1695 : rTwoRect.mnSrcHeight = aCropRect.GetHeight();
168 1695 : rTwoRect.mnDestX = nDstX1;
169 1695 : rTwoRect.mnDestY = nDstY1;
170 1695 : rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
171 1695 : rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
172 : }
173 : }
174 1705 : }
175 :
176 : // =======================================================================
177 :
178 1696 : void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, void* pVoidPosAry )
179 : {
180 1696 : SalTwoRect* pPosAry = (SalTwoRect*)pVoidPosAry;
181 : SalGraphics* pGraphics2;
182 :
183 1696 : if ( this == pSrcDev )
184 0 : pGraphics2 = NULL;
185 : else
186 : {
187 1959 : if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
188 263 : (GetOutDevType() != OUTDEV_WINDOW) )
189 : {
190 1696 : if ( !pSrcDev->mpGraphics )
191 : {
192 0 : if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
193 : return;
194 : }
195 1696 : pGraphics2 = pSrcDev->mpGraphics;
196 : }
197 : else
198 : {
199 0 : if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow )
200 0 : pGraphics2 = NULL;
201 : else
202 : {
203 0 : if ( !pSrcDev->mpGraphics )
204 : {
205 0 : if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
206 : return;
207 : }
208 0 : pGraphics2 = pSrcDev->mpGraphics;
209 :
210 0 : if ( !mpGraphics )
211 : {
212 0 : if ( !ImplGetGraphics() )
213 : return;
214 : }
215 : DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
216 : "OutputDevice::DrawOutDev(): We need more than one Graphics" );
217 : }
218 : }
219 : }
220 :
221 : // #102532# Offset only has to be pseudo window offset
222 : const Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
223 1696 : Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
224 :
225 1696 : ImplAdjustTwoRect( *pPosAry, aSrcOutRect );
226 :
227 1696 : if ( pPosAry->mnSrcWidth && pPosAry->mnSrcHeight && pPosAry->mnDestWidth && pPosAry->mnDestHeight )
228 : {
229 : // --- RTL --- if this is no window, but pSrcDev is a window
230 : // mirroring may be required
231 : // because only windows have a SalGraphicsLayout
232 : // mirroring is performed here
233 1696 : if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) )
234 : {
235 0 : SalTwoRect pPosAry2 = *pPosAry;
236 0 : pGraphics2->mirror( pPosAry2.mnSrcX, pPosAry2.mnSrcWidth, pSrcDev );
237 0 : mpGraphics->CopyBits( &pPosAry2, pGraphics2, this, pSrcDev );
238 : }
239 : else
240 1696 : mpGraphics->CopyBits( pPosAry, pGraphics2, this, pSrcDev );
241 : }
242 : }
243 :
244 10 : void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
245 : const Point& rSrcPt, const Size& rSrcSize )
246 : {
247 : OSL_TRACE( "OutputDevice::DrawOutDev()" );
248 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
249 : DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
250 :
251 10 : if( ImplIsRecordLayout() )
252 : return;
253 :
254 10 : if ( meOutDevType == OUTDEV_PRINTER )
255 : return;
256 :
257 10 : if ( ROP_INVERT == meRasterOp )
258 : {
259 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
260 : return;
261 : }
262 :
263 10 : if ( mpMetaFile )
264 : {
265 0 : const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
266 0 : mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
267 : }
268 :
269 10 : OUTDEV_INIT();
270 :
271 : SalTwoRect aPosAry;
272 10 : aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
273 10 : aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
274 10 : aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
275 10 : aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
276 :
277 10 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
278 : {
279 9 : aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
280 9 : aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
281 9 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
282 9 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
283 :
284 : const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
285 9 : Size( mnOutWidth, mnOutHeight ) );
286 :
287 9 : ImplAdjustTwoRect( aPosAry, aSrcOutRect );
288 :
289 9 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
290 9 : mpGraphics->CopyBits( &aPosAry, NULL, this, NULL );
291 : }
292 :
293 10 : if( mpAlphaVDev )
294 0 : mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize );
295 : }
296 :
297 1732 : void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
298 : const Point& rSrcPt, const Size& rSrcSize,
299 : const OutputDevice& rOutDev )
300 : {
301 : OSL_TRACE( "OutputDevice::DrawOutDev()" );
302 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
303 : DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice );
304 : DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
305 : DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
306 :
307 1732 : if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) || ImplIsRecordLayout() )
308 : return;
309 :
310 1732 : if ( ROP_INVERT == meRasterOp )
311 : {
312 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
313 : return;
314 : }
315 :
316 1732 : if ( mpMetaFile )
317 : {
318 0 : const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
319 0 : mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
320 : }
321 :
322 1732 : OUTDEV_INIT();
323 :
324 : SalTwoRect aPosAry;
325 1696 : aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
326 1696 : aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
327 1696 : aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
328 1696 : aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
329 1696 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
330 1696 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
331 1696 : aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
332 1696 : aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
333 :
334 1696 : if( mpAlphaVDev )
335 : {
336 0 : if( rOutDev.mpAlphaVDev )
337 : {
338 : // alpha-blend source over destination
339 0 : DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
340 :
341 : // This would be mode SOURCE:
342 : // copy source alpha channel to our alpha channel
343 : //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev );
344 : }
345 : else
346 : {
347 0 : ImplDrawOutDevDirect( &rOutDev, &aPosAry );
348 :
349 : // #i32109#: make destination rectangle opaque - source has no alpha
350 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
351 : }
352 : }
353 : else
354 : {
355 1696 : if( rOutDev.mpAlphaVDev )
356 : {
357 : // alpha-blend source over destination
358 0 : DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
359 : }
360 : else
361 : {
362 : // no alpha at all, neither in source nor destination device
363 1696 : ImplDrawOutDevDirect( &rOutDev, &aPosAry );
364 : }
365 : }
366 : }
367 :
368 0 : void OutputDevice::CopyArea( const Point& rDestPt,
369 : const Point& rSrcPt, const Size& rSrcSize,
370 : sal_uInt16 nFlags )
371 : {
372 : OSL_TRACE( "OutputDevice::CopyArea()" );
373 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
374 : DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
375 :
376 0 : if ( meOutDevType == OUTDEV_PRINTER || ImplIsRecordLayout() )
377 : return;
378 :
379 0 : RasterOp eOldRop = GetRasterOp();
380 0 : SetRasterOp( ROP_OVERPAINT );
381 :
382 0 : OUTDEV_INIT();
383 :
384 : SalTwoRect aPosAry;
385 0 : aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
386 0 : aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
387 :
388 0 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
389 : {
390 0 : aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
391 0 : aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
392 0 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
393 0 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
394 0 : aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
395 0 : aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
396 :
397 : const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
398 0 : Size( mnOutWidth, mnOutHeight ) );
399 : const Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
400 0 : Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
401 :
402 0 : ImplAdjustTwoRect( aPosAry, aSrcOutRect );
403 :
404 0 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
405 : {
406 0 : if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) )
407 : {
408 : ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect,
409 : aPosAry.mnDestX-aPosAry.mnSrcX,
410 : aPosAry.mnDestY-aPosAry.mnSrcY,
411 0 : false );
412 :
413 : mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
414 : aPosAry.mnSrcX, aPosAry.mnSrcY,
415 : aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
416 0 : SAL_COPYAREA_WINDOWINVALIDATE, this );
417 : }
418 : else
419 : {
420 0 : aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
421 0 : aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
422 0 : mpGraphics->CopyBits( &aPosAry, NULL, this, NULL );
423 : }
424 : }
425 : }
426 :
427 0 : SetRasterOp( eOldRop );
428 :
429 0 : if( mpAlphaVDev )
430 0 : mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags );
431 : }
432 :
433 0 : void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
434 : const OutputDevice& rOutDev, const Region& rRegion )
435 : {
436 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
437 :
438 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
439 0 : bool bOldMap = mbMap;
440 0 : RasterOp eOldROP = GetRasterOp();
441 0 : mpMetaFile = NULL;
442 0 : mbMap = false;
443 0 : SetRasterOp( ROP_OVERPAINT );
444 :
445 0 : if ( !IsDeviceOutputNecessary() )
446 : return;
447 :
448 0 : if ( !mpGraphics )
449 : {
450 0 : if ( !ImplGetGraphics() )
451 : return;
452 : }
453 :
454 : // ClipRegion zuruecksetzen
455 0 : if ( rRegion.IsNull() )
456 0 : mpGraphics->ResetClipRegion();
457 : else
458 0 : ImplSelectClipRegion( rRegion );
459 :
460 : SalTwoRect aPosAry;
461 0 : aPosAry.mnSrcX = rDevPt.X();
462 0 : aPosAry.mnSrcY = rDevPt.Y();
463 0 : aPosAry.mnSrcWidth = rDevSize.Width();
464 0 : aPosAry.mnSrcHeight = rDevSize.Height();
465 0 : aPosAry.mnDestX = rPt.X();
466 0 : aPosAry.mnDestY = rPt.Y();
467 0 : aPosAry.mnDestWidth = rDevSize.Width();
468 0 : aPosAry.mnDestHeight = rDevSize.Height();
469 0 : ImplDrawOutDevDirect( &rOutDev, &aPosAry );
470 :
471 : // Ensure that ClipRegion is recalculated and set
472 0 : mbInitClipRegion = true;
473 :
474 0 : SetRasterOp( eOldROP );
475 0 : mbMap = bOldMap;
476 0 : mpMetaFile = pOldMetaFile;
477 : }
478 :
479 0 : void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
480 : OutputDevice& rDev )
481 : {
482 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
483 :
484 0 : bool bOldMap = mbMap;
485 0 : mbMap = false;
486 0 : rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
487 0 : mbMap = bOldMap;
488 0 : }
489 :
490 2146 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
491 : {
492 : OSL_TRACE( "OutputDevice::DrawBitmap()" );
493 :
494 2146 : if( ImplIsRecordLayout() )
495 2146 : return;
496 :
497 2146 : const Size aSizePix( rBitmap.GetSizePixel() );
498 2146 : ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
499 :
500 2146 : if( mpAlphaVDev )
501 : {
502 : // #i32109#: Make bitmap area opaque
503 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) );
504 : }
505 : }
506 :
507 17 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
508 : {
509 : OSL_TRACE( "OutputDevice::DrawBitmap( Size )" );
510 :
511 17 : if( ImplIsRecordLayout() )
512 17 : return;
513 :
514 17 : ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
515 :
516 17 : if( mpAlphaVDev )
517 : {
518 : // #i32109#: Make bitmap area opaque
519 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
520 : }
521 : }
522 :
523 0 : void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
524 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
525 : const Bitmap& rBitmap )
526 : {
527 : OSL_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
528 :
529 0 : if( ImplIsRecordLayout() )
530 0 : return;
531 :
532 0 : ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
533 :
534 0 : if( mpAlphaVDev )
535 : {
536 : // #i32109#: Make bitmap area opaque
537 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
538 : }
539 : }
540 :
541 2163 : void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
542 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
543 : const Bitmap& rBitmap, const sal_uLong nAction )
544 : {
545 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
546 :
547 2163 : Bitmap aBmp( rBitmap );
548 :
549 2163 : if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
550 : {
551 : return;
552 : }
553 2163 : else if ( ROP_INVERT == meRasterOp )
554 : {
555 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
556 : return;
557 : }
558 2163 : else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
559 : DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
560 : {
561 0 : if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
562 : {
563 : sal_uInt8 cCmpVal;
564 :
565 0 : if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
566 0 : cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
567 : else
568 0 : cCmpVal = 255;
569 :
570 0 : Color aCol( cCmpVal, cCmpVal, cCmpVal );
571 0 : Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
572 0 : SetLineColor( aCol );
573 0 : SetFillColor( aCol );
574 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
575 0 : Pop();
576 : return;
577 : }
578 0 : else if( !!aBmp )
579 : {
580 0 : if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
581 0 : aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
582 :
583 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
584 0 : aBmp.Convert( BMP_CONVERSION_GHOSTED );
585 : }
586 : }
587 :
588 2163 : if ( mpMetaFile )
589 : {
590 9 : switch( nAction )
591 : {
592 : case( META_BMP_ACTION ):
593 0 : mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
594 0 : break;
595 :
596 : case( META_BMPSCALE_ACTION ):
597 9 : mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
598 9 : break;
599 :
600 : case( META_BMPSCALEPART_ACTION ):
601 : mpMetaFile->AddAction( new MetaBmpScalePartAction(
602 0 : rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
603 0 : break;
604 : }
605 : }
606 :
607 2163 : OUTDEV_INIT();
608 :
609 2154 : if( !aBmp.IsEmpty() )
610 : {
611 : SalTwoRect aPosAry;
612 :
613 10 : aPosAry.mnSrcX = rSrcPtPixel.X();
614 10 : aPosAry.mnSrcY = rSrcPtPixel.Y();
615 10 : aPosAry.mnSrcWidth = rSrcSizePixel.Width();
616 10 : aPosAry.mnSrcHeight = rSrcSizePixel.Height();
617 10 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
618 10 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
619 10 : aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
620 10 : aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
621 :
622 10 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
623 : {
624 10 : const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
625 :
626 10 : if ( nMirrFlags )
627 0 : aBmp.Mirror( nMirrFlags );
628 :
629 : /* #i75264# (corrected with #i81576#)
630 : * sometimes a bitmap is scaled to a ridiculous size and drawn
631 : * to a quite normal VDev, so only a very small part of
632 : * the scaled bitmap will be visible. However actually scaling
633 : * the bitmap will use so much memory that we end with a crash.
634 : * Workaround: since only a small part of the scaled bitmap will
635 : * be actually drawn anyway (because of clipping on the device
636 : * boundary), limit the destination and source rectangles so
637 : * that the destination rectangle will overlap the device but only
638 : * be reasonably (say factor 2) larger than the device itself.
639 : */
640 10 : if( aPosAry.mnDestWidth > 2048 || aPosAry.mnDestHeight > 2048 )
641 : {
642 0 : if( meOutDevType == OUTDEV_WINDOW ||
643 : (meOutDevType == OUTDEV_VIRDEV && mpPDFWriter == 0 ) )
644 : {
645 : // #i81576# do the following trick only if there is overlap at all
646 : // else the formulae don't work
647 : // theoretically in this case we wouldn't need to draw the bitmap at all
648 : // however there are some esoteric case where that is needed
649 0 : if( aPosAry.mnDestX + aPosAry.mnDestWidth >= 0
650 : && aPosAry.mnDestX < mnOutWidth
651 : && aPosAry.mnDestY + aPosAry.mnDestHeight >= 0
652 : && aPosAry.mnDestY < mnOutHeight )
653 : {
654 : // reduce scaling to something reasonable taking into account the output size
655 0 : if( aPosAry.mnDestWidth > 3*mnOutWidth && aPosAry.mnSrcWidth )
656 : {
657 0 : const double nScaleX = aPosAry.mnDestWidth/double(aPosAry.mnSrcWidth);
658 :
659 0 : if( aPosAry.mnDestX + aPosAry.mnDestWidth > mnOutWidth )
660 : {
661 0 : aPosAry.mnDestWidth = Max(long(0),mnOutWidth-aPosAry.mnDestX);
662 : }
663 0 : if( aPosAry.mnDestX < 0 )
664 : {
665 0 : aPosAry.mnDestWidth += aPosAry.mnDestX;
666 0 : aPosAry.mnSrcX -= sal::static_int_cast<long>(aPosAry.mnDestX / nScaleX);
667 0 : aPosAry.mnDestX = 0;
668 : }
669 :
670 0 : aPosAry.mnSrcWidth = sal::static_int_cast<long>(aPosAry.mnDestWidth / nScaleX);
671 : }
672 :
673 0 : if( aPosAry.mnDestHeight > 3*mnOutHeight && aPosAry.mnSrcHeight != 0 )
674 : {
675 0 : const double nScaleY = aPosAry.mnDestHeight/double(aPosAry.mnSrcHeight);
676 :
677 0 : if( aPosAry.mnDestY + aPosAry.mnDestHeight > mnOutHeight )
678 : {
679 0 : aPosAry.mnDestHeight = Max(long(0),mnOutHeight-aPosAry.mnDestY);
680 : }
681 0 : if( aPosAry.mnDestY < 0 )
682 : {
683 0 : aPosAry.mnDestHeight += aPosAry.mnDestY;
684 0 : aPosAry.mnSrcY -= sal::static_int_cast<long>(aPosAry.mnDestY / nScaleY);
685 0 : aPosAry.mnDestY = 0;
686 : }
687 :
688 0 : aPosAry.mnSrcHeight = sal::static_int_cast<long>(aPosAry.mnDestHeight / nScaleY);
689 : }
690 : }
691 : }
692 : }
693 :
694 10 : if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
695 : {
696 10 : const double nScaleX = aPosAry.mnDestWidth / static_cast<double>( aPosAry.mnSrcWidth );
697 10 : const double nScaleY = aPosAry.mnDestHeight / static_cast<double>( aPosAry.mnSrcHeight );
698 : // If subsampling, use Bitmap::Scale for subsampling for better quality.
699 10 : if ( meOutDevType != OUTDEV_PRINTER &&
700 : nAction == META_BMPSCALE_ACTION &&
701 : (nScaleX < 1.0 || nScaleY < 1.0) )
702 : {
703 0 : aBmp.Scale ( nScaleX, nScaleY );
704 0 : aPosAry.mnSrcWidth = aPosAry.mnDestWidth;
705 0 : aPosAry.mnSrcHeight = aPosAry.mnDestHeight;
706 : }
707 10 : mpGraphics->DrawBitmap( &aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
708 : }
709 : }
710 2163 : }
711 : }
712 :
713 2144 : void OutputDevice::DrawBitmapEx( const Point& rDestPt,
714 : const BitmapEx& rBitmapEx )
715 : {
716 : OSL_TRACE( "OutputDevice::DrawBitmapEx()" );
717 :
718 2144 : if( ImplIsRecordLayout() )
719 2144 : return;
720 :
721 2144 : if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
722 2144 : DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
723 : else
724 : {
725 0 : const Size aSizePix( rBitmapEx.GetSizePixel() );
726 0 : ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
727 : }
728 : }
729 :
730 22 : void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
731 : const BitmapEx& rBitmapEx )
732 : {
733 : OSL_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
734 :
735 22 : if( ImplIsRecordLayout() )
736 22 : return;
737 :
738 22 : if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
739 15 : DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
740 : else
741 7 : ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
742 : }
743 :
744 0 : void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
745 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
746 : const BitmapEx& rBitmapEx )
747 : {
748 : OSL_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
749 :
750 0 : if( ImplIsRecordLayout() )
751 0 : return;
752 :
753 0 : if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
754 0 : DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
755 : else
756 0 : ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
757 : }
758 :
759 7 : void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
760 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
761 : const BitmapEx& rBitmapEx, const sal_uLong nAction )
762 : {
763 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
764 :
765 7 : BitmapEx aBmpEx( rBitmapEx );
766 :
767 7 : if ( mnDrawMode & DRAWMODE_NOBITMAP )
768 : return;
769 7 : else if ( ROP_INVERT == meRasterOp )
770 : {
771 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
772 : return;
773 : }
774 7 : else if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
775 : DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
776 : {
777 0 : if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
778 : {
779 0 : Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
780 : sal_uInt8 cCmpVal;
781 :
782 0 : if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
783 0 : cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
784 : else
785 0 : cCmpVal = 255;
786 :
787 0 : aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
788 :
789 0 : if( aBmpEx.IsAlpha() )
790 : {
791 : // Create one-bit mask out of alpha channel, by
792 : // thresholding it at alpha=0.5. As
793 : // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
794 : // output, having alpha-induced grey levels is not
795 : // acceptable.
796 0 : Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() );
797 0 : aMask.MakeMono( 129 );
798 0 : aBmpEx = BitmapEx( aColorBmp, aMask );
799 : }
800 : else
801 : {
802 0 : aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
803 0 : }
804 : }
805 0 : else if( !!aBmpEx )
806 : {
807 0 : if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
808 0 : aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
809 :
810 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
811 0 : aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
812 : }
813 : }
814 :
815 7 : if ( mpMetaFile )
816 : {
817 1 : switch( nAction )
818 : {
819 : case( META_BMPEX_ACTION ):
820 0 : mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
821 0 : break;
822 :
823 : case( META_BMPEXSCALE_ACTION ):
824 1 : mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
825 1 : break;
826 :
827 : case( META_BMPEXSCALEPART_ACTION ):
828 : mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
829 0 : rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
830 0 : break;
831 : }
832 : }
833 :
834 7 : OUTDEV_INIT();
835 :
836 6 : if( OUTDEV_PRINTER == meOutDevType )
837 : {
838 0 : if( aBmpEx.IsAlpha() )
839 : {
840 : // #107169# For true alpha bitmaps, no longer masking the
841 : // bitmap, but perform a full alpha blend against a white
842 : // background here.
843 0 : Bitmap aBmp( aBmpEx.GetBitmap() );
844 0 : aBmp.Blend( aBmpEx.GetAlpha(), Color( COL_WHITE) );
845 0 : DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp );
846 : }
847 : else
848 : {
849 0 : Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() );
850 0 : aBmp.Replace( aMask, Color( COL_WHITE ) );
851 0 : ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
852 : }
853 : return;
854 : }
855 6 : else if( aBmpEx.IsAlpha() )
856 : {
857 2 : ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
858 : return;
859 : }
860 :
861 4 : if( !( !aBmpEx ) )
862 : {
863 : SalTwoRect aPosAry;
864 :
865 4 : aPosAry.mnSrcX = rSrcPtPixel.X();
866 4 : aPosAry.mnSrcY = rSrcPtPixel.Y();
867 4 : aPosAry.mnSrcWidth = rSrcSizePixel.Width();
868 4 : aPosAry.mnSrcHeight = rSrcSizePixel.Height();
869 4 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
870 4 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
871 4 : aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
872 4 : aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
873 :
874 4 : const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() );
875 :
876 4 : if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
877 : {
878 :
879 4 : if( nMirrFlags )
880 0 : aBmpEx.Mirror( nMirrFlags );
881 :
882 4 : const ImpBitmap* pImpBmp = aBmpEx.ImplGetBitmapImpBitmap();
883 4 : const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap();
884 :
885 4 : if ( pMaskBmp )
886 : {
887 : // #4919452# reduce operation area to bounds of
888 : // cliprect. since masked transparency involves
889 : // creation of a large vdev and copying the screen
890 : // content into that (slooow read from framebuffer),
891 : // that should considerably increase performance for
892 : // large bitmaps and small clippings.
893 :
894 : // Note that this optimisation is a workaround for a
895 : // Writer peculiarity, namely, to decompose background
896 : // graphics into myriads of disjunct, tiny
897 : // rectangles. That otherwise kills us here, since for
898 : // transparent output, SAL always prepares the whole
899 : // bitmap, if aPosAry contains the whole bitmap (and
900 : // it's _not_ to blame for that).
901 :
902 : // Note the call to ImplPixelToDevicePixel(), since
903 : // aPosAry already contains the mnOutOff-offsets, they
904 : // also have to be applied to the region
905 4 : Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
906 :
907 : // TODO: Also respect scaling (that's a bit tricky,
908 : // since the source points have to move fractional
909 : // amounts (which is not possible, thus has to be
910 : // emulated by increases copy area)
911 : // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
912 : // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
913 :
914 : // for now, only identity scales allowed
915 4 : if( !aClipRegionBounds.IsEmpty() &&
916 : aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
917 : aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
918 : {
919 : // now intersect dest rect with clip region
920 : aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
921 : aPosAry.mnDestY,
922 : aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
923 4 : aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
924 :
925 : // Note: I could theoretically optimize away the
926 : // DrawBitmap below, if the region is empty
927 : // here. Unfortunately, cannot rule out that
928 : // somebody relies on the side effects.
929 4 : if( !aClipRegionBounds.IsEmpty() )
930 : {
931 4 : aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
932 4 : aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
933 4 : aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
934 4 : aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
935 :
936 4 : aPosAry.mnDestX = aClipRegionBounds.Left();
937 4 : aPosAry.mnDestY = aClipRegionBounds.Top();
938 4 : aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
939 4 : aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
940 : }
941 : }
942 :
943 4 : mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
944 4 : *pMaskBmp->ImplGetSalBitmap(),
945 4 : this );
946 :
947 : // #110958# Paint mask to alpha channel. Luckily, the
948 : // black and white representation of the mask maps to
949 : // the alpha channel
950 :
951 : // #i25167# Restrict mask painting to _opaque_ areas
952 : // of the mask, otherwise we spoil areas where no
953 : // bitmap content was ever visible. Interestingly
954 : // enough, this can be achieved by taking the mask as
955 : // the transparency mask of itself
956 4 : if( mpAlphaVDev )
957 : mpAlphaVDev->DrawBitmapEx( rDestPt,
958 : rDestSize,
959 : BitmapEx( aBmpEx.GetMask(),
960 0 : aBmpEx.GetMask() ) );
961 : }
962 : else
963 : {
964 0 : mpGraphics->DrawBitmap( &aPosAry, *pImpBmp->ImplGetSalBitmap(), this );
965 :
966 0 : if( mpAlphaVDev )
967 : {
968 : // #i32109#: Make bitmap area opaque
969 0 : mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
970 : }
971 : }
972 : }
973 7 : }
974 : }
975 :
976 0 : void OutputDevice::DrawMask( const Point& rDestPt,
977 : const Bitmap& rBitmap, const Color& rMaskColor )
978 : {
979 : OSL_TRACE( "OutputDevice::DrawMask()" );
980 :
981 0 : if( ImplIsRecordLayout() )
982 0 : return;
983 :
984 0 : const Size aSizePix( rBitmap.GetSizePixel() );
985 0 : ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
986 :
987 0 : if( mpAlphaVDev )
988 : {
989 0 : const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
990 :
991 : // #i25167# Restrict mask painting to _opaque_ areas
992 : // of the mask, otherwise we spoil areas where no
993 : // bitmap content was ever visible. Interestingly
994 : // enough, this can be achieved by taking the mask as
995 : // the transparency mask of itself
996 : mpAlphaVDev->DrawBitmapEx( rDestPt,
997 : PixelToLogic( aSizePix ),
998 0 : BitmapEx( rMask, rMask ) );
999 : }
1000 : }
1001 :
1002 0 : void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1003 : const Bitmap& rBitmap, const Color& rMaskColor )
1004 : {
1005 : OSL_TRACE( "OutputDevice::DrawMask( Size )" );
1006 :
1007 0 : if( ImplIsRecordLayout() )
1008 0 : return;
1009 :
1010 0 : ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
1011 :
1012 : // TODO: Use mask here
1013 0 : if( mpAlphaVDev )
1014 : {
1015 0 : const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1016 :
1017 : // #i25167# Restrict mask painting to _opaque_ areas
1018 : // of the mask, otherwise we spoil areas where no
1019 : // bitmap content was ever visible. Interestingly
1020 : // enough, this can be achieved by taking the mask as
1021 : // the transparency mask of itself
1022 : mpAlphaVDev->DrawBitmapEx( rDestPt,
1023 : rDestSize,
1024 0 : BitmapEx( rMask, rMask ) );
1025 : }
1026 : }
1027 :
1028 0 : void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1029 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1030 : const Bitmap& rBitmap, const Color& rMaskColor )
1031 : {
1032 : OSL_TRACE( "OutputDevice::DrawMask( Point, Size )" );
1033 :
1034 0 : if( ImplIsRecordLayout() )
1035 0 : return;
1036 :
1037 0 : ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION );
1038 :
1039 : // TODO: Use mask here
1040 0 : if( mpAlphaVDev )
1041 : {
1042 0 : const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1043 :
1044 : // #i25167# Restrict mask painting to _opaque_ areas
1045 : // of the mask, otherwise we spoil areas where no
1046 : // bitmap content was ever visible. Interestingly
1047 : // enough, this can be achieved by taking the mask as
1048 : // the transparency mask of itself
1049 : mpAlphaVDev->DrawBitmapEx( rDestPt,
1050 : rDestSize,
1051 : rSrcPtPixel,
1052 : rSrcSizePixel,
1053 0 : BitmapEx( rMask, rMask ) );
1054 : }
1055 : }
1056 :
1057 0 : void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize,
1058 : const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1059 : const Bitmap& rBitmap, const Color& rMaskColor,
1060 : const sal_uLong nAction )
1061 : {
1062 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1063 :
1064 0 : if( ROP_INVERT == meRasterOp )
1065 : {
1066 0 : DrawRect( Rectangle( rDestPt, rDestSize ) );
1067 0 : return;
1068 : }
1069 :
1070 0 : if ( mpMetaFile )
1071 : {
1072 0 : switch( nAction )
1073 : {
1074 : case( META_MASK_ACTION ):
1075 : mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
1076 0 : rBitmap, rMaskColor ) );
1077 0 : break;
1078 :
1079 : case( META_MASKSCALE_ACTION ):
1080 : mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
1081 0 : rDestSize, rBitmap, rMaskColor ) );
1082 0 : break;
1083 :
1084 : case( META_MASKSCALEPART_ACTION ):
1085 : mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
1086 0 : rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
1087 0 : break;
1088 : }
1089 : }
1090 :
1091 0 : OUTDEV_INIT();
1092 :
1093 0 : if ( OUTDEV_PRINTER == meOutDevType )
1094 : {
1095 0 : ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
1096 0 : return;
1097 : }
1098 :
1099 0 : const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
1100 0 : if ( pImpBmp )
1101 : {
1102 : SalTwoRect aPosAry;
1103 :
1104 0 : aPosAry.mnSrcX = rSrcPtPixel.X();
1105 0 : aPosAry.mnSrcY = rSrcPtPixel.Y();
1106 0 : aPosAry.mnSrcWidth = rSrcSizePixel.Width();
1107 0 : aPosAry.mnSrcHeight = rSrcSizePixel.Height();
1108 0 : aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
1109 0 : aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
1110 0 : aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
1111 0 : aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
1112 :
1113 : // we don't want to mirror via cooridates
1114 0 : const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
1115 :
1116 : // check if output is necessary
1117 0 : if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
1118 : {
1119 :
1120 0 : if( nMirrFlags )
1121 : {
1122 0 : Bitmap aTmp( rBitmap );
1123 0 : aTmp.Mirror( nMirrFlags );
1124 0 : mpGraphics->DrawMask( &aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
1125 0 : ImplColorToSal( rMaskColor ) , this);
1126 : }
1127 : else
1128 0 : mpGraphics->DrawMask( &aPosAry, *pImpBmp->ImplGetSalBitmap(),
1129 0 : ImplColorToSal( rMaskColor ), this );
1130 :
1131 : }
1132 : }
1133 : }
1134 :
1135 : namespace
1136 : {
1137 0 : BitmapEx makeDisabledBitmap(const Bitmap &rBitmap)
1138 : {
1139 0 : const Size aTotalSize( rBitmap.GetSizePixel() );
1140 0 : Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
1141 0 : AlphaMask aGreyAlphaMask( aTotalSize );
1142 0 : BitmapReadAccess* pBmp = const_cast<Bitmap&>(rBitmap).AcquireReadAccess();
1143 0 : BitmapWriteAccess* pGrey = aGrey.AcquireWriteAccess();
1144 0 : BitmapWriteAccess* pGreyAlphaMask = aGreyAlphaMask.AcquireWriteAccess();
1145 :
1146 0 : if( pBmp && pGrey && pGreyAlphaMask )
1147 : {
1148 0 : BitmapColor aGreyVal( 0 );
1149 0 : BitmapColor aGreyAlphaMaskVal( 0 );
1150 0 : const int nLeft = 0, nRight = aTotalSize.Width();
1151 0 : const int nTop = 0, nBottom = nTop + aTotalSize.Height();
1152 :
1153 0 : for( int nY = nTop; nY < nBottom; ++nY )
1154 : {
1155 0 : for( int nX = nLeft; nX < nRight; ++nX )
1156 : {
1157 0 : aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
1158 0 : pGrey->SetPixel( nY, nX, aGreyVal );
1159 :
1160 0 : aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( 128ul ) );
1161 0 : pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
1162 : }
1163 0 : }
1164 : }
1165 :
1166 0 : const_cast<Bitmap&>(rBitmap).ReleaseAccess( pBmp );
1167 0 : aGrey.ReleaseAccess( pGrey );
1168 0 : aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
1169 0 : return BitmapEx( aGrey, aGreyAlphaMask );
1170 : }
1171 : }
1172 :
1173 2 : void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle )
1174 : {
1175 : DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1176 :
1177 2 : if( !rImage.mpImplData || ImplIsRecordLayout() )
1178 4 : return;
1179 :
1180 0 : switch( rImage.mpImplData->meType )
1181 : {
1182 : case IMAGETYPE_BITMAP:
1183 : {
1184 0 : const Bitmap &rBitmap = *static_cast< Bitmap* >( rImage.mpImplData->mpData );
1185 0 : if( nStyle & IMAGE_DRAW_DISABLE )
1186 0 : DrawBitmapEx( rPos, makeDisabledBitmap(rBitmap) );
1187 : else
1188 0 : DrawBitmap( rPos, rBitmap );
1189 : }
1190 0 : break;
1191 :
1192 : case IMAGETYPE_IMAGE:
1193 : {
1194 0 : ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1195 :
1196 0 : if( !pData->mpImageBitmap )
1197 : {
1198 0 : const Size aSize( pData->maBmpEx.GetSizePixel() );
1199 :
1200 0 : pData->mpImageBitmap = new ImplImageBmp;
1201 0 : pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1202 : }
1203 :
1204 0 : pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
1205 : }
1206 0 : break;
1207 :
1208 : default:
1209 0 : break;
1210 : }
1211 : }
1212 :
1213 0 : void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
1214 : const Image& rImage, sal_uInt16 nStyle )
1215 : {
1216 : DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1217 :
1218 0 : if( rImage.mpImplData && !ImplIsRecordLayout() )
1219 : {
1220 0 : switch( rImage.mpImplData->meType )
1221 : {
1222 : case IMAGETYPE_BITMAP:
1223 : {
1224 0 : const Bitmap &rBitmap = *static_cast< Bitmap* >( rImage.mpImplData->mpData );
1225 0 : if( nStyle & IMAGE_DRAW_DISABLE )
1226 0 : DrawBitmapEx( rPos, rSize, makeDisabledBitmap(rBitmap) );
1227 : else
1228 0 : DrawBitmap( rPos, rSize, rBitmap );
1229 : }
1230 0 : break;
1231 :
1232 : case IMAGETYPE_IMAGE:
1233 : {
1234 0 : ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1235 :
1236 0 : if ( !pData->mpImageBitmap )
1237 : {
1238 0 : const Size aSize( pData->maBmpEx.GetSizePixel() );
1239 :
1240 0 : pData->mpImageBitmap = new ImplImageBmp;
1241 0 : pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1242 : }
1243 :
1244 0 : pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
1245 : }
1246 0 : break;
1247 :
1248 : default:
1249 0 : break;
1250 : }
1251 : }
1252 0 : }
1253 :
1254 69 : Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
1255 : {
1256 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1257 :
1258 69 : Bitmap aBmp;
1259 69 : long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
1260 69 : long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
1261 69 : long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
1262 69 : long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
1263 :
1264 69 : if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
1265 : {
1266 69 : if ( nWidth && nHeight )
1267 : {
1268 69 : Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
1269 69 : bool bClipped = false;
1270 :
1271 : // X-Coordinate outside of draw area?
1272 69 : if ( nX < mnOutOffX )
1273 : {
1274 0 : nWidth -= ( mnOutOffX - nX );
1275 0 : nX = mnOutOffX;
1276 0 : bClipped = true;
1277 : }
1278 :
1279 : // Y-Coordinate outside of draw area?
1280 69 : if ( nY < mnOutOffY )
1281 : {
1282 0 : nHeight -= ( mnOutOffY - nY );
1283 0 : nY = mnOutOffY;
1284 0 : bClipped = true;
1285 : }
1286 :
1287 : // Width outside of draw area?
1288 69 : if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
1289 : {
1290 0 : nWidth = mnOutOffX + mnOutWidth - nX;
1291 0 : bClipped = true;
1292 : }
1293 :
1294 : // Height outside of draw area?
1295 69 : if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
1296 : {
1297 0 : nHeight = mnOutOffY + mnOutHeight - nY;
1298 0 : bClipped = true;
1299 : }
1300 :
1301 69 : if ( bClipped )
1302 : {
1303 : // If the visible part has been clipped, we have to create a
1304 : // Bitmap with the correct size in which we copy the clipped
1305 : // Bitmap to the correct position.
1306 0 : VirtualDevice aVDev( *this );
1307 :
1308 0 : if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
1309 : {
1310 0 : if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
1311 : {
1312 : SalTwoRect aPosAry;
1313 :
1314 0 : aPosAry.mnSrcX = nX;
1315 0 : aPosAry.mnSrcY = nY;
1316 0 : aPosAry.mnSrcWidth = nWidth;
1317 0 : aPosAry.mnSrcHeight = nHeight;
1318 0 : aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
1319 0 : aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
1320 0 : aPosAry.mnDestWidth = nWidth;
1321 0 : aPosAry.mnDestHeight = nHeight;
1322 :
1323 0 : if ( (nWidth > 0) && (nHeight > 0) )
1324 0 : (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( &aPosAry, mpGraphics, this, this );
1325 :
1326 0 : aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
1327 : }
1328 : else
1329 0 : bClipped = false;
1330 : }
1331 : else
1332 0 : bClipped = false;
1333 : }
1334 :
1335 69 : if ( !bClipped )
1336 : {
1337 69 : SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
1338 :
1339 69 : if( pSalBmp )
1340 : {
1341 69 : ImpBitmap* pImpBmp = new ImpBitmap;
1342 69 : pImpBmp->ImplSetSalBitmap( pSalBmp );
1343 69 : aBmp.ImplSetImpBitmap( pImpBmp );
1344 : }
1345 : }
1346 : }
1347 : }
1348 :
1349 69 : return aBmp;
1350 : }
1351 :
1352 0 : BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
1353 : {
1354 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1355 :
1356 : // #110958# Extract alpha value from VDev, if any
1357 0 : if( mpAlphaVDev )
1358 : {
1359 0 : Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
1360 :
1361 : // ensure 8 bit alpha
1362 0 : if( aAlphaBitmap.GetBitCount() > 8 )
1363 0 : aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
1364 :
1365 0 : return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
1366 : }
1367 : else
1368 0 : return GetBitmap( rSrcPt, rSize );
1369 : }
1370 :
1371 0 : Color OutputDevice::GetPixel( const Point& rPt ) const
1372 : {
1373 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1374 :
1375 0 : Color aColor;
1376 :
1377 0 : if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
1378 : {
1379 0 : if ( mbInitClipRegion )
1380 0 : ((OutputDevice*)this)->ImplInitClipRegion();
1381 :
1382 0 : if ( !mbOutputClipped )
1383 : {
1384 0 : const long nX = ImplLogicXToDevicePixel( rPt.X() );
1385 0 : const long nY = ImplLogicYToDevicePixel( rPt.Y() );
1386 0 : const SalColor aSalCol = mpGraphics->GetPixel( nX, nY, this );
1387 0 : aColor.SetRed( SALCOLOR_RED( aSalCol ) );
1388 0 : aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
1389 0 : aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
1390 : }
1391 : }
1392 0 : return aColor;
1393 : }
1394 :
1395 4241 : void OutputDevice::DrawPixel( const Point& rPt )
1396 : {
1397 : OSL_TRACE( "OutputDevice::DrawPixel()" );
1398 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1399 :
1400 4241 : if ( mpMetaFile )
1401 0 : mpMetaFile->AddAction( new MetaPointAction( rPt ) );
1402 :
1403 4241 : if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
1404 : return;
1405 :
1406 4241 : Point aPt = ImplLogicToDevicePixel( rPt );
1407 :
1408 4241 : if ( !mpGraphics )
1409 : {
1410 0 : if ( !ImplGetGraphics() )
1411 : return;
1412 : }
1413 :
1414 4241 : if ( mbInitClipRegion )
1415 845 : ImplInitClipRegion();
1416 4241 : if ( mbOutputClipped )
1417 : return;
1418 :
1419 4241 : if ( mbInitLineColor )
1420 3394 : ImplInitLineColor();
1421 :
1422 4241 : mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this );
1423 :
1424 4241 : if( mpAlphaVDev )
1425 0 : mpAlphaVDev->DrawPixel( rPt );
1426 : }
1427 :
1428 21105 : void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
1429 : {
1430 : OSL_TRACE( "OutputDevice::DrawPixel()" );
1431 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1432 :
1433 21105 : Color aColor = ImplDrawModeToColor( rColor );
1434 :
1435 21105 : if ( mpMetaFile )
1436 0 : mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
1437 :
1438 21105 : if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() )
1439 : return;
1440 :
1441 21105 : Point aPt = ImplLogicToDevicePixel( rPt );
1442 :
1443 21105 : if ( !mpGraphics )
1444 : {
1445 0 : if ( !ImplGetGraphics() )
1446 : return;
1447 : }
1448 :
1449 21105 : if ( mbInitClipRegion )
1450 603 : ImplInitClipRegion();
1451 21105 : if ( mbOutputClipped )
1452 : return;
1453 :
1454 21105 : mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this );
1455 :
1456 21105 : if( mpAlphaVDev )
1457 0 : mpAlphaVDev->DrawPixel( rPt );
1458 : }
1459 :
1460 0 : void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
1461 : {
1462 0 : if ( !pColors )
1463 0 : DrawPixel( rPts, GetLineColor() );
1464 : else
1465 : {
1466 : OSL_TRACE( "OutputDevice::DrawPixel()" );
1467 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1468 : DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
1469 :
1470 0 : const sal_uInt16 nSize = rPts.GetSize();
1471 :
1472 0 : if ( nSize )
1473 : {
1474 0 : if ( mpMetaFile )
1475 0 : for ( sal_uInt16 i = 0; i < nSize; i++ )
1476 0 : mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
1477 :
1478 0 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1479 0 : return;
1480 :
1481 0 : if ( mpGraphics || ImplGetGraphics() )
1482 : {
1483 0 : if ( mbInitClipRegion )
1484 0 : ImplInitClipRegion();
1485 :
1486 0 : if ( mbOutputClipped )
1487 0 : return;
1488 :
1489 0 : for ( sal_uInt16 i = 0; i < nSize; i++ )
1490 : {
1491 0 : const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
1492 0 : mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this );
1493 : }
1494 : }
1495 : }
1496 : }
1497 :
1498 0 : if( mpAlphaVDev )
1499 0 : mpAlphaVDev->DrawPixel( rPts, pColors );
1500 : }
1501 :
1502 0 : void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
1503 : {
1504 0 : if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() )
1505 : {
1506 0 : const sal_uInt16 nSize = rPts.GetSize();
1507 0 : Color* pColArray = new Color[ nSize ];
1508 :
1509 0 : for( sal_uInt16 i = 0; i < nSize; i++ )
1510 0 : pColArray[ i ] = rColor;
1511 :
1512 0 : DrawPixel( rPts, pColArray );
1513 0 : delete[] pColArray;
1514 : }
1515 :
1516 0 : if( mpAlphaVDev )
1517 0 : mpAlphaVDev->DrawPixel( rPts, rColor );
1518 0 : }
1519 :
1520 : namespace
1521 : {
1522 : // Co = Cs + Cd*(1-As) premultiplied alpha -or-
1523 : // Co = (AsCs + AdCd*(1-As)) / Ao
1524 0 : inline sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceAlpha,
1525 : const sal_uInt8 nDstAlpha, const sal_uInt8 nResAlpha, const sal_uInt8 nDestColor )
1526 : {
1527 : int c = nResAlpha ? ( (int)nSourceAlpha*nSourceColor + (int)nDstAlpha*nDestColor -
1528 0 : (int)nDstAlpha*nDestColor*nSourceAlpha/255 ) / (int)nResAlpha : 0;
1529 0 : return sal_uInt8( c );
1530 : }
1531 :
1532 0 : inline BitmapColor lcl_AlphaBlend( int nX, int nY,
1533 : const long nMapX,
1534 : const long nMapY,
1535 : BitmapReadAccess* pP,
1536 : BitmapReadAccess* pA,
1537 : BitmapReadAccess* pB,
1538 : BitmapWriteAccess* pAlphaW,
1539 : sal_uInt8& nResAlpha )
1540 : {
1541 0 : BitmapColor aDstCol,aSrcCol;
1542 0 : aSrcCol = pP->GetColor( nMapY, nMapX );
1543 0 : aDstCol = pB->GetColor( nY, nX );
1544 :
1545 : // vcl stores transparency, not alpha - invert it
1546 0 : const sal_uInt8 nSrcAlpha = 255 - pA->GetPixel( nMapY, nMapX ).GetBlueOrIndex();
1547 0 : const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixel( nY, nX ).GetBlueOrIndex();
1548 :
1549 : // Perform porter-duff compositing 'over' operation
1550 : //
1551 : // Co = Cs + Cd*(1-As)
1552 : // Ad = As + Ad*(1-As)
1553 0 : nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255;
1554 :
1555 0 : aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) );
1556 0 : aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) );
1557 0 : aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) );
1558 :
1559 0 : return aDstCol;
1560 : }
1561 : }
1562 :
1563 0 : Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp,
1564 : BitmapReadAccess* pP,
1565 : BitmapReadAccess* pA,
1566 : const Rectangle& aDstRect,
1567 : const sal_Int32 nOffY,
1568 : const sal_Int32 nDstHeight,
1569 : const sal_Int32 nOffX,
1570 : const sal_Int32 nDstWidth,
1571 : const long* pMapX,
1572 : const long* pMapY )
1573 : {
1574 0 : BitmapColor aDstCol;
1575 0 : Bitmap res;
1576 : int nX, nY;
1577 : sal_uInt8 nResAlpha;
1578 :
1579 : OSL_ENSURE(mpAlphaVDev,
1580 : "ImplBlendWithAlpha(): call me only with valid alpha VDev!" );
1581 :
1582 0 : bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
1583 0 : mpAlphaVDev->EnableMapMode(sal_False);
1584 :
1585 0 : Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
1586 0 : BitmapWriteAccess* pAlphaW = aAlphaBitmap.AcquireWriteAccess();
1587 :
1588 0 : if( GetBitCount() <= 8 )
1589 : {
1590 0 : Bitmap aDither( aBmp.GetSizePixel(), 8 );
1591 0 : BitmapColor aIndex( 0 );
1592 0 : BitmapReadAccess* pB = aBmp.AcquireReadAccess();
1593 0 : BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
1594 :
1595 0 : if( pB && pP && pA && pW && pAlphaW )
1596 : {
1597 : int nOutY;
1598 :
1599 0 : for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1600 : {
1601 0 : const long nMapY = pMapY[ nY ];
1602 0 : const long nModY = ( nOutY & 0x0FL ) << 4L;
1603 : int nOutX;
1604 :
1605 0 : for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1606 : {
1607 0 : const long nMapX = pMapX[ nX ];
1608 0 : const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
1609 :
1610 0 : aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
1611 :
1612 0 : aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
1613 0 : nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
1614 0 : nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
1615 0 : pW->SetPixel( nY, nX, aIndex );
1616 :
1617 0 : aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
1618 0 : nVCLGLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
1619 0 : nVCLBLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] ) );
1620 0 : pAlphaW->SetPixel( nY, nX, aIndex );
1621 : }
1622 : }
1623 : }
1624 :
1625 0 : aBmp.ReleaseAccess( pB );
1626 0 : aDither.ReleaseAccess( pW );
1627 0 : res = aDither;
1628 : }
1629 : else
1630 : {
1631 0 : BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
1632 0 : if( pP && pA && pB )
1633 : {
1634 0 : for( nY = 0; nY < nDstHeight; nY++ )
1635 : {
1636 0 : const long nMapY = pMapY[ nY ];
1637 :
1638 0 : for( nX = 0; nX < nDstWidth; nX++ )
1639 : {
1640 0 : const long nMapX = pMapX[ nX ];
1641 0 : aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
1642 :
1643 0 : pB->SetPixel( nY, nX, aDstCol );
1644 0 : pAlphaW->SetPixel( nY, nX, Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha) );
1645 : }
1646 : }
1647 : }
1648 :
1649 0 : aBmp.ReleaseAccess( pB );
1650 0 : res = aBmp;
1651 : }
1652 :
1653 0 : aAlphaBitmap.ReleaseAccess( pAlphaW );
1654 0 : mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
1655 0 : mpAlphaVDev->EnableMapMode( bOldMapMode );
1656 :
1657 0 : return res;
1658 : }
1659 :
1660 2 : Bitmap OutputDevice::ImplBlend( Bitmap aBmp,
1661 : BitmapReadAccess* pP,
1662 : BitmapReadAccess* pA,
1663 : const sal_Int32 nOffY,
1664 : const sal_Int32 nDstHeight,
1665 : const sal_Int32 nOffX,
1666 : const sal_Int32 nDstWidth,
1667 : const Rectangle& aBmpRect,
1668 : const Size& aOutSz,
1669 : const bool bHMirr,
1670 : const bool bVMirr,
1671 : const long* pMapX,
1672 : const long* pMapY )
1673 : {
1674 2 : BitmapColor aDstCol;
1675 2 : Bitmap res;
1676 : int nX, nY;
1677 :
1678 2 : if( GetBitCount() <= 8 )
1679 : {
1680 0 : Bitmap aDither( aBmp.GetSizePixel(), 8 );
1681 0 : BitmapColor aIndex( 0 );
1682 0 : BitmapReadAccess* pB = aBmp.AcquireReadAccess();
1683 0 : BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
1684 :
1685 0 : if( pB && pP && pA && pW )
1686 : {
1687 : int nOutY;
1688 :
1689 0 : for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1690 : {
1691 0 : const long nMapY = pMapY[ nY ];
1692 0 : const long nModY = ( nOutY & 0x0FL ) << 4L;
1693 : int nOutX;
1694 :
1695 0 : for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1696 : {
1697 0 : const long nMapX = pMapX[ nX ];
1698 0 : const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
1699 :
1700 0 : aDstCol = pB->GetColor( nY, nX );
1701 0 : aDstCol.Merge( pP->GetColor( nMapY, nMapX ), (sal_uInt8) pA->GetPixel( nMapY, nMapX ) );
1702 0 : aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
1703 0 : nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
1704 0 : nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
1705 0 : pW->SetPixel( nY, nX, aIndex );
1706 : }
1707 : }
1708 : }
1709 :
1710 0 : aBmp.ReleaseAccess( pB );
1711 0 : aDither.ReleaseAccess( pW );
1712 0 : res = aDither;
1713 : }
1714 : else
1715 : {
1716 2 : BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
1717 :
1718 2 : bool bFastBlend = false;
1719 2 : if( pP && pA && pB )
1720 : {
1721 : SalTwoRect aTR;
1722 2 : aTR.mnSrcX = aBmpRect.Left();
1723 2 : aTR.mnSrcY = aBmpRect.Top();
1724 2 : aTR.mnSrcWidth = aBmpRect.GetWidth();
1725 2 : aTR.mnSrcHeight = aBmpRect.GetHeight();
1726 2 : aTR.mnDestX = nOffX;
1727 2 : aTR.mnDestY = nOffY;
1728 2 : aTR.mnDestWidth = aOutSz.Width();
1729 2 : aTR.mnDestHeight= aOutSz.Height();
1730 :
1731 2 : if( !bHMirr && !bVMirr )
1732 2 : bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
1733 : }
1734 :
1735 2 : if( pP && pA && pB && !bFastBlend )
1736 : {
1737 2 : switch( pP->GetScanlineFormat() )
1738 : {
1739 : case( BMP_FORMAT_8BIT_PAL ):
1740 : {
1741 304 : for( nY = 0; nY < nDstHeight; nY++ )
1742 : {
1743 302 : const long nMapY = pMapY[ nY ];
1744 302 : Scanline pPScan = pP->GetScanline( nMapY );
1745 302 : Scanline pAScan = pA->GetScanline( nMapY );
1746 :
1747 45602 : for( nX = 0; nX < nDstWidth; nX++ )
1748 : {
1749 45300 : const long nMapX = pMapX[ nX ];
1750 45300 : aDstCol = pB->GetPixel( nY, nX );
1751 45300 : pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
1752 90600 : pAScan[ nMapX ] ) );
1753 : }
1754 : }
1755 : }
1756 2 : break;
1757 :
1758 : case( BMP_FORMAT_24BIT_TC_BGR ):
1759 : {
1760 0 : for( nY = 0; nY < nDstHeight; nY++ )
1761 : {
1762 0 : const long nMapY = pMapY[ nY ];
1763 0 : Scanline pPScan = pP->GetScanline( nMapY );
1764 0 : Scanline pAScan = pA->GetScanline( nMapY );
1765 :
1766 0 : for( nX = 0; nX < nDstWidth; nX++ )
1767 : {
1768 0 : const long nMapX = pMapX[ nX ];
1769 0 : Scanline pTmp = pPScan + nMapX * 3;
1770 :
1771 0 : aDstCol = pB->GetPixel( nY, nX );
1772 0 : pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
1773 0 : pAScan[ nMapX ] ) );
1774 : }
1775 : }
1776 : }
1777 0 : break;
1778 :
1779 : case( BMP_FORMAT_24BIT_TC_RGB ):
1780 : {
1781 0 : for( nY = 0; nY < nDstHeight; nY++ )
1782 : {
1783 0 : const long nMapY = pMapY[ nY ];
1784 0 : Scanline pPScan = pP->GetScanline( nMapY );
1785 0 : Scanline pAScan = pA->GetScanline( nMapY );
1786 :
1787 0 : for( nX = 0; nX < nDstWidth; nX++ )
1788 : {
1789 0 : const long nMapX = pMapX[ nX ];
1790 0 : Scanline pTmp = pPScan + nMapX * 3;
1791 :
1792 0 : aDstCol = pB->GetPixel( nY, nX );
1793 0 : pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
1794 0 : pAScan[ nMapX ] ) );
1795 : }
1796 : }
1797 : }
1798 0 : break;
1799 :
1800 : default:
1801 : {
1802 0 : for( nY = 0; nY < nDstHeight; nY++ )
1803 : {
1804 0 : const long nMapY = pMapY[ nY ];
1805 0 : Scanline pAScan = pA->GetScanline( nMapY );
1806 :
1807 0 : for( nX = 0; nX < nDstWidth; nX++ )
1808 : {
1809 0 : const long nMapX = pMapX[ nX ];
1810 0 : aDstCol = pB->GetPixel( nY, nX );
1811 : pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
1812 0 : pAScan[ nMapX ] ) );
1813 : }
1814 : }
1815 : }
1816 0 : break;
1817 : }
1818 : }
1819 :
1820 2 : aBmp.ReleaseAccess( pB );
1821 2 : res = aBmp;
1822 : }
1823 :
1824 2 : return res;
1825 : }
1826 :
1827 2 : void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
1828 : const Point& rDestPt, const Size& rDestSize,
1829 : const Point& rSrcPtPixel, const Size& rSrcSizePixel )
1830 : {
1831 2 : const Point aNullPt;
1832 2 : Point aOutPt( LogicToPixel( rDestPt ) );
1833 2 : Size aOutSz( LogicToPixel( rDestSize ) );
1834 2 : Rectangle aDstRect( aNullPt, GetOutputSizePixel() );
1835 2 : const bool bHMirr = aOutSz.Width() < 0;
1836 2 : const bool bVMirr = aOutSz.Height() < 0;
1837 :
1838 2 : if( OUTDEV_WINDOW == meOutDevType )
1839 : {
1840 0 : const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
1841 :
1842 0 : if( !aPaintRgn.IsNull() )
1843 0 : aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
1844 : }
1845 :
1846 2 : if( bHMirr )
1847 : {
1848 0 : aOutSz.Width() = -aOutSz.Width();
1849 0 : aOutPt.X() -= ( aOutSz.Width() - 1L );
1850 : }
1851 :
1852 2 : if( bVMirr )
1853 : {
1854 0 : aOutSz.Height() = -aOutSz.Height();
1855 0 : aOutPt.Y() -= ( aOutSz.Height() - 1L );
1856 : }
1857 :
1858 2 : if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
1859 : {
1860 2 : bool bNativeAlpha = false;
1861 2 : static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
1862 : // #i83087# Naturally, system alpha blending cannot work with
1863 : // separate alpha VDev
1864 2 : if( !mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr )
1865 : {
1866 2 : Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
1867 : SalTwoRect aTR = {
1868 4 : rSrcPtPixel.X(), rSrcPtPixel.Y(),
1869 4 : rSrcSizePixel.Width(), rSrcSizePixel.Height(),
1870 4 : aRelPt.X(), aRelPt.Y(),
1871 4 : aOutSz.Width(), aOutSz.Height()
1872 16 : };
1873 2 : SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap();
1874 2 : SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
1875 2 : bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this );
1876 : }
1877 :
1878 2 : VirtualDevice* pOldVDev = mpAlphaVDev;
1879 :
1880 2 : Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() );
1881 8 : if( !bNativeAlpha
1882 6 : && !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
1883 : {
1884 2 : GDIMetaFile* pOldMetaFile = mpMetaFile;
1885 2 : const bool bOldMap = mbMap;
1886 2 : mpMetaFile = NULL; // fdo#55044 reset before GetBitmap!
1887 2 : mbMap = false;
1888 2 : Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
1889 :
1890 : // #109044# The generated bitmap need not necessarily be
1891 : // of aDstRect dimensions, it's internally clipped to
1892 : // window bounds. Thus, we correct the dest size here,
1893 : // since we later use it (in nDstWidth/Height) for pixel
1894 : // access)
1895 : // #i38887# reading from screen may sometimes fail
1896 2 : if( aBmp.ImplGetImpBitmap() )
1897 2 : aDstRect.SetSize( aBmp.GetSizePixel() );
1898 :
1899 2 : BitmapColor aDstCol;
1900 2 : const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
1901 2 : const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
1902 2 : const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
1903 : // calculate offset in original bitmap
1904 : // in RTL case this is a little more complicated since the contents of the
1905 : // bitmap is not mirrored (it never is), however the paint region and bmp region
1906 : // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
1907 : // is content wise somewhere else and needs to take mirroring into account
1908 2 : const long nOffX = IsRTLEnabled()
1909 0 : ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
1910 2 : : aDstRect.Left() - aOutPt.X(),
1911 2 : nOffY = aDstRect.Top() - aOutPt.Y();
1912 : long nX, nOutX, nY, nOutY;
1913 2 : long nMirrOffX = 0;
1914 2 : long nMirrOffY = 0;
1915 2 : long* pMapX = new long[ nDstWidth ];
1916 2 : long* pMapY = new long[ nDstHeight ];
1917 :
1918 : // create horizontal mapping table
1919 2 : if( bHMirr )
1920 0 : nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
1921 :
1922 302 : for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1923 : {
1924 300 : pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
1925 300 : if( bHMirr )
1926 0 : pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
1927 : }
1928 :
1929 : // create vertical mapping table
1930 2 : if( bVMirr )
1931 0 : nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
1932 :
1933 304 : for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1934 : {
1935 302 : pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
1936 :
1937 302 : if( bVMirr )
1938 0 : pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
1939 : }
1940 :
1941 2 : BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
1942 2 : BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
1943 :
1944 : DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
1945 : pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
1946 : "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
1947 :
1948 : // #i38887# reading from screen may sometimes fail
1949 2 : if( aBmp.ImplGetImpBitmap() )
1950 : {
1951 2 : Bitmap aTmp;
1952 :
1953 2 : if( mpAlphaVDev )
1954 : {
1955 : aTmp = ImplBlendWithAlpha(
1956 : aBmp,pP,pA,
1957 : aDstRect,
1958 : nOffY,nDstHeight,
1959 : nOffX,nDstWidth,
1960 0 : pMapX,pMapY );
1961 : }
1962 : else
1963 : {
1964 : aTmp = ImplBlend(
1965 : aBmp,pP,pA,
1966 : nOffY,nDstHeight,
1967 : nOffX,nDstWidth,
1968 : aBmpRect,aOutSz,
1969 : bHMirr,bVMirr,
1970 2 : pMapX,pMapY );
1971 : }
1972 :
1973 : // #110958# Disable alpha VDev, we're doing the necessary
1974 : // stuff explicitly furher below
1975 2 : if( mpAlphaVDev )
1976 0 : mpAlphaVDev = NULL;
1977 :
1978 : DrawBitmap( aDstRect.TopLeft(),
1979 2 : aTmp );
1980 :
1981 : // #110958# Enable alpha VDev again
1982 2 : mpAlphaVDev = pOldVDev;
1983 : }
1984 :
1985 2 : ( (Bitmap&) rBmp ).ReleaseAccess( pP );
1986 2 : ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
1987 :
1988 2 : delete[] pMapX;
1989 2 : delete[] pMapY;
1990 2 : mbMap = bOldMap;
1991 2 : mpMetaFile = pOldMetaFile;
1992 : }
1993 : }
1994 2 : }
1995 :
1996 0 : void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
1997 : const Point& rDestPt, const Size& rDestSize,
1998 : const Point& rSrcPtPixel, const Size& rSrcSizePixel )
1999 : {
2000 0 : Point aPt;
2001 0 : Point aDestPt( LogicToPixel( rDestPt ) );
2002 0 : Size aDestSz( LogicToPixel( rDestSize ) );
2003 0 : Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
2004 :
2005 0 : aSrcRect.Justify();
2006 :
2007 0 : if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2008 : {
2009 0 : Bitmap aPaint( rBmp ), aMask( rMask );
2010 0 : sal_uLong nMirrFlags = 0UL;
2011 :
2012 0 : if( aMask.GetBitCount() > 1 )
2013 0 : aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2014 :
2015 : // mirrored horizontically
2016 0 : if( aDestSz.Width() < 0L )
2017 : {
2018 0 : aDestSz.Width() = -aDestSz.Width();
2019 0 : aDestPt.X() -= ( aDestSz.Width() - 1L );
2020 0 : nMirrFlags |= BMP_MIRROR_HORZ;
2021 : }
2022 :
2023 : // mirrored vertically
2024 0 : if( aDestSz.Height() < 0L )
2025 : {
2026 0 : aDestSz.Height() = -aDestSz.Height();
2027 0 : aDestPt.Y() -= ( aDestSz.Height() - 1L );
2028 0 : nMirrFlags |= BMP_MIRROR_VERT;
2029 : }
2030 :
2031 : // source cropped?
2032 0 : if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
2033 : {
2034 0 : aPaint.Crop( aSrcRect );
2035 0 : aMask.Crop( aSrcRect );
2036 : }
2037 :
2038 : // destination mirrored
2039 0 : if( nMirrFlags )
2040 : {
2041 0 : aPaint.Mirror( nMirrFlags );
2042 0 : aMask.Mirror( nMirrFlags );
2043 : }
2044 :
2045 : // we always want to have a mask
2046 0 : if( aMask.IsEmpty() )
2047 : {
2048 0 : aMask = Bitmap( aSrcRect.GetSize(), 1 );
2049 0 : aMask.Erase( Color( COL_BLACK ) );
2050 : }
2051 :
2052 : // do painting
2053 0 : const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2054 : long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2055 0 : long* pMapX = new long[ nSrcWidth + 1 ];
2056 0 : long* pMapY = new long[ nSrcHeight + 1 ];
2057 0 : const bool bOldMap = mbMap;
2058 :
2059 0 : mbMap = false;
2060 :
2061 : // create forward mapping tables
2062 0 : for( nX = 0L; nX <= nSrcWidth; nX++ )
2063 0 : pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2064 :
2065 0 : for( nY = 0L; nY <= nSrcHeight; nY++ )
2066 0 : pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2067 :
2068 : // walk through all rectangles of mask
2069 0 : Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2070 : ImplRegionInfo aInfo;
2071 0 : bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2072 :
2073 0 : while( bRgnRect )
2074 : {
2075 0 : Bitmap aBandBmp( aPaint );
2076 0 : const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) );
2077 0 : const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2078 0 : const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2079 :
2080 0 : aBandBmp.Crop( aBandRect );
2081 0 : ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION );
2082 0 : bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2083 0 : }
2084 :
2085 0 : mbMap = bOldMap;
2086 :
2087 0 : delete[] pMapX;
2088 0 : delete[] pMapY;
2089 : }
2090 0 : }
2091 :
2092 0 : void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
2093 : const Point& rDestPt, const Size& rDestSize,
2094 : const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2095 : {
2096 0 : Point aPt;
2097 0 : Point aDestPt( LogicToPixel( rDestPt ) );
2098 0 : Size aDestSz( LogicToPixel( rDestSize ) );
2099 0 : Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
2100 :
2101 0 : aSrcRect.Justify();
2102 :
2103 0 : if( !rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2104 : {
2105 0 : Bitmap aMask( rMask );
2106 0 : sal_uLong nMirrFlags = 0UL;
2107 :
2108 0 : if( aMask.GetBitCount() > 1 )
2109 0 : aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2110 :
2111 : // mirrored horizontically
2112 0 : if( aDestSz.Width() < 0L )
2113 : {
2114 0 : aDestSz.Width() = -aDestSz.Width();
2115 0 : aDestPt.X() -= ( aDestSz.Width() - 1L );
2116 0 : nMirrFlags |= BMP_MIRROR_HORZ;
2117 : }
2118 :
2119 : // mirrored vertically
2120 0 : if( aDestSz.Height() < 0L )
2121 : {
2122 0 : aDestSz.Height() = -aDestSz.Height();
2123 0 : aDestPt.Y() -= ( aDestSz.Height() - 1L );
2124 0 : nMirrFlags |= BMP_MIRROR_VERT;
2125 : }
2126 :
2127 : // source cropped?
2128 0 : if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) )
2129 0 : aMask.Crop( aSrcRect );
2130 :
2131 : // destination mirrored
2132 0 : if( nMirrFlags )
2133 0 : aMask.Mirror( nMirrFlags );
2134 :
2135 : // do painting
2136 0 : const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2137 : long nX, nY, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2138 0 : long* pMapX = new long[ nSrcWidth + 1 ];
2139 0 : long* pMapY = new long[ nSrcHeight + 1 ];
2140 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
2141 0 : const bool bOldMap = mbMap;
2142 :
2143 0 : mpMetaFile = NULL;
2144 0 : mbMap = false;
2145 0 : Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
2146 0 : SetLineColor( rMaskColor );
2147 0 : SetFillColor( rMaskColor );
2148 0 : ImplInitLineColor();
2149 0 : ImplInitFillColor();
2150 :
2151 : // create forward mapping tables
2152 0 : for( nX = 0L; nX <= nSrcWidth; nX++ )
2153 0 : pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2154 :
2155 0 : for( nY = 0L; nY <= nSrcHeight; nY++ )
2156 0 : pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2157 :
2158 : // walk through all rectangles of mask
2159 0 : Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2160 : ImplRegionInfo aInfo;
2161 0 : bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2162 :
2163 0 : while( bRgnRect )
2164 : {
2165 0 : const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2166 0 : const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2167 :
2168 0 : DrawRect( Rectangle( aMapPt, aMapSz ) );
2169 0 : bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2170 : }
2171 :
2172 0 : Pop();
2173 0 : delete[] pMapX;
2174 0 : delete[] pMapY;
2175 0 : mbMap = bOldMap;
2176 0 : mpMetaFile = pOldMetaFile;
2177 : }
2178 0 : }
2179 :
2180 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|