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 <prex.h>
21 : #include <X11/Xproto.h>
22 : #include <postx.h>
23 :
24 : #include "gdiimpl.hxx"
25 :
26 : #include "vcl/salbtype.hxx"
27 : #include <vcl/gradient.hxx>
28 :
29 : #include "unx/salunx.h"
30 : #include "unx/saldata.hxx"
31 : #include "unx/saldisp.hxx"
32 : #include "unx/salbmp.h"
33 : #include "unx/salgdi.h"
34 : #include "unx/salframe.h"
35 : #include "unx/salvd.h"
36 : #include <unx/x11/xlimits.hxx>
37 : #include "xrender_peer.hxx"
38 :
39 : #include "outdata.hxx"
40 :
41 : #include "basegfx/polygon/b2dpolygon.hxx"
42 : #include "basegfx/polygon/b2dpolypolygon.hxx"
43 : #include "basegfx/polygon/b2dpolypolygontools.hxx"
44 : #include "basegfx/polygon/b2dpolygontools.hxx"
45 : #include "basegfx/polygon/b2dpolygonclipper.hxx"
46 : #include "basegfx/polygon/b2dlinegeometry.hxx"
47 : #include "basegfx/matrix/b2dhommatrix.hxx"
48 : #include "basegfx/matrix/b2dhommatrixtools.hxx"
49 : #include "basegfx/polygon/b2dpolypolygoncutter.hxx"
50 : #include "basegfx/polygon/b2dtrapezoid.hxx"
51 :
52 : #undef SALGDI2_TESTTRANS
53 :
54 : #if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
55 : #define DBG_TESTTRANS( _def_drawable ) \
56 : { \
57 : XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \
58 : 0, 0, \
59 : rPosAry.mnDestWidth, rPosAry.mnDestHeight, \
60 : 0, 0 ); \
61 : }
62 : #else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
63 : #define DBG_TESTTRANS( _def_drawable )
64 : #endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS
65 :
66 : #define STATIC_POINTS 64
67 :
68 : class SalPolyLine
69 : {
70 : XPoint Points_[STATIC_POINTS];
71 : XPoint *pFirst_;
72 : public:
73 2 : SalPolyLine(sal_uLong nPoints, const SalPoint *p)
74 2 : : pFirst_(nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_)
75 : {
76 12 : for( sal_uLong i = 0; i < nPoints; i++ )
77 : {
78 10 : pFirst_[i].x = (short)p[i].mnX;
79 10 : pFirst_[i].y = (short)p[i].mnY;
80 : }
81 2 : pFirst_[nPoints] = pFirst_[0]; // close polyline
82 2 : }
83 :
84 2 : ~SalPolyLine()
85 : {
86 2 : if( pFirst_ != Points_ )
87 0 : delete [] pFirst_;
88 2 : }
89 :
90 2 : XPoint &operator [] ( sal_uLong n ) const
91 : {
92 2 : return pFirst_[n];
93 : }
94 : };
95 :
96 : #undef STATIC_POINTS
97 :
98 : namespace
99 : {
100 0 : void setForeBack(XGCValues& rValues, const SalColormap& rColMap, const SalBitmap& rSalBitmap)
101 : {
102 0 : rValues.foreground = rColMap.GetWhitePixel();
103 0 : rValues.background = rColMap.GetBlackPixel();
104 :
105 : //fdo#33455 and fdo#80160 handle 1 bit depth pngs with palette entries
106 : //to set fore/back colors
107 0 : SalBitmap& rBitmap = const_cast<SalBitmap&>(rSalBitmap);
108 0 : if (BitmapBuffer* pBitmapBuffer = rBitmap.AcquireBuffer(BITMAP_READ_ACCESS))
109 : {
110 0 : const BitmapPalette& rPalette = pBitmapBuffer->maPalette;
111 0 : if (rPalette.GetEntryCount() == 2)
112 : {
113 0 : const BitmapColor aWhite(rPalette[rPalette.GetBestIndex(Color(COL_WHITE))]);
114 0 : rValues.foreground = rColMap.GetPixel(ImplColorToSal(aWhite));
115 :
116 0 : const BitmapColor aBlack(rPalette[rPalette.GetBestIndex(Color(COL_BLACK))]);
117 0 : rValues.background = rColMap.GetPixel(ImplColorToSal(aBlack));
118 : }
119 0 : rBitmap.ReleaseBuffer(pBitmapBuffer, BITMAP_READ_ACCESS);
120 : }
121 0 : }
122 : }
123 :
124 208 : X11SalGraphicsImpl::X11SalGraphicsImpl(X11SalGraphics& rParent):
125 : mrParent(rParent),
126 : mnBrushColor( MAKE_SALCOLOR( 0xFF, 0xFF, 0XFF ) ),
127 : mpBrushGC(NULL),
128 : mnBrushPixel(0),
129 : mbPenGC(false),
130 : mbBrushGC(false),
131 : mbMonoGC(false),
132 : mbCopyGC(false),
133 : mbInvertGC(false),
134 : mbInvert50GC(false),
135 : mbStippleGC(false),
136 : mbTrackingGC(false),
137 : mbDitherBrush(false),
138 : mbXORMode(false),
139 : mpPenGC(NULL),
140 : mnPenColor( MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) ),
141 : mnPenPixel(0),
142 : mpMonoGC(NULL),
143 : mpCopyGC(NULL),
144 : mpMaskGC(NULL),
145 : mpInvertGC(NULL),
146 : mpInvert50GC(NULL),
147 : mpStippleGC(NULL),
148 208 : mpTrackingGC(NULL)
149 : {
150 208 : }
151 :
152 392 : X11SalGraphicsImpl::~X11SalGraphicsImpl()
153 : {
154 392 : }
155 :
156 388 : void X11SalGraphicsImpl::Init()
157 : {
158 388 : mnPenPixel = mrParent.GetPixel( mnPenColor );
159 388 : mnBrushPixel = mrParent.GetPixel( mnBrushColor );
160 388 : }
161 :
162 0 : bool X11SalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY )
163 : {
164 : //TODO lfrb: don't hardcode the depth
165 0 : Display* pDpy = mrParent.GetXDisplay();
166 0 : GC aTmpGC = XCreateGC( pDpy, pPixmap->GetPixmap(), 0, NULL );
167 :
168 0 : if( !aTmpGC )
169 : {
170 : SAL_WARN( "vcl", "Could not create GC from screen" );
171 0 : return false;
172 : }
173 :
174 : // Copy the background of the screen into a composite pixmap
175 : X11SalGraphics::CopyScreenArea( mrParent.GetXDisplay(),
176 : mrParent.GetDrawable(), mrParent.GetScreenNumber(),
177 0 : mrParent.GetVisual().GetDepth(),
178 0 : pPixmap->GetDrawable(), pPixmap->GetScreen(),
179 0 : pPixmap->GetDepth(),
180 : aTmpGC,
181 0 : nX, nY, pPixmap->GetWidth(), pPixmap->GetHeight(),
182 0 : 0, 0 );
183 :
184 0 : XFreeGC( pDpy, aTmpGC );
185 0 : return true;
186 : }
187 :
188 0 : bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*Mask*/, int nX, int nY )
189 : {
190 : // TODO: lfrb: Use the mask
191 0 : GC aFontGC = mrParent.GetFontGC();
192 :
193 : // The GC can't be null, otherwise we'd have no clip region
194 0 : if( aFontGC == NULL )
195 : {
196 : SAL_WARN( "vcl", "no valid GC to render pixmap" );
197 0 : return false;
198 : }
199 :
200 0 : if( !pPixmap )
201 0 : return false;
202 :
203 : X11SalGraphics::CopyScreenArea( mrParent.GetXDisplay(),
204 0 : pPixmap->GetDrawable(), pPixmap->GetScreen(),
205 0 : pPixmap->GetDepth(),
206 : mrParent.GetDrawable(), mrParent.m_nXScreen,
207 0 : mrParent.GetVisual().GetDepth(),
208 : aFontGC,
209 : 0, 0,
210 0 : pPixmap->GetWidth(), pPixmap->GetHeight(),
211 0 : nX, nY );
212 0 : return true;
213 : }
214 :
215 0 : XID X11SalGraphicsImpl::GetXRenderPicture()
216 : {
217 0 : XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
218 :
219 0 : if( !mrParent.m_aXRenderPicture )
220 : {
221 : // check xrender support for matching visual
222 0 : XRenderPictFormat* pXRenderFormat = mrParent.GetXRenderFormat();
223 0 : if( !pXRenderFormat )
224 0 : return 0;
225 : // get the matching xrender target for drawable
226 0 : mrParent.m_aXRenderPicture = rRenderPeer.CreatePicture( mrParent.hDrawable_, pXRenderFormat, 0, NULL );
227 : }
228 :
229 : {
230 : // reset clip region
231 : // TODO: avoid clip reset if already done
232 : XRenderPictureAttributes aAttr;
233 0 : aAttr.clip_mask = None;
234 0 : rRenderPeer.ChangePicture( mrParent.m_aXRenderPicture, CPClipMask, &aAttr );
235 : }
236 :
237 0 : return mrParent.m_aXRenderPicture;
238 : }
239 :
240 196 : void X11SalGraphicsImpl::freeResources()
241 : {
242 196 : Display *pDisplay = mrParent.GetXDisplay();
243 :
244 196 : if( mpPenGC ) XFreeGC( pDisplay, mpPenGC ), mpPenGC = None;
245 196 : if( mpBrushGC ) XFreeGC( pDisplay, mpBrushGC ), mpBrushGC = None;
246 196 : if( mpMonoGC ) XFreeGC( pDisplay, mpMonoGC ), mpMonoGC = None;
247 196 : if( mpTrackingGC ) XFreeGC( pDisplay, mpTrackingGC ), mpTrackingGC = None;
248 196 : if( mpCopyGC ) XFreeGC( pDisplay, mpCopyGC ), mpCopyGC = None;
249 196 : if( mpMaskGC ) XFreeGC( pDisplay, mpMaskGC ), mpMaskGC = None;
250 196 : if( mpInvertGC ) XFreeGC( pDisplay, mpInvertGC ), mpInvertGC = None;
251 196 : if( mpInvert50GC ) XFreeGC( pDisplay, mpInvert50GC ), mpInvert50GC = None;
252 196 : if( mpStippleGC ) XFreeGC( pDisplay, mpStippleGC ), mpStippleGC = None;
253 196 : mbTrackingGC = mbPenGC = mbBrushGC = mbMonoGC = mbCopyGC = mbInvertGC = mbInvert50GC = mbStippleGC = false;
254 196 : }
255 :
256 2 : GC X11SalGraphicsImpl::CreateGC( Drawable hDrawable, unsigned long nMask )
257 : {
258 : XGCValues values;
259 :
260 2 : values.graphics_exposures = False;
261 2 : values.foreground = mrParent.m_pColormap->GetBlackPixel()
262 2 : ^ mrParent.m_pColormap->GetWhitePixel();
263 2 : values.function = GXxor;
264 2 : values.line_width = 1;
265 2 : values.fill_style = FillStippled;
266 2 : values.stipple = mrParent.GetDisplay()->GetInvert50( mrParent.m_nXScreen );
267 2 : values.subwindow_mode = ClipByChildren;
268 :
269 2 : return XCreateGC( mrParent.GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values );
270 : }
271 :
272 2 : inline GC X11SalGraphicsImpl::GetCopyGC()
273 : {
274 2 : if( mbXORMode ) return GetInvertGC();
275 :
276 2 : if( !mpCopyGC )
277 2 : mpCopyGC = CreateGC( mrParent.GetDrawable() );
278 :
279 2 : if( !mbCopyGC )
280 : {
281 2 : mrParent.SetClipRegion( mpCopyGC );
282 2 : mbCopyGC = true;
283 : }
284 2 : return mpCopyGC;
285 : }
286 :
287 0 : GC X11SalGraphicsImpl::GetTrackingGC()
288 : {
289 0 : const char dash_list[2] = {2, 2};
290 :
291 0 : if( !mpTrackingGC )
292 : {
293 : XGCValues values;
294 :
295 0 : values.graphics_exposures = False;
296 0 : values.foreground = mrParent.m_pColormap->GetBlackPixel()
297 0 : ^ mrParent.m_pColormap->GetWhitePixel();
298 0 : values.function = GXxor;
299 0 : values.line_width = 1;
300 0 : values.line_style = LineOnOffDash;
301 :
302 : mpTrackingGC = XCreateGC( mrParent.GetXDisplay(), mrParent.GetDrawable(),
303 : GCGraphicsExposures | GCForeground | GCFunction
304 : | GCLineWidth | GCLineStyle,
305 0 : &values );
306 0 : XSetDashes( mrParent.GetXDisplay(), mpTrackingGC, 0, dash_list, 2 );
307 : }
308 :
309 0 : if( !mbTrackingGC )
310 : {
311 0 : mrParent.SetClipRegion( mpTrackingGC );
312 0 : mbTrackingGC = true;
313 : }
314 :
315 0 : return mpTrackingGC;
316 : }
317 :
318 : inline GC X11SalGraphicsImpl::GetMonoGC( Pixmap hPixmap )
319 : {
320 : if( !mpMonoGC )
321 : mpMonoGC = CreateGC( hPixmap );
322 :
323 : if( !mbMonoGC )
324 : {
325 : mrParent.SetClipRegion( mpMonoGC );
326 : mbMonoGC = true;
327 : }
328 :
329 : return mpMonoGC;
330 : }
331 :
332 0 : GC X11SalGraphicsImpl::GetInvertGC()
333 : {
334 0 : if( !mpInvertGC )
335 : mpInvertGC = CreateGC( mrParent.GetDrawable(),
336 : GCGraphicsExposures
337 : | GCForeground
338 : | GCFunction
339 0 : | GCLineWidth );
340 :
341 0 : if( !mbInvertGC )
342 : {
343 0 : mrParent.SetClipRegion( mpInvertGC );
344 0 : mbInvertGC = true;
345 : }
346 0 : return mpInvertGC;
347 : }
348 :
349 0 : GC X11SalGraphicsImpl::GetInvert50GC()
350 : {
351 0 : if( !mpInvert50GC )
352 : {
353 : XGCValues values;
354 :
355 0 : values.graphics_exposures = False;
356 0 : values.foreground = mrParent.m_pColormap->GetWhitePixel();
357 0 : values.background = mrParent.m_pColormap->GetBlackPixel();
358 0 : values.function = GXinvert;
359 0 : values.line_width = 1;
360 0 : values.line_style = LineSolid;
361 : unsigned long nValueMask =
362 : GCGraphicsExposures
363 : | GCForeground
364 : | GCBackground
365 : | GCFunction
366 : | GCLineWidth
367 : | GCLineStyle
368 : | GCFillStyle
369 0 : | GCStipple;
370 :
371 0 : char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" );
372 0 : if( pEnv && ! strcasecmp( pEnv, "true" ) )
373 : {
374 0 : values.fill_style = FillSolid;
375 0 : nValueMask &= ~ GCStipple;
376 : }
377 : else
378 : {
379 0 : values.fill_style = FillStippled;
380 0 : values.stipple = mrParent.GetDisplay()->GetInvert50( mrParent.m_nXScreen );
381 : }
382 :
383 : mpInvert50GC = XCreateGC( mrParent.GetXDisplay(), mrParent.GetDrawable(),
384 : nValueMask,
385 0 : &values );
386 : }
387 :
388 0 : if( !mbInvert50GC )
389 : {
390 0 : mrParent.SetClipRegion( mpInvert50GC );
391 0 : mbInvert50GC = true;
392 : }
393 0 : return mpInvert50GC;
394 : }
395 :
396 0 : inline GC X11SalGraphicsImpl::GetStippleGC()
397 : {
398 0 : if( !mpStippleGC )
399 : mpStippleGC = CreateGC( mrParent.GetDrawable(),
400 : GCGraphicsExposures
401 : | GCFillStyle
402 0 : | GCLineWidth );
403 :
404 0 : if( !mbStippleGC )
405 : {
406 0 : XSetFunction( mrParent.GetXDisplay(), mpStippleGC, mbXORMode ? GXxor : GXcopy );
407 0 : mrParent.SetClipRegion( mpStippleGC );
408 0 : mbStippleGC = true;
409 : }
410 :
411 0 : return mpStippleGC;
412 : }
413 :
414 182 : GC X11SalGraphicsImpl::SelectBrush()
415 : {
416 182 : Display *pDisplay = mrParent.GetXDisplay();
417 :
418 : DBG_ASSERT( mnBrushColor != SALCOLOR_NONE, "Brush Transparent" );
419 :
420 182 : if( !mpBrushGC )
421 : {
422 : XGCValues values;
423 177 : values.subwindow_mode = ClipByChildren;
424 177 : values.fill_rule = EvenOddRule; // Pict import/ Gradient
425 177 : values.graphics_exposures = False;
426 :
427 : mpBrushGC = XCreateGC( pDisplay, mrParent.hDrawable_,
428 : GCSubwindowMode | GCFillRule | GCGraphicsExposures,
429 177 : &values );
430 : }
431 :
432 182 : if( !mbBrushGC )
433 : {
434 179 : if( !mbDitherBrush )
435 : {
436 179 : XSetFillStyle ( pDisplay, mpBrushGC, FillSolid );
437 179 : XSetForeground( pDisplay, mpBrushGC, mnBrushPixel );
438 179 : if( mrParent.bPrinter_ )
439 0 : XSetTile( pDisplay, mpBrushGC, None );
440 : }
441 : else
442 : {
443 0 : XSetFillStyle ( pDisplay, mpBrushGC, FillTiled );
444 0 : XSetTile ( pDisplay, mpBrushGC, mrParent.hBrush_ );
445 : }
446 179 : XSetFunction ( pDisplay, mpBrushGC, mbXORMode ? GXxor : GXcopy );
447 179 : mrParent.SetClipRegion( mpBrushGC );
448 :
449 179 : mbBrushGC = true;
450 : }
451 :
452 182 : return mpBrushGC;
453 : }
454 :
455 0 : GC X11SalGraphicsImpl::SelectPen()
456 : {
457 0 : Display *pDisplay = mrParent.GetXDisplay();
458 :
459 0 : if( !mpPenGC )
460 : {
461 : XGCValues values;
462 0 : values.subwindow_mode = ClipByChildren;
463 0 : values.fill_rule = EvenOddRule; // Pict import/ Gradient
464 0 : values.graphics_exposures = False;
465 :
466 : mpPenGC = XCreateGC( pDisplay, mrParent.hDrawable_,
467 : GCSubwindowMode | GCFillRule | GCGraphicsExposures,
468 0 : &values );
469 : }
470 :
471 0 : if( !mbPenGC )
472 : {
473 0 : if( mnPenColor != SALCOLOR_NONE )
474 0 : XSetForeground( pDisplay, mpPenGC, mnPenPixel );
475 0 : XSetFunction ( pDisplay, mpPenGC, mbXORMode ? GXxor : GXcopy );
476 0 : mrParent.SetClipRegion( mpPenGC );
477 0 : mbPenGC = true;
478 : }
479 :
480 0 : return mpPenGC;
481 : }
482 :
483 0 : void X11SalGraphicsImpl::DrawLines( sal_uLong nPoints,
484 : const SalPolyLine &rPoints,
485 : GC pGC,
486 : bool bClose
487 : )
488 : {
489 : // calculate how many lines XWindow can draw in one go
490 0 : sal_uLong nMaxLines = (mrParent.GetDisplay()->GetMaxRequestSize() - sizeof(xPolyPointReq))
491 0 : / sizeof(xPoint);
492 0 : if( nMaxLines > nPoints ) nMaxLines = nPoints;
493 :
494 : // print all lines that XWindows can draw
495 : sal_uLong n;
496 0 : for( n = 0; nPoints - n > nMaxLines; n += nMaxLines - 1 )
497 : XDrawLines( mrParent.GetXDisplay(),
498 : mrParent.GetDrawable(),
499 : pGC,
500 0 : &rPoints[n],
501 : nMaxLines,
502 0 : CoordModeOrigin );
503 :
504 0 : if( n < nPoints )
505 : XDrawLines( mrParent.GetXDisplay(),
506 : mrParent.GetDrawable(),
507 : pGC,
508 0 : &rPoints[n],
509 : nPoints - n,
510 0 : CoordModeOrigin );
511 0 : if( bClose )
512 : {
513 0 : if( rPoints[nPoints-1].x != rPoints[0].x || rPoints[nPoints-1].y != rPoints[0].y )
514 0 : drawLine( rPoints[nPoints-1].x, rPoints[nPoints-1].y, rPoints[0].x, rPoints[0].y );
515 : }
516 0 : }
517 :
518 0 : void X11SalGraphicsImpl::copyBits( const SalTwoRect& rPosAry,
519 : SalGraphics *pSSrcGraphics )
520 : {
521 : X11SalGraphics* pSrcGraphics = pSSrcGraphics
522 : ? static_cast<X11SalGraphics*>(pSSrcGraphics)
523 0 : : &mrParent;
524 :
525 0 : if( rPosAry.mnSrcWidth <= 0
526 0 : || rPosAry.mnSrcHeight <= 0
527 0 : || rPosAry.mnDestWidth <= 0
528 0 : || rPosAry.mnDestHeight <= 0 )
529 : {
530 0 : return;
531 : }
532 :
533 : int n;
534 0 : if( pSrcGraphics == &mrParent )
535 : {
536 0 : n = 2;
537 : }
538 0 : else if( pSrcGraphics->bWindow_ )
539 : {
540 : // window or compatible virtual device
541 0 : if( pSrcGraphics->GetDisplay() == mrParent.GetDisplay() &&
542 0 : pSrcGraphics->m_nXScreen == mrParent.m_nXScreen &&
543 0 : pSrcGraphics->GetVisual().GetDepth() == mrParent.GetVisual().GetDepth()
544 : )
545 0 : n = 2; // same Display
546 : else
547 0 : n = 1; // printer or other display
548 : }
549 0 : else if( pSrcGraphics->bVirDev_ )
550 : {
551 : // printer compatible virtual device
552 0 : if( mrParent.bPrinter_ )
553 0 : n = 2; // printer or compatible virtual device == same display
554 : else
555 0 : n = 1; // window or compatible virtual device
556 : }
557 : else
558 0 : n = 0;
559 :
560 0 : if( n == 2
561 0 : && rPosAry.mnSrcWidth == rPosAry.mnDestWidth
562 0 : && rPosAry.mnSrcHeight == rPosAry.mnDestHeight
563 : )
564 : {
565 : // #i60699# Need to generate graphics exposures (to repaint
566 : // obscured areas beneath overlapping windows), src and dest
567 : // are the same window.
568 0 : const bool bNeedGraphicsExposures( pSrcGraphics == &mrParent &&
569 0 : !mrParent.bVirDev_ &&
570 0 : pSrcGraphics->bWindow_ );
571 :
572 0 : GC pCopyGC = GetCopyGC();
573 :
574 0 : if( bNeedGraphicsExposures )
575 : XSetGraphicsExposures( mrParent.GetXDisplay(),
576 : pCopyGC,
577 0 : True );
578 :
579 : XCopyArea( mrParent.GetXDisplay(),
580 : pSrcGraphics->GetDrawable(), // source
581 : mrParent.GetDrawable(), // destination
582 : pCopyGC, // destination clipping
583 : rPosAry.mnSrcX, rPosAry.mnSrcY,
584 : rPosAry.mnSrcWidth, rPosAry.mnSrcHeight,
585 0 : rPosAry.mnDestX, rPosAry.mnDestY );
586 :
587 0 : if( bNeedGraphicsExposures )
588 : {
589 0 : mrParent.YieldGraphicsExpose();
590 :
591 0 : if( pCopyGC )
592 : XSetGraphicsExposures( mrParent.GetXDisplay(),
593 : pCopyGC,
594 0 : False );
595 0 : }
596 : }
597 0 : else if( n )
598 : {
599 : // #i60699# No chance to handle graphics exposures - we copy
600 : // to a temp bitmap first, into which no repaints are
601 : // technically possible.
602 : std::unique_ptr<SalBitmap> xDDB(pSrcGraphics->getBitmap( rPosAry.mnSrcX,
603 : rPosAry.mnSrcY,
604 : rPosAry.mnSrcWidth,
605 0 : rPosAry.mnSrcHeight ));
606 :
607 0 : if( !xDDB )
608 : {
609 : stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" );
610 0 : return;
611 : }
612 :
613 0 : SalTwoRect aPosAry( rPosAry );
614 :
615 0 : aPosAry.mnSrcX = 0, aPosAry.mnSrcY = 0;
616 0 : drawBitmap( aPosAry, *xDDB );
617 : }
618 : else {
619 : stderr0( "X11SalGraphicsImpl::CopyBits from Printer not yet implemented\n" );
620 : }
621 : }
622 :
623 0 : void X11SalGraphicsImpl::copyArea ( long nDestX, long nDestY,
624 : long nSrcX, long nSrcY,
625 : long nSrcWidth, long nSrcHeight,
626 : sal_uInt16 )
627 : {
628 0 : SalTwoRect aPosAry(nSrcX, nSrcY, nSrcWidth, nSrcHeight, nDestX, nDestY, nSrcWidth, nSrcHeight);
629 0 : copyBits(aPosAry, 0);
630 0 : }
631 :
632 2 : void X11SalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
633 : {
634 2 : const SalDisplay* pSalDisp = mrParent.GetDisplay();
635 2 : Display* pXDisp = pSalDisp->GetDisplay();
636 2 : const Drawable aDrawable( mrParent.GetDrawable() );
637 2 : const SalColormap& rColMap = pSalDisp->GetColormap( mrParent.m_nXScreen );
638 2 : const long nDepth = mrParent.GetDisplay()->GetVisual( mrParent.m_nXScreen ).GetDepth();
639 2 : GC aGC( GetCopyGC() );
640 : XGCValues aOldVal, aNewVal;
641 2 : int nValues = GCForeground | GCBackground;
642 :
643 2 : if( rSalBitmap.GetBitCount() == 1 )
644 : {
645 : // set foreground/background values for 1Bit bitmaps
646 0 : XGetGCValues( pXDisp, aGC, nValues, &aOldVal );
647 0 : setForeBack(aNewVal, rColMap, rSalBitmap);
648 0 : XChangeGC( pXDisp, aGC, nValues, &aNewVal );
649 : }
650 :
651 2 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, mrParent.m_nXScreen, nDepth, rPosAry, aGC );
652 :
653 2 : if( rSalBitmap.GetBitCount() == 1 )
654 0 : XChangeGC( pXDisp, aGC, nValues, &aOldVal );
655 2 : XFlush( pXDisp );
656 2 : }
657 :
658 0 : void X11SalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry,
659 : const SalBitmap& rSrcBitmap,
660 : const SalBitmap& rMaskBitmap )
661 : {
662 : DBG_ASSERT( !mrParent.bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" );
663 :
664 : // decide if alpha masking or transparency masking is needed
665 0 : BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( BITMAP_READ_ACCESS );
666 0 : if( pAlphaBuffer != NULL )
667 : {
668 0 : int nMaskFormat = pAlphaBuffer->mnFormat;
669 0 : const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, BITMAP_READ_ACCESS );
670 0 : if( nMaskFormat == BMP_FORMAT_8BIT_PAL )
671 0 : drawAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap );
672 : }
673 :
674 0 : drawMaskedBitmap( rPosAry, rSrcBitmap, rMaskBitmap );
675 0 : }
676 :
677 0 : void X11SalGraphicsImpl::drawMaskedBitmap( const SalTwoRect& rPosAry,
678 : const SalBitmap& rSalBitmap,
679 : const SalBitmap& rTransBitmap )
680 : {
681 0 : const SalDisplay* pSalDisp = mrParent.GetDisplay();
682 0 : Display* pXDisp = pSalDisp->GetDisplay();
683 0 : Drawable aDrawable( mrParent.GetDrawable() );
684 :
685 : // figure work mode depth. If this is a VDev Drawable, use its
686 : // bitdepth to create pixmaps for, otherwise, XCopyArea will
687 : // refuse to work.
688 : const sal_uInt16 nDepth( mrParent.m_pVDev ?
689 0 : static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() :
690 0 : pSalDisp->GetVisual( mrParent.m_nXScreen ).GetDepth() );
691 : Pixmap aFG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth,
692 0 : rPosAry.mnDestHeight, nDepth ) );
693 : Pixmap aBG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth,
694 0 : rPosAry.mnDestHeight, nDepth ) );
695 :
696 0 : if( aFG && aBG )
697 : {
698 : GC aTmpGC;
699 : XGCValues aValues;
700 0 : setForeBack(aValues, pSalDisp->GetColormap(mrParent.m_nXScreen), rSalBitmap);
701 0 : const int nValues = GCFunction | GCForeground | GCBackground;
702 0 : SalTwoRect aTmpRect( rPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0;
703 :
704 : // draw paint bitmap in pixmap #1
705 0 : aValues.function = GXcopy;
706 0 : aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues );
707 0 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, mrParent.m_nXScreen, nDepth, aTmpRect, aTmpGC );
708 : DBG_TESTTRANS( aFG );
709 :
710 : // draw background in pixmap #2
711 : XCopyArea( pXDisp, aDrawable, aBG, aTmpGC,
712 : rPosAry.mnDestX, rPosAry.mnDestY,
713 : rPosAry.mnDestWidth, rPosAry.mnDestHeight,
714 0 : 0, 0 );
715 :
716 : DBG_TESTTRANS( aBG );
717 :
718 : // mask out paint bitmap in pixmap #1 (transparent areas 0)
719 0 : aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff;
720 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
721 0 : static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, mrParent.m_nXScreen, 1, aTmpRect, aTmpGC );
722 :
723 : DBG_TESTTRANS( aFG );
724 :
725 : // #105055# For XOR mode, keep background behind bitmap intact
726 0 : if( !mbXORMode )
727 : {
728 : // mask out background in pixmap #2 (nontransparent areas 0)
729 0 : aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
730 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
731 0 : static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, mrParent.m_nXScreen, 1, aTmpRect, aTmpGC );
732 :
733 : DBG_TESTTRANS( aBG );
734 : }
735 :
736 : // merge pixmap #1 and pixmap #2 in pixmap #2
737 0 : aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000;
738 0 : XChangeGC( pXDisp, aTmpGC, nValues, &aValues );
739 : XCopyArea( pXDisp, aFG, aBG, aTmpGC,
740 : 0, 0,
741 : rPosAry.mnDestWidth, rPosAry.mnDestHeight,
742 0 : 0, 0 );
743 : DBG_TESTTRANS( aBG );
744 :
745 : // #105055# Disable XOR temporarily
746 0 : bool bOldXORMode( mbXORMode );
747 0 : mbXORMode = false;
748 :
749 : // copy pixmap #2 (result) to background
750 : XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(),
751 : 0, 0,
752 : rPosAry.mnDestWidth, rPosAry.mnDestHeight,
753 0 : rPosAry.mnDestX, rPosAry.mnDestY );
754 :
755 : DBG_TESTTRANS( aBG );
756 :
757 0 : mbXORMode = bOldXORMode;
758 :
759 0 : XFreeGC( pXDisp, aTmpGC );
760 0 : XFlush( pXDisp );
761 : }
762 : else
763 0 : drawBitmap( rPosAry, rSalBitmap );
764 :
765 0 : if( aFG )
766 0 : XFreePixmap( pXDisp, aFG );
767 :
768 0 : if( aBG )
769 0 : XFreePixmap( pXDisp, aBG );
770 0 : }
771 :
772 0 : bool X11SalGraphicsImpl::blendBitmap( const SalTwoRect&,
773 : const SalBitmap& )
774 : {
775 0 : return false;
776 : }
777 :
778 0 : bool X11SalGraphicsImpl::blendAlphaBitmap( const SalTwoRect&,
779 : const SalBitmap&, const SalBitmap&, const SalBitmap& )
780 : {
781 0 : return false;
782 : }
783 :
784 2 : bool X11SalGraphicsImpl::drawAlphaBitmap( const SalTwoRect& rTR,
785 : const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp )
786 : {
787 : // non 8-bit alpha not implemented yet
788 2 : if( rAlphaBmp.GetBitCount() != 8 )
789 0 : return false;
790 :
791 : // horizontal mirroring not implemented yet
792 2 : if( rTR.mnDestWidth < 0 )
793 0 : return false;
794 :
795 : // stretched conversion is not implemented yet
796 2 : if( rTR.mnDestWidth != rTR.mnSrcWidth )
797 2 : return false;
798 0 : if( rTR.mnDestHeight!= rTR.mnSrcHeight )
799 0 : return false;
800 :
801 : // create destination picture
802 0 : Picture aDstPic = GetXRenderPicture();
803 0 : if( !aDstPic )
804 0 : return false;
805 :
806 0 : const SalDisplay* pSalDisp = mrParent.GetDisplay();
807 0 : const SalVisual& rSalVis = pSalDisp->GetVisual( mrParent.m_nXScreen );
808 0 : Display* pXDisplay = pSalDisp->GetDisplay();
809 :
810 : // create source Picture
811 0 : int nDepth = mrParent.m_pVDev ? static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() : rSalVis.GetDepth();
812 0 : const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap );
813 0 : ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( mrParent.hDrawable_, mrParent.m_nXScreen, nDepth, rTR );
814 0 : if( !pSrcDDB )
815 0 : return false;
816 :
817 : //#i75249# workaround for ImplGetDDB() giving us back a different depth than
818 : // we requested. E.g. mask pixmaps are always compatible with the drawable
819 : // TODO: find an appropriate picture format for these cases
820 : // then remove the workaround below and the one for #i75531#
821 0 : if( nDepth != pSrcDDB->ImplGetDepth() )
822 0 : return false;
823 :
824 0 : Pixmap aSrcPM = pSrcDDB->ImplGetPixmap();
825 0 : if( !aSrcPM )
826 0 : return false;
827 :
828 : // create source picture
829 : // TODO: use scoped picture
830 0 : Visual* pSrcXVisual = rSalVis.GetVisual();
831 0 : XRenderPeer& rPeer = XRenderPeer::GetInstance();
832 0 : XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual );
833 0 : if( !pSrcVisFmt )
834 0 : return false;
835 0 : Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL );
836 0 : if( !aSrcPic )
837 0 : return false;
838 :
839 : // create alpha Picture
840 :
841 : // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap
842 : // problem is that they don't provide an 8bit Pixmap on a non-8bit display
843 0 : BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( BITMAP_READ_ACCESS );
844 :
845 : // an XImage needs its data top_down
846 : // TODO: avoid wrongly oriented images in upper layers!
847 0 : const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize;
848 0 : const char* pSrcBits = reinterpret_cast<char*>(pAlphaBuffer->mpBits);
849 0 : char* pAlphaBits = new char[ nImageSize ];
850 0 : if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
851 0 : memcpy( pAlphaBits, pSrcBits, nImageSize );
852 : else
853 : {
854 0 : char* pDstBits = pAlphaBits + nImageSize;
855 0 : const int nLineSize = pAlphaBuffer->mnScanlineSize;
856 0 : for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize )
857 0 : memcpy( pDstBits, pSrcBits, nLineSize );
858 : }
859 :
860 : // the alpha values need to be inverted for XRender
861 : // TODO: make upper layers use standard alpha
862 0 : long* pLDst = reinterpret_cast<long*>(pAlphaBits);
863 0 : for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst )
864 0 : *pLDst = ~*pLDst;
865 :
866 0 : char* pCDst = reinterpret_cast<char*>(pLDst);
867 0 : for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst )
868 0 : *pCDst = ~*pCDst;
869 :
870 0 : const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8();
871 : XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0,
872 : pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
873 0 : pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
874 :
875 : Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_,
876 0 : rTR.mnDestWidth, rTR.mnDestHeight, 8 );
877 :
878 : XGCValues aAlphaGCV;
879 0 : aAlphaGCV.function = GXcopy;
880 0 : GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV );
881 : XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg,
882 0 : rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight );
883 0 : XFreeGC( pXDisplay, aAlphaGC );
884 0 : XFree( pAlphaImg );
885 0 : if( pAlphaBits != reinterpret_cast<char*>(pAlphaBuffer->mpBits) )
886 0 : delete[] pAlphaBits;
887 :
888 0 : const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, BITMAP_READ_ACCESS );
889 :
890 : XRenderPictureAttributes aAttr;
891 0 : aAttr.repeat = int(true);
892 0 : Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr );
893 0 : if( !aAlphaPic )
894 0 : return false;
895 :
896 : // set clipping
897 0 : if( mrParent.mpClipRegion && !XEmptyRegion( mrParent.mpClipRegion ) )
898 0 : rPeer.SetPictureClipRegion( aDstPic, mrParent.mpClipRegion );
899 :
900 : // paint source * mask over destination picture
901 : rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic,
902 : rTR.mnSrcX, rTR.mnSrcY, 0, 0,
903 0 : rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight );
904 :
905 0 : rPeer.FreePicture( aAlphaPic );
906 0 : XFreePixmap(pXDisplay, aAlphaPM);
907 0 : rPeer.FreePicture( aSrcPic );
908 0 : return true;
909 : }
910 :
911 0 : bool X11SalGraphicsImpl::drawTransformedBitmap(
912 : const basegfx::B2DPoint& rNull,
913 : const basegfx::B2DPoint& rX,
914 : const basegfx::B2DPoint& rY,
915 : const SalBitmap& rSourceBitmap,
916 : const SalBitmap* pAlphaBitmap)
917 : {
918 : // here direct support for transformed bitmaps can be implemented
919 : (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap;
920 0 : return false;
921 : }
922 :
923 0 : bool X11SalGraphicsImpl::drawAlphaRect( long nX, long nY, long nWidth,
924 : long nHeight, sal_uInt8 nTransparency )
925 : {
926 0 : if( ! mrParent.m_pFrame && ! mrParent.m_pVDev )
927 0 : return false;
928 :
929 0 : if( mbPenGC || !mbBrushGC || mbXORMode )
930 0 : return false; // can only perform solid fills without XOR.
931 :
932 0 : if( mrParent.m_pVDev && static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetDepth() < 8 )
933 0 : return false;
934 :
935 0 : Picture aDstPic = GetXRenderPicture();
936 0 : if( !aDstPic )
937 0 : return false;
938 :
939 0 : const double fTransparency = (100 - nTransparency) * (1.0/100);
940 0 : const XRenderColor aRenderColor = GetXRenderColor( mnBrushColor , fTransparency);
941 :
942 0 : XRenderPeer& rPeer = XRenderPeer::GetInstance();
943 : rPeer.FillRectangle( PictOpOver,
944 : aDstPic,
945 : &aRenderColor,
946 : nX, nY,
947 0 : nWidth, nHeight );
948 :
949 0 : return true;
950 : }
951 :
952 0 : void X11SalGraphicsImpl::drawBitmap( const SalTwoRect&,
953 : const SalBitmap&,
954 : SalColor )
955 : {
956 : OSL_FAIL( "::DrawBitmap with transparent color not supported" );
957 0 : }
958 :
959 0 : void X11SalGraphicsImpl::drawMask( const SalTwoRect& rPosAry,
960 : const SalBitmap &rSalBitmap,
961 : SalColor nMaskColor )
962 : {
963 0 : const SalDisplay* pSalDisp = mrParent.GetDisplay();
964 0 : Display* pXDisp = pSalDisp->GetDisplay();
965 0 : Drawable aDrawable( mrParent.GetDrawable() );
966 : Pixmap aStipple( limitXCreatePixmap( pXDisp, aDrawable,
967 : rPosAry.mnDestWidth,
968 0 : rPosAry.mnDestHeight, 1 ) );
969 :
970 0 : if( aStipple )
971 : {
972 0 : SalTwoRect aTwoRect( rPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
973 : GC aTmpGC;
974 : XGCValues aValues;
975 :
976 : // create a stipple bitmap first (set bits are changed to unset bits and vice versa)
977 0 : aValues.function = GXcopyInverted;
978 0 : aValues.foreground = 1, aValues.background = 0;
979 0 : aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues );
980 0 : static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, mrParent.m_nXScreen, 1, aTwoRect, aTmpGC );
981 :
982 0 : XFreeGC( pXDisp, aTmpGC );
983 :
984 : // Set stipple and draw rectangle
985 0 : GC aStippleGC( GetStippleGC() );
986 0 : int nX = rPosAry.mnDestX, nY = rPosAry.mnDestY;
987 :
988 0 : XSetStipple( pXDisp, aStippleGC, aStipple );
989 0 : XSetTSOrigin( pXDisp, aStippleGC, nX, nY );
990 0 : XSetForeground( pXDisp, aStippleGC, mrParent.GetPixel( nMaskColor ) );
991 : XFillRectangle( pXDisp, aDrawable, aStippleGC,
992 : nX, nY,
993 0 : rPosAry.mnDestWidth, rPosAry.mnDestHeight );
994 0 : XFreePixmap( pXDisp, aStipple );
995 0 : XFlush( pXDisp );
996 : }
997 : else
998 0 : drawBitmap( rPosAry, rSalBitmap );
999 0 : }
1000 :
1001 0 : void X11SalGraphicsImpl::ResetClipRegion()
1002 : {
1003 0 : if( mrParent.mpClipRegion )
1004 : {
1005 0 : mbPenGC = false;
1006 0 : mrParent.bFontGC_ = false;
1007 0 : mbBrushGC = false;
1008 0 : mbMonoGC = false;
1009 0 : mbCopyGC = false;
1010 0 : mbInvertGC = false;
1011 0 : mbInvert50GC = false;
1012 0 : mbStippleGC = false;
1013 0 : mbTrackingGC = false;
1014 :
1015 0 : XDestroyRegion( mrParent.mpClipRegion );
1016 0 : mrParent.mpClipRegion = NULL;
1017 : }
1018 0 : }
1019 :
1020 3 : bool X11SalGraphicsImpl::setClipRegion( const vcl::Region& i_rClip )
1021 : {
1022 3 : if( mrParent.mpClipRegion )
1023 0 : XDestroyRegion( mrParent.mpClipRegion );
1024 3 : mrParent.mpClipRegion = XCreateRegion();
1025 :
1026 3 : RectangleVector aRectangles;
1027 3 : i_rClip.GetRegionRectangles(aRectangles);
1028 :
1029 6 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
1030 : {
1031 3 : const long nW(aRectIter->GetWidth());
1032 :
1033 3 : if(nW)
1034 : {
1035 3 : const long nH(aRectIter->GetHeight());
1036 :
1037 3 : if(nH)
1038 : {
1039 : XRectangle aRect;
1040 :
1041 3 : aRect.x = (short)aRectIter->Left();
1042 3 : aRect.y = (short)aRectIter->Top();
1043 3 : aRect.width = (unsigned short)nW;
1044 3 : aRect.height = (unsigned short)nH;
1045 3 : XUnionRectWithRegion(&aRect, mrParent.mpClipRegion, mrParent.mpClipRegion);
1046 : }
1047 : }
1048 : }
1049 :
1050 : //ImplRegionInfo aInfo;
1051 : //long nX, nY, nW, nH;
1052 : //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
1053 : //while( bRegionRect )
1054 : //{
1055 : // if ( nW && nH )
1056 : // {
1057 : // XRectangle aRect;
1058 : // aRect.x = (short)nX;
1059 : // aRect.y = (short)nY;
1060 : // aRect.width = (unsigned short)nW;
1061 : // aRect.height = (unsigned short)nH;
1062 :
1063 : // XUnionRectWithRegion( &aRect, mrParent.mpClipRegion, mrParent.mpClipRegion );
1064 : // }
1065 : // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
1066 : //}
1067 :
1068 : // done, invalidate GCs
1069 3 : mbPenGC = false;
1070 3 : mrParent.bFontGC_ = false;
1071 3 : mbBrushGC = false;
1072 3 : mbMonoGC = false;
1073 3 : mbCopyGC = false;
1074 3 : mbInvertGC = false;
1075 3 : mbInvert50GC = false;
1076 3 : mbStippleGC = false;
1077 3 : mbTrackingGC = false;
1078 :
1079 3 : if( XEmptyRegion( mrParent.mpClipRegion ) )
1080 : {
1081 0 : XDestroyRegion( mrParent.mpClipRegion );
1082 0 : mrParent.mpClipRegion= NULL;
1083 : }
1084 3 : return true;
1085 : }
1086 :
1087 182 : void X11SalGraphicsImpl::SetLineColor()
1088 : {
1089 182 : if( mnPenColor != SALCOLOR_NONE )
1090 : {
1091 177 : mnPenColor = SALCOLOR_NONE;
1092 177 : mbPenGC = false;
1093 : }
1094 182 : }
1095 :
1096 0 : void X11SalGraphicsImpl::SetLineColor( SalColor nSalColor )
1097 : {
1098 0 : if( mnPenColor != nSalColor )
1099 : {
1100 0 : mnPenColor = nSalColor;
1101 0 : mnPenPixel = mrParent.GetPixel( nSalColor );
1102 0 : mbPenGC = false;
1103 : }
1104 0 : }
1105 :
1106 0 : void X11SalGraphicsImpl::SetFillColor()
1107 : {
1108 0 : if( mnBrushColor != SALCOLOR_NONE )
1109 : {
1110 0 : mbDitherBrush = false;
1111 0 : mnBrushColor = SALCOLOR_NONE;
1112 0 : mbBrushGC = false;
1113 : }
1114 0 : }
1115 :
1116 177 : void X11SalGraphicsImpl::SetFillColor( SalColor nSalColor )
1117 : {
1118 177 : if( mnBrushColor != nSalColor )
1119 : {
1120 0 : mbDitherBrush = false;
1121 0 : mnBrushColor = nSalColor;
1122 0 : mnBrushPixel = mrParent.GetPixel( nSalColor );
1123 0 : if( TrueColor != mrParent.GetColormap().GetVisual().GetClass()
1124 0 : && mrParent.GetColormap().GetColor( mnBrushPixel ) != mnBrushColor
1125 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) // black
1126 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x80 ) // blue
1127 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x00 ) // green
1128 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x80 ) // cyan
1129 0 : && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x00 ) // red
1130 0 : && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x80 ) // magenta
1131 0 : && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x00 ) // brown
1132 0 : && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x80 ) // gray
1133 0 : && nSalColor != MAKE_SALCOLOR( 0xC0, 0xC0, 0xC0 ) // light gray
1134 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0xFF ) // light blue
1135 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0x00 ) // light green
1136 0 : && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0xFF ) // light cyan
1137 0 : && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0x00 ) // light red
1138 0 : && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0xFF ) // light magenta
1139 0 : && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0x00 ) // light brown
1140 0 : && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) )
1141 0 : mbDitherBrush = mrParent.GetDitherPixmap(nSalColor);
1142 0 : mbBrushGC = false;
1143 : }
1144 177 : }
1145 :
1146 0 : void X11SalGraphicsImpl::SetROPLineColor( SalROPColor nROPColor )
1147 : {
1148 0 : switch( nROPColor )
1149 : {
1150 : case SAL_ROP_0 : // 0
1151 0 : mnPenPixel = (Pixel)0;
1152 0 : break;
1153 : case SAL_ROP_1 : // 1
1154 0 : mnPenPixel = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1;
1155 0 : break;
1156 : case SAL_ROP_INVERT : // 2
1157 0 : mnPenPixel = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1;
1158 0 : break;
1159 : }
1160 0 : mnPenColor = mrParent.GetColormap().GetColor( mnPenPixel );
1161 0 : mbPenGC = false;
1162 0 : }
1163 :
1164 0 : void X11SalGraphicsImpl::SetROPFillColor( SalROPColor nROPColor )
1165 : {
1166 0 : switch( nROPColor )
1167 : {
1168 : case SAL_ROP_0 : // 0
1169 0 : mnBrushPixel = (Pixel)0;
1170 0 : break;
1171 : case SAL_ROP_1 : // 1
1172 0 : mnBrushPixel = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1;
1173 0 : break;
1174 : case SAL_ROP_INVERT : // 2
1175 0 : mnBrushPixel = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1;
1176 0 : break;
1177 : }
1178 0 : mbDitherBrush = false;
1179 0 : mnBrushColor = mrParent.GetColormap().GetColor( mnBrushPixel );
1180 0 : mbBrushGC = false;
1181 0 : }
1182 :
1183 1002 : void X11SalGraphicsImpl::SetXORMode( bool bSet, bool )
1184 : {
1185 1002 : if (mbXORMode != bSet)
1186 : {
1187 0 : mbXORMode = bSet;
1188 0 : mbPenGC = false;
1189 0 : mrParent.bFontGC_ = false;
1190 0 : mbBrushGC = false;
1191 0 : mbMonoGC = false;
1192 0 : mbCopyGC = false;
1193 0 : mbInvertGC = false;
1194 0 : mbInvert50GC = false;
1195 0 : mbStippleGC = false;
1196 0 : mbTrackingGC = false;
1197 : }
1198 1002 : }
1199 :
1200 0 : void X11SalGraphicsImpl::drawPixel( long nX, long nY )
1201 : {
1202 0 : if( mnPenColor != SALCOLOR_NONE )
1203 0 : XDrawPoint( mrParent.GetXDisplay(), mrParent.GetDrawable(), SelectPen(), nX, nY );
1204 0 : }
1205 :
1206 0 : void X11SalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
1207 : {
1208 0 : if( nSalColor != SALCOLOR_NONE )
1209 : {
1210 0 : Display *pDisplay = mrParent.GetXDisplay();
1211 :
1212 0 : if( (mnPenColor == SALCOLOR_NONE) && !mbPenGC )
1213 : {
1214 0 : SetLineColor( nSalColor );
1215 0 : XDrawPoint( pDisplay, mrParent.GetDrawable(), SelectPen(), nX, nY );
1216 0 : mnPenColor = SALCOLOR_NONE;
1217 0 : mbPenGC = False;
1218 : }
1219 : else
1220 : {
1221 0 : GC pGC = SelectPen();
1222 :
1223 0 : if( nSalColor != mnPenColor )
1224 0 : XSetForeground( pDisplay, pGC, mrParent.GetPixel( nSalColor ) );
1225 :
1226 0 : XDrawPoint( pDisplay, mrParent.GetDrawable(), pGC, nX, nY );
1227 :
1228 0 : if( nSalColor != mnPenColor )
1229 0 : XSetForeground( pDisplay, pGC, mnPenPixel );
1230 : }
1231 : }
1232 0 : }
1233 :
1234 0 : void X11SalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
1235 : {
1236 0 : if( mnPenColor != SALCOLOR_NONE )
1237 : {
1238 : XDrawLine( mrParent.GetXDisplay(), mrParent.GetDrawable(),SelectPen(),
1239 0 : nX1, nY1, nX2, nY2 );
1240 : }
1241 0 : }
1242 :
1243 180 : void X11SalGraphicsImpl::drawRect( long nX, long nY, long nDX, long nDY )
1244 : {
1245 180 : if( mnBrushColor != SALCOLOR_NONE )
1246 : {
1247 : XFillRectangle( mrParent.GetXDisplay(),
1248 : mrParent.GetDrawable(),
1249 : SelectBrush(),
1250 180 : nX, nY, nDX, nDY );
1251 : }
1252 : // description DrawRect is wrong; thus -1
1253 180 : if( mnPenColor != SALCOLOR_NONE )
1254 : XDrawRectangle( mrParent.GetXDisplay(),
1255 : mrParent.GetDrawable(),
1256 : SelectPen(),
1257 0 : nX, nY, nDX-1, nDY-1 );
1258 180 : }
1259 :
1260 0 : void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry )
1261 : {
1262 0 : drawPolyLine( nPoints, pPtAry, false );
1263 0 : }
1264 :
1265 0 : void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry, bool bClose )
1266 : {
1267 0 : if( mnPenColor != SALCOLOR_NONE )
1268 : {
1269 0 : SalPolyLine Points( nPoints, pPtAry );
1270 :
1271 0 : DrawLines( nPoints, Points, SelectPen(), bClose );
1272 : }
1273 0 : }
1274 :
1275 2 : void X11SalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
1276 : {
1277 2 : if( nPoints == 0 )
1278 0 : return;
1279 :
1280 2 : if( nPoints < 3 )
1281 : {
1282 0 : if( !mbXORMode )
1283 : {
1284 0 : if( 1 == nPoints )
1285 0 : drawPixel( pPtAry[0].mnX, pPtAry[0].mnY );
1286 : else
1287 : drawLine( pPtAry[0].mnX, pPtAry[0].mnY,
1288 0 : pPtAry[1].mnX, pPtAry[1].mnY );
1289 : }
1290 0 : return;
1291 : }
1292 :
1293 2 : SalPolyLine Points( nPoints, pPtAry );
1294 :
1295 2 : nPoints++;
1296 :
1297 : /* WORKAROUND: some Xservers (Xorg, VIA chipset in this case)
1298 : * do not draw the visible part of a polygon
1299 : * if it overlaps to the left of screen 0,y.
1300 : * This happens to be the case in the gradient drawn in the
1301 : * menubar background. workaround for the special case of
1302 : * of a rectangle overlapping to the left.
1303 : */
1304 2 : if( nPoints == 5 &&
1305 0 : Points[ 0 ].x == Points[ 1 ].x &&
1306 0 : Points[ 1 ].y == Points[ 2 ].y &&
1307 0 : Points[ 2 ].x == Points[ 3 ].x &&
1308 2 : Points[ 0 ].x == Points[ 4 ].x && Points[ 0 ].y == Points[ 4 ].y
1309 : )
1310 : {
1311 0 : bool bLeft = false;
1312 0 : bool bRight = false;
1313 0 : for(unsigned int i = 0; i < nPoints; i++ )
1314 : {
1315 0 : if( Points[i].x < 0 )
1316 0 : bLeft = true;
1317 : else
1318 0 : bRight= true;
1319 : }
1320 0 : if( bLeft && ! bRight )
1321 0 : return;
1322 0 : if( bLeft && bRight )
1323 : {
1324 0 : for( unsigned int i = 0; i < nPoints; i++ )
1325 0 : if( Points[i].x < 0 )
1326 0 : Points[i].x = 0;
1327 : }
1328 : }
1329 :
1330 2 : if( mnBrushColor != SALCOLOR_NONE )
1331 : XFillPolygon( mrParent.GetXDisplay(),
1332 : mrParent.GetDrawable(),
1333 : SelectBrush(),
1334 2 : &Points[0], nPoints,
1335 4 : Complex, CoordModeOrigin );
1336 :
1337 2 : if( mnPenColor != SALCOLOR_NONE )
1338 0 : DrawLines( nPoints, Points, SelectPen(), true );
1339 : }
1340 :
1341 0 : void X11SalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly,
1342 : const sal_uInt32 *pPoints,
1343 : PCONSTSALPOINT *pPtAry )
1344 : {
1345 0 : if( mnBrushColor != SALCOLOR_NONE )
1346 : {
1347 : sal_uInt32 i, n;
1348 0 : Region pXRegA = NULL;
1349 :
1350 0 : for( i = 0; i < nPoly; i++ ) {
1351 0 : n = pPoints[i];
1352 0 : SalPolyLine Points( n, pPtAry[i] );
1353 0 : if( n > 2 )
1354 : {
1355 0 : Region pXRegB = XPolygonRegion( &Points[0], n+1, WindingRule );
1356 0 : if( !pXRegA )
1357 0 : pXRegA = pXRegB;
1358 : else
1359 : {
1360 0 : XXorRegion( pXRegA, pXRegB, pXRegA );
1361 0 : XDestroyRegion( pXRegB );
1362 : }
1363 : }
1364 0 : }
1365 :
1366 0 : if( pXRegA )
1367 : {
1368 : XRectangle aXRect;
1369 0 : XClipBox( pXRegA, &aXRect );
1370 :
1371 0 : GC pGC = SelectBrush();
1372 0 : mrParent.SetClipRegion( pGC, pXRegA ); // ??? twice
1373 0 : XDestroyRegion( pXRegA );
1374 0 : mbBrushGC = false;
1375 :
1376 : XFillRectangle( mrParent.GetXDisplay(),
1377 : mrParent.GetDrawable(),
1378 : pGC,
1379 0 : aXRect.x, aXRect.y, aXRect.width, aXRect.height );
1380 : }
1381 : }
1382 :
1383 0 : if( mnPenColor != SALCOLOR_NONE )
1384 0 : for( sal_uInt32 i = 0; i < nPoly; i++ )
1385 0 : drawPolyLine( pPoints[i], pPtAry[i], true );
1386 0 : }
1387 :
1388 0 : bool X11SalGraphicsImpl::drawPolyLineBezier( sal_uInt32, const SalPoint*, const sal_uInt8* )
1389 : {
1390 0 : return false;
1391 : }
1392 :
1393 0 : bool X11SalGraphicsImpl::drawPolygonBezier( sal_uInt32, const SalPoint*, const sal_uInt8* )
1394 : {
1395 0 : return false;
1396 : }
1397 :
1398 0 : bool X11SalGraphicsImpl::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*,
1399 : const SalPoint* const*, const sal_uInt8* const* )
1400 : {
1401 0 : return false;
1402 : }
1403 :
1404 0 : void X11SalGraphicsImpl::invert( long nX,
1405 : long nY,
1406 : long nDX,
1407 : long nDY,
1408 : SalInvert nFlags )
1409 : {
1410 : GC pGC;
1411 0 : if( SAL_INVERT_50 & nFlags )
1412 : {
1413 0 : pGC = GetInvert50GC();
1414 0 : XFillRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY );
1415 : }
1416 : else
1417 : {
1418 0 : if ( SAL_INVERT_TRACKFRAME & nFlags )
1419 : {
1420 0 : pGC = GetTrackingGC();
1421 0 : XDrawRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY );
1422 : }
1423 : else
1424 : {
1425 0 : pGC = GetInvertGC();
1426 0 : XFillRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY );
1427 : }
1428 : }
1429 0 : }
1430 :
1431 0 : void X11SalGraphicsImpl::invert( sal_uInt32 nPoints,
1432 : const SalPoint* pPtAry,
1433 : SalInvert nFlags )
1434 : {
1435 0 : SalPolyLine Points ( nPoints, pPtAry );
1436 :
1437 : GC pGC;
1438 0 : if( SAL_INVERT_50 & nFlags )
1439 0 : pGC = GetInvert50GC();
1440 : else
1441 0 : if ( SAL_INVERT_TRACKFRAME & nFlags )
1442 0 : pGC = GetTrackingGC();
1443 : else
1444 0 : pGC = GetInvertGC();
1445 :
1446 0 : if( SAL_INVERT_TRACKFRAME & nFlags )
1447 0 : DrawLines ( nPoints, Points, pGC, true );
1448 : else
1449 : XFillPolygon( mrParent.GetXDisplay(),
1450 : mrParent.GetDrawable(),
1451 : pGC,
1452 0 : &Points[0], nPoints,
1453 0 : Complex, CoordModeOrigin );
1454 0 : }
1455 :
1456 0 : bool X11SalGraphicsImpl::drawEPS( long,long,long,long,void*,sal_uLong )
1457 : {
1458 0 : return false;
1459 : }
1460 :
1461 : // draw a poly-polygon
1462 0 : bool X11SalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency )
1463 : {
1464 : // nothing to do for empty polypolygons
1465 0 : const int nOrigPolyCount = rOrigPolyPoly.count();
1466 0 : if( nOrigPolyCount <= 0 )
1467 0 : return true;
1468 :
1469 : // nothing to do if everything is transparent
1470 0 : if( (mnBrushColor == SALCOLOR_NONE)
1471 0 : && (mnPenColor == SALCOLOR_NONE) )
1472 0 : return true;
1473 :
1474 : // cannot handle pencolor!=brushcolor yet
1475 0 : if( (mnPenColor != SALCOLOR_NONE)
1476 0 : && (mnPenColor != mnBrushColor) )
1477 0 : return false;
1478 :
1479 : // TODO: remove the env-variable when no longer needed
1480 0 : static const char* pRenderEnv = getenv( "SAL_DISABLE_RENDER_POLY" );
1481 0 : if( pRenderEnv )
1482 0 : return false;
1483 :
1484 : // snap to raster if requested
1485 0 : basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly;
1486 0 : const bool bSnapToRaster = !mrParent.getAntiAliasB2DDraw();
1487 0 : if( bSnapToRaster )
1488 0 : aPolyPoly = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly );
1489 :
1490 : // don't bother with polygons outside of visible area
1491 0 : const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() );
1492 0 : aPolyPoly = basegfx::tools::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false );
1493 0 : if( !aPolyPoly.count() )
1494 0 : return true;
1495 :
1496 : // tesselate the polypolygon into trapezoids
1497 0 : basegfx::B2DTrapezoidVector aB2DTrapVector;
1498 0 : basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aPolyPoly );
1499 0 : const int nTrapCount = aB2DTrapVector.size();
1500 0 : if( !nTrapCount )
1501 0 : return true;
1502 0 : const bool bDrawn = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency );
1503 0 : return bDrawn;
1504 : }
1505 :
1506 0 : long X11SalGraphicsImpl::GetGraphicsHeight() const
1507 : {
1508 0 : if( mrParent.m_pFrame )
1509 0 : return mrParent.m_pFrame->maGeometry.nHeight;
1510 0 : else if( mrParent.m_pVDev )
1511 0 : return static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetHeight();
1512 : else
1513 0 : return 0;
1514 : }
1515 :
1516 0 : bool X11SalGraphicsImpl::drawFilledTrapezoids( const ::basegfx::B2DTrapezoid* pB2DTraps, int nTrapCount, double fTransparency )
1517 : {
1518 0 : if( nTrapCount <= 0 )
1519 0 : return true;
1520 :
1521 0 : Picture aDstPic = GetXRenderPicture();
1522 : // check xrender support for this drawable
1523 0 : if( !aDstPic )
1524 0 : return false;
1525 :
1526 : // convert the B2DTrapezoids into XRender-Trapezoids
1527 : typedef std::vector<XTrapezoid> TrapezoidVector;
1528 0 : TrapezoidVector aTrapVector( nTrapCount );
1529 0 : const basegfx::B2DTrapezoid* pB2DTrap = pB2DTraps;
1530 0 : for( int i = 0; i < nTrapCount; ++pB2DTrap, ++i )
1531 : {
1532 0 : XTrapezoid& rTrap = aTrapVector[ i ] ;
1533 :
1534 : // set y-coordinates
1535 0 : const double fY1 = pB2DTrap->getTopY();
1536 0 : rTrap.left.p1.y = rTrap.right.p1.y = rTrap.top = XDoubleToFixed( fY1 );
1537 0 : const double fY2 = pB2DTrap->getBottomY();
1538 0 : rTrap.left.p2.y = rTrap.right.p2.y = rTrap.bottom = XDoubleToFixed( fY2 );
1539 :
1540 : // set x-coordinates
1541 0 : const double fXL1 = pB2DTrap->getTopXLeft();
1542 0 : rTrap.left.p1.x = XDoubleToFixed( fXL1 );
1543 0 : const double fXR1 = pB2DTrap->getTopXRight();
1544 0 : rTrap.right.p1.x = XDoubleToFixed( fXR1 );
1545 0 : const double fXL2 = pB2DTrap->getBottomXLeft();
1546 0 : rTrap.left.p2.x = XDoubleToFixed( fXL2 );
1547 0 : const double fXR2 = pB2DTrap->getBottomXRight();
1548 0 : rTrap.right.p2.x = XDoubleToFixed( fXR2 );
1549 : }
1550 :
1551 : // get xrender Picture for polygon foreground
1552 : // TODO: cache it like the target picture which uses GetXRenderPicture()
1553 0 : XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
1554 0 : SalDisplay::RenderEntry& rEntry = mrParent.GetDisplay()->GetRenderEntries( mrParent.m_nXScreen )[ 32 ];
1555 0 : if( !rEntry.m_aPicture )
1556 : {
1557 0 : Display* pXDisplay = mrParent.GetXDisplay();
1558 :
1559 0 : rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_, 1, 1, 32 );
1560 : XRenderPictureAttributes aAttr;
1561 0 : aAttr.repeat = int(true);
1562 :
1563 0 : XRenderPictFormat* pXRPF = rRenderPeer.FindStandardFormat( PictStandardARGB32 );
1564 0 : rEntry.m_aPicture = rRenderPeer.CreatePicture( rEntry.m_aPixmap, pXRPF, CPRepeat, &aAttr );
1565 : }
1566 :
1567 : // set polygon foreground color and opacity
1568 0 : XRenderColor aRenderColor = GetXRenderColor( mnBrushColor , fTransparency );
1569 0 : rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 );
1570 :
1571 : // set clipping
1572 : // TODO: move into GetXRenderPicture?
1573 0 : if( mrParent.mpClipRegion && !XEmptyRegion( mrParent.mpClipRegion ) )
1574 0 : rRenderPeer.SetPictureClipRegion( aDstPic, mrParent.mpClipRegion );
1575 :
1576 : // render the trapezoids
1577 0 : const XRenderPictFormat* pMaskFormat = rRenderPeer.GetStandardFormatA8();
1578 : rRenderPeer.CompositeTrapezoids( PictOpOver,
1579 0 : rEntry.m_aPicture, aDstPic, pMaskFormat, 0, 0, &aTrapVector[0], aTrapVector.size() );
1580 :
1581 0 : return true;
1582 : }
1583 :
1584 0 : bool X11SalGraphicsImpl::drawPolyLine(
1585 : const ::basegfx::B2DPolygon& rPolygon,
1586 : double fTransparency,
1587 : const ::basegfx::B2DVector& rLineWidth,
1588 : basegfx::B2DLineJoin eLineJoin,
1589 : com::sun::star::drawing::LineCap eLineCap)
1590 : {
1591 0 : const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2);
1592 :
1593 : // #i101491#
1594 0 : if( !bIsHairline && (rPolygon.count() > 1000) )
1595 : {
1596 : // the used basegfx::tools::createAreaGeometry is simply too
1597 : // expensive with very big polygons; fallback to caller (who
1598 : // should use ImplLineConverter normally)
1599 : // AW: ImplLineConverter had to be removed since it does not even
1600 : // know LineJoins, so the fallback will now prepare the line geometry
1601 : // the same way.
1602 0 : return false;
1603 : }
1604 :
1605 : // temporarily adjust brush color to pen color
1606 : // since the line is drawn as an area-polygon
1607 0 : const SalColor aKeepBrushColor = mnBrushColor;
1608 0 : mnBrushColor = mnPenColor;
1609 :
1610 : // #i11575#desc5#b adjust B2D tesselation result to raster positions
1611 0 : basegfx::B2DPolygon aPolygon = rPolygon;
1612 0 : const double fHalfWidth = 0.5 * rLineWidth.getX();
1613 :
1614 : // #i122456# This is probably thought to happen to align hairlines to pixel positions, so
1615 : // it should be a 0.5 translation, not more. It will definitely go wrong with fat lines
1616 0 : aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5) );
1617 :
1618 : // shortcut for hairline drawing to improve performance
1619 0 : bool bDrawnOk = true;
1620 0 : if( bIsHairline )
1621 : {
1622 : // hairlines can benefit from a simplified tesselation
1623 : // e.g. for hairlines the linejoin style can be ignored
1624 0 : basegfx::B2DTrapezoidVector aB2DTrapVector;
1625 0 : basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() );
1626 :
1627 : // draw tesselation result
1628 0 : const int nTrapCount = aB2DTrapVector.size();
1629 0 : if( nTrapCount > 0 )
1630 0 : bDrawnOk = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency );
1631 :
1632 : // restore the original brush GC
1633 0 : mnBrushColor = aKeepBrushColor;
1634 0 : return bDrawnOk;
1635 : }
1636 :
1637 : // get the area polygon for the line polygon
1638 0 : if( (rLineWidth.getX() != rLineWidth.getY())
1639 0 : && !basegfx::fTools::equalZero( rLineWidth.getY() ) )
1640 : {
1641 : // prepare for createAreaGeometry() with anisotropic linewidth
1642 0 : aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY()));
1643 : }
1644 :
1645 : // create the area-polygon for the line
1646 0 : const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) );
1647 :
1648 0 : if( (rLineWidth.getX() != rLineWidth.getY())
1649 0 : && !basegfx::fTools::equalZero( rLineWidth.getX() ) )
1650 : {
1651 : // postprocess createAreaGeometry() for anisotropic linewidth
1652 0 : aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX()));
1653 : }
1654 :
1655 : // draw each area polypolygon component individually
1656 : // to emulate the polypolygon winding rule "non-zero"
1657 0 : const int nPolyCount = aAreaPolyPoly.count();
1658 0 : for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
1659 : {
1660 0 : const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) );
1661 0 : bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency );
1662 0 : if( !bDrawnOk )
1663 0 : break;
1664 0 : }
1665 :
1666 : // restore the original brush GC
1667 0 : mnBrushColor = aKeepBrushColor;
1668 0 : return bDrawnOk;
1669 : }
1670 :
1671 0 : SalColor X11SalGraphicsImpl::getPixel( long nX, long nY )
1672 : {
1673 0 : if( mrParent.bWindow_ && !mrParent.bVirDev_ )
1674 : {
1675 : XWindowAttributes aAttrib;
1676 :
1677 0 : XGetWindowAttributes( mrParent.GetXDisplay(), mrParent.GetDrawable(), &aAttrib );
1678 0 : if( aAttrib.map_state != IsViewable )
1679 : {
1680 : stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" );
1681 0 : return 0;
1682 : }
1683 : }
1684 :
1685 : XImage *pXImage = XGetImage( mrParent.GetXDisplay(),
1686 : mrParent.GetDrawable(),
1687 : nX, nY,
1688 : 1, 1,
1689 : AllPlanes,
1690 0 : ZPixmap );
1691 0 : if( !pXImage )
1692 : {
1693 : stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" );
1694 0 : return 0;
1695 : }
1696 :
1697 : XColor aXColor;
1698 :
1699 0 : aXColor.pixel = XGetPixel( pXImage, 0, 0 );
1700 0 : XDestroyImage( pXImage );
1701 :
1702 0 : return mrParent.GetColormap().GetColor( aXColor.pixel );
1703 : }
1704 :
1705 5 : SalBitmap *X11SalGraphicsImpl::getBitmap( long nX, long nY, long nDX, long nDY )
1706 : {
1707 5 : if( mrParent.bPrinter_ && !mrParent.bVirDev_ )
1708 0 : return NULL;
1709 :
1710 5 : bool bFakeWindowBG = false;
1711 :
1712 : // normalize
1713 5 : if( nDX < 0 )
1714 : {
1715 0 : nX += nDX;
1716 0 : nDX = -nDX;
1717 : }
1718 5 : if ( nDY < 0 )
1719 : {
1720 0 : nY += nDY;
1721 0 : nDY = -nDY;
1722 : }
1723 :
1724 5 : if( mrParent.bWindow_ && !mrParent.bVirDev_ )
1725 : {
1726 : XWindowAttributes aAttrib;
1727 :
1728 0 : XGetWindowAttributes( mrParent.GetXDisplay(), mrParent.GetDrawable(), &aAttrib );
1729 0 : if( aAttrib.map_state != IsViewable )
1730 0 : bFakeWindowBG = true;
1731 : else
1732 : {
1733 0 : long nOrgDX = nDX, nOrgDY = nDY;
1734 :
1735 : // clip to window size
1736 0 : if ( nX < 0 )
1737 : {
1738 0 : nDX += nX;
1739 0 : nX = 0;
1740 : }
1741 0 : if ( nY < 0 )
1742 : {
1743 0 : nDY += nY;
1744 0 : nY = 0;
1745 : }
1746 0 : if( nX + nDX > aAttrib.width )
1747 0 : nDX = aAttrib.width - nX;
1748 0 : if( nY + nDY > aAttrib.height )
1749 0 : nDY = aAttrib.height - nY;
1750 :
1751 : // inside ?
1752 0 : if( nDX <= 0 || nDY <= 0 )
1753 : {
1754 0 : bFakeWindowBG = true;
1755 0 : nDX = nOrgDX;
1756 0 : nDY = nOrgDY;
1757 : }
1758 : }
1759 : }
1760 :
1761 5 : X11SalBitmap* pSalBitmap = new X11SalBitmap;
1762 5 : sal_uInt16 nBitCount = GetBitCount();
1763 :
1764 5 : if( &mrParent.GetDisplay()->GetColormap( mrParent.m_nXScreen ) != &mrParent.GetColormap() )
1765 0 : nBitCount = 1;
1766 :
1767 5 : if( ! bFakeWindowBG )
1768 5 : pSalBitmap->ImplCreateFromDrawable( mrParent.GetDrawable(), mrParent.m_nXScreen, nBitCount, nX, nY, nDX, nDY );
1769 : else
1770 0 : pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) );
1771 :
1772 5 : return pSalBitmap;
1773 : }
1774 :
1775 348 : sal_uInt16 X11SalGraphicsImpl::GetBitCount() const
1776 : {
1777 348 : return mrParent.GetVisual().GetDepth();
1778 : }
1779 :
1780 0 : long X11SalGraphicsImpl::GetGraphicsWidth() const
1781 : {
1782 0 : if( mrParent.m_pFrame )
1783 0 : return mrParent.m_pFrame->maGeometry.nWidth;
1784 0 : else if( mrParent.m_pVDev )
1785 0 : return static_cast< X11SalVirtualDevice* >(mrParent.m_pVDev)->GetWidth();
1786 : else
1787 0 : return 0;
1788 : }
1789 :
1790 0 : bool X11SalGraphicsImpl::drawGradient(const tools::PolyPolygon& /*rPolygon*/, const Gradient& /*rGradient*/)
1791 : {
1792 0 : return false;
1793 9 : }
1794 :
1795 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|