19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
59f62ea84SAndrew Rist * distributed with this work for additional information
69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist * software distributed under the License is distributed on an
159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
179f62ea84SAndrew Rist * specific language governing permissions and limitations
189f62ea84SAndrew Rist * under the License.
19cdf0e10cSrcweir *
209f62ea84SAndrew Rist *************************************************************/
219f62ea84SAndrew Rist
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_vcl.hxx"
24cdf0e10cSrcweir
25cdf0e10cSrcweir #include <tools/debug.hxx>
26cdf0e10cSrcweir #include <vcl/bitmap.hxx>
27cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
28cdf0e10cSrcweir #include <vcl/window.hxx>
29cdf0e10cSrcweir #include <vcl/metaact.hxx>
30cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
31cdf0e10cSrcweir #include <vcl/virdev.hxx>
32cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
33cdf0e10cSrcweir #include <vcl/outdev.hxx>
34cdf0e10cSrcweir #include <vcl/window.hxx>
35cdf0e10cSrcweir #include <vcl/image.hxx>
36cdf0e10cSrcweir #include <bmpfast.hxx>
37cdf0e10cSrcweir #include <salbmp.hxx>
38cdf0e10cSrcweir #include <salgdi.hxx>
39cdf0e10cSrcweir #include <impbmp.hxx>
40cdf0e10cSrcweir #include <sallayout.hxx>
41cdf0e10cSrcweir #include <image.h>
42cdf0e10cSrcweir #include <outdev.h>
43cdf0e10cSrcweir #include <window.h>
44cdf0e10cSrcweir #include <outdata.hxx>
455f27b83cSArmin Le Grand #include <basegfx/matrix/b2dhommatrix.hxx>
46f8c0d554SArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
47cdf0e10cSrcweir
48cdf0e10cSrcweir #define BAND_MAX_SIZE 512000
49cdf0e10cSrcweir
50cdf0e10cSrcweir // =======================================================================
51cdf0e10cSrcweir
52cdf0e10cSrcweir DBG_NAMEEX( OutputDevice )
53cdf0e10cSrcweir
54cdf0e10cSrcweir // =======================================================================
55cdf0e10cSrcweir
56cdf0e10cSrcweir // -----------
57cdf0e10cSrcweir // - Defines -
58cdf0e10cSrcweir // -----------
59cdf0e10cSrcweir
60cdf0e10cSrcweir #define OUTDEV_INIT() \
61cdf0e10cSrcweir { \
62cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() ) \
63cdf0e10cSrcweir return; \
64cdf0e10cSrcweir \
65cdf0e10cSrcweir if ( !mpGraphics ) \
66cdf0e10cSrcweir if ( !ImplGetGraphics() ) \
67cdf0e10cSrcweir return; \
68cdf0e10cSrcweir \
69cdf0e10cSrcweir if ( mbInitClipRegion ) \
70cdf0e10cSrcweir ImplInitClipRegion(); \
71cdf0e10cSrcweir \
72cdf0e10cSrcweir if ( mbOutputClipped ) \
73cdf0e10cSrcweir return; \
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
76cdf0e10cSrcweir // -------------
77cdf0e10cSrcweir // - externals -
78cdf0e10cSrcweir // -------------
79cdf0e10cSrcweir
80cdf0e10cSrcweir extern sal_uLong nVCLRLut[ 6 ];
81cdf0e10cSrcweir extern sal_uLong nVCLGLut[ 6 ];
82cdf0e10cSrcweir extern sal_uLong nVCLBLut[ 6 ];
83cdf0e10cSrcweir extern sal_uLong nVCLDitherLut[ 256 ];
84cdf0e10cSrcweir extern sal_uLong nVCLLut[ 256 ];
85cdf0e10cSrcweir
86cdf0e10cSrcweir // =======================================================================
87cdf0e10cSrcweir
ImplAdjustTwoRect(SalTwoRect & rTwoRect,const Size & rSizePix)885f27b83cSArmin Le Grand sal_uLong ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir sal_uLong nMirrFlags = 0;
91cdf0e10cSrcweir
92cdf0e10cSrcweir if ( rTwoRect.mnDestWidth < 0 )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
95cdf0e10cSrcweir rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
96cdf0e10cSrcweir rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
97cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir
100cdf0e10cSrcweir if ( rTwoRect.mnDestHeight < 0 )
101cdf0e10cSrcweir {
102cdf0e10cSrcweir rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
103cdf0e10cSrcweir rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
104cdf0e10cSrcweir rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
105cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT;
106cdf0e10cSrcweir }
107cdf0e10cSrcweir
108cdf0e10cSrcweir if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
109cdf0e10cSrcweir ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
110cdf0e10cSrcweir ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
111cdf0e10cSrcweir ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
114cdf0e10cSrcweir Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
115cdf0e10cSrcweir Rectangle aCropRect( aSourceRect );
116cdf0e10cSrcweir
117cdf0e10cSrcweir aCropRect.Intersection( Rectangle( Point(), rSizePix ) );
118cdf0e10cSrcweir
119cdf0e10cSrcweir if( aCropRect.IsEmpty() )
120cdf0e10cSrcweir rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
121cdf0e10cSrcweir else
122cdf0e10cSrcweir {
123cdf0e10cSrcweir const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
124cdf0e10cSrcweir const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
125cdf0e10cSrcweir
126cdf0e10cSrcweir const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
127cdf0e10cSrcweir const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
128cdf0e10cSrcweir const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
129cdf0e10cSrcweir const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
130cdf0e10cSrcweir
131cdf0e10cSrcweir rTwoRect.mnSrcX = aCropRect.Left();
132cdf0e10cSrcweir rTwoRect.mnSrcY = aCropRect.Top();
133cdf0e10cSrcweir rTwoRect.mnSrcWidth = aCropRect.GetWidth();
134cdf0e10cSrcweir rTwoRect.mnSrcHeight = aCropRect.GetHeight();
135cdf0e10cSrcweir rTwoRect.mnDestX = nDstX1;
136cdf0e10cSrcweir rTwoRect.mnDestY = nDstY1;
137cdf0e10cSrcweir rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
138cdf0e10cSrcweir rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
139cdf0e10cSrcweir }
140cdf0e10cSrcweir }
141cdf0e10cSrcweir
142cdf0e10cSrcweir return nMirrFlags;
143cdf0e10cSrcweir }
144cdf0e10cSrcweir
145cdf0e10cSrcweir // =======================================================================
146cdf0e10cSrcweir
ImplDrawOutDevDirect(const OutputDevice * pSrcDev,SalTwoRect & rPosAry)1475f27b83cSArmin Le Grand void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, SalTwoRect& rPosAry )
148cdf0e10cSrcweir {
149cdf0e10cSrcweir SalGraphics* pGraphics2;
150cdf0e10cSrcweir
1515f27b83cSArmin Le Grand if ( rPosAry.mnSrcWidth && rPosAry.mnSrcHeight && rPosAry.mnDestWidth && rPosAry.mnDestHeight )
152cdf0e10cSrcweir {
153cdf0e10cSrcweir if ( this == pSrcDev )
154cdf0e10cSrcweir pGraphics2 = NULL;
155cdf0e10cSrcweir else
156cdf0e10cSrcweir {
157cdf0e10cSrcweir if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
158cdf0e10cSrcweir (GetOutDevType() != OUTDEV_WINDOW) )
159cdf0e10cSrcweir {
160cdf0e10cSrcweir if ( !pSrcDev->mpGraphics )
161cdf0e10cSrcweir {
162cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
163cdf0e10cSrcweir return;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir else
168cdf0e10cSrcweir {
169cdf0e10cSrcweir if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow )
170cdf0e10cSrcweir pGraphics2 = NULL;
171cdf0e10cSrcweir else
172cdf0e10cSrcweir {
173cdf0e10cSrcweir if ( !pSrcDev->mpGraphics )
174cdf0e10cSrcweir {
175cdf0e10cSrcweir if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
176cdf0e10cSrcweir return;
177cdf0e10cSrcweir }
178cdf0e10cSrcweir pGraphics2 = pSrcDev->mpGraphics;
179cdf0e10cSrcweir
180cdf0e10cSrcweir if ( !mpGraphics )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir if ( !ImplGetGraphics() )
183cdf0e10cSrcweir return;
184cdf0e10cSrcweir }
185cdf0e10cSrcweir DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
186cdf0e10cSrcweir "OutputDevice::DrawOutDev(): We need more than one Graphics" );
187cdf0e10cSrcweir }
188cdf0e10cSrcweir }
189cdf0e10cSrcweir }
190cdf0e10cSrcweir
191cdf0e10cSrcweir // #102532# Offset only has to be pseudo window offset
192cdf0e10cSrcweir Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
193cdf0e10cSrcweir Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
1945f27b83cSArmin Le Grand Rectangle aSrcRect( Point( rPosAry.mnSrcX, rPosAry.mnSrcY ),
1955f27b83cSArmin Le Grand Size( rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ) );
196cdf0e10cSrcweir const long nOldRight = aSrcRect.Right();
197cdf0e10cSrcweir const long nOldBottom = aSrcRect.Bottom();
198cdf0e10cSrcweir
199cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
200cdf0e10cSrcweir {
2015f27b83cSArmin Le Grand if ( (rPosAry.mnSrcX+rPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
202cdf0e10cSrcweir {
2035f27b83cSArmin Le Grand const long nOldWidth = rPosAry.mnSrcWidth;
2045f27b83cSArmin Le Grand rPosAry.mnSrcWidth -= (nOldRight - aSrcRect.Right());
2055f27b83cSArmin Le Grand rPosAry.mnDestWidth = rPosAry.mnDestWidth * rPosAry.mnSrcWidth / nOldWidth;
206cdf0e10cSrcweir }
207cdf0e10cSrcweir
2085f27b83cSArmin Le Grand if ( (rPosAry.mnSrcY+rPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
209cdf0e10cSrcweir {
2105f27b83cSArmin Le Grand const long nOldHeight = rPosAry.mnSrcHeight;
2115f27b83cSArmin Le Grand rPosAry.mnSrcHeight -= (nOldBottom - aSrcRect.Bottom());
2125f27b83cSArmin Le Grand rPosAry.mnDestHeight = rPosAry.mnDestHeight * rPosAry.mnSrcHeight / nOldHeight;
213cdf0e10cSrcweir }
214cdf0e10cSrcweir
215cdf0e10cSrcweir // --- RTL --- if this is no window, but pSrcDev is a window
216cdf0e10cSrcweir // mirroring may be required
217cdf0e10cSrcweir // because only windows have a SalGraphicsLayout
218cdf0e10cSrcweir // mirroring is performed here
219cdf0e10cSrcweir if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) )
220cdf0e10cSrcweir {
2215f27b83cSArmin Le Grand SalTwoRect aPosAry2 = rPosAry;
2225f27b83cSArmin Le Grand pGraphics2->mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcDev );
2235f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry2, pGraphics2, this, pSrcDev );
224cdf0e10cSrcweir }
225cdf0e10cSrcweir else
2265f27b83cSArmin Le Grand mpGraphics->CopyBits( rPosAry, pGraphics2, this, pSrcDev );
227cdf0e10cSrcweir }
228cdf0e10cSrcweir }
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
231cdf0e10cSrcweir // ------------------------------------------------------------------
232cdf0e10cSrcweir
DrawOutDev(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPt,const Size & rSrcSize)233cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
234cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize )
235cdf0e10cSrcweir {
236cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" );
237cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
238cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
239cdf0e10cSrcweir
240cdf0e10cSrcweir if( ImplIsRecordLayout() )
241cdf0e10cSrcweir return;
242cdf0e10cSrcweir
243cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER )
244cdf0e10cSrcweir return;
245cdf0e10cSrcweir
246cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp )
247cdf0e10cSrcweir {
248cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
249cdf0e10cSrcweir return;
250cdf0e10cSrcweir }
251cdf0e10cSrcweir
252cdf0e10cSrcweir if ( mpMetaFile )
253cdf0e10cSrcweir {
254cdf0e10cSrcweir const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
255cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
256cdf0e10cSrcweir }
257cdf0e10cSrcweir
258cdf0e10cSrcweir OUTDEV_INIT();
259cdf0e10cSrcweir
2605f27b83cSArmin Le Grand SalTwoRect aPosAry;
261cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
262cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
263cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
264cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
265cdf0e10cSrcweir
266cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
267cdf0e10cSrcweir {
268cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
269cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
270cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
271cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
272cdf0e10cSrcweir
273cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
274cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) );
275cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
276cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
277cdf0e10cSrcweir long nOldRight = aSrcRect.Right();
278cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom();
279cdf0e10cSrcweir
280cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
281cdf0e10cSrcweir {
282cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
283cdf0e10cSrcweir {
284cdf0e10cSrcweir long nOldWidth = aPosAry.mnSrcWidth;
285cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
286cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnDestWidth*aPosAry.mnSrcWidth/nOldWidth;
287cdf0e10cSrcweir }
288cdf0e10cSrcweir
289cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
290cdf0e10cSrcweir {
291cdf0e10cSrcweir long nOldHeight = aPosAry.mnSrcHeight;
292cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
293cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnDestHeight*aPosAry.mnSrcHeight/nOldHeight;
294cdf0e10cSrcweir }
295cdf0e10cSrcweir
2965f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry, NULL, this, NULL );
297cdf0e10cSrcweir }
298cdf0e10cSrcweir }
299cdf0e10cSrcweir
300cdf0e10cSrcweir if( mpAlphaVDev )
301cdf0e10cSrcweir mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize );
302cdf0e10cSrcweir }
303cdf0e10cSrcweir
304cdf0e10cSrcweir // ------------------------------------------------------------------
305cdf0e10cSrcweir
DrawOutDev(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPt,const Size & rSrcSize,const OutputDevice & rOutDev)306cdf0e10cSrcweir void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
307cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize,
308cdf0e10cSrcweir const OutputDevice& rOutDev )
309cdf0e10cSrcweir {
310cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawOutDev()" );
311cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
312cdf0e10cSrcweir DBG_CHKOBJ( &rOutDev, OutputDevice, ImplDbgCheckOutputDevice );
313cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
314cdf0e10cSrcweir DBG_ASSERT( rOutDev.meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::DrawOutDev(...) with printer devices!" );
315cdf0e10cSrcweir
316cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_PRINTER) || (rOutDev.meOutDevType == OUTDEV_PRINTER) || ImplIsRecordLayout() )
317cdf0e10cSrcweir return;
318cdf0e10cSrcweir
319cdf0e10cSrcweir if ( ROP_INVERT == meRasterOp )
320cdf0e10cSrcweir {
321cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
322cdf0e10cSrcweir return;
323cdf0e10cSrcweir }
324cdf0e10cSrcweir
325cdf0e10cSrcweir if ( mpMetaFile )
326cdf0e10cSrcweir {
327cdf0e10cSrcweir const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
328cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
329cdf0e10cSrcweir }
330cdf0e10cSrcweir
331cdf0e10cSrcweir OUTDEV_INIT();
332cdf0e10cSrcweir
3335f27b83cSArmin Le Grand SalTwoRect aPosAry;
334cdf0e10cSrcweir aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
335cdf0e10cSrcweir aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
336cdf0e10cSrcweir aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
337cdf0e10cSrcweir aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
338cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
339cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
340cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
341cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
342cdf0e10cSrcweir
343cdf0e10cSrcweir if( mpAlphaVDev )
344cdf0e10cSrcweir {
345cdf0e10cSrcweir if( rOutDev.mpAlphaVDev )
346cdf0e10cSrcweir {
347cdf0e10cSrcweir // alpha-blend source over destination
348cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
349cdf0e10cSrcweir
350cdf0e10cSrcweir // This would be mode SOURCE:
351cdf0e10cSrcweir // copy source alpha channel to our alpha channel
352cdf0e10cSrcweir //mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize, *rOutDev.mpAlphaVDev );
353cdf0e10cSrcweir }
354cdf0e10cSrcweir else
355cdf0e10cSrcweir {
3565f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry );
357cdf0e10cSrcweir
358cdf0e10cSrcweir // #i32109#: make destination rectangle opaque - source has no alpha
359cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
360cdf0e10cSrcweir }
361cdf0e10cSrcweir }
362cdf0e10cSrcweir else
363cdf0e10cSrcweir {
364cdf0e10cSrcweir if( rOutDev.mpAlphaVDev )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir // alpha-blend source over destination
367cdf0e10cSrcweir DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
368cdf0e10cSrcweir }
369cdf0e10cSrcweir else
370cdf0e10cSrcweir {
371cdf0e10cSrcweir // no alpha at all, neither in source nor destination device
3725f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry );
373cdf0e10cSrcweir }
374cdf0e10cSrcweir }
375cdf0e10cSrcweir }
376cdf0e10cSrcweir
377cdf0e10cSrcweir // ------------------------------------------------------------------
378cdf0e10cSrcweir
CopyArea(const Point & rDestPt,const Point & rSrcPt,const Size & rSrcSize,sal_uInt16 nFlags)379cdf0e10cSrcweir void OutputDevice::CopyArea( const Point& rDestPt,
380cdf0e10cSrcweir const Point& rSrcPt, const Size& rSrcSize,
381cdf0e10cSrcweir sal_uInt16 nFlags )
382cdf0e10cSrcweir {
383cdf0e10cSrcweir DBG_TRACE( "OutputDevice::CopyArea()" );
384cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
385cdf0e10cSrcweir DBG_ASSERT( meOutDevType != OUTDEV_PRINTER, "Don't use OutputDevice::CopyArea(...) with printer devices!" );
386cdf0e10cSrcweir
387cdf0e10cSrcweir if ( meOutDevType == OUTDEV_PRINTER || ImplIsRecordLayout() )
388cdf0e10cSrcweir return;
389cdf0e10cSrcweir
390cdf0e10cSrcweir RasterOp eOldRop = GetRasterOp();
391cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT );
392cdf0e10cSrcweir
393cdf0e10cSrcweir OUTDEV_INIT();
394cdf0e10cSrcweir
3955f27b83cSArmin Le Grand SalTwoRect aPosAry;
396cdf0e10cSrcweir aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
397cdf0e10cSrcweir aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
398cdf0e10cSrcweir
399cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
400cdf0e10cSrcweir {
401cdf0e10cSrcweir aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
402cdf0e10cSrcweir aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
403cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
404cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
405cdf0e10cSrcweir
406cdf0e10cSrcweir Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
407cdf0e10cSrcweir Size( mnOutWidth, mnOutHeight ) );
408cdf0e10cSrcweir Rectangle aSrcRect( Point( aPosAry.mnSrcX, aPosAry.mnSrcY ),
409cdf0e10cSrcweir Size( aPosAry.mnSrcWidth, aPosAry.mnSrcHeight ) );
410cdf0e10cSrcweir long nOldRight = aSrcRect.Right();
411cdf0e10cSrcweir long nOldBottom = aSrcRect.Bottom();
412cdf0e10cSrcweir
413cdf0e10cSrcweir if ( !aSrcRect.Intersection( aSrcOutRect ).IsEmpty() )
414cdf0e10cSrcweir {
415cdf0e10cSrcweir if ( (aPosAry.mnSrcX+aPosAry.mnSrcWidth-1) > aSrcOutRect.Right() )
416cdf0e10cSrcweir aPosAry.mnSrcWidth -= nOldRight-aSrcRect.Right();
417cdf0e10cSrcweir
418cdf0e10cSrcweir if ( (aPosAry.mnSrcY+aPosAry.mnSrcHeight-1) > aSrcOutRect.Bottom() )
419cdf0e10cSrcweir aPosAry.mnSrcHeight -= nOldBottom-aSrcRect.Bottom();
420cdf0e10cSrcweir
421cdf0e10cSrcweir if ( (meOutDevType == OUTDEV_WINDOW) && (nFlags & COPYAREA_WINDOWINVALIDATE) )
422cdf0e10cSrcweir {
423cdf0e10cSrcweir ((Window*)this)->ImplMoveAllInvalidateRegions( aSrcRect,
424cdf0e10cSrcweir aPosAry.mnDestX-aPosAry.mnSrcX,
425cdf0e10cSrcweir aPosAry.mnDestY-aPosAry.mnSrcY,
426cdf0e10cSrcweir sal_False );
427cdf0e10cSrcweir
428cdf0e10cSrcweir mpGraphics->CopyArea( aPosAry.mnDestX, aPosAry.mnDestY,
429cdf0e10cSrcweir aPosAry.mnSrcX, aPosAry.mnSrcY,
430cdf0e10cSrcweir aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
431cdf0e10cSrcweir SAL_COPYAREA_WINDOWINVALIDATE, this );
432cdf0e10cSrcweir }
433cdf0e10cSrcweir else
434cdf0e10cSrcweir {
435cdf0e10cSrcweir aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
436cdf0e10cSrcweir aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
4375f27b83cSArmin Le Grand mpGraphics->CopyBits( aPosAry, NULL, this, NULL );
438cdf0e10cSrcweir }
439cdf0e10cSrcweir }
440cdf0e10cSrcweir }
441cdf0e10cSrcweir
442cdf0e10cSrcweir SetRasterOp( eOldRop );
443cdf0e10cSrcweir
444cdf0e10cSrcweir if( mpAlphaVDev )
445cdf0e10cSrcweir mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags );
446cdf0e10cSrcweir }
447cdf0e10cSrcweir
448cdf0e10cSrcweir // ------------------------------------------------------------------
449cdf0e10cSrcweir
ImplDrawFrameDev(const Point & rPt,const Point & rDevPt,const Size & rDevSize,const OutputDevice & rOutDev,const Region & rRegion)450cdf0e10cSrcweir void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
451cdf0e10cSrcweir const OutputDevice& rOutDev, const Region& rRegion )
452cdf0e10cSrcweir {
453cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
454cdf0e10cSrcweir
455cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile;
456cdf0e10cSrcweir sal_Bool bOldMap = mbMap;
457cdf0e10cSrcweir RasterOp eOldROP = GetRasterOp();
458cdf0e10cSrcweir mpMetaFile = NULL;
459cdf0e10cSrcweir mbMap = sal_False;
460cdf0e10cSrcweir SetRasterOp( ROP_OVERPAINT );
461cdf0e10cSrcweir
462cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() )
463cdf0e10cSrcweir return;
464cdf0e10cSrcweir
465cdf0e10cSrcweir if ( !mpGraphics )
466cdf0e10cSrcweir {
467cdf0e10cSrcweir if ( !ImplGetGraphics() )
468cdf0e10cSrcweir return;
469cdf0e10cSrcweir }
470cdf0e10cSrcweir
471cdf0e10cSrcweir // ClipRegion zuruecksetzen
472cdf0e10cSrcweir if ( rRegion.IsNull() )
473cdf0e10cSrcweir mpGraphics->ResetClipRegion();
474cdf0e10cSrcweir else
475cdf0e10cSrcweir ImplSelectClipRegion( rRegion );
476cdf0e10cSrcweir
4775f27b83cSArmin Le Grand SalTwoRect aPosAry;
478cdf0e10cSrcweir aPosAry.mnSrcX = rDevPt.X();
479cdf0e10cSrcweir aPosAry.mnSrcY = rDevPt.Y();
480cdf0e10cSrcweir aPosAry.mnSrcWidth = rDevSize.Width();
481cdf0e10cSrcweir aPosAry.mnSrcHeight = rDevSize.Height();
482cdf0e10cSrcweir aPosAry.mnDestX = rPt.X();
483cdf0e10cSrcweir aPosAry.mnDestY = rPt.Y();
484cdf0e10cSrcweir aPosAry.mnDestWidth = rDevSize.Width();
485cdf0e10cSrcweir aPosAry.mnDestHeight = rDevSize.Height();
4865f27b83cSArmin Le Grand ImplDrawOutDevDirect( &rOutDev, aPosAry );
487cdf0e10cSrcweir
488cdf0e10cSrcweir // Dafuer sorgen, das ClipRegion neu berechnet und gesetzt wird
489cdf0e10cSrcweir mbInitClipRegion = sal_True;
490cdf0e10cSrcweir
491cdf0e10cSrcweir SetRasterOp( eOldROP );
492cdf0e10cSrcweir mbMap = bOldMap;
493cdf0e10cSrcweir mpMetaFile = pOldMetaFile;
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
496cdf0e10cSrcweir // ------------------------------------------------------------------
497cdf0e10cSrcweir
ImplGetFrameDev(const Point & rPt,const Point & rDevPt,const Size & rDevSize,OutputDevice & rDev)498cdf0e10cSrcweir void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
499cdf0e10cSrcweir OutputDevice& rDev )
500cdf0e10cSrcweir {
501cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
502cdf0e10cSrcweir
503cdf0e10cSrcweir sal_Bool bOldMap = mbMap;
504cdf0e10cSrcweir mbMap = sal_False;
505cdf0e10cSrcweir rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
506cdf0e10cSrcweir mbMap = bOldMap;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir
509cdf0e10cSrcweir // ------------------------------------------------------------------
510cdf0e10cSrcweir
DrawBitmap(const Point & rDestPt,const Bitmap & rBitmap)511cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
512cdf0e10cSrcweir {
513cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap()" );
514cdf0e10cSrcweir
515cdf0e10cSrcweir if( ImplIsRecordLayout() )
516cdf0e10cSrcweir return;
517cdf0e10cSrcweir
518cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() );
519cdf0e10cSrcweir ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
520cdf0e10cSrcweir
521cdf0e10cSrcweir if( mpAlphaVDev )
522cdf0e10cSrcweir {
523cdf0e10cSrcweir // #i32109#: Make bitmap area opaque
524cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) );
525cdf0e10cSrcweir }
526cdf0e10cSrcweir }
527cdf0e10cSrcweir
528cdf0e10cSrcweir // ------------------------------------------------------------------
529cdf0e10cSrcweir
DrawBitmap(const Point & rDestPt,const Size & rDestSize,const Bitmap & rBitmap)530cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
531cdf0e10cSrcweir {
532cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Size )" );
533cdf0e10cSrcweir
534cdf0e10cSrcweir if( ImplIsRecordLayout() )
535cdf0e10cSrcweir return;
536cdf0e10cSrcweir
537cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
538cdf0e10cSrcweir
539cdf0e10cSrcweir if( mpAlphaVDev )
540cdf0e10cSrcweir {
541cdf0e10cSrcweir // #i32109#: Make bitmap area opaque
542cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
543cdf0e10cSrcweir }
544cdf0e10cSrcweir }
545cdf0e10cSrcweir
546cdf0e10cSrcweir // ------------------------------------------------------------------
547cdf0e10cSrcweir
DrawBitmap(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const Bitmap & rBitmap)548cdf0e10cSrcweir void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
549cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
550cdf0e10cSrcweir const Bitmap& rBitmap )
551cdf0e10cSrcweir {
552cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmap( Point, Size )" );
553cdf0e10cSrcweir
554cdf0e10cSrcweir if( ImplIsRecordLayout() )
555cdf0e10cSrcweir return;
556cdf0e10cSrcweir
557cdf0e10cSrcweir ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
558cdf0e10cSrcweir
559cdf0e10cSrcweir if( mpAlphaVDev )
560cdf0e10cSrcweir {
561cdf0e10cSrcweir // #i32109#: Make bitmap area opaque
562cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
563cdf0e10cSrcweir }
564cdf0e10cSrcweir }
565cdf0e10cSrcweir
566cdf0e10cSrcweir // -----------------------------------------------------------------------------
567cdf0e10cSrcweir
ImplDrawBitmap(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const Bitmap & rBitmap,const sal_uLong nAction)568cdf0e10cSrcweir void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
569cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
570cdf0e10cSrcweir const Bitmap& rBitmap, const sal_uLong nAction )
571cdf0e10cSrcweir {
572cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
573cdf0e10cSrcweir
574cdf0e10cSrcweir if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
575cdf0e10cSrcweir return;
5765f27b83cSArmin Le Grand
5775f27b83cSArmin Le Grand if ( ROP_INVERT == meRasterOp )
578cdf0e10cSrcweir {
579cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
580cdf0e10cSrcweir return;
581cdf0e10cSrcweir }
5825f27b83cSArmin Le Grand
5835f27b83cSArmin Le Grand Bitmap aBmp( rBitmap );
5845f27b83cSArmin Le Grand
5855f27b83cSArmin Le Grand if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
586cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
587cdf0e10cSrcweir {
588cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
589cdf0e10cSrcweir {
590cdf0e10cSrcweir sal_uInt8 cCmpVal;
591cdf0e10cSrcweir
592cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
593cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
594cdf0e10cSrcweir else
595cdf0e10cSrcweir cCmpVal = 255;
596cdf0e10cSrcweir
597cdf0e10cSrcweir Color aCol( cCmpVal, cCmpVal, cCmpVal );
598cdf0e10cSrcweir Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
599cdf0e10cSrcweir SetLineColor( aCol );
600cdf0e10cSrcweir SetFillColor( aCol );
601cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
602cdf0e10cSrcweir Pop();
603cdf0e10cSrcweir return;
604cdf0e10cSrcweir }
605cdf0e10cSrcweir else if( !!aBmp )
606cdf0e10cSrcweir {
607cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
608cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
609cdf0e10cSrcweir
610cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
611cdf0e10cSrcweir aBmp.Convert( BMP_CONVERSION_GHOSTED );
612cdf0e10cSrcweir }
613cdf0e10cSrcweir }
614cdf0e10cSrcweir
615cdf0e10cSrcweir if ( mpMetaFile )
616cdf0e10cSrcweir {
617cdf0e10cSrcweir switch( nAction )
618cdf0e10cSrcweir {
619cdf0e10cSrcweir case( META_BMP_ACTION ):
620cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
621cdf0e10cSrcweir break;
622cdf0e10cSrcweir
623cdf0e10cSrcweir case( META_BMPSCALE_ACTION ):
624cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
625cdf0e10cSrcweir break;
626cdf0e10cSrcweir
627cdf0e10cSrcweir case( META_BMPSCALEPART_ACTION ):
628cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpScalePartAction(
629cdf0e10cSrcweir rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
630cdf0e10cSrcweir break;
631cdf0e10cSrcweir }
632cdf0e10cSrcweir }
633cdf0e10cSrcweir
634cdf0e10cSrcweir OUTDEV_INIT();
635cdf0e10cSrcweir
636cdf0e10cSrcweir if( !aBmp.IsEmpty() )
637cdf0e10cSrcweir {
6385f27b83cSArmin Le Grand SalTwoRect aPosAry;
639cdf0e10cSrcweir
640cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X();
641cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y();
642cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width();
643cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height();
644cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
645cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
646cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
647cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
648cdf0e10cSrcweir
649cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
650cdf0e10cSrcweir
651cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
652cdf0e10cSrcweir {
653cdf0e10cSrcweir if ( nMirrFlags )
654cdf0e10cSrcweir aBmp.Mirror( nMirrFlags );
655cdf0e10cSrcweir
656cdf0e10cSrcweir /* #i75264# (corrected with #i81576#)
657cdf0e10cSrcweir * sometimes a bitmap is scaled to a ridiculous size and drawn
658cdf0e10cSrcweir * to a quite normal VDev, so only a very small part of
659cdf0e10cSrcweir * the scaled bitmap will be visible. However actually scaling
660cdf0e10cSrcweir * the bitmap will use so much memory that we end with a crash.
661cdf0e10cSrcweir * Workaround: since only a small part of the scaled bitmap will
662cdf0e10cSrcweir * be actually drawn anyway (because of clipping on the device
663cdf0e10cSrcweir * boundary), limit the destination and source rectangles so
664cdf0e10cSrcweir * that the destination rectangle will overlap the device but only
665cdf0e10cSrcweir * be reasonably (say factor 2) larger than the device itself.
666cdf0e10cSrcweir */
6675f27b83cSArmin Le Grand
6685f27b83cSArmin Le Grand // not needed for win32, it uses GdiPlus and is able to do everything without
6695f27b83cSArmin Le Grand // internally scaling the bitmap
6705f27b83cSArmin Le Grand #ifndef WIN32
6715f27b83cSArmin Le Grand
672cdf0e10cSrcweir if( aPosAry.mnDestWidth > 2048 || aPosAry.mnDestHeight > 2048 )
673cdf0e10cSrcweir {
674cdf0e10cSrcweir if( meOutDevType == OUTDEV_WINDOW ||
675cdf0e10cSrcweir (meOutDevType == OUTDEV_VIRDEV && mpPDFWriter == 0 ) )
676cdf0e10cSrcweir {
677cdf0e10cSrcweir // #i81576# do the following trick only if there is overlap at all
678cdf0e10cSrcweir // else the formulae don't work
679cdf0e10cSrcweir // theoretically in this case we wouldn't need to draw the bitmap at all
680cdf0e10cSrcweir // however there are some esoteric case where that is needed
681cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth >= 0
682cdf0e10cSrcweir && aPosAry.mnDestX < mnOutWidth
683cdf0e10cSrcweir && aPosAry.mnDestY + aPosAry.mnDestHeight >= 0
684cdf0e10cSrcweir && aPosAry.mnDestY < mnOutHeight )
685cdf0e10cSrcweir {
686cdf0e10cSrcweir // reduce scaling to something reasonable taking into account the output size
687cdf0e10cSrcweir if( aPosAry.mnDestWidth > 3*mnOutWidth && aPosAry.mnSrcWidth )
688cdf0e10cSrcweir {
689cdf0e10cSrcweir const double nScaleX = aPosAry.mnDestWidth/double(aPosAry.mnSrcWidth);
690cdf0e10cSrcweir
691cdf0e10cSrcweir if( aPosAry.mnDestX + aPosAry.mnDestWidth > mnOutWidth )
692cdf0e10cSrcweir {
693cdf0e10cSrcweir aPosAry.mnDestWidth = Max(long(0),mnOutWidth-aPosAry.mnDestX);
694cdf0e10cSrcweir }
695cdf0e10cSrcweir if( aPosAry.mnDestX < 0 )
696cdf0e10cSrcweir {
697cdf0e10cSrcweir aPosAry.mnDestWidth += aPosAry.mnDestX;
698cdf0e10cSrcweir aPosAry.mnSrcX -= sal::static_int_cast<long>(aPosAry.mnDestX / nScaleX);
699cdf0e10cSrcweir aPosAry.mnDestX = 0;
700cdf0e10cSrcweir }
701cdf0e10cSrcweir
702cdf0e10cSrcweir aPosAry.mnSrcWidth = sal::static_int_cast<long>(aPosAry.mnDestWidth / nScaleX);
703cdf0e10cSrcweir }
704cdf0e10cSrcweir
705cdf0e10cSrcweir if( aPosAry.mnDestHeight > 3*mnOutHeight && aPosAry.mnSrcHeight != 0 )
706cdf0e10cSrcweir {
707cdf0e10cSrcweir const double nScaleY = aPosAry.mnDestHeight/double(aPosAry.mnSrcHeight);
708cdf0e10cSrcweir
709cdf0e10cSrcweir if( aPosAry.mnDestY + aPosAry.mnDestHeight > mnOutHeight )
710cdf0e10cSrcweir {
711cdf0e10cSrcweir aPosAry.mnDestHeight = Max(long(0),mnOutHeight-aPosAry.mnDestY);
712cdf0e10cSrcweir }
713cdf0e10cSrcweir if( aPosAry.mnDestY < 0 )
714cdf0e10cSrcweir {
715cdf0e10cSrcweir aPosAry.mnDestHeight += aPosAry.mnDestY;
716cdf0e10cSrcweir aPosAry.mnSrcY -= sal::static_int_cast<long>(aPosAry.mnDestY / nScaleY);
717cdf0e10cSrcweir aPosAry.mnDestY = 0;
718cdf0e10cSrcweir }
719cdf0e10cSrcweir
720cdf0e10cSrcweir aPosAry.mnSrcHeight = sal::static_int_cast<long>(aPosAry.mnDestHeight / nScaleY);
721cdf0e10cSrcweir }
722cdf0e10cSrcweir }
723cdf0e10cSrcweir }
724cdf0e10cSrcweir }
7255f27b83cSArmin Le Grand #endif
726cdf0e10cSrcweir
727cdf0e10cSrcweir if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
7285f27b83cSArmin Le Grand {
7295f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
7305f27b83cSArmin Le Grand }
731cdf0e10cSrcweir }
732cdf0e10cSrcweir }
733cdf0e10cSrcweir }
734cdf0e10cSrcweir
735cdf0e10cSrcweir // ------------------------------------------------------------------
736cdf0e10cSrcweir
DrawBitmapEx(const Point & rDestPt,const BitmapEx & rBitmapEx)737cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt,
738cdf0e10cSrcweir const BitmapEx& rBitmapEx )
739cdf0e10cSrcweir {
740cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx()" );
741cdf0e10cSrcweir
742cdf0e10cSrcweir if( ImplIsRecordLayout() )
743cdf0e10cSrcweir return;
744cdf0e10cSrcweir
745cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
7465f27b83cSArmin Le Grand {
747cdf0e10cSrcweir DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
7485f27b83cSArmin Le Grand }
749cdf0e10cSrcweir else
750cdf0e10cSrcweir {
751cdf0e10cSrcweir const Size aSizePix( rBitmapEx.GetSizePixel() );
752cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
753cdf0e10cSrcweir }
754cdf0e10cSrcweir }
755cdf0e10cSrcweir
756cdf0e10cSrcweir // ------------------------------------------------------------------
757cdf0e10cSrcweir
DrawBitmapEx(const Point & rDestPt,const Size & rDestSize,const BitmapEx & rBitmapEx)758cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
759cdf0e10cSrcweir const BitmapEx& rBitmapEx )
760cdf0e10cSrcweir {
761cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Size )" );
762cdf0e10cSrcweir
763cdf0e10cSrcweir if( ImplIsRecordLayout() )
764cdf0e10cSrcweir return;
765cdf0e10cSrcweir
766cdf0e10cSrcweir if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
7675f27b83cSArmin Le Grand {
768cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
7695f27b83cSArmin Le Grand }
770cdf0e10cSrcweir else
7715f27b83cSArmin Le Grand {
772cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
773cdf0e10cSrcweir }
7745f27b83cSArmin Le Grand }
775cdf0e10cSrcweir
776cdf0e10cSrcweir // ------------------------------------------------------------------
777cdf0e10cSrcweir
DrawBitmapEx(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const BitmapEx & rBitmapEx)778cdf0e10cSrcweir void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
779cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
780cdf0e10cSrcweir const BitmapEx& rBitmapEx )
781cdf0e10cSrcweir {
782cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
783cdf0e10cSrcweir
784cdf0e10cSrcweir if( ImplIsRecordLayout() )
785cdf0e10cSrcweir return;
786cdf0e10cSrcweir
787cdf0e10cSrcweir if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
7885f27b83cSArmin Le Grand {
789cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
7905f27b83cSArmin Le Grand }
791cdf0e10cSrcweir else
7925f27b83cSArmin Le Grand {
793cdf0e10cSrcweir ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
794cdf0e10cSrcweir }
7955f27b83cSArmin Le Grand }
7965f27b83cSArmin Le Grand
7975f27b83cSArmin Le Grand // ------------------------------------------------------------------
7985f27b83cSArmin Le Grand
DrawTransformedBitmapEx(const basegfx::B2DHomMatrix & rTransformation,const BitmapEx & rBitmapEx)7995f27b83cSArmin Le Grand void OutputDevice::DrawTransformedBitmapEx(
8005f27b83cSArmin Le Grand const basegfx::B2DHomMatrix& rTransformation,
8015f27b83cSArmin Le Grand const BitmapEx& rBitmapEx)
8025f27b83cSArmin Le Grand {
8035f27b83cSArmin Le Grand DBG_TRACE( "OutputDevice::DrawBitmapEx( Point, Size )" );
8045f27b83cSArmin Le Grand
8055f27b83cSArmin Le Grand if( ImplIsRecordLayout() )
8065f27b83cSArmin Le Grand return;
8075f27b83cSArmin Le Grand
8085f27b83cSArmin Le Grand if(rBitmapEx.IsEmpty())
8095f27b83cSArmin Le Grand return;
8105f27b83cSArmin Le Grand
8115f27b83cSArmin Le Grand if ( mnDrawMode & DRAWMODE_NOBITMAP )
8125f27b83cSArmin Le Grand return;
8135f27b83cSArmin Le Grand
8145f27b83cSArmin Le Grand // decompose matrix to check rotation and shear
8155f27b83cSArmin Le Grand basegfx::B2DVector aScale, aTranslate;
8165f27b83cSArmin Le Grand double fRotate, fShearX;
8175f27b83cSArmin Le Grand rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
8185f27b83cSArmin Le Grand const bool bRotated(!basegfx::fTools::equalZero(fRotate));
8195f27b83cSArmin Le Grand const bool bSheared(!basegfx::fTools::equalZero(fShearX));
8205f27b83cSArmin Le Grand const bool bMirroredX(basegfx::fTools::less(aScale.getX(), 0.0));
8215f27b83cSArmin Le Grand const bool bMirroredY(basegfx::fTools::less(aScale.getY(), 0.0));
822f8c0d554SArmin Le Grand static bool bForceToOwnTransformer(false);
8235f27b83cSArmin Le Grand
824f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && !bRotated && !bSheared && !bMirroredX && !bMirroredY)
8255f27b83cSArmin Le Grand {
8265f27b83cSArmin Le Grand // with no rotation, shear or mirroring it can be mapped to DrawBitmapEx
8275f27b83cSArmin Le Grand // do *not* execute the mirroring here, it's done in the fallback
828fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values
8295f27b83cSArmin Le Grand const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
830fa004bb0SArmin Le Grand const Size aDestSize(
831fa004bb0SArmin Le Grand basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
832fa004bb0SArmin Le Grand basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
8335f27b83cSArmin Le Grand
8345f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
8355f27b83cSArmin Le Grand return;
8365f27b83cSArmin Le Grand }
8375f27b83cSArmin Le Grand
8385f27b83cSArmin Le Grand // we have rotation,shear or mirror, check if some crazy mode needs the
8395f27b83cSArmin Le Grand // created transformed bitmap
8405f27b83cSArmin Le Grand const bool bInvert(ROP_INVERT == meRasterOp);
8415f27b83cSArmin Le Grand const bool bBitmapChangedColor(mnDrawMode & (DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP));
8425f27b83cSArmin Le Grand const bool bMetafile(mpMetaFile);
8435f27b83cSArmin Le Grand const bool bPrinter(OUTDEV_PRINTER == meOutDevType);
8445f27b83cSArmin Le Grand bool bDone(false);
8455f27b83cSArmin Le Grand const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
8465f27b83cSArmin Le Grand const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile && !bPrinter);
8475f27b83cSArmin Le Grand
848f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && bTryDirectPaint)
8495f27b83cSArmin Le Grand {
8505f27b83cSArmin Le Grand // try to paint directly
8515f27b83cSArmin Le Grand const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0));
8525f27b83cSArmin Le Grand const basegfx::B2DPoint aTopX(aFullTransform * basegfx::B2DPoint(1.0, 0.0));
8535f27b83cSArmin Le Grand const basegfx::B2DPoint aTopY(aFullTransform * basegfx::B2DPoint(0.0, 1.0));
8545f27b83cSArmin Le Grand SalBitmap* pSalSrcBmp = rBitmapEx.GetBitmap().ImplGetImpBitmap()->ImplGetSalBitmap();
8555f27b83cSArmin Le Grand SalBitmap* pSalAlphaBmp = 0;
8565f27b83cSArmin Le Grand
8575f27b83cSArmin Le Grand if(rBitmapEx.IsTransparent())
8585f27b83cSArmin Le Grand {
8595f27b83cSArmin Le Grand if(rBitmapEx.IsAlpha())
8605f27b83cSArmin Le Grand {
8615f27b83cSArmin Le Grand pSalAlphaBmp = rBitmapEx.GetAlpha().ImplGetImpBitmap()->ImplGetSalBitmap();
8625f27b83cSArmin Le Grand }
8635f27b83cSArmin Le Grand else
8645f27b83cSArmin Le Grand {
8655f27b83cSArmin Le Grand pSalAlphaBmp = rBitmapEx.GetMask().ImplGetImpBitmap()->ImplGetSalBitmap();
8665f27b83cSArmin Le Grand }
8675f27b83cSArmin Le Grand }
8685f27b83cSArmin Le Grand
8695f27b83cSArmin Le Grand bDone = mpGraphics->DrawTransformedBitmap(
8705f27b83cSArmin Le Grand aNull,
8715f27b83cSArmin Le Grand aTopX,
8725f27b83cSArmin Le Grand aTopY,
8735f27b83cSArmin Le Grand *pSalSrcBmp,
8745f27b83cSArmin Le Grand pSalAlphaBmp,
8755f27b83cSArmin Le Grand this);
8765f27b83cSArmin Le Grand }
8775f27b83cSArmin Le Grand
8785f27b83cSArmin Le Grand if(!bDone)
8795f27b83cSArmin Le Grand {
8805f27b83cSArmin Le Grand // take the fallback when no rotate and shear, but mirror (else we would have done this above)
881f8c0d554SArmin Le Grand if(!bForceToOwnTransformer && !bRotated && !bSheared)
8825f27b83cSArmin Le Grand {
8835f27b83cSArmin Le Grand // with no rotation or shear it can be mapped to DrawBitmapEx
8845f27b83cSArmin Le Grand // do *not* execute the mirroring here, it's done in the fallback
885fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values
8865f27b83cSArmin Le Grand const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
887fa004bb0SArmin Le Grand const Size aDestSize(
888fa004bb0SArmin Le Grand basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
889fa004bb0SArmin Le Grand basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
8905f27b83cSArmin Le Grand
8915f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
8925f27b83cSArmin Le Grand return;
8935f27b83cSArmin Le Grand }
8945f27b83cSArmin Le Grand
8955f27b83cSArmin Le Grand // fallback; create transformed bitmap the hard way (back-transform
8965f27b83cSArmin Le Grand // the pixels) and paint
897f8c0d554SArmin Le Grand basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0);
898f8c0d554SArmin Le Grand
899f8c0d554SArmin Le Grand // limit maximum area to something looking good for non-pixel-based targets (metafile, printer)
9005496114cSArmin Le Grand // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area
9015496114cSArmin Le Grand // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
90202f6802cSJohn Bampton // to avoid crashes/resource problems (ca. 1500x3000 here)
9035496114cSArmin Le Grand const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
9045496114cSArmin Le Grand const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
9055496114cSArmin Le Grand const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea);
9065496114cSArmin Le Grand double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled)));
907f8c0d554SArmin Le Grand
908f8c0d554SArmin Le Grand if(!bMetafile && !bPrinter)
909f8c0d554SArmin Le Grand {
910f8c0d554SArmin Le Grand // limit TargetRange to existing pixels (if pixel device)
911f8c0d554SArmin Le Grand // first get discrete range of object
912f8c0d554SArmin Le Grand basegfx::B2DRange aFullPixelRange(aVisibleRange);
913f8c0d554SArmin Le Grand
914f8c0d554SArmin Le Grand aFullPixelRange.transform(aFullTransform);
915f8c0d554SArmin Le Grand
916f8c0d554SArmin Le Grand if(basegfx::fTools::equalZero(aFullPixelRange.getWidth()) || basegfx::fTools::equalZero(aFullPixelRange.getHeight()))
917f8c0d554SArmin Le Grand {
918f8c0d554SArmin Le Grand // object is outside of visible area
919f8c0d554SArmin Le Grand return;
920f8c0d554SArmin Le Grand }
921f8c0d554SArmin Le Grand
922f8c0d554SArmin Le Grand // now get discrete target pixels; start with OutDev pixel size and evtl.
923f8c0d554SArmin Le Grand // intersect with active clipping area
924f8c0d554SArmin Le Grand basegfx::B2DRange aOutPixel(
925f8c0d554SArmin Le Grand 0.0,
926f8c0d554SArmin Le Grand 0.0,
927f8c0d554SArmin Le Grand GetOutputSizePixel().Width(),
928f8c0d554SArmin Le Grand GetOutputSizePixel().Height());
929f8c0d554SArmin Le Grand
930f8c0d554SArmin Le Grand if(IsClipRegion())
931f8c0d554SArmin Le Grand {
932f8c0d554SArmin Le Grand const Rectangle aRegionRectangle(GetActiveClipRegion().GetBoundRect());
933f8c0d554SArmin Le Grand
934f8c0d554SArmin Le Grand aOutPixel.intersect( // caution! Range from rectangle, one too much (!)
935f8c0d554SArmin Le Grand basegfx::B2DRange(
936f8c0d554SArmin Le Grand aRegionRectangle.Left(),
937f8c0d554SArmin Le Grand aRegionRectangle.Top(),
938f8c0d554SArmin Le Grand aRegionRectangle.Right() + 1,
939f8c0d554SArmin Le Grand aRegionRectangle.Bottom() + 1));
940f8c0d554SArmin Le Grand }
941f8c0d554SArmin Le Grand
942f8c0d554SArmin Le Grand if(aOutPixel.isEmpty())
943f8c0d554SArmin Le Grand {
944f8c0d554SArmin Le Grand // no active output area
945f8c0d554SArmin Le Grand return;
946f8c0d554SArmin Le Grand }
947f8c0d554SArmin Le Grand
948f8c0d554SArmin Le Grand // if aFullPixelRange is not completely inside of aOutPixel,
949f8c0d554SArmin Le Grand // reduction of target pixels is possible
950f8c0d554SArmin Le Grand basegfx::B2DRange aVisiblePixelRange(aFullPixelRange);
951f8c0d554SArmin Le Grand
952f8c0d554SArmin Le Grand if(!aOutPixel.isInside(aFullPixelRange))
953f8c0d554SArmin Le Grand {
954f8c0d554SArmin Le Grand aVisiblePixelRange.intersect(aOutPixel);
955f8c0d554SArmin Le Grand
956f8c0d554SArmin Le Grand if(aVisiblePixelRange.isEmpty())
957f8c0d554SArmin Le Grand {
958f8c0d554SArmin Le Grand // nothing in visible part, reduces to nothing
959f8c0d554SArmin Le Grand return;
960f8c0d554SArmin Le Grand }
961f8c0d554SArmin Le Grand
962f8c0d554SArmin Le Grand // aVisiblePixelRange contains the reduced output area in
963f8c0d554SArmin Le Grand // discrete coordinates. To make it useful everywhere, make it relative to
964f8c0d554SArmin Le Grand // the object range
965f8c0d554SArmin Le Grand basegfx::B2DHomMatrix aMakeVisibleRangeRelative;
966f8c0d554SArmin Le Grand
967f8c0d554SArmin Le Grand aVisibleRange = aVisiblePixelRange;
968f8c0d554SArmin Le Grand aMakeVisibleRangeRelative.translate(
969f8c0d554SArmin Le Grand -aFullPixelRange.getMinX(),
970f8c0d554SArmin Le Grand -aFullPixelRange.getMinY());
971f8c0d554SArmin Le Grand aMakeVisibleRangeRelative.scale(
972f8c0d554SArmin Le Grand 1.0 / aFullPixelRange.getWidth(),
973f8c0d554SArmin Le Grand 1.0 / aFullPixelRange.getHeight());
974f8c0d554SArmin Le Grand aVisibleRange.transform(aMakeVisibleRangeRelative);
975f8c0d554SArmin Le Grand }
976f8c0d554SArmin Le Grand
977f8c0d554SArmin Le Grand // for pixel devices, do *not* limit size, else OutputDevice::ImplDrawAlpha
978f8c0d554SArmin Le Grand // will create another, badly scaled bitmap to do the job. Nonetheless, do a
979f8c0d554SArmin Le Grand // maximum clipping of something big (1600x1280x2). Add 1.0 to avoid rounding
980f8c0d554SArmin Le Grand // errors in rough estimations
981f8c0d554SArmin Le Grand const double fNewMaxArea(aVisiblePixelRange.getWidth() * aVisiblePixelRange.getHeight());
982f8c0d554SArmin Le Grand
983f8c0d554SArmin Le Grand fMaximumArea = std::min(4096000.0, fNewMaxArea + 1.0);
984f8c0d554SArmin Le Grand }
985f8c0d554SArmin Le Grand
986f8c0d554SArmin Le Grand if(!aVisibleRange.isEmpty())
987f8c0d554SArmin Le Grand {
988f8c0d554SArmin Le Grand static bool bDoSmoothAtAll(true);
9895496114cSArmin Le Grand BitmapEx aTransformed(rBitmapEx);
9905496114cSArmin Le Grand
9915496114cSArmin Le Grand // #122923# when the result needs an alpha channel due to being rotated or sheared
9925496114cSArmin Le Grand // and thus uncovering areas, add these channels so that the own transformer (used
9935496114cSArmin Le Grand // in getTransformed) also creates a transformed alpha channel
9945496114cSArmin Le Grand if(!aTransformed.IsTransparent() && (bSheared || bRotated))
9955496114cSArmin Le Grand {
9965496114cSArmin Le Grand // parts will be uncovered, extend aTransformed with a mask bitmap
9975496114cSArmin Le Grand const Bitmap aContent(aTransformed.GetBitmap());
9985496114cSArmin Le Grand #if defined(MACOSX)
9995496114cSArmin Le Grand AlphaMask aMaskBmp(aContent.GetSizePixel());
10005496114cSArmin Le Grand aMaskBmp.Erase(0);
10015496114cSArmin Le Grand #else
10025496114cSArmin Le Grand Bitmap aMaskBmp(aContent.GetSizePixel(), 1);
10035496114cSArmin Le Grand aMaskBmp.Erase(Color(COL_BLACK)); // #122758# Initialize to non-transparent
10045496114cSArmin Le Grand #endif
10055496114cSArmin Le Grand aTransformed = BitmapEx(aContent, aMaskBmp);
10065496114cSArmin Le Grand }
10075496114cSArmin Le Grand
10085496114cSArmin Le Grand aTransformed = aTransformed.getTransformed(
1009f8c0d554SArmin Le Grand aFullTransform,
1010f8c0d554SArmin Le Grand aVisibleRange,
1011f8c0d554SArmin Le Grand fMaximumArea,
10125496114cSArmin Le Grand bDoSmoothAtAll);
10135f27b83cSArmin Le Grand basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
1014f8c0d554SArmin Le Grand
1015f8c0d554SArmin Le Grand // get logic object target range
10165f27b83cSArmin Le Grand aTargetRange.transform(rTransformation);
1017f8c0d554SArmin Le Grand
1018f8c0d554SArmin Le Grand // get from unified/relative VisibleRange to logoc one
1019f8c0d554SArmin Le Grand aVisibleRange.transform(
1020f8c0d554SArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix(
1021f8c0d554SArmin Le Grand aTargetRange.getRange(),
1022f8c0d554SArmin Le Grand aTargetRange.getMinimum()));
1023f8c0d554SArmin Le Grand
1024f8c0d554SArmin Le Grand // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose
1025fa004bb0SArmin Le Grand // #124580# the correct DestSize needs to be calculated based on MaxXY values
1026f8c0d554SArmin Le Grand const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
1027fa004bb0SArmin Le Grand const Size aDestSize(
1028fa004bb0SArmin Le Grand basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(),
1029fa004bb0SArmin Le Grand basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y());
10305f27b83cSArmin Le Grand
10315f27b83cSArmin Le Grand DrawBitmapEx(aDestPt, aDestSize, aTransformed);
10325f27b83cSArmin Le Grand }
10335f27b83cSArmin Le Grand }
1034f8c0d554SArmin Le Grand }
1035cdf0e10cSrcweir
1036cdf0e10cSrcweir // ------------------------------------------------------------------
1037cdf0e10cSrcweir
ImplDrawBitmapEx(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const BitmapEx & rBitmapEx,const sal_uLong nAction)1038cdf0e10cSrcweir void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
1039cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1040cdf0e10cSrcweir const BitmapEx& rBitmapEx, const sal_uLong nAction )
1041cdf0e10cSrcweir {
1042cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
10435f27b83cSArmin Le Grand OSL_ENSURE(TRANSPARENT_NONE != rBitmapEx.GetTransparentType(), "ImplDrawBitmapEx not needed, no transparency in BitmapEx (!)");
1044cdf0e10cSrcweir
1045cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_NOBITMAP )
1046cdf0e10cSrcweir return;
10475f27b83cSArmin Le Grand
10485f27b83cSArmin Le Grand if ( ROP_INVERT == meRasterOp )
1049cdf0e10cSrcweir {
1050cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
1051cdf0e10cSrcweir return;
1052cdf0e10cSrcweir }
10535f27b83cSArmin Le Grand
10545f27b83cSArmin Le Grand BitmapEx aBmpEx( rBitmapEx );
10555f27b83cSArmin Le Grand
10565f27b83cSArmin Le Grand if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
1057cdf0e10cSrcweir DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
1058cdf0e10cSrcweir {
1059cdf0e10cSrcweir if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
1060cdf0e10cSrcweir {
1061cdf0e10cSrcweir Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
1062cdf0e10cSrcweir sal_uInt8 cCmpVal;
1063cdf0e10cSrcweir
1064cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
1065cdf0e10cSrcweir cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
1066cdf0e10cSrcweir else
1067cdf0e10cSrcweir cCmpVal = 255;
1068cdf0e10cSrcweir
1069cdf0e10cSrcweir aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
1070cdf0e10cSrcweir
1071cdf0e10cSrcweir if( aBmpEx.IsAlpha() )
1072cdf0e10cSrcweir {
1073cdf0e10cSrcweir // Create one-bit mask out of alpha channel, by
1074cdf0e10cSrcweir // thresholding it at alpha=0.5. As
1075cdf0e10cSrcweir // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
1076cdf0e10cSrcweir // output, having alpha-induced grey levels is not
1077cdf0e10cSrcweir // acceptable.
1078cdf0e10cSrcweir Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() );
1079cdf0e10cSrcweir aMask.MakeMono( 128 );
1080cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aMask );
1081cdf0e10cSrcweir }
1082cdf0e10cSrcweir else
1083cdf0e10cSrcweir {
1084cdf0e10cSrcweir aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir }
1087cdf0e10cSrcweir else if( !!aBmpEx )
1088cdf0e10cSrcweir {
1089cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
1090cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
1091cdf0e10cSrcweir
1092cdf0e10cSrcweir if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
1093cdf0e10cSrcweir aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
1094cdf0e10cSrcweir }
1095cdf0e10cSrcweir }
1096cdf0e10cSrcweir
1097cdf0e10cSrcweir if ( mpMetaFile )
1098cdf0e10cSrcweir {
1099cdf0e10cSrcweir switch( nAction )
1100cdf0e10cSrcweir {
1101cdf0e10cSrcweir case( META_BMPEX_ACTION ):
1102cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
1103cdf0e10cSrcweir break;
1104cdf0e10cSrcweir
1105cdf0e10cSrcweir case( META_BMPEXSCALE_ACTION ):
1106cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
1107cdf0e10cSrcweir break;
1108cdf0e10cSrcweir
1109cdf0e10cSrcweir case( META_BMPEXSCALEPART_ACTION ):
1110cdf0e10cSrcweir mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
1111cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
1112cdf0e10cSrcweir break;
1113cdf0e10cSrcweir }
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir
1116cdf0e10cSrcweir OUTDEV_INIT();
1117cdf0e10cSrcweir
1118cdf0e10cSrcweir if( OUTDEV_PRINTER == meOutDevType )
1119cdf0e10cSrcweir {
1120cdf0e10cSrcweir if( aBmpEx.IsAlpha() )
1121cdf0e10cSrcweir {
1122cdf0e10cSrcweir // #107169# For true alpha bitmaps, no longer masking the
1123cdf0e10cSrcweir // bitmap, but perform a full alpha blend against a white
1124cdf0e10cSrcweir // background here.
1125cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() );
1126cdf0e10cSrcweir aBmp.Blend( aBmpEx.GetAlpha(), Color( COL_WHITE) );
1127cdf0e10cSrcweir DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp );
1128cdf0e10cSrcweir }
1129cdf0e10cSrcweir else
1130cdf0e10cSrcweir {
1131cdf0e10cSrcweir Bitmap aBmp( aBmpEx.GetBitmap() ), aMask( aBmpEx.GetMask() );
1132cdf0e10cSrcweir aBmp.Replace( aMask, Color( COL_WHITE ) );
1133cdf0e10cSrcweir ImplPrintTransparent( aBmp, aMask, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
1134cdf0e10cSrcweir }
11355f27b83cSArmin Le Grand
1136cdf0e10cSrcweir return;
1137cdf0e10cSrcweir }
11385f27b83cSArmin Le Grand
11395f27b83cSArmin Le Grand if(aBmpEx.IsAlpha())
1140cdf0e10cSrcweir {
1141cdf0e10cSrcweir ImplDrawAlpha( aBmpEx.GetBitmap(), aBmpEx.GetAlpha(), rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
1142cdf0e10cSrcweir return;
1143cdf0e10cSrcweir }
1144cdf0e10cSrcweir
1145cdf0e10cSrcweir if( !( !aBmpEx ) )
1146cdf0e10cSrcweir {
11475f27b83cSArmin Le Grand SalTwoRect aPosAry;
1148cdf0e10cSrcweir
1149cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X();
1150cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y();
1151cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width();
1152cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height();
1153cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
1154cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
1155cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
1156cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
1157cdf0e10cSrcweir
1158cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmpEx.GetSizePixel() );
1159cdf0e10cSrcweir
1160cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
1161cdf0e10cSrcweir {
1162cdf0e10cSrcweir
1163cdf0e10cSrcweir if( nMirrFlags )
1164cdf0e10cSrcweir aBmpEx.Mirror( nMirrFlags );
1165cdf0e10cSrcweir
11665f27b83cSArmin Le Grand const SalBitmap* pSalSrcBmp = aBmpEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
1167cdf0e10cSrcweir const ImpBitmap* pMaskBmp = aBmpEx.ImplGetMaskImpBitmap();
1168cdf0e10cSrcweir
1169cdf0e10cSrcweir if ( pMaskBmp )
1170cdf0e10cSrcweir {
11715f27b83cSArmin Le Grand SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap();
11725f27b83cSArmin Le Grand bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp);
11735f27b83cSArmin Le Grand
11745f27b83cSArmin Le Grand if(bTryDirectPaint)
11755f27b83cSArmin Le Grand {
11765f27b83cSArmin Le Grand // only paint direct when no scaling and no MapMode, else the
11775f27b83cSArmin Le Grand // more expensive conversions may be done for short-time Bitmap/BitmapEx
11785f27b83cSArmin Le Grand // used for buffering only
11795f27b83cSArmin Le Grand if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight)
11805f27b83cSArmin Le Grand {
11815f27b83cSArmin Le Grand bTryDirectPaint = false;
11825f27b83cSArmin Le Grand }
11835f27b83cSArmin Le Grand }
11845f27b83cSArmin Le Grand
11855f27b83cSArmin Le Grand if(bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this))
11865f27b83cSArmin Le Grand {
11875f27b83cSArmin Le Grand // tried to paint as alpha directly. If tis worked, we are done (except
11885f27b83cSArmin Le Grand // alpha, see below)
11895f27b83cSArmin Le Grand }
11905f27b83cSArmin Le Grand else
11915f27b83cSArmin Le Grand {
1192cdf0e10cSrcweir // #4919452# reduce operation area to bounds of
1193cdf0e10cSrcweir // cliprect. since masked transparency involves
1194cdf0e10cSrcweir // creation of a large vdev and copying the screen
1195cdf0e10cSrcweir // content into that (slooow read from framebuffer),
1196cdf0e10cSrcweir // that should considerably increase performance for
1197cdf0e10cSrcweir // large bitmaps and small clippings.
1198cdf0e10cSrcweir
1199cdf0e10cSrcweir // Note that this optimisation is a workaround for a
1200cdf0e10cSrcweir // Writer peculiarity, namely, to decompose background
1201cdf0e10cSrcweir // graphics into myriads of disjunct, tiny
1202cdf0e10cSrcweir // rectangles. That otherwise kills us here, since for
1203cdf0e10cSrcweir // transparent output, SAL always prepares the whole
1204cdf0e10cSrcweir // bitmap, if aPosAry contains the whole bitmap (and
1205cdf0e10cSrcweir // it's _not_ to blame for that).
1206cdf0e10cSrcweir
1207cdf0e10cSrcweir // Note the call to ImplPixelToDevicePixel(), since
1208cdf0e10cSrcweir // aPosAry already contains the mnOutOff-offsets, they
1209cdf0e10cSrcweir // also have to be applied to the region
1210cdf0e10cSrcweir Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
1211cdf0e10cSrcweir
1212cdf0e10cSrcweir // TODO: Also respect scaling (that's a bit tricky,
1213cdf0e10cSrcweir // since the source points have to move fractional
1214cdf0e10cSrcweir // amounts (which is not possible, thus has to be
1215cdf0e10cSrcweir // emulated by increases copy area)
1216cdf0e10cSrcweir // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
1217cdf0e10cSrcweir // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
1218cdf0e10cSrcweir
1219cdf0e10cSrcweir // for now, only identity scales allowed
1220cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() &&
1221cdf0e10cSrcweir aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
1222cdf0e10cSrcweir aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
1223cdf0e10cSrcweir {
1224cdf0e10cSrcweir // now intersect dest rect with clip region
1225cdf0e10cSrcweir aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
1226cdf0e10cSrcweir aPosAry.mnDestY,
1227cdf0e10cSrcweir aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
1228cdf0e10cSrcweir aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
1229cdf0e10cSrcweir
1230cdf0e10cSrcweir // Note: I could theoretically optimize away the
1231cdf0e10cSrcweir // DrawBitmap below, if the region is empty
1232cdf0e10cSrcweir // here. Unfortunately, cannot rule out that
1233cdf0e10cSrcweir // somebody relies on the side effects.
1234cdf0e10cSrcweir if( !aClipRegionBounds.IsEmpty() )
1235cdf0e10cSrcweir {
1236cdf0e10cSrcweir aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
1237cdf0e10cSrcweir aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
1238cdf0e10cSrcweir aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
1239cdf0e10cSrcweir aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
1240cdf0e10cSrcweir
1241cdf0e10cSrcweir aPosAry.mnDestX = aClipRegionBounds.Left();
1242cdf0e10cSrcweir aPosAry.mnDestY = aClipRegionBounds.Top();
1243cdf0e10cSrcweir aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
1244cdf0e10cSrcweir aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
1245cdf0e10cSrcweir }
1246cdf0e10cSrcweir }
1247cdf0e10cSrcweir
12485f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp,
1249cdf0e10cSrcweir *pMaskBmp->ImplGetSalBitmap(),
1250cdf0e10cSrcweir this );
12515f27b83cSArmin Le Grand }
1252cdf0e10cSrcweir
1253cdf0e10cSrcweir // #110958# Paint mask to alpha channel. Luckily, the
1254cdf0e10cSrcweir // black and white representation of the mask maps to
1255cdf0e10cSrcweir // the alpha channel
1256cdf0e10cSrcweir
1257cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas
1258cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no
1259cdf0e10cSrcweir // bitmap content was ever visible. Interestingly
1260cdf0e10cSrcweir // enough, this can be achieved by taking the mask as
1261cdf0e10cSrcweir // the transparency mask of itself
1262cdf0e10cSrcweir if( mpAlphaVDev )
1263cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt,
1264cdf0e10cSrcweir rDestSize,
1265cdf0e10cSrcweir BitmapEx( aBmpEx.GetMask(),
1266cdf0e10cSrcweir aBmpEx.GetMask() ) );
1267cdf0e10cSrcweir }
1268cdf0e10cSrcweir else
1269cdf0e10cSrcweir {
12705f27b83cSArmin Le Grand mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, this );
1271cdf0e10cSrcweir
1272cdf0e10cSrcweir if( mpAlphaVDev )
1273cdf0e10cSrcweir {
1274cdf0e10cSrcweir // #i32109#: Make bitmap area opaque
1275cdf0e10cSrcweir mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
1276cdf0e10cSrcweir }
1277cdf0e10cSrcweir }
1278cdf0e10cSrcweir }
1279cdf0e10cSrcweir }
1280cdf0e10cSrcweir }
1281cdf0e10cSrcweir
1282cdf0e10cSrcweir // ------------------------------------------------------------------
1283cdf0e10cSrcweir
DrawMask(const Point & rDestPt,const Bitmap & rBitmap,const Color & rMaskColor)1284cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt,
1285cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor )
1286cdf0e10cSrcweir {
1287cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask()" );
1288cdf0e10cSrcweir
1289cdf0e10cSrcweir if( ImplIsRecordLayout() )
1290cdf0e10cSrcweir return;
1291cdf0e10cSrcweir
1292cdf0e10cSrcweir const Size aSizePix( rBitmap.GetSizePixel() );
1293cdf0e10cSrcweir ImplDrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
1294cdf0e10cSrcweir
1295cdf0e10cSrcweir if( mpAlphaVDev )
1296cdf0e10cSrcweir {
1297cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1298cdf0e10cSrcweir
1299cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas
1300cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no
1301cdf0e10cSrcweir // bitmap content was ever visible. Interestingly
1302cdf0e10cSrcweir // enough, this can be achieved by taking the mask as
1303cdf0e10cSrcweir // the transparency mask of itself
1304cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt,
1305cdf0e10cSrcweir PixelToLogic( aSizePix ),
1306cdf0e10cSrcweir BitmapEx( rMask, rMask ) );
1307cdf0e10cSrcweir }
1308cdf0e10cSrcweir }
1309cdf0e10cSrcweir
1310cdf0e10cSrcweir // ------------------------------------------------------------------
1311cdf0e10cSrcweir
DrawMask(const Point & rDestPt,const Size & rDestSize,const Bitmap & rBitmap,const Color & rMaskColor)1312cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1313cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor )
1314cdf0e10cSrcweir {
1315cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Size )" );
1316cdf0e10cSrcweir
1317cdf0e10cSrcweir if( ImplIsRecordLayout() )
1318cdf0e10cSrcweir return;
1319cdf0e10cSrcweir
1320cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
1321cdf0e10cSrcweir
1322cdf0e10cSrcweir // TODO: Use mask here
1323cdf0e10cSrcweir if( mpAlphaVDev )
1324cdf0e10cSrcweir {
1325cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1326cdf0e10cSrcweir
1327cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas
1328cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no
1329cdf0e10cSrcweir // bitmap content was ever visible. Interestingly
1330cdf0e10cSrcweir // enough, this can be achieved by taking the mask as
1331cdf0e10cSrcweir // the transparency mask of itself
1332cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt,
1333cdf0e10cSrcweir rDestSize,
1334cdf0e10cSrcweir BitmapEx( rMask, rMask ) );
1335cdf0e10cSrcweir }
1336cdf0e10cSrcweir }
1337cdf0e10cSrcweir
1338cdf0e10cSrcweir // ------------------------------------------------------------------
1339cdf0e10cSrcweir
DrawMask(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const Bitmap & rBitmap,const Color & rMaskColor)1340cdf0e10cSrcweir void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
1341cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1342cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor )
1343cdf0e10cSrcweir {
1344cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawMask( Point, Size )" );
1345cdf0e10cSrcweir
1346cdf0e10cSrcweir if( ImplIsRecordLayout() )
1347cdf0e10cSrcweir return;
1348cdf0e10cSrcweir
1349cdf0e10cSrcweir ImplDrawMask( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor, META_MASKSCALEPART_ACTION );
1350cdf0e10cSrcweir
1351cdf0e10cSrcweir // TODO: Use mask here
1352cdf0e10cSrcweir if( mpAlphaVDev )
1353cdf0e10cSrcweir {
1354cdf0e10cSrcweir const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
1355cdf0e10cSrcweir
1356cdf0e10cSrcweir // #i25167# Restrict mask painting to _opaque_ areas
1357cdf0e10cSrcweir // of the mask, otherwise we spoil areas where no
1358cdf0e10cSrcweir // bitmap content was ever visible. Interestingly
1359cdf0e10cSrcweir // enough, this can be achieved by taking the mask as
1360cdf0e10cSrcweir // the transparency mask of itself
1361cdf0e10cSrcweir mpAlphaVDev->DrawBitmapEx( rDestPt,
1362cdf0e10cSrcweir rDestSize,
1363cdf0e10cSrcweir rSrcPtPixel,
1364cdf0e10cSrcweir rSrcSizePixel,
1365cdf0e10cSrcweir BitmapEx( rMask, rMask ) );
1366cdf0e10cSrcweir }
1367cdf0e10cSrcweir }
1368cdf0e10cSrcweir
1369cdf0e10cSrcweir // ------------------------------------------------------------------
1370cdf0e10cSrcweir
ImplDrawMask(const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel,const Bitmap & rBitmap,const Color & rMaskColor,const sal_uLong nAction)1371cdf0e10cSrcweir void OutputDevice::ImplDrawMask( const Point& rDestPt, const Size& rDestSize,
1372cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel,
1373cdf0e10cSrcweir const Bitmap& rBitmap, const Color& rMaskColor,
1374cdf0e10cSrcweir const sal_uLong nAction )
1375cdf0e10cSrcweir {
1376cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1377cdf0e10cSrcweir
1378cdf0e10cSrcweir if( ROP_INVERT == meRasterOp )
1379cdf0e10cSrcweir {
1380cdf0e10cSrcweir DrawRect( Rectangle( rDestPt, rDestSize ) );
1381cdf0e10cSrcweir return;
1382cdf0e10cSrcweir }
1383cdf0e10cSrcweir
1384cdf0e10cSrcweir if ( mpMetaFile )
1385cdf0e10cSrcweir {
1386cdf0e10cSrcweir switch( nAction )
1387cdf0e10cSrcweir {
1388cdf0e10cSrcweir case( META_MASK_ACTION ):
1389cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
1390cdf0e10cSrcweir rBitmap, rMaskColor ) );
1391cdf0e10cSrcweir break;
1392cdf0e10cSrcweir
1393cdf0e10cSrcweir case( META_MASKSCALE_ACTION ):
1394cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
1395cdf0e10cSrcweir rDestSize, rBitmap, rMaskColor ) );
1396cdf0e10cSrcweir break;
1397cdf0e10cSrcweir
1398cdf0e10cSrcweir case( META_MASKSCALEPART_ACTION ):
1399cdf0e10cSrcweir mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
1400cdf0e10cSrcweir rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
1401cdf0e10cSrcweir break;
1402cdf0e10cSrcweir }
1403cdf0e10cSrcweir }
1404cdf0e10cSrcweir
1405cdf0e10cSrcweir OUTDEV_INIT();
1406cdf0e10cSrcweir
1407cdf0e10cSrcweir if ( OUTDEV_PRINTER == meOutDevType )
1408cdf0e10cSrcweir {
1409cdf0e10cSrcweir ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
1410cdf0e10cSrcweir return;
1411cdf0e10cSrcweir }
1412cdf0e10cSrcweir
1413cdf0e10cSrcweir const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
1414cdf0e10cSrcweir if ( pImpBmp )
1415cdf0e10cSrcweir {
14165f27b83cSArmin Le Grand SalTwoRect aPosAry;
1417cdf0e10cSrcweir
1418cdf0e10cSrcweir aPosAry.mnSrcX = rSrcPtPixel.X();
1419cdf0e10cSrcweir aPosAry.mnSrcY = rSrcPtPixel.Y();
1420cdf0e10cSrcweir aPosAry.mnSrcWidth = rSrcSizePixel.Width();
1421cdf0e10cSrcweir aPosAry.mnSrcHeight = rSrcSizePixel.Height();
1422cdf0e10cSrcweir aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
1423cdf0e10cSrcweir aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
1424cdf0e10cSrcweir aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
1425cdf0e10cSrcweir aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
1426cdf0e10cSrcweir
1427cdf0e10cSrcweir // spiegeln via Koordinaten wollen wir nicht
1428cdf0e10cSrcweir const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
1429cdf0e10cSrcweir
1430cdf0e10cSrcweir // check if output is necessary
1431cdf0e10cSrcweir if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
1432cdf0e10cSrcweir {
1433cdf0e10cSrcweir
1434cdf0e10cSrcweir if( nMirrFlags )
1435cdf0e10cSrcweir {
1436cdf0e10cSrcweir Bitmap aTmp( rBitmap );
1437cdf0e10cSrcweir aTmp.Mirror( nMirrFlags );
14385f27b83cSArmin Le Grand mpGraphics->DrawMask( aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
1439cdf0e10cSrcweir ImplColorToSal( rMaskColor ) , this);
1440cdf0e10cSrcweir }
1441cdf0e10cSrcweir else
14425f27b83cSArmin Le Grand mpGraphics->DrawMask( aPosAry, *pImpBmp->ImplGetSalBitmap(),
1443cdf0e10cSrcweir ImplColorToSal( rMaskColor ), this );
1444cdf0e10cSrcweir
1445cdf0e10cSrcweir }
1446cdf0e10cSrcweir }
1447cdf0e10cSrcweir }
1448cdf0e10cSrcweir
1449cdf0e10cSrcweir // ------------------------------------------------------------------
1450cdf0e10cSrcweir
DrawImage(const Point & rPos,const Image & rImage,sal_uInt16 nStyle)1451cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle )
1452cdf0e10cSrcweir {
1453cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1454cdf0e10cSrcweir
1455cdf0e10cSrcweir if( !rImage.mpImplData || ImplIsRecordLayout() )
1456cdf0e10cSrcweir return;
1457cdf0e10cSrcweir
1458cdf0e10cSrcweir switch( rImage.mpImplData->meType )
1459cdf0e10cSrcweir {
1460cdf0e10cSrcweir case IMAGETYPE_BITMAP:
1461cdf0e10cSrcweir DrawBitmap( rPos, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) );
1462cdf0e10cSrcweir break;
1463cdf0e10cSrcweir
1464cdf0e10cSrcweir case IMAGETYPE_IMAGE:
1465cdf0e10cSrcweir {
1466cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1467cdf0e10cSrcweir
1468cdf0e10cSrcweir if( !pData->mpImageBitmap )
1469cdf0e10cSrcweir {
1470cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() );
1471cdf0e10cSrcweir
1472cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp;
1473cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1474cdf0e10cSrcweir }
1475cdf0e10cSrcweir
1476cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
1477cdf0e10cSrcweir }
1478cdf0e10cSrcweir break;
1479cdf0e10cSrcweir
1480cdf0e10cSrcweir default:
1481cdf0e10cSrcweir break;
1482cdf0e10cSrcweir }
1483cdf0e10cSrcweir }
1484cdf0e10cSrcweir
1485cdf0e10cSrcweir // ------------------------------------------------------------------
1486cdf0e10cSrcweir
DrawImage(const Point & rPos,const Size & rSize,const Image & rImage,sal_uInt16 nStyle)1487cdf0e10cSrcweir void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
1488cdf0e10cSrcweir const Image& rImage, sal_uInt16 nStyle )
1489cdf0e10cSrcweir {
1490cdf0e10cSrcweir DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
1491cdf0e10cSrcweir
1492cdf0e10cSrcweir if( rImage.mpImplData && !ImplIsRecordLayout() )
1493cdf0e10cSrcweir {
1494cdf0e10cSrcweir switch( rImage.mpImplData->meType )
1495cdf0e10cSrcweir {
1496cdf0e10cSrcweir case IMAGETYPE_BITMAP:
1497cdf0e10cSrcweir DrawBitmap( rPos, rSize, *static_cast< Bitmap* >( rImage.mpImplData->mpData ) );
1498cdf0e10cSrcweir break;
1499cdf0e10cSrcweir
1500cdf0e10cSrcweir case IMAGETYPE_IMAGE:
1501cdf0e10cSrcweir {
1502cdf0e10cSrcweir ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
1503cdf0e10cSrcweir
1504cdf0e10cSrcweir if ( !pData->mpImageBitmap )
1505cdf0e10cSrcweir {
1506cdf0e10cSrcweir const Size aSize( pData->maBmpEx.GetSizePixel() );
1507cdf0e10cSrcweir
1508cdf0e10cSrcweir pData->mpImageBitmap = new ImplImageBmp;
1509cdf0e10cSrcweir pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
1510cdf0e10cSrcweir }
1511cdf0e10cSrcweir
1512cdf0e10cSrcweir pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
1513cdf0e10cSrcweir }
1514cdf0e10cSrcweir break;
1515cdf0e10cSrcweir
1516cdf0e10cSrcweir default:
1517cdf0e10cSrcweir break;
1518cdf0e10cSrcweir }
1519cdf0e10cSrcweir }
1520cdf0e10cSrcweir }
1521cdf0e10cSrcweir
1522cdf0e10cSrcweir // ------------------------------------------------------------------
1523cdf0e10cSrcweir
GetBitmap(const Point & rSrcPt,const Size & rSize) const1524cdf0e10cSrcweir Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
1525cdf0e10cSrcweir {
1526cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1527*1d625a01SJohn Bampton OSL_ENSURE(OUTDEV_PRINTER != GetOutDevType(), "OutputDevice::GetBitmap with source type OUTDEV_PRINTER should not be used (!)");
1528cdf0e10cSrcweir
1529cdf0e10cSrcweir Bitmap aBmp;
1530cdf0e10cSrcweir long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
1531cdf0e10cSrcweir long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
1532cdf0e10cSrcweir long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
1533cdf0e10cSrcweir long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
1534cdf0e10cSrcweir
1535cdf0e10cSrcweir if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
1536cdf0e10cSrcweir {
1537ff0f521cSArmin Le Grand if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
1538cdf0e10cSrcweir {
1539cdf0e10cSrcweir Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
1540cdf0e10cSrcweir sal_Bool bClipped = sal_False;
1541cdf0e10cSrcweir
1542cdf0e10cSrcweir // X-Koordinate ausserhalb des Bereichs?
1543cdf0e10cSrcweir if ( nX < mnOutOffX )
1544cdf0e10cSrcweir {
1545cdf0e10cSrcweir nWidth -= ( mnOutOffX - nX );
1546cdf0e10cSrcweir nX = mnOutOffX;
1547cdf0e10cSrcweir bClipped = sal_True;
1548cdf0e10cSrcweir }
1549cdf0e10cSrcweir
1550cdf0e10cSrcweir // Y-Koordinate ausserhalb des Bereichs?
1551cdf0e10cSrcweir if ( nY < mnOutOffY )
1552cdf0e10cSrcweir {
1553cdf0e10cSrcweir nHeight -= ( mnOutOffY - nY );
1554cdf0e10cSrcweir nY = mnOutOffY;
1555cdf0e10cSrcweir bClipped = sal_True;
1556cdf0e10cSrcweir }
1557cdf0e10cSrcweir
1558cdf0e10cSrcweir // Breite ausserhalb des Bereichs?
1559cdf0e10cSrcweir if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
1560cdf0e10cSrcweir {
1561cdf0e10cSrcweir nWidth = mnOutOffX + mnOutWidth - nX;
1562cdf0e10cSrcweir bClipped = sal_True;
1563cdf0e10cSrcweir }
1564cdf0e10cSrcweir
1565cdf0e10cSrcweir // Hoehe ausserhalb des Bereichs?
1566cdf0e10cSrcweir if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
1567cdf0e10cSrcweir {
1568cdf0e10cSrcweir nHeight = mnOutOffY + mnOutHeight - nY;
1569cdf0e10cSrcweir bClipped = sal_True;
1570cdf0e10cSrcweir }
1571cdf0e10cSrcweir
1572cdf0e10cSrcweir if ( bClipped )
1573cdf0e10cSrcweir {
1574cdf0e10cSrcweir // Falls auf den sichtbaren Bereich geclipped wurde,
1575cdf0e10cSrcweir // muessen wir eine Bitmap in der rchtigen Groesse
1576cdf0e10cSrcweir // erzeugen, in die die geclippte Bitmap an die angepasste
1577cdf0e10cSrcweir // Position kopiert wird
1578cdf0e10cSrcweir VirtualDevice aVDev( *this );
1579cdf0e10cSrcweir
1580cdf0e10cSrcweir if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
1581cdf0e10cSrcweir {
1582cdf0e10cSrcweir if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
1583cdf0e10cSrcweir {
15845f27b83cSArmin Le Grand SalTwoRect aPosAry;
1585cdf0e10cSrcweir
1586cdf0e10cSrcweir aPosAry.mnSrcX = nX;
1587cdf0e10cSrcweir aPosAry.mnSrcY = nY;
1588cdf0e10cSrcweir aPosAry.mnSrcWidth = nWidth;
1589cdf0e10cSrcweir aPosAry.mnSrcHeight = nHeight;
1590cdf0e10cSrcweir aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
1591cdf0e10cSrcweir aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
1592cdf0e10cSrcweir aPosAry.mnDestWidth = nWidth;
1593cdf0e10cSrcweir aPosAry.mnDestHeight = nHeight;
1594cdf0e10cSrcweir
1595cdf0e10cSrcweir if ( (nWidth > 0) && (nHeight > 0) )
1596ff0f521cSArmin Le Grand {
15975f27b83cSArmin Le Grand (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this );
1598ff0f521cSArmin Le Grand }
1599ff0f521cSArmin Le Grand else
1600ff0f521cSArmin Le Grand {
1601ff0f521cSArmin Le Grand OSL_ENSURE(false, "CopyBits with negative width or height (!)");
1602ff0f521cSArmin Le Grand }
1603cdf0e10cSrcweir
1604cdf0e10cSrcweir aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir else
1607cdf0e10cSrcweir bClipped = sal_False;
1608cdf0e10cSrcweir }
1609cdf0e10cSrcweir else
1610cdf0e10cSrcweir bClipped = sal_False;
1611cdf0e10cSrcweir }
1612cdf0e10cSrcweir
1613cdf0e10cSrcweir if ( !bClipped )
1614cdf0e10cSrcweir {
1615cdf0e10cSrcweir SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
1616cdf0e10cSrcweir
1617cdf0e10cSrcweir if( pSalBmp )
1618cdf0e10cSrcweir {
1619cdf0e10cSrcweir ImpBitmap* pImpBmp = new ImpBitmap;
1620cdf0e10cSrcweir pImpBmp->ImplSetSalBitmap( pSalBmp );
1621cdf0e10cSrcweir aBmp.ImplSetImpBitmap( pImpBmp );
1622cdf0e10cSrcweir }
1623cdf0e10cSrcweir }
1624cdf0e10cSrcweir }
1625cdf0e10cSrcweir }
1626cdf0e10cSrcweir
1627cdf0e10cSrcweir return aBmp;
1628cdf0e10cSrcweir }
1629cdf0e10cSrcweir
1630cdf0e10cSrcweir // ------------------------------------------------------------------
1631cdf0e10cSrcweir
GetBitmapEx(const Point & rSrcPt,const Size & rSize) const1632cdf0e10cSrcweir BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
1633cdf0e10cSrcweir {
1634cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1635cdf0e10cSrcweir
1636cdf0e10cSrcweir // #110958# Extract alpha value from VDev, if any
1637cdf0e10cSrcweir if( mpAlphaVDev )
1638cdf0e10cSrcweir {
1639cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
1640cdf0e10cSrcweir
1641cdf0e10cSrcweir // ensure 8 bit alpha
1642cdf0e10cSrcweir if( aAlphaBitmap.GetBitCount() > 8 )
1643cdf0e10cSrcweir aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
1644cdf0e10cSrcweir
1645cdf0e10cSrcweir return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
1646cdf0e10cSrcweir }
1647cdf0e10cSrcweir else
1648cdf0e10cSrcweir return GetBitmap( rSrcPt, rSize );
1649cdf0e10cSrcweir }
1650cdf0e10cSrcweir
1651cdf0e10cSrcweir // ------------------------------------------------------------------
1652cdf0e10cSrcweir
ImplGetFrameBitmap(const Point & rDestPt,const Size & rSize,Bitmap & rBitmap) const1653cdf0e10cSrcweir void OutputDevice::ImplGetFrameBitmap( const Point& rDestPt, const Size& rSize,
1654cdf0e10cSrcweir Bitmap& rBitmap ) const
1655cdf0e10cSrcweir {
1656cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1657cdf0e10cSrcweir
1658cdf0e10cSrcweir sal_Bool bOldMap = mbMap;
1659cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = sal_False;
1660cdf0e10cSrcweir rBitmap = GetBitmap( rDestPt, rSize );
1661cdf0e10cSrcweir ((OutputDevice*)this)->mbMap = bOldMap;
1662cdf0e10cSrcweir }
1663cdf0e10cSrcweir
1664cdf0e10cSrcweir // ------------------------------------------------------------------
1665cdf0e10cSrcweir
GetPixel(const Point & rPt) const1666cdf0e10cSrcweir Color OutputDevice::GetPixel( const Point& rPt ) const
1667cdf0e10cSrcweir {
1668cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1669cdf0e10cSrcweir
1670cdf0e10cSrcweir Color aColor;
1671cdf0e10cSrcweir
1672cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
1673cdf0e10cSrcweir {
1674cdf0e10cSrcweir if ( mbInitClipRegion )
1675cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion();
1676cdf0e10cSrcweir
1677cdf0e10cSrcweir if ( !mbOutputClipped )
1678cdf0e10cSrcweir {
1679cdf0e10cSrcweir const long nX = ImplLogicXToDevicePixel( rPt.X() );
1680cdf0e10cSrcweir const long nY = ImplLogicYToDevicePixel( rPt.Y() );
1681cdf0e10cSrcweir const SalColor aSalCol = mpGraphics->GetPixel( nX, nY, this );
1682cdf0e10cSrcweir aColor.SetRed( SALCOLOR_RED( aSalCol ) );
1683cdf0e10cSrcweir aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
1684cdf0e10cSrcweir aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
1685cdf0e10cSrcweir }
1686cdf0e10cSrcweir }
1687cdf0e10cSrcweir return aColor;
1688cdf0e10cSrcweir }
1689cdf0e10cSrcweir
1690cdf0e10cSrcweir // ------------------------------------------------------------------
1691cdf0e10cSrcweir
GetPixel(const Polygon & rPts) const1692cdf0e10cSrcweir Color* OutputDevice::GetPixel( const Polygon& rPts ) const
1693cdf0e10cSrcweir {
1694cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1695cdf0e10cSrcweir
1696cdf0e10cSrcweir Color* pColors = NULL;
1697cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize();
1698cdf0e10cSrcweir
1699cdf0e10cSrcweir if( nSize )
1700cdf0e10cSrcweir {
1701cdf0e10cSrcweir if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
1702cdf0e10cSrcweir {
1703cdf0e10cSrcweir if ( mbInitClipRegion )
1704cdf0e10cSrcweir ((OutputDevice*)this)->ImplInitClipRegion();
1705cdf0e10cSrcweir
1706cdf0e10cSrcweir if ( !mbOutputClipped )
1707cdf0e10cSrcweir {
1708cdf0e10cSrcweir pColors = new Color[ nSize ];
1709cdf0e10cSrcweir
1710cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ )
1711cdf0e10cSrcweir {
1712cdf0e10cSrcweir Color& rCol = pColors[ i ];
1713cdf0e10cSrcweir const Point& rPt = rPts[ i ];
1714cdf0e10cSrcweir const SalColor aSalCol( mpGraphics->GetPixel( ImplLogicXToDevicePixel( rPt.X() ),
1715cdf0e10cSrcweir ImplLogicYToDevicePixel( rPt.Y() ) , this) );
1716cdf0e10cSrcweir
1717cdf0e10cSrcweir rCol.SetRed( SALCOLOR_RED( aSalCol ) );
1718cdf0e10cSrcweir rCol.SetGreen( SALCOLOR_GREEN( aSalCol ) );
1719cdf0e10cSrcweir rCol.SetBlue( SALCOLOR_BLUE( aSalCol ) );
1720cdf0e10cSrcweir }
1721cdf0e10cSrcweir }
1722cdf0e10cSrcweir }
1723cdf0e10cSrcweir }
1724cdf0e10cSrcweir
1725cdf0e10cSrcweir return pColors;
1726cdf0e10cSrcweir }
1727cdf0e10cSrcweir
1728cdf0e10cSrcweir // -----------------------------------------------------------------------
1729cdf0e10cSrcweir
DrawPixel(const Point & rPt)1730cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt )
1731cdf0e10cSrcweir {
1732cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" );
1733cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1734cdf0e10cSrcweir
1735cdf0e10cSrcweir if ( mpMetaFile )
1736cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPointAction( rPt ) );
1737cdf0e10cSrcweir
1738cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
1739cdf0e10cSrcweir return;
1740cdf0e10cSrcweir
1741cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt );
1742cdf0e10cSrcweir
1743cdf0e10cSrcweir // we need a graphics
1744cdf0e10cSrcweir if ( !mpGraphics )
1745cdf0e10cSrcweir {
1746cdf0e10cSrcweir if ( !ImplGetGraphics() )
1747cdf0e10cSrcweir return;
1748cdf0e10cSrcweir }
1749cdf0e10cSrcweir
1750cdf0e10cSrcweir if ( mbInitClipRegion )
1751cdf0e10cSrcweir ImplInitClipRegion();
1752cdf0e10cSrcweir if ( mbOutputClipped )
1753cdf0e10cSrcweir return;
1754cdf0e10cSrcweir
1755cdf0e10cSrcweir if ( mbInitLineColor )
1756cdf0e10cSrcweir ImplInitLineColor();
1757cdf0e10cSrcweir
1758cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this );
1759cdf0e10cSrcweir
1760cdf0e10cSrcweir if( mpAlphaVDev )
1761cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt );
1762cdf0e10cSrcweir }
1763cdf0e10cSrcweir
1764cdf0e10cSrcweir // -----------------------------------------------------------------------
1765cdf0e10cSrcweir
DrawPixel(const Point & rPt,const Color & rColor)1766cdf0e10cSrcweir void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
1767cdf0e10cSrcweir {
1768cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" );
1769cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1770cdf0e10cSrcweir
1771cdf0e10cSrcweir Color aColor( rColor );
1772cdf0e10cSrcweir
1773cdf0e10cSrcweir if( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
1774cdf0e10cSrcweir DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE |
1775cdf0e10cSrcweir DRAWMODE_SETTINGSLINE ) )
1776cdf0e10cSrcweir {
1777cdf0e10cSrcweir if( !ImplIsColorTransparent( aColor ) )
1778cdf0e10cSrcweir {
1779cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_BLACKLINE )
1780cdf0e10cSrcweir {
1781cdf0e10cSrcweir aColor = Color( COL_BLACK );
1782cdf0e10cSrcweir }
1783cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_WHITELINE )
1784cdf0e10cSrcweir {
1785cdf0e10cSrcweir aColor = Color( COL_WHITE );
1786cdf0e10cSrcweir }
1787cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_GRAYLINE )
1788cdf0e10cSrcweir {
1789cdf0e10cSrcweir const sal_uInt8 cLum = aColor.GetLuminance();
1790cdf0e10cSrcweir aColor = Color( cLum, cLum, cLum );
1791cdf0e10cSrcweir }
1792cdf0e10cSrcweir else if( mnDrawMode & DRAWMODE_SETTINGSLINE )
1793cdf0e10cSrcweir {
1794cdf0e10cSrcweir aColor = GetSettings().GetStyleSettings().GetFontColor();
1795cdf0e10cSrcweir }
1796cdf0e10cSrcweir
1797cdf0e10cSrcweir if( mnDrawMode & DRAWMODE_GHOSTEDLINE )
1798cdf0e10cSrcweir {
1799cdf0e10cSrcweir aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
1800cdf0e10cSrcweir ( aColor.GetGreen() >> 1 ) | 0x80,
1801cdf0e10cSrcweir ( aColor.GetBlue() >> 1 ) | 0x80 );
1802cdf0e10cSrcweir }
1803cdf0e10cSrcweir }
1804cdf0e10cSrcweir }
1805cdf0e10cSrcweir
1806cdf0e10cSrcweir if ( mpMetaFile )
1807cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
1808cdf0e10cSrcweir
1809cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() )
1810cdf0e10cSrcweir return;
1811cdf0e10cSrcweir
1812cdf0e10cSrcweir Point aPt = ImplLogicToDevicePixel( rPt );
1813cdf0e10cSrcweir
1814cdf0e10cSrcweir // we need a graphics
1815cdf0e10cSrcweir if ( !mpGraphics )
1816cdf0e10cSrcweir {
1817cdf0e10cSrcweir if ( !ImplGetGraphics() )
1818cdf0e10cSrcweir return;
1819cdf0e10cSrcweir }
1820cdf0e10cSrcweir
1821cdf0e10cSrcweir if ( mbInitClipRegion )
1822cdf0e10cSrcweir ImplInitClipRegion();
1823cdf0e10cSrcweir if ( mbOutputClipped )
1824cdf0e10cSrcweir return;
1825cdf0e10cSrcweir
1826cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this );
1827cdf0e10cSrcweir
1828cdf0e10cSrcweir if( mpAlphaVDev )
1829cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPt );
1830cdf0e10cSrcweir }
1831cdf0e10cSrcweir
1832cdf0e10cSrcweir // -----------------------------------------------------------------------
1833cdf0e10cSrcweir
DrawPixel(const Polygon & rPts,const Color * pColors)1834cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
1835cdf0e10cSrcweir {
1836cdf0e10cSrcweir if ( !pColors )
1837cdf0e10cSrcweir DrawPixel( rPts, GetLineColor() );
1838cdf0e10cSrcweir else
1839cdf0e10cSrcweir {
1840cdf0e10cSrcweir DBG_TRACE( "OutputDevice::DrawPixel()" );
1841cdf0e10cSrcweir DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1842cdf0e10cSrcweir DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
1843cdf0e10cSrcweir
1844cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize();
1845cdf0e10cSrcweir
1846cdf0e10cSrcweir if ( nSize )
1847cdf0e10cSrcweir {
1848cdf0e10cSrcweir if ( mpMetaFile )
1849cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ )
1850cdf0e10cSrcweir mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
1851cdf0e10cSrcweir
1852cdf0e10cSrcweir if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
1853cdf0e10cSrcweir return;
1854cdf0e10cSrcweir
1855cdf0e10cSrcweir // we need a graphics
1856cdf0e10cSrcweir if ( mpGraphics || ImplGetGraphics() )
1857cdf0e10cSrcweir {
1858cdf0e10cSrcweir if ( mbInitClipRegion )
1859cdf0e10cSrcweir ImplInitClipRegion();
1860cdf0e10cSrcweir
1861cdf0e10cSrcweir if ( mbOutputClipped )
1862cdf0e10cSrcweir return;
1863cdf0e10cSrcweir
1864cdf0e10cSrcweir for ( sal_uInt16 i = 0; i < nSize; i++ )
1865cdf0e10cSrcweir {
1866cdf0e10cSrcweir const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
1867cdf0e10cSrcweir mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this );
1868cdf0e10cSrcweir }
1869cdf0e10cSrcweir }
1870cdf0e10cSrcweir }
1871cdf0e10cSrcweir }
1872cdf0e10cSrcweir
1873cdf0e10cSrcweir if( mpAlphaVDev )
1874cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, pColors );
1875cdf0e10cSrcweir }
1876cdf0e10cSrcweir
1877cdf0e10cSrcweir // -----------------------------------------------------------------------
1878cdf0e10cSrcweir
DrawPixel(const Polygon & rPts,const Color & rColor)1879cdf0e10cSrcweir void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
1880cdf0e10cSrcweir {
1881cdf0e10cSrcweir if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() )
1882cdf0e10cSrcweir {
1883cdf0e10cSrcweir const sal_uInt16 nSize = rPts.GetSize();
1884cdf0e10cSrcweir Color* pColArray = new Color[ nSize ];
1885cdf0e10cSrcweir
1886cdf0e10cSrcweir for( sal_uInt16 i = 0; i < nSize; i++ )
1887cdf0e10cSrcweir pColArray[ i ] = rColor;
1888cdf0e10cSrcweir
1889cdf0e10cSrcweir DrawPixel( rPts, pColArray );
1890cdf0e10cSrcweir delete[] pColArray;
1891cdf0e10cSrcweir }
1892cdf0e10cSrcweir
1893cdf0e10cSrcweir if( mpAlphaVDev )
1894cdf0e10cSrcweir mpAlphaVDev->DrawPixel( rPts, rColor );
1895cdf0e10cSrcweir }
1896cdf0e10cSrcweir
1897cdf0e10cSrcweir // ------------------------------------------------------------------------
1898cdf0e10cSrcweir
1899cdf0e10cSrcweir namespace
1900cdf0e10cSrcweir {
lcl_calcColor(const sal_uInt8 nSourceColor,const sal_uInt8 nSourceOpaq,const sal_uInt8 nDestColor)1901cdf0e10cSrcweir sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceOpaq, const sal_uInt8 nDestColor )
1902cdf0e10cSrcweir {
1903cdf0e10cSrcweir int c = ( (int)nDestColor * ( 255 - nSourceOpaq ) )
1904cdf0e10cSrcweir + (int)nSourceOpaq * (int)nSourceColor;
1905cdf0e10cSrcweir return sal_uInt8( c / 255 );
1906cdf0e10cSrcweir }
1907cdf0e10cSrcweir }
1908cdf0e10cSrcweir
1909cdf0e10cSrcweir // ------------------------------------------------------------------------
1910cdf0e10cSrcweir
ImplBlendWithAlpha(Bitmap aBmp,BitmapReadAccess * pP,BitmapReadAccess * pA,const Rectangle & aDstRect,const sal_Int32 nOffY,const sal_Int32 nDstHeight,const sal_Int32 nOffX,const sal_Int32 nDstWidth,const long * pMapX,const long * pMapY)1911cdf0e10cSrcweir Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp,
1912cdf0e10cSrcweir BitmapReadAccess* pP,
1913cdf0e10cSrcweir BitmapReadAccess* pA,
1914cdf0e10cSrcweir const Rectangle& aDstRect,
1915cdf0e10cSrcweir const sal_Int32 nOffY,
1916cdf0e10cSrcweir const sal_Int32 nDstHeight,
1917cdf0e10cSrcweir const sal_Int32 nOffX,
1918cdf0e10cSrcweir const sal_Int32 nDstWidth,
1919cdf0e10cSrcweir const long* pMapX,
1920cdf0e10cSrcweir const long* pMapY )
1921cdf0e10cSrcweir {
1922cdf0e10cSrcweir BitmapColor aDstCol,aSrcCol;
1923cdf0e10cSrcweir Bitmap res;
1924cdf0e10cSrcweir int nX, nOutX, nY, nOutY;
1925cdf0e10cSrcweir
1926cdf0e10cSrcweir OSL_ENSURE(mpAlphaVDev,
1927cdf0e10cSrcweir "ImplBlendWithAlpha(): call me only with valid alpha VDev!" );
1928cdf0e10cSrcweir
1929cdf0e10cSrcweir sal_Bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
1930cdf0e10cSrcweir mpAlphaVDev->EnableMapMode(sal_False);
1931cdf0e10cSrcweir
1932cdf0e10cSrcweir Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
1933cdf0e10cSrcweir BitmapWriteAccess* pAlphaW = aAlphaBitmap.AcquireWriteAccess();
1934cdf0e10cSrcweir
1935cdf0e10cSrcweir if( GetBitCount() <= 8 )
1936cdf0e10cSrcweir {
1937cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 );
1938cdf0e10cSrcweir BitmapColor aIndex( 0 );
1939cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess();
1940cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
1941cdf0e10cSrcweir
1942cdf0e10cSrcweir if( pB && pP && pA && pW && pAlphaW )
1943cdf0e10cSrcweir {
1944cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
1945cdf0e10cSrcweir {
1946cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
1947cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L;
1948cdf0e10cSrcweir
1949cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
1950cdf0e10cSrcweir {
1951cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
1952cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
1953cdf0e10cSrcweir
1954cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX );
1955cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX );
195687bc88d3SHerbert Dürr const sal_uInt8 nSrcOpaq = 255 - pA->GetPixelIndex( nMapY, nMapX );
195787bc88d3SHerbert Dürr const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixelIndex( nY, nX );
1958cdf0e10cSrcweir
1959cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) );
1960cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) );
1961cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) );
1962cdf0e10cSrcweir
1963cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
1964cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
1965cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
1966cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex );
1967cdf0e10cSrcweir
1968cdf0e10cSrcweir // Have to perform the compositing 'algebra' in
1969cdf0e10cSrcweir // the inverse alpha space (with 255 meaning
1970cdf0e10cSrcweir // opaque), otherwise, transitivity is not
1971cdf0e10cSrcweir // achieved.
1972cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq );
1973cdf0e10cSrcweir
1974cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] +
1975cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] +
1976cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ nSrcAlpha ] + nD ) >> 16UL ] ) );
1977cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, aIndex );
1978cdf0e10cSrcweir }
1979cdf0e10cSrcweir }
1980cdf0e10cSrcweir }
1981cdf0e10cSrcweir
1982cdf0e10cSrcweir aBmp.ReleaseAccess( pB );
1983cdf0e10cSrcweir aDither.ReleaseAccess( pW );
1984cdf0e10cSrcweir res = aDither;
1985cdf0e10cSrcweir }
1986cdf0e10cSrcweir else
1987cdf0e10cSrcweir {
1988cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
1989cdf0e10cSrcweir if( pP && pA && pB )
1990cdf0e10cSrcweir {
1991cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ )
1992cdf0e10cSrcweir {
1993cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
1994cdf0e10cSrcweir
1995cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ )
1996cdf0e10cSrcweir {
1997cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
1998cdf0e10cSrcweir
1999cdf0e10cSrcweir aSrcCol = pP->GetColor( nMapY, nMapX );
2000cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX );
200187bc88d3SHerbert Dürr const sal_uInt8 nSrcOpaq = 255 - pA->GetPixelIndex( nMapY, nMapX );
200287bc88d3SHerbert Dürr const sal_uInt8 nDstOpaq = 255 - pAlphaW->GetPixelIndex( nY, nX );
2003cdf0e10cSrcweir
2004cdf0e10cSrcweir aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcOpaq, aDstCol.GetRed() ) );
2005cdf0e10cSrcweir aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcOpaq, aDstCol.GetBlue() ) );
2006cdf0e10cSrcweir aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcOpaq, aDstCol.GetGreen() ) );
2007cdf0e10cSrcweir
2008cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol );
2009cdf0e10cSrcweir
2010cdf0e10cSrcweir // Have to perform the compositing 'algebra' in
2011cdf0e10cSrcweir // the inverse alpha space (with 255 meaning
2012cdf0e10cSrcweir // opaque), otherwise, transitivity is not
2013cdf0e10cSrcweir // achieved.
2014cdf0e10cSrcweir const sal_uInt8 nSrcAlpha = 255-COLOR_CHANNEL_MERGE( 255, (sal_uInt8)nDstOpaq, nSrcOpaq );
2015cdf0e10cSrcweir
2016cdf0e10cSrcweir pAlphaW->SetPixel( nY, nX, Color(nSrcAlpha, nSrcAlpha, nSrcAlpha) );
2017cdf0e10cSrcweir }
2018cdf0e10cSrcweir }
2019cdf0e10cSrcweir }
2020cdf0e10cSrcweir
2021cdf0e10cSrcweir aBmp.ReleaseAccess( pB );
2022cdf0e10cSrcweir res = aBmp;
2023cdf0e10cSrcweir }
2024cdf0e10cSrcweir
2025cdf0e10cSrcweir aAlphaBitmap.ReleaseAccess( pAlphaW );
2026cdf0e10cSrcweir mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
2027cdf0e10cSrcweir mpAlphaVDev->EnableMapMode( bOldMapMode );
2028cdf0e10cSrcweir
2029cdf0e10cSrcweir return res;
2030cdf0e10cSrcweir }
2031cdf0e10cSrcweir
2032cdf0e10cSrcweir // ------------------------------------------------------------------------
2033cdf0e10cSrcweir
ImplBlend(Bitmap aBmp,BitmapReadAccess * pP,BitmapReadAccess * pA,const sal_Int32 nOffY,const sal_Int32 nDstHeight,const sal_Int32 nOffX,const sal_Int32 nDstWidth,const Rectangle & aBmpRect,const Size & aOutSz,const bool bHMirr,const bool bVMirr,const long * pMapX,const long * pMapY)2034cdf0e10cSrcweir Bitmap OutputDevice::ImplBlend( Bitmap aBmp,
2035cdf0e10cSrcweir BitmapReadAccess* pP,
2036cdf0e10cSrcweir BitmapReadAccess* pA,
2037cdf0e10cSrcweir const sal_Int32 nOffY,
2038cdf0e10cSrcweir const sal_Int32 nDstHeight,
2039cdf0e10cSrcweir const sal_Int32 nOffX,
2040cdf0e10cSrcweir const sal_Int32 nDstWidth,
2041cdf0e10cSrcweir const Rectangle& aBmpRect,
2042cdf0e10cSrcweir const Size& aOutSz,
2043cdf0e10cSrcweir const bool bHMirr,
2044cdf0e10cSrcweir const bool bVMirr,
2045cdf0e10cSrcweir const long* pMapX,
2046cdf0e10cSrcweir const long* pMapY )
2047cdf0e10cSrcweir {
2048cdf0e10cSrcweir BitmapColor aDstCol;
2049cdf0e10cSrcweir Bitmap res;
2050cdf0e10cSrcweir int nX, nOutX, nY, nOutY;
2051cdf0e10cSrcweir
2052cdf0e10cSrcweir if( GetBitCount() <= 8 )
2053cdf0e10cSrcweir {
2054cdf0e10cSrcweir Bitmap aDither( aBmp.GetSizePixel(), 8 );
2055cdf0e10cSrcweir BitmapColor aIndex( 0 );
2056cdf0e10cSrcweir BitmapReadAccess* pB = aBmp.AcquireReadAccess();
2057cdf0e10cSrcweir BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
2058cdf0e10cSrcweir
2059cdf0e10cSrcweir if( pB && pP && pA && pW )
2060cdf0e10cSrcweir {
2061cdf0e10cSrcweir for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
2062cdf0e10cSrcweir {
2063cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
2064cdf0e10cSrcweir const long nModY = ( nOutY & 0x0FL ) << 4L;
2065cdf0e10cSrcweir
2066cdf0e10cSrcweir for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
2067cdf0e10cSrcweir {
2068cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
2069cdf0e10cSrcweir const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
2070cdf0e10cSrcweir
2071cdf0e10cSrcweir aDstCol = pB->GetColor( nY, nX );
207287bc88d3SHerbert Dürr aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pA->GetPixelIndex( nMapY, nMapX ) );
2073cdf0e10cSrcweir aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
2074cdf0e10cSrcweir nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
2075cdf0e10cSrcweir nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
2076cdf0e10cSrcweir pW->SetPixel( nY, nX, aIndex );
2077cdf0e10cSrcweir }
2078cdf0e10cSrcweir }
2079cdf0e10cSrcweir }
2080cdf0e10cSrcweir
2081cdf0e10cSrcweir aBmp.ReleaseAccess( pB );
2082cdf0e10cSrcweir aDither.ReleaseAccess( pW );
2083cdf0e10cSrcweir res = aDither;
2084cdf0e10cSrcweir }
2085cdf0e10cSrcweir else
2086cdf0e10cSrcweir {
2087cdf0e10cSrcweir BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
2088cdf0e10cSrcweir
2089cdf0e10cSrcweir bool bFastBlend = false;
2090cdf0e10cSrcweir if( pP && pA && pB )
2091cdf0e10cSrcweir {
2092cdf0e10cSrcweir SalTwoRect aTR;
2093cdf0e10cSrcweir aTR.mnSrcX = aBmpRect.Left();
2094cdf0e10cSrcweir aTR.mnSrcY = aBmpRect.Top();
2095cdf0e10cSrcweir aTR.mnSrcWidth = aBmpRect.GetWidth();
2096cdf0e10cSrcweir aTR.mnSrcHeight = aBmpRect.GetHeight();
2097cdf0e10cSrcweir aTR.mnDestX = nOffX;
2098cdf0e10cSrcweir aTR.mnDestY = nOffY;
2099cdf0e10cSrcweir aTR.mnDestWidth = aOutSz.Width();
2100cdf0e10cSrcweir aTR.mnDestHeight= aOutSz.Height();
2101cdf0e10cSrcweir
2102cdf0e10cSrcweir if( !bHMirr || !bVMirr )
2103cdf0e10cSrcweir bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
2104cdf0e10cSrcweir }
2105cdf0e10cSrcweir
2106cdf0e10cSrcweir if( pP && pA && pB && !bFastBlend )
2107cdf0e10cSrcweir {
2108cdf0e10cSrcweir switch( pP->GetScanlineFormat() )
2109cdf0e10cSrcweir {
2110cdf0e10cSrcweir case( BMP_FORMAT_8BIT_PAL ):
2111cdf0e10cSrcweir {
2112cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ )
2113cdf0e10cSrcweir {
2114cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
2115cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY );
2116cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY );
2117cdf0e10cSrcweir
2118cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ )
2119cdf0e10cSrcweir {
2120cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
2121cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX );
2122cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
2123cdf0e10cSrcweir pAScan[ nMapX ] ) );
2124cdf0e10cSrcweir }
2125cdf0e10cSrcweir }
2126cdf0e10cSrcweir }
2127cdf0e10cSrcweir break;
2128cdf0e10cSrcweir
2129cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_BGR ):
2130cdf0e10cSrcweir {
2131cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ )
2132cdf0e10cSrcweir {
2133cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
2134cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY );
2135cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY );
2136cdf0e10cSrcweir
2137cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ )
2138cdf0e10cSrcweir {
2139cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
2140cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3;
2141cdf0e10cSrcweir
2142cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX );
2143cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
2144cdf0e10cSrcweir pAScan[ nMapX ] ) );
2145cdf0e10cSrcweir }
2146cdf0e10cSrcweir }
2147cdf0e10cSrcweir }
2148cdf0e10cSrcweir break;
2149cdf0e10cSrcweir
2150cdf0e10cSrcweir case( BMP_FORMAT_24BIT_TC_RGB ):
2151cdf0e10cSrcweir {
2152cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ )
2153cdf0e10cSrcweir {
2154cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
2155cdf0e10cSrcweir Scanline pPScan = pP->GetScanline( nMapY );
2156cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY );
2157cdf0e10cSrcweir
2158cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ )
2159cdf0e10cSrcweir {
2160cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
2161cdf0e10cSrcweir Scanline pTmp = pPScan + nMapX * 3;
2162cdf0e10cSrcweir
2163cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX );
2164cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
2165cdf0e10cSrcweir pAScan[ nMapX ] ) );
2166cdf0e10cSrcweir }
2167cdf0e10cSrcweir }
2168cdf0e10cSrcweir }
2169cdf0e10cSrcweir break;
2170cdf0e10cSrcweir
2171cdf0e10cSrcweir default:
2172cdf0e10cSrcweir {
2173cdf0e10cSrcweir for( nY = 0; nY < nDstHeight; nY++ )
2174cdf0e10cSrcweir {
2175cdf0e10cSrcweir const long nMapY = pMapY[ nY ];
2176cdf0e10cSrcweir Scanline pAScan = pA->GetScanline( nMapY );
2177cdf0e10cSrcweir
2178cdf0e10cSrcweir for( nX = 0; nX < nDstWidth; nX++ )
2179cdf0e10cSrcweir {
2180cdf0e10cSrcweir const long nMapX = pMapX[ nX ];
2181cdf0e10cSrcweir aDstCol = pB->GetPixel( nY, nX );
2182cdf0e10cSrcweir pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
2183cdf0e10cSrcweir pAScan[ nMapX ] ) );
2184cdf0e10cSrcweir }
2185cdf0e10cSrcweir }
2186cdf0e10cSrcweir }
2187cdf0e10cSrcweir break;
2188cdf0e10cSrcweir }
2189cdf0e10cSrcweir }
2190cdf0e10cSrcweir
2191cdf0e10cSrcweir aBmp.ReleaseAccess( pB );
2192cdf0e10cSrcweir res = aBmp;
2193cdf0e10cSrcweir }
2194cdf0e10cSrcweir
2195cdf0e10cSrcweir return res;
2196cdf0e10cSrcweir }
2197cdf0e10cSrcweir
2198cdf0e10cSrcweir // ------------------------------------------------------------------------
2199cdf0e10cSrcweir
ImplDrawAlpha(const Bitmap & rBmp,const AlphaMask & rAlpha,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel)2200cdf0e10cSrcweir void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
2201cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize,
2202cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2203cdf0e10cSrcweir {
2204cdf0e10cSrcweir const Point aNullPt;
2205cdf0e10cSrcweir Point aOutPt( LogicToPixel( rDestPt ) );
2206cdf0e10cSrcweir Size aOutSz( LogicToPixel( rDestSize ) );
2207cdf0e10cSrcweir Rectangle aDstRect( aNullPt, GetOutputSizePixel() );
2208cdf0e10cSrcweir const sal_Bool bHMirr = aOutSz.Width() < 0, bVMirr = aOutSz.Height() < 0;
2209cdf0e10cSrcweir
2210cdf0e10cSrcweir if( OUTDEV_WINDOW == meOutDevType )
2211cdf0e10cSrcweir {
2212cdf0e10cSrcweir const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
2213cdf0e10cSrcweir
2214cdf0e10cSrcweir if( !aPaintRgn.IsNull() )
2215cdf0e10cSrcweir aDstRect.Intersection( LogicToPixel( aPaintRgn.GetBoundRect() ) );
2216cdf0e10cSrcweir }
2217cdf0e10cSrcweir
2218cdf0e10cSrcweir if( bHMirr )
2219cdf0e10cSrcweir {
2220cdf0e10cSrcweir aOutSz.Width() = -aOutSz.Width();
2221cdf0e10cSrcweir aOutPt.X() -= ( aOutSz.Width() - 1L );
2222cdf0e10cSrcweir }
2223cdf0e10cSrcweir
2224cdf0e10cSrcweir if( bVMirr )
2225cdf0e10cSrcweir {
2226cdf0e10cSrcweir aOutSz.Height() = -aOutSz.Height();
2227cdf0e10cSrcweir aOutPt.Y() -= ( aOutSz.Height() - 1L );
2228cdf0e10cSrcweir }
2229cdf0e10cSrcweir
2230cdf0e10cSrcweir if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
2231cdf0e10cSrcweir {
2232cdf0e10cSrcweir bool bNativeAlpha = false;
2233cdf0e10cSrcweir static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
2234cdf0e10cSrcweir // #i83087# Naturally, system alpha blending cannot work with
2235cdf0e10cSrcweir // separate alpha VDev
22365f27b83cSArmin Le Grand bool bTryDirectPaint(!mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr);
22375f27b83cSArmin Le Grand
22385f27b83cSArmin Le Grand #ifdef WNT
22395f27b83cSArmin Le Grand if(bTryDirectPaint)
22405f27b83cSArmin Le Grand {
22415f27b83cSArmin Le Grand // only paint direct when no scaling and no MapMode, else the
22425f27b83cSArmin Le Grand // more expensive conversions may be done for short-time Bitmap/BitmapEx
22435f27b83cSArmin Le Grand // used for buffering only
22445f27b83cSArmin Le Grand if(!IsMapMode() && rSrcSizePixel.Width() == aOutSz.Width() && rSrcSizePixel.Height() == aOutSz.Height())
22455f27b83cSArmin Le Grand {
22465f27b83cSArmin Le Grand bTryDirectPaint = false;
22475f27b83cSArmin Le Grand }
22485f27b83cSArmin Le Grand }
22495f27b83cSArmin Le Grand #endif
22505f27b83cSArmin Le Grand
22515f27b83cSArmin Le Grand if(bTryDirectPaint)
2252cdf0e10cSrcweir {
2253cdf0e10cSrcweir Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
2254cdf0e10cSrcweir SalTwoRect aTR = {
2255cdf0e10cSrcweir rSrcPtPixel.X(), rSrcPtPixel.Y(),
2256cdf0e10cSrcweir rSrcSizePixel.Width(), rSrcSizePixel.Height(),
2257cdf0e10cSrcweir aRelPt.X(), aRelPt.Y(),
2258cdf0e10cSrcweir aOutSz.Width(), aOutSz.Height()
2259cdf0e10cSrcweir };
2260cdf0e10cSrcweir SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap();
2261cdf0e10cSrcweir SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
2262cdf0e10cSrcweir bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this );
2263cdf0e10cSrcweir }
2264cdf0e10cSrcweir
2265cdf0e10cSrcweir VirtualDevice* pOldVDev = mpAlphaVDev;
2266cdf0e10cSrcweir
2267cdf0e10cSrcweir Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() );
2268cdf0e10cSrcweir if( !bNativeAlpha
2269cdf0e10cSrcweir && !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
2270cdf0e10cSrcweir {
2271cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile; mpMetaFile = NULL;
2272cdf0e10cSrcweir const sal_Bool bOldMap = mbMap; mbMap = sal_False;
2273cdf0e10cSrcweir Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
2274cdf0e10cSrcweir
2275cdf0e10cSrcweir // #109044# The generated bitmap need not necessarily be
2276cdf0e10cSrcweir // of aDstRect dimensions, it's internally clipped to
2277cdf0e10cSrcweir // window bounds. Thus, we correct the dest size here,
2278cdf0e10cSrcweir // since we later use it (in nDstWidth/Height) for pixel
2279cdf0e10cSrcweir // access)
2280cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail
2281cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() )
2282cdf0e10cSrcweir aDstRect.SetSize( aBmp.GetSizePixel() );
2283cdf0e10cSrcweir
2284cdf0e10cSrcweir BitmapColor aDstCol;
2285cdf0e10cSrcweir const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
2286cdf0e10cSrcweir const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
2287cdf0e10cSrcweir const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
2288cdf0e10cSrcweir // calculate offset in original bitmap
2289cdf0e10cSrcweir // in RTL case this is a little more complicated since the contents of the
2290cdf0e10cSrcweir // bitmap is not mirrored (it never is), however the paint region and bmp region
2291cdf0e10cSrcweir // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
2292cdf0e10cSrcweir // is content wise somewhere else and needs to take mirroring into account
2293cdf0e10cSrcweir const long nOffX = IsRTLEnabled()
2294cdf0e10cSrcweir ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
2295cdf0e10cSrcweir : aDstRect.Left() - aOutPt.X(),
2296cdf0e10cSrcweir nOffY = aDstRect.Top() - aOutPt.Y();
2297cdf0e10cSrcweir long nX, nOutX, nY, nOutY;
2298cdf0e10cSrcweir long nMirrOffX = 0;
2299cdf0e10cSrcweir long nMirrOffY = 0;
2300cdf0e10cSrcweir long* pMapX = new long[ nDstWidth ];
2301cdf0e10cSrcweir long* pMapY = new long[ nDstHeight ];
2302cdf0e10cSrcweir
2303cdf0e10cSrcweir // create horizontal mapping table
2304cdf0e10cSrcweir if( bHMirr )
2305cdf0e10cSrcweir nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
2306cdf0e10cSrcweir
2307cdf0e10cSrcweir for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
2308cdf0e10cSrcweir {
2309cdf0e10cSrcweir pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
2310cdf0e10cSrcweir if( bHMirr )
2311cdf0e10cSrcweir pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
2312cdf0e10cSrcweir }
2313cdf0e10cSrcweir
2314cdf0e10cSrcweir // create vertical mapping table
2315cdf0e10cSrcweir if( bVMirr )
2316cdf0e10cSrcweir nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
2317cdf0e10cSrcweir
2318cdf0e10cSrcweir for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
2319cdf0e10cSrcweir {
2320cdf0e10cSrcweir pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
2321cdf0e10cSrcweir
2322cdf0e10cSrcweir if( bVMirr )
2323cdf0e10cSrcweir pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
2324cdf0e10cSrcweir }
2325cdf0e10cSrcweir
2326cdf0e10cSrcweir BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
2327cdf0e10cSrcweir BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
2328cdf0e10cSrcweir
2329cdf0e10cSrcweir DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
2330cdf0e10cSrcweir pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
2331cdf0e10cSrcweir "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
2332cdf0e10cSrcweir
2333cdf0e10cSrcweir // #i38887# reading from screen may sometimes fail
2334cdf0e10cSrcweir if( aBmp.ImplGetImpBitmap() )
2335cdf0e10cSrcweir {
2336cdf0e10cSrcweir Bitmap aTmp;
2337cdf0e10cSrcweir
2338cdf0e10cSrcweir if( mpAlphaVDev )
2339cdf0e10cSrcweir {
2340cdf0e10cSrcweir aTmp = ImplBlendWithAlpha(
2341cdf0e10cSrcweir aBmp,pP,pA,
2342cdf0e10cSrcweir aDstRect,
2343cdf0e10cSrcweir nOffY,nDstHeight,
2344cdf0e10cSrcweir nOffX,nDstWidth,
2345cdf0e10cSrcweir pMapX,pMapY );
2346cdf0e10cSrcweir }
2347cdf0e10cSrcweir else
2348cdf0e10cSrcweir {
2349cdf0e10cSrcweir aTmp = ImplBlend(
2350cdf0e10cSrcweir aBmp,pP,pA,
2351cdf0e10cSrcweir nOffY,nDstHeight,
2352cdf0e10cSrcweir nOffX,nDstWidth,
2353cdf0e10cSrcweir aBmpRect,aOutSz,
2354cdf0e10cSrcweir bHMirr,bVMirr,
2355cdf0e10cSrcweir pMapX,pMapY );
2356cdf0e10cSrcweir }
2357cdf0e10cSrcweir
2358cdf0e10cSrcweir // #110958# Disable alpha VDev, we're doing the necessary
235956b8eddcSmseidel // stuff explicitly further below
2360cdf0e10cSrcweir if( mpAlphaVDev )
2361cdf0e10cSrcweir mpAlphaVDev = NULL;
2362cdf0e10cSrcweir
2363cdf0e10cSrcweir DrawBitmap( aDstRect.TopLeft(),
2364cdf0e10cSrcweir aTmp );
2365cdf0e10cSrcweir
2366cdf0e10cSrcweir // #110958# Enable alpha VDev again
2367cdf0e10cSrcweir mpAlphaVDev = pOldVDev;
2368cdf0e10cSrcweir }
2369cdf0e10cSrcweir
2370cdf0e10cSrcweir ( (Bitmap&) rBmp ).ReleaseAccess( pP );
2371cdf0e10cSrcweir ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
2372cdf0e10cSrcweir
2373cdf0e10cSrcweir delete[] pMapX;
2374cdf0e10cSrcweir delete[] pMapY;
2375cdf0e10cSrcweir mbMap = bOldMap;
2376cdf0e10cSrcweir mpMetaFile = pOldMetaFile;
2377cdf0e10cSrcweir }
2378cdf0e10cSrcweir }
2379cdf0e10cSrcweir }
2380cdf0e10cSrcweir
2381cdf0e10cSrcweir // ------------------------------------------------------------------------
2382cdf0e10cSrcweir
ImplPrintTransparent(const Bitmap & rBmp,const Bitmap & rMask,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel)2383cdf0e10cSrcweir void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
2384cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize,
2385cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2386cdf0e10cSrcweir {
2387cdf0e10cSrcweir Point aPt;
2388cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) );
2389cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) );
2390cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
2391cdf0e10cSrcweir
2392cdf0e10cSrcweir aSrcRect.Justify();
2393cdf0e10cSrcweir
2394cdf0e10cSrcweir if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2395cdf0e10cSrcweir {
2396cdf0e10cSrcweir Bitmap aPaint( rBmp ), aMask( rMask );
2397cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL;
2398cdf0e10cSrcweir
2399cdf0e10cSrcweir if( aMask.GetBitCount() > 1 )
2400cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2401cdf0e10cSrcweir
2402cdf0e10cSrcweir // mirrored horizontically
2403cdf0e10cSrcweir if( aDestSz.Width() < 0L )
2404cdf0e10cSrcweir {
2405cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width();
2406cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L );
2407cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ;
2408cdf0e10cSrcweir }
2409cdf0e10cSrcweir
2410cdf0e10cSrcweir // mirrored vertically
2411cdf0e10cSrcweir if( aDestSz.Height() < 0L )
2412cdf0e10cSrcweir {
2413cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height();
2414cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L );
2415cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT;
2416cdf0e10cSrcweir }
2417cdf0e10cSrcweir
2418cdf0e10cSrcweir // source cropped?
2419cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
2420cdf0e10cSrcweir {
2421cdf0e10cSrcweir aPaint.Crop( aSrcRect );
2422cdf0e10cSrcweir aMask.Crop( aSrcRect );
2423cdf0e10cSrcweir }
2424cdf0e10cSrcweir
2425cdf0e10cSrcweir // destination mirrored
2426cdf0e10cSrcweir if( nMirrFlags )
2427cdf0e10cSrcweir {
2428cdf0e10cSrcweir aPaint.Mirror( nMirrFlags );
2429cdf0e10cSrcweir aMask.Mirror( nMirrFlags );
2430cdf0e10cSrcweir }
2431cdf0e10cSrcweir
2432cdf0e10cSrcweir // we always want to have a mask
2433cdf0e10cSrcweir if( aMask.IsEmpty() )
2434cdf0e10cSrcweir {
2435cdf0e10cSrcweir aMask = Bitmap( aSrcRect.GetSize(), 1 );
2436cdf0e10cSrcweir aMask.Erase( Color( COL_BLACK ) );
2437cdf0e10cSrcweir }
2438cdf0e10cSrcweir
2439cdf0e10cSrcweir // do painting
2440cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2441e6f63103SArmin Le Grand long nX, nY; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2442cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ];
2443cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ];
2444cdf0e10cSrcweir const sal_Bool bOldMap = mbMap;
2445cdf0e10cSrcweir
2446cdf0e10cSrcweir mbMap = sal_False;
2447cdf0e10cSrcweir
2448cdf0e10cSrcweir // create forward mapping tables
2449cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ )
2450cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2451cdf0e10cSrcweir
2452cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ )
2453cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2454cdf0e10cSrcweir
2455cdf0e10cSrcweir // walk through all rectangles of mask
2456e6f63103SArmin Le Grand const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
2457e6f63103SArmin Le Grand RectangleVector aRectangles;
2458e6f63103SArmin Le Grand aWorkRgn.GetRegionRectangles(aRectangles);
2459cdf0e10cSrcweir
2460e6f63103SArmin Le Grand for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
2461cdf0e10cSrcweir {
2462e6f63103SArmin Le Grand const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
2463e6f63103SArmin Le Grand const Size aMapSz(
2464e6f63103SArmin Le Grand pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
2465e6f63103SArmin Le Grand pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y
2466cdf0e10cSrcweir Bitmap aBandBmp(aPaint);
2467cdf0e10cSrcweir
2468e6f63103SArmin Le Grand aBandBmp.Crop(*aRectIter);
2469cdf0e10cSrcweir ImplDrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION);
2470cdf0e10cSrcweir }
2471cdf0e10cSrcweir
2472e6f63103SArmin Le Grand //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2473e6f63103SArmin Le Grand //ImplRegionInfo aInfo;
2474e6f63103SArmin Le Grand //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2475e6f63103SArmin Le Grand //
2476e6f63103SArmin Le Grand //while( bRgnRect )
2477e6f63103SArmin Le Grand //{
2478e6f63103SArmin Le Grand // Bitmap aBandBmp( aPaint );
2479e6f63103SArmin Le Grand // const Rectangle aBandRect( Point( nWorkX, nWorkY ), Size( nWorkWidth, nWorkHeight ) );
2480e6f63103SArmin Le Grand // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2481e6f63103SArmin Le Grand // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2482e6f63103SArmin Le Grand //
2483e6f63103SArmin Le Grand // aBandBmp.Crop( aBandRect );
2484e6f63103SArmin Le Grand // ImplDrawBitmap( aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION );
2485e6f63103SArmin Le Grand // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2486e6f63103SArmin Le Grand //}
2487e6f63103SArmin Le Grand
2488cdf0e10cSrcweir mbMap = bOldMap;
2489cdf0e10cSrcweir
2490cdf0e10cSrcweir delete[] pMapX;
2491cdf0e10cSrcweir delete[] pMapY;
2492cdf0e10cSrcweir }
2493cdf0e10cSrcweir }
2494cdf0e10cSrcweir
2495cdf0e10cSrcweir // ------------------------------------------------------------------------
2496cdf0e10cSrcweir
ImplPrintMask(const Bitmap & rMask,const Color & rMaskColor,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel)2497cdf0e10cSrcweir void OutputDevice::ImplPrintMask( const Bitmap& rMask, const Color& rMaskColor,
2498cdf0e10cSrcweir const Point& rDestPt, const Size& rDestSize,
2499cdf0e10cSrcweir const Point& rSrcPtPixel, const Size& rSrcSizePixel )
2500cdf0e10cSrcweir {
2501cdf0e10cSrcweir Point aPt;
2502cdf0e10cSrcweir Point aDestPt( LogicToPixel( rDestPt ) );
2503cdf0e10cSrcweir Size aDestSz( LogicToPixel( rDestSize ) );
2504cdf0e10cSrcweir Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
2505cdf0e10cSrcweir
2506cdf0e10cSrcweir aSrcRect.Justify();
2507cdf0e10cSrcweir
2508cdf0e10cSrcweir if( !rMask.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
2509cdf0e10cSrcweir {
2510cdf0e10cSrcweir Bitmap aMask( rMask );
2511cdf0e10cSrcweir sal_uLong nMirrFlags = 0UL;
2512cdf0e10cSrcweir
2513cdf0e10cSrcweir if( aMask.GetBitCount() > 1 )
2514cdf0e10cSrcweir aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
2515cdf0e10cSrcweir
2516cdf0e10cSrcweir // mirrored horizontically
2517cdf0e10cSrcweir if( aDestSz.Width() < 0L )
2518cdf0e10cSrcweir {
2519cdf0e10cSrcweir aDestSz.Width() = -aDestSz.Width();
2520cdf0e10cSrcweir aDestPt.X() -= ( aDestSz.Width() - 1L );
2521cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_HORZ;
2522cdf0e10cSrcweir }
2523cdf0e10cSrcweir
2524cdf0e10cSrcweir // mirrored vertically
2525cdf0e10cSrcweir if( aDestSz.Height() < 0L )
2526cdf0e10cSrcweir {
2527cdf0e10cSrcweir aDestSz.Height() = -aDestSz.Height();
2528cdf0e10cSrcweir aDestPt.Y() -= ( aDestSz.Height() - 1L );
2529cdf0e10cSrcweir nMirrFlags |= BMP_MIRROR_VERT;
2530cdf0e10cSrcweir }
2531cdf0e10cSrcweir
2532cdf0e10cSrcweir // source cropped?
2533cdf0e10cSrcweir if( aSrcRect != Rectangle( aPt, aMask.GetSizePixel() ) )
2534cdf0e10cSrcweir aMask.Crop( aSrcRect );
2535cdf0e10cSrcweir
2536cdf0e10cSrcweir // destination mirrored
2537cdf0e10cSrcweir if( nMirrFlags )
2538cdf0e10cSrcweir aMask.Mirror( nMirrFlags );
2539cdf0e10cSrcweir
2540cdf0e10cSrcweir // do painting
2541cdf0e10cSrcweir const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
2542e6f63103SArmin Le Grand long nX, nY; //, nWorkX, nWorkY, nWorkWidth, nWorkHeight;
2543cdf0e10cSrcweir long* pMapX = new long[ nSrcWidth + 1 ];
2544cdf0e10cSrcweir long* pMapY = new long[ nSrcHeight + 1 ];
2545cdf0e10cSrcweir GDIMetaFile* pOldMetaFile = mpMetaFile;
2546cdf0e10cSrcweir const sal_Bool bOldMap = mbMap;
2547cdf0e10cSrcweir
2548cdf0e10cSrcweir mpMetaFile = NULL;
2549cdf0e10cSrcweir mbMap = sal_False;
2550cdf0e10cSrcweir Push( PUSH_FILLCOLOR | PUSH_LINECOLOR );
2551cdf0e10cSrcweir SetLineColor( rMaskColor );
2552cdf0e10cSrcweir SetFillColor( rMaskColor );
2553cdf0e10cSrcweir ImplInitLineColor();
2554cdf0e10cSrcweir ImplInitFillColor();
2555cdf0e10cSrcweir
2556cdf0e10cSrcweir // create forward mapping tables
2557cdf0e10cSrcweir for( nX = 0L; nX <= nSrcWidth; nX++ )
2558cdf0e10cSrcweir pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
2559cdf0e10cSrcweir
2560cdf0e10cSrcweir for( nY = 0L; nY <= nSrcHeight; nY++ )
2561cdf0e10cSrcweir pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
2562cdf0e10cSrcweir
2563cdf0e10cSrcweir // walk through all rectangles of mask
2564e6f63103SArmin Le Grand const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
2565e6f63103SArmin Le Grand RectangleVector aRectangles;
2566e6f63103SArmin Le Grand aWorkRgn.GetRegionRectangles(aRectangles);
2567cdf0e10cSrcweir
2568e6f63103SArmin Le Grand for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
2569cdf0e10cSrcweir {
2570e6f63103SArmin Le Grand const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
2571e6f63103SArmin Le Grand const Size aMapSz(
2572e6f63103SArmin Le Grand pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
2573e6f63103SArmin Le Grand pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y
2574cdf0e10cSrcweir
2575cdf0e10cSrcweir DrawRect(Rectangle(aMapPt, aMapSz));
2576cdf0e10cSrcweir }
2577cdf0e10cSrcweir
2578e6f63103SArmin Le Grand //Region aWorkRgn( aMask.CreateRegion( COL_BLACK, Rectangle( Point(), aMask.GetSizePixel() ) ) );
2579e6f63103SArmin Le Grand //ImplRegionInfo aInfo;
2580e6f63103SArmin Le Grand //sal_Bool bRgnRect = aWorkRgn.ImplGetFirstRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2581e6f63103SArmin Le Grand //
2582e6f63103SArmin Le Grand //while( bRgnRect )
2583e6f63103SArmin Le Grand //{
2584e6f63103SArmin Le Grand // const Point aMapPt( pMapX[ nWorkX ], pMapY[ nWorkY ] );
2585e6f63103SArmin Le Grand // const Size aMapSz( pMapX[ nWorkX + nWorkWidth ] - aMapPt.X(), pMapY[ nWorkY + nWorkHeight ] - aMapPt.Y() );
2586e6f63103SArmin Le Grand //
2587e6f63103SArmin Le Grand // DrawRect( Rectangle( aMapPt, aMapSz ) );
2588e6f63103SArmin Le Grand // bRgnRect = aWorkRgn.ImplGetNextRect( aInfo, nWorkX, nWorkY, nWorkWidth, nWorkHeight );
2589e6f63103SArmin Le Grand //}
2590e6f63103SArmin Le Grand
2591cdf0e10cSrcweir Pop();
2592cdf0e10cSrcweir delete[] pMapX;
2593cdf0e10cSrcweir delete[] pMapY;
2594cdf0e10cSrcweir mbMap = bOldMap;
2595cdf0e10cSrcweir mpMetaFile = pOldMetaFile;
2596cdf0e10cSrcweir }
2597cdf0e10cSrcweir }
2598