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