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