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