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 : #include <vcl/outdev.hxx>
22 : #include <vcl/virdev.hxx>
23 : #include <vcl/bmpacc.hxx>
24 : #include <vcl/metaact.hxx>
25 : #include <vcl/gdimtf.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/wrkwin.hxx>
28 : #include <vcl/graph.hxx>
29 :
30 : #include <wall2.hxx>
31 : #include <salgdi.hxx>
32 : #include <window.h>
33 : #include <svdata.hxx>
34 : #include <outdev.h>
35 :
36 : #include <com/sun/star/uno/Sequence.hxx>
37 :
38 : #include <basegfx/vector/b2dvector.hxx>
39 : #include <basegfx/polygon/b2dpolypolygon.hxx>
40 : #include <basegfx/polygon/b2dpolygon.hxx>
41 : #include <basegfx/matrix/b2dhommatrix.hxx>
42 :
43 : #include <math.h>
44 :
45 : // ========================================================================
46 :
47 : DBG_NAMEEX( OutputDevice )
48 :
49 : // ------------------------------------------------------------------------
50 :
51 4349 : void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags )
52 : {
53 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
54 :
55 4349 : Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
56 4349 : aDstRect.Intersection( rRect );
57 :
58 4349 : if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
59 0 : return;
60 :
61 4349 : if( !mpGraphics && !ImplGetGraphics() )
62 0 : return;
63 :
64 4349 : if( mbInitClipRegion )
65 13 : ImplInitClipRegion();
66 :
67 4349 : if( mbOutputClipped )
68 0 : return;
69 :
70 4349 : const long nDistX = std::max( rDist.Width(), 1L );
71 4349 : const long nDistY = std::max( rDist.Height(), 1L );
72 4349 : long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
73 4349 : long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
74 4349 : const long nRight = aDstRect.Right();
75 4349 : const long nBottom = aDstRect.Bottom();
76 4349 : const long nStartX = ImplLogicXToDevicePixel( nX );
77 4349 : const long nEndX = ImplLogicXToDevicePixel( nRight );
78 4349 : const long nStartY = ImplLogicYToDevicePixel( nY );
79 4349 : const long nEndY = ImplLogicYToDevicePixel( nBottom );
80 4349 : long nHorzCount = 0L;
81 4349 : long nVertCount = 0L;
82 :
83 4349 : ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
84 8698 : ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
85 :
86 4349 : if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
87 : {
88 2450 : aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
89 2450 : aVertBuf[ nVertCount++ ] = nStartY;
90 35115 : while( ( nY += nDistY ) <= nBottom )
91 30215 : aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
92 : }
93 :
94 4349 : if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
95 : {
96 2111 : aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
97 2111 : aHorzBuf[ nHorzCount++ ] = nStartX;
98 18817 : while( ( nX += nDistX ) <= nRight )
99 14595 : aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
100 : }
101 :
102 4349 : if( mbInitLineColor )
103 1980 : ImplInitLineColor();
104 :
105 4349 : if( mbInitFillColor )
106 0 : ImplInitFillColor();
107 :
108 4349 : const sal_Bool bOldMap = mbMap;
109 4349 : EnableMapMode( sal_False );
110 :
111 4349 : if( nFlags & GRID_DOTS )
112 : {
113 2865 : for( long i = 0L; i < nVertCount; i++ )
114 56152 : for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
115 53499 : mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
116 : }
117 : else
118 : {
119 4137 : if( nFlags & GRID_HORZLINES )
120 : {
121 32250 : for( long i = 0L; i < nVertCount; i++ )
122 : {
123 30012 : nY = aVertBuf[ i ];
124 30012 : mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
125 : }
126 : }
127 :
128 4137 : if( nFlags & GRID_VERTLINES )
129 : {
130 14329 : for( long i = 0L; i < nHorzCount; i++ )
131 : {
132 12430 : nX = aHorzBuf[ i ];
133 12430 : mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
134 : }
135 : }
136 : }
137 :
138 4349 : EnableMapMode( bOldMap );
139 :
140 4349 : if( mpAlphaVDev )
141 4349 : mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
142 : }
143 :
144 : // ------------------------------------------------------------------------
145 : // Caution: This method is nearly the same as
146 : // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
147 : // so when changes are made here do not forget to make change sthere, too
148 :
149 123135 : void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
150 : {
151 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
152 :
153 : // AW: Do NOT paint empty PolyPolygons
154 123135 : if(!rB2DPolyPoly.count())
155 0 : return;
156 :
157 : // we need a graphics
158 123135 : if( !mpGraphics )
159 0 : if( !ImplGetGraphics() )
160 0 : return;
161 :
162 123135 : if( mbInitClipRegion )
163 948 : ImplInitClipRegion();
164 123135 : if( mbOutputClipped )
165 0 : return;
166 :
167 123135 : if( mbInitLineColor )
168 6356 : ImplInitLineColor();
169 123135 : if( mbInitFillColor )
170 101865 : ImplInitFillColor();
171 :
172 246270 : if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
173 0 : && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
174 123135 : && ROP_OVERPAINT == GetRasterOp() )
175 : {
176 : // b2dpolygon support not implemented yet on non-UNX platforms
177 0 : const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
178 0 : basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
179 :
180 : // transform the polygon into device space and ensure it is closed
181 0 : aB2DPolyPolygon.transform( aTransform );
182 0 : aB2DPolyPolygon.setClosed( true );
183 :
184 0 : bool bDrawnOk = true;
185 0 : if( IsFillColor() )
186 0 : bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
187 0 : if( bDrawnOk && IsLineColor() )
188 : {
189 0 : const basegfx::B2DVector aHairlineWidth(1,1);
190 0 : const int nPolyCount = aB2DPolyPolygon.count();
191 0 : for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
192 : {
193 0 : const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
194 0 : mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
195 0 : }
196 : }
197 :
198 0 : if( bDrawnOk )
199 : {
200 0 : if( mpMetaFile )
201 0 : mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
202 0 : return;
203 0 : }
204 : }
205 :
206 : // fallback to old polygon drawing if needed
207 123135 : DrawTransparent(PolyPolygon(rB2DPolyPoly), static_cast< sal_uInt16 >(fTransparency * 100.0));
208 : }
209 :
210 : // ------------------------------------------------------------------------
211 :
212 125253 : void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
213 : sal_uInt16 nTransparencePercent )
214 : {
215 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
216 :
217 : // short circuit for drawing an opaque polygon
218 125253 : if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
219 : {
220 122381 : DrawPolyPolygon( rPolyPoly );
221 122381 : return;
222 : }
223 :
224 : // short circuit for drawing an invisible polygon
225 2872 : if( !mbFillColor || (nTransparencePercent >= 100) )
226 : {
227 : // short circuit if the polygon border is invisible too
228 9 : if( !mbLineColor )
229 9 : return;
230 :
231 : // DrawTransparent() assumes that the border is NOT to be drawn transparently???
232 0 : Push( PUSH_FILLCOLOR );
233 0 : SetFillColor();
234 0 : DrawPolyPolygon( rPolyPoly );
235 0 : Pop();
236 0 : return;
237 : }
238 :
239 : // handle metafile recording
240 2863 : if( mpMetaFile )
241 3 : mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
242 :
243 2863 : bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
244 2863 : if( bDrawn )
245 3 : return;
246 :
247 : // get the device graphics as drawing target
248 2860 : if( !mpGraphics )
249 0 : if( !ImplGetGraphics() )
250 0 : return;
251 :
252 : // debug helper:
253 2860 : static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
254 :
255 : // try hard to draw it directly, because the emulation layers are slower
256 5720 : if( !pDisableNative
257 2860 : && mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
258 : #if defined UNX && ! defined MACOSX
259 2860 : && GetBitCount() > 8
260 : #endif
261 : #ifdef WIN32
262 : // workaround bad dithering on remote displaying when using GDI+ with toolbar buttoin hilighting
263 : && !rPolyPoly.IsRect()
264 : #endif
265 : )
266 : {
267 : // prepare the graphics device
268 0 : if( mbInitClipRegion )
269 0 : ImplInitClipRegion();
270 0 : if( mbOutputClipped )
271 0 : return;
272 0 : if( mbInitLineColor )
273 0 : ImplInitLineColor();
274 0 : if( mbInitFillColor )
275 0 : ImplInitFillColor();
276 :
277 : // get the polygon in device coordinates
278 0 : basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
279 0 : const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
280 0 : aB2DPolyPolygon.transform( aTransform );
281 :
282 0 : const double fTransparency = 0.01 * nTransparencePercent;
283 0 : if( mbFillColor )
284 : {
285 : // #i121591#
286 : // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
287 : // should be used when printing. Normally this is avoided by the printer being
288 : // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
289 : // to add (OUTDEV_PRINTER != meOutDevType) to the entering if statement, thus
290 : // using the fallbacl some lines below (which is not very good, though). For
291 : // now, WinSalGraphics::drawPolyPolygon will detect printer usage and correct
292 : // the wrong mapping (see there for details)
293 0 : bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
294 : }
295 :
296 0 : if( mbLineColor )
297 : {
298 : // disable the fill color for now
299 0 : mpGraphics->SetFillColor();
300 : // draw the border line
301 0 : const basegfx::B2DVector aLineWidths( 1, 1 );
302 0 : const int nPolyCount = aB2DPolyPolygon.count();
303 0 : for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
304 : {
305 0 : const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
306 0 : bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
307 0 : }
308 : // prepare to restore the fill color
309 0 : mbInitFillColor = mbFillColor;
310 0 : }
311 : }
312 :
313 2860 : if( bDrawn )
314 0 : return;
315 :
316 2860 : VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
317 :
318 : // #110958# Disable alpha VDev, we perform the necessary
319 : // operation explicitly further below.
320 2860 : if( mpAlphaVDev )
321 0 : mpAlphaVDev = NULL;
322 :
323 2860 : GDIMetaFile* pOldMetaFile = mpMetaFile;
324 2860 : mpMetaFile = NULL;
325 :
326 2860 : if( OUTDEV_PRINTER == meOutDevType )
327 : {
328 0 : if(100 <= nTransparencePercent)
329 : {
330 : // #i112959# 100% transparent, draw nothing
331 0 : return;
332 : }
333 :
334 0 : Rectangle aPolyRect( LogicToPixel( rPolyPoly ).GetBoundRect() );
335 0 : const Size aDPISize( LogicToPixel( Size( 1, 1 ), MAP_INCH ) );
336 0 : const long nBaseExtent = std::max( FRound( aDPISize.Width() / 300. ), 1L );
337 : long nMove;
338 : const sal_uInt16 nTrans = ( nTransparencePercent < 13 ) ? 0 :
339 : ( nTransparencePercent < 38 ) ? 25 :
340 : ( nTransparencePercent < 63 ) ? 50 :
341 0 : ( nTransparencePercent < 88 ) ? 75 : 100;
342 :
343 0 : switch( nTrans )
344 : {
345 0 : case( 25 ): nMove = nBaseExtent * 3; break;
346 0 : case( 50 ): nMove = nBaseExtent * 4; break;
347 0 : case( 75 ): nMove = nBaseExtent * 6; break;
348 :
349 : // #i112959# very transparent (88 < nTransparencePercent <= 99)
350 0 : case( 100 ): nMove = nBaseExtent * 8; break;
351 :
352 : // #i112959# not transparent (nTransparencePercent < 13)
353 0 : default: nMove = 0; break;
354 : }
355 :
356 0 : Push( PUSH_CLIPREGION | PUSH_LINECOLOR );
357 0 : IntersectClipRegion(Region(rPolyPoly));
358 0 : SetLineColor( GetFillColor() );
359 0 : const sal_Bool bOldMap = mbMap;
360 0 : EnableMapMode( sal_False );
361 :
362 0 : if(nMove)
363 : {
364 0 : Rectangle aRect( aPolyRect.TopLeft(), Size( aPolyRect.GetWidth(), nBaseExtent ) );
365 0 : while( aRect.Top() <= aPolyRect.Bottom() )
366 : {
367 0 : DrawRect( aRect );
368 0 : aRect.Move( 0, nMove );
369 : }
370 :
371 0 : aRect = Rectangle( aPolyRect.TopLeft(), Size( nBaseExtent, aPolyRect.GetHeight() ) );
372 0 : while( aRect.Left() <= aPolyRect.Right() )
373 : {
374 0 : DrawRect( aRect );
375 0 : aRect.Move( nMove, 0 );
376 : }
377 : }
378 : else
379 : {
380 : // #i112959# if not transparent, draw full rectangle in clip region
381 0 : DrawRect( aPolyRect );
382 : }
383 :
384 0 : EnableMapMode( bOldMap );
385 0 : Pop();
386 : }
387 : else
388 : {
389 2860 : PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
390 2860 : Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
391 2860 : Point aPoint;
392 2860 : Rectangle aDstRect( aPoint, GetOutputSizePixel() );
393 :
394 2860 : aDstRect.Intersection( aPolyRect );
395 :
396 2860 : if( OUTDEV_WINDOW == meOutDevType )
397 : {
398 2106 : const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
399 :
400 2106 : if( !aPaintRgn.IsNull() )
401 2105 : aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
402 : }
403 :
404 2860 : if( !aDstRect.IsEmpty() )
405 : {
406 : // #i66849# Added fast path for exactly rectangular
407 : // polygons
408 : // #i83087# Naturally, system alpha blending cannot
409 : // work with separate alpha VDev
410 2860 : if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
411 : {
412 : // setup Graphics only here (other cases delegate
413 : // to basic OutDev methods)
414 0 : if ( mbInitClipRegion )
415 0 : ImplInitClipRegion();
416 0 : if ( mbInitLineColor )
417 0 : ImplInitLineColor();
418 0 : if ( mbInitFillColor )
419 0 : ImplInitFillColor();
420 :
421 0 : Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
422 0 : Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
423 :
424 0 : if( !mbOutputClipped )
425 : {
426 : bDrawn = mpGraphics->DrawAlphaRect(
427 0 : aPixelRect.Left(), aPixelRect.Top(),
428 : // #i98405# use methods with small g, else one pixel too much will be painted.
429 : // This is because the source is a polygon which when painted would not paint
430 : // the rightmost and lowest pixel line(s), so use one pixel less for the
431 : // rectangle, too.
432 : aPixelRect.getWidth(), aPixelRect.getHeight(),
433 0 : sal::static_int_cast<sal_uInt8>(nTransparencePercent),
434 0 : this );
435 : }
436 : else
437 0 : bDrawn = true;
438 : }
439 :
440 2860 : if( !bDrawn )
441 : {
442 2860 : VirtualDevice aVDev( *this, 1 );
443 2860 : const Size aDstSz( aDstRect.GetSize() );
444 2860 : const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
445 :
446 2860 : if( aDstRect.Left() || aDstRect.Top() )
447 2662 : aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
448 :
449 2860 : if( aVDev.SetOutputSizePixel( aDstSz ) )
450 : {
451 2860 : const sal_Bool bOldMap = mbMap;
452 :
453 2860 : EnableMapMode( sal_False );
454 :
455 2860 : aVDev.SetLineColor( COL_BLACK );
456 2860 : aVDev.SetFillColor( COL_BLACK );
457 2860 : aVDev.DrawPolyPolygon( aPolyPoly );
458 :
459 2860 : Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
460 5720 : Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
461 :
462 : // #107766# check for non-empty bitmaps before accessing them
463 2860 : if( !!aPaint && !!aPolyMask )
464 : {
465 2860 : BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
466 2860 : BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
467 :
468 2860 : if( pW && pR )
469 : {
470 2860 : BitmapColor aPixCol;
471 5720 : const BitmapColor aFillCol( GetFillColor() );
472 5720 : const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
473 5720 : const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
474 2860 : const long nWidth = pW->Width(), nHeight = pW->Height();
475 2860 : const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
476 : long nX, nY;
477 :
478 2860 : if( aPaint.GetBitCount() <= 8 )
479 : {
480 0 : const BitmapPalette& rPal = pW->GetPalette();
481 0 : const sal_uInt16 nCount = rPal.GetEntryCount();
482 0 : BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ];
483 :
484 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
485 : {
486 0 : BitmapColor aCol( rPal[ i ] );
487 0 : pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
488 0 : }
489 :
490 0 : if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
491 0 : pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
492 : {
493 0 : const sal_uInt8 cBlack = aBlack.GetIndex();
494 :
495 0 : for( nY = 0; nY < nHeight; nY++ )
496 : {
497 0 : Scanline pWScan = pW->GetScanline( nY );
498 0 : Scanline pRScan = pR->GetScanline( nY );
499 0 : sal_uInt8 cBit = 128;
500 :
501 0 : for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
502 : {
503 0 : if( !cBit )
504 0 : cBit = 128, pRScan++;
505 :
506 0 : if( ( *pRScan & cBit ) == cBlack )
507 0 : *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex();
508 : }
509 : }
510 : }
511 : else
512 : {
513 0 : for( nY = 0; nY < nHeight; nY++ )
514 0 : for( nX = 0; nX < nWidth; nX++ )
515 0 : if( pR->GetPixel( nY, nX ) == aBlack )
516 0 : pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
517 : }
518 :
519 0 : delete[] (sal_uInt8*) pMap;
520 : }
521 : else
522 : {
523 5720 : if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
524 2860 : pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
525 : {
526 2860 : const sal_uInt8 cBlack = aBlack.GetIndex();
527 :
528 97266 : for( nY = 0; nY < nHeight; nY++ )
529 : {
530 94406 : Scanline pWScan = pW->GetScanline( nY );
531 94406 : Scanline pRScan = pR->GetScanline( nY );
532 94406 : sal_uInt8 cBit = 128;
533 :
534 5899658 : for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
535 : {
536 5805252 : if( !cBit )
537 659493 : cBit = 128, pRScan++;
538 :
539 5805252 : if( ( *pRScan & cBit ) == cBlack )
540 : {
541 2914794 : pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
542 2914794 : pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
543 2914794 : pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
544 : }
545 : }
546 : }
547 : }
548 : else
549 : {
550 0 : for( nY = 0; nY < nHeight; nY++ )
551 : {
552 0 : for( nX = 0; nX < nWidth; nX++ )
553 : {
554 0 : if( pR->GetPixel( nY, nX ) == aBlack )
555 : {
556 0 : aPixCol = pW->GetColor( nY, nX );
557 0 : pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
558 : }
559 : }
560 : }
561 : }
562 2860 : }
563 : }
564 :
565 2860 : aPolyMask.ReleaseAccess( pR );
566 2860 : aPaint.ReleaseAccess( pW );
567 :
568 2860 : DrawBitmap( aDstRect.TopLeft(), aPaint );
569 :
570 2860 : EnableMapMode( bOldMap );
571 :
572 2860 : if( mbLineColor )
573 : {
574 2106 : Push( PUSH_FILLCOLOR );
575 2106 : SetFillColor();
576 2106 : DrawPolyPolygon( rPolyPoly );
577 2106 : Pop();
578 : }
579 2860 : }
580 : }
581 : else
582 0 : DrawPolyPolygon( rPolyPoly );
583 : }
584 2860 : }
585 : }
586 :
587 2860 : mpMetaFile = pOldMetaFile;
588 :
589 : // #110958# Restore disabled alpha VDev
590 2860 : mpAlphaVDev = pOldAlphaVDev;
591 :
592 : // #110958# Apply alpha value also to VDev alpha channel
593 2860 : if( mpAlphaVDev )
594 : {
595 0 : const Color aFillCol( mpAlphaVDev->GetFillColor() );
596 0 : mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
597 0 : sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
598 0 : sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
599 :
600 0 : mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
601 :
602 0 : mpAlphaVDev->SetFillColor( aFillCol );
603 : }
604 : }
605 :
606 : // -----------------------------------------------------------------------
607 :
608 0 : void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
609 : const Size& rSize, const Gradient& rTransparenceGradient )
610 : {
611 : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
612 :
613 0 : const Color aBlack( COL_BLACK );
614 :
615 0 : if( mpMetaFile )
616 : {
617 : // missing here is to map the data using the DeviceTransformation
618 0 : mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
619 : }
620 :
621 0 : if ( !IsDeviceOutputNecessary() )
622 0 : return;
623 :
624 0 : if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
625 : ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
626 : {
627 0 : ( (GDIMetaFile&) rMtf ).WindStart();
628 0 : ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
629 0 : ( (GDIMetaFile&) rMtf ).WindStart();
630 : }
631 : else
632 : {
633 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
634 0 : Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
635 0 : Point aPoint;
636 0 : Rectangle aDstRect( aPoint, GetOutputSizePixel() );
637 :
638 0 : mpMetaFile = NULL;
639 0 : aDstRect.Intersection( aOutRect );
640 :
641 0 : if( OUTDEV_WINDOW == meOutDevType )
642 : {
643 0 : const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
644 :
645 0 : if( !aPaintRgn.IsNull() )
646 0 : aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
647 : }
648 :
649 0 : if( !aDstRect.IsEmpty() )
650 : {
651 0 : VirtualDevice* pVDev = new VirtualDevice;
652 :
653 0 : ((OutputDevice*)pVDev)->mnDPIX = mnDPIX;
654 0 : ((OutputDevice*)pVDev)->mnDPIY = mnDPIY;
655 :
656 0 : if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
657 : {
658 0 : if(GetAntialiasing())
659 : {
660 : // #i102109#
661 : // For MetaFile replay (see task) it may now be necessary to take
662 : // into account that the content is AntiAlialised and needs to be masked
663 : // like that. Instead of masking, i will use a copy-modify-paste cycle
664 : // here (as i already use in the VclPrimiziveRenderer with successs)
665 0 : pVDev->SetAntialiasing(GetAntialiasing());
666 :
667 : // create MapMode for buffer (offset needed) and set
668 0 : MapMode aMap(GetMapMode());
669 0 : const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
670 0 : aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
671 0 : pVDev->SetMapMode(aMap);
672 :
673 : // copy MapMode state and disable for target
674 0 : const bool bOrigMapModeEnabled(IsMapModeEnabled());
675 0 : EnableMapMode(false);
676 :
677 : // copy MapMode state and disable for buffer
678 0 : const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
679 0 : pVDev->EnableMapMode(false);
680 :
681 : // copy content from original to buffer
682 : pVDev->DrawOutDev(
683 0 : aPoint, pVDev->GetOutputSizePixel(), // dest
684 0 : aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
685 0 : *this);
686 :
687 : // draw MetaFile to buffer
688 0 : pVDev->EnableMapMode(bBufferMapModeEnabled);
689 0 : ((GDIMetaFile&)rMtf).WindStart();
690 0 : ((GDIMetaFile&)rMtf).Play(pVDev, rPos, rSize);
691 0 : ((GDIMetaFile&)rMtf).WindStart();
692 :
693 : // get content bitmap from buffer
694 0 : pVDev->EnableMapMode(false);
695 0 : const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
696 :
697 : // create alpha mask from gradient and get as Bitmap
698 0 : pVDev->EnableMapMode(bBufferMapModeEnabled);
699 0 : pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
700 0 : pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
701 0 : pVDev->SetDrawMode(DRAWMODE_DEFAULT);
702 0 : pVDev->EnableMapMode(false);
703 0 : const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
704 :
705 0 : delete pVDev;
706 :
707 : // draw masked content to target and restore MapMode
708 0 : DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
709 0 : EnableMapMode(bOrigMapModeEnabled);
710 : }
711 : else
712 : {
713 0 : Bitmap aPaint, aMask;
714 0 : AlphaMask aAlpha;
715 0 : MapMode aMap( GetMapMode() );
716 0 : Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
717 0 : const sal_Bool bOldMap = mbMap;
718 :
719 0 : aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
720 0 : pVDev->SetMapMode( aMap );
721 0 : const sal_Bool bVDevOldMap = pVDev->IsMapModeEnabled();
722 :
723 : // create paint bitmap
724 0 : ( (GDIMetaFile&) rMtf ).WindStart();
725 0 : ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
726 0 : ( (GDIMetaFile&) rMtf ).WindStart();
727 0 : pVDev->EnableMapMode( sal_False );
728 0 : aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
729 0 : pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
730 :
731 : // create mask bitmap
732 0 : pVDev->SetLineColor( COL_BLACK );
733 0 : pVDev->SetFillColor( COL_BLACK );
734 0 : pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
735 : pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
736 0 : DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
737 0 : ( (GDIMetaFile&) rMtf ).WindStart();
738 0 : ( (GDIMetaFile&) rMtf ).Play( pVDev, rPos, rSize );
739 0 : ( (GDIMetaFile&) rMtf ).WindStart();
740 0 : pVDev->EnableMapMode( sal_False );
741 0 : aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
742 0 : pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
743 :
744 : // create alpha mask from gradient
745 0 : pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
746 0 : pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
747 0 : pVDev->SetDrawMode( DRAWMODE_DEFAULT );
748 0 : pVDev->EnableMapMode( sal_False );
749 0 : pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
750 :
751 0 : aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
752 :
753 0 : delete pVDev;
754 :
755 0 : EnableMapMode( sal_False );
756 0 : DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
757 0 : EnableMapMode( bOldMap );
758 : }
759 : }
760 : else
761 0 : delete pVDev;
762 : }
763 :
764 0 : mpMetaFile = pOldMetaFile;
765 : }
766 : }
767 :
768 : // -----------------------------------------------------------------------
769 :
770 137991 : void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
771 : long nWidth, long nHeight,
772 : const Wallpaper& rWallpaper )
773 : {
774 : // Wallpaper ohne Umrandung zeichnen
775 137991 : Color aOldLineColor = GetLineColor();
776 137991 : Color aOldFillColor = GetFillColor();
777 137991 : SetLineColor();
778 137991 : SetFillColor( rWallpaper.GetColor() );
779 137991 : sal_Bool bMap = mbMap;
780 137991 : EnableMapMode( sal_False );
781 137991 : DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
782 137991 : SetLineColor( aOldLineColor );
783 137991 : SetFillColor( aOldFillColor );
784 137991 : EnableMapMode( bMap );
785 137991 : }
786 :
787 : // -----------------------------------------------------------------------
788 :
789 0 : void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
790 : long nWidth, long nHeight,
791 : const Wallpaper& rWallpaper )
792 : {
793 0 : BitmapEx aBmpEx;
794 0 : const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
795 0 : Point aPos;
796 0 : Size aSize;
797 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
798 0 : const WallpaperStyle eStyle = rWallpaper.GetStyle();
799 0 : const sal_Bool bOldMap = mbMap;
800 0 : bool bDrawn = false;
801 0 : bool bDrawGradientBackground = false;
802 0 : bool bDrawColorBackground = false;
803 :
804 0 : if( pCached )
805 0 : aBmpEx = *pCached;
806 : else
807 0 : aBmpEx = rWallpaper.GetBitmap();
808 :
809 0 : const long nBmpWidth = aBmpEx.GetSizePixel().Width();
810 0 : const long nBmpHeight = aBmpEx.GetSizePixel().Height();
811 0 : const sal_Bool bTransparent = aBmpEx.IsTransparent();
812 :
813 : // draw background
814 0 : if( bTransparent )
815 : {
816 0 : if( rWallpaper.IsGradient() )
817 0 : bDrawGradientBackground = true;
818 : else
819 : {
820 0 : if( !pCached && !rWallpaper.GetColor().GetTransparency() )
821 : {
822 0 : VirtualDevice aVDev( *this );
823 0 : aVDev.SetBackground( rWallpaper.GetColor() );
824 0 : aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
825 0 : aVDev.DrawBitmapEx( Point(), aBmpEx );
826 0 : aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
827 : }
828 :
829 0 : bDrawColorBackground = true;
830 : }
831 : }
832 0 : else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
833 : {
834 0 : if( rWallpaper.IsGradient() )
835 0 : bDrawGradientBackground = true;
836 : else
837 0 : bDrawColorBackground = true;
838 : }
839 :
840 : // background of bitmap?
841 0 : if( bDrawGradientBackground )
842 0 : ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
843 0 : else if( bDrawColorBackground && bTransparent )
844 : {
845 0 : ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
846 0 : bDrawColorBackground = false;
847 : }
848 :
849 : // calc pos and size
850 0 : if( rWallpaper.IsRect() )
851 : {
852 0 : const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
853 0 : aPos = aBound.TopLeft();
854 0 : aSize = aBound.GetSize();
855 : }
856 : else
857 : {
858 0 : aPos = Point( 0, 0 );
859 0 : aSize = Size( mnOutWidth, mnOutHeight );
860 : }
861 :
862 0 : mpMetaFile = NULL;
863 0 : EnableMapMode( sal_False );
864 0 : Push( PUSH_CLIPREGION );
865 0 : IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
866 :
867 0 : switch( eStyle )
868 : {
869 : case( WALLPAPER_SCALE ):
870 : {
871 0 : if( !pCached || ( pCached->GetSizePixel() != aSize ) )
872 : {
873 0 : if( pCached )
874 0 : rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
875 :
876 0 : aBmpEx = rWallpaper.GetBitmap();
877 0 : aBmpEx.Scale( aSize );
878 0 : aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
879 : }
880 : }
881 0 : break;
882 :
883 : case( WALLPAPER_TOPLEFT ):
884 0 : break;
885 :
886 : case( WALLPAPER_TOP ):
887 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
888 0 : break;
889 :
890 : case( WALLPAPER_TOPRIGHT ):
891 0 : aPos.X() += ( aSize.Width() - nBmpWidth );
892 0 : break;
893 :
894 : case( WALLPAPER_LEFT ):
895 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
896 0 : break;
897 :
898 : case( WALLPAPER_CENTER ):
899 : {
900 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
901 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
902 : }
903 0 : break;
904 :
905 : case( WALLPAPER_RIGHT ):
906 : {
907 0 : aPos.X() += ( aSize.Width() - nBmpWidth );
908 0 : aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
909 : }
910 0 : break;
911 :
912 : case( WALLPAPER_BOTTOMLEFT ):
913 0 : aPos.Y() += ( aSize.Height() - nBmpHeight );
914 0 : break;
915 :
916 : case( WALLPAPER_BOTTOM ):
917 : {
918 0 : aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
919 0 : aPos.Y() += ( aSize.Height() - nBmpHeight );
920 : }
921 0 : break;
922 :
923 : case( WALLPAPER_BOTTOMRIGHT ):
924 : {
925 0 : aPos.X() += ( aSize.Width() - nBmpWidth );
926 0 : aPos.Y() += ( aSize.Height() - nBmpHeight );
927 : }
928 0 : break;
929 :
930 : default:
931 : {
932 0 : const long nRight = nX + nWidth - 1L;
933 0 : const long nBottom = nY + nHeight - 1L;
934 : long nFirstX;
935 : long nFirstY;
936 :
937 0 : if( eStyle == WALLPAPER_TILE )
938 : {
939 0 : nFirstX = aPos.X();
940 0 : nFirstY = aPos.Y();
941 : }
942 : else
943 : {
944 0 : nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
945 0 : nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
946 : }
947 :
948 0 : const long nOffX = ( nFirstX - nX ) % nBmpWidth;
949 0 : const long nOffY = ( nFirstY - nY ) % nBmpHeight;
950 0 : long nStartX = nX + nOffX;
951 0 : long nStartY = nY + nOffY;
952 :
953 0 : if( nOffX > 0L )
954 0 : nStartX -= nBmpWidth;
955 :
956 0 : if( nOffY > 0L )
957 0 : nStartY -= nBmpHeight;
958 :
959 0 : for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
960 0 : for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
961 0 : DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
962 :
963 0 : bDrawn = true;
964 : }
965 0 : break;
966 : }
967 :
968 0 : if( !bDrawn )
969 : {
970 : // optimized for non-transparent bitmaps
971 0 : if( bDrawColorBackground )
972 : {
973 0 : const Size aBmpSize( aBmpEx.GetSizePixel() );
974 0 : const Point aTmpPoint;
975 0 : const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
976 0 : const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
977 0 : Rectangle aWorkRect;
978 :
979 0 : aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
980 0 : aWorkRect.Justify();
981 0 : aWorkRect.Intersection( aColRect );
982 0 : if( !aWorkRect.IsEmpty() )
983 : {
984 0 : ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
985 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
986 0 : rWallpaper );
987 : }
988 :
989 0 : aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
990 0 : aWorkRect.Justify();
991 0 : aWorkRect.Intersection( aColRect );
992 0 : if( !aWorkRect.IsEmpty() )
993 : {
994 0 : ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
995 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
996 0 : rWallpaper );
997 : }
998 :
999 0 : aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
1000 0 : aWorkRect.Justify();
1001 0 : aWorkRect.Intersection( aColRect );
1002 0 : if( !aWorkRect.IsEmpty() )
1003 : {
1004 0 : ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1005 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1006 0 : rWallpaper );
1007 : }
1008 :
1009 0 : aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
1010 0 : aWorkRect.Justify();
1011 0 : aWorkRect.Intersection( aColRect );
1012 0 : if( !aWorkRect.IsEmpty() )
1013 : {
1014 0 : ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
1015 : aWorkRect.GetWidth(), aWorkRect.GetHeight(),
1016 0 : rWallpaper );
1017 : }
1018 : }
1019 :
1020 0 : DrawBitmapEx( aPos, aBmpEx );
1021 : }
1022 :
1023 0 : rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
1024 :
1025 0 : Pop();
1026 0 : EnableMapMode( bOldMap );
1027 0 : mpMetaFile = pOldMetaFile;
1028 0 : }
1029 :
1030 : // -----------------------------------------------------------------------
1031 :
1032 2873 : void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
1033 : long nWidth, long nHeight,
1034 : const Wallpaper& rWallpaper )
1035 : {
1036 2873 : Rectangle aBound;
1037 2873 : GDIMetaFile* pOldMetaFile = mpMetaFile;
1038 2873 : const sal_Bool bOldMap = mbMap;
1039 2873 : bool bNeedGradient = true;
1040 :
1041 2873 : aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
1042 :
1043 2873 : mpMetaFile = NULL;
1044 2873 : EnableMapMode( sal_False );
1045 2873 : Push( PUSH_CLIPREGION );
1046 2873 : IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
1047 :
1048 2873 : if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT )
1049 : {
1050 2873 : Window *pWin = dynamic_cast< Window* >( this );
1051 2873 : if( pWin )
1052 : {
1053 : // limit gradient to useful size, so that it still can be noticed
1054 : // in maximized windows
1055 2873 : long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width();
1056 2873 : if( gradientWidth > 1024 )
1057 0 : gradientWidth = 1024;
1058 2873 : if( mnOutOffX+nWidth > gradientWidth )
1059 0 : ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() );
1060 2873 : if( mnOutOffX > gradientWidth )
1061 0 : bNeedGradient = false;
1062 : else
1063 2873 : aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) );
1064 : }
1065 : }
1066 :
1067 2873 : if( bNeedGradient )
1068 2873 : DrawGradient( aBound, rWallpaper.GetGradient() );
1069 :
1070 2873 : Pop();
1071 2873 : EnableMapMode( bOldMap );
1072 2873 : mpMetaFile = pOldMetaFile;
1073 2873 : }
1074 :
1075 : // -----------------------------------------------------------------------
1076 :
1077 140864 : void OutputDevice::ImplDrawWallpaper( long nX, long nY,
1078 : long nWidth, long nHeight,
1079 : const Wallpaper& rWallpaper )
1080 : {
1081 140864 : if( rWallpaper.IsBitmap() )
1082 0 : ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1083 140864 : else if( rWallpaper.IsGradient() )
1084 2873 : ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1085 : else
1086 137991 : ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
1087 140864 : }
1088 :
1089 : // -----------------------------------------------------------------------
1090 :
1091 24694 : void OutputDevice::DrawWallpaper( const Rectangle& rRect,
1092 : const Wallpaper& rWallpaper )
1093 : {
1094 24694 : if ( mpMetaFile )
1095 1492 : mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
1096 :
1097 24694 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1098 24701 : return;
1099 :
1100 24687 : if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
1101 : {
1102 23155 : Rectangle aRect = LogicToPixel( rRect );
1103 23155 : aRect.Justify();
1104 :
1105 23155 : if ( !aRect.IsEmpty() )
1106 : {
1107 46310 : ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1108 69465 : rWallpaper );
1109 : }
1110 : }
1111 :
1112 24687 : if( mpAlphaVDev )
1113 1492 : mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
1114 : }
1115 :
1116 : // -----------------------------------------------------------------------
1117 :
1118 117709 : void OutputDevice::Erase()
1119 : {
1120 117709 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1121 117709 : return;
1122 :
1123 117709 : sal_Bool bNativeOK = sal_False;
1124 :
1125 117709 : if( meOutDevType == OUTDEV_WINDOW )
1126 : {
1127 28593 : Window* pWindow = static_cast<Window*>(this);
1128 28593 : ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground;
1129 28593 : if( aCtrlPart != 0 && ! pWindow->IsControlBackground() )
1130 : {
1131 0 : ImplControlValue aControlValue;
1132 0 : Point aGcc3WorkaroundTemporary;
1133 0 : Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() );
1134 0 : ControlState nState = 0;
1135 :
1136 0 : if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED;
1137 : bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
1138 0 : nState, aControlValue, OUString() );
1139 : }
1140 : }
1141 :
1142 117709 : if ( mbBackground && ! bNativeOK )
1143 : {
1144 117709 : RasterOp eRasterOp = GetRasterOp();
1145 117709 : if ( eRasterOp != ROP_OVERPAINT )
1146 0 : SetRasterOp( ROP_OVERPAINT );
1147 117709 : ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
1148 117709 : if ( eRasterOp != ROP_OVERPAINT )
1149 0 : SetRasterOp( eRasterOp );
1150 : }
1151 :
1152 117709 : if( mpAlphaVDev )
1153 0 : mpAlphaVDev->Erase();
1154 : }
1155 :
1156 : // -----------------------------------------------------------------------
1157 :
1158 0 : bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
1159 : const GfxLink& rGfxLink, GDIMetaFile* pSubst )
1160 : {
1161 0 : bool bDrawn(true);
1162 :
1163 0 : if ( mpMetaFile )
1164 : {
1165 0 : GDIMetaFile aSubst;
1166 :
1167 0 : if( pSubst )
1168 0 : aSubst = *pSubst;
1169 :
1170 0 : mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
1171 : }
1172 :
1173 0 : if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1174 0 : return bDrawn;
1175 :
1176 0 : if( mbOutputClipped )
1177 0 : return bDrawn;
1178 :
1179 0 : Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
1180 :
1181 0 : if( !aRect.IsEmpty() )
1182 : {
1183 : // draw the real EPS graphics
1184 0 : if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
1185 : {
1186 0 : if( !mpGraphics && !ImplGetGraphics() )
1187 0 : return bDrawn;
1188 :
1189 0 : if( mbInitClipRegion )
1190 0 : ImplInitClipRegion();
1191 :
1192 0 : aRect.Justify();
1193 0 : bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
1194 0 : (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this );
1195 : }
1196 :
1197 : // else draw the substitution graphics
1198 0 : if( !bDrawn && pSubst )
1199 : {
1200 0 : GDIMetaFile* pOldMetaFile = mpMetaFile;
1201 :
1202 0 : mpMetaFile = NULL;
1203 0 : Graphic( *pSubst ).Draw( this, rPoint, rSize );
1204 0 : mpMetaFile = pOldMetaFile;
1205 : }
1206 : }
1207 :
1208 0 : if( mpAlphaVDev )
1209 0 : mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
1210 :
1211 0 : return bDrawn;
1212 : }
1213 :
1214 : // -----------------------------------------------------------------------
1215 :
1216 0 : void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd)
1217 : {
1218 0 : const sal_uInt32 nMaxX(rPos.X() + rSize.Width());
1219 0 : const sal_uInt32 nMaxY(rPos.Y() + rSize.Height());
1220 :
1221 0 : Push(PUSH_LINECOLOR|PUSH_FILLCOLOR);
1222 0 : SetLineColor();
1223 :
1224 0 : for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen)
1225 : {
1226 0 : const sal_uInt32 nRight(std::min(nMaxX, nX + nLen));
1227 :
1228 0 : for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen)
1229 : {
1230 0 : const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen));
1231 :
1232 0 : SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd);
1233 0 : DrawRect(Rectangle(nX, nY, nRight, nBottom));
1234 : }
1235 : }
1236 :
1237 0 : Pop();
1238 465 : }
1239 :
1240 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|