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