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 : explicit BasePixelPtr( PIXBYTE* p = NULL ) : mpPixel( p ) {}
34 0 : void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
35 0 : PIXBYTE* GetRawPtr() 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 : static PIXBYTE GetAlpha() { return 0; }
67 0 : static void SetAlpha( PIXBYTE ) {}
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 : static PIXBYTE GetAlpha() { return 0; }
87 0 : static void SetAlpha( PIXBYTE ) {}
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 : static PIXBYTE GetAlpha() { return 0; }
188 0 : static void SetAlpha( PIXBYTE ) {}
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 : static PIXBYTE GetAlpha() { return 0; }
208 0 : static void SetAlpha( PIXBYTE ) {}
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 : static void SetColor( PIXBYTE, PIXBYTE, PIXBYTE ) {}
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 <sal_uLong SRCFMT, sal_uLong DSTFMT>
271 0 : inline void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst,
272 : const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal )
273 : {
274 : static const unsigned nAlphaShift = 8;
275 0 : if( !nAlphaVal )
276 0 : ImplConvertPixel( rDst, rSrc );
277 0 : else if( nAlphaVal != ~(~0U << nAlphaShift) )
278 : {
279 0 : int nR = rDst.GetRed();
280 0 : int nS = rSrc.GetRed();
281 0 : nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
282 :
283 0 : int nG = rDst.GetGreen();
284 0 : nS = rSrc.GetGreen();
285 0 : nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
286 :
287 0 : int nB = rDst.GetBlue();
288 0 : nS = rSrc.GetBlue();
289 0 : nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
290 :
291 0 : rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
292 0 : sal::static_int_cast<PIXBYTE>(nG),
293 0 : sal::static_int_cast<PIXBYTE>(nB) );
294 : }
295 0 : }
296 :
297 : template <sal_uLong MASKFMT, sal_uLong SRCFMT, sal_uLong DSTFMT>
298 0 : inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
299 : const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk,
300 : int nPixelCount )
301 : {
302 0 : TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
303 0 : TrueColorPixelPtr<DSTFMT> aDst( rDst );
304 0 : TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
305 0 : while( --nPixelCount >= 0 )
306 : {
307 0 : ImplBlendPixels(aDst, aSrc, aMsk.GetAlpha());
308 0 : ++aDst;
309 0 : ++aSrc;
310 0 : ++aMsk;
311 : }
312 0 : }
313 :
314 7 : static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
315 : {
316 7 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
317 7 : int nDstLinestep = rDstBuffer.mnScanlineSize;
318 :
319 7 : const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
320 7 : PIXBYTE* pRawDst = rDstBuffer.mpBits;
321 :
322 : // source and destination don't match upside down
323 7 : if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
324 : {
325 0 : pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
326 0 : nDstLinestep = -rDstBuffer.mnScanlineSize;
327 : }
328 7 : else if( nSrcLinestep == nDstLinestep )
329 : {
330 7 : memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
331 7 : return true;
332 : }
333 :
334 0 : int nByteWidth = nSrcLinestep;
335 0 : if( nByteWidth > rDstBuffer.mnScanlineSize )
336 0 : nByteWidth = rDstBuffer.mnScanlineSize;
337 :
338 0 : for( int y = rSrcBuffer.mnHeight; --y >= 0; )
339 : {
340 0 : memcpy( pRawDst, pRawSrc, nByteWidth );
341 0 : pRawSrc += nSrcLinestep;
342 0 : pRawDst += nDstLinestep;
343 : }
344 :
345 0 : return true;
346 : }
347 :
348 : template <sal_uLong DSTFMT,sal_uLong SRCFMT>
349 0 : bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
350 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
351 : {
352 : // help the compiler to avoid instantiations of unneeded conversions
353 : DBG_ASSERT( SRCFMT != DSTFMT, "ImplConvertToBitmap into same format");
354 : if( SRCFMT == DSTFMT )
355 0 : return false;
356 :
357 0 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
358 0 : int nDstLinestep = rDstBuffer.mnScanlineSize;
359 :
360 0 : TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
361 :
362 : // source and destination don't match upside down
363 0 : if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
364 : {
365 0 : aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
366 0 : nDstLinestep = -nDstLinestep;
367 : }
368 :
369 0 : for( int y = rSrcBuffer.mnHeight; --y >= 0; )
370 : {
371 0 : ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
372 0 : rSrcLine.AddByteOffset( nSrcLinestep );
373 0 : aDstLine.AddByteOffset( nDstLinestep );
374 : }
375 :
376 0 : return true;
377 : }
378 :
379 : template <sal_uLong SRCFMT>
380 0 : inline bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
381 : {
382 0 : TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
383 :
384 : // select the matching instantiation for the destination's bitmap format
385 0 : switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
386 : {
387 : case BMP_FORMAT_1BIT_MSB_PAL:
388 : case BMP_FORMAT_1BIT_LSB_PAL:
389 : case BMP_FORMAT_4BIT_MSN_PAL:
390 : case BMP_FORMAT_4BIT_LSN_PAL:
391 : case BMP_FORMAT_8BIT_PAL:
392 0 : break;
393 :
394 : case BMP_FORMAT_8BIT_TC_MASK:
395 : // return ImplConvertToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc );
396 : case BMP_FORMAT_24BIT_TC_MASK:
397 : // return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc );
398 : case BMP_FORMAT_32BIT_TC_MASK:
399 : // return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc );
400 0 : break;
401 :
402 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
403 0 : return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc );
404 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
405 0 : return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc );
406 :
407 : case BMP_FORMAT_24BIT_TC_BGR:
408 0 : return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc );
409 : case BMP_FORMAT_24BIT_TC_RGB:
410 0 : return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc );
411 :
412 : case BMP_FORMAT_32BIT_TC_ABGR:
413 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc );
414 : #ifdef FAST_ARGB_BGRA
415 : case BMP_FORMAT_32BIT_TC_ARGB:
416 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc );
417 : case BMP_FORMAT_32BIT_TC_BGRA:
418 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc );
419 : #endif
420 : case BMP_FORMAT_32BIT_TC_RGBA:
421 0 : return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc );
422 : }
423 :
424 : static int nNotAccelerated = 0;
425 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
426 : "vcl.gdi",
427 : "ImplConvertFromBitmap for not accelerated case (" << std::hex << rSrc.mnFormat << "->" << rDst.mnFormat << ")" );
428 :
429 0 : return false;
430 : }
431 :
432 : // A universal stretching conversion is overkill in most common situations
433 : // => performance benefits for speeding up the non-stretching cases
434 7 : bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
435 : const SalTwoRect& rTR )
436 : {
437 : // TODO:horizontal mirroring not implemented yet
438 7 : if( rTR.mnDestWidth < 0 )
439 0 : return false;
440 : // vertical mirroring
441 7 : if( rTR.mnDestHeight < 0 )
442 : // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
443 0 : return false;
444 :
445 : // offseted conversion is not implemented yet
446 7 : if( rTR.mnSrcX || rTR.mnSrcY )
447 0 : return false;
448 7 : if( rTR.mnDestX || rTR.mnDestY )
449 0 : return false;
450 :
451 : // stretched conversion is not implemented yet
452 7 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
453 0 : return false;
454 7 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
455 0 : return false;
456 :
457 : // check source image size
458 7 : if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
459 0 : return false;
460 7 : if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
461 0 : return false;
462 :
463 : // check dest image size
464 7 : if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
465 0 : return false;
466 7 : if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
467 0 : return false;
468 :
469 7 : const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
470 7 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
471 :
472 : // TODO: also implement conversions for 16bit colormasks with non-565 format
473 7 : if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
474 0 : if( rSrc.maColorMask.GetRedMask() != 0xF800
475 0 : || rSrc.maColorMask.GetGreenMask()!= 0x07E0
476 0 : || rSrc.maColorMask.GetBlueMask() != 0x001F )
477 0 : return false;
478 7 : if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
479 0 : if( rDst.maColorMask.GetRedMask() != 0xF800
480 0 : || rDst.maColorMask.GetGreenMask()!= 0x07E0
481 0 : || rDst.maColorMask.GetBlueMask() != 0x001F )
482 0 : return false;
483 :
484 : // special handling of trivial cases
485 7 : if( nSrcFormat == nDstFormat )
486 : {
487 : // accelerated palette conversions not yet implemented
488 7 : if( rSrc.maPalette != rDst.maPalette )
489 0 : return false;
490 7 : return ImplCopyImage( rDst, rSrc );
491 : }
492 :
493 : // select the matching instantiation for the source's bitmap format
494 0 : switch( nSrcFormat )
495 : {
496 : case BMP_FORMAT_1BIT_MSB_PAL:
497 : case BMP_FORMAT_1BIT_LSB_PAL:
498 : case BMP_FORMAT_4BIT_MSN_PAL:
499 : case BMP_FORMAT_4BIT_LSN_PAL:
500 : case BMP_FORMAT_8BIT_PAL:
501 0 : break;
502 :
503 : case BMP_FORMAT_8BIT_TC_MASK:
504 : // return ImplConvertFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
505 : case BMP_FORMAT_24BIT_TC_MASK:
506 : // return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
507 : case BMP_FORMAT_32BIT_TC_MASK:
508 : // return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
509 0 : break;
510 :
511 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
512 0 : return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc );
513 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
514 0 : return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc );
515 :
516 : case BMP_FORMAT_24BIT_TC_BGR:
517 0 : return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc );
518 : case BMP_FORMAT_24BIT_TC_RGB:
519 0 : return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc );
520 :
521 : case BMP_FORMAT_32BIT_TC_ABGR:
522 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc );
523 : #ifdef FAST_ARGB_BGRA
524 : case BMP_FORMAT_32BIT_TC_ARGB:
525 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc );
526 : case BMP_FORMAT_32BIT_TC_BGRA:
527 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc );
528 : #endif
529 : case BMP_FORMAT_32BIT_TC_RGBA:
530 0 : return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc );
531 : }
532 :
533 : static int nNotAccelerated = 0;
534 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
535 : "vcl.gdi",
536 : "ImplFastBitmapConversion for not accelerated case (" << std::hex << rSrc.mnFormat << "->" << rDst.mnFormat << ")" );
537 :
538 0 : return false;
539 : }
540 :
541 : template <sal_uLong DSTFMT,sal_uLong SRCFMT> //,sal_uLong MSKFMT>
542 0 : bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
543 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
544 : const BitmapBuffer& rMskBuffer )
545 : {
546 : DBG_ASSERT( rMskBuffer.mnFormat == BMP_FORMAT_8BIT_PAL, "FastBmp BlendImage: unusual MSKFMT" );
547 :
548 0 : const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
549 0 : int nMskLinestep = rMskBuffer.mnScanlineSize;
550 0 : int nDstLinestep = rDstBuffer.mnScanlineSize;
551 :
552 0 : TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
553 0 : TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
554 :
555 : // special case for single line masks
556 0 : if( rMskBuffer.mnHeight == 1 )
557 0 : nMskLinestep = 0;
558 :
559 : // source and mask don't match: upside down
560 0 : if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
561 : {
562 0 : aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
563 0 : nMskLinestep = -nMskLinestep;
564 : }
565 :
566 : // source and destination don't match: upside down
567 0 : if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
568 : {
569 0 : aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
570 0 : nDstLinestep = -nDstLinestep;
571 : }
572 :
573 : assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
574 0 : for (int y = rDstBuffer.mnHeight; --y >= 0;)
575 : {
576 0 : ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
577 0 : aDstLine.AddByteOffset( nDstLinestep );
578 0 : rSrcLine.AddByteOffset( nSrcLinestep );
579 0 : aMskLine.AddByteOffset( nMskLinestep );
580 : }
581 :
582 0 : return true;
583 : }
584 :
585 : // some specializations to reduce the code size
586 : template <>
587 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR,BMP_FORMAT_24BIT_TC_BGR>(
588 : TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR>&,
589 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
590 : const BitmapBuffer& rMskBuffer )
591 : {
592 0 : TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
593 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
594 : }
595 :
596 : template <>
597 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR,BMP_FORMAT_32BIT_TC_ABGR>(
598 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR>&,
599 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
600 : const BitmapBuffer& rMskBuffer )
601 : {
602 0 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
603 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
604 : }
605 :
606 : template <>
607 0 : inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA,BMP_FORMAT_32BIT_TC_BGRA>(
608 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA>&,
609 : BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
610 : const BitmapBuffer& rMskBuffer )
611 : {
612 0 : TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
613 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
614 : }
615 :
616 : template <sal_uLong SRCFMT>
617 0 : bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
618 : {
619 0 : TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
620 :
621 : // select the matching instantiation for the destination's bitmap format
622 0 : switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
623 : {
624 : case BMP_FORMAT_1BIT_MSB_PAL:
625 : case BMP_FORMAT_1BIT_LSB_PAL:
626 : case BMP_FORMAT_4BIT_MSN_PAL:
627 : case BMP_FORMAT_4BIT_LSN_PAL:
628 : case BMP_FORMAT_8BIT_PAL:
629 0 : break;
630 :
631 : case BMP_FORMAT_8BIT_TC_MASK:
632 : // return ImplBlendToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
633 : case BMP_FORMAT_24BIT_TC_MASK:
634 : // return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
635 : case BMP_FORMAT_32BIT_TC_MASK:
636 : // return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
637 0 : break;
638 :
639 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
640 0 : return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc, rMsk );
641 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
642 0 : return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc, rMsk );
643 :
644 : case BMP_FORMAT_24BIT_TC_BGR:
645 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc, rMsk );
646 : case BMP_FORMAT_24BIT_TC_RGB:
647 0 : return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc, rMsk );
648 :
649 : case BMP_FORMAT_32BIT_TC_ABGR:
650 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc, rMsk );
651 : #ifdef FAST_ARGB_BGRA
652 : case BMP_FORMAT_32BIT_TC_ARGB:
653 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc, rMsk );
654 : case BMP_FORMAT_32BIT_TC_BGRA:
655 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc, rMsk );
656 : #endif
657 : case BMP_FORMAT_32BIT_TC_RGBA:
658 0 : return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc, rMsk );
659 : }
660 :
661 : static int nNotAccelerated = 0;
662 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
663 : "vcl.gdi",
664 : "ImplBlendFromBitmap for not accelerated case (" << std::hex << rSrc.mnFormat << "*" << rMsk.mnFormat << "->" << rDst.mnFormat );
665 0 : return false;
666 : }
667 :
668 131514 : bool ImplFastBitmapBlending( BitmapWriteAccess& rDstWA,
669 : const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
670 : const SalTwoRect& rTR )
671 : {
672 : // accelerated blending of paletted bitmaps not implemented yet
673 131514 : if( rSrcRA.HasPalette() )
674 38208 : return false;
675 93306 : if( rDstWA.HasPalette() )
676 0 : return false;
677 : // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
678 :
679 : // horizontal mirroring not implemented yet
680 93306 : if( rTR.mnDestWidth < 0 )
681 0 : return false;
682 : // vertical mirroring
683 93306 : if( rTR.mnDestHeight < 0 )
684 : // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
685 0 : return false;
686 :
687 : // offseted blending is not implemented yet
688 93306 : if( rTR.mnSrcX || rTR.mnSrcY )
689 0 : return false;
690 93306 : if( rTR.mnDestX || rTR.mnDestY )
691 5391 : return false;
692 :
693 : // stretched blending is not implemented yet
694 87915 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
695 1876 : return false;
696 86039 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
697 961 : return false;
698 :
699 : // check source image size
700 85078 : if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
701 0 : return false;
702 85078 : if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
703 0 : return false;
704 :
705 : // check mask image size
706 85078 : if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
707 0 : return false;
708 85078 : if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
709 0 : if( rMskRA.Height() != 1 )
710 0 : return false;
711 :
712 : // check dest image size
713 85078 : if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
714 4064 : return false;
715 81014 : if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
716 14187 : return false;
717 :
718 66827 : BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
719 66827 : const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
720 66827 : const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
721 :
722 66827 : const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
723 66827 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
724 :
725 : // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented
726 66827 : if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
727 0 : if( rSrc.maColorMask.GetRedMask() != 0xF800
728 0 : || rSrc.maColorMask.GetGreenMask()!= 0x07E0
729 0 : || rSrc.maColorMask.GetBlueMask() != 0x001F)
730 0 : return false;
731 66827 : if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
732 0 : if( rDst.maColorMask.GetRedMask() != 0xF800
733 0 : || rDst.maColorMask.GetGreenMask()!= 0x07E0
734 0 : || rDst.maColorMask.GetBlueMask() != 0x001F)
735 0 : return false;
736 :
737 : // select the matching instantiation for the source's bitmap format
738 66827 : switch( nSrcFormat )
739 : {
740 : case BMP_FORMAT_1BIT_MSB_PAL:
741 : case BMP_FORMAT_1BIT_LSB_PAL:
742 : case BMP_FORMAT_4BIT_MSN_PAL:
743 : case BMP_FORMAT_4BIT_LSN_PAL:
744 : case BMP_FORMAT_8BIT_PAL:
745 0 : break;
746 :
747 : case BMP_FORMAT_8BIT_TC_MASK:
748 : // return ImplBlendFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
749 : case BMP_FORMAT_24BIT_TC_MASK:
750 : // return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
751 : case BMP_FORMAT_32BIT_TC_MASK:
752 : // return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
753 66827 : break;
754 :
755 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
756 0 : return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc, rMsk );
757 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
758 0 : return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc, rMsk );
759 :
760 : case BMP_FORMAT_24BIT_TC_BGR:
761 0 : return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc, rMsk );
762 : case BMP_FORMAT_24BIT_TC_RGB:
763 0 : return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc, rMsk );
764 :
765 : case BMP_FORMAT_32BIT_TC_ABGR:
766 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc, rMsk );
767 : #ifdef FAST_ARGB_BGRA
768 : case BMP_FORMAT_32BIT_TC_ARGB:
769 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc, rMsk );
770 : case BMP_FORMAT_32BIT_TC_BGRA:
771 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc, rMsk );
772 : #endif
773 : case BMP_FORMAT_32BIT_TC_RGBA:
774 0 : return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc, rMsk );
775 : }
776 :
777 : static int nNotAccelerated = 0;
778 : SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
779 : "vcl.gdi",
780 : "ImplFastBlend for not accelerated case (" << std::hex << rSrc.mnFormat << "*" << rMsk.mnFormat << "->" << rDst.mnFormat << ")" );
781 :
782 66827 : return false;
783 : }
784 :
785 1201 : bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
786 : {
787 1201 : const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
788 :
789 : // erasing a bitmap is often just a byte-wise memory fill
790 1201 : bool bByteFill = true;
791 : sal_uInt8 nFillByte;
792 :
793 1201 : switch( nDstFormat )
794 : {
795 : case BMP_FORMAT_1BIT_MSB_PAL:
796 : case BMP_FORMAT_1BIT_LSB_PAL:
797 451 : nFillByte = rColor.GetIndex();
798 451 : nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
799 451 : break;
800 : case BMP_FORMAT_4BIT_MSN_PAL:
801 : case BMP_FORMAT_4BIT_LSN_PAL:
802 6 : nFillByte = rColor.GetIndex();
803 6 : nFillByte &= 0x0F;
804 6 : nFillByte |= (nFillByte << 4);
805 6 : break;
806 : case BMP_FORMAT_8BIT_PAL:
807 : case BMP_FORMAT_8BIT_TC_MASK:
808 631 : nFillByte = rColor.GetIndex();
809 631 : break;
810 :
811 : case BMP_FORMAT_24BIT_TC_MASK:
812 : case BMP_FORMAT_24BIT_TC_BGR:
813 : case BMP_FORMAT_24BIT_TC_RGB:
814 0 : nFillByte = rColor.GetRed();
815 0 : if( (nFillByte != rColor.GetGreen())
816 0 : || (nFillByte != rColor.GetBlue()) )
817 0 : bByteFill = false;
818 0 : break;
819 :
820 : default:
821 113 : bByteFill = false;
822 113 : nFillByte = 0x00;
823 113 : break;
824 : }
825 :
826 1201 : if( bByteFill )
827 : {
828 1088 : long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
829 1088 : memset( rDst.mpBits, nFillByte, nByteCount );
830 1088 : return true;
831 : }
832 :
833 : // TODO: handle other bitmap formats
834 113 : switch( nDstFormat )
835 : {
836 : case BMP_FORMAT_32BIT_TC_MASK:
837 : case BMP_FORMAT_16BIT_TC_MSB_MASK:
838 : case BMP_FORMAT_16BIT_TC_LSB_MASK:
839 :
840 : case BMP_FORMAT_24BIT_TC_BGR:
841 : case BMP_FORMAT_24BIT_TC_RGB:
842 :
843 : case BMP_FORMAT_32BIT_TC_ABGR:
844 : #ifdef FAST_ARGB_BGRA
845 : case BMP_FORMAT_32BIT_TC_ARGB:
846 : case BMP_FORMAT_32BIT_TC_BGRA:
847 : #endif
848 : case BMP_FORMAT_32BIT_TC_RGBA:
849 113 : break;
850 :
851 : default:
852 0 : break;
853 : }
854 :
855 113 : return false;
856 : }
857 :
858 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|