1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: outdev2.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
37 #include <vcl/salbmp.hxx>
38 #include <vcl/salgdi.hxx>
39 #include <vcl/impbmp.hxx>
40 #include <tools/debug.hxx>
41 #include <vcl/bitmap.hxx>
42 #include <vcl/bitmapex.hxx>
43 #include <vcl/window.hxx>
44 #include <vcl/metaact.hxx>
45 #include <vcl/gdimtf.hxx>
46 #include <vcl/virdev.hxx>
47 #include <vcl/outdata.hxx>
48 #include <vcl/outdev.h>
49 #include <vcl/bmpacc.hxx>
50 #include <vcl/region.h>
51 #include <vcl/outdev.hxx>
52 #include <vcl/window.hxx>
53 #include <vcl/window.h>
54 #include <vcl/sallayout.hxx>
55 #include <vcl/image.h>
56 #include <vcl/image.hxx>
57 #include <vcl/bmpfast.hxx>
59 #define BAND_MAX_SIZE 512000
61 // =======================================================================
63 DBG_NAMEEX( OutputDevice
)
65 // =======================================================================
71 #define OUTDEV_INIT() \
73 if ( !IsDeviceOutputNecessary() ) \
77 if ( !ImplGetGraphics() ) \
80 if ( mbInitClipRegion ) \
81 ImplInitClipRegion(); \
83 if ( mbOutputClipped ) \
87 #define TwoRect SalTwoRect
93 extern ULONG nVCLRLut
[ 6 ];
94 extern ULONG nVCLGLut
[ 6 ];
95 extern ULONG nVCLBLut
[ 6 ];
96 extern ULONG nVCLDitherLut
[ 256 ];
97 extern ULONG nVCLLut
[ 256 ];
99 // =======================================================================
101 ULONG
ImplAdjustTwoRect( TwoRect
& rTwoRect
, const Size
& rSizePix
)
103 ULONG nMirrFlags
= 0;
105 if ( rTwoRect
.mnDestWidth
< 0 )
107 rTwoRect
.mnSrcX
= rSizePix
.Width() - rTwoRect
.mnSrcX
- rTwoRect
.mnSrcWidth
;
108 rTwoRect
.mnDestWidth
= -rTwoRect
.mnDestWidth
;
109 rTwoRect
.mnDestX
-= rTwoRect
.mnDestWidth
-1;
110 nMirrFlags
|= BMP_MIRROR_HORZ
;
113 if ( rTwoRect
.mnDestHeight
< 0 )
115 rTwoRect
.mnSrcY
= rSizePix
.Height() - rTwoRect
.mnSrcY
- rTwoRect
.mnSrcHeight
;
116 rTwoRect
.mnDestHeight
= -rTwoRect
.mnDestHeight
;
117 rTwoRect
.mnDestY
-= rTwoRect
.mnDestHeight
-1;
118 nMirrFlags
|= BMP_MIRROR_VERT
;
121 if( ( rTwoRect
.mnSrcX
< 0 ) || ( rTwoRect
.mnSrcX
>= rSizePix
.Width() ) ||
122 ( rTwoRect
.mnSrcY
< 0 ) || ( rTwoRect
.mnSrcY
>= rSizePix
.Height() ) ||
123 ( ( rTwoRect
.mnSrcX
+ rTwoRect
.mnSrcWidth
) > rSizePix
.Width() ) ||
124 ( ( rTwoRect
.mnSrcY
+ rTwoRect
.mnSrcHeight
) > rSizePix
.Height() ) )
126 const Rectangle
aSourceRect( Point( rTwoRect
.mnSrcX
, rTwoRect
.mnSrcY
),
127 Size( rTwoRect
.mnSrcWidth
, rTwoRect
.mnSrcHeight
) );
128 Rectangle
aCropRect( aSourceRect
);
130 aCropRect
.Intersection( Rectangle( Point(), rSizePix
) );
132 if( aCropRect
.IsEmpty() )
133 rTwoRect
.mnSrcWidth
= rTwoRect
.mnSrcHeight
= rTwoRect
.mnDestWidth
= rTwoRect
.mnDestHeight
= 0;
136 const double fFactorX
= ( rTwoRect
.mnSrcWidth
> 1 ) ? (double) ( rTwoRect
.mnDestWidth
- 1 ) / ( rTwoRect
.mnSrcWidth
- 1 ) : 0.0;
137 const double fFactorY
= ( rTwoRect
.mnSrcHeight
> 1 ) ? (double) ( rTwoRect
.mnDestHeight
- 1 ) / ( rTwoRect
.mnSrcHeight
- 1 ) : 0.0;
139 const long nDstX1
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Left() - rTwoRect
.mnSrcX
) );
140 const long nDstY1
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Top() - rTwoRect
.mnSrcY
) );
141 const long nDstX2
= rTwoRect
.mnDestX
+ FRound( fFactorX
* ( aCropRect
.Right() - rTwoRect
.mnSrcX
) );
142 const long nDstY2
= rTwoRect
.mnDestY
+ FRound( fFactorY
* ( aCropRect
.Bottom() - rTwoRect
.mnSrcY
) );
144 rTwoRect
.mnSrcX
= aCropRect
.Left();
145 rTwoRect
.mnSrcY
= aCropRect
.Top();
146 rTwoRect
.mnSrcWidth
= aCropRect
.GetWidth();
147 rTwoRect
.mnSrcHeight
= aCropRect
.GetHeight();
148 rTwoRect
.mnDestX
= nDstX1
;
149 rTwoRect
.mnDestY
= nDstY1
;
150 rTwoRect
.mnDestWidth
= nDstX2
- nDstX1
+ 1;
151 rTwoRect
.mnDestHeight
= nDstY2
- nDstY1
+ 1;
158 // =======================================================================
160 void OutputDevice::ImplDrawOutDevDirect( const OutputDevice
* pSrcDev
, void* pVoidPosAry
)
162 TwoRect
* pPosAry
= (TwoRect
*)pVoidPosAry
;
163 SalGraphics
* pGraphics2
;
165 if ( pPosAry
->mnSrcWidth
&& pPosAry
->mnSrcHeight
&& pPosAry
->mnDestWidth
&& pPosAry
->mnDestHeight
)
167 if ( this == pSrcDev
)
171 if ( (GetOutDevType() != pSrcDev
->GetOutDevType()) ||
172 (GetOutDevType() != OUTDEV_WINDOW
) )
174 if ( !pSrcDev
->mpGraphics
)
176 if ( !((OutputDevice
*)pSrcDev
)->ImplGetGraphics() )
179 pGraphics2
= pSrcDev
->mpGraphics
;
183 if ( ((Window
*)this)->mpWindowImpl
->mpFrameWindow
== ((Window
*)pSrcDev
)->mpWindowImpl
->mpFrameWindow
)
187 if ( !pSrcDev
->mpGraphics
)
189 if ( !((OutputDevice
*)pSrcDev
)->ImplGetGraphics() )
192 pGraphics2
= pSrcDev
->mpGraphics
;
196 if ( !ImplGetGraphics() )
199 DBG_ASSERT( mpGraphics
&& pSrcDev
->mpGraphics
,
200 "OutputDevice::DrawOutDev(): We need more than one Graphics" );
205 // #102532# Offset only has to be pseudo window offset
206 Rectangle
aSrcOutRect( Point( pSrcDev
->mnOutOffX
, pSrcDev
->mnOutOffY
),
207 Size( pSrcDev
->mnOutWidth
, pSrcDev
->mnOutHeight
) );
208 Rectangle
aSrcRect( Point( pPosAry
->mnSrcX
, pPosAry
->mnSrcY
),
209 Size( pPosAry
->mnSrcWidth
, pPosAry
->mnSrcHeight
) );
210 const long nOldRight
= aSrcRect
.Right();
211 const long nOldBottom
= aSrcRect
.Bottom();
213 if ( !aSrcRect
.Intersection( aSrcOutRect
).IsEmpty() )
215 if ( (pPosAry
->mnSrcX
+pPosAry
->mnSrcWidth
-1) > aSrcOutRect
.Right() )
217 const long nOldWidth
= pPosAry
->mnSrcWidth
;
218 pPosAry
->mnSrcWidth
-= (nOldRight
- aSrcRect
.Right());
219 pPosAry
->mnDestWidth
= pPosAry
->mnDestWidth
* pPosAry
->mnSrcWidth
/ nOldWidth
;
222 if ( (pPosAry
->mnSrcY
+pPosAry
->mnSrcHeight
-1) > aSrcOutRect
.Bottom() )
224 const long nOldHeight
= pPosAry
->mnSrcHeight
;
225 pPosAry
->mnSrcHeight
-= (nOldBottom
- aSrcRect
.Bottom());
226 pPosAry
->mnDestHeight
= pPosAry
->mnDestHeight
* pPosAry
->mnSrcHeight
/ nOldHeight
;
229 // --- RTL --- if this is no window, but pSrcDev is a window
230 // mirroring may be required
231 // because only windows have a SalGraphicsLayout
232 // mirroring is performed here
233 if( (GetOutDevType() != OUTDEV_WINDOW
) && pGraphics2
&& (pGraphics2
->GetLayout() & SAL_LAYOUT_BIDI_RTL
) )
235 SalTwoRect pPosAry2
= *pPosAry
;
236 pGraphics2
->mirror( pPosAry2
.mnSrcX
, pPosAry2
.mnSrcWidth
, pSrcDev
);
237 mpGraphics
->CopyBits( &pPosAry2
, pGraphics2
, this, pSrcDev
);
240 mpGraphics
->CopyBits( pPosAry
, pGraphics2
, this, pSrcDev
);
245 // ------------------------------------------------------------------
247 void OutputDevice::DrawOutDev( const Point
& rDestPt
, const Size
& rDestSize
,
248 const Point
& rSrcPt
, const Size
& rSrcSize
)
250 DBG_TRACE( "OutputDevice::DrawOutDev()" );
251 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
252 DBG_ASSERT( meOutDevType
!= OUTDEV_PRINTER
, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
254 if( ImplIsRecordLayout() )
257 if ( meOutDevType
== OUTDEV_PRINTER
)
260 if ( ROP_INVERT
== meRasterOp
)
262 DrawRect( Rectangle( rDestPt
, rDestSize
) );
268 const Bitmap
aBmp( GetBitmap( rSrcPt
, rSrcSize
) );
269 mpMetaFile
->AddAction( new MetaBmpScaleAction( rDestPt
, rDestSize
, aBmp
) );
275 aPosAry
.mnSrcWidth
= ImplLogicWidthToDevicePixel( rSrcSize
.Width() );
276 aPosAry
.mnSrcHeight
= ImplLogicHeightToDevicePixel( rSrcSize
.Height() );
277 aPosAry
.mnDestWidth
= ImplLogicWidthToDevicePixel( rDestSize
.Width() );
278 aPosAry
.mnDestHeight
= ImplLogicHeightToDevicePixel( rDestSize
.Height() );
280 if ( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
&& aPosAry
.mnDestWidth
&& aPosAry
.mnDestHeight
)
282 aPosAry
.mnSrcX
= ImplLogicXToDevicePixel( rSrcPt
.X() );
283 aPosAry
.mnSrcY
= ImplLogicYToDevicePixel( rSrcPt
.Y() );
284 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
285 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
287 Rectangle
aSrcOutRect( Point( mnOutOffX
, mnOutOffY
),
288 Size( mnOutWidth
, mnOutHeight
) );
289 Rectangle
aSrcRect( Point( aPosAry
.mnSrcX
, aPosAry
.mnSrcY
),
290 Size( aPosAry
.mnSrcWidth
, aPosAry
.mnSrcHeight
) );
291 long nOldRight
= aSrcRect
.Right();
292 long nOldBottom
= aSrcRect
.Bottom();
294 if ( !aSrcRect
.Intersection( aSrcOutRect
).IsEmpty() )
296 if ( (aPosAry
.mnSrcX
+aPosAry
.mnSrcWidth
-1) > aSrcOutRect
.Right() )
298 long nOldWidth
= aPosAry
.mnSrcWidth
;
299 aPosAry
.mnSrcWidth
-= nOldRight
-aSrcRect
.Right();
300 aPosAry
.mnDestWidth
= aPosAry
.mnDestWidth
*aPosAry
.mnSrcWidth
/nOldWidth
;
303 if ( (aPosAry
.mnSrcY
+aPosAry
.mnSrcHeight
-1) > aSrcOutRect
.Bottom() )
305 long nOldHeight
= aPosAry
.mnSrcHeight
;
306 aPosAry
.mnSrcHeight
-= nOldBottom
-aSrcRect
.Bottom();
307 aPosAry
.mnDestHeight
= aPosAry
.mnDestHeight
*aPosAry
.mnSrcHeight
/nOldHeight
;
310 mpGraphics
->CopyBits( &aPosAry
, NULL
, this, NULL
);
315 mpAlphaVDev
->DrawOutDev( rDestPt
, rDestSize
, rSrcPt
, rSrcSize
);
318 // ------------------------------------------------------------------
320 void OutputDevice::DrawOutDev( const Point
& rDestPt
, const Size
& rDestSize
,
321 const Point
& rSrcPt
, const Size
& rSrcSize
,
322 const OutputDevice
& rOutDev
)
324 DBG_TRACE( "OutputDevice::DrawOutDev()" );
325 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
326 DBG_CHKOBJ( &rOutDev
, OutputDevice
, ImplDbgCheckOutputDevice
);
327 DBG_ASSERT( meOutDevType
!= OUTDEV_PRINTER
, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
328 DBG_ASSERT( rOutDev
.meOutDevType
!= OUTDEV_PRINTER
, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
330 if ( (meOutDevType
== OUTDEV_PRINTER
) || (rOutDev
.meOutDevType
== OUTDEV_PRINTER
) || ImplIsRecordLayout() )
333 if ( ROP_INVERT
== meRasterOp
)
335 DrawRect( Rectangle( rDestPt
, rDestSize
) );
341 const Bitmap
aBmp( rOutDev
.GetBitmap( rSrcPt
, rSrcSize
) );
342 mpMetaFile
->AddAction( new MetaBmpScaleAction( rDestPt
, rDestSize
, aBmp
) );
348 aPosAry
.mnSrcX
= rOutDev
.ImplLogicXToDevicePixel( rSrcPt
.X() );
349 aPosAry
.mnSrcY
= rOutDev
.ImplLogicYToDevicePixel( rSrcPt
.Y() );
350 aPosAry
.mnSrcWidth
= rOutDev
.ImplLogicWidthToDevicePixel( rSrcSize
.Width() );
351 aPosAry
.mnSrcHeight
= rOutDev
.ImplLogicHeightToDevicePixel( rSrcSize
.Height() );
352 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
353 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
354 aPosAry
.mnDestWidth
= ImplLogicWidthToDevicePixel( rDestSize
.Width() );
355 aPosAry
.mnDestHeight
= ImplLogicHeightToDevicePixel( rDestSize
.Height() );
359 if( rOutDev
.mpAlphaVDev
)
361 // alpha-blend source over destination
362 DrawBitmapEx( rDestPt
, rDestSize
, rOutDev
.GetBitmapEx(rSrcPt
, rSrcSize
) );
364 // This would be mode SOURCE:
365 // copy source alpha channel to our alpha channel
366 //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev );
370 ImplDrawOutDevDirect( &rOutDev
, &aPosAry
);
372 // #i32109#: make destination rectangle opaque - source has no alpha
373 mpAlphaVDev
->ImplFillOpaqueRectangle( Rectangle(rDestPt
, rDestSize
) );
378 if( rOutDev
.mpAlphaVDev
)
380 // alpha-blend source over destination
381 DrawBitmapEx( rDestPt
, rDestSize
, rOutDev
.GetBitmapEx(rSrcPt
, rSrcSize
) );
385 // no alpha at all, neither in source nor destination device
386 ImplDrawOutDevDirect( &rOutDev
, &aPosAry
);
391 // ------------------------------------------------------------------
393 void OutputDevice::CopyArea( const Point
& rDestPt
,
394 const Point
& rSrcPt
, const Size
& rSrcSize
,
397 DBG_TRACE( "OutputDevice::CopyArea()" );
398 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
399 DBG_ASSERT( meOutDevType
!= OUTDEV_PRINTER
, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
401 if ( meOutDevType
== OUTDEV_PRINTER
|| ImplIsRecordLayout() )
404 RasterOp eOldRop
= GetRasterOp();
405 SetRasterOp( ROP_OVERPAINT
);
410 aPosAry
.mnSrcWidth
= ImplLogicWidthToDevicePixel( rSrcSize
.Width() );
411 aPosAry
.mnSrcHeight
= ImplLogicHeightToDevicePixel( rSrcSize
.Height() );
413 if ( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
)
415 aPosAry
.mnSrcX
= ImplLogicXToDevicePixel( rSrcPt
.X() );
416 aPosAry
.mnSrcY
= ImplLogicYToDevicePixel( rSrcPt
.Y() );
417 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
418 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
420 Rectangle
aSrcOutRect( Point( mnOutOffX
, mnOutOffY
),
421 Size( mnOutWidth
, mnOutHeight
) );
422 Rectangle
aSrcRect( Point( aPosAry
.mnSrcX
, aPosAry
.mnSrcY
),
423 Size( aPosAry
.mnSrcWidth
, aPosAry
.mnSrcHeight
) );
424 long nOldRight
= aSrcRect
.Right();
425 long nOldBottom
= aSrcRect
.Bottom();
427 if ( !aSrcRect
.Intersection( aSrcOutRect
).IsEmpty() )
429 if ( (aPosAry
.mnSrcX
+aPosAry
.mnSrcWidth
-1) > aSrcOutRect
.Right() )
430 aPosAry
.mnSrcWidth
-= nOldRight
-aSrcRect
.Right();
432 if ( (aPosAry
.mnSrcY
+aPosAry
.mnSrcHeight
-1) > aSrcOutRect
.Bottom() )
433 aPosAry
.mnSrcHeight
-= nOldBottom
-aSrcRect
.Bottom();
435 if ( (meOutDevType
== OUTDEV_WINDOW
) && (nFlags
& COPYAREA_WINDOWINVALIDATE
) )
437 ((Window
*)this)->ImplMoveAllInvalidateRegions( aSrcRect
,
438 aPosAry
.mnDestX
-aPosAry
.mnSrcX
,
439 aPosAry
.mnDestY
-aPosAry
.mnSrcY
,
442 mpGraphics
->CopyArea( aPosAry
.mnDestX
, aPosAry
.mnDestY
,
443 aPosAry
.mnSrcX
, aPosAry
.mnSrcY
,
444 aPosAry
.mnSrcWidth
, aPosAry
.mnSrcHeight
,
445 SAL_COPYAREA_WINDOWINVALIDATE
, this );
449 aPosAry
.mnDestWidth
= aPosAry
.mnSrcWidth
;
450 aPosAry
.mnDestHeight
= aPosAry
.mnSrcHeight
;
451 mpGraphics
->CopyBits( &aPosAry
, NULL
, this, NULL
);
456 SetRasterOp( eOldRop
);
459 mpAlphaVDev
->CopyArea( rDestPt
, rSrcPt
, rSrcSize
, nFlags
);
462 // ------------------------------------------------------------------
464 void OutputDevice::ImplDrawFrameDev( const Point
& rPt
, const Point
& rDevPt
, const Size
& rDevSize
,
465 const OutputDevice
& rOutDev
, const Region
& rRegion
)
467 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
469 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
470 BOOL bOldMap
= mbMap
;
471 RasterOp eOldROP
= GetRasterOp();
474 SetRasterOp( ROP_OVERPAINT
);
476 if ( !IsDeviceOutputNecessary() )
481 if ( !ImplGetGraphics() )
485 // ClipRegion zuruecksetzen
486 if ( rRegion
.IsNull() )
487 mpGraphics
->ResetClipRegion();
489 ImplSelectClipRegion( rRegion
);
492 aPosAry
.mnSrcX
= rDevPt
.X();
493 aPosAry
.mnSrcY
= rDevPt
.Y();
494 aPosAry
.mnSrcWidth
= rDevSize
.Width();
495 aPosAry
.mnSrcHeight
= rDevSize
.Height();
496 aPosAry
.mnDestX
= rPt
.X();
497 aPosAry
.mnDestY
= rPt
.Y();
498 aPosAry
.mnDestWidth
= rDevSize
.Width();
499 aPosAry
.mnDestHeight
= rDevSize
.Height();
500 ImplDrawOutDevDirect( &rOutDev
, &aPosAry
);
502 // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird
503 mbInitClipRegion
= TRUE
;
505 SetRasterOp( eOldROP
);
507 mpMetaFile
= pOldMetaFile
;
510 // ------------------------------------------------------------------
512 void OutputDevice::ImplGetFrameDev( const Point
& rPt
, const Point
& rDevPt
, const Size
& rDevSize
,
515 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
517 BOOL bOldMap
= mbMap
;
519 rDev
.DrawOutDev( rDevPt
, rDevSize
, rPt
, rDevSize
, *this );
523 // ------------------------------------------------------------------
525 void OutputDevice::DrawBitmap( const Point
& rDestPt
, const Bitmap
& rBitmap
)
527 DBG_TRACE( "OutputDevice::DrawBitmap()" );
529 if( ImplIsRecordLayout() )
532 const Size
aSizePix( rBitmap
.GetSizePixel() );
533 ImplDrawBitmap( rDestPt
, PixelToLogic( aSizePix
), Point(), aSizePix
, rBitmap
, META_BMP_ACTION
);
537 // #i32109#: Make bitmap area opaque
538 mpAlphaVDev
->ImplFillOpaqueRectangle( Rectangle(rDestPt
, PixelToLogic( aSizePix
)) );
542 // ------------------------------------------------------------------
544 void OutputDevice::DrawBitmap( const Point
& rDestPt
, const Size
& rDestSize
, const Bitmap
& rBitmap
)
546 DBG_TRACE( "OutputDevice::DrawBitmap( Size )" );
548 if( ImplIsRecordLayout() )
551 ImplDrawBitmap( rDestPt
, rDestSize
, Point(), rBitmap
.GetSizePixel(), rBitmap
, META_BMPSCALE_ACTION
);
555 // #i32109#: Make bitmap area opaque
556 mpAlphaVDev
->ImplFillOpaqueRectangle( Rectangle(rDestPt
, rDestSize
) );
560 // ------------------------------------------------------------------
562 void OutputDevice::DrawBitmap( const Point
& rDestPt
, const Size
& rDestSize
,
563 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
564 const Bitmap
& rBitmap
)
566 DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
568 if( ImplIsRecordLayout() )
571 ImplDrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, rBitmap
, META_BMPSCALEPART_ACTION
);
575 // #i32109#: Make bitmap area opaque
576 mpAlphaVDev
->ImplFillOpaqueRectangle( Rectangle(rDestPt
, rDestSize
) );
580 // -----------------------------------------------------------------------------
582 void OutputDevice::ImplDrawBitmap( const Point
& rDestPt
, const Size
& rDestSize
,
583 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
584 const Bitmap
& rBitmap
, const ULONG nAction
)
586 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
588 Bitmap
aBmp( rBitmap
);
590 if ( ( mnDrawMode
& DRAWMODE_NOBITMAP
) )
592 else if ( ROP_INVERT
== meRasterOp
)
594 DrawRect( Rectangle( rDestPt
, rDestSize
) );
597 else if ( mnDrawMode
& ( DRAWMODE_BLACKBITMAP
| DRAWMODE_WHITEBITMAP
|
598 DRAWMODE_GRAYBITMAP
| DRAWMODE_GHOSTEDBITMAP
) )
600 if ( mnDrawMode
& ( DRAWMODE_BLACKBITMAP
| DRAWMODE_WHITEBITMAP
) )
604 if ( mnDrawMode
& DRAWMODE_BLACKBITMAP
)
605 cCmpVal
= ( mnDrawMode
& DRAWMODE_GHOSTEDBITMAP
) ? 0x80 : 0;
609 Color
aCol( cCmpVal
, cCmpVal
, cCmpVal
);
610 Push( PUSH_LINECOLOR
| PUSH_FILLCOLOR
);
611 SetLineColor( aCol
);
612 SetFillColor( aCol
);
613 DrawRect( Rectangle( rDestPt
, rDestSize
) );
619 if ( mnDrawMode
& DRAWMODE_GRAYBITMAP
)
620 aBmp
.Convert( BMP_CONVERSION_8BIT_GREYS
);
622 if ( mnDrawMode
& DRAWMODE_GHOSTEDBITMAP
)
623 aBmp
.Convert( BMP_CONVERSION_GHOSTED
);
631 case( META_BMP_ACTION
):
632 mpMetaFile
->AddAction( new MetaBmpAction( rDestPt
, aBmp
) );
635 case( META_BMPSCALE_ACTION
):
636 mpMetaFile
->AddAction( new MetaBmpScaleAction( rDestPt
, rDestSize
, aBmp
) );
639 case( META_BMPSCALEPART_ACTION
):
640 mpMetaFile
->AddAction( new MetaBmpScalePartAction(
641 rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
) );
648 if( !aBmp
.IsEmpty() )
652 aPosAry
.mnSrcX
= rSrcPtPixel
.X();
653 aPosAry
.mnSrcY
= rSrcPtPixel
.Y();
654 aPosAry
.mnSrcWidth
= rSrcSizePixel
.Width();
655 aPosAry
.mnSrcHeight
= rSrcSizePixel
.Height();
656 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
657 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
658 aPosAry
.mnDestWidth
= ImplLogicWidthToDevicePixel( rDestSize
.Width() );
659 aPosAry
.mnDestHeight
= ImplLogicHeightToDevicePixel( rDestSize
.Height() );
661 const ULONG nMirrFlags
= ImplAdjustTwoRect( aPosAry
, aBmp
.GetSizePixel() );
663 if ( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
&& aPosAry
.mnDestWidth
&& aPosAry
.mnDestHeight
)
666 aBmp
.Mirror( nMirrFlags
);
668 /* #i75264# (corrected with #i81576#)
669 * sometimes a bitmap is scaled to a ridiculous size and drawn
670 * to a quite normal VDev, so only a very small part of
671 * the scaled bitmap will be visible. However actually scaling
672 * the bitmap will use so much memory that we end with a crash.
673 * Workaround: since only a small part of the scaled bitmap will
674 * be actually drawn anyway (because of clipping on the device
675 * boundary), limit the destination and source rectangles so
676 * that the destination rectangle will overlap the device but only
677 * be reasonably (say factor 2) larger than the device itself.
679 if( aPosAry
.mnDestWidth
> 2048 || aPosAry
.mnDestHeight
> 2048 )
681 if( meOutDevType
== OUTDEV_WINDOW
||
682 (meOutDevType
== OUTDEV_VIRDEV
&& mpPDFWriter
== 0 ) )
684 // #i81576# do the following trick only if there is overlap at all
685 // else the formulae don't work
686 // theoretically in this case we wouldn't need to draw the bitmap at all
687 // however there are some esoteric case where that is needed
688 if( aPosAry
.mnDestX
+ aPosAry
.mnDestWidth
>= 0
689 && aPosAry
.mnDestX
< mnOutWidth
690 && aPosAry
.mnDestY
+ aPosAry
.mnDestHeight
>= 0
691 && aPosAry
.mnDestY
< mnOutHeight
)
693 // reduce scaling to something reasonable taking into account the output size
694 if( aPosAry
.mnDestWidth
> 3*mnOutWidth
&& aPosAry
.mnSrcWidth
)
696 const double nScaleX
= aPosAry
.mnDestWidth
/double(aPosAry
.mnSrcWidth
);
698 if( aPosAry
.mnDestX
+ aPosAry
.mnDestWidth
> mnOutWidth
)
700 aPosAry
.mnDestWidth
= Max(long(0),mnOutWidth
-aPosAry
.mnDestX
);
702 if( aPosAry
.mnDestX
< 0 )
704 aPosAry
.mnDestWidth
+= aPosAry
.mnDestX
;
705 aPosAry
.mnSrcX
-= sal::static_int_cast
<long>(aPosAry
.mnDestX
/ nScaleX
);
709 aPosAry
.mnSrcWidth
= sal::static_int_cast
<long>(aPosAry
.mnDestWidth
/ nScaleX
);
712 if( aPosAry
.mnDestHeight
> 3*mnOutHeight
&& aPosAry
.mnSrcHeight
!= 0 )
714 const double nScaleY
= aPosAry
.mnDestHeight
/double(aPosAry
.mnSrcHeight
);
716 if( aPosAry
.mnDestY
+ aPosAry
.mnDestHeight
> mnOutHeight
)
718 aPosAry
.mnDestHeight
= Max(long(0),mnOutHeight
-aPosAry
.mnDestY
);
720 if( aPosAry
.mnDestY
< 0 )
722 aPosAry
.mnDestHeight
+= aPosAry
.mnDestY
;
723 aPosAry
.mnSrcY
-= sal::static_int_cast
<long>(aPosAry
.mnDestY
/ nScaleY
);
727 aPosAry
.mnSrcHeight
= sal::static_int_cast
<long>(aPosAry
.mnDestHeight
/ nScaleY
);
733 if ( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
&& aPosAry
.mnDestWidth
&& aPosAry
.mnDestHeight
)
734 mpGraphics
->DrawBitmap( &aPosAry
, *aBmp
.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
739 // ------------------------------------------------------------------
741 void OutputDevice::DrawBitmapEx( const Point
& rDestPt
,
742 const BitmapEx
& rBitmapEx
)
744 DBG_TRACE( "OutputDevice::DrawBitmapEx()" );
746 if( ImplIsRecordLayout() )
749 if( TRANSPARENT_NONE
== rBitmapEx
.GetTransparentType() )
750 DrawBitmap( rDestPt
, rBitmapEx
.GetBitmap() );
753 const Size
aSizePix( rBitmapEx
.GetSizePixel() );
754 ImplDrawBitmapEx( rDestPt
, PixelToLogic( aSizePix
), Point(), aSizePix
, rBitmapEx
, META_BMPEX_ACTION
);
758 // ------------------------------------------------------------------
760 void OutputDevice::DrawBitmapEx( const Point
& rDestPt
, const Size
& rDestSize
,
761 const BitmapEx
& rBitmapEx
)
763 DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
765 if( ImplIsRecordLayout() )
768 if ( TRANSPARENT_NONE
== rBitmapEx
.GetTransparentType() )
769 DrawBitmap( rDestPt
, rDestSize
, rBitmapEx
.GetBitmap() );
771 ImplDrawBitmapEx( rDestPt
, rDestSize
, Point(), rBitmapEx
.GetSizePixel(), rBitmapEx
, META_BMPEXSCALE_ACTION
);
774 // ------------------------------------------------------------------
776 void OutputDevice::DrawBitmapEx( const Point
& rDestPt
, const Size
& rDestSize
,
777 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
778 const BitmapEx
& rBitmapEx
)
780 DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
782 if( ImplIsRecordLayout() )
785 if( TRANSPARENT_NONE
== rBitmapEx
.GetTransparentType() )
786 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, rBitmapEx
.GetBitmap() );
788 ImplDrawBitmapEx( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, rBitmapEx
, META_BMPEXSCALEPART_ACTION
);
791 // ------------------------------------------------------------------
793 void OutputDevice::ImplDrawBitmapEx( const Point
& rDestPt
, const Size
& rDestSize
,
794 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
795 const BitmapEx
& rBitmapEx
, const ULONG nAction
)
797 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
799 BitmapEx
aBmpEx( rBitmapEx
);
801 if ( mnDrawMode
& DRAWMODE_NOBITMAP
)
803 else if ( ROP_INVERT
== meRasterOp
)
805 DrawRect( Rectangle( rDestPt
, rDestSize
) );
808 else if ( mnDrawMode
& ( DRAWMODE_BLACKBITMAP
| DRAWMODE_WHITEBITMAP
|
809 DRAWMODE_GRAYBITMAP
| DRAWMODE_GHOSTEDBITMAP
) )
811 if ( mnDrawMode
& ( DRAWMODE_BLACKBITMAP
| DRAWMODE_WHITEBITMAP
) )
813 Bitmap
aColorBmp( aBmpEx
.GetSizePixel(), ( mnDrawMode
& DRAWMODE_GHOSTEDBITMAP
) ? 4 : 1 );
816 if ( mnDrawMode
& DRAWMODE_BLACKBITMAP
)
817 cCmpVal
= ( mnDrawMode
& DRAWMODE_GHOSTEDBITMAP
) ? 0x80 : 0;
821 aColorBmp
.Erase( Color( cCmpVal
, cCmpVal
, cCmpVal
) );
823 if( aBmpEx
.IsAlpha() )
825 // Create one-bit mask out of alpha channel, by
826 // thresholding it at alpha=0.5. As
827 // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
828 // output, having alpha-induced grey levels is not
830 Bitmap
aMask( aBmpEx
.GetAlpha().GetBitmap() );
831 aMask
.MakeMono( 128 );
832 aBmpEx
= BitmapEx( aColorBmp
, aMask
);
836 aBmpEx
= BitmapEx( aColorBmp
, aBmpEx
.GetMask() );
841 if ( mnDrawMode
& DRAWMODE_GRAYBITMAP
)
842 aBmpEx
.Convert( BMP_CONVERSION_8BIT_GREYS
);
844 if ( mnDrawMode
& DRAWMODE_GHOSTEDBITMAP
)
845 aBmpEx
.Convert( BMP_CONVERSION_GHOSTED
);
853 case( META_BMPEX_ACTION
):
854 mpMetaFile
->AddAction( new MetaBmpExAction( rDestPt
, aBmpEx
) );
857 case( META_BMPEXSCALE_ACTION
):
858 mpMetaFile
->AddAction( new MetaBmpExScaleAction( rDestPt
, rDestSize
, aBmpEx
) );
861 case( META_BMPEXSCALEPART_ACTION
):
862 mpMetaFile
->AddAction( new MetaBmpExScalePartAction( rDestPt
, rDestSize
,
863 rSrcPtPixel
, rSrcSizePixel
, aBmpEx
) );
870 if( OUTDEV_PRINTER
== meOutDevType
)
872 if( aBmpEx
.IsAlpha() )
874 // #107169# For true alpha bitmaps, no longer masking the
875 // bitmap, but perform a full alpha blend against a white
877 Bitmap
aBmp( aBmpEx
.GetBitmap() );
878 aBmp
.Blend( aBmpEx
.GetAlpha(), Color( COL_WHITE
) );
879 DrawBitmap( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, aBmp
);
883 Bitmap
aBmp( aBmpEx
.GetBitmap() ), aMask( aBmpEx
.GetMask() );
884 aBmp
.Replace( aMask
, Color( COL_WHITE
) );
885 ImplPrintTransparent( aBmp
, aMask
, rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
889 else if( aBmpEx
.IsAlpha() )
891 ImplDrawAlpha( aBmpEx
.GetBitmap(), aBmpEx
.GetAlpha(), rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
899 aPosAry
.mnSrcX
= rSrcPtPixel
.X();
900 aPosAry
.mnSrcY
= rSrcPtPixel
.Y();
901 aPosAry
.mnSrcWidth
= rSrcSizePixel
.Width();
902 aPosAry
.mnSrcHeight
= rSrcSizePixel
.Height();
903 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
904 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
905 aPosAry
.mnDestWidth
= ImplLogicWidthToDevicePixel( rDestSize
.Width() );
906 aPosAry
.mnDestHeight
= ImplLogicHeightToDevicePixel( rDestSize
.Height() );
908 const ULONG nMirrFlags
= ImplAdjustTwoRect( aPosAry
, aBmpEx
.GetSizePixel() );
910 if( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
&& aPosAry
.mnDestWidth
&& aPosAry
.mnDestHeight
)
914 aBmpEx
.Mirror( nMirrFlags
);
916 const ImpBitmap
* pImpBmp
= aBmpEx
.ImplGetBitmapImpBitmap();
917 const ImpBitmap
* pMaskBmp
= aBmpEx
.ImplGetMaskImpBitmap();
921 // #4919452# reduce operation area to bounds of
922 // cliprect. since masked transparency involves
923 // creation of a large vdev and copying the screen
924 // content into that (slooow read from framebuffer),
925 // that should considerably increase performance for
926 // large bitmaps and small clippings.
928 // Note that this optimisation is a workaround for a
929 // Writer peculiarity, namely, to decompose background
930 // graphics into myriads of disjunct, tiny
931 // rectangles. That otherwise kills us here, since for
932 // transparent output, SAL always prepares the whole
933 // bitmap, if aPosAry contains the whole bitmap (and
934 // it's _not_ to blame for that).
936 // Note the call to ImplPixelToDevicePixel(), since
937 // aPosAry already contains the mnOutOff-offsets, they
938 // also have to be applied to the region
939 Rectangle
aClipRegionBounds( ImplPixelToDevicePixel(maRegion
).GetBoundRect() );
941 // TODO: Also respect scaling (that's a bit tricky,
942 // since the source points have to move fractional
943 // amounts (which is not possible, thus has to be
944 // emulated by increases copy area)
945 // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
946 // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
948 // for now, only identity scales allowed
949 if( !aClipRegionBounds
.IsEmpty() &&
950 aPosAry
.mnDestWidth
== aPosAry
.mnSrcWidth
&&
951 aPosAry
.mnDestHeight
== aPosAry
.mnSrcHeight
)
953 // now intersect dest rect with clip region
954 aClipRegionBounds
.Intersection( Rectangle( aPosAry
.mnDestX
,
956 aPosAry
.mnDestX
+ aPosAry
.mnDestWidth
- 1,
957 aPosAry
.mnDestY
+ aPosAry
.mnDestHeight
- 1 ) );
959 // Note: I could theoretically optimize away the
960 // DrawBitmap below, if the region is empty
961 // here. Unfortunately, cannot rule out that
962 // somebody relies on the side effects.
963 if( !aClipRegionBounds
.IsEmpty() )
965 aPosAry
.mnSrcX
+= aClipRegionBounds
.Left() - aPosAry
.mnDestX
;
966 aPosAry
.mnSrcY
+= aClipRegionBounds
.Top() - aPosAry
.mnDestY
;
967 aPosAry
.mnSrcWidth
= aClipRegionBounds
.GetWidth();
968 aPosAry
.mnSrcHeight
= aClipRegionBounds
.GetHeight();
970 aPosAry
.mnDestX
= aClipRegionBounds
.Left();
971 aPosAry
.mnDestY
= aClipRegionBounds
.Top();
972 aPosAry
.mnDestWidth
= aClipRegionBounds
.GetWidth();
973 aPosAry
.mnDestHeight
= aClipRegionBounds
.GetHeight();
977 mpGraphics
->DrawBitmap( &aPosAry
, *pImpBmp
->ImplGetSalBitmap(),
978 *pMaskBmp
->ImplGetSalBitmap(),
981 // #110958# Paint mask to alpha channel. Luckily, the
982 // black and white representation of the mask maps to
985 // #i25167# Restrict mask painting to _opaque_ areas
986 // of the mask, otherwise we spoil areas where no
987 // bitmap content was ever visible. Interestingly
988 // enough, this can be achieved by taking the mask as
989 // the transparency mask of itself
991 mpAlphaVDev
->DrawBitmapEx( rDestPt
,
993 BitmapEx( aBmpEx
.GetMask(),
994 aBmpEx
.GetMask() ) );
998 mpGraphics
->DrawBitmap( &aPosAry
, *pImpBmp
->ImplGetSalBitmap(), this );
1002 // #i32109#: Make bitmap area opaque
1003 mpAlphaVDev
->ImplFillOpaqueRectangle( Rectangle(rDestPt
, rDestSize
) );
1010 // ------------------------------------------------------------------
1012 void OutputDevice::DrawMask( const Point
& rDestPt
,
1013 const Bitmap
& rBitmap
, const Color
& rMaskColor
)
1015 DBG_TRACE( "OutputDevice::DrawMask()" );
1017 if( ImplIsRecordLayout() )
1020 const Size
aSizePix( rBitmap
.GetSizePixel() );
1021 ImplDrawMask( rDestPt
, PixelToLogic( aSizePix
), Point(), aSizePix
, rBitmap
, rMaskColor
, META_MASK_ACTION
);
1025 const Bitmap
& rMask( rBitmap
.CreateMask( rMaskColor
) );
1027 // #i25167# Restrict mask painting to _opaque_ areas
1028 // of the mask, otherwise we spoil areas where no
1029 // bitmap content was ever visible. Interestingly
1030 // enough, this can be achieved by taking the mask as
1031 // the transparency mask of itself
1032 mpAlphaVDev
->DrawBitmapEx( rDestPt
,
1033 PixelToLogic( aSizePix
),
1034 BitmapEx( rMask
, rMask
) );
1038 // ------------------------------------------------------------------
1040 void OutputDevice::DrawMask( const Point
& rDestPt
, const Size
& rDestSize
,
1041 const Bitmap
& rBitmap
, const Color
& rMaskColor
)
1043 DBG_TRACE( "OutputDevice::DrawMask( Size )" );
1045 if( ImplIsRecordLayout() )
1048 ImplDrawMask( rDestPt
, rDestSize
, Point(), rBitmap
.GetSizePixel(), rBitmap
, rMaskColor
, META_MASKSCALE_ACTION
);
1050 // TODO: Use mask here
1053 const Bitmap
& rMask( rBitmap
.CreateMask( rMaskColor
) );
1055 // #i25167# Restrict mask painting to _opaque_ areas
1056 // of the mask, otherwise we spoil areas where no
1057 // bitmap content was ever visible. Interestingly
1058 // enough, this can be achieved by taking the mask as
1059 // the transparency mask of itself
1060 mpAlphaVDev
->DrawBitmapEx( rDestPt
,
1062 BitmapEx( rMask
, rMask
) );
1066 // ------------------------------------------------------------------
1068 void OutputDevice::DrawMask( const Point
& rDestPt
, const Size
& rDestSize
,
1069 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
1070 const Bitmap
& rBitmap
, const Color
& rMaskColor
)
1072 DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" );
1074 if( ImplIsRecordLayout() )
1077 ImplDrawMask( rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
, rBitmap
, rMaskColor
, META_MASKSCALEPART_ACTION
);
1079 // TODO: Use mask here
1082 const Bitmap
& rMask( rBitmap
.CreateMask( rMaskColor
) );
1084 // #i25167# Restrict mask painting to _opaque_ areas
1085 // of the mask, otherwise we spoil areas where no
1086 // bitmap content was ever visible. Interestingly
1087 // enough, this can be achieved by taking the mask as
1088 // the transparency mask of itself
1089 mpAlphaVDev
->DrawBitmapEx( rDestPt
,
1093 BitmapEx( rMask
, rMask
) );
1097 // ------------------------------------------------------------------
1099 void OutputDevice::ImplDrawMask( const Point
& rDestPt
, const Size
& rDestSize
,
1100 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
,
1101 const Bitmap
& rBitmap
, const Color
& rMaskColor
,
1102 const ULONG nAction
)
1104 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1106 if( ROP_INVERT
== meRasterOp
)
1108 DrawRect( Rectangle( rDestPt
, rDestSize
) );
1116 case( META_MASK_ACTION
):
1117 mpMetaFile
->AddAction( new MetaMaskAction( rDestPt
,
1118 rBitmap
, rMaskColor
) );
1121 case( META_MASKSCALE_ACTION
):
1122 mpMetaFile
->AddAction( new MetaMaskScaleAction( rDestPt
,
1123 rDestSize
, rBitmap
, rMaskColor
) );
1126 case( META_MASKSCALEPART_ACTION
):
1127 mpMetaFile
->AddAction( new MetaMaskScalePartAction( rDestPt
, rDestSize
,
1128 rSrcPtPixel
, rSrcSizePixel
, rBitmap
, rMaskColor
) );
1135 if ( OUTDEV_PRINTER
== meOutDevType
)
1137 ImplPrintMask( rBitmap
, rMaskColor
, rDestPt
, rDestSize
, rSrcPtPixel
, rSrcSizePixel
);
1141 const ImpBitmap
* pImpBmp
= rBitmap
.ImplGetImpBitmap();
1146 aPosAry
.mnSrcX
= rSrcPtPixel
.X();
1147 aPosAry
.mnSrcY
= rSrcPtPixel
.Y();
1148 aPosAry
.mnSrcWidth
= rSrcSizePixel
.Width();
1149 aPosAry
.mnSrcHeight
= rSrcSizePixel
.Height();
1150 aPosAry
.mnDestX
= ImplLogicXToDevicePixel( rDestPt
.X() );
1151 aPosAry
.mnDestY
= ImplLogicYToDevicePixel( rDestPt
.Y() );
1152 aPosAry
.mnDestWidth
= ImplLogicWidthToDevicePixel( rDestSize
.Width() );
1153 aPosAry
.mnDestHeight
= ImplLogicHeightToDevicePixel( rDestSize
.Height() );
1155 // spiegeln via Koordinaten wollen wir nicht
1156 const ULONG nMirrFlags
= ImplAdjustTwoRect( aPosAry
, pImpBmp
->ImplGetSize() );
1158 // check if output is necessary
1159 if( aPosAry
.mnSrcWidth
&& aPosAry
.mnSrcHeight
&& aPosAry
.mnDestWidth
&& aPosAry
.mnDestHeight
)
1164 Bitmap
aTmp( rBitmap
);
1165 aTmp
.Mirror( nMirrFlags
);
1166 mpGraphics
->DrawMask( &aPosAry
, *aTmp
.ImplGetImpBitmap()->ImplGetSalBitmap(),
1167 ImplColorToSal( rMaskColor
) , this);
1170 mpGraphics
->DrawMask( &aPosAry
, *pImpBmp
->ImplGetSalBitmap(),
1171 ImplColorToSal( rMaskColor
), this );
1177 // ------------------------------------------------------------------
1179 void OutputDevice::DrawImage( const Point
& rPos
, const Image
& rImage
, USHORT nStyle
)
1181 DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER
, "DrawImage(): Images can't be drawn on any mprinter" );
1183 if( !rImage
.mpImplData
|| ImplIsRecordLayout() )
1186 switch( rImage
.mpImplData
->meType
)
1188 case IMAGETYPE_BITMAP
:
1189 DrawBitmap( rPos
, *static_cast< Bitmap
* >( rImage
.mpImplData
->mpData
) );
1192 case IMAGETYPE_IMAGE
:
1194 ImplImageData
* pData
= static_cast< ImplImageData
* >( rImage
.mpImplData
->mpData
);
1196 if( !pData
->mpImageBitmap
)
1198 const Size
aSize( pData
->maBmpEx
.GetSizePixel() );
1200 pData
->mpImageBitmap
= new ImplImageBmp
;
1201 pData
->mpImageBitmap
->Create( pData
->maBmpEx
, aSize
.Width(), aSize
.Height(), 1 );
1204 pData
->mpImageBitmap
->Draw( 0, this, rPos
, nStyle
);
1213 // ------------------------------------------------------------------
1215 void OutputDevice::DrawImage( const Point
& rPos
, const Size
& rSize
,
1216 const Image
& rImage
, USHORT nStyle
)
1218 DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER
, "DrawImage(): Images can't be drawn on any mprinter" );
1220 if( rImage
.mpImplData
&& !ImplIsRecordLayout() )
1222 switch( rImage
.mpImplData
->meType
)
1224 case IMAGETYPE_BITMAP
:
1225 DrawBitmap( rPos
, rSize
, *static_cast< Bitmap
* >( rImage
.mpImplData
->mpData
) );
1228 case IMAGETYPE_IMAGE
:
1230 ImplImageData
* pData
= static_cast< ImplImageData
* >( rImage
.mpImplData
->mpData
);
1232 if ( !pData
->mpImageBitmap
)
1234 const Size
aSize( pData
->maBmpEx
.GetSizePixel() );
1236 pData
->mpImageBitmap
= new ImplImageBmp
;
1237 pData
->mpImageBitmap
->Create( pData
->maBmpEx
, aSize
.Width(), aSize
.Height(), 1 );
1240 pData
->mpImageBitmap
->Draw( 0, this, rPos
, nStyle
, &rSize
);
1250 // ------------------------------------------------------------------
1252 Bitmap
OutputDevice::GetBitmap( const Point
& rSrcPt
, const Size
& rSize
) const
1254 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1257 long nX
= ImplLogicXToDevicePixel( rSrcPt
.X() );
1258 long nY
= ImplLogicYToDevicePixel( rSrcPt
.Y() );
1259 long nWidth
= ImplLogicWidthToDevicePixel( rSize
.Width() );
1260 long nHeight
= ImplLogicHeightToDevicePixel( rSize
.Height() );
1262 if ( mpGraphics
|| ( (OutputDevice
*) this )->ImplGetGraphics() )
1264 if ( nWidth
&& nHeight
)
1266 Rectangle
aRect( Point( nX
, nY
), Size( nWidth
, nHeight
) );
1267 BOOL bClipped
= FALSE
;
1269 // X-Koordinate ausserhalb des Bereichs?
1270 if ( nX
< mnOutOffX
)
1272 nWidth
-= ( mnOutOffX
- nX
);
1277 // Y-Koordinate ausserhalb des Bereichs?
1278 if ( nY
< mnOutOffY
)
1280 nHeight
-= ( mnOutOffY
- nY
);
1285 // Breite ausserhalb des Bereichs?
1286 if ( (nWidth
+ nX
) > (mnOutWidth
+ mnOutOffX
) )
1288 nWidth
= mnOutOffX
+ mnOutWidth
- nX
;
1292 // Hoehe ausserhalb des Bereichs?
1293 if ( (nHeight
+ nY
) > (mnOutHeight
+ mnOutOffY
) )
1295 nHeight
= mnOutOffY
+ mnOutHeight
- nY
;
1301 // Falls auf den sichtbaren Bereich geclipped wurde,
1302 // muessen wir eine Bitmap in der rchtigen Groesse
1303 // erzeugen, in die die geclippte Bitmap an die angepasste
1304 // Position kopiert wird
1305 VirtualDevice
aVDev( *this );
1307 if ( aVDev
.SetOutputSizePixel( aRect
.GetSize() ) )
1309 if ( ((OutputDevice
*)&aVDev
)->mpGraphics
|| ((OutputDevice
*)&aVDev
)->ImplGetGraphics() )
1313 aPosAry
.mnSrcX
= nX
;
1314 aPosAry
.mnSrcY
= nY
;
1315 aPosAry
.mnSrcWidth
= nWidth
;
1316 aPosAry
.mnSrcHeight
= nHeight
;
1317 aPosAry
.mnDestX
= ( aRect
.Left() < mnOutOffX
) ? ( mnOutOffX
- aRect
.Left() ) : 0L;
1318 aPosAry
.mnDestY
= ( aRect
.Top() < mnOutOffY
) ? ( mnOutOffY
- aRect
.Top() ) : 0L;
1319 aPosAry
.mnDestWidth
= nWidth
;
1320 aPosAry
.mnDestHeight
= nHeight
;
1322 if ( (nWidth
> 0) && (nHeight
> 0) )
1323 (((OutputDevice
*)&aVDev
)->mpGraphics
)->CopyBits( &aPosAry
, mpGraphics
, this, this );
1325 aBmp
= aVDev
.GetBitmap( Point(), aVDev
.GetOutputSizePixel() );
1336 SalBitmap
* pSalBmp
= mpGraphics
->GetBitmap( nX
, nY
, nWidth
, nHeight
, this );
1340 ImpBitmap
* pImpBmp
= new ImpBitmap
;
1341 pImpBmp
->ImplSetSalBitmap( pSalBmp
);
1342 aBmp
.ImplSetImpBitmap( pImpBmp
);
1351 // ------------------------------------------------------------------
1353 BitmapEx
OutputDevice::GetBitmapEx( const Point
& rSrcPt
, const Size
& rSize
) const
1355 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1357 // #110958# Extract alpha value from VDev, if any
1360 Bitmap
aAlphaBitmap( mpAlphaVDev
->GetBitmap( rSrcPt
, rSize
) );
1362 // ensure 8 bit alpha
1363 if( aAlphaBitmap
.GetBitCount() > 8 )
1364 aAlphaBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
1366 return BitmapEx(GetBitmap( rSrcPt
, rSize
), AlphaMask( aAlphaBitmap
) );
1369 return GetBitmap( rSrcPt
, rSize
);
1372 // ------------------------------------------------------------------
1374 void OutputDevice::ImplGetFrameBitmap( const Point
& rDestPt
, const Size
& rSize
,
1375 Bitmap
& rBitmap
) const
1377 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1379 BOOL bOldMap
= mbMap
;
1380 ((OutputDevice
*)this)->mbMap
= FALSE
;
1381 rBitmap
= GetBitmap( rDestPt
, rSize
);
1382 ((OutputDevice
*)this)->mbMap
= bOldMap
;
1385 // ------------------------------------------------------------------
1387 Color
OutputDevice::GetPixel( const Point
& rPt
) const
1389 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1393 if ( mpGraphics
|| ((OutputDevice
*)this)->ImplGetGraphics() )
1395 if ( mbInitClipRegion
)
1396 ((OutputDevice
*)this)->ImplInitClipRegion();
1398 if ( !mbOutputClipped
)
1400 const long nX
= ImplLogicXToDevicePixel( rPt
.X() );
1401 const long nY
= ImplLogicYToDevicePixel( rPt
.Y() );
1402 const SalColor aSalCol
= mpGraphics
->GetPixel( nX
, nY
, this );
1403 aColor
.SetRed( SALCOLOR_RED( aSalCol
) );
1404 aColor
.SetGreen( SALCOLOR_GREEN( aSalCol
) );
1405 aColor
.SetBlue( SALCOLOR_BLUE( aSalCol
) );
1411 // ------------------------------------------------------------------
1413 Color
* OutputDevice::GetPixel( const Polygon
& rPts
) const
1415 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1417 Color
* pColors
= NULL
;
1418 const USHORT nSize
= rPts
.GetSize();
1422 if ( mpGraphics
|| ((OutputDevice
*)this)->ImplGetGraphics() )
1424 if ( mbInitClipRegion
)
1425 ((OutputDevice
*)this)->ImplInitClipRegion();
1427 if ( !mbOutputClipped
)
1429 pColors
= new Color
[ nSize
];
1431 for( USHORT i
= 0; i
< nSize
; i
++ )
1433 Color
& rCol
= pColors
[ i
];
1434 const Point
& rPt
= rPts
[ i
];
1435 const SalColor
aSalCol( mpGraphics
->GetPixel( ImplLogicXToDevicePixel( rPt
.X() ),
1436 ImplLogicYToDevicePixel( rPt
.Y() ) , this) );
1438 rCol
.SetRed( SALCOLOR_RED( aSalCol
) );
1439 rCol
.SetGreen( SALCOLOR_GREEN( aSalCol
) );
1440 rCol
.SetBlue( SALCOLOR_BLUE( aSalCol
) );
1449 // -----------------------------------------------------------------------
1451 void OutputDevice::DrawPixel( const Point
& rPt
)
1453 DBG_TRACE( "OutputDevice::DrawPixel()" );
1454 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1457 mpMetaFile
->AddAction( new MetaPointAction( rPt
) );
1459 if ( !IsDeviceOutputNecessary() || !mbLineColor
|| ImplIsRecordLayout() )
1462 Point aPt
= ImplLogicToDevicePixel( rPt
);
1464 // we need a graphics
1467 if ( !ImplGetGraphics() )
1471 if ( mbInitClipRegion
)
1472 ImplInitClipRegion();
1473 if ( mbOutputClipped
)
1476 if ( mbInitLineColor
)
1477 ImplInitLineColor();
1479 mpGraphics
->DrawPixel( aPt
.X(), aPt
.Y(), this );
1482 mpAlphaVDev
->DrawPixel( rPt
);
1485 // -----------------------------------------------------------------------
1487 void OutputDevice::DrawPixel( const Point
& rPt
, const Color
& rColor
)
1489 DBG_TRACE( "OutputDevice::DrawPixel()" );
1490 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1492 Color
aColor( rColor
);
1494 if( mnDrawMode
& ( DRAWMODE_BLACKLINE
| DRAWMODE_WHITELINE
|
1495 DRAWMODE_GRAYLINE
| DRAWMODE_GHOSTEDLINE
|
1496 DRAWMODE_SETTINGSLINE
) )
1498 if( !ImplIsColorTransparent( aColor
) )
1500 if( mnDrawMode
& DRAWMODE_BLACKLINE
)
1502 aColor
= Color( COL_BLACK
);
1504 else if( mnDrawMode
& DRAWMODE_WHITELINE
)
1506 aColor
= Color( COL_WHITE
);
1508 else if( mnDrawMode
& DRAWMODE_GRAYLINE
)
1510 const UINT8 cLum
= aColor
.GetLuminance();
1511 aColor
= Color( cLum
, cLum
, cLum
);
1513 else if( mnDrawMode
& DRAWMODE_SETTINGSLINE
)
1515 aColor
= GetSettings().GetStyleSettings().GetFontColor();
1518 if( mnDrawMode
& DRAWMODE_GHOSTEDLINE
)
1520 aColor
= Color( ( aColor
.GetRed() >> 1 ) | 0x80,
1521 ( aColor
.GetGreen() >> 1 ) | 0x80,
1522 ( aColor
.GetBlue() >> 1 ) | 0x80 );
1528 mpMetaFile
->AddAction( new MetaPixelAction( rPt
, aColor
) );
1530 if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor
) || ImplIsRecordLayout() )
1533 Point aPt
= ImplLogicToDevicePixel( rPt
);
1535 // we need a graphics
1538 if ( !ImplGetGraphics() )
1542 if ( mbInitClipRegion
)
1543 ImplInitClipRegion();
1544 if ( mbOutputClipped
)
1547 mpGraphics
->DrawPixel( aPt
.X(), aPt
.Y(), ImplColorToSal( aColor
), this );
1550 mpAlphaVDev
->DrawPixel( rPt
);
1553 // -----------------------------------------------------------------------
1555 void OutputDevice::DrawPixel( const Polygon
& rPts
, const Color
* pColors
)
1558 DrawPixel( rPts
, GetLineColor() );
1561 DBG_TRACE( "OutputDevice::DrawPixel()" );
1562 DBG_CHKTHIS( OutputDevice
, ImplDbgCheckOutputDevice
);
1563 DBG_ASSERT( pColors
, "OutputDevice::DrawPixel: No color array specified" );
1565 const USHORT nSize
= rPts
.GetSize();
1570 for ( USHORT i
= 0; i
< nSize
; i
++ )
1571 mpMetaFile
->AddAction( new MetaPixelAction( rPts
[ i
], pColors
[ i
] ) );
1573 if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1576 // we need a graphics
1577 if ( mpGraphics
|| ImplGetGraphics() )
1579 if ( mbInitClipRegion
)
1580 ImplInitClipRegion();
1582 if ( mbOutputClipped
)
1585 for ( USHORT i
= 0; i
< nSize
; i
++ )
1587 const Point
aPt( ImplLogicToDevicePixel( rPts
[ i
] ) );
1588 mpGraphics
->DrawPixel( aPt
.X(), aPt
.Y(), ImplColorToSal( pColors
[ i
] ), this );
1595 mpAlphaVDev
->DrawPixel( rPts
, pColors
);
1598 // -----------------------------------------------------------------------
1600 void OutputDevice::DrawPixel( const Polygon
& rPts
, const Color
& rColor
)
1602 if( rColor
!= COL_TRANSPARENT
&& ! ImplIsRecordLayout() )
1604 const USHORT nSize
= rPts
.GetSize();
1605 Color
* pColArray
= new Color
[ nSize
];
1607 for( USHORT i
= 0; i
< nSize
; i
++ )
1608 pColArray
[ i
] = rColor
;
1610 DrawPixel( rPts
, pColArray
);
1615 mpAlphaVDev
->DrawPixel( rPts
, rColor
);
1618 // ------------------------------------------------------------------------
1620 Bitmap
OutputDevice::ImplBlendWithAlpha( Bitmap aBmp
,
1621 BitmapReadAccess
* pP
,
1622 BitmapReadAccess
* pA
,
1623 const Rectangle
& aDstRect
,
1624 const sal_Int32 nOffY
,
1625 const sal_Int32 nDstHeight
,
1626 const sal_Int32 nOffX
,
1627 const sal_Int32 nDstWidth
,
1631 BitmapColor aDstCol
,aSrcCol
;
1632 BYTE nSrcAlpha
, nDstAlpha
;
1634 int nX
, nOutX
, nY
, nOutY
;
1636 OSL_ENSURE(mpAlphaVDev
,
1637 "ImplBlendWithAlpha(): call me only with valid alpha VDev!" );
1639 BOOL
bOldMapMode( mpAlphaVDev
->IsMapModeEnabled() );
1640 mpAlphaVDev
->EnableMapMode(FALSE
);
1642 Bitmap
aAlphaBitmap( mpAlphaVDev
->GetBitmap( aDstRect
.TopLeft(), aDstRect
.GetSize() ) );
1643 BitmapWriteAccess
* pAlphaW
= aAlphaBitmap
.AcquireWriteAccess();
1645 if( GetBitCount() <= 8 )
1647 Bitmap
aDither( aBmp
.GetSizePixel(), 8 );
1648 BitmapColor
aIndex( 0 );
1649 BitmapReadAccess
* pB
= aBmp
.AcquireReadAccess();
1650 BitmapWriteAccess
* pW
= aDither
.AcquireWriteAccess();
1652 if( pB
&& pP
&& pA
&& pW
&& pAlphaW
)
1654 for( nY
= 0, nOutY
= nOffY
; nY
< nDstHeight
; nY
++, nOutY
++ )
1656 const long nMapY
= pMapY
[ nY
];
1657 const long nModY
= ( nOutY
& 0x0FL
) << 4L;
1659 for( nX
= 0, nOutX
= nOffX
; nX
< nDstWidth
; nX
++, nOutX
++ )
1661 const long nMapX
= pMapX
[ nX
];
1662 const ULONG nD
= nVCLDitherLut
[ nModY
| ( nOutX
& 0x0FL
) ];
1664 aSrcCol
= pP
->GetColor( nMapY
, nMapX
);
1665 aDstCol
= pB
->GetColor( nY
, nX
);
1666 nSrcAlpha
= 255 - pA
->GetPixel( nMapY
, nMapX
).GetBlueOrIndex();
1667 nDstAlpha
= 255 - pAlphaW
->GetPixel( nY
, nX
).GetBlueOrIndex();
1669 if( nSrcAlpha
+ nDstAlpha
== 0 )
1671 // #i70653# zero alpha -> zero color values
1672 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ ( nVCLLut
[ 0 ] + nD
) >> 16UL ] +
1673 nVCLGLut
[ ( nVCLLut
[ 0 ] + nD
) >> 16UL ] +
1674 nVCLBLut
[ ( nVCLLut
[ 0 ] + nD
) >> 16UL ] ) );
1678 aDstCol
.SetRed( (BYTE
)(((int)(aSrcCol
.GetRed())*nSrcAlpha
+ (int)(aDstCol
.GetRed())*nDstAlpha
) /
1679 (nSrcAlpha
+nDstAlpha
)) );
1680 aDstCol
.SetGreen( (BYTE
)(((int)(aSrcCol
.GetGreen())*nSrcAlpha
+ (int)(aDstCol
.GetGreen())*nDstAlpha
) /
1681 (nSrcAlpha
+nDstAlpha
)) );
1682 aDstCol
.SetBlue( (BYTE
)(((int)(aSrcCol
.GetBlue())*nSrcAlpha
+ (int)(aDstCol
.GetBlue())*nDstAlpha
) /
1683 (nSrcAlpha
+nDstAlpha
)) );
1685 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ ( nVCLLut
[ aDstCol
.GetRed() ] + nD
) >> 16UL ] +
1686 nVCLGLut
[ ( nVCLLut
[ aDstCol
.GetGreen() ] + nD
) >> 16UL ] +
1687 nVCLBLut
[ ( nVCLLut
[ aDstCol
.GetBlue() ] + nD
) >> 16UL ] ) );
1689 pW
->SetPixel( nY
, nX
, aIndex
);
1691 // Have to perform the compositing 'algebra' in
1692 // the inverse alpha space (with 255 meaning
1693 // opaque), otherwise, transitivity is not
1695 nSrcAlpha
= 255-COLOR_CHANNEL_MERGE( 255, (BYTE
)nDstAlpha
, nSrcAlpha
);
1697 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ ( nVCLLut
[ nSrcAlpha
] + nD
) >> 16UL ] +
1698 nVCLGLut
[ ( nVCLLut
[ nSrcAlpha
] + nD
) >> 16UL ] +
1699 nVCLBLut
[ ( nVCLLut
[ nSrcAlpha
] + nD
) >> 16UL ] ) );
1700 pAlphaW
->SetPixel( nY
, nX
, aIndex
);
1705 aBmp
.ReleaseAccess( pB
);
1706 aDither
.ReleaseAccess( pW
);
1711 BitmapWriteAccess
* pB
= aBmp
.AcquireWriteAccess();
1712 if( pP
&& pA
&& pB
)
1714 for( nY
= 0; nY
< nDstHeight
; nY
++ )
1716 const long nMapY
= pMapY
[ nY
];
1718 for( nX
= 0; nX
< nDstWidth
; nX
++ )
1720 const long nMapX
= pMapX
[ nX
];
1722 aSrcCol
= pP
->GetColor( nMapY
, nMapX
);
1723 aDstCol
= pB
->GetColor( nY
, nX
);
1724 nSrcAlpha
= 255 - pA
->GetPixel( nMapY
, nMapX
).GetBlueOrIndex();
1725 nDstAlpha
= 255 - pAlphaW
->GetPixel( nY
, nX
).GetBlueOrIndex();
1727 if( nSrcAlpha
+ nDstAlpha
== 0 )
1729 // #i70653# zero alpha -> zero color values
1731 aDstCol
.SetGreen(0);
1736 aDstCol
.SetRed( (BYTE
)(((int)(aSrcCol
.GetRed())*nSrcAlpha
+ (int)(aDstCol
.GetRed())*nDstAlpha
) /
1737 (nSrcAlpha
+nDstAlpha
)) );
1738 aDstCol
.SetGreen( (BYTE
)(((int)(aSrcCol
.GetGreen())*nSrcAlpha
+ (int)(aDstCol
.GetGreen())*nDstAlpha
) /
1739 (nSrcAlpha
+nDstAlpha
)) );
1740 aDstCol
.SetBlue( (BYTE
)(((int)(aSrcCol
.GetBlue())*nSrcAlpha
+ (int)(aDstCol
.GetBlue())*nDstAlpha
) /
1741 (nSrcAlpha
+nDstAlpha
)) );
1744 pB
->SetPixel( nY
, nX
, aDstCol
);
1746 // Have to perform the compositing 'algebra' in
1747 // the inverse alpha space (with 255 meaning
1748 // opaque), otherwise, transitivity is not
1750 nSrcAlpha
= 255-COLOR_CHANNEL_MERGE( 255, (BYTE
)nDstAlpha
, nSrcAlpha
);
1752 pAlphaW
->SetPixel( nY
, nX
, Color(nSrcAlpha
, nSrcAlpha
, nSrcAlpha
) );
1757 aBmp
.ReleaseAccess( pB
);
1761 aAlphaBitmap
.ReleaseAccess( pAlphaW
);
1762 mpAlphaVDev
->DrawBitmap( aDstRect
.TopLeft(), aAlphaBitmap
);
1763 mpAlphaVDev
->EnableMapMode( bOldMapMode
);
1768 // ------------------------------------------------------------------------
1770 Bitmap
OutputDevice::ImplBlend( Bitmap aBmp
,
1771 BitmapReadAccess
* pP
,
1772 BitmapReadAccess
* pA
,
1773 const sal_Int32 nOffY
,
1774 const sal_Int32 nDstHeight
,
1775 const sal_Int32 nOffX
,
1776 const sal_Int32 nDstWidth
,
1777 const Rectangle
& aBmpRect
,
1784 BitmapColor aDstCol
;
1786 int nX
, nOutX
, nY
, nOutY
;
1788 if( GetBitCount() <= 8 )
1790 Bitmap
aDither( aBmp
.GetSizePixel(), 8 );
1791 BitmapColor
aIndex( 0 );
1792 BitmapReadAccess
* pB
= aBmp
.AcquireReadAccess();
1793 BitmapWriteAccess
* pW
= aDither
.AcquireWriteAccess();
1795 if( pB
&& pP
&& pA
&& pW
)
1797 for( nY
= 0, nOutY
= nOffY
; nY
< nDstHeight
; nY
++, nOutY
++ )
1799 const long nMapY
= pMapY
[ nY
];
1800 const long nModY
= ( nOutY
& 0x0FL
) << 4L;
1802 for( nX
= 0, nOutX
= nOffX
; nX
< nDstWidth
; nX
++, nOutX
++ )
1804 const long nMapX
= pMapX
[ nX
];
1805 const ULONG nD
= nVCLDitherLut
[ nModY
| ( nOutX
& 0x0FL
) ];
1807 aDstCol
= pB
->GetColor( nY
, nX
);
1808 aDstCol
.Merge( pP
->GetColor( nMapY
, nMapX
), (BYTE
) pA
->GetPixel( nMapY
, nMapX
) );
1809 aIndex
.SetIndex( (BYTE
) ( nVCLRLut
[ ( nVCLLut
[ aDstCol
.GetRed() ] + nD
) >> 16UL ] +
1810 nVCLGLut
[ ( nVCLLut
[ aDstCol
.GetGreen() ] + nD
) >> 16UL ] +
1811 nVCLBLut
[ ( nVCLLut
[ aDstCol
.GetBlue() ] + nD
) >> 16UL ] ) );
1812 pW
->SetPixel( nY
, nX
, aIndex
);
1817 aBmp
.ReleaseAccess( pB
);
1818 aDither
.ReleaseAccess( pW
);
1823 BitmapWriteAccess
* pB
= aBmp
.AcquireWriteAccess();
1825 bool bFastBlend
= false;
1826 if( pP
&& pA
&& pB
)
1829 aTR
.mnSrcX
= aBmpRect
.Left();
1830 aTR
.mnSrcY
= aBmpRect
.Top();
1831 aTR
.mnSrcWidth
= aBmpRect
.GetWidth();
1832 aTR
.mnSrcHeight
= aBmpRect
.GetHeight();
1833 aTR
.mnDestX
= nOffX
;
1834 aTR
.mnDestY
= nOffY
;
1835 aTR
.mnDestWidth
= aOutSz
.Width();
1836 aTR
.mnDestHeight
= aOutSz
.Height();
1838 if( !bHMirr
|| !bVMirr
)
1839 bFastBlend
= ImplFastBitmapBlending( *pB
,*pP
,*pA
, aTR
);
1842 if( pP
&& pA
&& pB
&& !bFastBlend
)
1844 switch( pP
->GetScanlineFormat() )
1846 case( BMP_FORMAT_8BIT_PAL
):
1848 for( nY
= 0; nY
< nDstHeight
; nY
++ )
1850 const long nMapY
= pMapY
[ nY
];
1851 Scanline pPScan
= pP
->GetScanline( nMapY
);
1852 Scanline pAScan
= pA
->GetScanline( nMapY
);
1854 for( nX
= 0; nX
< nDstWidth
; nX
++ )
1856 const long nMapX
= pMapX
[ nX
];
1857 aDstCol
= pB
->GetPixel( nY
, nX
);
1858 pB
->SetPixel( nY
, nX
, aDstCol
.Merge( pP
->GetPaletteColor( pPScan
[ nMapX
] ),
1859 pAScan
[ nMapX
] ) );
1865 case( BMP_FORMAT_24BIT_TC_BGR
):
1867 for( nY
= 0; nY
< nDstHeight
; nY
++ )
1869 const long nMapY
= pMapY
[ nY
];
1870 Scanline pPScan
= pP
->GetScanline( nMapY
);
1871 Scanline pAScan
= pA
->GetScanline( nMapY
);
1873 for( nX
= 0; nX
< nDstWidth
; nX
++ )
1875 const long nMapX
= pMapX
[ nX
];
1876 Scanline pTmp
= pPScan
+ nMapX
* 3;
1878 aDstCol
= pB
->GetPixel( nY
, nX
);
1879 pB
->SetPixel( nY
, nX
, aDstCol
.Merge( pTmp
[ 2 ], pTmp
[ 1 ], pTmp
[ 0 ],
1880 pAScan
[ nMapX
] ) );
1886 case( BMP_FORMAT_24BIT_TC_RGB
):
1888 for( nY
= 0; nY
< nDstHeight
; nY
++ )
1890 const long nMapY
= pMapY
[ nY
];
1891 Scanline pPScan
= pP
->GetScanline( nMapY
);
1892 Scanline pAScan
= pA
->GetScanline( nMapY
);
1894 for( nX
= 0; nX
< nDstWidth
; nX
++ )
1896 const long nMapX
= pMapX
[ nX
];
1897 Scanline pTmp
= pPScan
+ nMapX
* 3;
1899 aDstCol
= pB
->GetPixel( nY
, nX
);
1900 pB
->SetPixel( nY
, nX
, aDstCol
.Merge( pTmp
[ 0 ], pTmp
[ 1 ], pTmp
[ 2 ],
1901 pAScan
[ nMapX
] ) );
1909 for( nY
= 0; nY
< nDstHeight
; nY
++ )
1911 const long nMapY
= pMapY
[ nY
];
1912 Scanline pAScan
= pA
->GetScanline( nMapY
);
1914 for( nX
= 0; nX
< nDstWidth
; nX
++ )
1916 const long nMapX
= pMapX
[ nX
];
1917 aDstCol
= pB
->GetPixel( nY
, nX
);
1918 pB
->SetPixel( nY
, nX
, aDstCol
.Merge( pP
->GetColor( nMapY
, nMapX
),
1919 pAScan
[ nMapX
] ) );
1927 aBmp
.ReleaseAccess( pB
);
1934 // ------------------------------------------------------------------------
1936 void OutputDevice::ImplDrawAlpha( const Bitmap
& rBmp
, const AlphaMask
& rAlpha
,
1937 const Point
& rDestPt
, const Size
& rDestSize
,
1938 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
1940 const Point aNullPt
;
1941 Point
aOutPt( LogicToPixel( rDestPt
) );
1942 Size
aOutSz( LogicToPixel( rDestSize
) );
1943 Rectangle
aDstRect( aNullPt
, GetOutputSizePixel() );
1944 const BOOL bHMirr
= aOutSz
.Width() < 0, bVMirr
= aOutSz
.Height() < 0;
1946 if( OUTDEV_WINDOW
== meOutDevType
)
1948 const Region
aPaintRgn( ( (Window
*) this )->GetPaintRegion() );
1950 if( !aPaintRgn
.IsNull() )
1951 aDstRect
.Intersection( LogicToPixel( aPaintRgn
.GetBoundRect() ) );
1956 aOutSz
.Width() = -aOutSz
.Width();
1957 aOutPt
.X() -= ( aOutSz
.Width() - 1L );
1962 aOutSz
.Height() = -aOutSz
.Height();
1963 aOutPt
.Y() -= ( aOutSz
.Height() - 1L );
1966 if( !aDstRect
.Intersection( Rectangle( aOutPt
, aOutSz
) ).IsEmpty() )
1968 bool bNativeAlpha
= false;
1969 static const char* pDisableNative
= getenv( "SAL_DISABLE_NATIVE_ALPHA");
1970 // #i83087# Naturally, system alpha blending cannot work with
1971 // separate alpha VDev
1972 if( !mpAlphaVDev
&& !pDisableNative
&& !bHMirr
&& !bVMirr
)
1974 Point aRelPt
= aOutPt
+ Point( mnOutOffX
, mnOutOffY
);
1976 rSrcPtPixel
.X(), rSrcPtPixel
.Y(),
1977 rSrcSizePixel
.Width(), rSrcSizePixel
.Height(),
1978 aRelPt
.X(), aRelPt
.Y(),
1979 aOutSz
.Width(), aOutSz
.Height()
1981 SalBitmap
* pSalSrcBmp
= rBmp
.ImplGetImpBitmap()->ImplGetSalBitmap();
1982 SalBitmap
* pSalAlphaBmp
= rAlpha
.ImplGetImpBitmap()->ImplGetSalBitmap();
1983 bNativeAlpha
= mpGraphics
->DrawAlphaBitmap( aTR
, *pSalSrcBmp
, *pSalAlphaBmp
, this );
1986 VirtualDevice
* pOldVDev
= mpAlphaVDev
;
1988 Rectangle
aBmpRect( aNullPt
, rBmp
.GetSizePixel() );
1990 && !aBmpRect
.Intersection( Rectangle( rSrcPtPixel
, rSrcSizePixel
) ).IsEmpty() )
1992 GDIMetaFile
* pOldMetaFile
= mpMetaFile
; mpMetaFile
= NULL
;
1993 const BOOL bOldMap
= mbMap
; mbMap
= FALSE
;
1994 Bitmap
aBmp( GetBitmap( aDstRect
.TopLeft(), aDstRect
.GetSize() ) );
1996 // #109044# The generated bitmap need not necessarily be
1997 // of aDstRect dimensions, it's internally clipped to
1998 // window bounds. Thus, we correct the dest size here,
1999 // since we later use it (in nDstWidth/Height) for pixel
2001 // #i38887# reading from screen may sometimes fail
2002 if( aBmp
.ImplGetImpBitmap() )
2003 aDstRect
.SetSize( aBmp
.GetSizePixel() );
2005 BitmapColor aDstCol
;
2006 const long nSrcWidth
= aBmpRect
.GetWidth(), nSrcHeight
= aBmpRect
.GetHeight();
2007 const long nDstWidth
= aDstRect
.GetWidth(), nDstHeight
= aDstRect
.GetHeight();
2008 const long nOutWidth
= aOutSz
.Width(), nOutHeight
= aOutSz
.Height();
2009 const long nOffX
= aDstRect
.Left() - aOutPt
.X(), nOffY
= aDstRect
.Top() - aOutPt
.Y();
2010 long nX
, nOutX
, nY
, nOutY
;
2013 long* pMapX
= new long[ nDstWidth
];
2014 long* pMapY
= new long[ nDstHeight
];
2016 // create horizontal mapping table
2018 nMirrOffX
= ( aBmpRect
.Left() << 1 ) + nSrcWidth
- 1;
2020 for( nX
= 0L, nOutX
= nOffX
; nX
< nDstWidth
; nX
++, nOutX
++ )
2022 pMapX
[ nX
] = aBmpRect
.Left() + nOutX
* nSrcWidth
/ nOutWidth
;
2025 pMapX
[ nX
] = nMirrOffX
- pMapX
[ nX
];
2028 // create vertical mapping table
2030 nMirrOffY
= ( aBmpRect
.Top() << 1 ) + nSrcHeight
- 1;
2032 for( nY
= 0L, nOutY
= nOffY
; nY
< nDstHeight
; nY
++, nOutY
++ )
2034 pMapY
[ nY
] = aBmpRect
.Top() + nOutY
* nSrcHeight
/ nOutHeight
;
2037 pMapY
[ nY
] = nMirrOffY
- pMapY
[ nY
];
2040 BitmapReadAccess
* pP
= ( (Bitmap
&) rBmp
).AcquireReadAccess();
2041 BitmapReadAccess
* pA
= ( (AlphaMask
&) rAlpha
).AcquireReadAccess();
2043 DBG_ASSERT( pA
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
||
2044 pA
->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK
,
2045 "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
2047 // #i38887# reading from screen may sometimes fail
2048 if( aBmp
.ImplGetImpBitmap() )
2054 aTmp
= ImplBlendWithAlpha(
2072 // #110958# Disable alpha VDev, we're doing the necessary
2073 // stuff explicitely furher below
2077 DrawBitmap( aDstRect
.TopLeft(),
2080 // #110958# Enable alpha VDev again
2081 mpAlphaVDev
= pOldVDev
;
2084 ( (Bitmap
&) rBmp
).ReleaseAccess( pP
);
2085 ( (AlphaMask
&) rAlpha
).ReleaseAccess( pA
);
2090 mpMetaFile
= pOldMetaFile
;
2095 // ------------------------------------------------------------------------
2097 void OutputDevice::ImplPrintTransparent( const Bitmap
& rBmp
, const Bitmap
& rMask
,
2098 const Point
& rDestPt
, const Size
& rDestSize
,
2099 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
2102 Point
aDestPt( LogicToPixel( rDestPt
) );
2103 Size
aDestSz( LogicToPixel( rDestSize
) );
2104 Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
2108 if( !rBmp
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height() )
2110 Bitmap
aPaint( rBmp
), aMask( rMask
);
2111 ULONG nMirrFlags
= 0UL;
2113 if( aMask
.GetBitCount() > 1 )
2114 aMask
.Convert( BMP_CONVERSION_1BIT_THRESHOLD
);
2116 // mirrored horizontically
2117 if( aDestSz
.Width() < 0L )
2119 aDestSz
.Width() = -aDestSz
.Width();
2120 aDestPt
.X() -= ( aDestSz
.Width() - 1L );
2121 nMirrFlags
|= BMP_MIRROR_HORZ
;
2124 // mirrored vertically
2125 if( aDestSz
.Height() < 0L )
2127 aDestSz
.Height() = -aDestSz
.Height();
2128 aDestPt
.Y() -= ( aDestSz
.Height() - 1L );
2129 nMirrFlags
|= BMP_MIRROR_VERT
;
2133 if( aSrcRect
!= Rectangle( aPt
, aPaint
.GetSizePixel() ) )
2135 aPaint
.Crop( aSrcRect
);
2136 aMask
.Crop( aSrcRect
);
2139 // destination mirrored
2142 aPaint
.Mirror( nMirrFlags
);
2143 aMask
.Mirror( nMirrFlags
);
2146 // we always want to have a mask
2147 if( aMask
.IsEmpty() )
2149 aMask
= Bitmap( aSrcRect
.GetSize(), 1 );
2150 aMask
.Erase( Color( COL_BLACK
) );
2154 const long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
2155 long nX
, nY
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
;
2156 long* pMapX
= new long[ nSrcWidth
+ 1 ];
2157 long* pMapY
= new long[ nSrcHeight
+ 1 ];
2158 const BOOL bOldMap
= mbMap
;
2162 // create forward mapping tables
2163 for( nX
= 0L; nX
<= nSrcWidth
; nX
++ )
2164 pMapX
[ nX
] = aDestPt
.X() + FRound( (double) aDestSz
.Width() * nX
/ nSrcWidth
);
2166 for( nY
= 0L; nY
<= nSrcHeight
; nY
++ )
2167 pMapY
[ nY
] = aDestPt
.Y() + FRound( (double) aDestSz
.Height() * nY
/ nSrcHeight
);
2169 // walk through all rectangles of mask
2170 Region
aWorkRgn( aMask
.CreateRegion( COL_BLACK
, Rectangle( Point(), aMask
.GetSizePixel() ) ) );
2171 ImplRegionInfo aInfo
;
2172 BOOL bRgnRect
= aWorkRgn
.ImplGetFirstRect( aInfo
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
);
2176 Bitmap
aBandBmp( aPaint
);
2177 const Rectangle
aBandRect( Point( nWorkX
, nWorkY
), Size( nWorkWidth
, nWorkHeight
) );
2178 const Point
aMapPt( pMapX
[ nWorkX
], pMapY
[ nWorkY
] );
2179 const Size
aMapSz( pMapX
[ nWorkX
+ nWorkWidth
] - aMapPt
.X(), pMapY
[ nWorkY
+ nWorkHeight
] - aMapPt
.Y() );
2181 aBandBmp
.Crop( aBandRect
);
2182 ImplDrawBitmap( aMapPt
, aMapSz
, Point(), aBandBmp
.GetSizePixel(), aBandBmp
, META_BMPSCALEPART_ACTION
);
2183 bRgnRect
= aWorkRgn
.ImplGetNextRect( aInfo
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
);
2193 // ------------------------------------------------------------------------
2195 void OutputDevice::ImplPrintMask( const Bitmap
& rMask
, const Color
& rMaskColor
,
2196 const Point
& rDestPt
, const Size
& rDestSize
,
2197 const Point
& rSrcPtPixel
, const Size
& rSrcSizePixel
)
2200 Point
aDestPt( LogicToPixel( rDestPt
) );
2201 Size
aDestSz( LogicToPixel( rDestSize
) );
2202 Rectangle
aSrcRect( rSrcPtPixel
, rSrcSizePixel
);
2206 if( !rMask
.IsEmpty() && aSrcRect
.GetWidth() && aSrcRect
.GetHeight() && aDestSz
.Width() && aDestSz
.Height() )
2208 Bitmap
aMask( rMask
);
2209 ULONG nMirrFlags
= 0UL;
2211 if( aMask
.GetBitCount() > 1 )
2212 aMask
.Convert( BMP_CONVERSION_1BIT_THRESHOLD
);
2214 // mirrored horizontically
2215 if( aDestSz
.Width() < 0L )
2217 aDestSz
.Width() = -aDestSz
.Width();
2218 aDestPt
.X() -= ( aDestSz
.Width() - 1L );
2219 nMirrFlags
|= BMP_MIRROR_HORZ
;
2222 // mirrored vertically
2223 if( aDestSz
.Height() < 0L )
2225 aDestSz
.Height() = -aDestSz
.Height();
2226 aDestPt
.Y() -= ( aDestSz
.Height() - 1L );
2227 nMirrFlags
|= BMP_MIRROR_VERT
;
2231 if( aSrcRect
!= Rectangle( aPt
, aMask
.GetSizePixel() ) )
2232 aMask
.Crop( aSrcRect
);
2234 // destination mirrored
2236 aMask
.Mirror( nMirrFlags
);
2239 const long nSrcWidth
= aSrcRect
.GetWidth(), nSrcHeight
= aSrcRect
.GetHeight();
2240 long nX
, nY
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
;
2241 long* pMapX
= new long[ nSrcWidth
+ 1 ];
2242 long* pMapY
= new long[ nSrcHeight
+ 1 ];
2243 GDIMetaFile
* pOldMetaFile
= mpMetaFile
;
2244 const BOOL bOldMap
= mbMap
;
2248 Push( PUSH_FILLCOLOR
| PUSH_LINECOLOR
);
2249 SetLineColor( rMaskColor
);
2250 SetFillColor( rMaskColor
);
2251 ImplInitLineColor();
2252 ImplInitFillColor();
2254 // create forward mapping tables
2255 for( nX
= 0L; nX
<= nSrcWidth
; nX
++ )
2256 pMapX
[ nX
] = aDestPt
.X() + FRound( (double) aDestSz
.Width() * nX
/ nSrcWidth
);
2258 for( nY
= 0L; nY
<= nSrcHeight
; nY
++ )
2259 pMapY
[ nY
] = aDestPt
.Y() + FRound( (double) aDestSz
.Height() * nY
/ nSrcHeight
);
2261 // walk through all rectangles of mask
2262 Region
aWorkRgn( aMask
.CreateRegion( COL_BLACK
, Rectangle( Point(), aMask
.GetSizePixel() ) ) );
2263 ImplRegionInfo aInfo
;
2264 BOOL bRgnRect
= aWorkRgn
.ImplGetFirstRect( aInfo
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
);
2268 const Point
aMapPt( pMapX
[ nWorkX
], pMapY
[ nWorkY
] );
2269 const Size
aMapSz( pMapX
[ nWorkX
+ nWorkWidth
] - aMapPt
.X(), pMapY
[ nWorkY
+ nWorkHeight
] - aMapPt
.Y() );
2271 DrawRect( Rectangle( aMapPt
, aMapSz
) );
2272 bRgnRect
= aWorkRgn
.ImplGetNextRect( aInfo
, nWorkX
, nWorkY
, nWorkWidth
, nWorkHeight
);
2279 mpMetaFile
= pOldMetaFile
;