Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <vcl/salbtype.hxx>
31 : : #include <vcl/bitmap.hxx>
32 : : #include <vcl/bmpacc.hxx>
33 : :
34 : : #include <impbmp.hxx>
35 : :
36 : : #include <string.h>
37 : :
38 : : // --------------------
39 : : // - BitmapReadAccess -
40 : : // --------------------
41 : :
42 : 458953 : BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, sal_Bool bModify ) :
43 : : mpBuffer ( NULL ),
44 : : mpScanBuf ( NULL ),
45 : : mFncGetPixel ( NULL ),
46 : : mFncSetPixel ( NULL ),
47 [ + - ]: 458953 : mbModify ( bModify )
48 : : {
49 [ + - ]: 458953 : ImplCreate( rBitmap );
50 : 458953 : }
51 : :
52 : : // ------------------------------------------------------------------
53 : :
54 : 821769 : BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
55 : : mpBuffer ( NULL ),
56 : : mpScanBuf ( NULL ),
57 : : mFncGetPixel ( NULL ),
58 : : mFncSetPixel ( NULL ),
59 [ + - ]: 821769 : mbModify ( sal_False )
60 : : {
61 [ + - ]: 821769 : ImplCreate( rBitmap );
62 : 821769 : }
63 : :
64 : : // ------------------------------------------------------------------
65 : :
66 : 1280722 : BitmapReadAccess::~BitmapReadAccess()
67 : : {
68 [ + - ]: 1280722 : ImplDestroy();
69 [ - + ]: 2102491 : }
70 : :
71 : : // ------------------------------------------------------------------
72 : :
73 : 1280722 : void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
74 : : {
75 : 1280722 : ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
76 : :
77 : : DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
78 : :
79 [ + - ]: 1280722 : if( pImpBmp )
80 : : {
81 [ + + ][ + - ]: 1280722 : if( mbModify && !maBitmap.ImplGetImpBitmap() )
[ + + ]
82 : : {
83 : 458953 : rBitmap.ImplMakeUnique();
84 : 458953 : pImpBmp = rBitmap.ImplGetImpBitmap();
85 : : }
86 : : else
87 : : {
88 : : DBG_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
89 : : "Unpredictable results: bitmap is referenced more than once!" );
90 : : }
91 : :
92 : 1280722 : mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
93 : :
94 [ + + ]: 1280722 : if( !mpBuffer )
95 : : {
96 [ + - ]: 10 : ImpBitmap* pNewImpBmp = new ImpBitmap;
97 : :
98 [ - + ]: 10 : if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
99 : : {
100 : 0 : pImpBmp = pNewImpBmp;
101 : 0 : rBitmap.ImplSetImpBitmap( pImpBmp );
102 : 0 : mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
103 : : }
104 : : else
105 [ + - ]: 10 : delete pNewImpBmp;
106 : : }
107 : :
108 [ + + ]: 1280722 : if( mpBuffer )
109 : : {
110 : 1280712 : const long nHeight = mpBuffer->mnHeight;
111 : 1280712 : Scanline pTmpLine = mpBuffer->mpBits;
112 : :
113 : 1280712 : mpScanBuf = new Scanline[ nHeight ];
114 : 1280712 : maColorMask = mpBuffer->maColorMask;
115 : :
116 [ - + ]: 1280712 : if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
117 : : {
118 [ # # ]: 0 : for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
119 : 0 : mpScanBuf[ nY ] = pTmpLine;
120 : : }
121 : : else
122 : : {
123 [ + + ]: 160320351 : for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
124 : 159039639 : mpScanBuf[ nY ] = pTmpLine;
125 : : }
126 : :
127 [ - + ]: 1280712 : if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
128 : : {
129 [ # # ]: 0 : delete[] mpScanBuf;
130 : 0 : mpScanBuf = NULL;
131 : :
132 : 0 : pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
133 : 0 : mpBuffer = NULL;
134 : : }
135 : : else
136 : 1280712 : maBitmap = rBitmap;
137 : : }
138 : : }
139 : 1280722 : }
140 : :
141 : : // ------------------------------------------------------------------
142 : :
143 : 1280722 : void BitmapReadAccess::ImplDestroy()
144 : : {
145 : 1280722 : ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
146 : :
147 [ + + ]: 1280722 : delete[] mpScanBuf;
148 : 1280722 : mpScanBuf = NULL;
149 : :
150 [ + + ][ + - ]: 1280722 : if( mpBuffer && pImpBmp )
151 : : {
152 : 1280712 : pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
153 : 1280712 : mpBuffer = NULL;
154 : : }
155 : 1280722 : }
156 : :
157 : : // ------------------------------------------------------------------
158 : :
159 : 1280712 : sal_Bool BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat )
160 : : {
161 : 1280712 : sal_Bool bRet = sal_True;
162 : :
163 [ + - + - : 1280712 : switch( nFormat )
+ - - - +
- - - - -
- - - ]
164 : : {
165 : 6265 : CASE_FORMAT( _1BIT_MSB_PAL )
166 : 0 : CASE_FORMAT( _1BIT_LSB_PAL )
167 : 838 : CASE_FORMAT( _4BIT_MSN_PAL )
168 : 0 : CASE_FORMAT( _4BIT_LSN_PAL )
169 : 652753 : CASE_FORMAT( _8BIT_PAL )
170 : 0 : CASE_FORMAT( _8BIT_TC_MASK )
171 : 0 : CASE_FORMAT( _16BIT_TC_MSB_MASK )
172 : 0 : CASE_FORMAT( _16BIT_TC_LSB_MASK )
173 : 620856 : CASE_FORMAT( _24BIT_TC_BGR )
174 : 0 : CASE_FORMAT( _24BIT_TC_RGB )
175 : 0 : CASE_FORMAT( _24BIT_TC_MASK )
176 : 0 : CASE_FORMAT( _32BIT_TC_ABGR )
177 : 0 : CASE_FORMAT( _32BIT_TC_ARGB )
178 : 0 : CASE_FORMAT( _32BIT_TC_BGRA )
179 : 0 : CASE_FORMAT( _32BIT_TC_RGBA )
180 : 0 : CASE_FORMAT( _32BIT_TC_MASK )
181 : :
182 : : default:
183 : 0 : bRet = sal_False;
184 : 0 : break;
185 : : }
186 : :
187 : 1280712 : return bRet;
188 : : }
189 : :
190 : : // ------------------------------------------------------------------
191 : :
192 : 2963 : void BitmapReadAccess::ImplZeroInitUnusedBits()
193 : : {
194 : 2963 : const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
195 : :
196 [ + - ][ + - ]: 2963 : if( nWidth && nHeight && nScanSize && GetBuffer() )
[ + - ][ + - ]
[ + - ]
197 : : {
198 : : sal_uInt32 nBits;
199 : : bool bMsb;
200 : :
201 : 2963 : const sal_uLong nScanlineFormat = GetScanlineFormat();
202 [ + - + - : 2963 : switch( nScanlineFormat )
+ - + -
- ]
203 : : {
204 : : case( BMP_FORMAT_1BIT_MSB_PAL ):
205 : 55 : nBits = 1;
206 : 55 : bMsb = true;
207 : 55 : break;
208 : :
209 : : case( BMP_FORMAT_1BIT_LSB_PAL ):
210 : 0 : nBits = 1;
211 : 0 : bMsb = false;
212 : 0 : break;
213 : :
214 : : case( BMP_FORMAT_4BIT_MSN_PAL ):
215 : 16 : nBits = 4;
216 : 16 : bMsb = true;
217 : 16 : break;
218 : :
219 : : case( BMP_FORMAT_4BIT_LSN_PAL ):
220 : 0 : nBits = 4;
221 : 0 : bMsb = false;
222 : 0 : break;
223 : :
224 : : case( BMP_FORMAT_8BIT_PAL ):
225 : : case( BMP_FORMAT_8BIT_TC_MASK ):
226 : 1585 : bMsb = true;
227 : 1585 : nBits = 8;
228 : 1585 : break;
229 : :
230 : : case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
231 : : case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
232 : 0 : bMsb = true;
233 : 0 : nBits = 16;
234 : 0 : break;
235 : :
236 : : case( BMP_FORMAT_24BIT_TC_BGR ):
237 : : case( BMP_FORMAT_24BIT_TC_RGB ):
238 : : case( BMP_FORMAT_24BIT_TC_MASK ):
239 : 1307 : bMsb = true;
240 : 1307 : nBits = 24;
241 : 1307 : break;
242 : :
243 : : case( BMP_FORMAT_32BIT_TC_ABGR ):
244 : : case( BMP_FORMAT_32BIT_TC_ARGB ):
245 : : case( BMP_FORMAT_32BIT_TC_BGRA ):
246 : : case( BMP_FORMAT_32BIT_TC_RGBA ):
247 : : case( BMP_FORMAT_32BIT_TC_MASK ):
248 : 0 : bMsb = true;
249 : 0 : nBits = 32;
250 : 0 : break;
251 : :
252 : : default:
253 : : {
254 : : OSL_FAIL( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
255 : 0 : nBits = 0;
256 : 0 : bMsb = true;
257 : : }
258 : 0 : break;
259 : : }
260 : :
261 : 2963 : nBits *= nWidth;
262 [ + + ][ - + ]: 2963 : if( nScanSize % 4 || !bMsb )
263 : : {
264 : : DBG_ASSERT( 8*nScanSize >= nBits,
265 : : "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
266 : 1400 : const sal_uInt32 nLeftOverBits = 8*sizeof(sal_uInt8)*nScanSize - nBits;
267 [ + + ]: 1400 : if( nLeftOverBits != 0 ) // else there is really nothing to do
268 : : {
269 : 5 : const sal_uInt32 nBytes = (nLeftOverBits + 7U) >> 3U;
270 : : sal_uInt8 nMask;
271 : :
272 [ + - ]: 5 : if( bMsb )
273 : 5 : nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
274 : : else
275 : 0 : nMask = static_cast<sal_uInt8>(0xffU >> (nLeftOverBits & 3UL));
276 : :
277 : 5 : sal_uInt8* pLastBytes = (sal_uInt8*)GetBuffer() + ( nScanSize - nBytes );
278 [ + + ]: 255 : for( sal_uInt32 i = 0; i < nHeight; i++, pLastBytes += nScanSize )
279 : : {
280 : 250 : *pLastBytes &= nMask;
281 [ - + ]: 250 : for( sal_uInt32 j = 1; j < nBytes; j++ )
282 : 0 : pLastBytes[j] = 0;
283 : : }
284 : 1400 : }
285 : : }
286 [ + + ]: 1563 : else if( nBits & 0x1f )
287 : : {
288 : 1232 : sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
289 : 1232 : sal_uInt8* pLast4Bytes = (sal_uInt8*) GetBuffer() + ( nScanSize - 4 );
290 : :
291 : : #ifdef OSL_LITENDIAN
292 : 1232 : nMask = OSL_SWAPDWORD( nMask );
293 : : #endif
294 [ + + ]: 22659 : for( sal_uInt32 i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
295 : 19696 : ( *(sal_uInt32*) pLast4Bytes ) &= nMask;
296 : : }
297 : : }
298 : 2963 : }
299 : :
300 : : // ------------------------------------------------------------------
301 : :
302 : 968672 : sal_uInt16 BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
303 : : {
304 [ + - ]: 968672 : return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
305 : : }
306 : :
307 : : // ---------------------
308 : : // - BitmapWriteAccess -
309 : : // ---------------------
310 : :
311 : 458953 : BitmapWriteAccess::BitmapWriteAccess( Bitmap& rBitmap ) :
312 : : BitmapReadAccess( rBitmap, sal_True ),
313 : : mpLineColor ( NULL ),
314 : 458953 : mpFillColor ( NULL )
315 : : {
316 : 458953 : }
317 : :
318 : : // ------------------------------------------------------------------
319 : :
320 : 458953 : BitmapWriteAccess::~BitmapWriteAccess()
321 : : {
322 [ + + ]: 458953 : delete mpLineColor;
323 [ + + ]: 458953 : delete mpFillColor;
324 [ - + ]: 917906 : }
325 : :
326 : : // ------------------------------------------------------------------
327 : :
328 : 0 : void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
329 : : {
330 : : DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
331 : : DBG_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
332 : : DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
333 : :
334 [ # # # # ]: 0 : if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
[ # # ]
335 : 0 : ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
336 : : {
337 : 0 : memcpy( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
338 : : }
339 : : else
340 : : // TODO: use fastbmp infrastructure
341 [ # # ]: 0 : for( long nX = 0L, nWidth = Min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
342 [ # # ]: 0 : SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
343 : 0 : }
344 : :
345 : : // ------------------------------------------------------------------
346 : :
347 : 21110 : void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline,
348 : : sal_uLong nSrcScanlineFormat, sal_uLong nSrcScanlineSize )
349 : : {
350 : 21110 : const sal_uLong nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
351 : :
352 : : DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
353 : : DBG_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
354 : : ( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
355 : : "No copying possible between palette and non palette scanlines!" );
356 : :
357 : 21110 : const sal_uLong nCount = Min( GetScanlineSize(), nSrcScanlineSize );
358 : :
359 [ + - ]: 21110 : if( nCount )
360 : : {
361 [ + + ]: 21110 : if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
362 : 15704 : memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
363 : : else
364 : : {
365 : : DBG_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK &&
366 : : nFormat != BMP_FORMAT_16BIT_TC_MSB_MASK && nFormat != BMP_FORMAT_16BIT_TC_LSB_MASK &&
367 : : nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
368 : : "No support for pixel formats with color masks yet!" );
369 : :
370 : : // TODO: use fastbmp infrastructure
371 : : FncGetPixel pFncGetPixel;
372 : :
373 [ - - - - : 5406 : switch( nFormat )
- - - - -
+ - - - -
- - - ]
374 : : {
375 : 0 : case( BMP_FORMAT_1BIT_MSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
376 : 0 : case( BMP_FORMAT_1BIT_LSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
377 : 0 : case( BMP_FORMAT_4BIT_MSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
378 : 0 : case( BMP_FORMAT_4BIT_LSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
379 : 0 : case( BMP_FORMAT_8BIT_PAL ): pFncGetPixel = GetPixelFor_8BIT_PAL; break;
380 : 0 : case( BMP_FORMAT_8BIT_TC_MASK ): pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
381 : 0 : case( BMP_FORMAT_16BIT_TC_MSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_MSB_MASK; break;
382 : 0 : case( BMP_FORMAT_16BIT_TC_LSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_LSB_MASK; break;
383 : 0 : case( BMP_FORMAT_24BIT_TC_BGR ): pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
384 : 5406 : case( BMP_FORMAT_24BIT_TC_RGB ): pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
385 : 0 : case( BMP_FORMAT_24BIT_TC_MASK ): pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
386 : 0 : case( BMP_FORMAT_32BIT_TC_ABGR ): pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
387 : 0 : case( BMP_FORMAT_32BIT_TC_ARGB ): pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
388 : 0 : case( BMP_FORMAT_32BIT_TC_BGRA ): pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
389 : 0 : case( BMP_FORMAT_32BIT_TC_RGBA ): pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
390 : 0 : case( BMP_FORMAT_32BIT_TC_MASK ): pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
391 : :
392 : : default:
393 : 0 : pFncGetPixel = NULL;
394 : 0 : break;
395 : : }
396 : :
397 [ + - ]: 5406 : if( pFncGetPixel )
398 : : {
399 [ + - ]: 5406 : const ColorMask aDummyMask;
400 : :
401 [ + + ]: 193672 : for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
402 [ + - ][ + - ]: 193672 : SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
403 : : }
404 : : }
405 : : }
406 : 21110 : }
407 : :
408 : :
409 : : // ------------------------------------------------------------------
410 : :
411 : 0 : void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
412 : : {
413 : : DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
414 : :
415 [ # # # # ]: 0 : if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
[ # # ]
416 : 0 : ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
417 : : {
418 : 0 : const long nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() );
419 : 0 : const sal_uLong nCount = nHeight * mpBuffer->mnScanlineSize;
420 : :
421 : 0 : memcpy( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
422 : : }
423 : : else
424 [ # # ]: 0 : for( long nY = 0L, nHeight = Min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
425 : 0 : CopyScanline( nY, rReadAcc );
426 : 0 : }
427 : :
428 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|