nss: upgrade to release 3.73
[LibreOffice.git] / vcl / unx / generic / gdi / salgdi.cxx
blobb5bb273b2bf22261dc8505ec3b8ea48b6734af55
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/extensions/Xrender.h>
25 #include <basegfx/polygon/b2dpolygon.hxx>
26 #include <basegfx/polygon/b2dpolypolygon.hxx>
27 #include <basegfx/polygon/b2dpolypolygontools.hxx>
28 #include <basegfx/matrix/b2dhommatrix.hxx>
29 #include <basegfx/curve/b2dcubicbezier.hxx>
31 #include <headless/svpgdi.hxx>
33 #include <vcl/sysdata.hxx>
34 #include <vcl/virdev.hxx>
35 #include <sal/log.hxx>
37 #include <unx/salunx.h>
38 #include <unx/saldisp.hxx>
39 #include <unx/salgdi.h>
40 #include <unx/x11/xlimits.hxx>
42 #include <salframe.hxx>
43 #include <salgdiimpl.hxx>
44 #include <textrender.hxx>
45 #include <salvd.hxx>
46 #include "gdiimpl.hxx"
47 #include <opengl/x11/gdiimpl.hxx>
48 #include <unx/x11/x11cairotextrender.hxx>
49 #include <opengl/x11/cairotextrender.hxx>
51 #include <unx/x11/xrender_peer.hxx>
52 #include "cairo_xlib_cairo.hxx"
53 #include <cairo-xlib.h>
55 #include <vcl/opengl/OpenGLHelper.hxx>
57 #include <config_features.h>
58 #include <vcl/skia/SkiaHelper.hxx>
59 #if HAVE_FEATURE_SKIA
60 #include <skia/x11/gdiimpl.hxx>
61 #include <skia/x11/textrender.hxx>
62 #endif
64 X11SalGraphics::X11SalGraphics():
65 m_pFrame(nullptr),
66 m_pVDev(nullptr),
67 m_pColormap(nullptr),
68 hDrawable_(None),
69 m_pExternalSurface(nullptr),
70 m_nXScreen( 0 ),
71 m_pXRenderFormat(nullptr),
72 m_aXRenderPicture(0),
73 mpClipRegion(nullptr),
74 #if ENABLE_CAIRO_CANVAS
75 maClipRegion(),
76 mnPenColor(SALCOLOR_NONE),
77 mnFillColor(SALCOLOR_NONE),
78 #endif // ENABLE_CAIRO_CANVAS
79 hBrush_(None),
80 bWindow_(false),
81 bVirDev_(false),
82 m_bOpenGL(OpenGLHelper::isVCLOpenGLEnabled()),
83 m_bSkia(SkiaHelper::isVCLSkiaEnabled())
85 #if HAVE_FEATURE_SKIA
86 if (m_bSkia)
88 mxImpl.reset(new X11SkiaSalGraphicsImpl(*this));
89 mxTextRenderImpl.reset(new SkiaTextRender);
91 else
92 #endif
93 if (m_bOpenGL)
95 mxImpl.reset(new X11OpenGLSalGraphicsImpl(*this));
96 mxTextRenderImpl.reset(new OpenGLX11CairoTextRender(*this));
98 else
100 mxTextRenderImpl.reset(new X11CairoTextRender(*this));
101 mxImpl.reset(new X11SalGraphicsImpl(*this));
106 X11SalGraphics::~X11SalGraphics() COVERITY_NOEXCEPT_FALSE
108 DeInit();
109 ReleaseFonts();
110 freeResources();
113 void X11SalGraphics::freeResources()
115 Display *pDisplay = GetXDisplay();
117 if( mpClipRegion )
119 XDestroyRegion( mpClipRegion );
120 mpClipRegion = None;
123 mxImpl->freeResources();
125 if( hBrush_ )
127 XFreePixmap( pDisplay, hBrush_ );
128 hBrush_ = None;
130 if( m_pDeleteColormap )
132 m_pDeleteColormap.reset();
133 m_pColormap = nullptr;
135 if( m_aXRenderPicture )
137 XRenderPeer::GetInstance().FreePicture( m_aXRenderPicture );
138 m_aXRenderPicture = 0;
142 SalGraphicsImpl* X11SalGraphics::GetImpl() const
144 return mxImpl.get();
147 void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* pExternalSurface, SalX11Screen nXScreen)
149 m_pExternalSurface = pExternalSurface;
151 // shortcut if nothing changed
152 if( hDrawable_ == aDrawable )
153 return;
155 // free screen specific resources if needed
156 if( nXScreen != m_nXScreen )
158 freeResources();
159 m_pColormap = &vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap( nXScreen );
160 m_nXScreen = nXScreen;
163 hDrawable_ = aDrawable;
164 SetXRenderFormat( nullptr );
165 if( m_aXRenderPicture )
167 XRenderPeer::GetInstance().FreePicture( m_aXRenderPicture );
168 m_aXRenderPicture = 0;
172 void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
173 SalX11Screen nXScreen )
175 m_pColormap = &vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap(nXScreen);
176 m_nXScreen = nXScreen;
178 m_pFrame = pFrame;
179 m_pVDev = nullptr;
181 bWindow_ = true;
182 bVirDev_ = false;
184 SetDrawable(aTarget, nullptr, nXScreen);
185 mxImpl->Init();
188 void X11SalGraphics::DeInit()
190 mxImpl->DeInit();
191 SetDrawable(None, nullptr, m_nXScreen);
194 void X11SalGraphics::SetClipRegion( GC pGC, Region pXReg ) const
196 Display *pDisplay = GetXDisplay();
198 int n = 0;
199 Region Regions[3];
201 if( mpClipRegion )
202 Regions[n++] = mpClipRegion;
204 if( pXReg && !XEmptyRegion( pXReg ) )
205 Regions[n++] = pXReg;
207 if( 0 == n )
208 XSetClipMask( pDisplay, pGC, None );
209 else if( 1 == n )
210 XSetRegion( pDisplay, pGC, Regions[0] );
211 else
213 Region pTmpRegion = XCreateRegion();
214 XIntersectRegion( Regions[0], Regions[1], pTmpRegion );
216 XSetRegion( pDisplay, pGC, pTmpRegion );
217 XDestroyRegion( pTmpRegion );
221 // Calculate a dither-pixmap and make a brush of it
222 #define P_DELTA 51
223 #define DMAP( v, m ) ((v % P_DELTA) > m ? (v / P_DELTA) + 1 : (v / P_DELTA))
225 bool X11SalGraphics::GetDitherPixmap( Color nColor )
227 static const short nOrdDither8Bit[ 8 ][ 8 ] =
229 { 0, 38, 9, 48, 2, 40, 12, 50},
230 {25, 12, 35, 22, 28, 15, 37, 24},
231 { 6, 44, 3, 41, 8, 47, 5, 44},
232 {32, 19, 28, 16, 34, 21, 31, 18},
233 { 1, 40, 11, 49, 0, 39, 10, 48},
234 {27, 14, 36, 24, 26, 13, 36, 23},
235 { 8, 46, 4, 43, 7, 45, 4, 42},
236 {33, 20, 30, 17, 32, 20, 29, 16}
239 // test for correct depth (8bit)
240 if( GetColormap().GetVisual().GetDepth() != 8 )
241 return false;
243 char pBits[64];
244 char *pBitsPtr = pBits;
246 // Set the palette-entries for the dithering tile
247 sal_uInt8 nColorRed = nColor.GetRed();
248 sal_uInt8 nColorGreen = nColor.GetGreen();
249 sal_uInt8 nColorBlue = nColor.GetBlue();
251 for(auto & nY : nOrdDither8Bit)
253 for( int nX = 0; nX < 8; nX++ )
255 short nMagic = nY[nX];
256 sal_uInt8 nR = P_DELTA * DMAP( nColorRed, nMagic );
257 sal_uInt8 nG = P_DELTA * DMAP( nColorGreen, nMagic );
258 sal_uInt8 nB = P_DELTA * DMAP( nColorBlue, nMagic );
260 *pBitsPtr++ = GetColormap().GetPixel( Color( nR, nG, nB ) );
264 // create the tile as ximage and an according pixmap -> caching
265 XImage *pImage = XCreateImage( GetXDisplay(),
266 GetColormap().GetXVisual(),
268 ZPixmap,
269 0, // offset
270 pBits, // data
271 8, 8, // width & height
272 8, // bitmap_pad
273 0 ); // (default) bytes_per_line
275 if( !hBrush_ )
276 hBrush_ = limitXCreatePixmap( GetXDisplay(), GetDrawable(), 8, 8, 8 );
278 // put the ximage to the pixmap
279 XPutImage( GetXDisplay(),
280 hBrush_,
281 GetDisplay()->GetCopyGC( m_nXScreen ),
282 pImage,
283 0, 0, // Source
284 0, 0, // Destination
285 8, 8 ); // width & height
287 // destroy image-frame but not palette-data
288 pImage->data = nullptr;
289 XDestroyImage( pImage );
291 return true;
294 void X11SalGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY ) // const
296 char* pForceDpi;
297 if ((pForceDpi = getenv("SAL_FORCEDPI")))
299 OString sForceDPI(pForceDpi);
300 rDPIX = rDPIY = sForceDPI.toInt32();
301 return;
304 const SalDisplay *pDisplay = GetDisplay();
305 if (!pDisplay)
307 SAL_WARN( "vcl", "Null display");
308 rDPIX = rDPIY = 96;
309 return;
312 Pair dpi = pDisplay->GetResolution();
313 rDPIX = dpi.A();
314 rDPIY = dpi.B();
316 if ( rDPIY > 200 )
318 rDPIX = Divide( rDPIX * 200, rDPIY );
319 rDPIY = 200;
322 // #i12705# equalize x- and y-resolution if they are close enough
323 if( rDPIX == rDPIY )
324 return;
326 // different x- and y- resolutions are usually artifacts of
327 // a wrongly calculated screen size.
328 #ifdef DEBUG
329 SAL_INFO("vcl.gdi", "Forcing Resolution from "
330 << std::hex << rDPIX
331 << std::dec << rDPIX
332 << " to "
333 << std::hex << rDPIY
334 << std::dec << rDPIY);
335 #endif
336 rDPIX = rDPIY; // y-resolution is more trustworthy
339 sal_uInt16 X11SalGraphics::GetBitCount() const
341 return mxImpl->GetBitCount();
344 tools::Long X11SalGraphics::GetGraphicsWidth() const
346 return mxImpl->GetGraphicsWidth();
349 void X11SalGraphics::ResetClipRegion()
351 #if ENABLE_CAIRO_CANVAS
352 maClipRegion.SetNull();
353 #endif
354 mxImpl->ResetClipRegion();
357 bool X11SalGraphics::setClipRegion( const vcl::Region& i_rClip )
359 #if ENABLE_CAIRO_CANVAS
360 maClipRegion = i_rClip;
361 #endif
362 return mxImpl->setClipRegion( i_rClip );
365 void X11SalGraphics::SetLineColor()
367 #if ENABLE_CAIRO_CANVAS
368 mnPenColor = SALCOLOR_NONE;
369 #endif // ENABLE_CAIRO_CANVAS
371 mxImpl->SetLineColor();
374 void X11SalGraphics::SetLineColor( Color nColor )
376 #if ENABLE_CAIRO_CANVAS
377 mnPenColor = nColor;
378 #endif // ENABLE_CAIRO_CANVAS
380 mxImpl->SetLineColor( nColor );
383 void X11SalGraphics::SetFillColor()
385 #if ENABLE_CAIRO_CANVAS
386 mnFillColor = SALCOLOR_NONE;
387 #endif // ENABLE_CAIRO_CANVAS
389 mxImpl->SetFillColor();
392 void X11SalGraphics::SetFillColor( Color nColor )
394 #if ENABLE_CAIRO_CANVAS
395 mnFillColor = nColor;
396 #endif // ENABLE_CAIRO_CANVAS
398 mxImpl->SetFillColor( nColor );
401 void X11SalGraphics::SetROPLineColor( SalROPColor nROPColor )
403 mxImpl->SetROPLineColor( nROPColor );
406 void X11SalGraphics::SetROPFillColor( SalROPColor nROPColor )
408 mxImpl->SetROPFillColor( nROPColor );
411 void X11SalGraphics::SetXORMode( bool bSet, bool bInvertOnly )
413 mxImpl->SetXORMode( bSet, bInvertOnly );
416 void X11SalGraphics::drawPixel( tools::Long nX, tools::Long nY )
418 mxImpl->drawPixel( nX, nY );
421 void X11SalGraphics::drawPixel( tools::Long nX, tools::Long nY, Color nColor )
423 mxImpl->drawPixel( nX, nY, nColor );
426 void X11SalGraphics::drawLine( tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2 )
428 mxImpl->drawLine( nX1, nY1, nX2, nY2 );
431 void X11SalGraphics::drawRect( tools::Long nX, tools::Long nY, tools::Long nDX, tools::Long nDY )
433 mxImpl->drawRect( nX, nY, nDX, nDY );
436 void X11SalGraphics::drawPolyLine( sal_uInt32 nPoints, const Point *pPtAry )
438 mxImpl->drawPolyLine( nPoints, pPtAry );
441 void X11SalGraphics::drawPolygon( sal_uInt32 nPoints, const Point* pPtAry )
443 mxImpl->drawPolygon( nPoints, pPtAry );
446 void X11SalGraphics::drawPolyPolygon( sal_uInt32 nPoly,
447 const sal_uInt32 *pPoints,
448 const Point* *pPtAry )
450 mxImpl->drawPolyPolygon( nPoly, pPoints, pPtAry );
453 bool X11SalGraphics::drawPolyLineBezier( sal_uInt32 nPoints, const Point* pPtAry, const PolyFlags* pFlgAry )
455 return mxImpl->drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
458 bool X11SalGraphics::drawPolygonBezier( sal_uInt32 nPoints, const Point* pPtAry, const PolyFlags* pFlgAry )
460 return mxImpl->drawPolygonBezier( nPoints, pPtAry, pFlgAry );
463 bool X11SalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoints, const sal_uInt32* pPoints,
464 const Point* const* pPtAry, const PolyFlags* const* pFlgAry)
466 return mxImpl->drawPolyPolygonBezier( nPoints, pPoints, pPtAry, pFlgAry );
469 void X11SalGraphics::invert( sal_uInt32 nPoints,
470 const Point* pPtAry,
471 SalInvert nFlags )
473 mxImpl->invert( nPoints, pPtAry, nFlags );
476 bool X11SalGraphics::drawEPS( tools::Long nX, tools::Long nY, tools::Long nWidth,
477 tools::Long nHeight, void* pPtr, sal_uInt32 nSize )
479 return mxImpl->drawEPS( nX, nY, nWidth, nHeight, pPtr, nSize );
482 XRenderPictFormat* X11SalGraphics::GetXRenderFormat() const
484 if( m_pXRenderFormat == nullptr )
485 m_pXRenderFormat = XRenderPeer::GetInstance().FindVisualFormat( GetVisual().visual );
486 return m_pXRenderFormat;
489 SystemGraphicsData X11SalGraphics::GetGraphicsData() const
491 SystemGraphicsData aRes;
493 aRes.nSize = sizeof(aRes);
494 aRes.pDisplay = GetXDisplay();
495 aRes.hDrawable = hDrawable_;
496 aRes.pVisual = GetVisual().visual;
497 aRes.nScreen = m_nXScreen.getXScreen();
498 aRes.pXRenderFormat = m_pXRenderFormat;
499 return aRes;
502 void X11SalGraphics::Flush()
504 if( X11GraphicsImpl* x11Impl = dynamic_cast< X11GraphicsImpl* >( mxImpl.get()))
505 x11Impl->Flush();
508 #if ENABLE_CAIRO_CANVAS
510 bool X11SalGraphics::SupportsCairo() const
512 static bool bSupportsCairo = [this] {
513 Display *pDisplay = GetXDisplay();
514 int nDummy;
515 return XQueryExtension(pDisplay, "RENDER", &nDummy, &nDummy, &nDummy);
516 }();
517 return bSupportsCairo;
520 cairo::SurfaceSharedPtr X11SalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
522 return std::make_shared<cairo::X11Surface>(rSurface);
525 namespace
527 cairo::X11SysData getSysData( const vcl::Window& rWindow )
529 const SystemEnvData* pSysData = rWindow.GetSystemData();
531 if( !pSysData )
532 return cairo::X11SysData();
533 else
534 return cairo::X11SysData(*pSysData, rWindow.ImplGetFrame());
537 cairo::X11SysData getSysData( const VirtualDevice& rVirDev )
539 return cairo::X11SysData( rVirDev.GetSystemGfxData() );
543 cairo::SurfaceSharedPtr X11SalGraphics::CreateSurface( const OutputDevice& rRefDevice,
544 int x, int y, int width, int height ) const
546 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
547 return std::make_shared<cairo::X11Surface>(getSysData(static_cast<const vcl::Window&>(rRefDevice)),
548 x,y,width,height);
549 if( rRefDevice.IsVirtual() )
550 return std::make_shared<cairo::X11Surface>(getSysData(static_cast<const VirtualDevice&>(rRefDevice)),
551 x,y,width,height);
552 return cairo::SurfaceSharedPtr();
555 cairo::SurfaceSharedPtr X11SalGraphics::CreateBitmapSurface( const OutputDevice& rRefDevice,
556 const BitmapSystemData& rData,
557 const Size& rSize ) const
559 SAL_INFO("vcl", "requested size: " << rSize.Width() << " x " << rSize.Height()
560 << " available size: " << rData.mnWidth << " x "
561 << rData.mnHeight);
562 if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
564 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
565 return std::make_shared<cairo::X11Surface>(getSysData(static_cast<const vcl::Window&>(rRefDevice)), rData );
566 else if( rRefDevice.IsVirtual() )
567 return std::make_shared<cairo::X11Surface>(getSysData(static_cast<const VirtualDevice&>(rRefDevice)), rData );
570 return cairo::SurfaceSharedPtr();
573 css::uno::Any X11SalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& /*rSize*/) const
575 cairo::X11Surface& rXlibSurface=dynamic_cast<cairo::X11Surface&>(*rSurface);
576 css::uno::Sequence< css::uno::Any > args( 3 );
577 args[0] <<= false; // do not call XFreePixmap on it
578 args[1] <<= sal_Int64(rXlibSurface.getPixmap()->mhDrawable);
579 args[2] <<= sal_Int32( rXlibSurface.getDepth() );
580 return css::uno::Any(args);
583 #endif // ENABLE_CAIRO_CANVAS
585 // draw a poly-polygon
586 bool X11SalGraphics::drawPolyPolygon(
587 const basegfx::B2DHomMatrix& rObjectToDevice,
588 const basegfx::B2DPolyPolygon& rPolyPolygon,
589 double fTransparency)
591 if(fTransparency >= 1.0)
593 return true;
596 if(rPolyPolygon.count() == 0)
598 return true;
601 #if ENABLE_CAIRO_CANVAS
602 // Fallback: Transform to DeviceCoordinates
603 basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
604 aPolyPolygon.transform(rObjectToDevice);
606 if(SALCOLOR_NONE == mnFillColor && SALCOLOR_NONE == mnPenColor)
608 return true;
611 // enable by setting to something
612 static const char* pUseCairoForPolygons(getenv("SAL_ENABLE_USE_CAIRO_FOR_POLYGONS"));
614 if (!m_bOpenGL && !m_bSkia && nullptr != pUseCairoForPolygons && SupportsCairo())
616 // snap to raster if requested
617 const bool bSnapPoints(!getAntiAlias());
619 if(bSnapPoints)
621 aPolyPolygon = basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygon);
624 cairo_t* cr = getCairoContext();
625 clipRegion(cr);
627 for(auto const& rPolygon : aPolyPolygon)
629 const sal_uInt32 nPointCount(rPolygon.count());
631 if(nPointCount)
633 const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nPointCount : nPointCount - 1);
635 if(nEdgeCount)
637 basegfx::B2DCubicBezier aEdge;
639 for(sal_uInt32 b = 0; b < nEdgeCount; ++b)
641 rPolygon.getBezierSegment(b, aEdge);
643 if(!b)
645 const basegfx::B2DPoint aStart(aEdge.getStartPoint());
646 cairo_move_to(cr, aStart.getX(), aStart.getY());
649 const basegfx::B2DPoint aEnd(aEdge.getEndPoint());
651 if(aEdge.isBezier())
653 const basegfx::B2DPoint aCP1(aEdge.getControlPointA());
654 const basegfx::B2DPoint aCP2(aEdge.getControlPointB());
655 cairo_curve_to(cr,
656 aCP1.getX(), aCP1.getY(),
657 aCP2.getX(), aCP2.getY(),
658 aEnd.getX(), aEnd.getY());
660 else
662 cairo_line_to(cr, aEnd.getX(), aEnd.getY());
666 cairo_close_path(cr);
671 if(SALCOLOR_NONE != mnFillColor)
673 cairo_set_source_rgba(cr,
674 mnFillColor.GetRed()/255.0,
675 mnFillColor.GetGreen()/255.0,
676 mnFillColor.GetBlue()/255.0,
677 1.0 - fTransparency);
678 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
679 cairo_fill_preserve(cr);
682 if(SALCOLOR_NONE != mnPenColor)
684 cairo_set_source_rgba(cr,
685 mnPenColor.GetRed()/255.0,
686 mnPenColor.GetGreen()/255.0,
687 mnPenColor.GetBlue()/255.0,
688 1.0 - fTransparency);
689 cairo_stroke_preserve(cr);
692 releaseCairoContext(cr);
693 return true;
695 #endif // ENABLE_CAIRO_CANVAS
697 return mxImpl->drawPolyPolygon(
698 rObjectToDevice,
699 rPolyPolygon,
700 fTransparency);
703 #if ENABLE_CAIRO_CANVAS
704 void X11SalGraphics::clipRegion(cairo_t* cr)
706 SvpSalGraphics::clipRegion(cr, maClipRegion);
708 #endif // ENABLE_CAIRO_CANVAS
710 bool X11SalGraphics::drawPolyLine(
711 const basegfx::B2DHomMatrix& rObjectToDevice,
712 const basegfx::B2DPolygon& rPolygon,
713 double fTransparency,
714 double fLineWidth,
715 const std::vector< double >* pStroke, // MM01
716 basegfx::B2DLineJoin eLineJoin,
717 css::drawing::LineCap eLineCap,
718 double fMiterMinimumAngle,
719 bool bPixelSnapHairline)
721 if(0 == rPolygon.count())
723 return true;
726 if(fTransparency >= 1.0)
728 return true;
731 #if ENABLE_CAIRO_CANVAS
732 // disable by setting to something
733 static const char* pUseCairoForFatLines(getenv("SAL_DISABLE_USE_CAIRO_FOR_FATLINES"));
735 if (!m_bOpenGL && !m_bSkia && nullptr == pUseCairoForFatLines && SupportsCairo())
737 cairo_t* cr = getCairoContext();
738 clipRegion(cr);
740 // Use the now available static drawPolyLine from the Cairo-Headless-Fallback
741 // that will take care of all needed stuff
742 const bool bRetval(
743 SvpSalGraphics::drawPolyLine(
745 nullptr,
746 mnPenColor,
747 getAntiAlias(),
748 rObjectToDevice,
749 rPolygon,
750 fTransparency,
751 fLineWidth,
752 pStroke, // MM01
753 eLineJoin,
754 eLineCap,
755 fMiterMinimumAngle,
756 bPixelSnapHairline));
758 releaseCairoContext(cr);
760 if(bRetval)
762 return true;
765 #endif // ENABLE_CAIRO_CANVAS
767 return mxImpl->drawPolyLine(
768 rObjectToDevice,
769 rPolygon,
770 fTransparency,
771 fLineWidth,
772 pStroke, // MM01
773 eLineJoin,
774 eLineCap,
775 fMiterMinimumAngle,
776 bPixelSnapHairline);
779 bool X11SalGraphics::drawGradient(const tools::PolyPolygon& rPoly, const Gradient& rGradient)
781 return mxImpl->drawGradient(rPoly, rGradient);
784 bool X11SalGraphics::implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient)
786 return mxImpl->implDrawGradient(rPolyPolygon, rGradient);
789 SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const
791 if (m_pFrame)
792 return static_cast< SalGeometryProvider * >(m_pFrame);
793 else
794 return static_cast< SalGeometryProvider * >(m_pVDev);
797 cairo_t* X11SalGraphics::getCairoContext()
799 if (m_pExternalSurface)
800 return cairo_create(m_pExternalSurface);
802 cairo_surface_t* surface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_,
803 GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
805 cairo_t *cr = cairo_create(surface);
806 cairo_surface_destroy(surface);
808 return cr;
811 void X11SalGraphics::releaseCairoContext(cairo_t* cr)
813 cairo_destroy(cr);
816 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */