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