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 <stdio.h>
22 : #include <poll.h>
23 :
24 : #include "vcl/salbtype.hxx"
25 :
26 : #include "unx/salunx.h"
27 : #include "unx/saldata.hxx"
28 : #include "unx/saldisp.hxx"
29 : #include "unx/salbmp.h"
30 : #include "unx/salgdi.h"
31 : #include "unx/salframe.h"
32 : #include "unx/salvd.h"
33 : #include <unx/x11/xlimits.hxx>
34 : #include "xrender_peer.hxx"
35 :
36 : #include "generic/printergfx.hxx"
37 :
38 : #include "vcl/bmpacc.hxx"
39 : #include <outdata.hxx>
40 :
41 : #undef SALGDI2_TESTTRANS
42 :
43 : // -=-= debugging =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
44 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
45 :
46 : // -----------------------------------------------------------------------------
47 :
48 : #if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
49 : #define DBG_TESTTRANS( _def_drawable ) \
50 : { \
51 : XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \
52 : 0, 0, \
53 : pPosAry->mnDestWidth, pPosAry->mnDestHeight, \
54 : 0, 0 ); \
55 : }
56 : #else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
57 : #define DBG_TESTTRANS( _def_drawable )
58 : #endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
59 :
60 : // -=-= X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
61 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
62 0 : void X11SalGraphics::CopyScreenArea( Display* pDisplay,
63 : Drawable aSrc, SalX11Screen nXScreenSrc, int nSrcDepth,
64 : Drawable aDest, SalX11Screen nXScreenDest, int nDestDepth,
65 : GC aDestGC,
66 : int src_x, int src_y,
67 : unsigned int w, unsigned int h,
68 : int dest_x, int dest_y )
69 : {
70 0 : if( nSrcDepth == nDestDepth )
71 : {
72 0 : if( nXScreenSrc == nXScreenDest )
73 : XCopyArea( pDisplay, aSrc, aDest, aDestGC,
74 0 : src_x, src_y, w, h, dest_x, dest_y );
75 : else
76 : {
77 0 : GetGenericData()->ErrorTrapPush();
78 : XImage* pImage = XGetImage( pDisplay, aSrc, src_x, src_y, w, h,
79 0 : AllPlanes, ZPixmap );
80 0 : if( pImage )
81 : {
82 0 : if( pImage->data )
83 : XPutImage( pDisplay, aDest, aDestGC, pImage,
84 0 : 0, 0, dest_x, dest_y, w, h );
85 0 : XDestroyImage( pImage );
86 : }
87 0 : GetGenericData()->ErrorTrapPop();
88 : }
89 : }
90 : else
91 : {
92 0 : X11SalBitmap aBM;
93 0 : aBM.ImplCreateFromDrawable( aSrc, nXScreenSrc, nSrcDepth, src_x, src_y, w, h );
94 : SalTwoRect aTwoRect;
95 0 : aTwoRect.mnSrcX = aTwoRect.mnSrcY = 0;
96 0 : aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = w;
97 0 : aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = h;
98 0 : aTwoRect.mnDestX = dest_x;
99 0 : aTwoRect.mnDestY = dest_y;
100 0 : aBM.ImplDraw( aDest, nXScreenDest, nDestDepth, aTwoRect,aDestGC );
101 : }
102 0 : }
103 :
104 0 : GC X11SalGraphics::CreateGC( Drawable hDrawable, unsigned long nMask )
105 : {
106 : XGCValues values;
107 :
108 0 : values.graphics_exposures = False;
109 0 : values.foreground = m_pColormap->GetBlackPixel()
110 0 : ^ m_pColormap->GetWhitePixel();
111 0 : values.function = GXxor;
112 0 : values.line_width = 1;
113 0 : values.fill_style = FillStippled;
114 0 : values.stipple = GetDisplay()->GetInvert50( m_nXScreen );
115 0 : values.subwindow_mode = ClipByChildren;
116 :
117 0 : return XCreateGC( GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values );
118 : }
119 :
120 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
121 : inline GC X11SalGraphics::GetMonoGC( Pixmap hPixmap )
122 : {
123 : if( !pMonoGC_ )
124 : pMonoGC_ = CreateGC( hPixmap );
125 :
126 : if( !bMonoGC_ )
127 : {
128 : SetClipRegion( pMonoGC_ );
129 : bMonoGC_ = sal_True;
130 : }
131 :
132 : return pMonoGC_;
133 : }
134 :
135 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
136 0 : inline GC X11SalGraphics::GetCopyGC()
137 : {
138 0 : if( bXORMode_ ) return GetInvertGC();
139 :
140 0 : if( !pCopyGC_ )
141 0 : pCopyGC_ = CreateGC( GetDrawable() );
142 :
143 0 : if( !bCopyGC_ )
144 : {
145 0 : SetClipRegion( pCopyGC_ );
146 0 : bCopyGC_ = sal_True;
147 : }
148 0 : return pCopyGC_;
149 : }
150 :
151 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
152 0 : GC X11SalGraphics::GetInvertGC()
153 : {
154 0 : if( !pInvertGC_ )
155 : pInvertGC_ = CreateGC( GetDrawable(),
156 : GCGraphicsExposures
157 : | GCForeground
158 : | GCFunction
159 0 : | GCLineWidth );
160 :
161 0 : if( !bInvertGC_ )
162 : {
163 0 : SetClipRegion( pInvertGC_ );
164 0 : bInvertGC_ = sal_True;
165 : }
166 0 : return pInvertGC_;
167 : }
168 :
169 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
170 0 : GC X11SalGraphics::GetInvert50GC()
171 : {
172 0 : if( !pInvert50GC_ )
173 : {
174 : XGCValues values;
175 :
176 0 : values.graphics_exposures = False;
177 0 : values.foreground = m_pColormap->GetWhitePixel();
178 0 : values.background = m_pColormap->GetBlackPixel();
179 0 : values.function = GXinvert;
180 0 : values.line_width = 1;
181 0 : values.line_style = LineSolid;
182 : unsigned long nValueMask =
183 : GCGraphicsExposures
184 : | GCForeground
185 : | GCBackground
186 : | GCFunction
187 : | GCLineWidth
188 : | GCLineStyle
189 : | GCFillStyle
190 0 : | GCStipple;
191 :
192 0 : char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" );
193 0 : if( pEnv && ! strcasecmp( pEnv, "true" ) )
194 : {
195 0 : values.fill_style = FillSolid;
196 0 : nValueMask &= ~ GCStipple;
197 : }
198 : else
199 : {
200 0 : values.fill_style = FillStippled;
201 0 : values.stipple = GetDisplay()->GetInvert50( m_nXScreen );
202 : }
203 :
204 : pInvert50GC_ = XCreateGC( GetXDisplay(), GetDrawable(),
205 : nValueMask,
206 0 : &values );
207 : }
208 :
209 0 : if( !bInvert50GC_ )
210 : {
211 0 : SetClipRegion( pInvert50GC_ );
212 0 : bInvert50GC_ = sal_True;
213 : }
214 0 : return pInvert50GC_;
215 : }
216 :
217 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
218 0 : inline GC X11SalGraphics::GetStippleGC()
219 : {
220 0 : if( !pStippleGC_ )
221 : pStippleGC_ = CreateGC( GetDrawable(),
222 : GCGraphicsExposures
223 : | GCFillStyle
224 0 : | GCLineWidth );
225 :
226 0 : if( !bStippleGC_ )
227 : {
228 0 : XSetFunction( GetXDisplay(), pStippleGC_, bXORMode_ ? GXxor : GXcopy );
229 0 : SetClipRegion( pStippleGC_ );
230 0 : bStippleGC_ = sal_True;
231 : }
232 :
233 0 : return pStippleGC_;
234 : }
235 :
236 : // -=-= SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
237 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
238 :
239 : extern "C"
240 : {
241 0 : static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow )
242 : {
243 0 : Bool bRet = False;
244 0 : if( (pEvent->type == GraphicsExpose || pEvent->type == NoExpose) &&
245 : pEvent->xnoexpose.drawable == (Drawable)pFrameWindow )
246 : {
247 0 : bRet = True;
248 : }
249 0 : return bRet;
250 : }
251 : }
252 :
253 :
254 0 : void X11SalGraphics::YieldGraphicsExpose()
255 : {
256 : // get frame if necessary
257 0 : SalFrame* pFrame = m_pFrame;
258 0 : Display* pDisplay = GetXDisplay();
259 0 : XLIB_Window aWindow = GetDrawable();
260 0 : if( ! pFrame )
261 : {
262 0 : const std::list< SalFrame* >& rFrames = GetGenericData()->GetSalDisplay()->getFrames();
263 0 : for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end() && ! pFrame; ++it )
264 : {
265 0 : const SystemEnvData* pEnvData = (*it)->GetSystemData();
266 0 : if( Drawable(pEnvData->aWindow) == aWindow )
267 0 : pFrame = *it;
268 : }
269 0 : if( ! pFrame )
270 0 : return;
271 : }
272 :
273 : XEvent aEvent;
274 0 : while( XCheckTypedWindowEvent( pDisplay, aWindow, Expose, &aEvent ) )
275 : {
276 0 : SalPaintEvent aPEvt( aEvent.xexpose.x, aEvent.xexpose.y, aEvent.xexpose.width+1, aEvent.xexpose.height+1 );
277 0 : pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
278 : }
279 :
280 0 : do
281 : {
282 0 : if( ! GetDisplay()->XIfEventWithTimeout( &aEvent, (XPointer)aWindow, GraphicsExposePredicate ) )
283 : // this should not happen at all; still sometimes it happens
284 0 : break;
285 :
286 0 : if( aEvent.type == NoExpose )
287 0 : break;
288 :
289 0 : if( pFrame )
290 : {
291 0 : SalPaintEvent aPEvt( aEvent.xgraphicsexpose.x, aEvent.xgraphicsexpose.y, aEvent.xgraphicsexpose.width+1, aEvent.xgraphicsexpose.height+1 );
292 0 : pFrame->CallCallback( SALEVENT_PAINT, &aPEvt );
293 : }
294 : } while( aEvent.xgraphicsexpose.count != 0 );
295 : }
296 :
297 0 : void X11SalGraphics::copyBits( const SalTwoRect *pPosAry,
298 : SalGraphics *pSSrcGraphics )
299 : {
300 : X11SalGraphics* pSrcGraphics = pSSrcGraphics
301 : ? static_cast<X11SalGraphics*>(pSSrcGraphics)
302 0 : : this;
303 :
304 0 : if( pPosAry->mnSrcWidth <= 0
305 : || pPosAry->mnSrcHeight <= 0
306 : || pPosAry->mnDestWidth <= 0
307 : || pPosAry->mnDestHeight <= 0 )
308 : {
309 0 : return;
310 : }
311 :
312 : int n;
313 0 : if( pSrcGraphics == this )
314 : {
315 0 : n = 2;
316 : }
317 0 : else if( pSrcGraphics->bWindow_ )
318 : {
319 : // window or compatible virtual device
320 0 : if( pSrcGraphics->GetDisplay() == GetDisplay() &&
321 0 : pSrcGraphics->m_nXScreen == m_nXScreen &&
322 0 : pSrcGraphics->GetVisual().GetDepth() == GetVisual().GetDepth()
323 : )
324 0 : n = 2; // same Display
325 : else
326 0 : n = 1; // printer or other display
327 : }
328 0 : else if( pSrcGraphics->bVirDev_ )
329 : {
330 : // printer compatible virtual device
331 0 : if( bPrinter_ )
332 0 : n = 2; // printer or compatible virtual device == same display
333 : else
334 0 : n = 1; // window or compatible virtual device
335 : }
336 : else
337 0 : n = 0;
338 :
339 0 : if( n == 2
340 : && pPosAry->mnSrcWidth == pPosAry->mnDestWidth
341 : && pPosAry->mnSrcHeight == pPosAry->mnDestHeight
342 : )
343 : {
344 : // #i60699# Need to generate graphics exposures (to repaint
345 : // obscured areas beneath overlapping windows), src and dest
346 : // are the same window.
347 : const bool bNeedGraphicsExposures( pSrcGraphics == this &&
348 0 : !bVirDev_ &&
349 0 : pSrcGraphics->bWindow_ );
350 :
351 : GC pCopyGC;
352 :
353 0 : if( bXORMode_
354 0 : && !pSrcGraphics->bVirDev_
355 0 : && (GetDisplay()->GetProperties() & PROPERTY_BUG_XCopyArea_GXxor) )
356 : {
357 : Pixmap hPixmap = limitXCreatePixmap( GetXDisplay(),
358 : pSrcGraphics->GetDrawable(), // source
359 : pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
360 0 : pSrcGraphics->GetBitCount() );
361 :
362 0 : pCopyGC = GetDisplay()->GetCopyGC( m_nXScreen );
363 :
364 0 : if( bNeedGraphicsExposures )
365 : XSetGraphicsExposures( GetXDisplay(),
366 : pCopyGC,
367 0 : True );
368 :
369 : XCopyArea( GetXDisplay(),
370 : pSrcGraphics->GetDrawable(), // source
371 : hPixmap, // destination
372 : pCopyGC, // no clipping
373 : pPosAry->mnSrcX, pPosAry->mnSrcY,
374 : pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
375 0 : 0, 0 ); // destination
376 : XCopyArea( GetXDisplay(),
377 : hPixmap, // source
378 : GetDrawable(), // destination
379 : GetInvertGC(), // destination clipping
380 : 0, 0, // source
381 : pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
382 0 : pPosAry->mnDestX, pPosAry->mnDestY );
383 0 : XFreePixmap( GetXDisplay(), hPixmap );
384 : }
385 : else
386 : {
387 0 : pCopyGC = GetCopyGC();
388 :
389 0 : if( bNeedGraphicsExposures )
390 : XSetGraphicsExposures( GetXDisplay(),
391 : pCopyGC,
392 0 : True );
393 :
394 : XCopyArea( GetXDisplay(),
395 : pSrcGraphics->GetDrawable(), // source
396 : GetDrawable(), // destination
397 : pCopyGC, // destination clipping
398 : pPosAry->mnSrcX, pPosAry->mnSrcY,
399 : pPosAry->mnSrcWidth, pPosAry->mnSrcHeight,
400 0 : pPosAry->mnDestX, pPosAry->mnDestY );
401 : }
402 :
403 0 : if( bNeedGraphicsExposures )
404 : {
405 0 : YieldGraphicsExpose();
406 :
407 0 : if( pCopyGC )
408 : XSetGraphicsExposures( GetXDisplay(),
409 : pCopyGC,
410 0 : False );
411 0 : }
412 : }
413 0 : else if( n )
414 : {
415 : // #i60699# No chance to handle graphics exposures - we copy
416 : // to a temp bitmap first, into which no repaints are
417 : // technically possible.
418 : SalBitmap *pDDB = pSrcGraphics->getBitmap( pPosAry->mnSrcX,
419 : pPosAry->mnSrcY,
420 : pPosAry->mnSrcWidth,
421 0 : pPosAry->mnSrcHeight );
422 :
423 0 : if( !pDDB )
424 : {
425 : stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
426 : return;
427 : }
428 :
429 0 : SalTwoRect aPosAry( *pPosAry );
430 :
431 0 : aPosAry.mnSrcX = 0, aPosAry.mnSrcY = 0;
432 0 : drawBitmap( &aPosAry, *pDDB );
433 :
434 0 : delete pDDB;
435 : }
436 : else {
437 : stderr0( "X11SalGraphics::CopyBits from Printer not yet implemented\n" );
438 : }
439 : }
440 :
441 : // --------------------------------------------------------------------------
442 :
443 0 : void X11SalGraphics::copyArea ( long nDestX, long nDestY,
444 : long nSrcX, long nSrcY,
445 : long nSrcWidth, long nSrcHeight,
446 : sal_uInt16 )
447 : {
448 : SalTwoRect aPosAry;
449 :
450 0 : aPosAry.mnDestX = nDestX;
451 0 : aPosAry.mnDestY = nDestY;
452 0 : aPosAry.mnDestWidth = nSrcWidth;
453 0 : aPosAry.mnDestHeight = nSrcHeight;
454 :
455 0 : aPosAry.mnSrcX = nSrcX;
456 0 : aPosAry.mnSrcY = nSrcY;
457 0 : aPosAry.mnSrcWidth = nSrcWidth;
458 0 : aPosAry.mnSrcHeight = nSrcHeight;
459 :
460 0 : copyBits ( &aPosAry, 0 );
461 0 : }
462 :
463 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
464 0 : void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap )
465 : {
466 0 : const SalDisplay* pSalDisp = GetDisplay();
467 0 : Display* pXDisp = pSalDisp->GetDisplay();
468 0 : const Drawable aDrawable( GetDrawable() );
469 0 : const SalColormap& rColMap = pSalDisp->GetColormap( m_nXScreen );
470 0 : const long nDepth = GetDisplay()->GetVisual( m_nXScreen ).GetDepth();
471 0 : GC aGC( GetCopyGC() );
472 : XGCValues aOldVal, aNewVal;
473 0 : int nValues = GCForeground | GCBackground;
474 :
475 0 : if( rSalBitmap.GetBitCount() == 1 )
476 : {
477 : // set foreground/background values for 1Bit bitmaps
478 0 : XGetGCValues( pXDisp, aGC, nValues, &aOldVal );
479 :
480 0 : aNewVal.foreground = rColMap.GetWhitePixel();
481 0 : aNewVal.background = rColMap.GetBlackPixel();
482 :
483 : //fdo#33455 handle 1 bit depth pngs with palette entries
484 : //to set fore/back colors
485 0 : if (const BitmapBuffer* pBitmapBuffer = const_cast<SalBitmap&>(rSalBitmap).AcquireBuffer(true))
486 : {
487 0 : const BitmapPalette& rPalette = pBitmapBuffer->maPalette;
488 0 : if (rPalette.GetEntryCount() == 2)
489 : {
490 0 : aNewVal.foreground = rColMap.GetPixel(ImplColorToSal(rPalette[0]));
491 0 : aNewVal.background = rColMap.GetPixel(ImplColorToSal(rPalette[1]));
492 : }
493 : }
494 :
495 0 : XChangeGC( pXDisp, aGC, nValues, &aNewVal );
496 : }
497 :
498 0 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nXScreen, nDepth, *pPosAry, aGC );
499 :
500 0 : if( rSalBitmap.GetBitCount() == 1 )
501 0 : XChangeGC( pXDisp, aGC, nValues, &aOldVal );
502 0 : XFlush( pXDisp );
503 0 : }
504 :
505 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
506 :
507 0 : void X11SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
508 : const SalBitmap& rSrcBitmap,
509 : const SalBitmap& rMaskBitmap )
510 : {
511 : DBG_ASSERT( !bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" );
512 :
513 : // decide if alpha masking or transparency masking is needed
514 0 : BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( sal_True );
515 0 : if( pAlphaBuffer != NULL )
516 : {
517 0 : int nMaskFormat = pAlphaBuffer->mnFormat;
518 0 : const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, sal_True );
519 0 : if( nMaskFormat == BMP_FORMAT_8BIT_PAL )
520 0 : drawAlphaBitmap( *pPosAry, rSrcBitmap, rMaskBitmap );
521 : }
522 :
523 0 : drawMaskedBitmap( pPosAry, rSrcBitmap, rMaskBitmap );
524 0 : }
525 :
526 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
527 :
528 0 : void X11SalGraphics::drawMaskedBitmap( const SalTwoRect* pPosAry,
529 : const SalBitmap& rSalBitmap,
530 : const SalBitmap& rTransBitmap )
531 : {
532 0 : const SalDisplay* pSalDisp = GetDisplay();
533 0 : Display* pXDisp = pSalDisp->GetDisplay();
534 0 : Drawable aDrawable( GetDrawable() );
535 :
536 : // figure work mode depth. If this is a VDev Drawable, use its
537 : // bitdepth to create pixmaps for, otherwise, XCopyArea will
538 : // refuse to work.
539 : const sal_uInt16 nDepth( m_pVDev ?
540 0 : m_pVDev->GetDepth() :
541 0 : pSalDisp->GetVisual( m_nXScreen ).GetDepth() );
542 : Pixmap aFG( limitXCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
543 0 : pPosAry->mnDestHeight, nDepth ) );
544 : Pixmap aBG( limitXCreatePixmap( pXDisp, aDrawable, pPosAry->mnDestWidth,
545 0 : pPosAry->mnDestHeight, nDepth ) );
546 :
547 0 : if( aFG && aBG )
548 : {
549 : GC aTmpGC;
550 : XGCValues aValues;
551 0 : const SalColormap& rColMap = pSalDisp->GetColormap( m_nXScreen );
552 0 : const int nBlack = rColMap.GetBlackPixel(), nWhite = rColMap.GetWhitePixel();
553 0 : const int nValues = GCFunction | GCForeground | GCBackground;
554 0 : SalTwoRect aTmpRect( *pPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0;
555 :
556 : // draw paint bitmap in pixmap #1
557 0 : aValues.function = GXcopy, aValues.foreground = nWhite, aValues.background = nBlack;
558 0 : aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues );
559 0 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, m_nXScreen, nDepth, aTmpRect, aTmpGC );
560 : DBG_TESTTRANS( aFG );
561 :
562 : // draw background in pixmap #2
563 : XCopyArea( pXDisp, aDrawable, aBG, aTmpGC,
564 : pPosAry->mnDestX, pPosAry->mnDestY,
565 : pPosAry->mnDestWidth, pPosAry->mnDestHeight,
566 0 : 0, 0 );
567 :
568 : DBG_TESTTRANS( aBG );
569 :
570 : // mask out paint bitmap in pixmap #1 (transparent areas 0)
571 0 : aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff;
572 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
573 0 : static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, m_nXScreen, 1, aTmpRect, aTmpGC );
574 :
575 : DBG_TESTTRANS( aFG );
576 :
577 : // #105055# For XOR mode, keep background behind bitmap intact
578 0 : if( !bXORMode_ )
579 : {
580 : // mask out background in pixmap #2 (nontransparent areas 0)
581 0 : aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
582 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
583 0 : static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, m_nXScreen, 1, aTmpRect, aTmpGC );
584 :
585 : DBG_TESTTRANS( aBG );
586 : }
587 :
588 : // merge pixmap #1 and pixmap #2 in pixmap #2
589 0 : aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
590 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
591 : XCopyArea( pXDisp, aFG, aBG, aTmpGC,
592 : 0, 0,
593 : pPosAry->mnDestWidth, pPosAry->mnDestHeight,
594 0 : 0, 0 );
595 : DBG_TESTTRANS( aBG );
596 :
597 : // #105055# Disable XOR temporarily
598 0 : sal_Bool bOldXORMode( bXORMode_ );
599 0 : bXORMode_ = sal_False;
600 :
601 : // copy pixmap #2 (result) to background
602 : XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(),
603 : 0, 0,
604 : pPosAry->mnDestWidth, pPosAry->mnDestHeight,
605 0 : pPosAry->mnDestX, pPosAry->mnDestY );
606 :
607 : DBG_TESTTRANS( aBG );
608 :
609 0 : bXORMode_ = bOldXORMode;
610 :
611 0 : XFreeGC( pXDisp, aTmpGC );
612 0 : XFlush( pXDisp );
613 : }
614 : else
615 0 : drawBitmap( pPosAry, rSalBitmap );
616 :
617 0 : if( aFG )
618 0 : XFreePixmap( pXDisp, aFG );
619 :
620 0 : if( aBG )
621 0 : XFreePixmap( pXDisp, aBG );
622 0 : }
623 :
624 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
625 0 : bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
626 : const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
627 : {
628 : // non 8-bit alpha not implemented yet
629 0 : if( rAlphaBmp.GetBitCount() != 8 )
630 0 : return false;
631 :
632 : // horizontal mirroring not implemented yet
633 0 : if( rTR.mnDestWidth < 0 )
634 0 : return false;
635 :
636 : // stretched conversion is not implemented yet
637 0 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
638 0 : return false;
639 0 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
640 0 : return false;
641 :
642 : // create destination picture
643 0 : Picture aDstPic = GetXRenderPicture();
644 0 : if( !aDstPic )
645 0 : return false;
646 :
647 0 : const SalDisplay* pSalDisp = GetDisplay();
648 0 : const SalVisual& rSalVis = pSalDisp->GetVisual( m_nXScreen );
649 0 : Display* pXDisplay = pSalDisp->GetDisplay();
650 :
651 : // create source Picture
652 0 : int nDepth = m_pVDev ? m_pVDev->GetDepth() : rSalVis.GetDepth();
653 0 : const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
654 0 : ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nXScreen, nDepth, rTR );
655 0 : if( !pSrcDDB )
656 0 : return false;
657 :
658 : //#i75249# workaround for ImplGetDDB() giving us back a different depth than
659 : // we requested. E.g. mask pixmaps are always compatible with the drawable
660 : // TODO: find an appropriate picture format for these cases
661 : // then remove the workaround below and the one for #i75531#
662 0 : if( nDepth != pSrcDDB->ImplGetDepth() )
663 0 : return false;
664 :
665 0 : Pixmap aSrcPM = pSrcDDB->ImplGetPixmap();
666 0 : if( !aSrcPM )
667 0 : return false;
668 :
669 : // create source picture
670 : // TODO: use scoped picture
671 0 : Visual* pSrcXVisual = rSalVis.GetVisual();
672 0 : XRenderPeer& rPeer = XRenderPeer::GetInstance();
673 0 : XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual );
674 0 : if( !pSrcVisFmt )
675 0 : return false;
676 0 : Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL );
677 0 : if( !aSrcPic )
678 0 : return false;
679 :
680 : // create alpha Picture
681 :
682 : // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
683 : // problem is that they don't provide an 8bit Pixmap on a non-8bit display
684 0 : BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( sal_True );
685 :
686 : // an XImage needs its data top_down
687 : // TODO: avoid wrongly oriented images in upper layers!
688 0 : const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
689 0 : const char* pSrcBits = (char*)pAlphaBuffer->mpBits;
690 0 : char* pAlphaBits = new char[ nImageSize ];
691 0 : if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
692 0 : memcpy( pAlphaBits, pSrcBits, nImageSize );
693 : else
694 : {
695 0 : char* pDstBits = pAlphaBits + nImageSize;
696 0 : const int nLineSize = pAlphaBuffer->mnScanlineSize;
697 0 : for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
698 0 : memcpy( pDstBits, pSrcBits, nLineSize );
699 : }
700 :
701 : // the alpha values need to be inverted for XRender
702 : // TODO: make upper layers use standard alpha
703 0 : long* pLDst = (long*)pAlphaBits;
704 0 : for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
705 0 : *pLDst = ~*pLDst;
706 :
707 0 : char* pCDst = (char*)pLDst;
708 0 : for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
709 0 : *pCDst = ~*pCDst;
710 :
711 0 : const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
712 : XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
713 : pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
714 0 : pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
715 :
716 : Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, hDrawable_,
717 0 : rTR.mnDestWidth, rTR.mnDestHeight, 8 );
718 :
719 : XGCValues aAlphaGCV;
720 0 : aAlphaGCV.function = GXcopy;
721 0 : GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
722 : XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
723 0 : rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
724 0 : XFreeGC( pXDisplay, aAlphaGC );
725 0 : XFree( pAlphaImg );
726 0 : if( pAlphaBits != (char*)pAlphaBuffer->mpBits )
727 0 : delete[] pAlphaBits;
728 :
729 0 : const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, sal_True );
730 :
731 : XRenderPictureAttributes aAttr;
732 0 : aAttr.repeat = true;
733 0 : Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
734 0 : if( !aAlphaPic )
735 0 : return false;
736 :
737 : // set clipping
738 0 : if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
739 0 : rPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
740 :
741 : // paint source * mask over destination picture
742 : rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic,
743 : rTR.mnSrcX, rTR.mnSrcY, 0, 0,
744 0 : rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
745 :
746 0 : rPeer.FreePicture( aAlphaPic );
747 0 : XFreePixmap(pXDisplay, aAlphaPM);
748 0 : rPeer.FreePicture( aSrcPic );
749 0 : return true;
750 : }
751 :
752 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
753 0 : bool X11SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
754 : long nHeight, sal_uInt8 nTransparency )
755 : {
756 0 : if( ! m_pFrame && ! m_pVDev )
757 0 : return false;
758 :
759 0 : if( bPenGC_ || !bBrushGC_ || bXORMode_ )
760 0 : return false; // can only perform solid fills without XOR.
761 :
762 0 : if( m_pVDev && m_pVDev->GetDepth() < 8 )
763 0 : return false;
764 :
765 0 : Picture aDstPic = GetXRenderPicture();
766 0 : if( !aDstPic )
767 0 : return false;
768 :
769 0 : const double fTransparency = (100 - nTransparency) * (1.0/100);
770 0 : const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency);
771 :
772 0 : XRenderPeer& rPeer = XRenderPeer::GetInstance();
773 : rPeer.FillRectangle( PictOpOver,
774 : aDstPic,
775 : &aRenderColor,
776 : nX, nY,
777 0 : nWidth, nHeight );
778 :
779 0 : return true;
780 : }
781 :
782 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
783 0 : void X11SalGraphics::drawBitmap( const SalTwoRect*,
784 : const SalBitmap&,
785 : SalColor )
786 : {
787 : OSL_FAIL( "::DrawBitmap with transparent color not supported" );
788 0 : }
789 :
790 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
791 0 : void X11SalGraphics::drawMask( const SalTwoRect* pPosAry,
792 : const SalBitmap &rSalBitmap,
793 : SalColor nMaskColor )
794 : {
795 0 : const SalDisplay* pSalDisp = GetDisplay();
796 0 : Display* pXDisp = pSalDisp->GetDisplay();
797 0 : Drawable aDrawable( GetDrawable() );
798 : Pixmap aStipple( limitXCreatePixmap( pXDisp, aDrawable,
799 : pPosAry->mnDestWidth,
800 0 : pPosAry->mnDestHeight, 1 ) );
801 :
802 0 : if( aStipple )
803 : {
804 0 : SalTwoRect aTwoRect( *pPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
805 : GC aTmpGC;
806 : XGCValues aValues;
807 :
808 : // create a stipple bitmap first (set bits are changed to unset bits and vice versa)
809 0 : aValues.function = GXcopyInverted;
810 0 : aValues.foreground = 1, aValues.background = 0;
811 0 : aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues );
812 0 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, m_nXScreen, 1, aTwoRect, aTmpGC );
813 :
814 0 : XFreeGC( pXDisp, aTmpGC );
815 :
816 : // Set stipple and draw rectangle
817 0 : GC aStippleGC( GetStippleGC() );
818 0 : int nX = pPosAry->mnDestX, nY = pPosAry->mnDestY;
819 :
820 0 : XSetStipple( pXDisp, aStippleGC, aStipple );
821 0 : XSetTSOrigin( pXDisp, aStippleGC, nX, nY );
822 0 : XSetForeground( pXDisp, aStippleGC, GetPixel( nMaskColor ) );
823 : XFillRectangle( pXDisp, aDrawable, aStippleGC,
824 : nX, nY,
825 0 : pPosAry->mnDestWidth, pPosAry->mnDestHeight );
826 0 : XFreePixmap( pXDisp, aStipple );
827 0 : XFlush( pXDisp );
828 : }
829 : else
830 0 : drawBitmap( pPosAry, rSalBitmap );
831 0 : }
832 :
833 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
834 0 : SalBitmap *X11SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
835 : {
836 0 : if( bPrinter_ && !bVirDev_ )
837 0 : return NULL;
838 :
839 0 : bool bFakeWindowBG = false;
840 :
841 : // normalize
842 0 : if( nDX < 0 )
843 : {
844 0 : nX += nDX;
845 0 : nDX = -nDX;
846 : }
847 0 : if ( nDY < 0 )
848 : {
849 0 : nY += nDY;
850 0 : nDY = -nDY;
851 : }
852 :
853 0 : if( bWindow_ && !bVirDev_ )
854 : {
855 : XWindowAttributes aAttrib;
856 :
857 0 : XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
858 0 : if( aAttrib.map_state != IsViewable )
859 0 : bFakeWindowBG = true;
860 : else
861 : {
862 0 : long nOrgDX = nDX, nOrgDY = nDY;
863 :
864 : // clip to window size
865 0 : if ( nX < 0 )
866 : {
867 0 : nDX += nX;
868 0 : nX = 0;
869 : }
870 0 : if ( nY < 0 )
871 : {
872 0 : nDY += nY;
873 0 : nY = 0;
874 : }
875 0 : if( nX + nDX > aAttrib.width )
876 0 : nDX = aAttrib.width - nX;
877 0 : if( nY + nDY > aAttrib.height )
878 0 : nDY = aAttrib.height - nY;
879 :
880 : // inside ?
881 0 : if( nDX <= 0 || nDY <= 0 )
882 : {
883 0 : bFakeWindowBG = true;
884 0 : nDX = nOrgDX;
885 0 : nDY = nOrgDY;
886 : }
887 : }
888 : }
889 :
890 0 : X11SalBitmap* pSalBitmap = new X11SalBitmap;
891 0 : sal_uInt16 nBitCount = GetBitCount();
892 :
893 0 : if( &GetDisplay()->GetColormap( m_nXScreen ) != &GetColormap() )
894 0 : nBitCount = 1;
895 :
896 0 : if( ! bFakeWindowBG )
897 0 : pSalBitmap->ImplCreateFromDrawable( GetDrawable(), m_nXScreen, nBitCount, nX, nY, nDX, nDY );
898 : else
899 0 : pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) );
900 :
901 0 : return pSalBitmap;
902 : }
903 :
904 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
905 0 : SalColor X11SalGraphics::getPixel( long nX, long nY )
906 : {
907 0 : if( bWindow_ && !bVirDev_ )
908 : {
909 : XWindowAttributes aAttrib;
910 :
911 0 : XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib );
912 0 : if( aAttrib.map_state != IsViewable )
913 : {
914 : stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" );
915 0 : return 0;
916 : }
917 : }
918 :
919 : XImage *pXImage = XGetImage( GetXDisplay(),
920 : GetDrawable(),
921 : nX, nY,
922 : 1, 1,
923 : AllPlanes,
924 0 : ZPixmap );
925 0 : if( !pXImage )
926 : {
927 : stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
928 0 : return 0;
929 : }
930 :
931 : XColor aXColor;
932 :
933 0 : aXColor.pixel = XGetPixel( pXImage, 0, 0 );
934 0 : XDestroyImage( pXImage );
935 :
936 0 : return GetColormap().GetColor( aXColor.pixel );
937 : }
938 :
939 : // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
940 0 : void X11SalGraphics::invert( long nX,
941 : long nY,
942 : long nDX,
943 : long nDY,
944 : SalInvert nFlags )
945 : {
946 : GC pGC;
947 0 : if( SAL_INVERT_50 & nFlags )
948 : {
949 0 : pGC = GetInvert50GC();
950 0 : XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
951 : }
952 : else
953 : {
954 0 : if ( SAL_INVERT_TRACKFRAME & nFlags )
955 : {
956 0 : pGC = GetTrackingGC();
957 0 : XDrawRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
958 : }
959 : else
960 : {
961 0 : pGC = GetInvertGC();
962 0 : XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY );
963 : }
964 : }
965 0 : }
966 :
967 0 : bool X11SalGraphics::supportsOperation( OutDevSupportType eType ) const
968 : {
969 0 : bool bRet = false;
970 0 : switch( eType )
971 : {
972 : case OutDevSupport_TransparentRect:
973 : case OutDevSupport_B2DDraw:
974 : {
975 0 : XRenderPeer& rPeer = XRenderPeer::GetInstance();
976 0 : const SalDisplay* pSalDisp = GetDisplay();
977 0 : const SalVisual& rSalVis = pSalDisp->GetVisual( m_nXScreen );
978 :
979 0 : Visual* pDstXVisual = rSalVis.GetVisual();
980 0 : XRenderPictFormat* pDstVisFmt = rPeer.FindVisualFormat( pDstXVisual );
981 0 : if( pDstVisFmt )
982 0 : bRet = true;
983 : }
984 0 : break;
985 0 : default: break;
986 : }
987 0 : return bRet;
988 : }
989 :
990 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|