1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include "tools/debug.hxx"
28
29 #include "basegfx/polygon/b2dpolygon.hxx"
30 #include "basegfx/polygon/b2dpolypolygon.hxx"
31 #include "basegfx/polygon/b2dpolypolygontools.hxx"
32 #include "basegfx/polygon/b2dpolygontools.hxx"
33 #include "basegfx/polygon/b2dpolygonclipper.hxx"
34 #include "basegfx/polygon/b2dlinegeometry.hxx"
35 #include "basegfx/matrix/b2dhommatrix.hxx"
36 #include "basegfx/matrix/b2dhommatrixtools.hxx"
37 #include "basegfx/polygon/b2dpolypolygoncutter.hxx"
38 #include "basegfx/polygon/b2dtrapezoid.hxx"
39
40 #include "vcl/jobdata.hxx"
41
42 #include "unx/Xproto.h"
43 #include "unx/salunx.h"
44 #include "unx/saldata.hxx"
45 #include "unx/saldisp.hxx"
46 #include "unx/salgdi.h"
47 #include "unx/salframe.h"
48 #include "unx/salvd.h"
49
50 #include "printergfx.hxx"
51 #include "xrender_peer.hxx"
52
53 #include <vector>
54 #include <queue>
55 #include <set>
56
57 // -=-= SalPolyLine =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
58 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
59 #define STATIC_POINTS 64
60
61 class SalPolyLine
62 {
63 XPoint Points_[STATIC_POINTS];
64 XPoint *pFirst_;
65 public:
66 inline SalPolyLine( sal_uLong nPoints );
67 inline SalPolyLine( sal_uLong nPoints, const SalPoint *p );
68 inline ~SalPolyLine();
operator [](sal_uLong n) const69 inline XPoint &operator [] ( sal_uLong n ) const
70 { return pFirst_[n]; }
71 };
72
SalPolyLine(sal_uLong nPoints)73 inline SalPolyLine::SalPolyLine( sal_uLong nPoints )
74 : pFirst_( nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_ )
75 {}
76
SalPolyLine(sal_uLong nPoints,const SalPoint * p)77 inline SalPolyLine::SalPolyLine( sal_uLong nPoints, const SalPoint *p )
78 : pFirst_( nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_ )
79 {
80 for( sal_uLong i = 0; i < nPoints; i++ )
81 {
82 pFirst_[i].x = (short)p[i].mnX;
83 pFirst_[i].y = (short)p[i].mnY;
84 }
85 pFirst_[nPoints] = pFirst_[0]; // close polyline
86 }
87
~SalPolyLine()88 inline SalPolyLine::~SalPolyLine()
89 { if( pFirst_ != Points_ ) delete [] pFirst_; }
90
91 #undef STATIC_POINTS
92 // -=-= X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
93 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
X11SalGraphics()94 X11SalGraphics::X11SalGraphics()
95 {
96 m_pFrame = NULL;
97 m_pVDev = NULL;
98 m_pDeleteColormap = NULL;
99 hDrawable_ = None;
100 m_aRenderPicture = 0;
101 m_pRenderFormat = NULL;
102
103 mpClipRegion = NULL;
104 pPaintRegion_ = NULL;
105
106 pPenGC_ = NULL;
107 nPenPixel_ = 0;
108 nPenColor_ = MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black
109
110 pFontGC_ = NULL;
111 for( int i = 0; i < MAX_FALLBACK; ++i )
112 mpServerFont[i] = NULL;
113
114 nTextPixel_ = 0;
115 nTextColor_ = MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black
116
117 #ifdef ENABLE_GRAPHITE
118 // check if graphite fonts have been disabled
119 static const char* pDisableGraphiteStr = getenv( "SAL_DISABLE_GRAPHITE" );
120 bDisableGraphite_ = pDisableGraphiteStr ? (pDisableGraphiteStr[0]!='0') : sal_False;
121 #endif
122
123 pBrushGC_ = NULL;
124 nBrushPixel_ = 0;
125 nBrushColor_ = MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ); // White
126 hBrush_ = None;
127
128 pMonoGC_ = NULL;
129 pCopyGC_ = NULL;
130 pMaskGC_ = NULL;
131 pInvertGC_ = NULL;
132 pInvert50GC_ = NULL;
133 pStippleGC_ = NULL;
134 pTrackingGC_ = NULL;
135
136 bWindow_ = sal_False;
137 bPrinter_ = sal_False;
138 bVirDev_ = sal_False;
139 bPenGC_ = sal_False;
140 bFontGC_ = sal_False;
141 bBrushGC_ = sal_False;
142 bMonoGC_ = sal_False;
143 bCopyGC_ = sal_False;
144 bInvertGC_ = sal_False;
145 bInvert50GC_ = sal_False;
146 bStippleGC_ = sal_False;
147 bTrackingGC_ = sal_False;
148 bXORMode_ = sal_False;
149 bDitherBrush_ = sal_False;
150 }
151
152 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
~X11SalGraphics()153 X11SalGraphics::~X11SalGraphics()
154 {
155 ReleaseFonts();
156 freeResources();
157 }
158
159 // -=-= SalGraphics / X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
160
freeResources()161 void X11SalGraphics::freeResources()
162 {
163 Display *pDisplay = GetXDisplay();
164
165 DBG_ASSERT( !pPaintRegion_, "pPaintRegion_" );
166 if( mpClipRegion ) XDestroyRegion( mpClipRegion ), mpClipRegion = None;
167
168 if( hBrush_ ) XFreePixmap( pDisplay, hBrush_ ), hBrush_ = None;
169 if( pPenGC_ ) XFreeGC( pDisplay, pPenGC_ ), pPenGC_ = None;
170 if( pFontGC_ ) XFreeGC( pDisplay, pFontGC_ ), pFontGC_ = None;
171 if( pBrushGC_ ) XFreeGC( pDisplay, pBrushGC_ ), pBrushGC_ = None;
172 if( pMonoGC_ ) XFreeGC( pDisplay, pMonoGC_ ), pMonoGC_ = None;
173 if( pCopyGC_ ) XFreeGC( pDisplay, pCopyGC_ ), pCopyGC_ = None;
174 if( pMaskGC_ ) XFreeGC( pDisplay, pMaskGC_ ), pMaskGC_ = None;
175 if( pInvertGC_ ) XFreeGC( pDisplay, pInvertGC_ ), pInvertGC_ = None;
176 if( pInvert50GC_ ) XFreeGC( pDisplay, pInvert50GC_ ), pInvert50GC_ = None;
177 if( pStippleGC_ ) XFreeGC( pDisplay, pStippleGC_ ), pStippleGC_ = None;
178 if( pTrackingGC_ ) XFreeGC( pDisplay, pTrackingGC_ ), pTrackingGC_ = None;
179 if( m_pDeleteColormap )
180 delete m_pDeleteColormap, m_pColormap = m_pDeleteColormap = NULL;
181
182 if( m_aRenderPicture )
183 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture ), m_aRenderPicture = 0;
184
185 bPenGC_ = bFontGC_ = bBrushGC_ = bMonoGC_ = bCopyGC_ = bInvertGC_ = bInvert50GC_ = bStippleGC_ = bTrackingGC_ = false;
186 }
187
SetDrawable(Drawable aDrawable,int nScreen)188 void X11SalGraphics::SetDrawable( Drawable aDrawable, int nScreen )
189 {
190 // shortcut if nothing changed
191 if( hDrawable_ == aDrawable )
192 return;
193
194 // free screen specific resources if needed
195 if( nScreen != m_nScreen )
196 {
197 freeResources();
198 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap( nScreen );
199 m_nScreen = nScreen;
200 }
201
202 hDrawable_ = aDrawable;
203 SetXRenderFormat( NULL );
204 if( m_aRenderPicture )
205 {
206 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture );
207 m_aRenderPicture = 0;
208 }
209
210 if( hDrawable_ )
211 {
212 nPenPixel_ = GetPixel( nPenColor_ );
213 nTextPixel_ = GetPixel( nTextColor_ );
214 nBrushPixel_ = GetPixel( nBrushColor_ );
215 }
216 }
217
Init(SalFrame * pFrame,Drawable aTarget,int nScreen)218 void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget, int nScreen )
219 {
220 #if 0 // TODO: use SetDrawable() instead
221 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap(nScreen);
222 hDrawable_ = aTarget;
223 m_nScreen = nScreen;
224 SetXRenderFormat( NULL );
225 if( m_aRenderPicture )
226 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture ), m_aRenderPicture = 0;
227
228 nPenPixel_ = GetPixel( nPenColor_ );
229 nTextPixel_ = GetPixel( nTextColor_ );
230 nBrushPixel_ = GetPixel( nBrushColor_ );
231 #else
232 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap(nScreen);
233 m_nScreen = nScreen;
234 SetDrawable( aTarget, nScreen );
235 #endif
236
237 bWindow_ = sal_True;
238 m_pFrame = pFrame;
239 m_pVDev = NULL;
240 }
241
242 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
DeInit()243 void X11SalGraphics::DeInit()
244 {
245 SetDrawable( None, m_nScreen );
246 }
247
248 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetClipRegion(GC pGC,XLIB_Region pXReg) const249 void X11SalGraphics::SetClipRegion( GC pGC, XLIB_Region pXReg ) const
250 {
251 Display *pDisplay = GetXDisplay();
252
253 int n = 0;
254 XLIB_Region Regions[3];
255
256 if( mpClipRegion /* && !XEmptyRegion( mpClipRegion ) */ )
257 Regions[n++] = mpClipRegion;
258 // if( pPaintRegion_ /* && !XEmptyRegion( pPaintRegion_ ) */ )
259 // Regions[n++] = pPaintRegion_;
260
261 if( pXReg && !XEmptyRegion( pXReg ) )
262 Regions[n++] = pXReg;
263
264 if( 0 == n )
265 XSetClipMask( pDisplay, pGC, None );
266 else if( 1 == n )
267 XSetRegion( pDisplay, pGC, Regions[0] );
268 else
269 {
270 XLIB_Region pTmpRegion = XCreateRegion();
271 XIntersectRegion( Regions[0], Regions[1], pTmpRegion );
272 // if( 3 == n )
273 // XIntersectRegion( Regions[2], pTmpRegion, pTmpRegion );
274 XSetRegion( pDisplay, pGC, pTmpRegion );
275 XDestroyRegion( pTmpRegion );
276 }
277 }
278
279 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SelectPen()280 GC X11SalGraphics::SelectPen()
281 {
282 Display *pDisplay = GetXDisplay();
283
284 if( !pPenGC_ )
285 {
286 XGCValues values;
287 values.subwindow_mode = ClipByChildren;
288 values.fill_rule = EvenOddRule; // Pict import/ Gradient
289 values.graphics_exposures = False;
290
291 pPenGC_ = XCreateGC( pDisplay, hDrawable_,
292 GCSubwindowMode | GCFillRule | GCGraphicsExposures,
293 &values );
294 }
295
296 if( !bPenGC_ )
297 {
298 if( nPenColor_ != SALCOLOR_NONE )
299 XSetForeground( pDisplay, pPenGC_, nPenPixel_ );
300 XSetFunction ( pDisplay, pPenGC_, bXORMode_ ? GXxor : GXcopy );
301 SetClipRegion( pPenGC_ );
302 bPenGC_ = sal_True;
303 }
304
305 return pPenGC_;
306 }
307
308 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SelectBrush()309 GC X11SalGraphics::SelectBrush()
310 {
311 Display *pDisplay = GetXDisplay();
312
313 DBG_ASSERT( nBrushColor_ != SALCOLOR_NONE, "Brush Transparent" );
314
315 if( !pBrushGC_ )
316 {
317 XGCValues values;
318 // values.subwindow_mode = IncludeInferiors;
319 values.subwindow_mode = ClipByChildren;
320 values.fill_rule = EvenOddRule; // Pict import/ Gradient
321 values.graphics_exposures = False;
322
323 pBrushGC_ = XCreateGC( pDisplay, hDrawable_,
324 GCSubwindowMode | GCFillRule | GCGraphicsExposures,
325 &values );
326 }
327
328 if( !bBrushGC_ )
329 {
330 if( !bDitherBrush_ )
331 {
332 XSetFillStyle ( pDisplay, pBrushGC_, FillSolid );
333 XSetForeground( pDisplay, pBrushGC_, nBrushPixel_ );
334 if( bPrinter_ )
335 XSetTile( pDisplay, pBrushGC_, None );
336 }
337 else
338 {
339 // Bug in Sun Solaris 2.5.1, XFillPolygon doesn't allways reflect
340 // changes of the tile. PROPERTY_BUG_Tile doesn't fix this !
341 if (GetDisplay()->GetProperties() & PROPERTY_BUG_FillPolygon_Tile)
342 XSetFillStyle ( pDisplay, pBrushGC_, FillSolid );
343
344 XSetFillStyle ( pDisplay, pBrushGC_, FillTiled );
345 XSetTile ( pDisplay, pBrushGC_, hBrush_ );
346 }
347 XSetFunction ( pDisplay, pBrushGC_, bXORMode_ ? GXxor : GXcopy );
348 SetClipRegion( pBrushGC_ );
349
350 bBrushGC_ = sal_True;
351 }
352
353 return pBrushGC_;
354 }
355
356 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetTrackingGC()357 GC X11SalGraphics::GetTrackingGC()
358 {
359 const char dash_list[2] = {2, 2};
360
361 if( !pTrackingGC_ )
362 {
363 XGCValues values;
364
365 values.graphics_exposures = False;
366 values.foreground = m_pColormap->GetBlackPixel()
367 ^ m_pColormap->GetWhitePixel();
368 values.function = GXxor;
369 values.line_width = 1;
370 values.line_style = LineOnOffDash;
371
372 pTrackingGC_ = XCreateGC( GetXDisplay(), GetDrawable(),
373 GCGraphicsExposures | GCForeground | GCFunction
374 | GCLineWidth | GCLineStyle,
375 &values );
376 XSetDashes( GetXDisplay(), pTrackingGC_, 0, dash_list, 2 );
377 }
378
379 if( !bTrackingGC_ )
380 {
381 SetClipRegion( pTrackingGC_ );
382 bTrackingGC_ = sal_True;
383 }
384
385 return pTrackingGC_;
386 }
387
388 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
DrawLines(sal_uLong nPoints,const SalPolyLine & rPoints,GC pGC,bool bClose)389 void X11SalGraphics::DrawLines( sal_uLong nPoints,
390 const SalPolyLine &rPoints,
391 GC pGC,
392 bool bClose
393 )
394 {
395 // errechne wie viele Linien XWindow auf einmal zeichnen kann
396 sal_uLong nMaxLines = (GetDisplay()->GetMaxRequestSize() - sizeof(xPolyPointReq))
397 / sizeof(xPoint);
398 if( nMaxLines > nPoints ) nMaxLines = nPoints;
399
400 // gebe alle Linien aus, die XWindows zeichnen kann.
401 sal_uLong n;
402 for( n = 0; nPoints - n > nMaxLines; n += nMaxLines - 1 )
403 XDrawLines( GetXDisplay(),
404 GetDrawable(),
405 pGC,
406 &rPoints[n],
407 nMaxLines,
408 CoordModeOrigin );
409
410 if( n < nPoints )
411 XDrawLines( GetXDisplay(),
412 GetDrawable(),
413 pGC,
414 &rPoints[n],
415 nPoints - n,
416 CoordModeOrigin );
417 if( bClose )
418 {
419 if( rPoints[nPoints-1].x != rPoints[0].x || rPoints[nPoints-1].y != rPoints[0].y )
420 drawLine( rPoints[nPoints-1].x, rPoints[nPoints-1].y, rPoints[0].x, rPoints[0].y );
421 }
422 }
423
424 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
425 // Dithern: Calculate a dither-pixmap and make a brush of it
426 #define P_DELTA 51
427 #define DMAP( v, m ) ((v % P_DELTA) > m ? (v / P_DELTA) + 1 : (v / P_DELTA))
428
GetDitherPixmap(SalColor nSalColor)429 BOOL X11SalGraphics::GetDitherPixmap( SalColor nSalColor )
430 {
431 static const short nOrdDither8Bit[ 8 ][ 8 ] =
432 {
433 { 0, 38, 9, 48, 2, 40, 12, 50},
434 {25, 12, 35, 22, 28, 15, 37, 24},
435 { 6, 44, 3, 41, 8, 47, 5, 44},
436 {32, 19, 28, 16, 34, 21, 31, 18},
437 { 1, 40, 11, 49, 0, 39, 10, 48},
438 {27, 14, 36, 24, 26, 13, 36, 23},
439 { 8, 46, 4, 43, 7, 45, 4, 42},
440 {33, 20, 30, 17, 32, 20, 29, 16}
441 };
442
443 // test for correct depth (8bit)
444 if( GetColormap().GetVisual().GetDepth() != 8 )
445 return sal_False;
446
447 char pBits[64];
448 char *pBitsPtr = pBits;
449
450 // Set the pallette-entries for the dithering tile
451 sal_uInt8 nSalColorRed = SALCOLOR_RED ( nSalColor );
452 sal_uInt8 nSalColorGreen = SALCOLOR_GREEN ( nSalColor );
453 sal_uInt8 nSalColorBlue = SALCOLOR_BLUE ( nSalColor );
454
455 for( int nY = 0; nY < 8; nY++ )
456 {
457 for( int nX = 0; nX < 8; nX++ )
458 {
459 short nMagic = nOrdDither8Bit[nY][nX];
460 sal_uInt8 nR = P_DELTA * DMAP( nSalColorRed, nMagic );
461 sal_uInt8 nG = P_DELTA * DMAP( nSalColorGreen, nMagic );
462 sal_uInt8 nB = P_DELTA * DMAP( nSalColorBlue, nMagic );
463
464 *pBitsPtr++ = GetColormap().GetPixel( MAKE_SALCOLOR( nR, nG, nB ) );
465 }
466 }
467
468 // create the tile as ximage and an according pixmap -> caching
469 XImage *pImage = XCreateImage( GetXDisplay(),
470 GetColormap().GetXVisual(),
471 8,
472 ZPixmap,
473 0, // offset
474 pBits, // data
475 8, 8, // width & height
476 8, // bitmap_pad
477 0 ); // (default) bytes_per_line
478
479 if ( GetDisplay()->GetProperties() & PROPERTY_BUG_Tile )
480 {
481 if (hBrush_)
482 XFreePixmap (GetXDisplay(), hBrush_);
483 hBrush_ = XCreatePixmap( GetXDisplay(), GetDrawable(), 8, 8, 8 );
484 }
485 else
486 if( !hBrush_ )
487 hBrush_ = XCreatePixmap( GetXDisplay(), GetDrawable(), 8, 8, 8 );
488
489 // put the ximage to the pixmap
490 XPutImage( GetXDisplay(),
491 hBrush_,
492 GetDisplay()->GetCopyGC( m_nScreen ),
493 pImage,
494 0, 0, // Source
495 0, 0, // Destination
496 8, 8 ); // width & height
497
498 // destroy image-frame but not palette-data
499 pImage->data = NULL;
500 XDestroyImage( pImage );
501
502 return sal_True;
503 }
504
505 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetResolution(sal_Int32 & rDPIX,sal_Int32 & rDPIY)506 void X11SalGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY ) // const
507 {
508 const SalDisplay *pDisplay = GetDisplay();
509
510 rDPIX = pDisplay->GetResolution().A();
511 rDPIY = pDisplay->GetResolution().B();
512 if( !pDisplay->GetExactResolution() && rDPIY < 96 )
513 {
514 rDPIX = Divide( rDPIX * 96, rDPIY );
515 rDPIY = 96;
516 }
517 else if ( rDPIY > 200 )
518 {
519 rDPIX = Divide( rDPIX * 200, rDPIY );
520 rDPIY = 200;
521 }
522
523 // #i12705# equalize x- and y-resolution if they are close enough
524 if( rDPIX != rDPIY )
525 {
526 // different x- and y- resolutions are usually artifacts of
527 // a wrongly calculated screen size.
528 //if( (13*rDPIX >= 10*rDPIY) && (13*rDPIY >= 10*rDPIX) ) //+-30%
529 {
530 #ifdef DEBUG
531 printf("Forcing Resolution from %" SAL_PRIdINT32 "x%" SAL_PRIdINT32 " to %" SAL_PRIdINT32 "x%" SAL_PRIdINT32 "\n",
532 rDPIX,rDPIY,rDPIY,rDPIY);
533 #endif
534 rDPIX = rDPIY; // y-resolution is more trustworthy
535 }
536 }
537 }
538
539 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetBitCount()540 sal_uInt16 X11SalGraphics::GetBitCount() // const
541 {
542 return GetVisual().GetDepth();
543 }
544
545 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetGraphicsWidth() const546 long X11SalGraphics::GetGraphicsWidth() const
547 {
548 if( m_pFrame )
549 return m_pFrame->maGeometry.nWidth;
550 else if( m_pVDev )
551 return m_pVDev->GetWidth();
552 else
553 return 0;
554 }
555
556 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
GetGraphicsHeight() const557 long X11SalGraphics::GetGraphicsHeight() const
558 {
559 if( m_pFrame )
560 return m_pFrame->maGeometry.nHeight;
561 else if( m_pVDev )
562 return m_pVDev->GetHeight();
563 else
564 return 0;
565 }
566
567 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ResetClipRegion()568 void X11SalGraphics::ResetClipRegion()
569 {
570 if( mpClipRegion )
571 {
572 bPenGC_ = sal_False;
573 bFontGC_ = sal_False;
574 bBrushGC_ = sal_False;
575 bMonoGC_ = sal_False;
576 bCopyGC_ = sal_False;
577 bInvertGC_ = sal_False;
578 bInvert50GC_ = sal_False;
579 bStippleGC_ = sal_False;
580 bTrackingGC_ = sal_False;
581
582 XDestroyRegion( mpClipRegion );
583 mpClipRegion = NULL;
584 }
585 }
586
setClipRegion(const Region & i_rClip)587 bool X11SalGraphics::setClipRegion( const Region& i_rClip )
588 {
589 if( mpClipRegion )
590 XDestroyRegion( mpClipRegion );
591 mpClipRegion = XCreateRegion();
592
593 RectangleVector aRectangles;
594 i_rClip.GetRegionRectangles(aRectangles);
595
596 for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
597 {
598 const long nW(aRectIter->GetWidth());
599
600 if(nW)
601 {
602 const long nH(aRectIter->GetHeight());
603
604 if(nH)
605 {
606 XRectangle aRect;
607
608 aRect.x = (short)aRectIter->Left();
609 aRect.y = (short)aRectIter->Top();
610 aRect.width = (unsigned short)nW;
611 aRect.height = (unsigned short)nH;
612 XUnionRectWithRegion(&aRect, mpClipRegion, mpClipRegion);
613 }
614 }
615 }
616
617 //ImplRegionInfo aInfo;
618 //long nX, nY, nW, nH;
619 //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
620 //while( bRegionRect )
621 //{
622 // if ( nW && nH )
623 // {
624 // XRectangle aRect;
625 // aRect.x = (short)nX;
626 // aRect.y = (short)nY;
627 // aRect.width = (unsigned short)nW;
628 // aRect.height = (unsigned short)nH;
629 //
630 // XUnionRectWithRegion( &aRect, mpClipRegion, mpClipRegion );
631 // }
632 // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
633 //}
634
635 // done, invalidate GCs
636 bPenGC_ = sal_False;
637 bFontGC_ = sal_False;
638 bBrushGC_ = sal_False;
639 bMonoGC_ = sal_False;
640 bCopyGC_ = sal_False;
641 bInvertGC_ = sal_False;
642 bInvert50GC_ = sal_False;
643 bStippleGC_ = sal_False;
644 bTrackingGC_ = sal_False;
645
646 if( XEmptyRegion( mpClipRegion ) )
647 {
648 XDestroyRegion( mpClipRegion );
649 mpClipRegion= NULL;
650 }
651 return true;
652 }
653
654 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetLineColor()655 void X11SalGraphics::SetLineColor()
656 {
657 if( nPenColor_ != SALCOLOR_NONE )
658 {
659 nPenColor_ = SALCOLOR_NONE;
660 bPenGC_ = sal_False;
661 }
662 }
663
664 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetLineColor(SalColor nSalColor)665 void X11SalGraphics::SetLineColor( SalColor nSalColor )
666 {
667 if( nPenColor_ != nSalColor )
668 {
669 nPenColor_ = nSalColor;
670 nPenPixel_ = GetPixel( nSalColor );
671 bPenGC_ = sal_False;
672 }
673 }
674
675 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetFillColor()676 void X11SalGraphics::SetFillColor()
677 {
678 if( nBrushColor_ != SALCOLOR_NONE )
679 {
680 bDitherBrush_ = sal_False;
681 nBrushColor_ = SALCOLOR_NONE;
682 bBrushGC_ = sal_False;
683 }
684 }
685
686 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetFillColor(SalColor nSalColor)687 void X11SalGraphics::SetFillColor( SalColor nSalColor )
688 {
689 if( nBrushColor_ != nSalColor )
690 {
691 bDitherBrush_ = sal_False;
692 nBrushColor_ = nSalColor;
693 nBrushPixel_ = GetPixel( nSalColor );
694 if( TrueColor != GetColormap().GetVisual().GetClass()
695 && GetColormap().GetColor( nBrushPixel_ ) != nBrushColor_
696 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) // black
697 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x80 ) // blue
698 && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x00 ) // green
699 && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x80 ) // cyan
700 && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x00 ) // red
701 && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x80 ) // magenta
702 && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x00 ) // brown
703 && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x80 ) // gray
704 && nSalColor != MAKE_SALCOLOR( 0xC0, 0xC0, 0xC0 ) // light gray
705 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0xFF ) // light blue
706 && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0x00 ) // light green
707 && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0xFF ) // light cyan
708 && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0x00 ) // light red
709 && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0xFF ) // light magenta
710 && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0x00 ) // light brown
711 && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) )
712 bDitherBrush_ = GetDitherPixmap(nSalColor);
713 bBrushGC_ = sal_False;
714 }
715 }
716
717 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetROPLineColor(SalROPColor nROPColor)718 void X11SalGraphics::SetROPLineColor( SalROPColor nROPColor )
719 {
720 switch( nROPColor )
721 {
722 case SAL_ROP_0 : // 0
723 nPenPixel_ = (Pixel)0;
724 break;
725 case SAL_ROP_1 : // 1
726 nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1;
727 break;
728 case SAL_ROP_INVERT : // 2
729 nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1;
730 break;
731 }
732 nPenColor_ = GetColormap().GetColor( nPenPixel_ );
733 bPenGC_ = sal_False;
734 }
735
736 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetROPFillColor(SalROPColor nROPColor)737 void X11SalGraphics::SetROPFillColor( SalROPColor nROPColor )
738 {
739 switch( nROPColor )
740 {
741 case SAL_ROP_0 : // 0
742 nBrushPixel_ = (Pixel)0;
743 break;
744 case SAL_ROP_1 : // 1
745 nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1;
746 break;
747 case SAL_ROP_INVERT : // 2
748 nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1;
749 break;
750 }
751 bDitherBrush_ = sal_False;
752 nBrushColor_ = GetColormap().GetColor( nBrushPixel_ );
753 bBrushGC_ = sal_False;
754 }
755
756 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SetXORMode(bool bSet,bool)757 void X11SalGraphics::SetXORMode( bool bSet, bool )
758 {
759 if( !bXORMode_ == bSet )
760 {
761 bXORMode_ = bSet;
762 bPenGC_ = sal_False;
763 bFontGC_ = sal_False;
764 bBrushGC_ = sal_False;
765 bMonoGC_ = sal_False;
766 bCopyGC_ = sal_False;
767 bInvertGC_ = sal_False;
768 bInvert50GC_ = sal_False;
769 bStippleGC_ = sal_False;
770 bTrackingGC_ = sal_False;
771 }
772 }
773
774 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawPixel(long nX,long nY)775 void X11SalGraphics::drawPixel( long nX, long nY )
776 {
777 if( nPenColor_ != SALCOLOR_NONE )
778 XDrawPoint( GetXDisplay(), GetDrawable(), SelectPen(), nX, nY );
779 }
780
drawPixel(long nX,long nY,SalColor nSalColor)781 void X11SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
782 {
783 if( nSalColor != SALCOLOR_NONE )
784 {
785 Display *pDisplay = GetXDisplay();
786
787 if( (nPenColor_ == SALCOLOR_NONE) && !bPenGC_ )
788 {
789 SetLineColor( nSalColor );
790 XDrawPoint( pDisplay, GetDrawable(), SelectPen(), nX, nY );
791 nPenColor_ = SALCOLOR_NONE;
792 bPenGC_ = False;
793 }
794 else
795 {
796 GC pGC = SelectPen();
797
798 if( nSalColor != nPenColor_ )
799 XSetForeground( pDisplay, pGC, GetPixel( nSalColor ) );
800
801 XDrawPoint( pDisplay, GetDrawable(), pGC, nX, nY );
802
803 if( nSalColor != nPenColor_ )
804 XSetForeground( pDisplay, pGC, nPenPixel_ );
805 }
806 }
807 }
808
809 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawLine(long nX1,long nY1,long nX2,long nY2)810 void X11SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
811 {
812 if( nPenColor_ != SALCOLOR_NONE )
813 {
814 if ( GetDisplay()->GetProperties() & PROPERTY_BUG_DrawLine )
815 {
816 GC aGC = SelectPen();
817 XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX1, (int)nY1);
818 XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX2, (int)nY2);
819 XDrawLine (GetXDisplay(), GetDrawable(), aGC, nX1, nY1, nX2, nY2 );
820 }
821 else
822 XDrawLine( GetXDisplay(), GetDrawable(),SelectPen(),
823 nX1, nY1, nX2, nY2 );
824 }
825 }
826
827 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawRect(long nX,long nY,long nDX,long nDY)828 void X11SalGraphics::drawRect( long nX, long nY, long nDX, long nDY )
829 {
830 if( nBrushColor_ != SALCOLOR_NONE )
831 {
832 XFillRectangle( GetXDisplay(),
833 GetDrawable(),
834 SelectBrush(),
835 nX, nY, nDX, nDY );
836 }
837 // Beschreibung DrawRect verkehrt, deshalb -1
838 if( nPenColor_ != SALCOLOR_NONE )
839 XDrawRectangle( GetXDisplay(),
840 GetDrawable(),
841 SelectPen(),
842 nX, nY, nDX-1, nDY-1 );
843 }
844
845 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawPolyLine(sal_uInt32 nPoints,const SalPoint * pPtAry)846 void X11SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry )
847 {
848 drawPolyLine( nPoints, pPtAry, false );
849 }
850
851 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawPolyLine(sal_uInt32 nPoints,const SalPoint * pPtAry,bool bClose)852 void X11SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry, bool bClose )
853 {
854 if( nPenColor_ != SALCOLOR_NONE)
855 {
856 SalPolyLine Points( nPoints, pPtAry );
857
858 DrawLines( nPoints, Points, SelectPen(), bClose );
859 }
860 }
861
862 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawPolygon(sal_uInt32 nPoints,const SalPoint * pPtAry)863 void X11SalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
864 {
865 if( nPoints == 0 )
866 return;
867
868 if( nPoints < 3 )
869 {
870 if( !bXORMode_ )
871 {
872 if( 1 == nPoints )
873 drawPixel( pPtAry[0].mnX, pPtAry[0].mnY );
874 else
875 drawLine( pPtAry[0].mnX, pPtAry[0].mnY,
876 pPtAry[1].mnX, pPtAry[1].mnY );
877 }
878 return;
879 }
880
881 SalPolyLine Points( nPoints, pPtAry );
882
883 nPoints++;
884
885 /* WORKAROUND: some Xservers (Xorg, VIA chipset in this case)
886 * do not draw the visible part of a polygon
887 * if it overlaps to the left of screen 0,y.
888 * This happens to be the case in the gradient drawn in the
889 * menubar background. workaround for the special case of
890 * of a rectangle overlapping to the left.
891 */
892 if( nPoints == 5 &&
893 Points[ 0 ].x == Points[ 1 ].x &&
894 Points[ 1 ].y == Points[ 2 ].y &&
895 Points[ 2 ].x == Points[ 3 ].x &&
896 Points[ 0 ].x == Points[ 4 ].x && Points[ 0 ].y == Points[ 4 ].y
897 )
898 {
899 bool bLeft = false;
900 bool bRight = false;
901 for(unsigned int i = 0; i < nPoints; i++ )
902 {
903 if( Points[i].x < 0 )
904 bLeft = true;
905 else
906 bRight= true;
907 }
908 if( bLeft && ! bRight )
909 return;
910 if( bLeft && bRight )
911 {
912 for( unsigned int i = 0; i < nPoints; i++ )
913 if( Points[i].x < 0 )
914 Points[i].x = 0;
915 }
916 }
917
918 if( nBrushColor_ != SALCOLOR_NONE )
919 XFillPolygon( GetXDisplay(),
920 GetDrawable(),
921 SelectBrush(),
922 &Points[0], nPoints,
923 Complex, CoordModeOrigin );
924
925 if( nPenColor_ != SALCOLOR_NONE)
926 DrawLines( nPoints, Points, SelectPen(), true );
927 }
928
929 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
drawPolyPolygon(sal_uInt32 nPoly,const sal_uInt32 * pPoints,PCONSTSALPOINT * pPtAry)930 void X11SalGraphics::drawPolyPolygon( sal_uInt32 nPoly,
931 const sal_uInt32 *pPoints,
932 PCONSTSALPOINT *pPtAry )
933 {
934 if( nBrushColor_ != SALCOLOR_NONE )
935 {
936 sal_uInt32 i, n;
937 XLIB_Region pXRegA = NULL;
938
939 for( i = 0; i < nPoly; i++ ) {
940 n = pPoints[i];
941 SalPolyLine Points( n, pPtAry[i] );
942 if( n > 2 )
943 {
944 XLIB_Region pXRegB = XPolygonRegion( &Points[0], n+1, WindingRule );
945 if( !pXRegA )
946 pXRegA = pXRegB;
947 else
948 {
949 XXorRegion( pXRegA, pXRegB, pXRegA );
950 XDestroyRegion( pXRegB );
951 }
952 }
953 }
954
955 if( pXRegA )
956 {
957 XRectangle aXRect;
958 XClipBox( pXRegA, &aXRect );
959
960 GC pGC = SelectBrush();
961 SetClipRegion( pGC, pXRegA ); // ??? doppelt
962 XDestroyRegion( pXRegA );
963 bBrushGC_ = sal_False;
964
965 XFillRectangle( GetXDisplay(),
966 GetDrawable(),
967 pGC,
968 aXRect.x, aXRect.y, aXRect.width, aXRect.height );
969 }
970 }
971
972 if( nPenColor_ != SALCOLOR_NONE )
973 for( sal_uInt32 i = 0; i < nPoly; i++ )
974 drawPolyLine( pPoints[i], pPtAry[i], true );
975 }
976
977 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
978
drawPolyLineBezier(sal_uInt32,const SalPoint *,const BYTE *)979 sal_Bool X11SalGraphics::drawPolyLineBezier( sal_uInt32, const SalPoint*, const BYTE* )
980 {
981 return sal_False;
982 }
983
984 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
985
drawPolygonBezier(sal_uInt32,const SalPoint *,const BYTE *)986 sal_Bool X11SalGraphics::drawPolygonBezier( sal_uInt32, const SalPoint*, const BYTE* )
987 {
988 return sal_False;
989 }
990
991 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
992
drawPolyPolygonBezier(sal_uInt32,const sal_uInt32 *,const SalPoint * const *,const BYTE * const *)993 sal_Bool X11SalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*,
994 const SalPoint* const*, const BYTE* const* )
995 {
996 return sal_False;
997 }
998
999 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1000
invert(sal_uInt32 nPoints,const SalPoint * pPtAry,SalInvert nFlags)1001 void X11SalGraphics::invert( sal_uInt32 nPoints,
1002 const SalPoint* pPtAry,
1003 SalInvert nFlags )
1004 {
1005 SalPolyLine Points ( nPoints, pPtAry );
1006
1007 GC pGC;
1008 if( SAL_INVERT_50 & nFlags )
1009 pGC = GetInvert50GC();
1010 else
1011 if ( SAL_INVERT_TRACKFRAME & nFlags )
1012 pGC = GetTrackingGC();
1013 else
1014 pGC = GetInvertGC();
1015
1016 if( SAL_INVERT_TRACKFRAME & nFlags )
1017 DrawLines ( nPoints, Points, pGC, true );
1018 else
1019 XFillPolygon( GetXDisplay(),
1020 GetDrawable(),
1021 pGC,
1022 &Points[0], nPoints,
1023 Complex, CoordModeOrigin );
1024 }
1025
1026 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1027
drawEPS(long,long,long,long,void *,sal_uLong)1028 BOOL X11SalGraphics::drawEPS( long,long,long,long,void*,sal_uLong )
1029 {
1030 return sal_False;
1031 }
1032
1033 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1034
GetXRenderPicture()1035 XID X11SalGraphics::GetXRenderPicture()
1036 {
1037 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
1038
1039 if( !m_aRenderPicture )
1040 {
1041 // check xrender support for matching visual
1042 // find a XRenderPictFormat compatible with the Drawable
1043 XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat());
1044 if( !pVisualFormat )
1045 {
1046 Visual* pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual();
1047 pVisualFormat = rRenderPeer.FindVisualFormat( pVisual );
1048 if( !pVisualFormat )
1049 return 0;
1050 // cache the XRenderPictFormat
1051 SetXRenderFormat( static_cast<void*>(pVisualFormat) );
1052 }
1053
1054 // get the matching xrender target for drawable
1055 m_aRenderPicture = rRenderPeer.CreatePicture( hDrawable_, pVisualFormat, 0, NULL );
1056 }
1057
1058 #if 0
1059 // setup clipping so the callers don't have to do it themselves
1060 // TODO: avoid clipping if already set correctly
1061 if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
1062 rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
1063 else
1064 #endif
1065 {
1066 // reset clip region
1067 // TODO: avoid clip reset if already done
1068 XRenderPictureAttributes aAttr;
1069 aAttr.clip_mask = None;
1070 rRenderPeer.ChangePicture( m_aRenderPicture, CPClipMask, &aAttr );
1071 }
1072
1073 return m_aRenderPicture;
1074 }
1075
1076 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1077
GetGraphicsData() const1078 SystemGraphicsData X11SalGraphics::GetGraphicsData() const
1079 {
1080 SystemGraphicsData aRes;
1081
1082 aRes.nSize = sizeof(aRes);
1083 aRes.pDisplay = GetXDisplay();
1084 aRes.hDrawable = hDrawable_;
1085 aRes.pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual();
1086 aRes.nScreen = m_nScreen;
1087 aRes.nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth();
1088 aRes.aColormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap();
1089 aRes.pRenderFormat = m_pRenderFormat;
1090 return aRes;
1091 }
1092
1093 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1094
1095 // draw a poly-polygon
drawPolyPolygon(const::basegfx::B2DPolyPolygon & rOrigPolyPoly,double fTransparency)1096 bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency )
1097 {
1098 // nothing to do for empty polypolygons
1099 const int nOrigPolyCount = rOrigPolyPoly.count();
1100 if( nOrigPolyCount <= 0 )
1101 return sal_True;
1102
1103 // nothing to do if everything is transparent
1104 if( (nBrushColor_ == SALCOLOR_NONE)
1105 && (nPenColor_ == SALCOLOR_NONE) )
1106 return sal_True;
1107
1108 // cannot handle pencolor!=brushcolor yet
1109 if( (nPenColor_ != SALCOLOR_NONE)
1110 && (nPenColor_ != nBrushColor_) )
1111 return sal_False;
1112
1113 // TODO: remove the env-variable when no longer needed
1114 static const char* pRenderEnv = getenv( "SAL_DISABLE_RENDER_POLY" );
1115 if( pRenderEnv )
1116 return sal_False;
1117
1118 // snap to raster if requested
1119 basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly;
1120 const bool bSnapToRaster = !getAntiAliasB2DDraw();
1121 if( bSnapToRaster )
1122 aPolyPoly = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly );
1123
1124 // don't bother with polygons outside of visible area
1125 const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() );
1126 aPolyPoly = basegfx::tools::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false );
1127 if( !aPolyPoly.count() )
1128 return true;
1129
1130 // tesselate the polypolygon into trapezoids
1131 basegfx::B2DTrapezoidVector aB2DTrapVector;
1132 basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aPolyPoly );
1133 const int nTrapCount = aB2DTrapVector.size();
1134 if( !nTrapCount )
1135 return true;
1136 const bool bDrawn = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency );
1137 return bDrawn;
1138 }
1139
1140 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1141
drawFilledTrapezoids(const::basegfx::B2DTrapezoid * pB2DTraps,int nTrapCount,double fTransparency)1142 bool X11SalGraphics::drawFilledTrapezoids( const ::basegfx::B2DTrapezoid* pB2DTraps, int nTrapCount, double fTransparency )
1143 {
1144 if( nTrapCount <= 0 )
1145 return true;
1146
1147 Picture aDstPic = GetXRenderPicture();
1148 // check xrender support for this drawable
1149 if( !aDstPic )
1150 return false;
1151
1152 // convert the B2DTrapezoids into XRender-Trapezoids
1153 typedef std::vector<XTrapezoid> TrapezoidVector;
1154 TrapezoidVector aTrapVector( nTrapCount );
1155 const basegfx::B2DTrapezoid* pB2DTrap = pB2DTraps;
1156 for( int i = 0; i < nTrapCount; ++pB2DTrap, ++i )
1157 {
1158 XTrapezoid& rTrap = aTrapVector[ i ] ;
1159
1160 // set y-coordinates
1161 const double fY1 = pB2DTrap->getTopY();
1162 rTrap.left.p1.y = rTrap.right.p1.y = rTrap.top = XDoubleToFixed( fY1 );
1163 const double fY2 = pB2DTrap->getBottomY();
1164 rTrap.left.p2.y = rTrap.right.p2.y = rTrap.bottom = XDoubleToFixed( fY2 );
1165
1166 // set x-coordinates
1167 const double fXL1 = pB2DTrap->getTopXLeft();
1168 rTrap.left.p1.x = XDoubleToFixed( fXL1 );
1169 const double fXR1 = pB2DTrap->getTopXRight();
1170 rTrap.right.p1.x = XDoubleToFixed( fXR1 );
1171 const double fXL2 = pB2DTrap->getBottomXLeft();
1172 rTrap.left.p2.x = XDoubleToFixed( fXL2 );
1173 const double fXR2 = pB2DTrap->getBottomXRight();
1174 rTrap.right.p2.x = XDoubleToFixed( fXR2 );
1175 }
1176
1177 // get xrender Picture for polygon foreground
1178 // TODO: cache it like the target picture which uses GetXRenderPicture()
1179 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
1180 SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nScreen )[ 32 ];
1181 if( !rEntry.m_aPicture )
1182 {
1183 Display* pXDisplay = GetXDisplay();
1184
1185 rEntry.m_aPixmap = ::XCreatePixmap( pXDisplay, hDrawable_, 1, 1, 32 );
1186 XRenderPictureAttributes aAttr;
1187 aAttr.repeat = true;
1188
1189 XRenderPictFormat* pXRPF = rRenderPeer.FindStandardFormat( PictStandardARGB32 );
1190 rEntry.m_aPicture = rRenderPeer.CreatePicture( rEntry.m_aPixmap, pXRPF, CPRepeat, &aAttr );
1191 }
1192
1193 // set polygon foreground color and opacity
1194 XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency );
1195 rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 );
1196
1197 // set clipping
1198 // TODO: move into GetXRenderPicture?
1199 if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
1200 rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
1201
1202 // render the trapezoids
1203 const XRenderPictFormat* pMaskFormat = rRenderPeer.GetStandardFormatA8();
1204 rRenderPeer.CompositeTrapezoids( PictOpOver,
1205 rEntry.m_aPicture, aDstPic, pMaskFormat, 0, 0, &aTrapVector[0], aTrapVector.size() );
1206
1207 return true;
1208 }
1209
1210 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1211
drawPolyLine(const::basegfx::B2DPolygon & rPolygon,double fTransparency,const::basegfx::B2DVector & rLineWidth,basegfx::B2DLineJoin eLineJoin,com::sun::star::drawing::LineCap eLineCap)1212 bool X11SalGraphics::drawPolyLine(
1213 const ::basegfx::B2DPolygon& rPolygon,
1214 double fTransparency,
1215 const ::basegfx::B2DVector& rLineWidth,
1216 basegfx::B2DLineJoin eLineJoin,
1217 com::sun::star::drawing::LineCap eLineCap)
1218 {
1219 const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2);
1220
1221 // #i101491#
1222 if( !bIsHairline && (rPolygon.count() > 1000) )
1223 {
1224 // the used basegfx::tools::createAreaGeometry is simply too
1225 // expensive with very big polygons; fallback to caller (who
1226 // should use ImplLineConverter normally)
1227 // AW: ImplLineConverter had to be removed since it does not even
1228 // know LineJoins, so the fallback will now prepare the line geometry
1229 // the same way.
1230 return false;
1231 }
1232
1233 // temporarily adjust brush color to pen color
1234 // since the line is drawn as an area-polygon
1235 const SalColor aKeepBrushColor = nBrushColor_;
1236 nBrushColor_ = nPenColor_;
1237
1238 // #i11575#desc5#b adjust B2D tesselation result to raster positions
1239 basegfx::B2DPolygon aPolygon = rPolygon;
1240 const double fHalfWidth = 0.5 * rLineWidth.getX();
1241
1242 // #122456# This is probably thought to happen to align hairlines to pixel positions, so
1243 // it should be a 0.5 translation, not more. It will definitely go wrong with fat lines
1244 aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5) );
1245
1246 // shortcut for hairline drawing to improve performance
1247 bool bDrawnOk = true;
1248 if( bIsHairline )
1249 {
1250 // hairlines can benefit from a simplified tesselation
1251 // e.g. for hairlines the linejoin style can be ignored
1252 basegfx::B2DTrapezoidVector aB2DTrapVector;
1253 basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() );
1254
1255 // draw tesselation result
1256 const int nTrapCount = aB2DTrapVector.size();
1257 if( nTrapCount > 0 )
1258 bDrawnOk = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency );
1259
1260 // restore the original brush GC
1261 nBrushColor_ = aKeepBrushColor;
1262 return bDrawnOk;
1263 }
1264
1265 // get the area polygon for the line polygon
1266 if( (rLineWidth.getX() != rLineWidth.getY())
1267 && !basegfx::fTools::equalZero( rLineWidth.getY() ) )
1268 {
1269 // prepare for createAreaGeometry() with anisotropic linewidth
1270 aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY()));
1271 }
1272
1273 // create the area-polygon for the line
1274 const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) );
1275
1276 if( (rLineWidth.getX() != rLineWidth.getY())
1277 && !basegfx::fTools::equalZero( rLineWidth.getX() ) )
1278 {
1279 // postprocess createAreaGeometry() for anisotropic linewidth
1280 aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX()));
1281 }
1282
1283 // draw each area polypolygon component individually
1284 // to emulate the polypolygon winding rule "non-zero"
1285 const int nPolyCount = aAreaPolyPoly.count();
1286 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
1287 {
1288 const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) );
1289 bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency );
1290 if( !bDrawnOk )
1291 break;
1292 }
1293
1294 // restore the original brush GC
1295 nBrushColor_ = aKeepBrushColor;
1296 return bDrawnOk;
1297 }
1298
1299 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1300
1301