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 : #include <bmpfast.hxx>
21 : #include <tools/debug.hxx>
22 : #include <vcl/bmpacc.hxx>
23 :
24 : #define FAST_ARGB_BGRA
25 :
26 : #include <stdlib.h>
27 :
28 : typedef unsigned char PIXBYTE;
29 :
30 : class BasePixelPtr
31 : {
32 : public:
33 0 : BasePixelPtr( PIXBYTE* p = NULL ) : mpPixel( p ) {}
34 0 : void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
35 0 : PIXBYTE* GetRawPtr( void ) const { return mpPixel; }
36 0 : void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
37 :
38 : protected:
39 : PIXBYTE* mpPixel;
40 : };
41 :
42 : template <sal_uLong PIXFMT>
43 : class TrueColorPixelPtr : public BasePixelPtr
44 : {
45 : public:
46 : PIXBYTE GetRed() const;
47 : PIXBYTE GetGreen() const;
48 : PIXBYTE GetBlue() const;
49 : PIXBYTE GetAlpha() const;
50 :
51 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const;
52 : void SetAlpha( PIXBYTE a ) const;
53 : void operator++(int);
54 : };
55 :
56 : // template specializations for truecolor pixel formats
57 : template <>
58 0 : class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> : public BasePixelPtr
59 : {
60 : public:
61 0 : void operator++() { mpPixel += 3; }
62 :
63 0 : PIXBYTE GetRed() const { return mpPixel[0]; }
64 0 : PIXBYTE GetGreen() const { return mpPixel[1]; }
65 0 : PIXBYTE GetBlue() const { return mpPixel[2]; }
66 0 : PIXBYTE GetAlpha() const { return 0; }
67 0 : void SetAlpha( PIXBYTE ) const {}
68 :
69 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
70 : {
71 0 : mpPixel[0] = r;
72 0 : mpPixel[1] = g;
73 0 : mpPixel[2] = b;
74 0 : }
75 : };
76 :
77 : template <>
78 0 : class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR> : public BasePixelPtr
79 : {
80 : public:
81 0 : void operator++() { mpPixel += 3; }
82 :
83 0 : PIXBYTE GetRed() const { return mpPixel[2]; }
84 0 : PIXBYTE GetGreen() const { return mpPixel[1]; }
85 0 : PIXBYTE GetBlue() const { return mpPixel[0]; }
86 0 : PIXBYTE GetAlpha() const { return 0; }
87 0 : void SetAlpha( PIXBYTE ) const {}
88 :
89 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
90 : {
91 0 : mpPixel[0] = b;
92 0 : mpPixel[1] = g;
93 0 : mpPixel[2] = r;
94 0 : }
95 : };
96 :
97 : template <>
98 0 : class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> : public BasePixelPtr
99 : {
100 : public:
101 0 : void operator++() { mpPixel += 4; }
102 :
103 0 : PIXBYTE GetRed() const { return mpPixel[1]; }
104 0 : PIXBYTE GetGreen() const { return mpPixel[2]; }
105 0 : PIXBYTE GetBlue() const { return mpPixel[3]; }
106 0 : PIXBYTE GetAlpha() const { return mpPixel[0]; }
107 0 : void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
108 :
109 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
110 : {
111 0 : mpPixel[1] = r;
112 0 : mpPixel[2] = g;
113 0 : mpPixel[3] = b;
114 0 : }
115 : };
116 :
117 : template <>
118 0 : class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR> : public BasePixelPtr
119 : {
120 : public:
121 0 : void operator++() { mpPixel += 4; }
122 :
123 0 : PIXBYTE GetRed() const { return mpPixel[3]; }
124 0 : PIXBYTE GetGreen() const { return mpPixel[2]; }
125 0 : PIXBYTE GetBlue() const { return mpPixel[1]; }
126 0 : PIXBYTE GetAlpha() const { return mpPixel[0]; }
127 0 : void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
128 :
129 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
130 : {
131 0 : mpPixel[1] = b;
132 0 : mpPixel[2] = g;
133 0 : mpPixel[3] = r;
134 0 : }
135 : };
136 :
137 : template <>
138 0 : class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> : public BasePixelPtr
139 : {
140 : public:
141 0 : void operator++() { mpPixel += 4; }
142 :
143 0 : PIXBYTE GetRed() const { return mpPixel[0]; }
144 0 : PIXBYTE GetGreen() const { return mpPixel[1]; }
145 0 : PIXBYTE GetBlue() const { return mpPixel[2]; }
146 0 : PIXBYTE GetAlpha() const { return mpPixel[3]; }
147 0 : void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
148 :
149 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
150 : {
151 0 : mpPixel[0] = r;
152 0 : mpPixel[1] = g;
153 0 : mpPixel[2] = b;
154 0 : }
155 : };
156 :
157 : template <>
158 0 : class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA> : public BasePixelPtr
159 : {
160 : public:
161 0 : void operator++() { mpPixel += 4; }
162 :
163 0 : PIXBYTE GetRed() const { return mpPixel[2]; }
164 0 : PIXBYTE GetGreen() const { return mpPixel[1]; }
165 0 : PIXBYTE GetBlue() const { return mpPixel[0]; }
166 0 : PIXBYTE GetAlpha() const { return mpPixel[3]; }
167 0 : void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
168 :
169 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
170 : {
171 0 : mpPixel[0] = b;
172 0 : mpPixel[1] = g;
173 0 : mpPixel[2] = r;
174 0 : }
175 : };
176 :
177 : template <>
178 0 : class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK> : public BasePixelPtr
179 : {
180 : public:
181 0 : void operator++() { mpPixel += 2; }
182 :
183 : // TODO: non565-RGB
184 0 : PIXBYTE GetRed() const { return (mpPixel[0] & 0xF8U); }
185 0 : PIXBYTE GetGreen() const { return (mpPixel[0]<<5U) | ((mpPixel[1]>>3U)&28U); }
186 0 : PIXBYTE GetBlue() const { return (mpPixel[1]<<3U); }
187 0 : PIXBYTE GetAlpha() const { return 0; }
188 0 : void SetAlpha( PIXBYTE ) const {}
189 :
190 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
191 : {
192 0 : mpPixel[0] = ((g >> 5U) & 7U) | (r & 0xF8U);
193 0 : mpPixel[1] = ((g & 28U)<< 3U) | (b >> 3U);
194 0 : }
195 : };
196 :
197 : template <>
198 0 : class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK> : public BasePixelPtr
199 : {
200 : public:
201 0 : void operator++() { mpPixel += 2; }
202 :
203 : // TODO: non565-RGB
204 0 : PIXBYTE GetRed() const { return (mpPixel[1] & 0xF8U); }
205 0 : PIXBYTE GetGreen() const { return (mpPixel[1]<<5U) | ((mpPixel[0]>>3U)&28U); }
206 0 : PIXBYTE GetBlue() const { return (mpPixel[0]<<3U); }
207 0 : PIXBYTE GetAlpha() const { return 0; }
208 0 : void SetAlpha( PIXBYTE ) const {}
209 :
210 0 : void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
211 : {
212 0 : mpPixel[0] = ((g & 28U)<< 3U) | (b >> 3U);
213 0 : mpPixel[1] = ((g >> 5U) & 7U) | (r & 0xF8U);
214 0 : }
215 : };
216 :
217 : template <>
218 0 : class TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK> : public BasePixelPtr
219 : {
220 : public:
221 0 : void operator++() { mpPixel += 1; }
222 0 : PIXBYTE GetAlpha() const { return mpPixel[0]; }
223 : void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
224 : void SetColor( PIXBYTE, PIXBYTE, PIXBYTE ) const {}
225 : };
226 :
227 : // TODO: for some reason many Alpha maps are BMP_FORMAT_8BIT_PAL
228 : // they should be BMP_FORMAT_8BIT_TC_MASK
229 : template <>
230 0 : class TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL>
231 : : public TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK>
232 : {};
233 :
234 : // converting truecolor formats
235 : template <sal_uLong SRCFMT, sal_uLong DSTFMT>
236 0 : inline void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst,
237 : const TrueColorPixelPtr<SRCFMT>& rSrc )
238 : {
239 0 : rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() );
240 0 : rDst.SetAlpha( rSrc.GetAlpha() );
241 0 : }
242 :
243 : template <>
244 0 : inline void ImplConvertPixel<BMP_FORMAT_16BIT_TC_LSB_MASK, BMP_FORMAT_16BIT_TC_MSB_MASK> (
245 : const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK>& rDst,
246 : const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK>& rSrc )
247 : {
248 : // byte swapping
249 0 : const PIXBYTE* pSrc = rSrc.GetRawPtr();
250 0 : PIXBYTE* pDst = rDst.GetRawPtr();
251 0 : pDst[1] = pSrc[0];
252 0 : pDst[0] = pSrc[1];
253 0 : }
254 :
255 : template <sal_uLong SRCFMT, sal_uLong DSTFMT>
256 0 : inline void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst,
257 : const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount )
258 : {
259 0 : TrueColorPixelPtr<DSTFMT> aDst( rDst );
260 0 : TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
261 0 : while( --nPixelCount >= 0 )
262 : {
263 0 : ImplConvertPixel( aDst, aSrc );
264 0 : ++aSrc;
265 0 : ++aDst;
266 : }
267 0 : }
268 :
269 : // alpha blending truecolor pixels
270 : template <unsigned ALPHABITS, sal_uLong SRCFMT, sal_uLong DSTFMT>
271 0 : inline void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst,
272 : const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal )
273 : {
274 0 : if( !nAlphaVal )
275 0 : ImplConvertPixel( rDst, rSrc );
276 0 : else if( nAlphaVal != ~(~0 << ALPHABITS) )
277 : {
278 : static const unsigned nAlphaShift = (ALPHABITS > 8) ? 8 : ALPHABITS;
279 : if( ALPHABITS > nAlphaShift )
280 : nAlphaVal >>= ALPHABITS - nAlphaShift;
281 :
282 0 : int nR = rDst.GetRed();
283 0 : int nS = rSrc.GetRed();
284 0 : nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
285 :
286 0 : int nG = rDst.GetGreen();
287 0 : nS = rSrc.GetGreen();
288 0 : nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
289 :
290 0 : int nB = rDst.GetBlue();
291 0 : nS = rSrc.GetBlue();
292 0 : nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
293 :
294 0 : rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
295 0 : sal::static_int_cast<PIXBYTE>(nG),
296 0 : sal::static_int_cast<PIXBYTE>(nB) );
297 : }
298 0 : }
299 :
300 : template <unsigned ALPHABITS, sal_uLong MASKFMT, sal_uLong SRCFMT, sal_uLong DSTFMT>
301 0 : inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
302 : const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk,
303 : int nPixelCount )
304 : {
305 0 : TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
306 0 : TrueColorPixelPtr<DSTFMT> aDst( rDst );
307 0 : TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
308 0 : while( --nPixelCount >= 0 )
309 : {
310 0 : ImplBlendPixels<ALPHABITS>( aDst, aSrc, aMsk.GetAlpha() );
311 0 : ++aDst;
312 0 : ++aSrc;
313 0 : ++aMsk;
314 : }
315 0 : }
316 :
317 : template <unsigned ALPHABITS, sal_uLong SRCFMT, sal_uLong DSTFMT>
318 : inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
319 : const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal,
320 : int nPixelCount )
321 : {
322 : if( nAlphaVal == ~(~0 << ALPHABITS) )
323 : ImplConvertLine( rDst, rSrc, nPixelCount );
324 : else if( nAlphaVal )
325 : {
326 : TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
327 : TrueColorPixelPtr<DSTFMT> aDst( rDst );
328 : while( --nPixelCount >= 0 )
329 : {
330 : ImplBlendPixels<ALPHABITS>( aDst, aSrc, nAlphaVal );
331 : ++aDst;
332 : ++aSrc;
333 : }
334 : }
335 : }
336 :
337 0 : static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
338 : {
339 0 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
340 0 : int nDstLinestep = rDstBuffer.mnScanlineSize;
341 :
342 0 : const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
343 0 : PIXBYTE* pRawDst = rDstBuffer.mpBits;
344 :
345 : // source and destination don't match upside down
346 0 : if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
347 : {
348 0 : pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
349 0 : nDstLinestep = -rDstBuffer.mnScanlineSize;
350 : }
351 0 : else if( nSrcLinestep == nDstLinestep )
352 : {
353 0 : memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
354 0 : return true;
355 : }
356 :
357 0 : int nByteWidth = nSrcLinestep;
358 0 : if( nByteWidth > rDstBuffer.mnScanlineSize )
359 0 : nByteWidth = rDstBuffer.mnScanlineSize;
360 :
361 0 : for( int y = rSrcBuffer.mnHeight; --y >= 0; )
362 : {
363 0 : memcpy( pRawDst, pRawSrc, nByteWidth );
364 0 : pRawSrc += nSrcLinestep;
365 0 : pRawDst += nDstLinestep;
366 : }
367 :
368 0 : return true;
369 : }
370 :
371 : template <sal_uLong DSTFMT,sal_uLong SRCFMT>
372 0 : bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
373 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
374 : {
375 : // help the compiler to avoid instantiations of unneeded conversions
376 : DBG_ASSERT( SRCFMT != DSTFMT, "ImplConvertToBitmap into same format");
377 : if( SRCFMT == DSTFMT )
378 0 : return false;
379 :
380 0 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
381 0 : int nDstLinestep = rDstBuffer.mnScanlineSize;
382 :
383 0 : TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
384 :
385 : // source and destination don't match upside down
386 0 : if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
387 : {
388 0 : aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
389 0 : nDstLinestep = -nDstLinestep;
390 : }
391 :
392 0 : for( int y = rSrcBuffer.mnHeight; --y >= 0; )
393 : {
394 0 : ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
395 0 : rSrcLine.AddByteOffset( nSrcLinestep );
396 0 : aDstLine.AddByteOffset( nDstLinestep );
397 : }
398 :
399 0 : return true;
400 : }
401 :
402 : template <sal_uLong SRCFMT>
403 0 : inline bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
404 : {
405 0 : TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
406 :
407 : // select the matching instantiation for the destination's bitmap format
408 0 : switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
409 : {
410 : case BMP_FORMAT_1BIT_MSB_PAL:
411 : case BMP_FORMAT_1BIT_LSB_PAL:
412 : case BMP_FORMAT_4BIT_MSN_PAL:
413 : case BMP_FORMAT_4BIT_LSN_PAL:
414 : case BMP_FORMAT_8BIT_PAL:
415 0 : break;
416 :
417 : case BMP_FORMAT_8BIT_TC_MASK:
418 : // return ImplConvertToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc );
419 : case BMP_FORMAT_24BIT_TC_MASK:
420 : // return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc );
421 : case BMP_FORMAT_32BIT_TC_MASK:
422 : // return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc );
423 0 : break;
424 :
425 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
426 0 : return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc );
427 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
428 0 : return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc );
429 :
430 : case BMP_FORMAT_24BIT_TC_BGR:
431 0 : return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc );
432 : case BMP_FORMAT_24BIT_TC_RGB:
433 0 : return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc );
434 :
435 : case BMP_FORMAT_32BIT_TC_ABGR:
436 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc );
437 : #ifdef FAST_ARGB_BGRA
438 : case BMP_FORMAT_32BIT_TC_ARGB:
439 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc );
440 : case BMP_FORMAT_32BIT_TC_BGRA:
441 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc );
442 : #endif
443 : case BMP_FORMAT_32BIT_TC_RGBA:
444 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc );
445 : }
446 :
447 : static int nNotAccelerated = 0;
448 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
449 : "vcl.gdi",
450 : "ImplConvertFromBitmap for not accelerated case (" << std::hex << rSrc.mnFormat << "->" << rDst.mnFormat << ")" );
451 :
452 0 : return false;
453 : }
454 :
455 : // A universal stretching conversion is overkill in most common situations
456 : // => performance benefits for speeding up the non-stretching cases
457 0 : bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
458 : const SalTwoRect& rTR )
459 : {
460 : // TODO:horizontal mirroring not implemented yet
461 0 : if( rTR.mnDestWidth < 0 )
462 0 : return false;
463 : // vertical mirroring
464 0 : if( rTR.mnDestHeight < 0 )
465 : // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
466 0 : return false;
467 :
468 : // offseted conversion is not implemented yet
469 0 : if( rTR.mnSrcX || rTR.mnSrcY )
470 0 : return false;
471 0 : if( rTR.mnDestX || rTR.mnDestY )
472 0 : return false;
473 :
474 : // stretched conversion is not implemented yet
475 0 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
476 0 : return false;
477 0 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
478 0 : return false;
479 :
480 : // check source image size
481 0 : if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
482 0 : return false;
483 0 : if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
484 0 : return false;
485 :
486 : // check dest image size
487 0 : if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
488 0 : return false;
489 0 : if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
490 0 : return false;
491 :
492 0 : const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
493 0 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
494 :
495 : // TODO: also implement conversions for 16bit colormasks with non-565 format
496 0 : if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
497 0 : if( rSrc.maColorMask.GetRedMask() != 0xF800
498 0 : || rSrc.maColorMask.GetGreenMask()!= 0x07E0
499 0 : || rSrc.maColorMask.GetBlueMask() != 0x001F )
500 0 : return false;
501 0 : if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
502 0 : if( rDst.maColorMask.GetRedMask() != 0xF800
503 0 : || rDst.maColorMask.GetGreenMask()!= 0x07E0
504 0 : || rDst.maColorMask.GetBlueMask() != 0x001F )
505 0 : return false;
506 :
507 : // special handling of trivial cases
508 0 : if( nSrcFormat == nDstFormat )
509 : {
510 : // accelerated palette conversions not yet implemented
511 0 : if( rSrc.maPalette != rDst.maPalette )
512 0 : return false;
513 0 : return ImplCopyImage( rDst, rSrc );
514 : }
515 :
516 : // select the matching instantiation for the source's bitmap format
517 0 : switch( nSrcFormat )
518 : {
519 : case BMP_FORMAT_1BIT_MSB_PAL:
520 : case BMP_FORMAT_1BIT_LSB_PAL:
521 : case BMP_FORMAT_4BIT_MSN_PAL:
522 : case BMP_FORMAT_4BIT_LSN_PAL:
523 : case BMP_FORMAT_8BIT_PAL:
524 0 : break;
525 :
526 : case BMP_FORMAT_8BIT_TC_MASK:
527 : // return ImplConvertFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
528 : case BMP_FORMAT_24BIT_TC_MASK:
529 : // return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
530 : case BMP_FORMAT_32BIT_TC_MASK:
531 : // return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
532 0 : break;
533 :
534 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
535 0 : return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc );
536 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
537 0 : return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc );
538 :
539 : case BMP_FORMAT_24BIT_TC_BGR:
540 0 : return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc );
541 : case BMP_FORMAT_24BIT_TC_RGB:
542 0 : return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc );
543 :
544 : case BMP_FORMAT_32BIT_TC_ABGR:
545 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc );
546 : #ifdef FAST_ARGB_BGRA
547 : case BMP_FORMAT_32BIT_TC_ARGB:
548 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc );
549 : case BMP_FORMAT_32BIT_TC_BGRA:
550 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc );
551 : #endif
552 : case BMP_FORMAT_32BIT_TC_RGBA:
553 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc );
554 : }
555 :
556 : static int nNotAccelerated = 0;
557 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
558 : "vcl.gdi",
559 : "ImplFastBitmapConversion for not accelerated case (" << std::hex << rSrc.mnFormat << "->" << rDst.mnFormat << ")" );
560 :
561 0 : return false;
562 : }
563 :
564 : template <sal_uLong DSTFMT,sal_uLong SRCFMT> //,sal_uLong MSKFMT>
565 0 : bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
566 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
567 : const BitmapBuffer& rMskBuffer )
568 : {
569 : DBG_ASSERT( rMskBuffer.mnFormat == BMP_FORMAT_8BIT_PAL, "FastBmp BlendImage: unusual MSKFMT" );
570 :
571 0 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
572 0 : int nMskLinestep = rMskBuffer.mnScanlineSize;
573 0 : int nDstLinestep = rDstBuffer.mnScanlineSize;
574 :
575 0 : TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
576 0 : TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
577 :
578 : // special case for single line masks
579 0 : if( rMskBuffer.mnHeight == 1 )
580 0 : nMskLinestep = 0;
581 :
582 : // source and mask don't match: upside down
583 0 : if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
584 : {
585 0 : aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
586 0 : nMskLinestep = -nMskLinestep;
587 : }
588 :
589 : // source and destination don't match: upside down
590 0 : if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
591 : {
592 0 : aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
593 0 : nDstLinestep = -nDstLinestep;
594 : }
595 :
596 : assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight); // not sure about that?
597 0 : for (int y = rDstBuffer.mnHeight; --y >= 0;)
598 : {
599 0 : ImplBlendLines<8>( aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth );
600 0 : aDstLine.AddByteOffset( nDstLinestep );
601 0 : rSrcLine.AddByteOffset( nSrcLinestep );
602 0 : aMskLine.AddByteOffset( nMskLinestep );
603 : }
604 :
605 0 : return true;
606 : }
607 :
608 : // some specializations to reduce the code size
609 : template <>
610 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR,BMP_FORMAT_24BIT_TC_BGR>(
611 : TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR>&,
612 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
613 : const BitmapBuffer& rMskBuffer )
614 : {
615 0 : TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
616 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
617 : }
618 :
619 : template <>
620 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR,BMP_FORMAT_32BIT_TC_ABGR>(
621 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR>&,
622 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
623 : const BitmapBuffer& rMskBuffer )
624 : {
625 0 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
626 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
627 : }
628 :
629 : template <>
630 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA,BMP_FORMAT_32BIT_TC_BGRA>(
631 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA>&,
632 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
633 : const BitmapBuffer& rMskBuffer )
634 : {
635 0 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
636 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
637 : }
638 :
639 : template <sal_uLong SRCFMT>
640 0 : bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
641 : {
642 0 : TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
643 :
644 : // select the matching instantiation for the destination's bitmap format
645 0 : switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
646 : {
647 : case BMP_FORMAT_1BIT_MSB_PAL:
648 : case BMP_FORMAT_1BIT_LSB_PAL:
649 : case BMP_FORMAT_4BIT_MSN_PAL:
650 : case BMP_FORMAT_4BIT_LSN_PAL:
651 : case BMP_FORMAT_8BIT_PAL:
652 0 : break;
653 :
654 : case BMP_FORMAT_8BIT_TC_MASK:
655 : // return ImplBlendToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
656 : case BMP_FORMAT_24BIT_TC_MASK:
657 : // return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
658 : case BMP_FORMAT_32BIT_TC_MASK:
659 : // return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
660 0 : break;
661 :
662 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
663 0 : return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc, rMsk );
664 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
665 0 : return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc, rMsk );
666 :
667 : case BMP_FORMAT_24BIT_TC_BGR:
668 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc, rMsk );
669 : case BMP_FORMAT_24BIT_TC_RGB:
670 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc, rMsk );
671 :
672 : case BMP_FORMAT_32BIT_TC_ABGR:
673 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc, rMsk );
674 : #ifdef FAST_ARGB_BGRA
675 : case BMP_FORMAT_32BIT_TC_ARGB:
676 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc, rMsk );
677 : case BMP_FORMAT_32BIT_TC_BGRA:
678 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc, rMsk );
679 : #endif
680 : case BMP_FORMAT_32BIT_TC_RGBA:
681 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc, rMsk );
682 : }
683 :
684 : static int nNotAccelerated = 0;
685 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
686 : "vcl.gdi",
687 : "ImplBlendFromBitmap for not accelerated case (" << std::hex << rSrc.mnFormat << "*" << rMsk.mnFormat << "->" << rDst.mnFormat );
688 0 : return false;
689 : }
690 :
691 0 : bool ImplFastBitmapBlending( BitmapWriteAccess& rDstWA,
692 : const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
693 : const SalTwoRect& rTR )
694 : {
695 : // accelerated blending of paletted bitmaps not implemented yet
696 0 : if( rSrcRA.HasPalette() )
697 0 : return false;
698 0 : if( rDstWA.HasPalette() )
699 0 : return false;
700 : // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
701 :
702 : // horizontal mirroring not implemented yet
703 0 : if( rTR.mnDestWidth < 0 )
704 0 : return false;
705 : // vertical mirroring
706 0 : if( rTR.mnDestHeight < 0 )
707 : // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
708 0 : return false;
709 :
710 : // offseted blending is not implemented yet
711 0 : if( rTR.mnSrcX || rTR.mnSrcY )
712 0 : return false;
713 0 : if( rTR.mnDestX || rTR.mnDestY )
714 0 : return false;
715 :
716 : // stretched blending is not implemented yet
717 0 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
718 0 : return false;
719 0 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
720 0 : return false;
721 :
722 : // check source image size
723 0 : if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
724 0 : return false;
725 0 : if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
726 0 : return false;
727 :
728 : // check mask image size
729 0 : if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
730 0 : return false;
731 0 : if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
732 0 : if( rMskRA.Height() != 1 )
733 0 : return false;
734 :
735 : // check dest image size
736 0 : if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
737 0 : return false;
738 0 : if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
739 0 : return false;
740 :
741 0 : BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
742 0 : const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
743 0 : const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
744 :
745 0 : const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
746 0 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
747 :
748 : // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented
749 0 : if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
750 0 : if( rSrc.maColorMask.GetRedMask() != 0xF800
751 0 : || rSrc.maColorMask.GetGreenMask()!= 0x07E0
752 0 : || rSrc.maColorMask.GetBlueMask() != 0x001F)
753 0 : return false;
754 0 : if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
755 0 : if( rDst.maColorMask.GetRedMask() != 0xF800
756 0 : || rDst.maColorMask.GetGreenMask()!= 0x07E0
757 0 : || rDst.maColorMask.GetBlueMask() != 0x001F)
758 0 : return false;
759 :
760 : // select the matching instantiation for the source's bitmap format
761 0 : switch( nSrcFormat )
762 : {
763 : case BMP_FORMAT_1BIT_MSB_PAL:
764 : case BMP_FORMAT_1BIT_LSB_PAL:
765 : case BMP_FORMAT_4BIT_MSN_PAL:
766 : case BMP_FORMAT_4BIT_LSN_PAL:
767 : case BMP_FORMAT_8BIT_PAL:
768 0 : break;
769 :
770 : case BMP_FORMAT_8BIT_TC_MASK:
771 : // return ImplBlendFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
772 : case BMP_FORMAT_24BIT_TC_MASK:
773 : // return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
774 : case BMP_FORMAT_32BIT_TC_MASK:
775 : // return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
776 0 : break;
777 :
778 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
779 0 : return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc, rMsk );
780 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
781 0 : return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc, rMsk );
782 :
783 : case BMP_FORMAT_24BIT_TC_BGR:
784 0 : return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc, rMsk );
785 : case BMP_FORMAT_24BIT_TC_RGB:
786 0 : return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc, rMsk );
787 :
788 : case BMP_FORMAT_32BIT_TC_ABGR:
789 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc, rMsk );
790 : #ifdef FAST_ARGB_BGRA
791 : case BMP_FORMAT_32BIT_TC_ARGB:
792 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc, rMsk );
793 : case BMP_FORMAT_32BIT_TC_BGRA:
794 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc, rMsk );
795 : #endif
796 : case BMP_FORMAT_32BIT_TC_RGBA:
797 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc, rMsk );
798 : }
799 :
800 : static int nNotAccelerated = 0;
801 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
802 : "vcl.gdi",
803 : "ImplFastBlend for not accelerated case (" << std::hex << rSrc.mnFormat << "*" << rMsk.mnFormat << "->" << rDst.mnFormat << ")" );
804 :
805 0 : return false;
806 : }
807 :
808 0 : bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
809 : {
810 0 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
811 :
812 : // erasing a bitmap is often just a byte-wise memory fill
813 0 : bool bByteFill = true;
814 : sal_uInt8 nFillByte;
815 :
816 0 : switch( nDstFormat )
817 : {
818 : case BMP_FORMAT_1BIT_MSB_PAL:
819 : case BMP_FORMAT_1BIT_LSB_PAL:
820 0 : nFillByte = rColor.GetIndex();
821 0 : nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
822 0 : break;
823 : case BMP_FORMAT_4BIT_MSN_PAL:
824 : case BMP_FORMAT_4BIT_LSN_PAL:
825 0 : nFillByte = rColor.GetIndex();
826 0 : nFillByte &= 0x0F;
827 0 : nFillByte |= (nFillByte << 4);
828 0 : break;
829 : case BMP_FORMAT_8BIT_PAL:
830 : case BMP_FORMAT_8BIT_TC_MASK:
831 0 : nFillByte = rColor.GetIndex();
832 0 : break;
833 :
834 : case BMP_FORMAT_24BIT_TC_MASK:
835 : case BMP_FORMAT_24BIT_TC_BGR:
836 : case BMP_FORMAT_24BIT_TC_RGB:
837 0 : nFillByte = rColor.GetRed();
838 0 : if( (nFillByte != rColor.GetGreen())
839 0 : || (nFillByte != rColor.GetBlue()) )
840 0 : bByteFill = false;
841 0 : break;
842 :
843 : default:
844 0 : bByteFill = false;
845 0 : nFillByte = 0x00;
846 0 : break;
847 : }
848 :
849 0 : if( bByteFill )
850 : {
851 0 : long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
852 0 : memset( rDst.mpBits, nFillByte, nByteCount );
853 0 : return true;
854 : }
855 :
856 : // TODO: handle other bitmap formats
857 0 : switch( nDstFormat )
858 : {
859 : case BMP_FORMAT_32BIT_TC_MASK:
860 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
861 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
862 :
863 : case BMP_FORMAT_24BIT_TC_BGR:
864 : case BMP_FORMAT_24BIT_TC_RGB:
865 :
866 : case BMP_FORMAT_32BIT_TC_ABGR:
867 : #ifdef FAST_ARGB_BGRA
868 : case BMP_FORMAT_32BIT_TC_ARGB:
869 : case BMP_FORMAT_32BIT_TC_BGRA:
870 : #endif
871 : case BMP_FORMAT_32BIT_TC_RGBA:
872 0 : break;
873 :
874 : default:
875 0 : break;
876 : }
877 :
878 0 : return false;
879 : }
880 :
881 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|