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 <string.h>
21 : #include <stdio.h>
22 : #include <errno.h>
23 :
24 : #ifdef FREEBSD
25 : #include <sys/types.h>
26 : #endif
27 :
28 : #include <prex.h>
29 : #include <X11/Xproto.h>
30 : #include <postx.h>
31 :
32 : #include <osl/endian.h>
33 :
34 : #include <vcl/bitmap.hxx>
35 : #include <vcl/salbtype.hxx>
36 : #include <com/sun/star/beans/XFastPropertySet.hpp>
37 :
38 : #include <unx/salunx.h>
39 : #include <unx/saldata.hxx>
40 : #include <unx/saldisp.hxx>
41 : #include <unx/salgdi.h>
42 : #include <unx/salbmp.h>
43 : #include <unx/salinst.h>
44 : #include <unx/x11/xlimits.hxx>
45 :
46 : #if defined HAVE_VALGRIND_HEADERS
47 : #include <valgrind/memcheck.h>
48 : #endif
49 :
50 : #include <boost/scoped_ptr.hpp>
51 :
52 : // - SalBitmap -
53 :
54 0 : SalBitmap* X11SalInstance::CreateSalBitmap()
55 : {
56 0 : return new X11SalBitmap();
57 : }
58 :
59 : ImplSalBitmapCache* X11SalBitmap::mpCache = NULL;
60 : sal_uLong X11SalBitmap::mnCacheInstCount = 0;
61 :
62 0 : X11SalBitmap::X11SalBitmap()
63 : : mpDIB( NULL )
64 : , mpDDB( NULL )
65 0 : , mbGrey( false )
66 : {
67 0 : }
68 :
69 0 : X11SalBitmap::~X11SalBitmap()
70 : {
71 0 : Destroy();
72 0 : }
73 :
74 0 : void X11SalBitmap::ImplCreateCache()
75 : {
76 0 : if( !mnCacheInstCount++ )
77 0 : mpCache = new ImplSalBitmapCache;
78 0 : }
79 :
80 0 : void X11SalBitmap::ImplDestroyCache()
81 : {
82 : DBG_ASSERT( mnCacheInstCount, "X11SalBitmap::ImplDestroyCache(): underflow" );
83 :
84 0 : if( mnCacheInstCount && !--mnCacheInstCount )
85 0 : delete mpCache, mpCache = NULL;
86 0 : }
87 :
88 0 : void X11SalBitmap::ImplRemovedFromCache()
89 : {
90 0 : if( mpDDB )
91 0 : delete mpDDB, mpDDB = NULL;
92 0 : }
93 :
94 : #if defined HAVE_VALGRIND_HEADERS
95 : namespace
96 : {
97 : void blankExtraSpace(BitmapBuffer* pDIB)
98 : {
99 : size_t nExtraSpaceInScanLine = pDIB->mnScanlineSize - pDIB->mnWidth * pDIB->mnBitCount / 8;
100 : if (nExtraSpaceInScanLine)
101 : {
102 : for (long i = 0; i < pDIB->mnHeight; ++i)
103 : {
104 : sal_uInt8 *pRow = pDIB->mpBits + (i * pDIB->mnScanlineSize);
105 : memset(pRow + (pDIB->mnScanlineSize - nExtraSpaceInScanLine), 0, nExtraSpaceInScanLine);
106 : }
107 : }
108 : }
109 : }
110 : #endif
111 :
112 0 : BitmapBuffer* X11SalBitmap::ImplCreateDIB(
113 : const Size& rSize,
114 : sal_uInt16 nBitCount,
115 : const BitmapPalette& rPal
116 : ) {
117 : DBG_ASSERT(
118 : nBitCount == 1
119 : || nBitCount == 4
120 : || nBitCount == 8
121 : || nBitCount == 16
122 : || nBitCount == 24
123 : , "Unsupported BitCount!"
124 : );
125 :
126 0 : BitmapBuffer* pDIB = NULL;
127 :
128 0 : if( rSize.Width() && rSize.Height() )
129 : {
130 : try
131 : {
132 0 : pDIB = new BitmapBuffer;
133 : }
134 0 : catch (const std::bad_alloc&)
135 : {
136 0 : pDIB = NULL;
137 : }
138 :
139 0 : if( pDIB )
140 : {
141 0 : const sal_uInt16 nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0;
142 :
143 0 : pDIB->mnFormat = BMP_FORMAT_BOTTOM_UP;
144 :
145 0 : switch( nBitCount )
146 : {
147 0 : case( 1 ): pDIB->mnFormat |= BMP_FORMAT_1BIT_MSB_PAL; break;
148 0 : case( 4 ): pDIB->mnFormat |= BMP_FORMAT_4BIT_MSN_PAL; break;
149 0 : case( 8 ): pDIB->mnFormat |= BMP_FORMAT_8BIT_PAL; break;
150 : #ifdef OSL_BIGENDIAN
151 : case(16 ):
152 : pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_MSB_MASK;
153 : pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
154 : break;
155 : #else
156 : case(16 ):
157 0 : pDIB->mnFormat|= BMP_FORMAT_16BIT_TC_LSB_MASK;
158 0 : pDIB->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f );
159 0 : break;
160 : #endif
161 : default:
162 0 : nBitCount = 24;
163 : //fall through
164 : case 24:
165 0 : pDIB->mnFormat |= BMP_FORMAT_24BIT_TC_BGR;
166 0 : break;
167 : }
168 :
169 0 : pDIB->mnWidth = rSize.Width();
170 0 : pDIB->mnHeight = rSize.Height();
171 0 : pDIB->mnScanlineSize = AlignedWidth4Bytes( pDIB->mnWidth * nBitCount );
172 0 : pDIB->mnBitCount = nBitCount;
173 :
174 0 : if( nColors )
175 : {
176 0 : pDIB->maPalette = rPal;
177 0 : pDIB->maPalette.SetEntryCount( nColors );
178 : }
179 :
180 : try
181 : {
182 0 : pDIB->mpBits = new sal_uInt8[ pDIB->mnScanlineSize * pDIB->mnHeight ];
183 : #if defined HAVE_VALGRIND_HEADERS
184 : if (RUNNING_ON_VALGRIND)
185 : blankExtraSpace(pDIB);
186 : #endif
187 : }
188 0 : catch (const std::bad_alloc&)
189 : {
190 0 : delete pDIB;
191 0 : pDIB = NULL;
192 : }
193 : }
194 : }
195 : else
196 0 : pDIB = NULL;
197 :
198 0 : return pDIB;
199 : }
200 :
201 0 : BitmapBuffer* X11SalBitmap::ImplCreateDIB(
202 : Drawable aDrawable,
203 : SalX11Screen nScreen,
204 : long nDrawableDepth,
205 : long nX,
206 : long nY,
207 : long nWidth,
208 : long nHeight,
209 : bool bGrey
210 : ) {
211 0 : BitmapBuffer* pDIB = NULL;
212 :
213 0 : if( aDrawable && nWidth && nHeight && nDrawableDepth )
214 : {
215 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
216 0 : Display* pXDisp = pSalDisp->GetDisplay();
217 :
218 : // do not die on XError here
219 : // alternatively one could check the coordinates for being offscreen
220 : // but this call can actually work on servers with backing store
221 : // defaults even if the rectangle is offscreen
222 : // so better catch the XError
223 0 : GetGenericData()->ErrorTrapPush();
224 0 : XImage* pImage = XGetImage( pXDisp, aDrawable, nX, nY, nWidth, nHeight, AllPlanes, ZPixmap );
225 0 : bool bWasError = GetGenericData()->ErrorTrapPop( false );
226 :
227 0 : if( ! bWasError && pImage && pImage->data )
228 : {
229 0 : const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight };
230 0 : BitmapBuffer aSrcBuf;
231 0 : sal_uLong nDstFormat = BMP_FORMAT_BOTTOM_UP;
232 0 : const BitmapPalette* pDstPal = NULL;
233 :
234 0 : aSrcBuf.mnFormat = BMP_FORMAT_TOP_DOWN;
235 0 : aSrcBuf.mnWidth = nWidth;
236 0 : aSrcBuf.mnHeight = nHeight;
237 0 : aSrcBuf.mnBitCount = pImage->bits_per_pixel;
238 0 : aSrcBuf.mnScanlineSize = pImage->bytes_per_line;
239 0 : aSrcBuf.mpBits = (sal_uInt8*) pImage->data;
240 :
241 0 : pImage->red_mask = pSalDisp->GetVisual( nScreen ).red_mask;
242 0 : pImage->green_mask = pSalDisp->GetVisual( nScreen ).green_mask;
243 0 : pImage->blue_mask = pSalDisp->GetVisual( nScreen ).blue_mask;
244 :
245 0 : switch( aSrcBuf.mnBitCount )
246 : {
247 : case( 1 ):
248 : {
249 0 : aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order
250 : ? BMP_FORMAT_1BIT_LSB_PAL
251 : : BMP_FORMAT_1BIT_MSB_PAL
252 0 : );
253 0 : nDstFormat |= BMP_FORMAT_1BIT_MSB_PAL;
254 : }
255 0 : break;
256 :
257 : case( 4 ):
258 : {
259 0 : aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order
260 : ? BMP_FORMAT_4BIT_LSN_PAL
261 : : BMP_FORMAT_4BIT_MSN_PAL
262 0 : );
263 0 : nDstFormat |= BMP_FORMAT_4BIT_MSN_PAL;
264 : }
265 0 : break;
266 :
267 : case( 8 ):
268 : {
269 0 : aSrcBuf.mnFormat |= BMP_FORMAT_8BIT_PAL;
270 0 : nDstFormat |= BMP_FORMAT_8BIT_PAL;
271 : }
272 0 : break;
273 :
274 : case( 16 ):
275 : {
276 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
277 0 : aSrcBuf.maColorMask = ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask );
278 :
279 0 : if( LSBFirst == pImage->byte_order )
280 : {
281 0 : aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
282 : }
283 : else
284 : {
285 0 : aSrcBuf.mnFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK;
286 : }
287 : }
288 0 : break;
289 :
290 : case( 24 ):
291 : {
292 0 : if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
293 0 : aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_RGB;
294 : else
295 0 : aSrcBuf.mnFormat |= BMP_FORMAT_24BIT_TC_BGR;
296 :
297 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
298 : }
299 0 : break;
300 :
301 : case( 32 ):
302 : {
303 0 : if( LSBFirst == pImage->byte_order )
304 0 : aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
305 : ? BMP_FORMAT_32BIT_TC_RGBA
306 : : BMP_FORMAT_32BIT_TC_BGRA
307 0 : );
308 : else
309 0 : aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
310 : ? BMP_FORMAT_32BIT_TC_ABGR
311 : : BMP_FORMAT_32BIT_TC_ARGB
312 0 : );
313 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
314 : }
315 0 : break;
316 : }
317 :
318 0 : BitmapPalette& rPal = aSrcBuf.maPalette;
319 :
320 0 : if( aSrcBuf.mnBitCount == 1 )
321 : {
322 0 : rPal.SetEntryCount( 2 );
323 0 : pDstPal = &rPal;
324 :
325 0 : rPal[ 0 ] = Color( COL_BLACK );
326 0 : rPal[ 1 ] = Color( COL_WHITE );
327 : }
328 0 : else if( pImage->depth == 8 && bGrey )
329 : {
330 0 : rPal.SetEntryCount( 256 );
331 0 : pDstPal = &rPal;
332 :
333 0 : for( sal_uInt16 i = 0; i < 256; i++ )
334 : {
335 0 : BitmapColor& rBmpCol = rPal[ i ];
336 :
337 0 : rBmpCol.SetRed( i );
338 0 : rBmpCol.SetGreen( i );
339 0 : rBmpCol.SetBlue( i );
340 0 : }
341 :
342 : }
343 0 : else if( aSrcBuf.mnBitCount <= 8 )
344 : {
345 0 : const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
346 0 : const sal_uInt16 nCols = std::min((sal_uLong)rColMap.GetUsed(),
347 0 : sal_uLong(1) << nDrawableDepth);
348 :
349 0 : rPal.SetEntryCount( nCols );
350 0 : pDstPal = &rPal;
351 :
352 0 : for( sal_uInt16 i = 0; i < nCols; i++ )
353 : {
354 0 : const SalColor nColor( rColMap.GetColor( i ) );
355 0 : BitmapColor& rBmpCol = rPal[ i ];
356 :
357 0 : rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
358 0 : rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
359 0 : rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
360 : }
361 : }
362 :
363 0 : nDstFormat = aSrcBuf.mnFormat;
364 : pDIB = StretchAndConvert( aSrcBuf, aTwoRect, nDstFormat,
365 0 : const_cast<BitmapPalette*>(pDstPal), &aSrcBuf.maColorMask );
366 0 : XDestroyImage( pImage );
367 : }
368 : }
369 :
370 0 : return pDIB;
371 : }
372 :
373 0 : XImage* X11SalBitmap::ImplCreateXImage(
374 : SalDisplay *pSalDisp,
375 : SalX11Screen nScreen,
376 : long nDepth,
377 : const SalTwoRect& rTwoRect
378 : ) const
379 : {
380 0 : XImage* pImage = NULL;
381 :
382 0 : if( !mpDIB && mpDDB )
383 : {
384 : const_cast<X11SalBitmap*>(this)->mpDIB =
385 : ImplCreateDIB( mpDDB->ImplGetPixmap(),
386 : mpDDB->ImplGetScreen(),
387 : mpDDB->ImplGetDepth(),
388 : 0, 0,
389 : mpDDB->ImplGetWidth(),
390 : mpDDB->ImplGetHeight(),
391 0 : mbGrey );
392 : }
393 :
394 0 : if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight )
395 : {
396 0 : Display* pXDisp = pSalDisp->GetDisplay();
397 0 : long nWidth = rTwoRect.mnDestWidth;
398 0 : long nHeight = rTwoRect.mnDestHeight;
399 :
400 0 : if( 1 == GetBitCount() )
401 0 : nDepth = 1;
402 :
403 0 : pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(),
404 : nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, NULL,
405 0 : nWidth, nHeight, 32, 0 );
406 :
407 0 : if( pImage )
408 : {
409 : BitmapBuffer* pDstBuf;
410 0 : sal_uLong nDstFormat = BMP_FORMAT_TOP_DOWN;
411 0 : boost::scoped_ptr<BitmapPalette> pPal;
412 0 : boost::scoped_ptr<ColorMask> pMask;
413 :
414 0 : switch( pImage->bits_per_pixel )
415 : {
416 : case( 1 ):
417 0 : nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
418 : ? BMP_FORMAT_1BIT_LSB_PAL
419 : : BMP_FORMAT_1BIT_MSB_PAL
420 0 : );
421 0 : break;
422 :
423 : case( 4 ):
424 0 : nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
425 : ? BMP_FORMAT_4BIT_LSN_PAL
426 : : BMP_FORMAT_4BIT_MSN_PAL
427 0 : );
428 0 : break;
429 :
430 : case( 8 ):
431 0 : nDstFormat |= BMP_FORMAT_8BIT_PAL;
432 0 : break;
433 :
434 : case( 16 ):
435 : {
436 : #ifdef OSL_BIGENDIAN
437 :
438 : if( MSBFirst == pImage->byte_order )
439 : nDstFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK;
440 : else
441 : nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
442 :
443 : #else /* OSL_LITENDIAN */
444 :
445 0 : nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
446 0 : if( MSBFirst == pImage->byte_order )
447 0 : pImage->byte_order = LSBFirst;
448 :
449 : #endif
450 :
451 0 : pMask.reset(new ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ));
452 : }
453 0 : break;
454 :
455 : case( 24 ):
456 : {
457 0 : if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
458 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_RGB;
459 : else
460 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
461 : }
462 0 : break;
463 :
464 : case( 32 ):
465 : {
466 0 : if( LSBFirst == pImage->byte_order )
467 0 : nDstFormat |= ( pImage->red_mask == 0xFF
468 : ? BMP_FORMAT_32BIT_TC_RGBA
469 : : BMP_FORMAT_32BIT_TC_BGRA
470 0 : );
471 : else
472 0 : nDstFormat |= ( pImage->red_mask == 0xFF
473 : ? BMP_FORMAT_32BIT_TC_ABGR
474 : : BMP_FORMAT_32BIT_TC_ARGB
475 0 : );
476 : }
477 0 : break;
478 : }
479 :
480 0 : if( pImage->depth == 1 )
481 : {
482 0 : pPal.reset(new BitmapPalette( 2 ));
483 0 : (*pPal)[ 0 ] = Color( COL_BLACK );
484 0 : (*pPal)[ 1 ] = Color( COL_WHITE );
485 : }
486 0 : else if( pImage->depth == 8 && mbGrey )
487 : {
488 0 : pPal.reset(new BitmapPalette( 256 ));
489 :
490 0 : for( sal_uInt16 i = 0; i < 256; i++ )
491 : {
492 0 : BitmapColor& rBmpCol = (*pPal)[ i ];
493 :
494 0 : rBmpCol.SetRed( i );
495 0 : rBmpCol.SetGreen( i );
496 0 : rBmpCol.SetBlue( i );
497 0 : }
498 :
499 : }
500 0 : else if( pImage->depth <= 8 )
501 : {
502 0 : const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
503 0 : const sal_uInt16 nCols = std::min( (sal_uLong)rColMap.GetUsed()
504 0 : , (sal_uLong)(1 << pImage->depth)
505 0 : );
506 :
507 0 : pPal.reset(new BitmapPalette( nCols ));
508 :
509 0 : for( sal_uInt16 i = 0; i < nCols; i++ )
510 : {
511 0 : const SalColor nColor( rColMap.GetColor( i ) );
512 0 : BitmapColor& rBmpCol = (*pPal)[ i ];
513 :
514 0 : rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
515 0 : rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
516 0 : rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
517 : }
518 : }
519 :
520 0 : pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, pPal.get(), pMask.get() );
521 0 : pPal.reset();
522 0 : pMask.reset();
523 :
524 0 : if( pDstBuf && pDstBuf->mpBits )
525 : {
526 : #if defined HAVE_VALGRIND_HEADERS
527 : if (RUNNING_ON_VALGRIND)
528 : blankExtraSpace(pDstBuf);
529 : #endif
530 : // set data in buffer as data member in pImage
531 0 : pImage->data = (char*) pDstBuf->mpBits;
532 :
533 : // destroy buffer; don't destroy allocated data in buffer
534 0 : delete pDstBuf;
535 : }
536 : else
537 : {
538 0 : XDestroyImage( pImage );
539 0 : pImage = NULL;
540 0 : }
541 : }
542 : }
543 :
544 0 : return pImage;
545 : }
546 :
547 0 : bool X11SalBitmap::ImplCreateFromDrawable(
548 : Drawable aDrawable,
549 : SalX11Screen nScreen,
550 : long nDrawableDepth,
551 : long nX,
552 : long nY,
553 : long nWidth,
554 : long nHeight
555 : ) {
556 0 : Destroy();
557 :
558 0 : if( aDrawable && nWidth && nHeight && nDrawableDepth )
559 0 : mpDDB = new ImplSalDDB( aDrawable, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight );
560 :
561 0 : return( mpDDB != NULL );
562 : }
563 :
564 0 : ImplSalDDB* X11SalBitmap::ImplGetDDB(
565 : Drawable aDrawable,
566 : SalX11Screen nXScreen,
567 : long nDrawableDepth,
568 : const SalTwoRect& rTwoRect
569 : ) const
570 : {
571 0 : if( !mpDDB || !mpDDB->ImplMatches( nXScreen, nDrawableDepth, rTwoRect ) )
572 : {
573 0 : if( mpDDB )
574 : {
575 : // do we already have a DIB? if not, create aDIB from current DDB first
576 0 : if( !mpDIB )
577 : {
578 : const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
579 : mpDDB->ImplGetScreen(),
580 : mpDDB->ImplGetDepth(),
581 : 0, 0,
582 : mpDDB->ImplGetWidth(),
583 : mpDDB->ImplGetHeight(),
584 0 : mbGrey );
585 : }
586 :
587 0 : delete mpDDB, const_cast<X11SalBitmap*>(this)->mpDDB = NULL;
588 : }
589 :
590 0 : if( mpCache )
591 0 : mpCache->ImplRemove( const_cast<X11SalBitmap*>(this) );
592 :
593 0 : SalTwoRect aTwoRect( rTwoRect );
594 0 : if( aTwoRect.mnSrcX < 0 )
595 : {
596 0 : aTwoRect.mnSrcWidth += aTwoRect.mnSrcX;
597 0 : aTwoRect.mnSrcX = 0;
598 : }
599 0 : if( aTwoRect.mnSrcY < 0 )
600 : {
601 0 : aTwoRect.mnSrcHeight += aTwoRect.mnSrcY;
602 0 : aTwoRect.mnSrcY = 0;
603 : }
604 :
605 : // create new DDB from DIB
606 0 : const Size aSize( GetSize() );
607 0 : if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth &&
608 0 : aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight )
609 : {
610 0 : aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
611 0 : aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
612 0 : aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
613 : }
614 0 : else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ||
615 0 : aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
616 : {
617 : // #i47823# this should not happen at all, but does nonetheless
618 : // because BitmapEx allows for mask bitmaps of different size
619 : // than image bitmap (broken)
620 0 : if( aTwoRect.mnSrcX >= aSize.Width() ||
621 0 : aTwoRect.mnSrcY >= aSize.Height() )
622 0 : return NULL; // this would be a really mad case
623 :
624 0 : if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() )
625 : {
626 0 : aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX;
627 0 : if( aTwoRect.mnSrcWidth < 1 )
628 : {
629 0 : aTwoRect.mnSrcX = 0;
630 0 : aTwoRect.mnSrcWidth = aSize.Width();
631 : }
632 : }
633 0 : if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
634 : {
635 0 : aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY;
636 0 : if( aTwoRect.mnSrcHeight < 1 )
637 : {
638 0 : aTwoRect.mnSrcY = 0;
639 0 : aTwoRect.mnSrcHeight = aSize.Height();
640 : }
641 : }
642 : }
643 :
644 : XImage* pImage = ImplCreateXImage( GetGenericData()->GetSalDisplay(), nXScreen,
645 0 : nDrawableDepth, aTwoRect );
646 :
647 0 : if( pImage )
648 : {
649 0 : const_cast<X11SalBitmap*>(this)->mpDDB = new ImplSalDDB( pImage, aDrawable, nXScreen, aTwoRect );
650 0 : delete[] pImage->data, pImage->data = NULL;
651 0 : XDestroyImage( pImage );
652 :
653 0 : if( mpCache )
654 0 : mpCache->ImplAdd( const_cast<X11SalBitmap*>(this), mpDDB->ImplGetMemSize() );
655 : }
656 : }
657 :
658 0 : return mpDDB;
659 : }
660 :
661 0 : void X11SalBitmap::ImplDraw(
662 : Drawable aDrawable,
663 : SalX11Screen nXScreen,
664 : long nDrawableDepth,
665 : const SalTwoRect& rTwoRect,
666 : const GC& rGC
667 : ) const
668 : {
669 0 : ImplGetDDB( aDrawable, nXScreen, nDrawableDepth, rTwoRect );
670 0 : if( mpDDB )
671 0 : mpDDB->ImplDraw( aDrawable, nDrawableDepth, rTwoRect, rGC );
672 0 : }
673 :
674 0 : bool X11SalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
675 : {
676 0 : Destroy();
677 0 : mpDIB = ImplCreateDIB( rSize, nBitCount, rPal );
678 :
679 0 : return( mpDIB != NULL );
680 : }
681 :
682 0 : bool X11SalBitmap::Create( const SalBitmap& rSSalBmp )
683 : {
684 0 : Destroy();
685 :
686 0 : const X11SalBitmap& rSalBmp = static_cast<const X11SalBitmap&>( rSSalBmp );
687 :
688 0 : if( rSalBmp.mpDIB )
689 : {
690 : // TODO: reference counting...
691 0 : mpDIB = new BitmapBuffer( *rSalBmp.mpDIB );
692 : // TODO: get rid of this when BitmapBuffer gets copy constructor
693 : try
694 : {
695 0 : mpDIB->mpBits = new sal_uInt8[ mpDIB->mnScanlineSize * mpDIB->mnHeight ];
696 : #if defined HAVE_VALGRIND_HEADERS
697 : if (RUNNING_ON_VALGRIND)
698 : blankExtraSpace(mpDIB);
699 : #endif
700 : }
701 0 : catch (const std::bad_alloc&)
702 : {
703 0 : delete mpDIB;
704 0 : mpDIB = NULL;
705 : }
706 :
707 0 : if( mpDIB )
708 0 : memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight );
709 : }
710 0 : else if( rSalBmp.mpDDB )
711 : ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(),
712 : rSalBmp.mpDDB->ImplGetScreen(),
713 : rSalBmp.mpDDB->ImplGetDepth(),
714 0 : 0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() );
715 :
716 0 : return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) ||
717 0 : ( rSalBmp.mpDIB && ( mpDIB != NULL ) ) ||
718 0 : ( rSalBmp.mpDDB && ( mpDDB != NULL ) ) );
719 : }
720 :
721 0 : bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* )
722 : {
723 0 : return false;
724 : }
725 :
726 0 : bool X11SalBitmap::Create( const SalBitmap&, sal_uInt16 )
727 : {
728 0 : return false;
729 : }
730 :
731 0 : bool X11SalBitmap::Create(
732 : const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas,
733 : Size& rSize,
734 : bool bMask
735 : ) {
736 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet >
737 0 : xFastPropertySet( xBitmapCanvas, ::com::sun::star::uno::UNO_QUERY );
738 :
739 0 : if( xFastPropertySet.get() ) {
740 : sal_Int32 depth;
741 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > args;
742 :
743 0 : if( xFastPropertySet->getFastPropertyValue(bMask ? 2 : 1) >>= args ) {
744 : long pixmapHandle;
745 0 : if( ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) ) {
746 :
747 0 : mbGrey = bMask;
748 : bool bSuccess = ImplCreateFromDrawable(
749 : pixmapHandle,
750 : // FIXME: this seems multi-screen broken to me
751 : SalX11Screen( 0 ),
752 : depth,
753 : 0,
754 : 0,
755 0 : (long) rSize.Width(),
756 0 : (long) rSize.Height()
757 0 : );
758 0 : bool bFreePixmap = false;
759 0 : if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap )
760 0 : XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), pixmapHandle );
761 :
762 0 : return bSuccess;
763 : }
764 0 : }
765 : }
766 :
767 0 : return false;
768 : }
769 :
770 0 : void X11SalBitmap::Destroy()
771 : {
772 0 : if( mpDIB )
773 : {
774 0 : delete[] mpDIB->mpBits;
775 0 : delete mpDIB, mpDIB = NULL;
776 : }
777 :
778 0 : if( mpDDB )
779 0 : delete mpDDB, mpDDB = NULL;
780 :
781 0 : if( mpCache )
782 0 : mpCache->ImplRemove( this );
783 0 : }
784 :
785 0 : Size X11SalBitmap::GetSize() const
786 : {
787 0 : Size aSize;
788 :
789 0 : if( mpDIB )
790 0 : aSize.Width() = mpDIB->mnWidth, aSize.Height() = mpDIB->mnHeight;
791 0 : else if( mpDDB )
792 0 : aSize.Width() = mpDDB->ImplGetWidth(), aSize.Height() = mpDDB->ImplGetHeight();
793 :
794 0 : return aSize;
795 : }
796 :
797 0 : sal_uInt16 X11SalBitmap::GetBitCount() const
798 : {
799 : sal_uInt16 nBitCount;
800 :
801 0 : if( mpDIB )
802 0 : nBitCount = mpDIB->mnBitCount;
803 0 : else if( mpDDB )
804 0 : nBitCount = mpDDB->ImplGetDepth();
805 : else
806 0 : nBitCount = 0;
807 :
808 0 : return nBitCount;
809 : }
810 :
811 0 : BitmapBuffer* X11SalBitmap::AcquireBuffer( bool )
812 : {
813 0 : if( !mpDIB && mpDDB )
814 : {
815 : mpDIB = ImplCreateDIB(
816 : mpDDB->ImplGetPixmap(),
817 : mpDDB->ImplGetScreen(),
818 : mpDDB->ImplGetDepth(),
819 : 0, 0,
820 : mpDDB->ImplGetWidth(),
821 : mpDDB->ImplGetHeight(),
822 : mbGrey
823 0 : );
824 : }
825 :
826 0 : return mpDIB;
827 : }
828 :
829 0 : void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, bool bReadOnly )
830 : {
831 0 : if( !bReadOnly )
832 : {
833 0 : if( mpDDB )
834 0 : delete mpDDB, mpDDB = NULL;
835 :
836 0 : if( mpCache )
837 0 : mpCache->ImplRemove( this );
838 : }
839 0 : }
840 :
841 0 : bool X11SalBitmap::GetSystemData( BitmapSystemData& rData )
842 : {
843 0 : if( mpDDB )
844 : {
845 : // Rename/retype pDummy to your likings (though X11 Pixmap is
846 : // prolly not a good idea, since it's accessed from
847 : // non-platform aware code in vcl/bitmap.hxx)
848 0 : rData.aPixmap = reinterpret_cast<void*>(mpDDB->ImplGetPixmap());
849 0 : rData.mnWidth = mpDDB->ImplGetWidth ();
850 0 : rData.mnHeight = mpDDB->ImplGetHeight ();
851 0 : return true;
852 : }
853 :
854 0 : return false;
855 : }
856 :
857 : // - ImplSalDDB -
858 :
859 0 : ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable,
860 : SalX11Screen nXScreen, const SalTwoRect& rTwoRect )
861 : : maPixmap ( 0 )
862 : , maTwoRect ( rTwoRect )
863 : , mnDepth ( pImage->depth )
864 0 : , mnXScreen ( nXScreen )
865 : {
866 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
867 0 : Display* pXDisp = pSalDisp->GetDisplay();
868 :
869 0 : if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() )) )
870 : {
871 : XGCValues aValues;
872 : GC aGC;
873 0 : int nValues = GCFunction;
874 :
875 0 : aValues.function = GXcopy;
876 :
877 0 : if( 1 == mnDepth )
878 : {
879 0 : nValues |= ( GCForeground | GCBackground );
880 0 : aValues.foreground = 1, aValues.background = 0;
881 : }
882 :
883 0 : aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
884 0 : XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight );
885 0 : XFreeGC( pXDisp, aGC );
886 : }
887 0 : }
888 :
889 0 : ImplSalDDB::ImplSalDDB(
890 : Drawable aDrawable,
891 : SalX11Screen nXScreen,
892 : long nDrawableDepth,
893 : long nX,
894 : long nY,
895 : long nWidth,
896 : long nHeight
897 : ) : mnDepth( nDrawableDepth )
898 0 : , mnXScreen( nXScreen )
899 : {
900 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
901 0 : Display* pXDisp = pSalDisp->GetDisplay();
902 :
903 0 : if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) )
904 : {
905 : XGCValues aValues;
906 : GC aGC;
907 0 : int nValues = GCFunction;
908 :
909 0 : aValues.function = GXcopy;
910 :
911 0 : if( 1 == mnDepth )
912 : {
913 0 : nValues |= ( GCForeground | GCBackground );
914 0 : aValues.foreground = 1, aValues.background = 0;
915 : }
916 :
917 0 : aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
918 : ImplDraw( aDrawable, nDrawableDepth, maPixmap, mnDepth,
919 0 : nX, nY, nWidth, nHeight, 0, 0, aGC );
920 0 : XFreeGC( pXDisp, aGC );
921 :
922 0 : maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0;
923 0 : maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = nWidth;
924 0 : maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = nHeight;
925 : }
926 : else
927 : {
928 0 : maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0;
929 0 : maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = 0;
930 0 : maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = 0;
931 : }
932 0 : }
933 :
934 0 : ImplSalDDB::~ImplSalDDB()
935 : {
936 0 : if( maPixmap && ImplGetSVData() )
937 0 : XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), maPixmap );
938 0 : }
939 :
940 0 : bool ImplSalDDB::ImplMatches( SalX11Screen nXScreen, long nDepth, const SalTwoRect& rTwoRect ) const
941 : {
942 0 : bool bRet = false;
943 :
944 0 : if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nXScreen == mnXScreen)
945 : {
946 0 : if ( rTwoRect.mnSrcX == maTwoRect.mnSrcX
947 0 : && rTwoRect.mnSrcY == maTwoRect.mnSrcY
948 0 : && rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth
949 0 : && rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight
950 0 : && rTwoRect.mnDestWidth == maTwoRect.mnDestWidth
951 0 : && rTwoRect.mnDestHeight == maTwoRect.mnDestHeight
952 : )
953 : {
954 : // absolutely indentically
955 0 : bRet = true;
956 : }
957 0 : else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth
958 0 : && rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight
959 0 : && maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth
960 0 : && maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight
961 0 : && rTwoRect.mnSrcX >= maTwoRect.mnSrcX
962 0 : && rTwoRect.mnSrcY >= maTwoRect.mnSrcY
963 0 : && ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth )
964 0 : && ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight )
965 : )
966 : {
967 0 : bRet = true;
968 : }
969 : }
970 :
971 0 : return bRet;
972 : }
973 :
974 0 : void ImplSalDDB::ImplDraw(
975 : Drawable aDrawable,
976 : long nDrawableDepth,
977 : const SalTwoRect& rTwoRect,
978 : const GC& rGC
979 : ) const
980 : {
981 : ImplDraw( maPixmap, mnDepth, aDrawable, nDrawableDepth,
982 : rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY,
983 : rTwoRect.mnDestWidth, rTwoRect.mnDestHeight,
984 0 : rTwoRect.mnDestX, rTwoRect.mnDestY, rGC );
985 0 : }
986 :
987 0 : void ImplSalDDB::ImplDraw(
988 : Drawable aSrcDrawable,
989 : long nSrcDrawableDepth,
990 : Drawable aDstDrawable,
991 : long,
992 : long nSrcX,
993 : long nSrcY,
994 : long nDestWidth,
995 : long nDestHeight,
996 : long nDestX,
997 : long nDestY,
998 : const GC& rGC
999 : ) {
1000 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
1001 0 : Display* pXDisp = pSalDisp->GetDisplay();
1002 :
1003 0 : if( 1 == nSrcDrawableDepth )
1004 : {
1005 : XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1006 0 : nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 );
1007 : }
1008 : else
1009 : {
1010 : XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1011 0 : nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY );
1012 : }
1013 0 : }
1014 :
1015 : // - ImplSalBitmapCache -
1016 :
1017 : struct ImplBmpObj
1018 : {
1019 : X11SalBitmap* mpBmp;
1020 : sal_uLong mnMemSize;
1021 : sal_uLong mnFlags;
1022 :
1023 0 : ImplBmpObj( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) :
1024 0 : mpBmp( pBmp ), mnMemSize( nMemSize ), mnFlags( nFlags ) {}
1025 : };
1026 :
1027 0 : ImplSalBitmapCache::ImplSalBitmapCache() :
1028 0 : mnTotalSize( 0UL )
1029 : {
1030 0 : }
1031 :
1032 0 : ImplSalBitmapCache::~ImplSalBitmapCache()
1033 : {
1034 0 : ImplClear();
1035 0 : }
1036 :
1037 0 : void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags )
1038 : {
1039 0 : ImplBmpObj* pObj = NULL;
1040 0 : bool bFound = false;
1041 :
1042 0 : for(
1043 0 : BmpList_impl::iterator it = maBmpList.begin();
1044 0 : (it != maBmpList.end() ) && !bFound ;
1045 : ++it
1046 : ) {
1047 0 : pObj = *it;
1048 0 : if( pObj->mpBmp == pBmp )
1049 0 : bFound = true;
1050 : }
1051 :
1052 0 : mnTotalSize += nMemSize;
1053 :
1054 0 : if( bFound )
1055 : {
1056 0 : mnTotalSize -= pObj->mnMemSize;
1057 0 : pObj->mnMemSize = nMemSize, pObj->mnFlags = nFlags;
1058 : }
1059 : else
1060 0 : maBmpList.push_back( new ImplBmpObj( pBmp, nMemSize, nFlags ) );
1061 0 : }
1062 :
1063 0 : void ImplSalBitmapCache::ImplRemove( X11SalBitmap* pBmp )
1064 : {
1065 0 : for(
1066 0 : BmpList_impl::iterator it = maBmpList.begin();
1067 0 : it != maBmpList.end();
1068 : ++it
1069 : ) {
1070 0 : if( (*it)->mpBmp == pBmp )
1071 : {
1072 0 : (*it)->mpBmp->ImplRemovedFromCache();
1073 0 : mnTotalSize -= (*it)->mnMemSize;
1074 0 : delete *it;
1075 0 : maBmpList.erase( it );
1076 0 : break;
1077 : }
1078 : }
1079 0 : }
1080 :
1081 0 : void ImplSalBitmapCache::ImplClear()
1082 : {
1083 0 : for(
1084 0 : BmpList_impl::iterator it = maBmpList.begin();
1085 0 : it != maBmpList.end();
1086 : ++it
1087 : ) {
1088 0 : (*it)->mpBmp->ImplRemovedFromCache();
1089 0 : delete *it;
1090 : }
1091 0 : maBmpList.clear();
1092 0 : mnTotalSize = 0;
1093 0 : }
1094 :
1095 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|