1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include <ctype.h>
28 #include <rtl/crc.h>
29 #include <tools/stream.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/rc.h>
32 #include <vcl/salbtype.hxx>
33 #include <vcl/outdev.hxx>
34 #include <vcl/alpha.hxx>
35 #include <vcl/bitmapex.hxx>
36 #include <vcl/pngread.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/bmpacc.hxx>
39 #include <vcl/dibtools.hxx>
40 #include <image.h>
41 #include <impimagetree.hxx>
42 #include <basegfx/matrix/b2dhommatrixtools.hxx>
43
44 // ------------
45 // - BitmapEx -
46 // ------------
47
BitmapEx()48 BitmapEx::BitmapEx() :
49 eTransparent( TRANSPARENT_NONE ),
50 bAlpha ( sal_False )
51 {
52 }
53
54 // ------------------------------------------------------------------
55
BitmapEx(const BitmapEx & rBitmapEx)56 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
57 aBitmap ( rBitmapEx.aBitmap ),
58 aMask ( rBitmapEx.aMask ),
59 aBitmapSize ( rBitmapEx.aBitmapSize ),
60 aTransparentColor ( rBitmapEx.aTransparentColor ),
61 eTransparent ( rBitmapEx.eTransparent ),
62 bAlpha ( rBitmapEx.bAlpha )
63 {
64 }
65
BitmapEx(const BitmapEx & rBitmapEx,Point aSrc,Size aSize)66 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) :
67 eTransparent( TRANSPARENT_NONE ),
68 bAlpha ( sal_False )
69 {
70 if( rBitmapEx.IsEmpty() )
71 return;
72
73 aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() );
74 aBitmapSize = aSize;
75 if( rBitmapEx.IsAlpha() )
76 {
77 bAlpha = sal_True;
78 aMask = AlphaMask( aSize ).ImplGetBitmap();
79 }
80 else if( rBitmapEx.IsTransparent() )
81 aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() );
82
83 Rectangle aDestRect( Point( 0, 0 ), aSize );
84 Rectangle aSrcRect( aSrc, aSize );
85 CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
86 }
87
88 // ------------------------------------------------------------------
89
BitmapEx(const ResId & rResId)90 BitmapEx::BitmapEx( const ResId& rResId ) :
91 eTransparent( TRANSPARENT_NONE ),
92 bAlpha ( sal_False )
93 {
94 static ImplImageTreeSingletonRef aImageTree;
95 ResMgr* pResMgr = NULL;
96
97 ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
98 pResMgr->ReadLong();
99 pResMgr->ReadLong();
100
101 const String aFileName( pResMgr->ReadString() );
102 ::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
103
104 if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this ) )
105 {
106 #ifdef DBG_UTIL
107 ByteString aErrorStr( "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <" );
108 DBG_ERROR( ( ( aErrorStr += ByteString( aFileName, RTL_TEXTENCODING_ASCII_US ) ) += '>' ).GetBuffer() );
109 #endif
110 }
111 }
112
113 // ------------------------------------------------------------------
114
BitmapEx(const Bitmap & rBmp)115 BitmapEx::BitmapEx( const Bitmap& rBmp ) :
116 aBitmap ( rBmp ),
117 aBitmapSize ( aBitmap.GetSizePixel() ),
118 eTransparent( TRANSPARENT_NONE ),
119 bAlpha ( sal_False )
120 {
121 }
122
123 // ------------------------------------------------------------------
124
BitmapEx(const Bitmap & rBmp,const Bitmap & rMask)125 BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
126 aBitmap ( rBmp ),
127 aMask ( rMask ),
128 aBitmapSize ( aBitmap.GetSizePixel() ),
129 eTransparent ( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
130 bAlpha ( sal_False )
131 {
132 if(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
133 {
134 OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
135 aMask.Scale(aBitmap.GetSizePixel());
136 }
137
138 // #105489# Ensure a mask is exactly one bit deep
139 if( !!aMask && aMask.GetBitCount() != 1 )
140 {
141 OSL_TRACE("BitmapEx: forced mask to monochrome");
142 aMask.ImplMakeMono( 255 );
143 }
144 }
145
146 // ------------------------------------------------------------------
147
BitmapEx(const Bitmap & rBmp,const AlphaMask & rAlphaMask)148 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
149 aBitmap ( rBmp ),
150 aMask ( rAlphaMask.ImplGetBitmap() ),
151 aBitmapSize ( aBitmap.GetSizePixel() ),
152 eTransparent ( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
153 bAlpha ( !rAlphaMask ? sal_False : sal_True )
154 {
155 if(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
156 {
157 OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
158 aMask.Scale(rBmp.GetSizePixel());
159 }
160
161 // #i75531# the workaround below can go when
162 // X11SalGraphics::drawAlphaBitmap()'s render acceleration
163 // can handle the bitmap depth mismatch directly
164 if( aBitmap.GetBitCount() < aMask.GetBitCount() )
165 aBitmap.Convert( BMP_CONVERSION_24BIT );
166 }
167
168 // ------------------------------------------------------------------
169
BitmapEx(const Bitmap & rBmp,const Color & rTransparentColor)170 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
171 aBitmap ( rBmp ),
172 aBitmapSize ( aBitmap.GetSizePixel() ),
173 aTransparentColor ( rTransparentColor ),
174 eTransparent ( TRANSPARENT_BITMAP ),
175 bAlpha ( sal_False )
176 {
177 aMask = aBitmap.CreateMask( aTransparentColor );
178
179 DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
180 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
181 }
182
183 // ------------------------------------------------------------------
184
~BitmapEx()185 BitmapEx::~BitmapEx()
186 {
187 }
188
189 // ------------------------------------------------------------------
190
191 // ------------------------------------------------------------------
192
operator =(const BitmapEx & rBitmapEx)193 BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
194 {
195 if( &rBitmapEx != this )
196 {
197 aBitmap = rBitmapEx.aBitmap;
198 aMask = rBitmapEx.aMask;
199 aBitmapSize = rBitmapEx.aBitmapSize;
200 aTransparentColor = rBitmapEx.aTransparentColor;
201 eTransparent = rBitmapEx.eTransparent;
202 bAlpha = rBitmapEx.bAlpha;
203 }
204
205 return *this;
206 }
207
208 // ------------------------------------------------------------------
209
operator ==(const BitmapEx & rBitmapEx) const210 sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
211 {
212 if( eTransparent != rBitmapEx.eTransparent )
213 return sal_False;
214
215 if( aBitmap != rBitmapEx.aBitmap )
216 return sal_False;
217
218 if( aBitmapSize != rBitmapEx.aBitmapSize )
219 return sal_False;
220
221 if( eTransparent == TRANSPARENT_NONE )
222 return sal_True;
223
224 if( eTransparent == TRANSPARENT_COLOR )
225 return aTransparentColor == rBitmapEx.aTransparentColor;
226
227 return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
228 }
229
230 // ------------------------------------------------------------------
231
IsEqual(const BitmapEx & rBmpEx) const232 sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
233 {
234 return( rBmpEx.eTransparent == eTransparent &&
235 rBmpEx.bAlpha == bAlpha &&
236 rBmpEx.aBitmap.IsEqual( aBitmap ) &&
237 rBmpEx.aMask.IsEqual( aMask ) );
238 }
239
240 // ------------------------------------------------------------------
241
IsEmpty() const242 sal_Bool BitmapEx::IsEmpty() const
243 {
244 return( aBitmap.IsEmpty() && aMask.IsEmpty() );
245 }
246
247 // ------------------------------------------------------------------
248
SetEmpty()249 void BitmapEx::SetEmpty()
250 {
251 aBitmap.SetEmpty();
252 aMask.SetEmpty();
253 eTransparent = TRANSPARENT_NONE;
254 bAlpha = sal_False;
255 }
256
257 // ------------------------------------------------------------------
258
Clear()259 void BitmapEx::Clear()
260 {
261 SetEmpty();
262 }
263
264 // ------------------------------------------------------------------
265
IsTransparent() const266 sal_Bool BitmapEx::IsTransparent() const
267 {
268 return( eTransparent != TRANSPARENT_NONE );
269 }
270
271 // ------------------------------------------------------------------
272
IsAlpha() const273 sal_Bool BitmapEx::IsAlpha() const
274 {
275 return( IsTransparent() && bAlpha );
276 }
277
278 // ------------------------------------------------------------------
279
GetBitmap(const Color * pTransReplaceColor) const280 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
281 {
282 Bitmap aRetBmp( aBitmap );
283
284 if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
285 {
286 Bitmap aTempMask;
287
288 if( eTransparent == TRANSPARENT_COLOR )
289 aTempMask = aBitmap.CreateMask( aTransparentColor );
290 else
291 aTempMask = aMask;
292
293 if( !IsAlpha() )
294 aRetBmp.Replace( aTempMask, *pTransReplaceColor );
295 else
296 aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
297 }
298
299 return aRetBmp;
300 }
301
302 // ------------------------------------------------------------------
303
GetColorTransformedBitmapEx(BmpColorMode eColorMode) const304 BitmapEx BitmapEx::GetColorTransformedBitmapEx( BmpColorMode eColorMode ) const
305 {
306 BitmapEx aRet;
307
308 if( BMP_COLOR_HIGHCONTRAST == eColorMode )
309 {
310 aRet = *this;
311 aRet.aBitmap = aBitmap.GetColorTransformedBitmap( eColorMode );
312 }
313 else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
314 BMP_COLOR_MONOCHROME_WHITE == eColorMode )
315 {
316 aRet = *this;
317 aRet.aBitmap = aRet.aBitmap.GetColorTransformedBitmap( eColorMode );
318
319 if( !aRet.aMask.IsEmpty() )
320 {
321 aRet.aMask.CombineSimple( aRet.aBitmap, BMP_COMBINE_OR );
322 aRet.aBitmap.Erase( ( BMP_COLOR_MONOCHROME_BLACK == eColorMode ) ? COL_BLACK : COL_WHITE );
323
324 DBG_ASSERT( aRet.aBitmap.GetSizePixel() == aRet.aMask.GetSizePixel(),
325 "BitmapEx::GetColorTransformedBitmapEx(): size mismatch for bitmap and alpha mask." );
326 }
327 }
328
329 return aRet;
330 }
331
332 // ------------------------------------------------------------------
333
GetMask() const334 Bitmap BitmapEx::GetMask() const
335 {
336 Bitmap aRet( aMask );
337
338 if( IsAlpha() )
339 aRet.ImplMakeMono( 255 );
340
341 return aRet;
342 }
343
344 // ------------------------------------------------------------------
345
GetAlpha() const346 AlphaMask BitmapEx::GetAlpha() const
347 {
348 AlphaMask aAlpha;
349
350 if( IsAlpha() )
351 aAlpha.ImplSetBitmap( aMask );
352 else
353 aAlpha = aMask;
354
355 return aAlpha;
356 }
357
358 // ------------------------------------------------------------------
359
GetSizeBytes() const360 sal_uLong BitmapEx::GetSizeBytes() const
361 {
362 sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
363
364 if( eTransparent == TRANSPARENT_BITMAP )
365 nSizeBytes += aMask.GetSizeBytes();
366
367 return nSizeBytes;
368 }
369
370 // ------------------------------------------------------------------
371
GetChecksum() const372 sal_uLong BitmapEx::GetChecksum() const
373 {
374 sal_uInt32 nCrc = aBitmap.GetChecksum();
375 SVBT32 aBT32;
376
377 UInt32ToSVBT32( (long) eTransparent, aBT32 );
378 nCrc = rtl_crc32( nCrc, aBT32, 4 );
379
380 UInt32ToSVBT32( (long) bAlpha, aBT32 );
381 nCrc = rtl_crc32( nCrc, aBT32, 4 );
382
383 if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
384 {
385 UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
386 nCrc = rtl_crc32( nCrc, aBT32, 4 );
387 }
388
389 return nCrc;
390 }
391
392 // ------------------------------------------------------------------
393
SetSizePixel(const Size & rNewSize,sal_uInt32 nScaleFlag)394 void BitmapEx::SetSizePixel( const Size& rNewSize, sal_uInt32 nScaleFlag )
395 {
396 if(GetSizePixel() != rNewSize)
397 {
398 Scale( rNewSize, nScaleFlag );
399 }
400 }
401
402 // ------------------------------------------------------------------
403
Invert()404 sal_Bool BitmapEx::Invert()
405 {
406 sal_Bool bRet = sal_False;
407
408 if( !!aBitmap )
409 {
410 bRet = aBitmap.Invert();
411
412 if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
413 aTransparentColor = BitmapColor( aTransparentColor ).Invert();
414 }
415
416 return bRet;
417 }
418
419 // ------------------------------------------------------------------
420
Mirror(sal_uLong nMirrorFlags)421 sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
422 {
423 sal_Bool bRet = sal_False;
424
425 if( !!aBitmap )
426 {
427 bRet = aBitmap.Mirror( nMirrorFlags );
428
429 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
430 aMask.Mirror( nMirrorFlags );
431 }
432
433 return bRet;
434 }
435
436 // ------------------------------------------------------------------
437
Scale(const double & rScaleX,const double & rScaleY,sal_uInt32 nScaleFlag)438 sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
439 {
440 sal_Bool bRet = sal_False;
441
442 if( !!aBitmap )
443 {
444 bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
445
446 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
447 {
448 aMask.Scale( rScaleX, rScaleY, nScaleFlag );
449 }
450
451 aBitmapSize = aBitmap.GetSizePixel();
452
453 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
454 "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
455 }
456
457 return bRet;
458 }
459
460 // ------------------------------------------------------------------------
461
Scale(const Size & rNewSize,sal_uInt32 nScaleFlag)462 sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
463 {
464 sal_Bool bRet;
465
466 if( aBitmapSize.Width() && aBitmapSize.Height() )
467 {
468 bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
469 (double) rNewSize.Height() / aBitmapSize.Height(),
470 nScaleFlag );
471 }
472 else
473 bRet = sal_True;
474
475 return bRet;
476 }
477
478 // ------------------------------------------------------------------
479
Rotate(long nAngle10,const Color & rFillColor)480 sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
481 {
482 sal_Bool bRet = sal_False;
483
484 if( !!aBitmap )
485 {
486 const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
487
488 if( bTransRotate )
489 {
490 if( eTransparent == TRANSPARENT_COLOR )
491 bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
492 else
493 {
494 bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
495
496 if( eTransparent == TRANSPARENT_NONE )
497 {
498 aMask = Bitmap( aBitmapSize, 1 );
499 aMask.Erase( COL_BLACK );
500 eTransparent = TRANSPARENT_BITMAP;
501 }
502
503 if( bRet && !!aMask )
504 aMask.Rotate( nAngle10, COL_WHITE );
505 }
506 }
507 else
508 {
509 bRet = aBitmap.Rotate( nAngle10, rFillColor );
510
511 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
512 aMask.Rotate( nAngle10, COL_WHITE );
513 }
514
515 aBitmapSize = aBitmap.GetSizePixel();
516
517 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
518 "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
519 }
520
521 return bRet;
522 }
523
524 // ------------------------------------------------------------------
525
Crop(const Rectangle & rRectPixel)526 sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
527 {
528 sal_Bool bRet = sal_False;
529
530 if( !!aBitmap )
531 {
532 bRet = aBitmap.Crop( rRectPixel );
533
534 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
535 aMask.Crop( rRectPixel );
536
537 aBitmapSize = aBitmap.GetSizePixel();
538
539 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
540 "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
541 }
542
543 return bRet;
544 }
545
546 // ------------------------------------------------------------------
547
Convert(BmpConversion eConversion)548 sal_Bool BitmapEx::Convert( BmpConversion eConversion )
549 {
550 return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
551 }
552
553 // ------------------------------------------------------------------
554
ReduceColors(sal_uInt16 nNewColorCount,BmpReduce eReduce)555 sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
556 {
557 return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
558 }
559
560 // ------------------------------------------------------------------
561
Expand(sal_uLong nDX,sal_uLong nDY,const Color * pInitColor,sal_Bool bExpandTransparent)562 sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
563 {
564 sal_Bool bRet = sal_False;
565
566 if( !!aBitmap )
567 {
568 bRet = aBitmap.Expand( nDX, nDY, pInitColor );
569
570 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
571 {
572 Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
573 aMask.Expand( nDX, nDY, &aColor );
574 }
575
576 aBitmapSize = aBitmap.GetSizePixel();
577
578 DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
579 "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
580 }
581
582 return bRet;
583 }
584
585 // ------------------------------------------------------------------
586
CopyPixel(const Rectangle & rRectDst,const Rectangle & rRectSrc,const BitmapEx * pBmpExSrc)587 sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
588 const BitmapEx* pBmpExSrc )
589 {
590 sal_Bool bRet = sal_False;
591
592 if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
593 {
594 if( !aBitmap.IsEmpty() )
595 {
596 bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
597
598 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
599 aMask.CopyPixel( rRectDst, rRectSrc );
600 }
601 }
602 else
603 {
604 if( !aBitmap.IsEmpty() )
605 {
606 bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
607
608 if( bRet )
609 {
610 if( pBmpExSrc->IsAlpha() )
611 {
612 if( IsAlpha() )
613 // cast to use the optimized AlphaMask::CopyPixel
614 ((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
615 else if( IsTransparent() )
616 {
617 AlphaMask* pAlpha = new AlphaMask( aMask );
618
619 aMask = pAlpha->ImplGetBitmap();
620 delete pAlpha;
621 bAlpha = sal_True;
622 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
623 }
624 else
625 {
626 sal_uInt8 cBlack = 0;
627 AlphaMask* pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
628
629 aMask = pAlpha->ImplGetBitmap();
630 delete pAlpha;
631 eTransparent = TRANSPARENT_BITMAP;
632 bAlpha = sal_True;
633 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
634 }
635 }
636 else if( pBmpExSrc->IsTransparent() )
637 {
638 if( IsAlpha() )
639 {
640 AlphaMask aAlpha( pBmpExSrc->aMask );
641 aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
642 }
643 else if( IsTransparent() )
644 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
645 else
646 {
647 aMask = Bitmap( GetSizePixel(), 1 );
648 aMask.Erase( Color( COL_BLACK ) );
649 eTransparent = TRANSPARENT_BITMAP;
650 aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
651 }
652 }
653 else if( IsAlpha() )
654 {
655 sal_uInt8 cBlack = 0;
656 const AlphaMask aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
657
658 aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
659 }
660 else if( IsTransparent() )
661 {
662 Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
663
664 aMaskSrc.Erase( Color( COL_BLACK ) );
665 aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
666 }
667 }
668 }
669 }
670
671 return bRet;
672 }
673
674 // ------------------------------------------------------------------
675
Erase(const Color & rFillColor)676 sal_Bool BitmapEx::Erase( const Color& rFillColor )
677 {
678 sal_Bool bRet = sal_False;
679
680 if( !!aBitmap )
681 {
682 bRet = aBitmap.Erase( rFillColor );
683
684 if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
685 {
686 // #104416# Respect transparency on fill color
687 if( rFillColor.GetTransparency() )
688 {
689 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
690 aMask.Erase( aFill );
691 }
692 else
693 {
694 const Color aBlack( COL_BLACK );
695 aMask.Erase( aBlack );
696 }
697 }
698 }
699
700 return bRet;
701 }
702
703 // ------------------------------------------------------------------
704
Dither(sal_uLong nDitherFlags)705 sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
706 {
707 return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
708 }
709
710 // ------------------------------------------------------------------
711
Replace(const Color & rSearchColor,const Color & rReplaceColor,sal_uLong nTol)712 sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
713 {
714 return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
715 }
716
717 // ------------------------------------------------------------------
718
Replace(const Color * pSearchColors,const Color * pReplaceColors,sal_uLong nColorCount,const sal_uLong * pTols)719 sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
720 {
721 return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
722 }
723
724 // ------------------------------------------------------------------
725
Adjust(short nLuminancePercent,short nContrastPercent,short nChannelRPercent,short nChannelGPercent,short nChannelBPercent,double fGamma,sal_Bool bInvert)726 sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
727 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
728 double fGamma, sal_Bool bInvert )
729 {
730 return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
731 nChannelRPercent, nChannelGPercent, nChannelBPercent,
732 fGamma, bInvert ) : sal_False );
733 }
734
735 // ------------------------------------------------------------------
736
Filter(BmpFilter eFilter,const BmpFilterParam * pFilterParam,const Link * pProgress)737 sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
738 {
739 return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
740 }
741
742 // ------------------------------------------------------------------
743
Draw(OutputDevice * pOutDev,const Point & rDestPt) const744 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
745 {
746 pOutDev->DrawBitmapEx( rDestPt, *this );
747 }
748
749 // ------------------------------------------------------------------
750
Draw(OutputDevice * pOutDev,const Point & rDestPt,const Size & rDestSize) const751 void BitmapEx::Draw( OutputDevice* pOutDev,
752 const Point& rDestPt, const Size& rDestSize ) const
753 {
754 pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
755 }
756
757 // ------------------------------------------------------------------
758
Draw(OutputDevice * pOutDev,const Point & rDestPt,const Size & rDestSize,const Point & rSrcPtPixel,const Size & rSrcSizePixel) const759 void BitmapEx::Draw( OutputDevice* pOutDev,
760 const Point& rDestPt, const Size& rDestSize,
761 const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
762 {
763 pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
764 }
765
766 // ------------------------------------------------------------------
767
GetTransparency(sal_Int32 nX,sal_Int32 nY) const768 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
769 {
770 sal_uInt8 nTransparency(0xff);
771
772 if(!aBitmap.IsEmpty())
773 {
774 if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
775 {
776 switch(eTransparent)
777 {
778 case TRANSPARENT_NONE:
779 {
780 // not transparent, ergo all covered
781 nTransparency = 0x00;
782 break;
783 }
784 case TRANSPARENT_COLOR:
785 {
786 Bitmap aTestBitmap(aBitmap);
787 BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
788
789 if(pRead)
790 {
791 const Color aColor = pRead->GetColor(nY, nX);
792
793 // if color is not equal to TransparentColor, we are not transparent
794 if(aColor != aTransparentColor)
795 {
796 nTransparency = 0x00;
797 }
798
799 aTestBitmap.ReleaseAccess(pRead);
800 }
801 break;
802 }
803 case TRANSPARENT_BITMAP:
804 {
805 if(!aMask.IsEmpty())
806 {
807 Bitmap aTestBitmap(aMask);
808 BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
809
810 if(pRead)
811 {
812 const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
813
814 if(bAlpha)
815 {
816 nTransparency = aBitmapColor.GetIndex();
817 }
818 else
819 {
820 if(0x00 == aBitmapColor.GetIndex())
821 {
822 nTransparency = 0x00;
823 }
824 }
825
826 aTestBitmap.ReleaseAccess(pRead);
827 }
828 }
829 break;
830 }
831 }
832 }
833 }
834
835 return nTransparency;
836 }
837
838 // ------------------------------------------------------------------
839
840 namespace
841 {
impTransformBitmap(const Bitmap & rSource,const Size aDestinationSize,const basegfx::B2DHomMatrix & rTransform,bool bSmooth)842 Bitmap impTransformBitmap(
843 const Bitmap& rSource,
844 const Size aDestinationSize,
845 const basegfx::B2DHomMatrix& rTransform,
846 bool bSmooth)
847 {
848 Bitmap aDestination(aDestinationSize, 24);
849 BitmapWriteAccess* pWrite = aDestination.AcquireWriteAccess();
850
851 if(pWrite)
852 {
853 //const Size aContentSizePixel(rSource.GetSizePixel());
854 BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
855
856 if(pRead)
857 {
858 const Size aDestinationSizePixel(aDestination.GetSizePixel());
859 const BitmapColor aOutside(BitmapColor(0xff, 0xff, 0xff));
860
861 for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
862 {
863 for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
864 {
865 const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
866
867 if(bSmooth)
868 {
869 pWrite->SetPixel(
870 y,
871 x,
872 pRead->GetInterpolatedColorWithFallback(
873 aSourceCoor.getY(),
874 aSourceCoor.getX(),
875 aOutside));
876 }
877 else
878 {
879 // this version does the correct <= 0.0 checks, so no need
880 // to do the static_cast< sal_Int32 > self and make an error
881 pWrite->SetPixel(
882 y,
883 x,
884 pRead->GetColorWithFallback(
885 aSourceCoor.getY(),
886 aSourceCoor.getX(),
887 aOutside));
888 }
889 }
890 }
891
892 delete pRead;
893 }
894
895 delete pWrite;
896 }
897
898 rSource.AdaptBitCount(aDestination);
899
900 return aDestination;
901 }
902 } // end of anonymous namespace
903
TransformBitmapEx(double fWidth,double fHeight,const basegfx::B2DHomMatrix & rTransformation,bool bSmooth) const904 BitmapEx BitmapEx::TransformBitmapEx(
905 double fWidth,
906 double fHeight,
907 const basegfx::B2DHomMatrix& rTransformation,
908 bool bSmooth) const
909 {
910 if(fWidth <= 1 || fHeight <= 1)
911 return BitmapEx();
912
913 // force destination to 24 bit, we want to smooth output
914 const Size aDestinationSize(basegfx::fround(fWidth), basegfx::fround(fHeight));
915 const Bitmap aDestination(impTransformBitmap(GetBitmap(), aDestinationSize, rTransformation, bSmooth));
916
917 // create mask
918 if(IsTransparent())
919 {
920 if(IsAlpha())
921 {
922 const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bSmooth));
923 return BitmapEx(aDestination, AlphaMask(aAlpha));
924 }
925 else
926 {
927 const Bitmap aMask(impTransformBitmap(GetMask(), aDestinationSize, rTransformation, false));
928 return BitmapEx(aDestination, aMask);
929 }
930 }
931
932 return BitmapEx(aDestination);
933 }
934
935 // ------------------------------------------------------------------
936
getTransformed(const basegfx::B2DHomMatrix & rTransformation,const basegfx::B2DRange & rVisibleRange,double fMaximumArea,bool bSmooth) const937 BitmapEx BitmapEx::getTransformed(
938 const basegfx::B2DHomMatrix& rTransformation,
939 const basegfx::B2DRange& rVisibleRange,
940 double fMaximumArea,
941 bool bSmooth) const
942 {
943 BitmapEx aRetval;
944
945 if(IsEmpty())
946 return aRetval;
947
948 const sal_uInt32 nSourceWidth(GetSizePixel().Width());
949 const sal_uInt32 nSourceHeight(GetSizePixel().Height());
950
951 if(!nSourceWidth || !nSourceHeight)
952 return aRetval;
953
954 // Get aOutlineRange
955 basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
956
957 aOutlineRange.transform(rTransformation);
958
959 // create visible range from it by moving from relative to absolute
960 basegfx::B2DRange aVisibleRange(rVisibleRange);
961
962 aVisibleRange.transform(
963 basegfx::tools::createScaleTranslateB2DHomMatrix(
964 aOutlineRange.getRange(),
965 aOutlineRange.getMinimum()));
966
967 // get target size (which is visible range's size)
968 double fWidth(aVisibleRange.getWidth());
969 double fHeight(aVisibleRange.getHeight());
970
971 if(fWidth < 1.0 || fHeight < 1.0)
972 {
973 return aRetval;
974 }
975
976 // test if discrete size (pixel) maybe too big and limit it
977 const double fArea(fWidth * fHeight);
978 const bool bNeedToReduce(basegfx::fTools::more(fArea, fMaximumArea));
979 double fReduceFactor(1.0);
980
981 if(bNeedToReduce)
982 {
983 fReduceFactor = sqrt(fMaximumArea / fArea);
984 fWidth *= fReduceFactor;
985 fHeight *= fReduceFactor;
986 }
987
988 // Build complete transform from source pixels to target pixels.
989 // Start by scaling from source pixel size to unit coordinates
990 basegfx::B2DHomMatrix aTransform(
991 basegfx::tools::createScaleB2DHomMatrix(
992 1.0 / nSourceWidth,
993 1.0 / nSourceHeight));
994
995 // multiply with given transform which leads from unit coordinates inside
996 // aOutlineRange
997 aTransform = rTransformation * aTransform;
998
999 // subtract top-left of absolute VisibleRange
1000 aTransform.translate(
1001 -aVisibleRange.getMinX(),
1002 -aVisibleRange.getMinY());
1003
1004 // scale to target pixels (if needed)
1005 if(bNeedToReduce)
1006 {
1007 aTransform.scale(fReduceFactor, fReduceFactor);
1008 }
1009
1010 // invert to get transformation from target pixel coordinates to source pixels
1011 aTransform.invert();
1012
1013 // create bitmap using source, destination and linear back-transformation
1014 aRetval = TransformBitmapEx(fWidth, fHeight, aTransform, bSmooth);
1015
1016 return aRetval;
1017 }
1018
1019 // ------------------------------------------------------------------
1020
ModifyBitmapEx(const basegfx::BColorModifierStack & rBColorModifierStack) const1021 BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorModifierStack) const
1022 {
1023 Bitmap aChangedBitmap(GetBitmap());
1024 bool bDone(false);
1025
1026 for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
1027 {
1028 const basegfx::BColorModifierSharedPtr& rModifier = rBColorModifierStack.getBColorModifier(--a);
1029 const basegfx::BColorModifier_replace* pReplace = dynamic_cast< const basegfx::BColorModifier_replace* >(rModifier.get());
1030
1031 if(pReplace)
1032 {
1033 // complete replace
1034 if(IsTransparent())
1035 {
1036 // clear bitmap with dest color
1037 if(aChangedBitmap.GetBitCount() <= 8)
1038 {
1039 // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
1040 // erase color is determined and used -> this may be different from what is
1041 // wanted here. Better create a new bitmap with the needed color explicitly
1042 BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
1043 OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
1044
1045 if(pReadAccess)
1046 {
1047 BitmapPalette aNewPalette(pReadAccess->GetPalette());
1048 aNewPalette[0] = BitmapColor(Color(pReplace->getBColor()));
1049 aChangedBitmap = Bitmap(
1050 aChangedBitmap.GetSizePixel(),
1051 aChangedBitmap.GetBitCount(),
1052 &aNewPalette);
1053 delete pReadAccess;
1054 }
1055 }
1056 else
1057 {
1058 aChangedBitmap.Erase(Color(pReplace->getBColor()));
1059 }
1060 }
1061 else
1062 {
1063 // erase bitmap, caller will know to paint direct
1064 aChangedBitmap.SetEmpty();
1065 }
1066
1067 bDone = true;
1068 }
1069 else
1070 {
1071 BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
1072
1073 if(pContent)
1074 {
1075 const double fConvertColor(1.0 / 255.0);
1076
1077 if(pContent->HasPalette())
1078 {
1079 const sal_uInt16 nCount(pContent->GetPaletteEntryCount());
1080
1081 for(sal_uInt16 a(0); a < nCount; a++)
1082 {
1083 const BitmapColor& rCol = pContent->GetPaletteColor(a);
1084 const basegfx::BColor aBSource(
1085 rCol.GetRed() * fConvertColor,
1086 rCol.GetGreen() * fConvertColor,
1087 rCol.GetBlue() * fConvertColor);
1088 const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1089 pContent->SetPaletteColor(a, BitmapColor(Color(aBDest)));
1090 }
1091 }
1092 else if(BMP_FORMAT_24BIT_TC_BGR == pContent->GetScanlineFormat())
1093 {
1094 for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
1095 {
1096 Scanline pScan = pContent->GetScanline(y);
1097
1098 for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
1099 {
1100 const basegfx::BColor aBSource(
1101 *(pScan + 2)* fConvertColor,
1102 *(pScan + 1) * fConvertColor,
1103 *pScan * fConvertColor);
1104 const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1105 *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
1106 *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
1107 *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
1108 }
1109 }
1110 }
1111 else if(BMP_FORMAT_24BIT_TC_RGB == pContent->GetScanlineFormat())
1112 {
1113 for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
1114 {
1115 Scanline pScan = pContent->GetScanline(y);
1116
1117 for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
1118 {
1119 const basegfx::BColor aBSource(
1120 *pScan * fConvertColor,
1121 *(pScan + 1) * fConvertColor,
1122 *(pScan + 2) * fConvertColor);
1123 const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1124 *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
1125 *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
1126 *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
1127 }
1128 }
1129 }
1130 else
1131 {
1132 for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
1133 {
1134 for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
1135 {
1136 const BitmapColor aBMCol(pContent->GetColor(y, x));
1137 const basegfx::BColor aBSource(
1138 (double)aBMCol.GetRed() * fConvertColor,
1139 (double)aBMCol.GetGreen() * fConvertColor,
1140 (double)aBMCol.GetBlue() * fConvertColor);
1141 const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
1142
1143 pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
1144 }
1145 }
1146 }
1147
1148 delete pContent;
1149 }
1150 }
1151 }
1152
1153 if(aChangedBitmap.IsEmpty())
1154 {
1155 return BitmapEx();
1156 }
1157 else
1158 {
1159 if(IsTransparent())
1160 {
1161 if(IsAlpha())
1162 {
1163 return BitmapEx(aChangedBitmap, GetAlpha());
1164 }
1165 else
1166 {
1167 return BitmapEx(aChangedBitmap, GetMask());
1168 }
1169 }
1170 else
1171 {
1172 return BitmapEx(aChangedBitmap);
1173 }
1174 }
1175 }
1176
1177 // -----------------------------------------------------------------------------
1178
createBlendFrame(const Size & rSize,sal_uInt8 nAlpha,Color aColorTopLeft,Color aColorBottomRight)1179 BitmapEx VCL_DLLPUBLIC createBlendFrame(
1180 const Size& rSize,
1181 sal_uInt8 nAlpha,
1182 Color aColorTopLeft,
1183 Color aColorBottomRight)
1184 {
1185 const sal_uInt32 nW(rSize.Width());
1186 const sal_uInt32 nH(rSize.Height());
1187
1188 if(nW || nH)
1189 {
1190 Color aColTopRight(aColorTopLeft);
1191 Color aColBottomLeft(aColorTopLeft);
1192 const sal_uInt32 nDE(nW + nH);
1193
1194 aColTopRight.Merge(aColorBottomRight, 255 - sal_uInt8((nW * 255) / nDE));
1195 aColBottomLeft.Merge(aColorBottomRight, 255 - sal_uInt8((nH * 255) / nDE));
1196
1197 return createBlendFrame(rSize, nAlpha, aColorTopLeft, aColTopRight, aColorBottomRight, aColBottomLeft);
1198 }
1199
1200 return BitmapEx();
1201 }
1202
createBlendFrame(const Size & rSize,sal_uInt8 nAlpha,Color aColorTopLeft,Color aColorTopRight,Color aColorBottomRight,Color aColorBottomLeft)1203 BitmapEx VCL_DLLPUBLIC createBlendFrame(
1204 const Size& rSize,
1205 sal_uInt8 nAlpha,
1206 Color aColorTopLeft,
1207 Color aColorTopRight,
1208 Color aColorBottomRight,
1209 Color aColorBottomLeft)
1210 {
1211 static Size aLastSize(0, 0);
1212 static sal_uInt8 nLastAlpha(0);
1213 static Color aLastColorTopLeft(COL_BLACK);
1214 static Color aLastColorTopRight(COL_BLACK);
1215 static Color aLastColorBottomRight(COL_BLACK);
1216 static Color aLastColorBottomLeft(COL_BLACK);
1217 static BitmapEx aLastResult;
1218
1219 if(aLastSize == rSize
1220 && nLastAlpha == nAlpha
1221 && aLastColorTopLeft == aColorTopLeft
1222 && aLastColorTopRight == aColorTopRight
1223 && aLastColorBottomRight == aColorBottomRight
1224 && aLastColorBottomLeft == aColorBottomLeft)
1225 {
1226 return aLastResult;
1227 }
1228
1229 aLastSize = rSize;
1230 nLastAlpha = nAlpha;
1231 aLastColorTopLeft = aColorTopLeft;
1232 aLastColorTopRight = aColorTopRight;
1233 aLastColorBottomRight = aColorBottomRight;
1234 aLastColorBottomLeft = aColorBottomLeft;
1235 aLastResult.Clear();
1236
1237 const long nW(rSize.Width());
1238 const long nH(rSize.Height());
1239
1240 if(nW && nH)
1241 {
1242 sal_uInt8 aEraseTrans(0xff);
1243 Bitmap aContent(rSize, 24);
1244 AlphaMask aAlpha(rSize, &aEraseTrans);
1245
1246 aContent.Erase(COL_BLACK);
1247
1248 BitmapWriteAccess* pContent = aContent.AcquireWriteAccess();
1249 BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess();
1250
1251 if(pContent && pAlpha)
1252 {
1253 long x(0);
1254 long y(0);
1255
1256 // x == 0, y == 0, top-left corner
1257 pContent->SetPixel(0, 0, aColorTopLeft);
1258 pAlpha->SetPixelIndex(0, 0, nAlpha);
1259
1260 // y == 0, top line left to right
1261 for(x = 1; x < nW - 1; x++)
1262 {
1263 Color aMix(aColorTopLeft);
1264
1265 aMix.Merge(aColorTopRight, 255 - sal_uInt8((x * 255) / nW));
1266 pContent->SetPixel(0, x, aMix);
1267 pAlpha->SetPixelIndex(0, x, nAlpha);
1268 }
1269
1270 // x == nW - 1, y == 0, top-right corner
1271 // #123690# Caution! When nW is 1, x == nW is possible (!)
1272 if(x < nW)
1273 {
1274 pContent->SetPixel(0, x, aColorTopRight);
1275 pAlpha->SetPixelIndex(0, x, nAlpha);
1276 }
1277
1278 // x == 0 and nW - 1, left and right line top-down
1279 for(y = 1; y < nH - 1; y++)
1280 {
1281 Color aMixA(aColorTopLeft);
1282
1283 aMixA.Merge(aColorBottomLeft, 255 - sal_uInt8((y * 255) / nH));
1284 pContent->SetPixel(y, 0, aMixA);
1285 pAlpha->SetPixelIndex(y, 0, nAlpha);
1286
1287 // #123690# Caution! When nW is 1, x == nW is possible (!)
1288 if(x < nW)
1289 {
1290 Color aMixB(aColorTopRight);
1291
1292 aMixB.Merge(aColorBottomRight, 255 - sal_uInt8((y * 255) / nH));
1293 pContent->SetPixel(y, x, aMixB);
1294 pAlpha->SetPixelIndex(y, x, nAlpha);
1295 }
1296 }
1297
1298 // #123690# Caution! When nH is 1, y == nH is possible (!)
1299 if(y < nH)
1300 {
1301 // x == 0, y == nH - 1, bottom-left corner
1302 pContent->SetPixel(y, 0, aColorBottomLeft);
1303 pAlpha->SetPixelIndex(y, 0, nAlpha);
1304
1305 // y == nH - 1, bottom line left to right
1306 for(x = 1; x < nW - 1; x++)
1307 {
1308 Color aMix(aColorBottomLeft);
1309
1310 aMix.Merge(aColorBottomRight, 255 - sal_uInt8(((x - 0)* 255) / nW));
1311 pContent->SetPixel(y, x, aMix);
1312 pAlpha->SetPixelIndex(y, x, nAlpha);
1313 }
1314
1315 // x == nW - 1, y == nH - 1, bottom-right corner
1316 // #123690# Caution! When nW is 1, x == nW is possible (!)
1317 if(x < nW)
1318 {
1319 pContent->SetPixel(y, x, aColorBottomRight);
1320 pAlpha->SetPixelIndex(y, x, nAlpha);
1321 }
1322 }
1323
1324 aContent.ReleaseAccess(pContent);
1325 aAlpha.ReleaseAccess(pAlpha);
1326
1327 aLastResult = BitmapEx(aContent, aAlpha);
1328 }
1329 else
1330 {
1331 if(pContent)
1332 {
1333 aContent.ReleaseAccess(pContent);
1334 }
1335
1336 if(pAlpha)
1337 {
1338 aAlpha.ReleaseAccess(pAlpha);
1339 }
1340 }
1341 }
1342
1343 return aLastResult;
1344 }
1345
1346 /* vim: set noet sw=4 ts=4: */
1347