xref: /AOO41X/main/vcl/unx/generic/gdi/salgdi.cxx (revision 54ae6a3709853714848b4c639248f08787cf46a5)
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