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