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 0 : );
349 :
350 0 : rPal.SetEntryCount( nCols );
351 0 : pDstPal = &rPal;
352 :
353 0 : for( sal_uInt16 i = 0; i < nCols; i++ )
354 : {
355 0 : const SalColor nColor( rColMap.GetColor( i ) );
356 0 : BitmapColor& rBmpCol = rPal[ i ];
357 :
358 0 : rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
359 0 : rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
360 0 : rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
361 : }
362 : }
363 :
364 0 : nDstFormat = aSrcBuf.mnFormat;
365 : pDIB = StretchAndConvert( aSrcBuf, aTwoRect, nDstFormat,
366 0 : const_cast<BitmapPalette*>(pDstPal), &aSrcBuf.maColorMask );
367 0 : XDestroyImage( pImage );
368 : }
369 : }
370 :
371 0 : return pDIB;
372 : }
373 :
374 0 : XImage* X11SalBitmap::ImplCreateXImage(
375 : SalDisplay *pSalDisp,
376 : SalX11Screen nScreen,
377 : long nDepth,
378 : const SalTwoRect& rTwoRect
379 : ) const
380 : {
381 0 : XImage* pImage = NULL;
382 :
383 0 : if( !mpDIB && mpDDB )
384 : {
385 : const_cast<X11SalBitmap*>(this)->mpDIB =
386 : ImplCreateDIB( mpDDB->ImplGetPixmap(),
387 : mpDDB->ImplGetScreen(),
388 : mpDDB->ImplGetDepth(),
389 : 0, 0,
390 : mpDDB->ImplGetWidth(),
391 : mpDDB->ImplGetHeight(),
392 0 : mbGrey );
393 : }
394 :
395 0 : if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight )
396 : {
397 0 : Display* pXDisp = pSalDisp->GetDisplay();
398 0 : long nWidth = rTwoRect.mnDestWidth;
399 0 : long nHeight = rTwoRect.mnDestHeight;
400 :
401 0 : if( 1 == GetBitCount() )
402 0 : nDepth = 1;
403 :
404 0 : pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(),
405 : nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, NULL,
406 0 : nWidth, nHeight, 32, 0 );
407 :
408 0 : if( pImage )
409 : {
410 : BitmapBuffer* pDstBuf;
411 0 : sal_uLong nDstFormat = BMP_FORMAT_TOP_DOWN;
412 0 : boost::scoped_ptr<BitmapPalette> pPal;
413 0 : boost::scoped_ptr<ColorMask> pMask;
414 :
415 0 : switch( pImage->bits_per_pixel )
416 : {
417 : case( 1 ):
418 0 : nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
419 : ? BMP_FORMAT_1BIT_LSB_PAL
420 : : BMP_FORMAT_1BIT_MSB_PAL
421 0 : );
422 0 : break;
423 :
424 : case( 4 ):
425 0 : nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
426 : ? BMP_FORMAT_4BIT_LSN_PAL
427 : : BMP_FORMAT_4BIT_MSN_PAL
428 0 : );
429 0 : break;
430 :
431 : case( 8 ):
432 0 : nDstFormat |= BMP_FORMAT_8BIT_PAL;
433 0 : break;
434 :
435 : case( 16 ):
436 : {
437 : #ifdef OSL_BIGENDIAN
438 :
439 : if( MSBFirst == pImage->byte_order )
440 : nDstFormat |= BMP_FORMAT_16BIT_TC_MSB_MASK;
441 : else
442 : nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
443 :
444 : #else /* OSL_LITENDIAN */
445 :
446 0 : nDstFormat |= BMP_FORMAT_16BIT_TC_LSB_MASK;
447 0 : if( MSBFirst == pImage->byte_order )
448 0 : pImage->byte_order = LSBFirst;
449 :
450 : #endif
451 :
452 0 : pMask.reset(new ColorMask( pImage->red_mask, pImage->green_mask, pImage->blue_mask ));
453 : }
454 0 : break;
455 :
456 : case( 24 ):
457 : {
458 0 : if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
459 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_RGB;
460 : else
461 0 : nDstFormat |= BMP_FORMAT_24BIT_TC_BGR;
462 : }
463 0 : break;
464 :
465 : case( 32 ):
466 : {
467 0 : if( LSBFirst == pImage->byte_order )
468 0 : nDstFormat |= ( pImage->red_mask == 0xFF
469 : ? BMP_FORMAT_32BIT_TC_RGBA
470 : : BMP_FORMAT_32BIT_TC_BGRA
471 0 : );
472 : else
473 0 : nDstFormat |= ( pImage->red_mask == 0xFF
474 : ? BMP_FORMAT_32BIT_TC_ABGR
475 : : BMP_FORMAT_32BIT_TC_ARGB
476 0 : );
477 : }
478 0 : break;
479 : }
480 :
481 0 : if( pImage->depth == 1 )
482 : {
483 0 : pPal.reset(new BitmapPalette( 2 ));
484 0 : (*pPal)[ 0 ] = Color( COL_BLACK );
485 0 : (*pPal)[ 1 ] = Color( COL_WHITE );
486 : }
487 0 : else if( pImage->depth == 8 && mbGrey )
488 : {
489 0 : pPal.reset(new BitmapPalette( 256 ));
490 :
491 0 : for( sal_uInt16 i = 0; i < 256; i++ )
492 : {
493 0 : BitmapColor& rBmpCol = (*pPal)[ i ];
494 :
495 0 : rBmpCol.SetRed( i );
496 0 : rBmpCol.SetGreen( i );
497 0 : rBmpCol.SetBlue( i );
498 0 : }
499 :
500 : }
501 0 : else if( pImage->depth <= 8 )
502 : {
503 0 : const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
504 0 : const sal_uInt16 nCols = std::min( (sal_uLong)rColMap.GetUsed()
505 0 : , (sal_uLong)(1 << pImage->depth)
506 0 : );
507 :
508 0 : pPal.reset(new BitmapPalette( nCols ));
509 :
510 0 : for( sal_uInt16 i = 0; i < nCols; i++ )
511 : {
512 0 : const SalColor nColor( rColMap.GetColor( i ) );
513 0 : BitmapColor& rBmpCol = (*pPal)[ i ];
514 :
515 0 : rBmpCol.SetRed( SALCOLOR_RED( nColor ) );
516 0 : rBmpCol.SetGreen( SALCOLOR_GREEN( nColor ) );
517 0 : rBmpCol.SetBlue( SALCOLOR_BLUE( nColor ) );
518 : }
519 : }
520 :
521 0 : pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, pPal.get(), pMask.get() );
522 0 : pPal.reset();
523 0 : pMask.reset();
524 :
525 0 : if( pDstBuf && pDstBuf->mpBits )
526 : {
527 : #if defined HAVE_VALGRIND_HEADERS
528 : if (RUNNING_ON_VALGRIND)
529 : blankExtraSpace(pDstBuf);
530 : #endif
531 : // set data in buffer as data member in pImage
532 0 : pImage->data = (char*) pDstBuf->mpBits;
533 :
534 : // destroy buffer; don't destroy allocated data in buffer
535 0 : delete pDstBuf;
536 : }
537 : else
538 : {
539 0 : XDestroyImage( pImage );
540 0 : pImage = NULL;
541 0 : }
542 : }
543 : }
544 :
545 0 : return pImage;
546 : }
547 :
548 0 : bool X11SalBitmap::ImplCreateFromDrawable(
549 : Drawable aDrawable,
550 : SalX11Screen nScreen,
551 : long nDrawableDepth,
552 : long nX,
553 : long nY,
554 : long nWidth,
555 : long nHeight
556 : ) {
557 0 : Destroy();
558 :
559 0 : if( aDrawable && nWidth && nHeight && nDrawableDepth )
560 0 : mpDDB = new ImplSalDDB( aDrawable, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight );
561 :
562 0 : return( mpDDB != NULL );
563 : }
564 :
565 0 : ImplSalDDB* X11SalBitmap::ImplGetDDB(
566 : Drawable aDrawable,
567 : SalX11Screen nXScreen,
568 : long nDrawableDepth,
569 : const SalTwoRect& rTwoRect
570 : ) const
571 : {
572 0 : if( !mpDDB || !mpDDB->ImplMatches( nXScreen, nDrawableDepth, rTwoRect ) )
573 : {
574 0 : if( mpDDB )
575 : {
576 : // do we already have a DIB? if not, create aDIB from current DDB first
577 0 : if( !mpDIB )
578 : {
579 : const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
580 : mpDDB->ImplGetScreen(),
581 : mpDDB->ImplGetDepth(),
582 : 0, 0,
583 : mpDDB->ImplGetWidth(),
584 : mpDDB->ImplGetHeight(),
585 0 : mbGrey );
586 : }
587 :
588 0 : delete mpDDB, const_cast<X11SalBitmap*>(this)->mpDDB = NULL;
589 : }
590 :
591 0 : if( mpCache )
592 0 : mpCache->ImplRemove( const_cast<X11SalBitmap*>(this) );
593 :
594 0 : SalTwoRect aTwoRect( rTwoRect );
595 0 : if( aTwoRect.mnSrcX < 0 )
596 : {
597 0 : aTwoRect.mnSrcWidth += aTwoRect.mnSrcX;
598 0 : aTwoRect.mnSrcX = 0;
599 : }
600 0 : if( aTwoRect.mnSrcY < 0 )
601 : {
602 0 : aTwoRect.mnSrcHeight += aTwoRect.mnSrcY;
603 0 : aTwoRect.mnSrcY = 0;
604 : }
605 :
606 : // create new DDB from DIB
607 0 : const Size aSize( GetSize() );
608 0 : if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth &&
609 0 : aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight )
610 : {
611 0 : aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
612 0 : aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
613 0 : aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
614 : }
615 0 : else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ||
616 0 : aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
617 : {
618 : // #i47823# this should not happen at all, but does nonetheless
619 : // because BitmapEx allows for mask bitmaps of different size
620 : // than image bitmap (broken)
621 0 : if( aTwoRect.mnSrcX >= aSize.Width() ||
622 0 : aTwoRect.mnSrcY >= aSize.Height() )
623 0 : return NULL; // this would be a really mad case
624 :
625 0 : if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() )
626 : {
627 0 : aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX;
628 0 : if( aTwoRect.mnSrcWidth < 1 )
629 : {
630 0 : aTwoRect.mnSrcX = 0;
631 0 : aTwoRect.mnSrcWidth = aSize.Width();
632 : }
633 : }
634 0 : if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
635 : {
636 0 : aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY;
637 0 : if( aTwoRect.mnSrcHeight < 1 )
638 : {
639 0 : aTwoRect.mnSrcY = 0;
640 0 : aTwoRect.mnSrcHeight = aSize.Height();
641 : }
642 : }
643 : }
644 :
645 : XImage* pImage = ImplCreateXImage( GetGenericData()->GetSalDisplay(), nXScreen,
646 0 : nDrawableDepth, aTwoRect );
647 :
648 0 : if( pImage )
649 : {
650 0 : const_cast<X11SalBitmap*>(this)->mpDDB = new ImplSalDDB( pImage, aDrawable, nXScreen, aTwoRect );
651 0 : delete[] pImage->data, pImage->data = NULL;
652 0 : XDestroyImage( pImage );
653 :
654 0 : if( mpCache )
655 0 : mpCache->ImplAdd( const_cast<X11SalBitmap*>(this), mpDDB->ImplGetMemSize() );
656 : }
657 : }
658 :
659 0 : return mpDDB;
660 : }
661 :
662 0 : void X11SalBitmap::ImplDraw(
663 : Drawable aDrawable,
664 : SalX11Screen nXScreen,
665 : long nDrawableDepth,
666 : const SalTwoRect& rTwoRect,
667 : const GC& rGC
668 : ) const
669 : {
670 0 : ImplGetDDB( aDrawable, nXScreen, nDrawableDepth, rTwoRect );
671 0 : if( mpDDB )
672 0 : mpDDB->ImplDraw( aDrawable, nDrawableDepth, rTwoRect, rGC );
673 0 : }
674 :
675 0 : bool X11SalBitmap::Create( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal )
676 : {
677 0 : Destroy();
678 0 : mpDIB = ImplCreateDIB( rSize, nBitCount, rPal );
679 :
680 0 : return( mpDIB != NULL );
681 : }
682 :
683 0 : bool X11SalBitmap::Create( const SalBitmap& rSSalBmp )
684 : {
685 0 : Destroy();
686 :
687 0 : const X11SalBitmap& rSalBmp = static_cast<const X11SalBitmap&>( rSSalBmp );
688 :
689 0 : if( rSalBmp.mpDIB )
690 : {
691 : // TODO: reference counting...
692 0 : mpDIB = new BitmapBuffer( *rSalBmp.mpDIB );
693 : // TODO: get rid of this when BitmapBuffer gets copy constructor
694 : try
695 : {
696 0 : mpDIB->mpBits = new sal_uInt8[ mpDIB->mnScanlineSize * mpDIB->mnHeight ];
697 : #if defined HAVE_VALGRIND_HEADERS
698 : if (RUNNING_ON_VALGRIND)
699 : blankExtraSpace(mpDIB);
700 : #endif
701 : }
702 0 : catch (const std::bad_alloc&)
703 : {
704 0 : delete mpDIB;
705 0 : mpDIB = NULL;
706 : }
707 :
708 0 : if( mpDIB )
709 0 : memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight );
710 : }
711 0 : else if( rSalBmp.mpDDB )
712 : ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(),
713 : rSalBmp.mpDDB->ImplGetScreen(),
714 : rSalBmp.mpDDB->ImplGetDepth(),
715 0 : 0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() );
716 :
717 0 : return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) ||
718 0 : ( rSalBmp.mpDIB && ( mpDIB != NULL ) ) ||
719 0 : ( rSalBmp.mpDDB && ( mpDDB != NULL ) ) );
720 : }
721 :
722 0 : bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* )
723 : {
724 0 : return false;
725 : }
726 :
727 0 : bool X11SalBitmap::Create( const SalBitmap&, sal_uInt16 )
728 : {
729 0 : return false;
730 : }
731 :
732 0 : bool X11SalBitmap::Create(
733 : const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas > xBitmapCanvas,
734 : Size& rSize,
735 : bool bMask
736 : ) {
737 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet >
738 0 : xFastPropertySet( xBitmapCanvas, ::com::sun::star::uno::UNO_QUERY );
739 :
740 0 : if( xFastPropertySet.get() ) {
741 : sal_Int32 depth;
742 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > args;
743 :
744 0 : if( xFastPropertySet->getFastPropertyValue(bMask ? 2 : 1) >>= args ) {
745 : long pixmapHandle;
746 0 : if( ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) ) {
747 :
748 0 : mbGrey = bMask;
749 : bool bSuccess = ImplCreateFromDrawable(
750 : pixmapHandle,
751 : // FIXME: this seems multi-screen broken to me
752 : SalX11Screen( 0 ),
753 : depth,
754 : 0,
755 : 0,
756 0 : (long) rSize.Width(),
757 0 : (long) rSize.Height()
758 0 : );
759 0 : bool bFreePixmap = false;
760 0 : if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap )
761 0 : XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), pixmapHandle );
762 :
763 0 : return bSuccess;
764 : }
765 0 : }
766 : }
767 :
768 0 : return false;
769 : }
770 :
771 0 : void X11SalBitmap::Destroy()
772 : {
773 0 : if( mpDIB )
774 : {
775 0 : delete[] mpDIB->mpBits;
776 0 : delete mpDIB, mpDIB = NULL;
777 : }
778 :
779 0 : if( mpDDB )
780 0 : delete mpDDB, mpDDB = NULL;
781 :
782 0 : if( mpCache )
783 0 : mpCache->ImplRemove( this );
784 0 : }
785 :
786 0 : Size X11SalBitmap::GetSize() const
787 : {
788 0 : Size aSize;
789 :
790 0 : if( mpDIB )
791 0 : aSize.Width() = mpDIB->mnWidth, aSize.Height() = mpDIB->mnHeight;
792 0 : else if( mpDDB )
793 0 : aSize.Width() = mpDDB->ImplGetWidth(), aSize.Height() = mpDDB->ImplGetHeight();
794 :
795 0 : return aSize;
796 : }
797 :
798 0 : sal_uInt16 X11SalBitmap::GetBitCount() const
799 : {
800 : sal_uInt16 nBitCount;
801 :
802 0 : if( mpDIB )
803 0 : nBitCount = mpDIB->mnBitCount;
804 0 : else if( mpDDB )
805 0 : nBitCount = mpDDB->ImplGetDepth();
806 : else
807 0 : nBitCount = 0;
808 :
809 0 : return nBitCount;
810 : }
811 :
812 0 : BitmapBuffer* X11SalBitmap::AcquireBuffer( bool )
813 : {
814 0 : if( !mpDIB && mpDDB )
815 : {
816 : mpDIB = ImplCreateDIB(
817 : mpDDB->ImplGetPixmap(),
818 : mpDDB->ImplGetScreen(),
819 : mpDDB->ImplGetDepth(),
820 : 0, 0,
821 : mpDDB->ImplGetWidth(),
822 : mpDDB->ImplGetHeight(),
823 : mbGrey
824 0 : );
825 : }
826 :
827 0 : return mpDIB;
828 : }
829 :
830 0 : void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, bool bReadOnly )
831 : {
832 0 : if( !bReadOnly )
833 : {
834 0 : if( mpDDB )
835 0 : delete mpDDB, mpDDB = NULL;
836 :
837 0 : if( mpCache )
838 0 : mpCache->ImplRemove( this );
839 : }
840 0 : }
841 :
842 0 : bool X11SalBitmap::GetSystemData( BitmapSystemData& rData )
843 : {
844 0 : if( mpDDB )
845 : {
846 : // Rename/retype pDummy to your likings (though X11 Pixmap is
847 : // prolly not a good idea, since it's accessed from
848 : // non-platform aware code in vcl/bitmap.hxx)
849 0 : rData.aPixmap = (void*)mpDDB->ImplGetPixmap();
850 0 : rData.mnWidth = mpDDB->ImplGetWidth ();
851 0 : rData.mnHeight = mpDDB->ImplGetHeight ();
852 0 : return true;
853 : }
854 :
855 0 : return false;
856 : }
857 :
858 : // - ImplSalDDB -
859 :
860 0 : ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable,
861 : SalX11Screen nXScreen, const SalTwoRect& rTwoRect )
862 : : maPixmap ( 0 )
863 : , maTwoRect ( rTwoRect )
864 : , mnDepth ( pImage->depth )
865 0 : , mnXScreen ( nXScreen )
866 : {
867 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
868 0 : Display* pXDisp = pSalDisp->GetDisplay();
869 :
870 0 : if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() )) )
871 : {
872 : XGCValues aValues;
873 : GC aGC;
874 0 : int nValues = GCFunction;
875 :
876 0 : aValues.function = GXcopy;
877 :
878 0 : if( 1 == mnDepth )
879 : {
880 0 : nValues |= ( GCForeground | GCBackground );
881 0 : aValues.foreground = 1, aValues.background = 0;
882 : }
883 :
884 0 : aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
885 0 : XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight );
886 0 : XFreeGC( pXDisp, aGC );
887 : }
888 0 : }
889 :
890 0 : ImplSalDDB::ImplSalDDB(
891 : Drawable aDrawable,
892 : SalX11Screen nXScreen,
893 : long nDrawableDepth,
894 : long nX,
895 : long nY,
896 : long nWidth,
897 : long nHeight
898 : ) : mnDepth( nDrawableDepth )
899 0 : , mnXScreen( nXScreen )
900 : {
901 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
902 0 : Display* pXDisp = pSalDisp->GetDisplay();
903 :
904 0 : if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) )
905 : {
906 : XGCValues aValues;
907 : GC aGC;
908 0 : int nValues = GCFunction;
909 :
910 0 : aValues.function = GXcopy;
911 :
912 0 : if( 1 == mnDepth )
913 : {
914 0 : nValues |= ( GCForeground | GCBackground );
915 0 : aValues.foreground = 1, aValues.background = 0;
916 : }
917 :
918 0 : aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
919 : ImplDraw( aDrawable, nDrawableDepth, maPixmap, mnDepth,
920 0 : nX, nY, nWidth, nHeight, 0, 0, aGC );
921 0 : XFreeGC( pXDisp, aGC );
922 :
923 0 : maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0;
924 0 : maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = nWidth;
925 0 : maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = nHeight;
926 : }
927 : else
928 : {
929 0 : maTwoRect.mnSrcX = maTwoRect.mnSrcY = maTwoRect.mnDestX = maTwoRect.mnDestY = 0;
930 0 : maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = 0;
931 0 : maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = 0;
932 : }
933 0 : }
934 :
935 0 : ImplSalDDB::~ImplSalDDB()
936 : {
937 0 : if( maPixmap && ImplGetSVData() )
938 0 : XFreePixmap( GetGenericData()->GetSalDisplay()->GetDisplay(), maPixmap );
939 0 : }
940 :
941 0 : bool ImplSalDDB::ImplMatches( SalX11Screen nXScreen, long nDepth, const SalTwoRect& rTwoRect ) const
942 : {
943 0 : bool bRet = false;
944 :
945 0 : if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nXScreen == mnXScreen)
946 : {
947 0 : if ( rTwoRect.mnSrcX == maTwoRect.mnSrcX
948 0 : && rTwoRect.mnSrcY == maTwoRect.mnSrcY
949 0 : && rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth
950 0 : && rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight
951 0 : && rTwoRect.mnDestWidth == maTwoRect.mnDestWidth
952 0 : && rTwoRect.mnDestHeight == maTwoRect.mnDestHeight
953 : )
954 : {
955 : // absolutely indentically
956 0 : bRet = true;
957 : }
958 0 : else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth
959 0 : && rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight
960 0 : && maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth
961 0 : && maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight
962 0 : && rTwoRect.mnSrcX >= maTwoRect.mnSrcX
963 0 : && rTwoRect.mnSrcY >= maTwoRect.mnSrcY
964 0 : && ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth )
965 0 : && ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight )
966 : )
967 : {
968 0 : bRet = true;
969 : }
970 : }
971 :
972 0 : return bRet;
973 : }
974 :
975 0 : void ImplSalDDB::ImplDraw(
976 : Drawable aDrawable,
977 : long nDrawableDepth,
978 : const SalTwoRect& rTwoRect,
979 : const GC& rGC
980 : ) const
981 : {
982 : ImplDraw( maPixmap, mnDepth, aDrawable, nDrawableDepth,
983 : rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY,
984 : rTwoRect.mnDestWidth, rTwoRect.mnDestHeight,
985 0 : rTwoRect.mnDestX, rTwoRect.mnDestY, rGC );
986 0 : }
987 :
988 0 : void ImplSalDDB::ImplDraw(
989 : Drawable aSrcDrawable,
990 : long nSrcDrawableDepth,
991 : Drawable aDstDrawable,
992 : long,
993 : long nSrcX,
994 : long nSrcY,
995 : long nDestWidth,
996 : long nDestHeight,
997 : long nDestX,
998 : long nDestY,
999 : const GC& rGC
1000 : ) {
1001 0 : SalDisplay* pSalDisp = GetGenericData()->GetSalDisplay();
1002 0 : Display* pXDisp = pSalDisp->GetDisplay();
1003 :
1004 0 : if( 1 == nSrcDrawableDepth )
1005 : {
1006 : XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1007 0 : nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 );
1008 : }
1009 : else
1010 : {
1011 : XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC,
1012 0 : nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY );
1013 : }
1014 0 : }
1015 :
1016 : // - ImplSalBitmapCache -
1017 :
1018 : struct ImplBmpObj
1019 : {
1020 : X11SalBitmap* mpBmp;
1021 : sal_uLong mnMemSize;
1022 : sal_uLong mnFlags;
1023 :
1024 0 : ImplBmpObj( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags ) :
1025 0 : mpBmp( pBmp ), mnMemSize( nMemSize ), mnFlags( nFlags ) {}
1026 : };
1027 :
1028 0 : ImplSalBitmapCache::ImplSalBitmapCache() :
1029 0 : mnTotalSize( 0UL )
1030 : {
1031 0 : }
1032 :
1033 0 : ImplSalBitmapCache::~ImplSalBitmapCache()
1034 : {
1035 0 : ImplClear();
1036 0 : }
1037 :
1038 0 : void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp, sal_uLong nMemSize, sal_uLong nFlags )
1039 : {
1040 0 : ImplBmpObj* pObj = NULL;
1041 0 : bool bFound = false;
1042 :
1043 0 : for(
1044 0 : BmpList_impl::iterator it = maBmpList.begin();
1045 0 : (it != maBmpList.end() ) && !bFound ;
1046 : ++it
1047 : ) {
1048 0 : pObj = *it;
1049 0 : if( pObj->mpBmp == pBmp )
1050 0 : bFound = true;
1051 : }
1052 :
1053 0 : mnTotalSize += nMemSize;
1054 :
1055 0 : if( bFound )
1056 : {
1057 0 : mnTotalSize -= pObj->mnMemSize;
1058 0 : pObj->mnMemSize = nMemSize, pObj->mnFlags = nFlags;
1059 : }
1060 : else
1061 0 : maBmpList.push_back( new ImplBmpObj( pBmp, nMemSize, nFlags ) );
1062 0 : }
1063 :
1064 0 : void ImplSalBitmapCache::ImplRemove( X11SalBitmap* pBmp )
1065 : {
1066 0 : for(
1067 0 : BmpList_impl::iterator it = maBmpList.begin();
1068 0 : it != maBmpList.end();
1069 : ++it
1070 : ) {
1071 0 : if( (*it)->mpBmp == pBmp )
1072 : {
1073 0 : (*it)->mpBmp->ImplRemovedFromCache();
1074 0 : mnTotalSize -= (*it)->mnMemSize;
1075 0 : delete *it;
1076 0 : maBmpList.erase( it );
1077 0 : break;
1078 : }
1079 : }
1080 0 : }
1081 :
1082 0 : void ImplSalBitmapCache::ImplClear()
1083 : {
1084 0 : for(
1085 0 : BmpList_impl::iterator it = maBmpList.begin();
1086 0 : it != maBmpList.end();
1087 : ++it
1088 : ) {
1089 0 : (*it)->mpBmp->ImplRemovedFromCache();
1090 0 : delete *it;
1091 : }
1092 0 : maBmpList.clear();
1093 0 : mnTotalSize = 0;
1094 0 : }
1095 :
1096 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|