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 196355 : BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap, sal_Bool bModify ) :
30 : mpBuffer ( NULL ),
31 : mpScanBuf ( NULL ),
32 : mFncGetPixel ( NULL ),
33 : mFncSetPixel ( NULL ),
34 196355 : mbModify ( bModify )
35 : {
36 196355 : ImplCreate( rBitmap );
37 196355 : }
38 :
39 385388 : BitmapReadAccess::BitmapReadAccess( Bitmap& rBitmap ) :
40 : mpBuffer ( NULL ),
41 : mpScanBuf ( NULL ),
42 : mFncGetPixel ( NULL ),
43 : mFncSetPixel ( NULL ),
44 385388 : mbModify ( sal_False )
45 : {
46 385388 : ImplCreate( rBitmap );
47 385388 : }
48 :
49 1548874 : BitmapReadAccess::~BitmapReadAccess()
50 : {
51 581743 : ImplDestroy();
52 967131 : }
53 :
54 581743 : void BitmapReadAccess::ImplCreate( Bitmap& rBitmap )
55 : {
56 581743 : ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
57 :
58 : DBG_ASSERT( pImpBmp, "Forbidden Access to empty bitmap!" );
59 :
60 581743 : if( pImpBmp )
61 : {
62 581741 : if( mbModify && !maBitmap.ImplGetImpBitmap() )
63 : {
64 196353 : rBitmap.ImplMakeUnique();
65 196353 : pImpBmp = rBitmap.ImplGetImpBitmap();
66 : }
67 : else
68 : {
69 : DBG_ASSERT( !mbModify || pImpBmp->ImplGetRefCount() == 2,
70 : "Unpredictable results: bitmap is referenced more than once!" );
71 : }
72 :
73 581741 : mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
74 :
75 581741 : if( !mpBuffer )
76 : {
77 4 : ImpBitmap* pNewImpBmp = new ImpBitmap;
78 :
79 4 : if( pNewImpBmp->ImplCreate( *pImpBmp, rBitmap.GetBitCount() ) )
80 : {
81 0 : pImpBmp = pNewImpBmp;
82 0 : rBitmap.ImplSetImpBitmap( pImpBmp );
83 0 : mpBuffer = pImpBmp->ImplAcquireBuffer( !mbModify );
84 : }
85 : else
86 4 : delete pNewImpBmp;
87 : }
88 :
89 581741 : if( mpBuffer )
90 : {
91 581737 : const long nHeight = mpBuffer->mnHeight;
92 581737 : Scanline pTmpLine = mpBuffer->mpBits;
93 :
94 581737 : mpScanBuf = new Scanline[ nHeight ];
95 581737 : maColorMask = mpBuffer->maColorMask;
96 :
97 581737 : if( BMP_SCANLINE_ADJUSTMENT( mpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
98 : {
99 0 : for( long nY = 0L; nY < nHeight; nY++, pTmpLine += mpBuffer->mnScanlineSize )
100 0 : mpScanBuf[ nY ] = pTmpLine;
101 : }
102 : else
103 : {
104 69994897 : for( long nY = nHeight - 1; nY >= 0; nY--, pTmpLine += mpBuffer->mnScanlineSize )
105 69413160 : mpScanBuf[ nY ] = pTmpLine;
106 : }
107 :
108 581737 : if( !ImplSetAccessPointers( BMP_SCANLINE_FORMAT( mpBuffer->mnFormat ) ) )
109 : {
110 0 : delete[] mpScanBuf;
111 0 : mpScanBuf = NULL;
112 :
113 0 : pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
114 0 : mpBuffer = NULL;
115 : }
116 : else
117 581737 : maBitmap = rBitmap;
118 : }
119 : }
120 581743 : }
121 :
122 581743 : void BitmapReadAccess::ImplDestroy()
123 : {
124 581743 : ImpBitmap* pImpBmp = maBitmap.ImplGetImpBitmap();
125 :
126 581743 : delete[] mpScanBuf;
127 581743 : mpScanBuf = NULL;
128 :
129 581743 : if( mpBuffer && pImpBmp )
130 : {
131 581737 : pImpBmp->ImplReleaseBuffer( mpBuffer, !mbModify );
132 581737 : mpBuffer = NULL;
133 : }
134 581743 : }
135 :
136 581737 : sal_Bool BitmapReadAccess::ImplSetAccessPointers( sal_uLong nFormat )
137 : {
138 581737 : sal_Bool bRet = sal_True;
139 :
140 581737 : switch( nFormat )
141 : {
142 3786 : CASE_FORMAT( _1BIT_MSB_PAL )
143 0 : CASE_FORMAT( _1BIT_LSB_PAL )
144 304 : CASE_FORMAT( _4BIT_MSN_PAL )
145 0 : CASE_FORMAT( _4BIT_LSN_PAL )
146 329074 : CASE_FORMAT( _8BIT_PAL )
147 0 : CASE_FORMAT( _8BIT_TC_MASK )
148 0 : CASE_FORMAT( _16BIT_TC_MSB_MASK )
149 0 : CASE_FORMAT( _16BIT_TC_LSB_MASK )
150 248573 : CASE_FORMAT( _24BIT_TC_BGR )
151 0 : CASE_FORMAT( _24BIT_TC_RGB )
152 0 : CASE_FORMAT( _24BIT_TC_MASK )
153 0 : CASE_FORMAT( _32BIT_TC_ABGR )
154 0 : CASE_FORMAT( _32BIT_TC_ARGB )
155 0 : CASE_FORMAT( _32BIT_TC_BGRA )
156 0 : CASE_FORMAT( _32BIT_TC_RGBA )
157 0 : CASE_FORMAT( _32BIT_TC_MASK )
158 :
159 : default:
160 0 : bRet = sal_False;
161 0 : break;
162 : }
163 :
164 581737 : return bRet;
165 : }
166 :
167 277 : void BitmapReadAccess::ImplZeroInitUnusedBits()
168 : {
169 277 : const sal_uInt32 nWidth = Width(), nHeight = Height(), nScanSize = GetScanlineSize();
170 :
171 277 : if( nWidth && nHeight && nScanSize && GetBuffer() )
172 : {
173 : sal_uInt32 nBits;
174 : bool bMsb;
175 :
176 277 : const sal_uLong nScanlineFormat = GetScanlineFormat();
177 277 : switch( nScanlineFormat )
178 : {
179 : case( BMP_FORMAT_1BIT_MSB_PAL ):
180 28 : nBits = 1;
181 28 : bMsb = true;
182 28 : break;
183 :
184 : case( BMP_FORMAT_1BIT_LSB_PAL ):
185 0 : nBits = 1;
186 0 : bMsb = false;
187 0 : break;
188 :
189 : case( BMP_FORMAT_4BIT_MSN_PAL ):
190 9 : nBits = 4;
191 9 : bMsb = true;
192 9 : break;
193 :
194 : case( BMP_FORMAT_4BIT_LSN_PAL ):
195 0 : nBits = 4;
196 0 : bMsb = false;
197 0 : break;
198 :
199 : case( BMP_FORMAT_8BIT_PAL ):
200 : case( BMP_FORMAT_8BIT_TC_MASK ):
201 182 : bMsb = true;
202 182 : nBits = 8;
203 182 : break;
204 :
205 : case( BMP_FORMAT_16BIT_TC_MSB_MASK ):
206 : case( BMP_FORMAT_16BIT_TC_LSB_MASK ):
207 0 : bMsb = true;
208 0 : nBits = 16;
209 0 : break;
210 :
211 : case( BMP_FORMAT_24BIT_TC_BGR ):
212 : case( BMP_FORMAT_24BIT_TC_RGB ):
213 : case( BMP_FORMAT_24BIT_TC_MASK ):
214 58 : bMsb = true;
215 58 : nBits = 24;
216 58 : break;
217 :
218 : case( BMP_FORMAT_32BIT_TC_ABGR ):
219 : case( BMP_FORMAT_32BIT_TC_ARGB ):
220 : case( BMP_FORMAT_32BIT_TC_BGRA ):
221 : case( BMP_FORMAT_32BIT_TC_RGBA ):
222 : case( BMP_FORMAT_32BIT_TC_MASK ):
223 0 : bMsb = true;
224 0 : nBits = 32;
225 0 : break;
226 :
227 : default:
228 : {
229 : OSL_FAIL( "BitmapWriteAccess::ZeroInitUnusedBits: Unsupported pixel format");
230 0 : nBits = 0;
231 0 : bMsb = true;
232 : }
233 0 : break;
234 : }
235 :
236 277 : nBits *= nWidth;
237 277 : if( nScanSize % 4 || !bMsb )
238 : {
239 : DBG_ASSERT( 8*nScanSize >= nBits,
240 : "BitmapWriteAccess::ZeroInitUnusedBits: span size smaller than width?!");
241 113 : const sal_uInt32 nLeftOverBits = 8*sizeof(sal_uInt8)*nScanSize - nBits;
242 113 : if( nLeftOverBits != 0 ) // else there is really nothing to do
243 : {
244 11 : const sal_uInt32 nBytes = (nLeftOverBits + 7U) >> 3U;
245 : sal_uInt8 nMask;
246 :
247 11 : if( bMsb )
248 11 : nMask = static_cast<sal_uInt8>(0xffU << (nLeftOverBits & 3UL));
249 : else
250 0 : nMask = static_cast<sal_uInt8>(0xffU >> (nLeftOverBits & 3UL));
251 :
252 11 : sal_uInt8* pLastBytes = (sal_uInt8*)GetBuffer() + ( nScanSize - nBytes );
253 166 : for( sal_uInt32 i = 0; i < nHeight; i++, pLastBytes += nScanSize )
254 : {
255 155 : *pLastBytes &= nMask;
256 155 : for( sal_uInt32 j = 1; j < nBytes; j++ )
257 0 : pLastBytes[j] = 0;
258 : }
259 113 : }
260 : }
261 164 : else if( nBits & 0x1f )
262 : {
263 29 : sal_uInt32 nMask = 0xffffffff << ( ( nScanSize << 3 ) - nBits );
264 29 : sal_uInt8* pLast4Bytes = (sal_uInt8*) GetBuffer() + ( nScanSize - 4 );
265 :
266 : #ifdef OSL_LITENDIAN
267 29 : nMask = OSL_SWAPDWORD( nMask );
268 : #endif
269 3206 : for( sal_uInt32 i = 0; i < nHeight; i++, pLast4Bytes += nScanSize )
270 3177 : ( *(sal_uInt32*) pLast4Bytes ) &= nMask;
271 : }
272 : }
273 277 : }
274 :
275 625188 : sal_uInt16 BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColor ) const
276 : {
277 625188 : return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
278 : }
279 :
280 196355 : BitmapWriteAccess::BitmapWriteAccess( Bitmap& rBitmap ) :
281 : BitmapReadAccess( rBitmap, sal_True ),
282 : mpLineColor ( NULL ),
283 196355 : mpFillColor ( NULL )
284 : {
285 196355 : }
286 :
287 589065 : BitmapWriteAccess::~BitmapWriteAccess()
288 : {
289 196355 : delete mpLineColor;
290 196355 : delete mpFillColor;
291 392710 : }
292 :
293 0 : void BitmapWriteAccess::CopyScanline( long nY, const BitmapReadAccess& rReadAcc )
294 : {
295 : DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
296 : DBG_ASSERT( nY < rReadAcc.Height(), "y-coordinate in source out of range!" );
297 : DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
298 :
299 0 : if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
300 0 : ( GetScanlineSize() >= rReadAcc.GetScanlineSize() ) )
301 : {
302 0 : memcpy( mpScanBuf[ nY ], rReadAcc.GetScanline( nY ), rReadAcc.GetScanlineSize() );
303 : }
304 : else
305 : // TODO: use fastbmp infrastructure
306 0 : for( long nX = 0L, nWidth = std::min( mpBuffer->mnWidth, rReadAcc.Width() ); nX < nWidth; nX++ )
307 0 : SetPixel( nY, nX, rReadAcc.GetPixel( nY, nX ) );
308 0 : }
309 :
310 :
311 10501 : void BitmapWriteAccess::CopyScanline( long nY, ConstScanline aSrcScanline,
312 : sal_uLong nSrcScanlineFormat, sal_uLong nSrcScanlineSize )
313 : {
314 10501 : const sal_uLong nFormat = BMP_SCANLINE_FORMAT( nSrcScanlineFormat );
315 :
316 : DBG_ASSERT( ( nY >= 0 ) && ( nY < mpBuffer->mnHeight ), "y-coordinate in destination out of range!" );
317 : DBG_ASSERT( ( HasPalette() && nFormat <= BMP_FORMAT_8BIT_PAL ) ||
318 : ( !HasPalette() && nFormat > BMP_FORMAT_8BIT_PAL ),
319 : "No copying possible between palette and non palette scanlines!" );
320 :
321 10501 : const sal_uLong nCount = std::min( GetScanlineSize(), nSrcScanlineSize );
322 :
323 10501 : if( nCount )
324 : {
325 10501 : if( GetScanlineFormat() == BMP_SCANLINE_FORMAT( nSrcScanlineFormat ) )
326 7897 : memcpy( mpScanBuf[ nY ], aSrcScanline, nCount );
327 : else
328 : {
329 : DBG_ASSERT( nFormat != BMP_FORMAT_8BIT_TC_MASK &&
330 : nFormat != BMP_FORMAT_16BIT_TC_MSB_MASK && nFormat != BMP_FORMAT_16BIT_TC_LSB_MASK &&
331 : nFormat != BMP_FORMAT_24BIT_TC_MASK && nFormat != BMP_FORMAT_32BIT_TC_MASK,
332 : "No support for pixel formats with color masks yet!" );
333 :
334 : // TODO: use fastbmp infrastructure
335 : FncGetPixel pFncGetPixel;
336 :
337 2604 : switch( nFormat )
338 : {
339 0 : case( BMP_FORMAT_1BIT_MSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_MSB_PAL; break;
340 0 : case( BMP_FORMAT_1BIT_LSB_PAL ): pFncGetPixel = GetPixelFor_1BIT_LSB_PAL; break;
341 0 : case( BMP_FORMAT_4BIT_MSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_MSN_PAL; break;
342 0 : case( BMP_FORMAT_4BIT_LSN_PAL ): pFncGetPixel = GetPixelFor_4BIT_LSN_PAL; break;
343 0 : case( BMP_FORMAT_8BIT_PAL ): pFncGetPixel = GetPixelFor_8BIT_PAL; break;
344 0 : case( BMP_FORMAT_8BIT_TC_MASK ): pFncGetPixel = GetPixelFor_8BIT_TC_MASK; break;
345 0 : case( BMP_FORMAT_16BIT_TC_MSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_MSB_MASK; break;
346 0 : case( BMP_FORMAT_16BIT_TC_LSB_MASK ): pFncGetPixel = GetPixelFor_16BIT_TC_LSB_MASK; break;
347 0 : case( BMP_FORMAT_24BIT_TC_BGR ): pFncGetPixel = GetPixelFor_24BIT_TC_BGR; break;
348 2604 : case( BMP_FORMAT_24BIT_TC_RGB ): pFncGetPixel = GetPixelFor_24BIT_TC_RGB; break;
349 0 : case( BMP_FORMAT_24BIT_TC_MASK ): pFncGetPixel = GetPixelFor_24BIT_TC_MASK; break;
350 0 : case( BMP_FORMAT_32BIT_TC_ABGR ): pFncGetPixel = GetPixelFor_32BIT_TC_ABGR; break;
351 0 : case( BMP_FORMAT_32BIT_TC_ARGB ): pFncGetPixel = GetPixelFor_32BIT_TC_ARGB; break;
352 0 : case( BMP_FORMAT_32BIT_TC_BGRA ): pFncGetPixel = GetPixelFor_32BIT_TC_BGRA; break;
353 0 : case( BMP_FORMAT_32BIT_TC_RGBA ): pFncGetPixel = GetPixelFor_32BIT_TC_RGBA; break;
354 0 : case( BMP_FORMAT_32BIT_TC_MASK ): pFncGetPixel = GetPixelFor_32BIT_TC_MASK; break;
355 :
356 : default:
357 0 : pFncGetPixel = NULL;
358 0 : break;
359 : }
360 :
361 2604 : if( pFncGetPixel )
362 : {
363 2604 : const ColorMask aDummyMask;
364 :
365 103922 : for( long nX = 0L, nWidth = mpBuffer->mnWidth; nX < nWidth; nX++ )
366 103922 : SetPixel( nY, nX, pFncGetPixel( aSrcScanline, nX, aDummyMask ) );
367 : }
368 : }
369 : }
370 10501 : }
371 :
372 0 : void BitmapWriteAccess::CopyBuffer( const BitmapReadAccess& rReadAcc )
373 : {
374 : DBG_ASSERT( ( HasPalette() && rReadAcc.HasPalette() ) || ( !HasPalette() && !rReadAcc.HasPalette() ), "No copying possible between palette bitmap and TC bitmap!" );
375 :
376 0 : if( ( GetScanlineFormat() == rReadAcc.GetScanlineFormat() ) &&
377 0 : ( GetScanlineSize() == rReadAcc.GetScanlineSize() ) )
378 : {
379 0 : const long nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() );
380 0 : const sal_uLong nCount = nHeight * mpBuffer->mnScanlineSize;
381 :
382 0 : memcpy( mpBuffer->mpBits, rReadAcc.GetBuffer(), nCount );
383 : }
384 : else
385 0 : for( long nY = 0L, nHeight = std::min( mpBuffer->mnHeight, rReadAcc.Height() ); nY < nHeight; nY++ )
386 0 : CopyScanline( nY, rReadAcc );
387 465 : }
388 :
389 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|