xref: /AOO41X/main/canvas/source/vcl/canvasbitmaphelper.cxx (revision 37ab0f2ded8d56c462c711095097172f45805977)
125ea7f45SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
325ea7f45SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
425ea7f45SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
525ea7f45SAndrew Rist  * distributed with this work for additional information
625ea7f45SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
725ea7f45SAndrew Rist  * to you under the Apache License, Version 2.0 (the
825ea7f45SAndrew Rist  * "License"); you may not use this file except in compliance
925ea7f45SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
1125ea7f45SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
1325ea7f45SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1425ea7f45SAndrew Rist  * software distributed under the License is distributed on an
1525ea7f45SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1625ea7f45SAndrew Rist  * KIND, either express or implied.  See the License for the
1725ea7f45SAndrew Rist  * specific language governing permissions and limitations
1825ea7f45SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
2025ea7f45SAndrew Rist  *************************************************************/
2125ea7f45SAndrew Rist 
2225ea7f45SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_canvas.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <com/sun/star/util/Endianness.hpp>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <rtl/logfile.hxx>
33cdf0e10cSrcweir #include <rtl/math.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <tools/poly.hxx>
36cdf0e10cSrcweir #include <vcl/window.hxx>
37cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
38cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
39cdf0e10cSrcweir #include <vcl/canvastools.hxx>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
42cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
43cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
44cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include <canvas/canvastools.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include "canvasbitmap.hxx"
49cdf0e10cSrcweir #include "canvasbitmaphelper.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir 
52cdf0e10cSrcweir using namespace ::com::sun::star;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir namespace vclcanvas
55cdf0e10cSrcweir {
CanvasBitmapHelper()56cdf0e10cSrcweir     CanvasBitmapHelper::CanvasBitmapHelper() :
57cdf0e10cSrcweir         mpBackBuffer(),
58cdf0e10cSrcweir         mpOutDevReference()
59cdf0e10cSrcweir     {
60cdf0e10cSrcweir     }
61cdf0e10cSrcweir 
setBitmap(const BitmapEx & rBitmap)62cdf0e10cSrcweir     void CanvasBitmapHelper::setBitmap( const BitmapEx& rBitmap )
63cdf0e10cSrcweir     {
64cdf0e10cSrcweir         ENSURE_OR_THROW( mpOutDev,
65cdf0e10cSrcweir                          "Invalid reference device" );
66cdf0e10cSrcweir 
67cdf0e10cSrcweir         mpBackBuffer.reset( new BitmapBackBuffer( rBitmap,
68cdf0e10cSrcweir                                                   mpOutDev->getOutDev() ) );
69cdf0e10cSrcweir 
70cdf0e10cSrcweir         // tell canvas helper about the new target OutDev (don't
71cdf0e10cSrcweir         // protect state, it's our own VirDev, anyways)
72cdf0e10cSrcweir         setOutDev( mpBackBuffer, false );
73cdf0e10cSrcweir     }
74cdf0e10cSrcweir 
init(const BitmapEx & rBitmap,rendering::XGraphicDevice & rDevice,const OutDevProviderSharedPtr & rOutDevReference)75cdf0e10cSrcweir     void CanvasBitmapHelper::init( const BitmapEx&                rBitmap,
76cdf0e10cSrcweir                                    rendering::XGraphicDevice&     rDevice,
77cdf0e10cSrcweir                                    const OutDevProviderSharedPtr& rOutDevReference )
78cdf0e10cSrcweir     {
79cdf0e10cSrcweir         mpOutDevReference = rOutDevReference;
80cdf0e10cSrcweir         mpBackBuffer.reset( new BitmapBackBuffer( rBitmap, rOutDevReference->getOutDev() ));
81cdf0e10cSrcweir 
82cdf0e10cSrcweir         // forward new settings to base class (ref device, output
83cdf0e10cSrcweir         // surface, no protection (own backbuffer), alpha depends on
84cdf0e10cSrcweir         // whether BmpEx is transparent or not)
85cdf0e10cSrcweir         CanvasHelper::init( rDevice,
86cdf0e10cSrcweir                             mpBackBuffer,
87cdf0e10cSrcweir                             false,
88cdf0e10cSrcweir                             rBitmap.IsTransparent() );
89cdf0e10cSrcweir     }
90cdf0e10cSrcweir 
disposing()91cdf0e10cSrcweir     void CanvasBitmapHelper::disposing()
92cdf0e10cSrcweir     {
93cdf0e10cSrcweir         mpBackBuffer.reset();
94cdf0e10cSrcweir         mpOutDevReference.reset();
95cdf0e10cSrcweir 
96cdf0e10cSrcweir         // forward to base class
97cdf0e10cSrcweir         CanvasHelper::disposing();
98cdf0e10cSrcweir     }
99cdf0e10cSrcweir 
getSize()100cdf0e10cSrcweir     geometry::IntegerSize2D CanvasBitmapHelper::getSize()
101cdf0e10cSrcweir     {
102cdf0e10cSrcweir         if( !mpBackBuffer )
103cdf0e10cSrcweir             return geometry::IntegerSize2D();
104cdf0e10cSrcweir 
105cdf0e10cSrcweir         return ::vcl::unotools::integerSize2DFromSize( mpBackBuffer->getBitmapSizePixel() );
106cdf0e10cSrcweir     }
107cdf0e10cSrcweir 
clear()108cdf0e10cSrcweir     void CanvasBitmapHelper::clear()
109cdf0e10cSrcweir     {
110cdf0e10cSrcweir         // are we disposed?
111cdf0e10cSrcweir         if( mpBackBuffer )
112cdf0e10cSrcweir             mpBackBuffer->clear(); // alpha vdev needs special treatment
113cdf0e10cSrcweir     }
114cdf0e10cSrcweir 
getScaledBitmap(const geometry::RealSize2D & newSize,sal_Bool beFast)115cdf0e10cSrcweir     uno::Reference< rendering::XBitmap > CanvasBitmapHelper::getScaledBitmap( const geometry::RealSize2D& 	newSize,
116cdf0e10cSrcweir                                                                               sal_Bool 						beFast )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         ENSURE_OR_THROW( mpDevice,
119cdf0e10cSrcweir                           "disposed CanvasHelper" );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir         RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getScaledBitmap()" );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         if( !mpBackBuffer || mpDevice )
124cdf0e10cSrcweir             return uno::Reference< rendering::XBitmap >(); // we're disposed
125cdf0e10cSrcweir 
126cdf0e10cSrcweir         BitmapEx aRes( mpBackBuffer->getBitmapReference() );
127cdf0e10cSrcweir 
128cdf0e10cSrcweir         aRes.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize),
129*37ab0f2dSArmin Le Grand                      beFast ? BMP_SCALE_FASTESTINTERPOLATE : BMP_SCALE_INTERPOLATE );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir         return uno::Reference< rendering::XBitmap >(
132cdf0e10cSrcweir             new CanvasBitmap( aRes, *mpDevice, mpOutDevReference ) );
133cdf0e10cSrcweir     }
134cdf0e10cSrcweir 
getData(rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerRectangle2D & rect)135cdf0e10cSrcweir     uno::Sequence< sal_Int8 > CanvasBitmapHelper::getData( rendering::IntegerBitmapLayout& 		rLayout,
136cdf0e10cSrcweir                                                            const geometry::IntegerRectangle2D&	rect )
137cdf0e10cSrcweir     {
138cdf0e10cSrcweir         RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getData()" );
139cdf0e10cSrcweir 
140cdf0e10cSrcweir         if( !mpBackBuffer )
141cdf0e10cSrcweir             return uno::Sequence< sal_Int8 >(); // we're disposed
142cdf0e10cSrcweir 
143cdf0e10cSrcweir         rLayout = getMemoryLayout();
144cdf0e10cSrcweir         Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
145cdf0e10cSrcweir         Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
146cdf0e10cSrcweir 
147cdf0e10cSrcweir         ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
148cdf0e10cSrcweir                                             aBitmap );
149cdf0e10cSrcweir         ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
150cdf0e10cSrcweir                                                  (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
151cdf0e10cSrcweir                                                  aAlpha );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir         ENSURE_OR_THROW( pReadAccess.get() != NULL,
154cdf0e10cSrcweir                          "Could not acquire read access to bitmap" );
155cdf0e10cSrcweir 
156cdf0e10cSrcweir         // TODO(F1): Support more formats.
157cdf0e10cSrcweir         const Size aBmpSize( aBitmap.GetSizePixel() );
158cdf0e10cSrcweir 
159cdf0e10cSrcweir         rLayout.ScanLines = aBmpSize.Height();
160cdf0e10cSrcweir         rLayout.ScanLineBytes = aBmpSize.Width()*4;
161cdf0e10cSrcweir         rLayout.ScanLineStride = rLayout.ScanLineBytes;
162cdf0e10cSrcweir 
163cdf0e10cSrcweir         // for the time being, always return as BGRA
164cdf0e10cSrcweir         uno::Sequence< sal_Int8 > aRes( 4*aBmpSize.Width()*aBmpSize.Height() );
165cdf0e10cSrcweir         sal_Int8* pRes = aRes.getArray();
166cdf0e10cSrcweir 
167cdf0e10cSrcweir         int nCurrPos(0);
168cdf0e10cSrcweir         for( int y=rect.Y1;
169cdf0e10cSrcweir              y<aBmpSize.Height() && y<rect.Y2;
170cdf0e10cSrcweir              ++y )
171cdf0e10cSrcweir         {
172cdf0e10cSrcweir             if( pAlphaReadAccess.get() != NULL )
173cdf0e10cSrcweir             {
174cdf0e10cSrcweir                 for( int x=rect.X1;
175cdf0e10cSrcweir                      x<aBmpSize.Width() && x<rect.X2;
176cdf0e10cSrcweir                      ++x )
177cdf0e10cSrcweir                 {
178cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
179cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
180cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
181cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pAlphaReadAccess->GetPixel( y, x ).GetIndex();
182cdf0e10cSrcweir                 }
183cdf0e10cSrcweir             }
184cdf0e10cSrcweir             else
185cdf0e10cSrcweir             {
186cdf0e10cSrcweir                 for( int x=rect.X1;
187cdf0e10cSrcweir                      x<aBmpSize.Width() && x<rect.X2;
188cdf0e10cSrcweir                      ++x )
189cdf0e10cSrcweir                 {
190cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
191cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
192cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
193cdf0e10cSrcweir                     pRes[ nCurrPos++ ] = sal_uInt8(255);
194cdf0e10cSrcweir                 }
195cdf0e10cSrcweir             }
196cdf0e10cSrcweir         }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir         return aRes;
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir 
setData(const uno::Sequence<sal_Int8> & data,const rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerRectangle2D & rect)201cdf0e10cSrcweir     void CanvasBitmapHelper::setData( const uno::Sequence< sal_Int8 >& 		data,
202cdf0e10cSrcweir                                       const rendering::IntegerBitmapLayout& rLayout,
203cdf0e10cSrcweir                                       const geometry::IntegerRectangle2D&	rect )
204cdf0e10cSrcweir     {
205cdf0e10cSrcweir         RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setData()" );
206cdf0e10cSrcweir 
207cdf0e10cSrcweir         if( !mpBackBuffer )
208cdf0e10cSrcweir             return; // we're disposed
209cdf0e10cSrcweir 
210cdf0e10cSrcweir         const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
211cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
212cdf0e10cSrcweir                              aRefLayout.ColorSpace  != rLayout.ColorSpace ||
213cdf0e10cSrcweir                              aRefLayout.Palette     != rLayout.Palette ||
214cdf0e10cSrcweir                              aRefLayout.IsMsbFirst  != rLayout.IsMsbFirst,
215cdf0e10cSrcweir                              "Mismatching memory layout" );
216cdf0e10cSrcweir 
217cdf0e10cSrcweir         // retrieve local copies from the BitmapEx, which are later
218cdf0e10cSrcweir         // stored back. Unfortunately, the BitmapEx does not permit
219cdf0e10cSrcweir         // in-place modifications, as they are necessary here.
220cdf0e10cSrcweir         Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
221cdf0e10cSrcweir         Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
222cdf0e10cSrcweir 
223cdf0e10cSrcweir         bool bCopyBack( false ); // only copy something back, if we
224cdf0e10cSrcweir                                  // actually changed a pixel
225cdf0e10cSrcweir 
226cdf0e10cSrcweir         {
227cdf0e10cSrcweir             ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
228cdf0e10cSrcweir                                                   aBitmap );
229cdf0e10cSrcweir             ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
230cdf0e10cSrcweir                                                        (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
231cdf0e10cSrcweir                                                        aAlpha );
232cdf0e10cSrcweir 
233cdf0e10cSrcweir             if( pAlphaWriteAccess.get() )
234cdf0e10cSrcweir             {
235cdf0e10cSrcweir                 DBG_ASSERT( pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
236cdf0e10cSrcweir                             pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
237cdf0e10cSrcweir                             "non-8bit alpha not supported!" );
238cdf0e10cSrcweir             }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir             ENSURE_OR_THROW( pWriteAccess.get() != NULL,
241cdf0e10cSrcweir                              "Could not acquire write access to bitmap" );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir             // TODO(F1): Support more formats.
244cdf0e10cSrcweir             const Size aBmpSize( aBitmap.GetSizePixel() );
245cdf0e10cSrcweir 
246cdf0e10cSrcweir             // for the time being, always read as BGRA
247cdf0e10cSrcweir             int x, y, nCurrPos(0);
248cdf0e10cSrcweir             for( y=rect.Y1;
249cdf0e10cSrcweir                  y<aBmpSize.Height() && y<rect.Y2;
250cdf0e10cSrcweir                  ++y )
251cdf0e10cSrcweir             {
252cdf0e10cSrcweir                 if( pAlphaWriteAccess.get() != NULL )
253cdf0e10cSrcweir                 {
254cdf0e10cSrcweir                     switch( pWriteAccess->GetScanlineFormat() )
255cdf0e10cSrcweir                     {
256cdf0e10cSrcweir                         case BMP_FORMAT_8BIT_PAL:
257cdf0e10cSrcweir                         {
258cdf0e10cSrcweir                             Scanline pScan  = pWriteAccess->GetScanline( y );
259cdf0e10cSrcweir                             Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
260cdf0e10cSrcweir 
261cdf0e10cSrcweir                             for( x=rect.X1;
262cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
263cdf0e10cSrcweir                                  ++x )
264cdf0e10cSrcweir                             {
265cdf0e10cSrcweir                                 *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex(
266cdf0e10cSrcweir                                     BitmapColor( data[ nCurrPos   ],
267cdf0e10cSrcweir                                                  data[ nCurrPos+1 ],
268cdf0e10cSrcweir                                                  data[ nCurrPos+2 ] ) );
269cdf0e10cSrcweir 
270cdf0e10cSrcweir                                 nCurrPos += 3;
271cdf0e10cSrcweir 
272cdf0e10cSrcweir                                 // cast to unsigned byte, for correct subtraction result
273cdf0e10cSrcweir                                 *pAScan++ = static_cast<sal_uInt8>(255 -
274cdf0e10cSrcweir                                                               static_cast<sal_uInt8>(data[ nCurrPos++ ]));
275cdf0e10cSrcweir                             }
276cdf0e10cSrcweir                         }
277cdf0e10cSrcweir                         break;
278cdf0e10cSrcweir 
279cdf0e10cSrcweir                         case BMP_FORMAT_24BIT_TC_BGR:
280cdf0e10cSrcweir                         {
281cdf0e10cSrcweir                             Scanline pScan  = pWriteAccess->GetScanline( y );
282cdf0e10cSrcweir                             Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
283cdf0e10cSrcweir 
284cdf0e10cSrcweir                             for( x=rect.X1;
285cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
286cdf0e10cSrcweir                                  ++x )
287cdf0e10cSrcweir                             {
288cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+2 ];
289cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+1 ];
290cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos   ];
291cdf0e10cSrcweir 
292cdf0e10cSrcweir                                 nCurrPos += 3;
293cdf0e10cSrcweir 
294cdf0e10cSrcweir                                 // cast to unsigned byte, for correct subtraction result
295cdf0e10cSrcweir                                 *pAScan++ = static_cast<sal_uInt8>(255 -
296cdf0e10cSrcweir                                                               static_cast<sal_uInt8>(data[ nCurrPos++ ]));
297cdf0e10cSrcweir                             }
298cdf0e10cSrcweir                         }
299cdf0e10cSrcweir                         break;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir                         case BMP_FORMAT_24BIT_TC_RGB:
302cdf0e10cSrcweir                         {
303cdf0e10cSrcweir                             Scanline pScan  = pWriteAccess->GetScanline( y );
304cdf0e10cSrcweir                             Scanline pAScan = pAlphaWriteAccess->GetScanline( y );
305cdf0e10cSrcweir 
306cdf0e10cSrcweir                             for( x=rect.X1;
307cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
308cdf0e10cSrcweir                                  ++x )
309cdf0e10cSrcweir                             {
310cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos   ];
311cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+1 ];
312cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+2 ];
313cdf0e10cSrcweir 
314cdf0e10cSrcweir                                 nCurrPos += 3;
315cdf0e10cSrcweir 
316cdf0e10cSrcweir                                 // cast to unsigned byte, for correct subtraction result
317cdf0e10cSrcweir                                 *pAScan++ = static_cast<sal_uInt8>(255 -
318cdf0e10cSrcweir                                                               static_cast<sal_uInt8>(data[ nCurrPos++ ]));
319cdf0e10cSrcweir                             }
320cdf0e10cSrcweir                         }
321cdf0e10cSrcweir                         break;
322cdf0e10cSrcweir 
323cdf0e10cSrcweir                         default:
324cdf0e10cSrcweir                         {
325cdf0e10cSrcweir                             for( x=rect.X1;
326cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
327cdf0e10cSrcweir                                  ++x )
328cdf0e10cSrcweir                             {
329cdf0e10cSrcweir                                 pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos   ],
330cdf0e10cSrcweir                                                                            data[ nCurrPos+1 ],
331cdf0e10cSrcweir                                                                            data[ nCurrPos+2 ] ) );
332cdf0e10cSrcweir                                 nCurrPos += 3;
333cdf0e10cSrcweir 
334cdf0e10cSrcweir                                 // cast to unsigned byte, for correct subtraction result
335cdf0e10cSrcweir                                 pAlphaWriteAccess->SetPixel( y, x,
336cdf0e10cSrcweir                                                              BitmapColor(
337cdf0e10cSrcweir                                                                  static_cast<sal_uInt8>(255 -
338cdf0e10cSrcweir                                                                                    static_cast<sal_uInt8>(data[ nCurrPos++ ])) ) );
339cdf0e10cSrcweir                             }
340cdf0e10cSrcweir                         }
341cdf0e10cSrcweir                         break;
342cdf0e10cSrcweir                     }
343cdf0e10cSrcweir                 }
344cdf0e10cSrcweir                 else
345cdf0e10cSrcweir                 {
346cdf0e10cSrcweir                     // TODO(Q3): This is copy'n'pasted from
347cdf0e10cSrcweir                     // canvashelper.cxx, unify!
348cdf0e10cSrcweir                     switch( pWriteAccess->GetScanlineFormat() )
349cdf0e10cSrcweir                     {
350cdf0e10cSrcweir                         case BMP_FORMAT_8BIT_PAL:
351cdf0e10cSrcweir                         {
352cdf0e10cSrcweir                             Scanline pScan = pWriteAccess->GetScanline( y );
353cdf0e10cSrcweir 
354cdf0e10cSrcweir                             for( x=rect.X1;
355cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
356cdf0e10cSrcweir                                  ++x )
357cdf0e10cSrcweir                             {
358cdf0e10cSrcweir                                 *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex(
359cdf0e10cSrcweir                                     BitmapColor( data[ nCurrPos   ],
360cdf0e10cSrcweir                                                  data[ nCurrPos+1 ],
361cdf0e10cSrcweir                                                  data[ nCurrPos+2 ] ) );
362cdf0e10cSrcweir 
363cdf0e10cSrcweir                                 nCurrPos += 4; // skip three colors, _plus_ alpha
364cdf0e10cSrcweir                             }
365cdf0e10cSrcweir                         }
366cdf0e10cSrcweir                         break;
367cdf0e10cSrcweir 
368cdf0e10cSrcweir                         case BMP_FORMAT_24BIT_TC_BGR:
369cdf0e10cSrcweir                         {
370cdf0e10cSrcweir                             Scanline pScan = pWriteAccess->GetScanline( y );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir                             for( x=rect.X1;
373cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
374cdf0e10cSrcweir                                  ++x )
375cdf0e10cSrcweir                             {
376cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+2 ];
377cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+1 ];
378cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos   ];
379cdf0e10cSrcweir 
380cdf0e10cSrcweir                                 nCurrPos += 4; // skip three colors, _plus_ alpha
381cdf0e10cSrcweir                             }
382cdf0e10cSrcweir                         }
383cdf0e10cSrcweir                         break;
384cdf0e10cSrcweir 
385cdf0e10cSrcweir                         case BMP_FORMAT_24BIT_TC_RGB:
386cdf0e10cSrcweir                         {
387cdf0e10cSrcweir                             Scanline pScan = pWriteAccess->GetScanline( y );
388cdf0e10cSrcweir 
389cdf0e10cSrcweir                             for( x=rect.X1;
390cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
391cdf0e10cSrcweir                                  ++x )
392cdf0e10cSrcweir                             {
393cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos   ];
394cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+1 ];
395cdf0e10cSrcweir                                 *pScan++ = data[ nCurrPos+2 ];
396cdf0e10cSrcweir 
397cdf0e10cSrcweir                                 nCurrPos += 4; // skip three colors, _plus_ alpha
398cdf0e10cSrcweir                             }
399cdf0e10cSrcweir                         }
400cdf0e10cSrcweir                         break;
401cdf0e10cSrcweir 
402cdf0e10cSrcweir                         default:
403cdf0e10cSrcweir                         {
404cdf0e10cSrcweir                             for( x=rect.X1;
405cdf0e10cSrcweir                                  x<aBmpSize.Width() && x<rect.X2;
406cdf0e10cSrcweir                                  ++x )
407cdf0e10cSrcweir                             {
408cdf0e10cSrcweir                                 pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos   ],
409cdf0e10cSrcweir                                                                            data[ nCurrPos+1 ],
410cdf0e10cSrcweir                                                                            data[ nCurrPos+2 ] ) );
411cdf0e10cSrcweir                                 nCurrPos += 4; // skip three colors, _plus_ alpha
412cdf0e10cSrcweir                             }
413cdf0e10cSrcweir                         }
414cdf0e10cSrcweir                         break;
415cdf0e10cSrcweir                     }
416cdf0e10cSrcweir                 }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir                 bCopyBack = true;
419cdf0e10cSrcweir             }
420cdf0e10cSrcweir         }
421cdf0e10cSrcweir 
422cdf0e10cSrcweir         // copy back only here, since the BitmapAccessors must be
423cdf0e10cSrcweir         // destroyed beforehand
424cdf0e10cSrcweir         if( bCopyBack )
425cdf0e10cSrcweir         {
426cdf0e10cSrcweir             if( aAlpha.IsEmpty() )
427cdf0e10cSrcweir                 setBitmap( BitmapEx( aBitmap ) );
428cdf0e10cSrcweir             else
429cdf0e10cSrcweir                 setBitmap( BitmapEx( aBitmap,
430cdf0e10cSrcweir                                      AlphaMask( aAlpha ) ) );
431cdf0e10cSrcweir         }
432cdf0e10cSrcweir     }
433cdf0e10cSrcweir 
setPixel(const uno::Sequence<sal_Int8> & color,const rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerPoint2D & pos)434cdf0e10cSrcweir     void CanvasBitmapHelper::setPixel( const uno::Sequence< sal_Int8 >& 	 color,
435cdf0e10cSrcweir                                        const rendering::IntegerBitmapLayout& rLayout,
436cdf0e10cSrcweir                                        const geometry::IntegerPoint2D& 		 pos )
437cdf0e10cSrcweir     {
438cdf0e10cSrcweir         RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setPixel()" );
439cdf0e10cSrcweir 
440cdf0e10cSrcweir         if( !mpBackBuffer )
441cdf0e10cSrcweir             return; // we're disposed
442cdf0e10cSrcweir 
443cdf0e10cSrcweir         const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
444cdf0e10cSrcweir 
445cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
446cdf0e10cSrcweir                          "X coordinate out of bounds" );
447cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
448cdf0e10cSrcweir                          "Y coordinate out of bounds" );
449cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( color.getLength() > 3,
450cdf0e10cSrcweir                          "not enough color components" );
451cdf0e10cSrcweir 
452cdf0e10cSrcweir         const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() );
453cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride ||
454cdf0e10cSrcweir                              aRefLayout.ColorSpace  != rLayout.ColorSpace ||
455cdf0e10cSrcweir                              aRefLayout.Palette     != rLayout.Palette ||
456cdf0e10cSrcweir                              aRefLayout.IsMsbFirst  != rLayout.IsMsbFirst,
457cdf0e10cSrcweir                              "Mismatching memory layout" );
458cdf0e10cSrcweir 
459cdf0e10cSrcweir         // retrieve local copies from the BitmapEx, which are later
460cdf0e10cSrcweir         // stored back. Unfortunately, the BitmapEx does not permit
461cdf0e10cSrcweir         // in-place modifications, as they are necessary here.
462cdf0e10cSrcweir         Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
463cdf0e10cSrcweir         Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
464cdf0e10cSrcweir 
465cdf0e10cSrcweir         bool bCopyBack( false ); // only copy something back, if we
466cdf0e10cSrcweir                                  // actually changed a pixel
467cdf0e10cSrcweir 
468cdf0e10cSrcweir         {
469cdf0e10cSrcweir             ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
470cdf0e10cSrcweir                                                   aBitmap );
471cdf0e10cSrcweir             ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ?
472cdf0e10cSrcweir                                                        (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(),
473cdf0e10cSrcweir                                                        aAlpha );
474cdf0e10cSrcweir 
475cdf0e10cSrcweir             ENSURE_OR_THROW( pWriteAccess.get() != NULL,
476cdf0e10cSrcweir                              "Could not acquire write access to bitmap" );
477cdf0e10cSrcweir 
478cdf0e10cSrcweir             pWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( color[ 0 ],
479cdf0e10cSrcweir                                                                color[ 1 ],
480cdf0e10cSrcweir                                                                color[ 2 ] ) );
481cdf0e10cSrcweir 
482cdf0e10cSrcweir             if( pAlphaWriteAccess.get() != NULL )
483cdf0e10cSrcweir                 pAlphaWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( 255 - color[ 3 ] ) );
484cdf0e10cSrcweir 
485cdf0e10cSrcweir             bCopyBack = true;
486cdf0e10cSrcweir         }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir         // copy back only here, since the BitmapAccessors must be
489cdf0e10cSrcweir         // destroyed beforehand
490cdf0e10cSrcweir         if( bCopyBack )
491cdf0e10cSrcweir         {
492cdf0e10cSrcweir             if( aAlpha.IsEmpty() )
493cdf0e10cSrcweir                 setBitmap( BitmapEx( aBitmap ) );
494cdf0e10cSrcweir             else
495cdf0e10cSrcweir                 setBitmap( BitmapEx( aBitmap,
496cdf0e10cSrcweir                                      AlphaMask( aAlpha ) ) );
497cdf0e10cSrcweir         }
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir 
getPixel(rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerPoint2D & pos)500cdf0e10cSrcweir     uno::Sequence< sal_Int8 > CanvasBitmapHelper::getPixel( rendering::IntegerBitmapLayout&	rLayout,
501cdf0e10cSrcweir                                                             const geometry::IntegerPoint2D& pos )
502cdf0e10cSrcweir     {
503cdf0e10cSrcweir         RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getPixel()" );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir         if( !mpBackBuffer )
506cdf0e10cSrcweir             return uno::Sequence< sal_Int8 >(); // we're disposed
507cdf0e10cSrcweir 
508cdf0e10cSrcweir         rLayout = getMemoryLayout();
509cdf0e10cSrcweir         rLayout.ScanLines = 1;
510cdf0e10cSrcweir         rLayout.ScanLineBytes = 4;
511cdf0e10cSrcweir         rLayout.ScanLineStride = rLayout.ScanLineBytes;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir         const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() );
514cdf0e10cSrcweir 
515cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
516cdf0e10cSrcweir                          "X coordinate out of bounds" );
517cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
518cdf0e10cSrcweir                          "Y coordinate out of bounds" );
519cdf0e10cSrcweir 
520cdf0e10cSrcweir         Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() );
521cdf0e10cSrcweir         Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() );
522cdf0e10cSrcweir 
523cdf0e10cSrcweir         ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
524cdf0e10cSrcweir                                             aBitmap );
525cdf0e10cSrcweir         ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ?
526cdf0e10cSrcweir                                                  (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(),
527cdf0e10cSrcweir                                                  aAlpha );
528cdf0e10cSrcweir         ENSURE_OR_THROW( pReadAccess.get() != NULL,
529cdf0e10cSrcweir                          "Could not acquire read access to bitmap" );
530cdf0e10cSrcweir 
531cdf0e10cSrcweir         uno::Sequence< sal_Int8 > aRes( 4 );
532cdf0e10cSrcweir         sal_Int8* pRes = aRes.getArray();
533cdf0e10cSrcweir 
534cdf0e10cSrcweir         const BitmapColor aColor( pReadAccess->GetColor( pos.Y, pos.X ) );
535cdf0e10cSrcweir         pRes[ 0 ] = aColor.GetRed();
536cdf0e10cSrcweir         pRes[ 1 ] = aColor.GetGreen();
537cdf0e10cSrcweir         pRes[ 2 ] = aColor.GetBlue();
538cdf0e10cSrcweir 
539cdf0e10cSrcweir         if( pAlphaReadAccess.get() != NULL )
540cdf0e10cSrcweir             pRes[ 3 ] = pAlphaReadAccess->GetPixel( pos.Y, pos.X ).GetIndex();
541cdf0e10cSrcweir         else
542cdf0e10cSrcweir             pRes[ 3 ] = sal_uInt8(255);
543cdf0e10cSrcweir 
544cdf0e10cSrcweir         return aRes;
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir 
getMemoryLayout()547cdf0e10cSrcweir     rendering::IntegerBitmapLayout CanvasBitmapHelper::getMemoryLayout()
548cdf0e10cSrcweir     {
549cdf0e10cSrcweir         if( !mpOutDev.get() )
550cdf0e10cSrcweir             return rendering::IntegerBitmapLayout(); // we're disposed
551cdf0e10cSrcweir 
552cdf0e10cSrcweir         return ::canvas::tools::getStdMemoryLayout(getSize());
553cdf0e10cSrcweir     }
554cdf0e10cSrcweir 
getBitmap() const555cdf0e10cSrcweir     BitmapEx CanvasBitmapHelper::getBitmap() const
556cdf0e10cSrcweir     {
557cdf0e10cSrcweir         if( !mpBackBuffer )
558cdf0e10cSrcweir             return BitmapEx(); // we're disposed
559cdf0e10cSrcweir         else
560cdf0e10cSrcweir             return mpBackBuffer->getBitmapReference();
561cdf0e10cSrcweir     }
562cdf0e10cSrcweir 
563cdf0e10cSrcweir }
564