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