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 <vcl/outdev.hxx>
21 : #include <vcl/bitmapex.hxx>
22 : #include <vcl/alpha.hxx>
23 : #include <vcl/window.hxx>
24 : #include <vcl/bmpacc.hxx>
25 : #include <vcl/virdev.hxx>
26 : #include <vcl/image.hxx>
27 : #include <vcl/settings.hxx>
28 :
29 : #include <image.h>
30 : #include <boost/scoped_array.hpp>
31 :
32 : #define IMPSYSIMAGEITEM_MASK ( 0x01 )
33 : #define IMPSYSIMAGEITEM_ALPHA ( 0x02 )
34 :
35 0 : ImageAryData::ImageAryData( const ImageAryData& rData ) :
36 : maName( rData.maName ),
37 : mnId( rData.mnId ),
38 0 : maBitmapEx( rData.maBitmapEx )
39 : {
40 0 : }
41 :
42 0 : ImageAryData::ImageAryData( const OUString &aName,
43 : sal_uInt16 nId, const BitmapEx &aBitmap )
44 0 : : maName( aName ), mnId( nId ), maBitmapEx( aBitmap )
45 : {
46 0 : }
47 :
48 0 : ImageAryData::~ImageAryData()
49 : {
50 0 : }
51 :
52 0 : ImageAryData& ImageAryData::operator=( const ImageAryData& rData )
53 : {
54 0 : maName = rData.maName;
55 0 : mnId = rData.mnId;
56 0 : maBitmapEx = rData.maBitmapEx;
57 :
58 0 : return *this;
59 : }
60 :
61 0 : ImplImageList::ImplImageList()
62 0 : : mnRefCount(1)
63 : {
64 0 : }
65 :
66 0 : ImplImageList::ImplImageList( const ImplImageList &aSrc )
67 : : maPrefix(aSrc.maPrefix)
68 : , maImageSize(aSrc.maImageSize)
69 0 : , mnRefCount(1)
70 : {
71 0 : maImages.reserve( aSrc.maImages.size() );
72 0 : for ( ImageAryDataVec::const_iterator aIt = aSrc.maImages.begin(), aEnd = aSrc.maImages.end(); aIt != aEnd; ++aIt )
73 : {
74 0 : ImageAryData* pAryData = new ImageAryData( **aIt );
75 0 : maImages.push_back( pAryData );
76 0 : if( !pAryData->maName.isEmpty() )
77 0 : maNameHash [ pAryData->maName ] = pAryData;
78 : }
79 0 : }
80 :
81 0 : ImplImageList::~ImplImageList()
82 : {
83 0 : for ( ImageAryDataVec::iterator aIt = maImages.begin(), aEnd = maImages.end(); aIt != aEnd; ++aIt )
84 0 : delete *aIt;
85 0 : }
86 :
87 0 : void ImplImageList::AddImage( const OUString &aName,
88 : sal_uInt16 nId, const BitmapEx &aBitmapEx )
89 : {
90 0 : ImageAryData *pImg = new ImageAryData( aName, nId, aBitmapEx );
91 0 : maImages.push_back( pImg );
92 0 : if( !aName.isEmpty() )
93 0 : maNameHash [ aName ] = pImg;
94 0 : }
95 :
96 0 : void ImplImageList::RemoveImage( sal_uInt16 nPos )
97 : {
98 0 : ImageAryData *pImg = maImages[ nPos ];
99 0 : if( !pImg->maName.isEmpty() )
100 0 : maNameHash.erase( pImg->maName );
101 0 : maImages.erase( maImages.begin() + nPos );
102 0 : }
103 :
104 0 : ImplImageData::ImplImageData( const BitmapEx& rBmpEx ) :
105 : mpImageBitmap( NULL ),
106 0 : maBmpEx( rBmpEx )
107 : {
108 0 : }
109 :
110 0 : ImplImageData::~ImplImageData()
111 : {
112 0 : delete mpImageBitmap;
113 0 : }
114 :
115 0 : bool ImplImageData::IsEqual( const ImplImageData& rData )
116 : {
117 0 : return( maBmpEx == rData.maBmpEx );
118 : }
119 :
120 0 : ImplImage::ImplImage()
121 : : mnRefCount(1)
122 : , mpData(NULL)
123 0 : , meType(IMAGETYPE_BITMAP)
124 : {
125 0 : }
126 :
127 0 : ImplImage::~ImplImage()
128 : {
129 0 : switch( meType )
130 : {
131 : case IMAGETYPE_BITMAP:
132 0 : delete static_cast< Bitmap* >( mpData );
133 0 : break;
134 :
135 : case IMAGETYPE_IMAGE:
136 0 : delete static_cast< ImplImageData* >( mpData );
137 0 : break;
138 : }
139 0 : }
140 :
141 0 : ImplImageBmp::ImplImageBmp() :
142 : mpDisplayBmp( NULL ),
143 : mpInfoAry( NULL ),
144 0 : mnSize( 0 )
145 : {
146 0 : }
147 :
148 0 : ImplImageBmp::~ImplImageBmp()
149 : {
150 0 : delete[] mpInfoAry;
151 0 : delete mpDisplayBmp;
152 0 : }
153 :
154 0 : void ImplImageBmp::Create( const BitmapEx& rBmpEx, long nItemWidth, long nItemHeight, sal_uInt16 nInitSize )
155 : {
156 0 : maBmpEx = rBmpEx;
157 0 : maDisabledBmpEx.SetEmpty();
158 :
159 0 : delete mpDisplayBmp;
160 0 : mpDisplayBmp = NULL;
161 :
162 0 : maSize = Size( nItemWidth, nItemHeight );
163 0 : mnSize = nInitSize;
164 :
165 0 : delete[] mpInfoAry;
166 0 : mpInfoAry = new sal_uInt8[ mnSize ];
167 : memset( mpInfoAry,
168 0 : rBmpEx.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA : ( rBmpEx.IsTransparent() ? IMPSYSIMAGEITEM_MASK : 0 ),
169 0 : mnSize );
170 0 : }
171 :
172 0 : void ImplImageBmp::Draw( sal_uInt16 nPos, OutputDevice* pOutDev,
173 : const Point& rPos, sal_uInt16 nStyle,
174 : const Size* pSize )
175 : {
176 0 : if( pOutDev->IsDeviceOutputNecessary() )
177 : {
178 0 : const Point aSrcPos( nPos * maSize.Width(), 0 );
179 0 : Size aOutSize;
180 :
181 0 : aOutSize = ( pSize ? *pSize : pOutDev->PixelToLogic( maSize ) );
182 :
183 0 : if( nStyle & IMAGE_DRAW_DISABLE )
184 : {
185 0 : ImplUpdateDisabledBmpEx( nPos);
186 0 : pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, maDisabledBmpEx );
187 : }
188 : else
189 : {
190 0 : if( nStyle & ( IMAGE_DRAW_COLORTRANSFORM |
191 : IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE | IMAGE_DRAW_SEMITRANSPARENT ) )
192 : {
193 0 : BitmapEx aTmpBmpEx;
194 0 : const Rectangle aCropRect( aSrcPos, maSize );
195 :
196 0 : if( mpInfoAry[ nPos ] & ( IMPSYSIMAGEITEM_MASK | IMPSYSIMAGEITEM_ALPHA ) )
197 0 : aTmpBmpEx = maBmpEx;
198 : else
199 0 : aTmpBmpEx = maBmpEx.GetBitmap();
200 :
201 0 : aTmpBmpEx.Crop( aCropRect );
202 :
203 0 : Bitmap aTmpBmp( aTmpBmpEx.GetBitmap() );
204 :
205 0 : if( nStyle & ( IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE ) )
206 : {
207 0 : BitmapWriteAccess* pAcc = aTmpBmp.AcquireWriteAccess();
208 :
209 0 : if( pAcc )
210 : {
211 0 : const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
212 0 : Color aColor;
213 0 : BitmapColor aCol;
214 0 : const long nW = pAcc->Width();
215 0 : const long nH = pAcc->Height();
216 0 : boost::scoped_array<sal_uInt8> pMapR(new sal_uInt8[ 256 ]);
217 0 : boost::scoped_array<sal_uInt8> pMapG(new sal_uInt8[ 256 ]);
218 0 : boost::scoped_array<sal_uInt8> pMapB(new sal_uInt8[ 256 ]);
219 : long nX, nY;
220 :
221 0 : if( nStyle & IMAGE_DRAW_HIGHLIGHT )
222 0 : aColor = rSettings.GetHighlightColor();
223 : else
224 0 : aColor = rSettings.GetDeactiveColor();
225 :
226 0 : const sal_uInt8 cR = aColor.GetRed();
227 0 : const sal_uInt8 cG = aColor.GetGreen();
228 0 : const sal_uInt8 cB = aColor.GetBlue();
229 :
230 0 : for( nX = 0L; nX < 256L; nX++ )
231 : {
232 0 : pMapR[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cR ) >> 1 ) > 255 ) ? 255 : nY );
233 0 : pMapG[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cG ) >> 1 ) > 255 ) ? 255 : nY );
234 0 : pMapB[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cB ) >> 1 ) > 255 ) ? 255 : nY );
235 : }
236 :
237 0 : if( pAcc->HasPalette() )
238 : {
239 0 : for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
240 : {
241 0 : const BitmapColor& rCol = pAcc->GetPaletteColor( i );
242 0 : aCol.SetRed( pMapR[ rCol.GetRed() ] );
243 0 : aCol.SetGreen( pMapG[ rCol.GetGreen() ] );
244 0 : aCol.SetBlue( pMapB[ rCol.GetBlue() ] );
245 0 : pAcc->SetPaletteColor( i, aCol );
246 : }
247 : }
248 0 : else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
249 : {
250 0 : for( nY = 0L; nY < nH; nY++ )
251 : {
252 0 : Scanline pScan = pAcc->GetScanline( nY );
253 :
254 0 : for( nX = 0L; nX < nW; nX++ )
255 : {
256 0 : *pScan = pMapB[ *pScan ]; pScan++;
257 0 : *pScan = pMapG[ *pScan ]; pScan++;
258 0 : *pScan = pMapR[ *pScan ]; pScan++;
259 : }
260 : }
261 : }
262 : else
263 : {
264 0 : for( nY = 0L; nY < nH; nY++ )
265 : {
266 0 : for( nX = 0L; nX < nW; nX++ )
267 : {
268 0 : aCol = pAcc->GetPixel( nY, nX );
269 0 : aCol.SetRed( pMapR[ aCol.GetRed() ] );
270 0 : aCol.SetGreen( pMapG[ aCol.GetGreen() ] );
271 0 : aCol.SetBlue( pMapB[ aCol.GetBlue() ] );
272 0 : pAcc->SetPixel( nY, nX, aCol );
273 : }
274 : }
275 : }
276 :
277 0 : aTmpBmp.ReleaseAccess( pAcc );
278 : }
279 : }
280 :
281 0 : if( nStyle & IMAGE_DRAW_SEMITRANSPARENT )
282 : {
283 0 : if( aTmpBmpEx.IsTransparent() )
284 : {
285 0 : Bitmap aAlphaBmp( aTmpBmpEx.GetAlpha().GetBitmap() );
286 :
287 0 : aAlphaBmp.Adjust( 50 );
288 0 : aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aAlphaBmp ) );
289 : }
290 : else
291 : {
292 0 : sal_uInt8 cErase = 128;
293 0 : aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aTmpBmp.GetSizePixel(), &cErase ) );
294 : }
295 : }
296 : else
297 : {
298 0 : if( aTmpBmpEx.IsAlpha() )
299 0 : aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetAlpha() );
300 0 : else if( aTmpBmpEx.IsAlpha() )
301 0 : aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetMask() );
302 : }
303 :
304 0 : pOutDev->DrawBitmapEx( rPos, aOutSize, aTmpBmpEx );
305 : }
306 : else
307 : {
308 : const BitmapEx* pOutputBmp;
309 :
310 0 : if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
311 : {
312 0 : ImplUpdateDisplayBmp( pOutDev );
313 0 : pOutputBmp = mpDisplayBmp;
314 : }
315 : else
316 0 : pOutputBmp = &maBmpEx;
317 :
318 0 : if( pOutputBmp )
319 0 : pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, *pOutputBmp );
320 : }
321 : }
322 : }
323 0 : }
324 :
325 0 : void ImplImageBmp::ImplUpdateDisplayBmp( OutputDevice*
326 : #if defined WNT
327 : pOutDev
328 : #endif
329 : )
330 : {
331 0 : if( !mpDisplayBmp && !maBmpEx.IsEmpty() )
332 : {
333 : #if defined WNT
334 : if( maBmpEx.IsAlpha() )
335 : mpDisplayBmp = new BitmapEx( maBmpEx );
336 : else
337 : {
338 : const Bitmap aBmp( maBmpEx.GetBitmap().CreateDisplayBitmap( pOutDev ) );
339 :
340 : if( maBmpEx.IsTransparent() )
341 : mpDisplayBmp = new BitmapEx( aBmp, maBmpEx.GetMask().CreateDisplayBitmap( pOutDev ) );
342 : else
343 : mpDisplayBmp = new BitmapEx( aBmp );
344 : }
345 : #else
346 0 : mpDisplayBmp = new BitmapEx( maBmpEx );
347 : #endif
348 : }
349 0 : }
350 :
351 0 : void ImplImageBmp::ImplUpdateDisabledBmpEx( int nPos )
352 : {
353 0 : const Size aTotalSize( maBmpEx.GetSizePixel() );
354 :
355 0 : if( maDisabledBmpEx.IsEmpty() )
356 : {
357 0 : Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
358 0 : AlphaMask aGreyAlphaMask( aTotalSize );
359 :
360 0 : maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );
361 0 : nPos = -1;
362 : }
363 :
364 0 : Bitmap aBmp( maBmpEx.GetBitmap() );
365 0 : BitmapReadAccess* pBmp( aBmp.AcquireReadAccess() );
366 0 : AlphaMask aBmpAlphaMask( maBmpEx.GetAlpha() );
367 0 : BitmapReadAccess* pBmpAlphaMask( aBmpAlphaMask.AcquireReadAccess() );
368 0 : Bitmap aGrey( maDisabledBmpEx.GetBitmap() );
369 0 : BitmapWriteAccess* pGrey( aGrey.AcquireWriteAccess() );
370 0 : AlphaMask aGreyAlphaMask( maDisabledBmpEx.GetAlpha() );
371 0 : BitmapWriteAccess* pGreyAlphaMask( aGreyAlphaMask.AcquireWriteAccess() );
372 :
373 0 : if( pBmp && pBmpAlphaMask && pGrey && pGreyAlphaMask )
374 : {
375 0 : BitmapColor aGreyVal( 0 );
376 0 : BitmapColor aGreyAlphaMaskVal( 0 );
377 0 : const Point aPos( ( nPos < 0 ) ? 0 : ( nPos * maSize.Width() ), 0 );
378 0 : const int nLeft = aPos.X(), nRight = nLeft + ( ( nPos < 0 ) ? aTotalSize.Width() : maSize.Width() );
379 0 : const int nTop = aPos.Y(), nBottom = nTop + maSize.Height();
380 :
381 0 : for( int nY = nTop; nY < nBottom; ++nY )
382 : {
383 0 : for( int nX = nLeft; nX < nRight; ++nX )
384 : {
385 0 : aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
386 0 : pGrey->SetPixel( nY, nX, aGreyVal );
387 :
388 0 : const BitmapColor aBmpAlphaMaskVal( pBmpAlphaMask->GetPixel( nY, nX ) );
389 :
390 0 : aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( ::std::min( aBmpAlphaMaskVal.GetIndex() + 178ul, 255ul ) ) );
391 0 : pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
392 0 : }
393 0 : }
394 : }
395 :
396 0 : aBmp.ReleaseAccess( pBmp );
397 0 : aBmpAlphaMask.ReleaseAccess( pBmpAlphaMask );
398 0 : aGrey.ReleaseAccess( pGrey );
399 0 : aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
400 :
401 0 : maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );
402 0 : }
403 :
404 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|