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