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