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