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