diff options
author | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-10-21 15:15:47 +0200 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-10-22 17:23:39 +0200 |
commit | 492768e3a4e9d497d4b6784ab59f239301542eea (patch) | |
tree | 9ac53d57c8edbc26f433706ecf032893808a92d3 | |
parent | 68a6645f6d625bcff56ea93294754a9a695b01e0 (diff) |
use Impl for unix vcl plugins
Change-Id: I110df787e1d4b817ab6e682fd9bf50a24332fafd
-rw-r--r-- | vcl/Library_vclplug_gen.mk | 1 | ||||
-rw-r--r-- | vcl/inc/salgdiimpl.hxx | 22 | ||||
-rw-r--r-- | vcl/inc/unx/salgdi.h | 62 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/gdiimpl.cxx | 1779 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/gdiimpl.hxx | 262 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi.cxx | 842 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi2.cxx | 769 |
7 files changed, 2124 insertions, 1613 deletions
diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk index c3f00aa4eef2..634fa741caa6 100644 --- a/vcl/Library_vclplug_gen.mk +++ b/vcl/Library_vclplug_gen.mk @@ -84,6 +84,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\ vcl/unx/generic/dtrans/X11_service \ vcl/unx/generic/dtrans/X11_transferable \ vcl/unx/generic/gdi/gcach_xpeer \ + vcl/unx/generic/gdi/gdiimpl \ vcl/unx/generic/gdi/salbmp \ vcl/unx/generic/gdi/salgdi2 \ vcl/unx/generic/gdi/salgdi3 \ diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx index 58d6c1a7f600..737524002b0b 100644 --- a/vcl/inc/salgdiimpl.hxx +++ b/vcl/inc/salgdiimpl.hxx @@ -36,39 +36,41 @@ public: virtual ~SalGraphicsImpl(); + virtual void freeResources() = 0; + virtual bool setClipRegion( const vcl::Region& ) = 0; // // get the depth of the device - virtual sal_uInt16 GetBitCount() const = 0; + virtual sal_uInt16 GetBitCount() const = 0; // get the width of the device - virtual long GetGraphicsWidth() const = 0; + virtual long GetGraphicsWidth() const = 0; // set the clip region to empty - virtual void ResetClipRegion() = 0; + virtual void ResetClipRegion() = 0; // set the line color to transparent (= don't draw lines) - virtual void SetLineColor() = 0; + virtual void SetLineColor() = 0; // set the line color to a specific color - virtual void SetLineColor( SalColor nSalColor ) = 0; + virtual void SetLineColor( SalColor nSalColor ) = 0; // set the fill color to transparent (= don't fill) - virtual void SetFillColor() = 0; + virtual void SetFillColor() = 0; // set the fill color to a specific color, shapes will be // filled accordingly - virtual void SetFillColor( SalColor nSalColor ) = 0; + virtual void SetFillColor( SalColor nSalColor ) = 0; // enable/disable XOR drawing - virtual void SetXORMode( bool bSet, bool bInvertOnly ) = 0; + virtual void SetXORMode( bool bSet, bool bInvertOnly ) = 0; // set line color for raster operations - virtual void SetROPLineColor( SalROPColor nROPColor ) = 0; + virtual void SetROPLineColor( SalROPColor nROPColor ) = 0; // set fill color for raster operations - virtual void SetROPFillColor( SalROPColor nROPColor ) = 0; + virtual void SetROPFillColor( SalROPColor nROPColor ) = 0; // draw --> LineColor and FillColor and RasterOp and ClipRegion virtual void drawPixel( long nX, long nY ) = 0; diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index d34c5d1a9d27..0d1a58427505 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -41,7 +41,7 @@ class SalColormap; class SalDisplay; class SalFrame; class X11SalVirtualDevice; -class SalPolyLine; +class X11SalGraphicsImpl; class PspSalPrinter; class PspSalInfoPrinter; class ServerFont; @@ -49,6 +49,7 @@ class ImplLayoutArgs; class ServerFontLayout; class PhysicalFontCollection; class PhysicalFontFace; +class SalGraphicsImpl; namespace basegfx { class B2DTrapezoid; @@ -86,7 +87,12 @@ public: class VCLPLUG_GEN_PUBLIC X11SalGraphics : public SalGraphics { - friend class ServerFontLayout; + friend class ServerFontLayout; + friend class X11SalGraphicsImpl; + +private: + SalGraphicsImpl* mpImpl; + protected: SalFrame* m_pFrame; // the SalFrame which created this Graphics or NULL X11SalVirtualDevice* m_pVDev; // the SalVirtualDevice which created this Graphics or NULL @@ -102,10 +108,6 @@ protected: Region pPaintRegion_; Region mpClipRegion; - GC pPenGC_; // Pen attributes - SalColor nPenColor_; - Pixel nPenPixel_; - GC pFontGC_; // Font attributes ServerFont* mpServerFont[ MAX_FALLBACK ]; @@ -114,55 +116,19 @@ protected: bool bDisableGraphite_; - GC pBrushGC_; // Brush attributes - SalColor nBrushColor_; - Pixel nBrushPixel_; Pixmap hBrush_; // Dither - GC pMonoGC_; - GC pCopyGC_; - GC pMaskGC_; - GC pInvertGC_; - GC pInvert50GC_; - GC pStippleGC_; - GC pTrackingGC_; - bool bWindow_ : 1; // is Window bool bPrinter_ : 1; // is Printer bool bVirDev_ : 1; // is VirDev - bool bPenGC_ : 1; // is Pen GC valid - bool bFontGC_ : 1; // is Font GC valid - bool bBrushGC_ : 1; // is Brush GC valid - bool bMonoGC_ : 1; // is Mono GC valid - bool bCopyGC_ : 1; // is Copy GC valid - bool bInvertGC_ : 1; // is Invert GC valid - bool bInvert50GC_ : 1; // is Invert50 GC valid - bool bStippleGC_ : 1; // is Stipple GC valid - bool bTrackingGC_ : 1; // is Tracking GC valid - bool bXORMode_ : 1; // is ROP XOR Mode set - bool bDitherBrush_ : 1; // is solid or tile + bool bFontGC_ : 1; // is Font GC valid using SalGraphics::SetClipRegion; void SetClipRegion( GC pGC, Region pXReg = NULL ) const; - GC GetTrackingGC(); - GC GetInvertGC(); - GC GetInvert50GC(); - GC CreateGC( Drawable hDrawable, - unsigned long nMask = GCGraphicsExposures ); - GC SelectPen(); - GC SelectBrush(); - void DrawLines( sal_uIntPtr nPoints, - const SalPolyLine &rPoints, - GC pGC, - bool bClose - ); bool GetDitherPixmap ( SalColor nSalColor ); - inline GC GetMonoGC( Pixmap hPixmap ); - inline GC GetCopyGC(); - inline GC GetStippleGC(); using SalGraphics::DrawBitmap; void DrawBitmap( const SalTwoRect& rPosAry, @@ -174,10 +140,6 @@ protected: GC GetFontGC(); bool setFont( const FontSelectPattern* pEntry, int nFallbackLevel ); - void drawMaskedBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - const SalBitmap& rTransparentBitmap ); - protected: void DrawPrinterString( const SalLayout& ); @@ -198,12 +160,11 @@ public: inline const SalVisual& GetVisual() const; inline Drawable GetDrawable() const { return hDrawable_; } void SetDrawable( Drawable d, SalX11Screen nXScreen ); - XID GetXRenderPicture(); XRenderPictFormat* GetXRenderFormat() const; inline void SetXRenderFormat( XRenderPictFormat* pXRenderFormat ) { m_pXRenderFormat = pXRenderFormat; } inline const SalColormap& GetColormap() const { return *m_pColormap; } using SalGraphics::GetPixel; - inline Pixel GetPixel( SalColor nSalColor ) const; + inline Pixel GetPixel( SalColor nSalColor ) const; SalX11Screen GetScreenNumber() const { return m_nXScreen; } @@ -211,7 +172,6 @@ public: virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) SAL_OVERRIDE; virtual sal_uInt16 GetBitCount() const SAL_OVERRIDE; virtual long GetGraphicsWidth() const SAL_OVERRIDE; - virtual long GetGraphicsHeight() const; virtual void ResetClipRegion() SAL_OVERRIDE; virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE; @@ -263,7 +223,6 @@ public: virtual void drawPixel( long nX, long nY, SalColor nSalColor ) SAL_OVERRIDE; virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ) SAL_OVERRIDE; virtual void drawRect( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ); virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; virtual void drawPolyPolygon( sal_uInt32 nPoly, @@ -276,7 +235,6 @@ public: const ::basegfx::B2DVector& rLineWidth, basegfx::B2DLineJoin, com::sun::star::drawing::LineCap) SAL_OVERRIDE; - virtual bool drawFilledTrapezoids( const ::basegfx::B2DTrapezoid*, int nTrapCount, double fTransparency ); #if 1 // TODO: remove these obselete methods virtual bool drawPolyLineBezier( sal_uInt32 nPoints, diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx new file mode 100644 index 000000000000..e95bee51363f --- /dev/null +++ b/vcl/unx/generic/gdi/gdiimpl.cxx @@ -0,0 +1,1779 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <prex.h> +#include <X11/Xproto.h> +#include <postx.h> + +#include "gdiimpl.hxx" + +#include "vcl/salbtype.hxx" + +#include "unx/salunx.h" +#include "unx/saldata.hxx" +#include "unx/saldisp.hxx" +#include "unx/salbmp.h" +#include "unx/salgdi.h" +#include "unx/salframe.h" +#include "unx/salvd.h" +#include <unx/x11/xlimits.hxx> +#include "xrender_peer.hxx" + +#include "outdata.hxx" + +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/polygon/b2dpolypolygon.hxx" +#include "basegfx/polygon/b2dpolypolygontools.hxx" +#include "basegfx/polygon/b2dpolygontools.hxx" +#include "basegfx/polygon/b2dpolygonclipper.hxx" +#include "basegfx/polygon/b2dlinegeometry.hxx" +#include "basegfx/matrix/b2dhommatrix.hxx" +#include "basegfx/matrix/b2dhommatrixtools.hxx" +#include "basegfx/polygon/b2dpolypolygoncutter.hxx" +#include "basegfx/polygon/b2dtrapezoid.hxx" + +#undef SALGDI2_TESTTRANS + +#if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS +#define DBG_TESTTRANS( _def_drawable ) \ +{ \ + XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \ + 0, 0, \ + rPosAry.mnDestWidth, rPosAry.mnDestHeight, \ + 0, 0 ); \ +} +#else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS +#define DBG_TESTTRANS( _def_drawable ) +#endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS + +#define STATIC_POINTS 64 + +class SalPolyLine +{ + XPoint Points_[STATIC_POINTS]; + XPoint *pFirst_; +public: + SalPolyLine(sal_uLong nPoints, const SalPoint *p) + : pFirst_(nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_) + { + for( sal_uLong i = 0; i < nPoints; i++ ) + { + pFirst_[i].x = (short)p[i].mnX; + pFirst_[i].y = (short)p[i].mnY; + } + pFirst_[nPoints] = pFirst_[0]; // close polyline + } + + ~SalPolyLine() + { + if( pFirst_ != Points_ ) + delete [] pFirst_; + } + + XPoint &operator [] ( sal_uLong n ) const + { + return pFirst_[n]; + } +}; + +#undef STATIC_POINTS + +namespace +{ + void setForeBack(XGCValues& rValues, const SalColormap& rColMap, const SalBitmap& rSalBitmap) + { + rValues.foreground = rColMap.GetWhitePixel(); + rValues.background = rColMap.GetBlackPixel(); + + //fdo#33455 and fdo#80160 handle 1 bit depth pngs with palette entries + //to set fore/back colors + SalBitmap& rBitmap = const_cast<SalBitmap&>(rSalBitmap); + if (BitmapBuffer* pBitmapBuffer = rBitmap.AcquireBuffer(true)) + { + const BitmapPalette& rPalette = pBitmapBuffer->maPalette; + if (rPalette.GetEntryCount() == 2) + { + const BitmapColor aWhite(rPalette[rPalette.GetBestIndex(Color(COL_WHITE))]); + rValues.foreground = rColMap.GetPixel(ImplColorToSal(aWhite)); + + const BitmapColor aBlack(rPalette[rPalette.GetBestIndex(Color(COL_BLACK))]); + rValues.background = rColMap.GetPixel(ImplColorToSal(aBlack)); + } + rBitmap.ReleaseBuffer(pBitmapBuffer, true); + } + } +} + +X11SalGraphicsImpl::X11SalGraphicsImpl(X11SalGraphics& rParent): + mrParent(rParent), + nBrushColor_( MAKE_SALCOLOR( 0xFF, 0xFF, 0XFF ) ), + pBrushGC_(NULL), + nBrushPixel_(0), + bPenGC_(false), + bBrushGC_(false), + bMonoGC_(false), + bCopyGC_(false), + bInvertGC_(false), + bInvert50GC_(false), + bStippleGC_(false), + bTrackingGC_(false), + bDitherBrush_(false), + bXORMode_(false), + pPenGC_(NULL), + nPenColor_( MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) ), + nPenPixel_(0), + pMonoGC_(NULL), + pCopyGC_(NULL), + pMaskGC_(NULL), + pInvertGC_(NULL), + pInvert50GC_(NULL), + pStippleGC_(NULL), + pTrackingGC_(NULL) +{ +} + +X11SalGraphicsImpl::~X11SalGraphicsImpl() +{ +} + +XID X11SalGraphicsImpl::GetXRenderPicture() +{ + XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); + + if( !mrParent.m_aXRenderPicture ) + { + // check xrender support for matching visual + XRenderPictFormat* pXRenderFormat = mrParent.GetXRenderFormat(); + if( !pXRenderFormat ) + return 0; + // get the matching xrender target for drawable + mrParent.m_aXRenderPicture = rRenderPeer.CreatePicture( mrParent.hDrawable_, pXRenderFormat, 0, NULL ); + } + + { + // reset clip region + // TODO: avoid clip reset if already done + XRenderPictureAttributes aAttr; + aAttr.clip_mask = None; + rRenderPeer.ChangePicture( mrParent.m_aXRenderPicture, CPClipMask, &aAttr ); + } + + return mrParent.m_aXRenderPicture; +} + +void X11SalGraphicsImpl::freeResources() +{ + Display *pDisplay = mrParent.GetXDisplay(); + + if( pPenGC_ ) XFreeGC( pDisplay, pPenGC_ ), pPenGC_ = None; + if( pBrushGC_ ) XFreeGC( pDisplay, pBrushGC_ ), pBrushGC_ = None; + if( pMonoGC_ ) XFreeGC( pDisplay, pMonoGC_ ), pMonoGC_ = None; + if( pTrackingGC_ ) XFreeGC( pDisplay, pTrackingGC_ ), pTrackingGC_ = None; + if( pCopyGC_ ) XFreeGC( pDisplay, pCopyGC_ ), pCopyGC_ = None; + if( pMaskGC_ ) XFreeGC( pDisplay, pMaskGC_ ), pMaskGC_ = None; + if( pInvertGC_ ) XFreeGC( pDisplay, pInvertGC_ ), pInvertGC_ = None; + if( pInvert50GC_ ) XFreeGC( pDisplay, pInvert50GC_ ), pInvert50GC_ = None; + if( pStippleGC_ ) XFreeGC( pDisplay, pStippleGC_ ), pStippleGC_ = None; + bTrackingGC_ = bPenGC_ = bBrushGC_ = bMonoGC_ = bCopyGC_ = bInvertGC_ = bInvert50GC_ = bStippleGC_ = false; +} + +GC X11SalGraphicsImpl::CreateGC( Drawable hDrawable, unsigned long nMask ) +{ + XGCValues values; + + values.graphics_exposures = False; + values.foreground = mrParent.m_pColormap->GetBlackPixel() + ^ mrParent.m_pColormap->GetWhitePixel(); + values.function = GXxor; + values.line_width = 1; + values.fill_style = FillStippled; + values.stipple = mrParent.GetDisplay()->GetInvert50( mrParent.m_nXScreen ); + values.subwindow_mode = ClipByChildren; + + return XCreateGC( mrParent.GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values ); +} + +inline GC X11SalGraphicsImpl::GetCopyGC() +{ + if( bXORMode_ ) return GetInvertGC(); + + if( !pCopyGC_ ) + pCopyGC_ = CreateGC( mrParent.GetDrawable() ); + + if( !bCopyGC_ ) + { + mrParent.SetClipRegion( pCopyGC_ ); + bCopyGC_ = true; + } + return pCopyGC_; +} + +GC X11SalGraphicsImpl::GetTrackingGC() +{ + const char dash_list[2] = {2, 2}; + + if( !pTrackingGC_ ) + { + XGCValues values; + + values.graphics_exposures = False; + values.foreground = mrParent.m_pColormap->GetBlackPixel() + ^ mrParent.m_pColormap->GetWhitePixel(); + values.function = GXxor; + values.line_width = 1; + values.line_style = LineOnOffDash; + + pTrackingGC_ = XCreateGC( mrParent.GetXDisplay(), mrParent.GetDrawable(), + GCGraphicsExposures | GCForeground | GCFunction + | GCLineWidth | GCLineStyle, + &values ); + XSetDashes( mrParent.GetXDisplay(), pTrackingGC_, 0, dash_list, 2 ); + } + + if( !bTrackingGC_ ) + { + mrParent.SetClipRegion( pTrackingGC_ ); + bTrackingGC_ = true; + } + + return pTrackingGC_; +} + +inline GC X11SalGraphicsImpl::GetMonoGC( Pixmap hPixmap ) +{ + if( !pMonoGC_ ) + pMonoGC_ = CreateGC( hPixmap ); + + if( !bMonoGC_ ) + { + mrParent.SetClipRegion( pMonoGC_ ); + bMonoGC_ = true; + } + + return pMonoGC_; +} + +GC X11SalGraphicsImpl::GetInvertGC() +{ + if( !pInvertGC_ ) + pInvertGC_ = CreateGC( mrParent.GetDrawable(), + GCGraphicsExposures + | GCForeground + | GCFunction + | GCLineWidth ); + + if( !bInvertGC_ ) + { + mrParent.SetClipRegion( pInvertGC_ ); + bInvertGC_ = true; + } + return pInvertGC_; +} + +GC X11SalGraphicsImpl::GetInvert50GC() +{ + if( !pInvert50GC_ ) + { + XGCValues values; + + values.graphics_exposures = False; + values.foreground = mrParent.m_pColormap->GetWhitePixel(); + values.background = mrParent.m_pColormap->GetBlackPixel(); + values.function = GXinvert; + values.line_width = 1; + values.line_style = LineSolid; + unsigned long nValueMask = + GCGraphicsExposures + | GCForeground + | GCBackground + | GCFunction + | GCLineWidth + | GCLineStyle + | GCFillStyle + | GCStipple; + + char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" ); + if( pEnv && ! strcasecmp( pEnv, "true" ) ) + { + values.fill_style = FillSolid; + nValueMask &= ~ GCStipple; + } + else + { + values.fill_style = FillStippled; + values.stipple = mrParent.GetDisplay()->GetInvert50( mrParent.m_nXScreen ); + } + + pInvert50GC_ = XCreateGC( mrParent.GetXDisplay(), mrParent.GetDrawable(), + nValueMask, + &values ); + } + + if( !bInvert50GC_ ) + { + mrParent.SetClipRegion( pInvert50GC_ ); + bInvert50GC_ = true; + } + return pInvert50GC_; +} + +inline GC X11SalGraphicsImpl::GetStippleGC() +{ + if( !pStippleGC_ ) + pStippleGC_ = CreateGC( mrParent.GetDrawable(), + GCGraphicsExposures + | GCFillStyle + | GCLineWidth ); + + if( !bStippleGC_ ) + { + XSetFunction( mrParent.GetXDisplay(), pStippleGC_, bXORMode_ ? GXxor : GXcopy ); + mrParent.SetClipRegion( pStippleGC_ ); + bStippleGC_ = true; + } + + return pStippleGC_; +} + +GC X11SalGraphicsImpl::SelectBrush() +{ + Display *pDisplay = mrParent.GetXDisplay(); + + DBG_ASSERT( nBrushColor_ != SALCOLOR_NONE, "Brush Transparent" ); + + if( !pBrushGC_ ) + { + XGCValues values; + values.subwindow_mode = ClipByChildren; + values.fill_rule = EvenOddRule; // Pict import/ Gradient + values.graphics_exposures = False; + + pBrushGC_ = XCreateGC( pDisplay, mrParent.hDrawable_, + GCSubwindowMode | GCFillRule | GCGraphicsExposures, + &values ); + } + + if( !bBrushGC_ ) + { + if( !bDitherBrush_ ) + { + XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); + XSetForeground( pDisplay, pBrushGC_, nBrushPixel_ ); + if( mrParent.bPrinter_ ) + XSetTile( pDisplay, pBrushGC_, None ); + } + else + { + // Bug in Sun Solaris 2.5.1, XFillPolygon doesn't always reflect + // changes of the tile. PROPERTY_BUG_Tile doesn't fix this ! + if (mrParent.GetDisplay()->GetProperties() & PROPERTY_BUG_FillPolygon_Tile) + XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); + + XSetFillStyle ( pDisplay, pBrushGC_, FillTiled ); + XSetTile ( pDisplay, pBrushGC_, mrParent.hBrush_ ); + } + XSetFunction ( pDisplay, pBrushGC_, bXORMode_ ? GXxor : GXcopy ); + mrParent.SetClipRegion( pBrushGC_ ); + + bBrushGC_ = true; + } + + return pBrushGC_; +} + +GC X11SalGraphicsImpl::SelectPen() +{ + Display *pDisplay = mrParent.GetXDisplay(); + + if( !pPenGC_ ) + { + XGCValues values; + values.subwindow_mode = ClipByChildren; + values.fill_rule = EvenOddRule; // Pict import/ Gradient + values.graphics_exposures = False; + + pPenGC_ = XCreateGC( pDisplay, mrParent.hDrawable_, + GCSubwindowMode | GCFillRule | GCGraphicsExposures, + &values ); + } + + if( !bPenGC_ ) + { + if( nPenColor_ != SALCOLOR_NONE ) + XSetForeground( pDisplay, pPenGC_, nPenPixel_ ); + XSetFunction ( pDisplay, pPenGC_, bXORMode_ ? GXxor : GXcopy ); + mrParent.SetClipRegion( pPenGC_ ); + bPenGC_ = true; + } + + return pPenGC_; +} + +void X11SalGraphicsImpl::DrawLines( sal_uLong nPoints, + const SalPolyLine &rPoints, + GC pGC, + bool bClose + ) +{ + // calculate how many lines XWindow can draw in one go + sal_uLong nMaxLines = (mrParent.GetDisplay()->GetMaxRequestSize() - sizeof(xPolyPointReq)) + / sizeof(xPoint); + if( nMaxLines > nPoints ) nMaxLines = nPoints; + + // print all lines that XWindows can draw + sal_uLong n; + for( n = 0; nPoints - n > nMaxLines; n += nMaxLines - 1 ) + XDrawLines( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + pGC, + &rPoints[n], + nMaxLines, + CoordModeOrigin ); + + if( n < nPoints ) + XDrawLines( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + pGC, + &rPoints[n], + nPoints - n, + CoordModeOrigin ); + if( bClose ) + { + if( rPoints[nPoints-1].x != rPoints[0].x || rPoints[nPoints-1].y != rPoints[0].y ) + drawLine( rPoints[nPoints-1].x, rPoints[nPoints-1].y, rPoints[0].x, rPoints[0].y ); + } +} + +void X11SalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, + SalGraphics *pSSrcGraphics ) +{ + X11SalGraphics* pSrcGraphics = pSSrcGraphics + ? static_cast<X11SalGraphics*>(pSSrcGraphics) + : &mrParent; + + if( rPosAry.mnSrcWidth <= 0 + || rPosAry.mnSrcHeight <= 0 + || rPosAry.mnDestWidth <= 0 + || rPosAry.mnDestHeight <= 0 ) + { + return; + } + + int n; + if( pSrcGraphics == &mrParent ) + { + n = 2; + } + else if( pSrcGraphics->bWindow_ ) + { + // window or compatible virtual device + if( pSrcGraphics->GetDisplay() == mrParent.GetDisplay() && + pSrcGraphics->m_nXScreen == mrParent.m_nXScreen && + pSrcGraphics->GetVisual().GetDepth() == mrParent.GetVisual().GetDepth() + ) + n = 2; // same Display + else + n = 1; // printer or other display + } + else if( pSrcGraphics->bVirDev_ ) + { + // printer compatible virtual device + if( mrParent.bPrinter_ ) + n = 2; // printer or compatible virtual device == same display + else + n = 1; // window or compatible virtual device + } + else + n = 0; + + if( n == 2 + && rPosAry.mnSrcWidth == rPosAry.mnDestWidth + && rPosAry.mnSrcHeight == rPosAry.mnDestHeight + ) + { + // #i60699# Need to generate graphics exposures (to repaint + // obscured areas beneath overlapping windows), src and dest + // are the same window. + const bool bNeedGraphicsExposures( pSrcGraphics == &mrParent && + !mrParent.bVirDev_ && + pSrcGraphics->bWindow_ ); + + GC pCopyGC; + + if( bXORMode_ + && !pSrcGraphics->bVirDev_ + && (mrParent.GetDisplay()->GetProperties() & PROPERTY_BUG_XCopyArea_GXxor) ) + { + Pixmap hPixmap = limitXCreatePixmap( mrParent.GetXDisplay(), + pSrcGraphics->GetDrawable(), // source + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, + pSrcGraphics->GetBitCount() ); + + pCopyGC = mrParent.GetDisplay()->GetCopyGC( mrParent.m_nXScreen ); + + if( bNeedGraphicsExposures ) + XSetGraphicsExposures( mrParent.GetXDisplay(), + pCopyGC, + True ); + + XCopyArea( mrParent.GetXDisplay(), + pSrcGraphics->GetDrawable(), // source + hPixmap, // destination + pCopyGC, // no clipping + rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, + 0, 0 ); // destination + XCopyArea( mrParent.GetXDisplay(), + hPixmap, // source + mrParent.GetDrawable(), // destination + GetInvertGC(), // destination clipping + 0, 0, // source + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, + rPosAry.mnDestX, rPosAry.mnDestY ); + XFreePixmap( mrParent.GetXDisplay(), hPixmap ); + } + else + { + pCopyGC = GetCopyGC(); + + if( bNeedGraphicsExposures ) + XSetGraphicsExposures( mrParent.GetXDisplay(), + pCopyGC, + True ); + + XCopyArea( mrParent.GetXDisplay(), + pSrcGraphics->GetDrawable(), // source + mrParent.GetDrawable(), // destination + pCopyGC, // destination clipping + rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, + rPosAry.mnDestX, rPosAry.mnDestY ); + } + + if( bNeedGraphicsExposures ) + { + mrParent.YieldGraphicsExpose(); + + if( pCopyGC ) + XSetGraphicsExposures( mrParent.GetXDisplay(), + pCopyGC, + False ); + } + } + else if( n ) + { + // #i60699# No chance to handle graphics exposures - we copy + // to a temp bitmap first, into which no repaints are + // technically possible. + boost::scoped_ptr<SalBitmap> pDDB(pSrcGraphics->getBitmap( rPosAry.mnSrcX, + rPosAry.mnSrcY, + rPosAry.mnSrcWidth, + rPosAry.mnSrcHeight )); + + if( !pDDB ) + { + stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" ); + return; + } + + SalTwoRect aPosAry( rPosAry ); + + aPosAry.mnSrcX = 0, aPosAry.mnSrcY = 0; + drawBitmap( aPosAry, *pDDB ); + } + else { + stderr0( "X11SalGraphicsImpl::CopyBits from Printer not yet implemented\n" ); + } +} + +void X11SalGraphicsImpl::copyArea ( long nDestX, long nDestY, + long nSrcX, long nSrcY, + long nSrcWidth, long nSrcHeight, + sal_uInt16 ) +{ + SalTwoRect aPosAry; + + aPosAry.mnDestX = nDestX; + aPosAry.mnDestY = nDestY; + aPosAry.mnDestWidth = nSrcWidth; + aPosAry.mnDestHeight = nSrcHeight; + + aPosAry.mnSrcX = nSrcX; + aPosAry.mnSrcY = nSrcY; + aPosAry.mnSrcWidth = nSrcWidth; + aPosAry.mnSrcHeight = nSrcHeight; + + copyBits ( aPosAry, 0 ); +} + +void X11SalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) +{ + const SalDisplay* pSalDisp = mrParent.GetDisplay(); + Display* pXDisp = pSalDisp->GetDisplay(); + const Drawable aDrawable( mrParent.GetDrawable() ); + const SalColormap& rColMap = pSalDisp->GetColormap( mrParent.m_nXScreen ); + const long nDepth = mrParent.GetDisplay()->GetVisual( mrParent.m_nXScreen ).GetDepth(); + GC aGC( GetCopyGC() ); + XGCValues aOldVal, aNewVal; + int nValues = GCForeground | GCBackground; + + if( rSalBitmap.GetBitCount() == 1 ) + { + // set foreground/background values for 1Bit bitmaps + XGetGCValues( pXDisp, aGC, nValues, &aOldVal ); + setForeBack(aNewVal, rColMap, rSalBitmap); + XChangeGC( pXDisp, aGC, nValues, &aNewVal ); + } + + static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, mrParent.m_nXScreen, nDepth, rPosAry, aGC ); + + if( rSalBitmap.GetBitCount() == 1 ) + XChangeGC( pXDisp, aGC, nValues, &aOldVal ); + XFlush( pXDisp ); +} + +void X11SalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, + const SalBitmap& rSrcBitmap, + const SalBitmap& rMaskBitmap ) +{ + DBG_ASSERT( !mrParent.bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" ); + + // decide if alpha masking or transparency masking is needed + BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( true ); + if( pAlphaBuffer != NULL ) + { + int nMaskFormat = pAlphaBuffer->mnFormat; + const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, true ); + if( nMaskFormat == BMP_FORMAT_8BIT_PAL ) + drawAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap ); + } + + drawMaskedBitmap( rPosAry, rSrcBitmap, rMaskBitmap ); +} + +void X11SalGraphicsImpl::drawMaskedBitmap( const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransBitmap ) +{ + const SalDisplay* pSalDisp = mrParent.GetDisplay(); + Display* pXDisp = pSalDisp->GetDisplay(); + Drawable aDrawable( mrParent.GetDrawable() ); + + // figure work mode depth. If this is a VDev Drawable, use its + // bitdepth to create pixmaps for, otherwise, XCopyArea will + // refuse to work. + const sal_uInt16 nDepth( mrParent.m_pVDev ? + mrParent.m_pVDev->GetDepth() : + pSalDisp->GetVisual( mrParent.m_nXScreen ).GetDepth() ); + Pixmap aFG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth, + rPosAry.mnDestHeight, nDepth ) ); + Pixmap aBG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth, + rPosAry.mnDestHeight, nDepth ) ); + + if( aFG && aBG ) + { + GC aTmpGC; + XGCValues aValues; + setForeBack(aValues, pSalDisp->GetColormap(mrParent.m_nXScreen), rSalBitmap); + const int nValues = GCFunction | GCForeground | GCBackground; + SalTwoRect aTmpRect( rPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0; + + // draw paint bitmap in pixmap #1 + aValues.function = GXcopy; + aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues ); + static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, mrParent.m_nXScreen, nDepth, aTmpRect, aTmpGC ); + DBG_TESTTRANS( aFG ); + + // draw background in pixmap #2 + XCopyArea( pXDisp, aDrawable, aBG, aTmpGC, + rPosAry.mnDestX, rPosAry.mnDestY, + rPosAry.mnDestWidth, rPosAry.mnDestHeight, + 0, 0 ); + + DBG_TESTTRANS( aBG ); + + // mask out paint bitmap in pixmap #1 (transparent areas 0) + aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff; + XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); + static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, mrParent.m_nXScreen, 1, aTmpRect, aTmpGC ); + + DBG_TESTTRANS( aFG ); + + // #105055# For XOR mode, keep background behind bitmap intact + if( !bXORMode_ ) + { + // mask out background in pixmap #2 (nontransparent areas 0) + aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000; + XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); + static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, mrParent.m_nXScreen, 1, aTmpRect, aTmpGC ); + + DBG_TESTTRANS( aBG ); + } + + // merge pixmap #1 and pixmap #2 in pixmap #2 + aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000; + XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); + XCopyArea( pXDisp, aFG, aBG, aTmpGC, + 0, 0, + rPosAry.mnDestWidth, rPosAry.mnDestHeight, + 0, 0 ); + DBG_TESTTRANS( aBG ); + + // #105055# Disable XOR temporarily + bool bOldXORMode( bXORMode_ ); + bXORMode_ = false; + + // copy pixmap #2 (result) to background + XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(), + 0, 0, + rPosAry.mnDestWidth, rPosAry.mnDestHeight, + rPosAry.mnDestX, rPosAry.mnDestY ); + + DBG_TESTTRANS( aBG ); + + bXORMode_ = bOldXORMode; + + XFreeGC( pXDisp, aTmpGC ); + XFlush( pXDisp ); + } + else + drawBitmap( rPosAry, rSalBitmap ); + + if( aFG ) + XFreePixmap( pXDisp, aFG ); + + if( aBG ) + XFreePixmap( pXDisp, aBG ); +} + +bool X11SalGraphicsImpl::drawAlphaBitmap( const SalTwoRect& rTR, + const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp ) +{ + // non 8-bit alpha not implemented yet + if( rAlphaBmp.GetBitCount() != 8 ) + return false; + + // horizontal mirroring not implemented yet + if( rTR.mnDestWidth < 0 ) + return false; + + // stretched conversion is not implemented yet + if( rTR.mnDestWidth != rTR.mnSrcWidth ) + return false; + if( rTR.mnDestHeight!= rTR.mnSrcHeight ) + return false; + + // create destination picture + Picture aDstPic = GetXRenderPicture(); + if( !aDstPic ) + return false; + + const SalDisplay* pSalDisp = mrParent.GetDisplay(); + const SalVisual& rSalVis = pSalDisp->GetVisual( mrParent.m_nXScreen ); + Display* pXDisplay = pSalDisp->GetDisplay(); + + // create source Picture + int nDepth = mrParent.m_pVDev ? mrParent.m_pVDev->GetDepth() : rSalVis.GetDepth(); + const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap ); + ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( mrParent.hDrawable_, mrParent.m_nXScreen, nDepth, rTR ); + if( !pSrcDDB ) + return false; + + //#i75249# workaround for ImplGetDDB() giving us back a different depth than + // we requested. E.g. mask pixmaps are always compatible with the drawable + // TODO: find an appropriate picture format for these cases + // then remove the workaround below and the one for #i75531# + if( nDepth != pSrcDDB->ImplGetDepth() ) + return false; + + Pixmap aSrcPM = pSrcDDB->ImplGetPixmap(); + if( !aSrcPM ) + return false; + + // create source picture + // TODO: use scoped picture + Visual* pSrcXVisual = rSalVis.GetVisual(); + XRenderPeer& rPeer = XRenderPeer::GetInstance(); + XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual ); + if( !pSrcVisFmt ) + return false; + Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL ); + if( !aSrcPic ) + return false; + + // create alpha Picture + + // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap + // problem is that they don't provide an 8bit Pixmap on a non-8bit display + BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( true ); + + // an XImage needs its data top_down + // TODO: avoid wrongly oriented images in upper layers! + const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize; + const char* pSrcBits = (char*)pAlphaBuffer->mpBits; + char* pAlphaBits = new char[ nImageSize ]; + if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN ) + memcpy( pAlphaBits, pSrcBits, nImageSize ); + else + { + char* pDstBits = pAlphaBits + nImageSize; + const int nLineSize = pAlphaBuffer->mnScanlineSize; + for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize ) + memcpy( pDstBits, pSrcBits, nLineSize ); + } + + // the alpha values need to be inverted for XRender + // TODO: make upper layers use standard alpha + long* pLDst = (long*)pAlphaBits; + for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst ) + *pLDst = ~*pLDst; + + char* pCDst = (char*)pLDst; + for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst ) + *pCDst = ~*pCDst; + + const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8(); + XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0, + pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight, + pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize ); + + Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_, + rTR.mnDestWidth, rTR.mnDestHeight, 8 ); + + XGCValues aAlphaGCV; + aAlphaGCV.function = GXcopy; + GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV ); + XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg, + rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight ); + XFreeGC( pXDisplay, aAlphaGC ); + XFree( pAlphaImg ); + if( pAlphaBits != (char*)pAlphaBuffer->mpBits ) + delete[] pAlphaBits; + + const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, true ); + + XRenderPictureAttributes aAttr; + aAttr.repeat = int(true); + Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr ); + if( !aAlphaPic ) + return false; + + // set clipping + if( mrParent.mpClipRegion && !XEmptyRegion( mrParent.mpClipRegion ) ) + rPeer.SetPictureClipRegion( aDstPic, mrParent.mpClipRegion ); + + // paint source * mask over destination picture + rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic, + rTR.mnSrcX, rTR.mnSrcY, 0, 0, + rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight ); + + rPeer.FreePicture( aAlphaPic ); + XFreePixmap(pXDisplay, aAlphaPM); + rPeer.FreePicture( aSrcPic ); + return true; +} + +bool X11SalGraphicsImpl::drawTransformedBitmap( + const basegfx::B2DPoint& rNull, + const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY, + const SalBitmap& rSourceBitmap, + const SalBitmap* pAlphaBitmap) +{ + // here direct support for transformed bitmaps can be impemented + (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap; + return false; +} + +bool X11SalGraphicsImpl::drawAlphaRect( long nX, long nY, long nWidth, + long nHeight, sal_uInt8 nTransparency ) +{ + if( ! mrParent.m_pFrame && ! mrParent.m_pVDev ) + return false; + + if( bPenGC_ || !bBrushGC_ || bXORMode_ ) + return false; // can only perform solid fills without XOR. + + if( mrParent.m_pVDev && mrParent.m_pVDev->GetDepth() < 8 ) + return false; + + Picture aDstPic = GetXRenderPicture(); + if( !aDstPic ) + return false; + + const double fTransparency = (100 - nTransparency) * (1.0/100); + const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency); + + XRenderPeer& rPeer = XRenderPeer::GetInstance(); + rPeer.FillRectangle( PictOpOver, + aDstPic, + &aRenderColor, + nX, nY, + nWidth, nHeight ); + + return true; +} + +void X11SalGraphicsImpl::drawBitmap( const SalTwoRect&, + const SalBitmap&, + SalColor ) +{ + OSL_FAIL( "::DrawBitmap with transparent color not supported" ); +} + +void X11SalGraphicsImpl::drawMask( const SalTwoRect& rPosAry, + const SalBitmap &rSalBitmap, + SalColor nMaskColor ) +{ + const SalDisplay* pSalDisp = mrParent.GetDisplay(); + Display* pXDisp = pSalDisp->GetDisplay(); + Drawable aDrawable( mrParent.GetDrawable() ); + Pixmap aStipple( limitXCreatePixmap( pXDisp, aDrawable, + rPosAry.mnDestWidth, + rPosAry.mnDestHeight, 1 ) ); + + if( aStipple ) + { + SalTwoRect aTwoRect( rPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0; + GC aTmpGC; + XGCValues aValues; + + // create a stipple bitmap first (set bits are changed to unset bits and vice versa) + aValues.function = GXcopyInverted; + aValues.foreground = 1, aValues.background = 0; + aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues ); + static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, mrParent.m_nXScreen, 1, aTwoRect, aTmpGC ); + + XFreeGC( pXDisp, aTmpGC ); + + // Set stipple and draw rectangle + GC aStippleGC( GetStippleGC() ); + int nX = rPosAry.mnDestX, nY = rPosAry.mnDestY; + + XSetStipple( pXDisp, aStippleGC, aStipple ); + XSetTSOrigin( pXDisp, aStippleGC, nX, nY ); + XSetForeground( pXDisp, aStippleGC, mrParent.GetPixel( nMaskColor ) ); + XFillRectangle( pXDisp, aDrawable, aStippleGC, + nX, nY, + rPosAry.mnDestWidth, rPosAry.mnDestHeight ); + XFreePixmap( pXDisp, aStipple ); + XFlush( pXDisp ); + } + else + drawBitmap( rPosAry, rSalBitmap ); +} + +void X11SalGraphicsImpl::ResetClipRegion() +{ + if( mrParent.mpClipRegion ) + { + bPenGC_ = false; + mrParent.bFontGC_ = false; + bBrushGC_ = false; + bMonoGC_ = false; + bCopyGC_ = false; + bInvertGC_ = false; + bInvert50GC_ = false; + bStippleGC_ = false; + bTrackingGC_ = false; + + XDestroyRegion( mrParent.mpClipRegion ); + mrParent.mpClipRegion = NULL; + } +} + +bool X11SalGraphicsImpl::setClipRegion( const vcl::Region& i_rClip ) +{ + if( mrParent.mpClipRegion ) + XDestroyRegion( mrParent.mpClipRegion ); + mrParent.mpClipRegion = XCreateRegion(); + + RectangleVector aRectangles; + i_rClip.GetRegionRectangles(aRectangles); + + for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) + { + const long nW(aRectIter->GetWidth()); + + if(nW) + { + const long nH(aRectIter->GetHeight()); + + if(nH) + { + XRectangle aRect; + + aRect.x = (short)aRectIter->Left(); + aRect.y = (short)aRectIter->Top(); + aRect.width = (unsigned short)nW; + aRect.height = (unsigned short)nH; + XUnionRectWithRegion(&aRect, mrParent.mpClipRegion, mrParent.mpClipRegion); + } + } + } + + //ImplRegionInfo aInfo; + //long nX, nY, nW, nH; + //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); + //while( bRegionRect ) + //{ + // if ( nW && nH ) + // { + // XRectangle aRect; + // aRect.x = (short)nX; + // aRect.y = (short)nY; + // aRect.width = (unsigned short)nW; + // aRect.height = (unsigned short)nH; + + // XUnionRectWithRegion( &aRect, mrParent.mpClipRegion, mrParent.mpClipRegion ); + // } + // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); + //} + + // done, invalidate GCs + bPenGC_ = false; + mrParent.bFontGC_ = false; + bBrushGC_ = false; + bMonoGC_ = false; + bCopyGC_ = false; + bInvertGC_ = false; + bInvert50GC_ = false; + bStippleGC_ = false; + bTrackingGC_ = false; + + if( XEmptyRegion( mrParent.mpClipRegion ) ) + { + XDestroyRegion( mrParent.mpClipRegion ); + mrParent.mpClipRegion= NULL; + } + return true; +} + +void X11SalGraphicsImpl::SetLineColor() +{ + if( nPenColor_ != SALCOLOR_NONE ) + { + nPenColor_ = SALCOLOR_NONE; + bPenGC_ = false; + } +} + +void X11SalGraphicsImpl::SetLineColor( SalColor nSalColor ) +{ + if( nPenColor_ != nSalColor ) + { + nPenColor_ = nSalColor; + nPenPixel_ = mrParent.GetPixel( nSalColor ); + bPenGC_ = false; + } +} + +void X11SalGraphicsImpl::SetFillColor() +{ + if( nBrushColor_ != SALCOLOR_NONE ) + { + bDitherBrush_ = false; + nBrushColor_ = SALCOLOR_NONE; + bBrushGC_ = false; + } +} + +void X11SalGraphicsImpl::SetFillColor( SalColor nSalColor ) +{ + if( nBrushColor_ != nSalColor ) + { + bDitherBrush_ = false; + nBrushColor_ = nSalColor; + nBrushPixel_ = mrParent.GetPixel( nSalColor ); + if( TrueColor != mrParent.GetColormap().GetVisual().GetClass() + && mrParent.GetColormap().GetColor( nBrushPixel_ ) != nBrushColor_ + && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) // black + && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x80 ) // blue + && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x00 ) // green + && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x80 ) // cyan + && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x00 ) // red + && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x80 ) // magenta + && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x00 ) // brown + && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x80 ) // gray + && nSalColor != MAKE_SALCOLOR( 0xC0, 0xC0, 0xC0 ) // light gray + && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0xFF ) // light blue + && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0x00 ) // light green + && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0xFF ) // light cyan + && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0x00 ) // light red + && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0xFF ) // light magenta + && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0x00 ) // light brown + && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) + bDitherBrush_ = mrParent.GetDitherPixmap(nSalColor); + bBrushGC_ = false; + } +} + +void X11SalGraphicsImpl::SetROPLineColor( SalROPColor nROPColor ) +{ + switch( nROPColor ) + { + case SAL_ROP_0 : // 0 + nPenPixel_ = (Pixel)0; + break; + case SAL_ROP_1 : // 1 + nPenPixel_ = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1; + break; + case SAL_ROP_INVERT : // 2 + nPenPixel_ = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1; + break; + } + nPenColor_ = mrParent.GetColormap().GetColor( nPenPixel_ ); + bPenGC_ = false; +} + +void X11SalGraphicsImpl::SetROPFillColor( SalROPColor nROPColor ) +{ + switch( nROPColor ) + { + case SAL_ROP_0 : // 0 + nBrushPixel_ = (Pixel)0; + break; + case SAL_ROP_1 : // 1 + nBrushPixel_ = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1; + break; + case SAL_ROP_INVERT : // 2 + nBrushPixel_ = (Pixel)(1 << mrParent.GetVisual().GetDepth()) - 1; + break; + } + bDitherBrush_ = false; + nBrushColor_ = mrParent.GetColormap().GetColor( nBrushPixel_ ); + bBrushGC_ = false; +} + +void X11SalGraphicsImpl::SetXORMode( bool bSet, bool ) +{ + if( !bXORMode_ == bSet ) + { + bXORMode_ = bSet; + bPenGC_ = false; + mrParent.bFontGC_ = false; + bBrushGC_ = false; + bMonoGC_ = false; + bCopyGC_ = false; + bInvertGC_ = false; + bInvert50GC_ = false; + bStippleGC_ = false; + bTrackingGC_ = false; + } +} + +void X11SalGraphicsImpl::drawPixel( long nX, long nY ) +{ + if( nPenColor_ != SALCOLOR_NONE ) + XDrawPoint( mrParent.GetXDisplay(), mrParent.GetDrawable(), SelectPen(), nX, nY ); +} + +void X11SalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor ) +{ + if( nSalColor != SALCOLOR_NONE ) + { + Display *pDisplay = mrParent.GetXDisplay(); + + if( (nPenColor_ == SALCOLOR_NONE) && !bPenGC_ ) + { + SetLineColor( nSalColor ); + XDrawPoint( pDisplay, mrParent.GetDrawable(), SelectPen(), nX, nY ); + nPenColor_ = SALCOLOR_NONE; + bPenGC_ = False; + } + else + { + GC pGC = SelectPen(); + + if( nSalColor != nPenColor_ ) + XSetForeground( pDisplay, pGC, mrParent.GetPixel( nSalColor ) ); + + XDrawPoint( pDisplay, mrParent.GetDrawable(), pGC, nX, nY ); + + if( nSalColor != nPenColor_ ) + XSetForeground( pDisplay, pGC, nPenPixel_ ); + } + } +} + +void X11SalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 ) +{ + if( nPenColor_ != SALCOLOR_NONE ) + { + if ( mrParent.GetDisplay()->GetProperties() & PROPERTY_BUG_DrawLine ) + { + GC aGC = SelectPen(); + XDrawPoint (mrParent.GetXDisplay(), mrParent.GetDrawable(), aGC, (int)nX1, (int)nY1); + XDrawPoint (mrParent.GetXDisplay(), mrParent.GetDrawable(), aGC, (int)nX2, (int)nY2); + XDrawLine (mrParent.GetXDisplay(), mrParent.GetDrawable(), aGC, nX1, nY1, nX2, nY2 ); + } + else + XDrawLine( mrParent.GetXDisplay(), mrParent.GetDrawable(),SelectPen(), + nX1, nY1, nX2, nY2 ); + } +} + +void X11SalGraphicsImpl::drawRect( long nX, long nY, long nDX, long nDY ) +{ + if( nBrushColor_ != SALCOLOR_NONE ) + { + XFillRectangle( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + SelectBrush(), + nX, nY, nDX, nDY ); + } + // description DrawRect is wrong; thus -1 + if( nPenColor_ != SALCOLOR_NONE ) + XDrawRectangle( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + SelectPen(), + nX, nY, nDX-1, nDY-1 ); +} + +void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry ) +{ + drawPolyLine( nPoints, pPtAry, false ); +} + +void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry, bool bClose ) +{ + if( nPenColor_ != SALCOLOR_NONE ) + { + SalPolyLine Points( nPoints, pPtAry ); + + DrawLines( nPoints, Points, SelectPen(), bClose ); + } +} + +void X11SalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) +{ + if( nPoints == 0 ) + return; + + if( nPoints < 3 ) + { + if( !bXORMode_ ) + { + if( 1 == nPoints ) + drawPixel( pPtAry[0].mnX, pPtAry[0].mnY ); + else + drawLine( pPtAry[0].mnX, pPtAry[0].mnY, + pPtAry[1].mnX, pPtAry[1].mnY ); + } + return; + } + + SalPolyLine Points( nPoints, pPtAry ); + + nPoints++; + + /* WORKAROUND: some Xservers (Xorg, VIA chipset in this case) + * do not draw the visible part of a polygon + * if it overlaps to the left of screen 0,y. + * This happens to be the case in the gradient drawn in the + * menubar background. workaround for the special case of + * of a rectangle overlapping to the left. + */ + if( nPoints == 5 && + Points[ 0 ].x == Points[ 1 ].x && + Points[ 1 ].y == Points[ 2 ].y && + Points[ 2 ].x == Points[ 3 ].x && + Points[ 0 ].x == Points[ 4 ].x && Points[ 0 ].y == Points[ 4 ].y + ) + { + bool bLeft = false; + bool bRight = false; + for(unsigned int i = 0; i < nPoints; i++ ) + { + if( Points[i].x < 0 ) + bLeft = true; + else + bRight= true; + } + if( bLeft && ! bRight ) + return; + if( bLeft && bRight ) + { + for( unsigned int i = 0; i < nPoints; i++ ) + if( Points[i].x < 0 ) + Points[i].x = 0; + } + } + + if( nBrushColor_ != SALCOLOR_NONE ) + XFillPolygon( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + SelectBrush(), + &Points[0], nPoints, + Complex, CoordModeOrigin ); + + if( nPenColor_ != SALCOLOR_NONE ) + DrawLines( nPoints, Points, SelectPen(), true ); +} + +void X11SalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, + const sal_uInt32 *pPoints, + PCONSTSALPOINT *pPtAry ) +{ + if( nBrushColor_ != SALCOLOR_NONE ) + { + sal_uInt32 i, n; + Region pXRegA = NULL; + + for( i = 0; i < nPoly; i++ ) { + n = pPoints[i]; + SalPolyLine Points( n, pPtAry[i] ); + if( n > 2 ) + { + Region pXRegB = XPolygonRegion( &Points[0], n+1, WindingRule ); + if( !pXRegA ) + pXRegA = pXRegB; + else + { + XXorRegion( pXRegA, pXRegB, pXRegA ); + XDestroyRegion( pXRegB ); + } + } + } + + if( pXRegA ) + { + XRectangle aXRect; + XClipBox( pXRegA, &aXRect ); + + GC pGC = SelectBrush(); + mrParent.SetClipRegion( pGC, pXRegA ); // ??? twice + XDestroyRegion( pXRegA ); + bBrushGC_ = false; + + XFillRectangle( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + pGC, + aXRect.x, aXRect.y, aXRect.width, aXRect.height ); + } + } + + if( nPenColor_ != SALCOLOR_NONE ) + for( sal_uInt32 i = 0; i < nPoly; i++ ) + drawPolyLine( pPoints[i], pPtAry[i], true ); +} + +bool X11SalGraphicsImpl::drawPolyLineBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) +{ + return false; +} + +bool X11SalGraphicsImpl::drawPolygonBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) +{ + return false; +} + +bool X11SalGraphicsImpl::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, + const SalPoint* const*, const sal_uInt8* const* ) +{ + return false; +} + +void X11SalGraphicsImpl::invert( long nX, + long nY, + long nDX, + long nDY, + SalInvert nFlags ) +{ + GC pGC; + if( SAL_INVERT_50 & nFlags ) + { + pGC = GetInvert50GC(); + XFillRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY ); + } + else + { + if ( SAL_INVERT_TRACKFRAME & nFlags ) + { + pGC = GetTrackingGC(); + XDrawRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY ); + } + else + { + pGC = GetInvertGC(); + XFillRectangle( mrParent.GetXDisplay(), mrParent.GetDrawable(), pGC, nX, nY, nDX, nDY ); + } + } +} + +void X11SalGraphicsImpl::invert( sal_uInt32 nPoints, + const SalPoint* pPtAry, + SalInvert nFlags ) +{ + SalPolyLine Points ( nPoints, pPtAry ); + + GC pGC; + if( SAL_INVERT_50 & nFlags ) + pGC = GetInvert50GC(); + else + if ( SAL_INVERT_TRACKFRAME & nFlags ) + pGC = GetTrackingGC(); + else + pGC = GetInvertGC(); + + if( SAL_INVERT_TRACKFRAME & nFlags ) + DrawLines ( nPoints, Points, pGC, true ); + else + XFillPolygon( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + pGC, + &Points[0], nPoints, + Complex, CoordModeOrigin ); +} + +bool X11SalGraphicsImpl::drawEPS( long,long,long,long,void*,sal_uLong ) +{ + return false; +} + +// draw a poly-polygon +bool X11SalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency ) +{ + // nothing to do for empty polypolygons + const int nOrigPolyCount = rOrigPolyPoly.count(); + if( nOrigPolyCount <= 0 ) + return true; + + // nothing to do if everything is transparent + if( (nBrushColor_ == SALCOLOR_NONE) + && (nPenColor_ == SALCOLOR_NONE) ) + return true; + + // cannot handle pencolor!=brushcolor yet + if( (nPenColor_ != SALCOLOR_NONE) + && (nPenColor_ != nBrushColor_) ) + return false; + + // TODO: remove the env-variable when no longer needed + static const char* pRenderEnv = getenv( "SAL_DISABLE_RENDER_POLY" ); + if( pRenderEnv ) + return false; + + // snap to raster if requested + basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly; + const bool bSnapToRaster = !mrParent.getAntiAliasB2DDraw(); + if( bSnapToRaster ) + aPolyPoly = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly ); + + // don't bother with polygons outside of visible area + const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() ); + aPolyPoly = basegfx::tools::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false ); + if( !aPolyPoly.count() ) + return true; + + // tesselate the polypolygon into trapezoids + basegfx::B2DTrapezoidVector aB2DTrapVector; + basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aPolyPoly ); + const int nTrapCount = aB2DTrapVector.size(); + if( !nTrapCount ) + return true; + const bool bDrawn = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); + return bDrawn; +} + +long X11SalGraphicsImpl::GetGraphicsHeight() const +{ + if( mrParent.m_pFrame ) + return mrParent.m_pFrame->maGeometry.nHeight; + else if( mrParent.m_pVDev ) + return mrParent.m_pVDev->GetHeight(); + else + return 0; +} + +bool X11SalGraphicsImpl::drawFilledTrapezoids( const ::basegfx::B2DTrapezoid* pB2DTraps, int nTrapCount, double fTransparency ) +{ + if( nTrapCount <= 0 ) + return true; + + Picture aDstPic = GetXRenderPicture(); + // check xrender support for this drawable + if( !aDstPic ) + return false; + + // convert the B2DTrapezoids into XRender-Trapezoids + typedef std::vector<XTrapezoid> TrapezoidVector; + TrapezoidVector aTrapVector( nTrapCount ); + const basegfx::B2DTrapezoid* pB2DTrap = pB2DTraps; + for( int i = 0; i < nTrapCount; ++pB2DTrap, ++i ) + { + XTrapezoid& rTrap = aTrapVector[ i ] ; + + // set y-coordinates + const double fY1 = pB2DTrap->getTopY(); + rTrap.left.p1.y = rTrap.right.p1.y = rTrap.top = XDoubleToFixed( fY1 ); + const double fY2 = pB2DTrap->getBottomY(); + rTrap.left.p2.y = rTrap.right.p2.y = rTrap.bottom = XDoubleToFixed( fY2 ); + + // set x-coordinates + const double fXL1 = pB2DTrap->getTopXLeft(); + rTrap.left.p1.x = XDoubleToFixed( fXL1 ); + const double fXR1 = pB2DTrap->getTopXRight(); + rTrap.right.p1.x = XDoubleToFixed( fXR1 ); + const double fXL2 = pB2DTrap->getBottomXLeft(); + rTrap.left.p2.x = XDoubleToFixed( fXL2 ); + const double fXR2 = pB2DTrap->getBottomXRight(); + rTrap.right.p2.x = XDoubleToFixed( fXR2 ); + } + + // get xrender Picture for polygon foreground + // TODO: cache it like the target picture which uses GetXRenderPicture() + XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); + SalDisplay::RenderEntry& rEntry = mrParent.GetDisplay()->GetRenderEntries( mrParent.m_nXScreen )[ 32 ]; + if( !rEntry.m_aPicture ) + { + Display* pXDisplay = mrParent.GetXDisplay(); + + rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_, 1, 1, 32 ); + XRenderPictureAttributes aAttr; + aAttr.repeat = int(true); + + XRenderPictFormat* pXRPF = rRenderPeer.FindStandardFormat( PictStandardARGB32 ); + rEntry.m_aPicture = rRenderPeer.CreatePicture( rEntry.m_aPixmap, pXRPF, CPRepeat, &aAttr ); + } + + // set polygon foreground color and opacity + XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency ); + rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 ); + + // set clipping + // TODO: move into GetXRenderPicture? + if( mrParent.mpClipRegion && !XEmptyRegion( mrParent.mpClipRegion ) ) + rRenderPeer.SetPictureClipRegion( aDstPic, mrParent.mpClipRegion ); + + // render the trapezoids + const XRenderPictFormat* pMaskFormat = rRenderPeer.GetStandardFormatA8(); + rRenderPeer.CompositeTrapezoids( PictOpOver, + rEntry.m_aPicture, aDstPic, pMaskFormat, 0, 0, &aTrapVector[0], aTrapVector.size() ); + + return true; +} + +bool X11SalGraphicsImpl::drawPolyLine( + const ::basegfx::B2DPolygon& rPolygon, + double fTransparency, + const ::basegfx::B2DVector& rLineWidth, + basegfx::B2DLineJoin eLineJoin, + com::sun::star::drawing::LineCap eLineCap) +{ + const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2); + + // #i101491# + if( !bIsHairline && (rPolygon.count() > 1000) ) + { + // the used basegfx::tools::createAreaGeometry is simply too + // expensive with very big polygons; fallback to caller (who + // should use ImplLineConverter normally) + // AW: ImplLineConverter had to be removed since it does not even + // know LineJoins, so the fallback will now prepare the line geometry + // the same way. + return false; + } + + // temporarily adjust brush color to pen color + // since the line is drawn as an area-polygon + const SalColor aKeepBrushColor = nBrushColor_; + nBrushColor_ = nPenColor_; + + // #i11575#desc5#b adjust B2D tesselation result to raster positions + basegfx::B2DPolygon aPolygon = rPolygon; + const double fHalfWidth = 0.5 * rLineWidth.getX(); + + // #i122456# This is probably thought to happen to align hairlines to pixel positions, so + // it should be a 0.5 translation, not more. It will definitely go wrong with fat lines + aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5) ); + + // shortcut for hairline drawing to improve performance + bool bDrawnOk = true; + if( bIsHairline ) + { + // hairlines can benefit from a simplified tesselation + // e.g. for hairlines the linejoin style can be ignored + basegfx::B2DTrapezoidVector aB2DTrapVector; + basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() ); + + // draw tesselation result + const int nTrapCount = aB2DTrapVector.size(); + if( nTrapCount > 0 ) + bDrawnOk = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); + + // restore the original brush GC + nBrushColor_ = aKeepBrushColor; + return bDrawnOk; + } + + // get the area polygon for the line polygon + if( (rLineWidth.getX() != rLineWidth.getY()) + && !basegfx::fTools::equalZero( rLineWidth.getY() ) ) + { + // prepare for createAreaGeometry() with anisotropic linewidth + aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY())); + } + + // create the area-polygon for the line + const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) ); + + if( (rLineWidth.getX() != rLineWidth.getY()) + && !basegfx::fTools::equalZero( rLineWidth.getX() ) ) + { + // postprocess createAreaGeometry() for anisotropic linewidth + aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX())); + } + + // draw each area polypolygon component individually + // to emulate the polypolygon winding rule "non-zero" + const int nPolyCount = aAreaPolyPoly.count(); + for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) + { + const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) ); + bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency ); + if( !bDrawnOk ) + break; + } + + // restore the original brush GC + nBrushColor_ = aKeepBrushColor; + return bDrawnOk; +} + +SalColor X11SalGraphicsImpl::getPixel( long nX, long nY ) +{ + if( mrParent.bWindow_ && !mrParent.bVirDev_ ) + { + XWindowAttributes aAttrib; + + XGetWindowAttributes( mrParent.GetXDisplay(), mrParent.GetDrawable(), &aAttrib ); + if( aAttrib.map_state != IsViewable ) + { + stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" ); + return 0; + } + } + + XImage *pXImage = XGetImage( mrParent.GetXDisplay(), + mrParent.GetDrawable(), + nX, nY, + 1, 1, + AllPlanes, + ZPixmap ); + if( !pXImage ) + { + stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" ); + return 0; + } + + XColor aXColor; + + aXColor.pixel = XGetPixel( pXImage, 0, 0 ); + XDestroyImage( pXImage ); + + return mrParent.GetColormap().GetColor( aXColor.pixel ); +} + +SalBitmap *X11SalGraphicsImpl::getBitmap( long nX, long nY, long nDX, long nDY ) +{ + if( mrParent.bPrinter_ && !mrParent.bVirDev_ ) + return NULL; + + bool bFakeWindowBG = false; + + // normalize + if( nDX < 0 ) + { + nX += nDX; + nDX = -nDX; + } + if ( nDY < 0 ) + { + nY += nDY; + nDY = -nDY; + } + + if( mrParent.bWindow_ && !mrParent.bVirDev_ ) + { + XWindowAttributes aAttrib; + + XGetWindowAttributes( mrParent.GetXDisplay(), mrParent.GetDrawable(), &aAttrib ); + if( aAttrib.map_state != IsViewable ) + bFakeWindowBG = true; + else + { + long nOrgDX = nDX, nOrgDY = nDY; + + // clip to window size + if ( nX < 0 ) + { + nDX += nX; + nX = 0; + } + if ( nY < 0 ) + { + nDY += nY; + nY = 0; + } + if( nX + nDX > aAttrib.width ) + nDX = aAttrib.width - nX; + if( nY + nDY > aAttrib.height ) + nDY = aAttrib.height - nY; + + // inside ? + if( nDX <= 0 || nDY <= 0 ) + { + bFakeWindowBG = true; + nDX = nOrgDX; + nDY = nOrgDY; + } + } + } + + X11SalBitmap* pSalBitmap = new X11SalBitmap; + sal_uInt16 nBitCount = GetBitCount(); + + if( &mrParent.GetDisplay()->GetColormap( mrParent.m_nXScreen ) != &mrParent.GetColormap() ) + nBitCount = 1; + + if( ! bFakeWindowBG ) + pSalBitmap->ImplCreateFromDrawable( mrParent.GetDrawable(), mrParent.m_nXScreen, nBitCount, nX, nY, nDX, nDY ); + else + pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) ); + + return pSalBitmap; +} + +sal_uInt16 X11SalGraphicsImpl::GetBitCount() const +{ + return mrParent.GetVisual().GetDepth(); +} + +long X11SalGraphicsImpl::GetGraphicsWidth() const +{ + if( mrParent.m_pFrame ) + return mrParent.m_pFrame->maGeometry.nWidth; + else if( mrParent.m_pVDev ) + return mrParent.m_pVDev->GetWidth(); + else + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx new file mode 100644 index 000000000000..86990f5e0fbc --- /dev/null +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <prex.h> +#include <postx.h> + +#include "unx/saltype.h" + +#include "salgdiimpl.hxx" + +#include <basegfx/polygon/b2dtrapezoid.hxx> + +class SalGraphics; +class SalBitmap; +class SalPolyLine; +class X11SalGraphics; + +class X11SalGraphicsImpl : public SalGraphicsImpl +{ +private: + X11SalGraphics& mrParent; + + SalColor nBrushColor_; + GC pBrushGC_; // Brush attributes + Pixel nBrushPixel_; + + bool bPenGC_ : 1; // is Pen GC valid + bool bBrushGC_ : 1; // is Brush GC valid + bool bMonoGC_ : 1; // is Mono GC valid + bool bCopyGC_ : 1; // is Copy GC valid + bool bInvertGC_ : 1; // is Invert GC valid + bool bInvert50GC_ : 1; // is Invert50 GC valid + bool bStippleGC_ : 1; // is Stipple GC valid + bool bTrackingGC_ : 1; // is Tracking GC valid + bool bDitherBrush_ : 1; // is solid or tile + + bool bXORMode_ : 1; // is ROP XOR Mode set + + GC pPenGC_; // Pen attributes + SalColor nPenColor_; + Pixel nPenPixel_; + + + GC pMonoGC_; + GC pCopyGC_; + GC pMaskGC_; + GC pInvertGC_; + GC pInvert50GC_; + GC pStippleGC_; + GC pTrackingGC_; + + GC CreateGC( Drawable hDrawable, + unsigned long nMask = GCGraphicsExposures ); + + GC SelectBrush(); + GC SelectPen(); + inline GC GetCopyGC(); + inline GC GetStippleGC(); + GC GetTrackingGC(); + GC GetInvertGC(); + GC GetInvert50GC(); + inline GC GetMonoGC( Pixmap hPixmap ); + + void DrawLines( sal_uIntPtr nPoints, + const SalPolyLine &rPoints, + GC pGC, + bool bClose + ); + + XID GetXRenderPicture(); + virtual bool drawFilledTrapezoids( const ::basegfx::B2DTrapezoid*, int nTrapCount, double fTransparency ); + + virtual long GetGraphicsHeight() const; + + void drawMaskedBitmap( const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ); + + void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose ); + +public: + + X11SalGraphicsImpl(X11SalGraphics& rParent); + + virtual void freeResources() SAL_OVERRIDE; + + virtual ~X11SalGraphicsImpl(); + + virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE; + // + // get the depth of the device + virtual sal_uInt16 GetBitCount() const SAL_OVERRIDE; + + // get the width of the device + virtual long GetGraphicsWidth() const SAL_OVERRIDE; + + // set the clip region to empty + virtual void ResetClipRegion() SAL_OVERRIDE; + + // set the line color to transparent (= don't draw lines) + + virtual void SetLineColor() SAL_OVERRIDE; + + // set the line color to a specific color + virtual void SetLineColor( SalColor nSalColor ) SAL_OVERRIDE; + + // set the fill color to transparent (= don't fill) + virtual void SetFillColor() SAL_OVERRIDE; + + // set the fill color to a specific color, shapes will be + // filled accordingly + virtual void SetFillColor( SalColor nSalColor ) SAL_OVERRIDE; + + // enable/disable XOR drawing + virtual void SetXORMode( bool bSet, bool bInvertOnly ) SAL_OVERRIDE; + + // set line color for raster operations + virtual void SetROPLineColor( SalROPColor nROPColor ) SAL_OVERRIDE; + + // set fill color for raster operations + virtual void SetROPFillColor( SalROPColor nROPColor ) SAL_OVERRIDE; + + // draw --> LineColor and FillColor and RasterOp and ClipRegion + virtual void drawPixel( long nX, long nY ) SAL_OVERRIDE; + virtual void drawPixel( long nX, long nY, SalColor nSalColor ) SAL_OVERRIDE; + + virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ) SAL_OVERRIDE; + + virtual void drawRect( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; + + virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; + + virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; + + virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry ) SAL_OVERRIDE; + virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ) SAL_OVERRIDE; + + virtual bool drawPolyLine( + const ::basegfx::B2DPolygon&, + double fTransparency, + const ::basegfx::B2DVector& rLineWidths, + basegfx::B2DLineJoin, + com::sun::star::drawing::LineCap) SAL_OVERRIDE; + + virtual bool drawPolyLineBezier( + sal_uInt32 nPoints, + const SalPoint* pPtAry, + const sal_uInt8* pFlgAry ) SAL_OVERRIDE; + + virtual bool drawPolygonBezier( + sal_uInt32 nPoints, + const SalPoint* pPtAry, + const sal_uInt8* pFlgAry ) SAL_OVERRIDE; + + virtual bool drawPolyPolygonBezier( + sal_uInt32 nPoly, + const sal_uInt32* pPoints, + const SalPoint* const* pPtAry, + const sal_uInt8* const* pFlgAry ) SAL_OVERRIDE; + + // CopyArea --> No RasterOp, but ClipRegion + virtual void copyArea( + long nDestX, long nDestY, + long nSrcX, long nSrcY, + long nSrcWidth, long nSrcHeight, + sal_uInt16 nFlags ) SAL_OVERRIDE; + + // CopyBits and DrawBitmap --> RasterOp and ClipRegion + // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics + virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE; + + virtual void drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) SAL_OVERRIDE; + + virtual void drawBitmap( + const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ) SAL_OVERRIDE; + + virtual void drawBitmap( + const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rMaskBitmap ) SAL_OVERRIDE; + + virtual void drawMask( + const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + SalColor nMaskColor ) SAL_OVERRIDE; + + virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; + + virtual SalColor getPixel( long nX, long nY ) SAL_OVERRIDE; + + // invert --> ClipRegion (only Windows or VirDevs) + virtual void invert( + long nX, long nY, + long nWidth, long nHeight, + SalInvert nFlags) SAL_OVERRIDE; + + virtual void invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags ) SAL_OVERRIDE; + + virtual bool drawEPS( + long nX, long nY, + long nWidth, long nHeight, + void* pPtr, + sal_uLong nSize ) SAL_OVERRIDE; + + /** Render bitmap with alpha channel + + @param rSourceBitmap + Source bitmap to blit + + @param rAlphaBitmap + Alpha channel to use for blitting + + @return true, if the operation succeeded, and false + otherwise. In this case, clients should try to emulate alpha + compositing themselves + */ + virtual bool drawAlphaBitmap( + const SalTwoRect&, + const SalBitmap& rSourceBitmap, + const SalBitmap& rAlphaBitmap ) SAL_OVERRIDE; + + /** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */ + virtual bool drawTransformedBitmap( + const basegfx::B2DPoint& rNull, + const basegfx::B2DPoint& rX, + const basegfx::B2DPoint& rY, + const SalBitmap& rSourceBitmap, + const SalBitmap* pAlphaBitmap) SAL_OVERRIDE; + + /** Render solid rectangle with given transparency + + @param nTransparency + Transparency value (0-255) to use. 0 blits and opaque, 255 a + fully transparent rectangle + */ + virtual bool drawAlphaRect( + long nX, long nY, + long nWidth, long nHeight, + sal_uInt8 nTransparency ) SAL_OVERRIDE; + + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index 4441458578b0..539856d64a18 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -50,43 +50,14 @@ #include "unx/salvd.h" #include <unx/x11/xlimits.hxx> +#include "salgdiimpl.hxx" + #include "generic/printergfx.hxx" #include "xrender_peer.hxx" -#define STATIC_POINTS 64 - -class SalPolyLine -{ - XPoint Points_[STATIC_POINTS]; - XPoint *pFirst_; -public: - SalPolyLine(sal_uLong nPoints, const SalPoint *p) - : pFirst_(nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_) - { - for( sal_uLong i = 0; i < nPoints; i++ ) - { - pFirst_[i].x = (short)p[i].mnX; - pFirst_[i].y = (short)p[i].mnY; - } - pFirst_[nPoints] = pFirst_[0]; // close polyline - } - - ~SalPolyLine() - { - if( pFirst_ != Points_ ) - delete [] pFirst_; - } - - XPoint &operator [] ( sal_uLong n ) const - { - return pFirst_[n]; - } -}; - -#undef STATIC_POINTS - X11SalGraphics::X11SalGraphics() - : m_nXScreen( 0 ) + : m_nXScreen( 0 ), + pFontGC_(NULL) { m_pFrame = NULL; m_pVDev = NULL; @@ -99,11 +70,6 @@ X11SalGraphics::X11SalGraphics() mpClipRegion = NULL; pPaintRegion_ = NULL; - pPenGC_ = NULL; - nPenPixel_ = 0; - nPenColor_ = MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black - - pFontGC_ = NULL; for( int i = 0; i < MAX_FALLBACK; ++i ) mpServerFont[i] = NULL; @@ -116,33 +82,11 @@ X11SalGraphics::X11SalGraphics() bDisableGraphite_ = pDisableGraphiteStr && (pDisableGraphiteStr[0]!='0'); #endif - pBrushGC_ = NULL; - nBrushPixel_ = 0; - nBrushColor_ = MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ); // White hBrush_ = None; - pMonoGC_ = NULL; - pCopyGC_ = NULL; - pMaskGC_ = NULL; - pInvertGC_ = NULL; - pInvert50GC_ = NULL; - pStippleGC_ = NULL; - pTrackingGC_ = NULL; - bWindow_ = false; bPrinter_ = false; bVirDev_ = false; - bPenGC_ = false; - bFontGC_ = false; - bBrushGC_ = false; - bMonoGC_ = false; - bCopyGC_ = false; - bInvertGC_ = false; - bInvert50GC_ = false; - bStippleGC_ = false; - bTrackingGC_ = false; - bXORMode_ = false; - bDitherBrush_ = false; } X11SalGraphics::~X11SalGraphics() @@ -159,23 +103,16 @@ void X11SalGraphics::freeResources() if( mpClipRegion ) XDestroyRegion( mpClipRegion ), mpClipRegion = None; if( hBrush_ ) XFreePixmap( pDisplay, hBrush_ ), hBrush_ = None; - if( pPenGC_ ) XFreeGC( pDisplay, pPenGC_ ), pPenGC_ = None; - if( pFontGC_ ) XFreeGC( pDisplay, pFontGC_ ), pFontGC_ = None; - if( pBrushGC_ ) XFreeGC( pDisplay, pBrushGC_ ), pBrushGC_ = None; - if( pMonoGC_ ) XFreeGC( pDisplay, pMonoGC_ ), pMonoGC_ = None; - if( pCopyGC_ ) XFreeGC( pDisplay, pCopyGC_ ), pCopyGC_ = None; - if( pMaskGC_ ) XFreeGC( pDisplay, pMaskGC_ ), pMaskGC_ = None; - if( pInvertGC_ ) XFreeGC( pDisplay, pInvertGC_ ), pInvertGC_ = None; - if( pInvert50GC_ ) XFreeGC( pDisplay, pInvert50GC_ ), pInvert50GC_ = None; - if( pStippleGC_ ) XFreeGC( pDisplay, pStippleGC_ ), pStippleGC_ = None; - if( pTrackingGC_ ) XFreeGC( pDisplay, pTrackingGC_ ), pTrackingGC_ = None; + if( pFontGC_ ) XFreeGC( pDisplay, pFontGC_ ), pFontGC_ = None; if( m_pDeleteColormap ) delete m_pDeleteColormap, m_pColormap = m_pDeleteColormap = NULL; if( m_aXRenderPicture ) XRenderPeer::GetInstance().FreePicture( m_aXRenderPicture ), m_aXRenderPicture = 0; - bPenGC_ = bFontGC_ = bBrushGC_ = bMonoGC_ = bCopyGC_ = bInvertGC_ = bInvert50GC_ = bStippleGC_ = bTrackingGC_ = false; + bFontGC_ = false; + + mpImpl->freeResources(); } void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen ) @@ -202,9 +139,9 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen ) if( hDrawable_ ) { - nPenPixel_ = GetPixel( nPenColor_ ); + // nPenPixel_ = GetPixel( nPenColor_ ); // TODO: moggi: FIX ME nTextPixel_ = GetPixel( nTextColor_ ); - nBrushPixel_ = GetPixel( nBrushColor_ ); + // nBrushPixel_ = GetPixel( nBrushColor_ ); // TODO: moggi: FIX ME } } @@ -252,146 +189,6 @@ void X11SalGraphics::SetClipRegion( GC pGC, Region pXReg ) const } } -GC X11SalGraphics::SelectPen() -{ - Display *pDisplay = GetXDisplay(); - - if( !pPenGC_ ) - { - XGCValues values; - values.subwindow_mode = ClipByChildren; - values.fill_rule = EvenOddRule; // Pict import/ Gradient - values.graphics_exposures = False; - - pPenGC_ = XCreateGC( pDisplay, hDrawable_, - GCSubwindowMode | GCFillRule | GCGraphicsExposures, - &values ); - } - - if( !bPenGC_ ) - { - if( nPenColor_ != SALCOLOR_NONE ) - XSetForeground( pDisplay, pPenGC_, nPenPixel_ ); - XSetFunction ( pDisplay, pPenGC_, bXORMode_ ? GXxor : GXcopy ); - SetClipRegion( pPenGC_ ); - bPenGC_ = true; - } - - return pPenGC_; -} - -GC X11SalGraphics::SelectBrush() -{ - Display *pDisplay = GetXDisplay(); - - DBG_ASSERT( nBrushColor_ != SALCOLOR_NONE, "Brush Transparent" ); - - if( !pBrushGC_ ) - { - XGCValues values; - values.subwindow_mode = ClipByChildren; - values.fill_rule = EvenOddRule; // Pict import/ Gradient - values.graphics_exposures = False; - - pBrushGC_ = XCreateGC( pDisplay, hDrawable_, - GCSubwindowMode | GCFillRule | GCGraphicsExposures, - &values ); - } - - if( !bBrushGC_ ) - { - if( !bDitherBrush_ ) - { - XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); - XSetForeground( pDisplay, pBrushGC_, nBrushPixel_ ); - if( bPrinter_ ) - XSetTile( pDisplay, pBrushGC_, None ); - } - else - { - // Bug in Sun Solaris 2.5.1, XFillPolygon doesn't always reflect - // changes of the tile. PROPERTY_BUG_Tile doesn't fix this ! - if (GetDisplay()->GetProperties() & PROPERTY_BUG_FillPolygon_Tile) - XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); - - XSetFillStyle ( pDisplay, pBrushGC_, FillTiled ); - XSetTile ( pDisplay, pBrushGC_, hBrush_ ); - } - XSetFunction ( pDisplay, pBrushGC_, bXORMode_ ? GXxor : GXcopy ); - SetClipRegion( pBrushGC_ ); - - bBrushGC_ = true; - } - - return pBrushGC_; -} - -GC X11SalGraphics::GetTrackingGC() -{ - const char dash_list[2] = {2, 2}; - - if( !pTrackingGC_ ) - { - XGCValues values; - - values.graphics_exposures = False; - values.foreground = m_pColormap->GetBlackPixel() - ^ m_pColormap->GetWhitePixel(); - values.function = GXxor; - values.line_width = 1; - values.line_style = LineOnOffDash; - - pTrackingGC_ = XCreateGC( GetXDisplay(), GetDrawable(), - GCGraphicsExposures | GCForeground | GCFunction - | GCLineWidth | GCLineStyle, - &values ); - XSetDashes( GetXDisplay(), pTrackingGC_, 0, dash_list, 2 ); - } - - if( !bTrackingGC_ ) - { - SetClipRegion( pTrackingGC_ ); - bTrackingGC_ = true; - } - - return pTrackingGC_; -} - -void X11SalGraphics::DrawLines( sal_uLong nPoints, - const SalPolyLine &rPoints, - GC pGC, - bool bClose - ) -{ - // calculate how many lines XWindow can draw in one go - sal_uLong nMaxLines = (GetDisplay()->GetMaxRequestSize() - sizeof(xPolyPointReq)) - / sizeof(xPoint); - if( nMaxLines > nPoints ) nMaxLines = nPoints; - - // print all lines that XWindows can draw - sal_uLong n; - for( n = 0; nPoints - n > nMaxLines; n += nMaxLines - 1 ) - XDrawLines( GetXDisplay(), - GetDrawable(), - pGC, - &rPoints[n], - nMaxLines, - CoordModeOrigin ); - - if( n < nPoints ) - XDrawLines( GetXDisplay(), - GetDrawable(), - pGC, - &rPoints[n], - nPoints - n, - CoordModeOrigin ); - if( bClose ) - { - if( rPoints[nPoints-1].x != rPoints[0].x || rPoints[nPoints-1].y != rPoints[0].y ) - drawLine( rPoints[nPoints-1].x, rPoints[nPoints-1].y, rPoints[0].x, rPoints[0].y ); - } -} - // Calculate a dither-pixmap and make a brush of it #define P_DELTA 51 #define DMAP( v, m ) ((v % P_DELTA) > m ? (v / P_DELTA) + 1 : (v / P_DELTA)) @@ -506,493 +303,123 @@ void X11SalGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY ) // cons sal_uInt16 X11SalGraphics::GetBitCount() const { - return GetVisual().GetDepth(); + return mpImpl->GetBitCount(); } long X11SalGraphics::GetGraphicsWidth() const { - if( m_pFrame ) - return m_pFrame->maGeometry.nWidth; - else if( m_pVDev ) - return m_pVDev->GetWidth(); - else - return 0; -} - -long X11SalGraphics::GetGraphicsHeight() const -{ - if( m_pFrame ) - return m_pFrame->maGeometry.nHeight; - else if( m_pVDev ) - return m_pVDev->GetHeight(); - else - return 0; + return mpImpl->GetGraphicsWidth(); } void X11SalGraphics::ResetClipRegion() { - if( mpClipRegion ) - { - bPenGC_ = false; - bFontGC_ = false; - bBrushGC_ = false; - bMonoGC_ = false; - bCopyGC_ = false; - bInvertGC_ = false; - bInvert50GC_ = false; - bStippleGC_ = false; - bTrackingGC_ = false; - - XDestroyRegion( mpClipRegion ); - mpClipRegion = NULL; - } + mpImpl->ResetClipRegion(); } bool X11SalGraphics::setClipRegion( const vcl::Region& i_rClip ) { - if( mpClipRegion ) - XDestroyRegion( mpClipRegion ); - mpClipRegion = XCreateRegion(); - - RectangleVector aRectangles; - i_rClip.GetRegionRectangles(aRectangles); - - for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) - { - const long nW(aRectIter->GetWidth()); - - if(nW) - { - const long nH(aRectIter->GetHeight()); - - if(nH) - { - XRectangle aRect; - - aRect.x = (short)aRectIter->Left(); - aRect.y = (short)aRectIter->Top(); - aRect.width = (unsigned short)nW; - aRect.height = (unsigned short)nH; - XUnionRectWithRegion(&aRect, mpClipRegion, mpClipRegion); - } - } - } - - //ImplRegionInfo aInfo; - //long nX, nY, nW, nH; - //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); - //while( bRegionRect ) - //{ - // if ( nW && nH ) - // { - // XRectangle aRect; - // aRect.x = (short)nX; - // aRect.y = (short)nY; - // aRect.width = (unsigned short)nW; - // aRect.height = (unsigned short)nH; - - // XUnionRectWithRegion( &aRect, mpClipRegion, mpClipRegion ); - // } - // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); - //} - - // done, invalidate GCs - bPenGC_ = false; - bFontGC_ = false; - bBrushGC_ = false; - bMonoGC_ = false; - bCopyGC_ = false; - bInvertGC_ = false; - bInvert50GC_ = false; - bStippleGC_ = false; - bTrackingGC_ = false; - - if( XEmptyRegion( mpClipRegion ) ) - { - XDestroyRegion( mpClipRegion ); - mpClipRegion= NULL; - } - return true; + return mpImpl->setClipRegion( i_rClip ); } void X11SalGraphics::SetLineColor() { - if( nPenColor_ != SALCOLOR_NONE ) - { - nPenColor_ = SALCOLOR_NONE; - bPenGC_ = false; - } + mpImpl->SetLineColor(); } void X11SalGraphics::SetLineColor( SalColor nSalColor ) { - if( nPenColor_ != nSalColor ) - { - nPenColor_ = nSalColor; - nPenPixel_ = GetPixel( nSalColor ); - bPenGC_ = false; - } + mpImpl->SetLineColor( nSalColor ); } void X11SalGraphics::SetFillColor() { - if( nBrushColor_ != SALCOLOR_NONE ) - { - bDitherBrush_ = false; - nBrushColor_ = SALCOLOR_NONE; - bBrushGC_ = false; - } + mpImpl->SetFillColor(); } void X11SalGraphics::SetFillColor( SalColor nSalColor ) { - if( nBrushColor_ != nSalColor ) - { - bDitherBrush_ = false; - nBrushColor_ = nSalColor; - nBrushPixel_ = GetPixel( nSalColor ); - if( TrueColor != GetColormap().GetVisual().GetClass() - && GetColormap().GetColor( nBrushPixel_ ) != nBrushColor_ - && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) // black - && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x80 ) // blue - && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x00 ) // green - && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x80 ) // cyan - && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x00 ) // red - && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x80 ) // magenta - && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x00 ) // brown - && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x80 ) // gray - && nSalColor != MAKE_SALCOLOR( 0xC0, 0xC0, 0xC0 ) // light gray - && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0xFF ) // light blue - && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0x00 ) // light green - && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0xFF ) // light cyan - && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0x00 ) // light red - && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0xFF ) // light magenta - && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0x00 ) // light brown - && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) - bDitherBrush_ = GetDitherPixmap(nSalColor); - bBrushGC_ = false; - } + mpImpl->SetFillColor( nSalColor ); } void X11SalGraphics::SetROPLineColor( SalROPColor nROPColor ) { - switch( nROPColor ) - { - case SAL_ROP_0 : // 0 - nPenPixel_ = (Pixel)0; - break; - case SAL_ROP_1 : // 1 - nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; - break; - case SAL_ROP_INVERT : // 2 - nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; - break; - } - nPenColor_ = GetColormap().GetColor( nPenPixel_ ); - bPenGC_ = false; + mpImpl->SetROPLineColor( nROPColor ); } void X11SalGraphics::SetROPFillColor( SalROPColor nROPColor ) { - switch( nROPColor ) - { - case SAL_ROP_0 : // 0 - nBrushPixel_ = (Pixel)0; - break; - case SAL_ROP_1 : // 1 - nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; - break; - case SAL_ROP_INVERT : // 2 - nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; - break; - } - bDitherBrush_ = false; - nBrushColor_ = GetColormap().GetColor( nBrushPixel_ ); - bBrushGC_ = false; + mpImpl->SetROPFillColor( nROPColor ); } -void X11SalGraphics::SetXORMode( bool bSet, bool ) +void X11SalGraphics::SetXORMode( bool bSet, bool bInvertOnly ) { - if( !bXORMode_ == bSet ) - { - bXORMode_ = bSet; - bPenGC_ = false; - bFontGC_ = false; - bBrushGC_ = false; - bMonoGC_ = false; - bCopyGC_ = false; - bInvertGC_ = false; - bInvert50GC_ = false; - bStippleGC_ = false; - bTrackingGC_ = false; - } + mpImpl->SetXORMode( bSet, bInvertOnly ); } void X11SalGraphics::drawPixel( long nX, long nY ) { - if( nPenColor_ != SALCOLOR_NONE ) - XDrawPoint( GetXDisplay(), GetDrawable(), SelectPen(), nX, nY ); + mpImpl->drawPixel( nX, nY ); } void X11SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) { - if( nSalColor != SALCOLOR_NONE ) - { - Display *pDisplay = GetXDisplay(); - - if( (nPenColor_ == SALCOLOR_NONE) && !bPenGC_ ) - { - SetLineColor( nSalColor ); - XDrawPoint( pDisplay, GetDrawable(), SelectPen(), nX, nY ); - nPenColor_ = SALCOLOR_NONE; - bPenGC_ = False; - } - else - { - GC pGC = SelectPen(); - - if( nSalColor != nPenColor_ ) - XSetForeground( pDisplay, pGC, GetPixel( nSalColor ) ); - - XDrawPoint( pDisplay, GetDrawable(), pGC, nX, nY ); - - if( nSalColor != nPenColor_ ) - XSetForeground( pDisplay, pGC, nPenPixel_ ); - } - } + mpImpl->drawPixel( nX, nY, nSalColor ); } void X11SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) { - if( nPenColor_ != SALCOLOR_NONE ) - { - if ( GetDisplay()->GetProperties() & PROPERTY_BUG_DrawLine ) - { - GC aGC = SelectPen(); - XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX1, (int)nY1); - XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX2, (int)nY2); - XDrawLine (GetXDisplay(), GetDrawable(), aGC, nX1, nY1, nX2, nY2 ); - } - else - XDrawLine( GetXDisplay(), GetDrawable(),SelectPen(), - nX1, nY1, nX2, nY2 ); - } + mpImpl->drawLine( nX1, nY1, nX2, nY2 ); } void X11SalGraphics::drawRect( long nX, long nY, long nDX, long nDY ) { - if( nBrushColor_ != SALCOLOR_NONE ) - { - XFillRectangle( GetXDisplay(), - GetDrawable(), - SelectBrush(), - nX, nY, nDX, nDY ); - } - // description DrawRect is wrong; thus -1 - if( nPenColor_ != SALCOLOR_NONE ) - XDrawRectangle( GetXDisplay(), - GetDrawable(), - SelectPen(), - nX, nY, nDX-1, nDY-1 ); + mpImpl->drawRect( nX, nY, nDX, nDY ); } void X11SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry ) { - drawPolyLine( nPoints, pPtAry, false ); -} - -void X11SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint *pPtAry, bool bClose ) -{ - if( nPenColor_ != SALCOLOR_NONE ) - { - SalPolyLine Points( nPoints, pPtAry ); - - DrawLines( nPoints, Points, SelectPen(), bClose ); - } + mpImpl->drawPolyLine( nPoints, pPtAry ); } void X11SalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) { - if( nPoints == 0 ) - return; - - if( nPoints < 3 ) - { - if( !bXORMode_ ) - { - if( 1 == nPoints ) - drawPixel( pPtAry[0].mnX, pPtAry[0].mnY ); - else - drawLine( pPtAry[0].mnX, pPtAry[0].mnY, - pPtAry[1].mnX, pPtAry[1].mnY ); - } - return; - } - - SalPolyLine Points( nPoints, pPtAry ); - - nPoints++; - - /* WORKAROUND: some Xservers (Xorg, VIA chipset in this case) - * do not draw the visible part of a polygon - * if it overlaps to the left of screen 0,y. - * This happens to be the case in the gradient drawn in the - * menubar background. workaround for the special case of - * of a rectangle overlapping to the left. - */ - if( nPoints == 5 && - Points[ 0 ].x == Points[ 1 ].x && - Points[ 1 ].y == Points[ 2 ].y && - Points[ 2 ].x == Points[ 3 ].x && - Points[ 0 ].x == Points[ 4 ].x && Points[ 0 ].y == Points[ 4 ].y - ) - { - bool bLeft = false; - bool bRight = false; - for(unsigned int i = 0; i < nPoints; i++ ) - { - if( Points[i].x < 0 ) - bLeft = true; - else - bRight= true; - } - if( bLeft && ! bRight ) - return; - if( bLeft && bRight ) - { - for( unsigned int i = 0; i < nPoints; i++ ) - if( Points[i].x < 0 ) - Points[i].x = 0; - } - } - - if( nBrushColor_ != SALCOLOR_NONE ) - XFillPolygon( GetXDisplay(), - GetDrawable(), - SelectBrush(), - &Points[0], nPoints, - Complex, CoordModeOrigin ); - - if( nPenColor_ != SALCOLOR_NONE ) - DrawLines( nPoints, Points, SelectPen(), true ); + mpImpl->drawPolygon( nPoints, pPtAry ); } void X11SalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32 *pPoints, PCONSTSALPOINT *pPtAry ) { - if( nBrushColor_ != SALCOLOR_NONE ) - { - sal_uInt32 i, n; - Region pXRegA = NULL; - - for( i = 0; i < nPoly; i++ ) { - n = pPoints[i]; - SalPolyLine Points( n, pPtAry[i] ); - if( n > 2 ) - { - Region pXRegB = XPolygonRegion( &Points[0], n+1, WindingRule ); - if( !pXRegA ) - pXRegA = pXRegB; - else - { - XXorRegion( pXRegA, pXRegB, pXRegA ); - XDestroyRegion( pXRegB ); - } - } - } - - if( pXRegA ) - { - XRectangle aXRect; - XClipBox( pXRegA, &aXRect ); - - GC pGC = SelectBrush(); - SetClipRegion( pGC, pXRegA ); // ??? twice - XDestroyRegion( pXRegA ); - bBrushGC_ = false; - - XFillRectangle( GetXDisplay(), - GetDrawable(), - pGC, - aXRect.x, aXRect.y, aXRect.width, aXRect.height ); - } - } - - if( nPenColor_ != SALCOLOR_NONE ) - for( sal_uInt32 i = 0; i < nPoly; i++ ) - drawPolyLine( pPoints[i], pPtAry[i], true ); + mpImpl->drawPolyPolygon( nPoly, pPoints, pPtAry ); } -bool X11SalGraphics::drawPolyLineBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) +bool X11SalGraphics::drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ) { - return false; + return mpImpl->drawPolyLineBezier( nPoints, pPtAry, pFlgAry ); } -bool X11SalGraphics::drawPolygonBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) +bool X11SalGraphics::drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ) { - return false; + return mpImpl->drawPolygonBezier( nPoints, pPtAry, pFlgAry ); } -bool X11SalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, - const SalPoint* const*, const sal_uInt8* const* ) +bool X11SalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoints, const sal_uInt32* pPoints, + const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry) { - return false; + return mpImpl->drawPolyPolygonBezier( nPoints, pPoints, pPtAry, pFlgAry ); } void X11SalGraphics::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags ) { - SalPolyLine Points ( nPoints, pPtAry ); - - GC pGC; - if( SAL_INVERT_50 & nFlags ) - pGC = GetInvert50GC(); - else - if ( SAL_INVERT_TRACKFRAME & nFlags ) - pGC = GetTrackingGC(); - else - pGC = GetInvertGC(); - - if( SAL_INVERT_TRACKFRAME & nFlags ) - DrawLines ( nPoints, Points, pGC, true ); - else - XFillPolygon( GetXDisplay(), - GetDrawable(), - pGC, - &Points[0], nPoints, - Complex, CoordModeOrigin ); + mpImpl->invert( nPoints, pPtAry, nFlags ); } -bool X11SalGraphics::drawEPS( long,long,long,long,void*,sal_uLong ) +bool X11SalGraphics::drawEPS( long nX, long nY, long nWidth, + long nHeight, void* pPtr, sal_uLong nSize ) { - return false; -} - -XID X11SalGraphics::GetXRenderPicture() -{ - XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); - - if( !m_aXRenderPicture ) - { - // check xrender support for matching visual - XRenderPictFormat* pXRenderFormat = GetXRenderFormat(); - if( !pXRenderFormat ) - return 0; - // get the matching xrender target for drawable - m_aXRenderPicture = rRenderPeer.CreatePicture( hDrawable_, pXRenderFormat, 0, NULL ); - } - - { - // reset clip region - // TODO: avoid clip reset if already done - XRenderPictureAttributes aAttr; - aAttr.clip_mask = None; - rRenderPeer.ChangePicture( m_aXRenderPicture, CPClipMask, &aAttr ); - } - - return m_aXRenderPicture; + return mpImpl->drawEPS( nX, nY, nWidth, nHeight, pPtr, nSize ); } XRenderPictFormat* X11SalGraphics::GetXRenderFormat() const @@ -1020,114 +447,7 @@ SystemGraphicsData X11SalGraphics::GetGraphicsData() const // draw a poly-polygon bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency ) { - // nothing to do for empty polypolygons - const int nOrigPolyCount = rOrigPolyPoly.count(); - if( nOrigPolyCount <= 0 ) - return true; - - // nothing to do if everything is transparent - if( (nBrushColor_ == SALCOLOR_NONE) - && (nPenColor_ == SALCOLOR_NONE) ) - return true; - - // cannot handle pencolor!=brushcolor yet - if( (nPenColor_ != SALCOLOR_NONE) - && (nPenColor_ != nBrushColor_) ) - return false; - - // TODO: remove the env-variable when no longer needed - static const char* pRenderEnv = getenv( "SAL_DISABLE_RENDER_POLY" ); - if( pRenderEnv ) - return false; - - // snap to raster if requested - basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly; - const bool bSnapToRaster = !getAntiAliasB2DDraw(); - if( bSnapToRaster ) - aPolyPoly = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly ); - - // don't bother with polygons outside of visible area - const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() ); - aPolyPoly = basegfx::tools::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false ); - if( !aPolyPoly.count() ) - return true; - - // tesselate the polypolygon into trapezoids - basegfx::B2DTrapezoidVector aB2DTrapVector; - basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aPolyPoly ); - const int nTrapCount = aB2DTrapVector.size(); - if( !nTrapCount ) - return true; - const bool bDrawn = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); - return bDrawn; -} - -bool X11SalGraphics::drawFilledTrapezoids( const ::basegfx::B2DTrapezoid* pB2DTraps, int nTrapCount, double fTransparency ) -{ - if( nTrapCount <= 0 ) - return true; - - Picture aDstPic = GetXRenderPicture(); - // check xrender support for this drawable - if( !aDstPic ) - return false; - - // convert the B2DTrapezoids into XRender-Trapezoids - typedef std::vector<XTrapezoid> TrapezoidVector; - TrapezoidVector aTrapVector( nTrapCount ); - const basegfx::B2DTrapezoid* pB2DTrap = pB2DTraps; - for( int i = 0; i < nTrapCount; ++pB2DTrap, ++i ) - { - XTrapezoid& rTrap = aTrapVector[ i ] ; - - // set y-coordinates - const double fY1 = pB2DTrap->getTopY(); - rTrap.left.p1.y = rTrap.right.p1.y = rTrap.top = XDoubleToFixed( fY1 ); - const double fY2 = pB2DTrap->getBottomY(); - rTrap.left.p2.y = rTrap.right.p2.y = rTrap.bottom = XDoubleToFixed( fY2 ); - - // set x-coordinates - const double fXL1 = pB2DTrap->getTopXLeft(); - rTrap.left.p1.x = XDoubleToFixed( fXL1 ); - const double fXR1 = pB2DTrap->getTopXRight(); - rTrap.right.p1.x = XDoubleToFixed( fXR1 ); - const double fXL2 = pB2DTrap->getBottomXLeft(); - rTrap.left.p2.x = XDoubleToFixed( fXL2 ); - const double fXR2 = pB2DTrap->getBottomXRight(); - rTrap.right.p2.x = XDoubleToFixed( fXR2 ); - } - - // get xrender Picture for polygon foreground - // TODO: cache it like the target picture which uses GetXRenderPicture() - XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); - SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nXScreen )[ 32 ]; - if( !rEntry.m_aPicture ) - { - Display* pXDisplay = GetXDisplay(); - - rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, hDrawable_, 1, 1, 32 ); - XRenderPictureAttributes aAttr; - aAttr.repeat = int(true); - - XRenderPictFormat* pXRPF = rRenderPeer.FindStandardFormat( PictStandardARGB32 ); - rEntry.m_aPicture = rRenderPeer.CreatePicture( rEntry.m_aPixmap, pXRPF, CPRepeat, &aAttr ); - } - - // set polygon foreground color and opacity - XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency ); - rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 ); - - // set clipping - // TODO: move into GetXRenderPicture? - if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) - rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion ); - - // render the trapezoids - const XRenderPictFormat* pMaskFormat = rRenderPeer.GetStandardFormatA8(); - rRenderPeer.CompositeTrapezoids( PictOpOver, - rEntry.m_aPicture, aDstPic, pMaskFormat, 0, 0, &aTrapVector[0], aTrapVector.size() ); - - return true; + return mpImpl->drawPolyPolygon( rOrigPolyPoly, fTransparency ); } bool X11SalGraphics::drawPolyLine( @@ -1137,84 +457,8 @@ bool X11SalGraphics::drawPolyLine( basegfx::B2DLineJoin eLineJoin, com::sun::star::drawing::LineCap eLineCap) { - const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2); - - // #i101491# - if( !bIsHairline && (rPolygon.count() > 1000) ) - { - // the used basegfx::tools::createAreaGeometry is simply too - // expensive with very big polygons; fallback to caller (who - // should use ImplLineConverter normally) - // AW: ImplLineConverter had to be removed since it does not even - // know LineJoins, so the fallback will now prepare the line geometry - // the same way. - return false; - } - - // temporarily adjust brush color to pen color - // since the line is drawn as an area-polygon - const SalColor aKeepBrushColor = nBrushColor_; - nBrushColor_ = nPenColor_; - - // #i11575#desc5#b adjust B2D tesselation result to raster positions - basegfx::B2DPolygon aPolygon = rPolygon; - const double fHalfWidth = 0.5 * rLineWidth.getX(); - - // #i122456# This is probably thought to happen to align hairlines to pixel positions, so - // it should be a 0.5 translation, not more. It will definitely go wrong with fat lines - aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5) ); - - // shortcut for hairline drawing to improve performance - bool bDrawnOk = true; - if( bIsHairline ) - { - // hairlines can benefit from a simplified tesselation - // e.g. for hairlines the linejoin style can be ignored - basegfx::B2DTrapezoidVector aB2DTrapVector; - basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() ); - - // draw tesselation result - const int nTrapCount = aB2DTrapVector.size(); - if( nTrapCount > 0 ) - bDrawnOk = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); - - // restore the original brush GC - nBrushColor_ = aKeepBrushColor; - return bDrawnOk; - } - - // get the area polygon for the line polygon - if( (rLineWidth.getX() != rLineWidth.getY()) - && !basegfx::fTools::equalZero( rLineWidth.getY() ) ) - { - // prepare for createAreaGeometry() with anisotropic linewidth - aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY())); - } - - // create the area-polygon for the line - const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) ); - - if( (rLineWidth.getX() != rLineWidth.getY()) - && !basegfx::fTools::equalZero( rLineWidth.getX() ) ) - { - // postprocess createAreaGeometry() for anisotropic linewidth - aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX())); - } - - // draw each area polypolygon component individually - // to emulate the polypolygon winding rule "non-zero" - const int nPolyCount = aAreaPolyPoly.count(); - for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) - { - const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) ); - bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency ); - if( !bDrawnOk ) - break; - } - - // restore the original brush GC - nBrushColor_ = aKeepBrushColor; - return bDrawnOk; + return mpImpl->drawPolyLine( rPolygon, fTransparency, rLineWidth, + eLineJoin, eLineCap ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx index 8059449c1371..aa2732a4ba8f 100644 --- a/vcl/unx/generic/gdi/salgdi2.cxx +++ b/vcl/unx/generic/gdi/salgdi2.cxx @@ -19,6 +19,7 @@ #include <stdio.h> #include <poll.h> +#include "salgdiimpl.hxx" #include "vcl/salbtype.hxx" @@ -38,20 +39,6 @@ #include <outdata.hxx> #include <boost/scoped_ptr.hpp> -#undef SALGDI2_TESTTRANS - -#if (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS -#define DBG_TESTTRANS( _def_drawable ) \ -{ \ - XCopyArea( pXDisp, _def_drawable, aDrawable, GetCopyGC(), \ - 0, 0, \ - rPosAry.mnDestWidth, rPosAry.mnDestHeight, \ - 0, 0 ); \ -} -#else // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS -#define DBG_TESTTRANS( _def_drawable ) -#endif // (OSL_DEBUG_LEVEL > 1) && defined SALGDI2_TESTTRANS - void X11SalGraphics::CopyScreenArea( Display* pDisplay, Drawable aSrc, SalX11Screen nXScreenSrc, int nSrcDepth, Drawable aDest, SalX11Screen nXScreenDest, int nDestDepth, @@ -94,133 +81,6 @@ void X11SalGraphics::CopyScreenArea( Display* pDisplay, } } -GC X11SalGraphics::CreateGC( Drawable hDrawable, unsigned long nMask ) -{ - XGCValues values; - - values.graphics_exposures = False; - values.foreground = m_pColormap->GetBlackPixel() - ^ m_pColormap->GetWhitePixel(); - values.function = GXxor; - values.line_width = 1; - values.fill_style = FillStippled; - values.stipple = GetDisplay()->GetInvert50( m_nXScreen ); - values.subwindow_mode = ClipByChildren; - - return XCreateGC( GetXDisplay(), hDrawable, nMask | GCSubwindowMode, &values ); -} - -inline GC X11SalGraphics::GetMonoGC( Pixmap hPixmap ) -{ - if( !pMonoGC_ ) - pMonoGC_ = CreateGC( hPixmap ); - - if( !bMonoGC_ ) - { - SetClipRegion( pMonoGC_ ); - bMonoGC_ = true; - } - - return pMonoGC_; -} - -inline GC X11SalGraphics::GetCopyGC() -{ - if( bXORMode_ ) return GetInvertGC(); - - if( !pCopyGC_ ) - pCopyGC_ = CreateGC( GetDrawable() ); - - if( !bCopyGC_ ) - { - SetClipRegion( pCopyGC_ ); - bCopyGC_ = true; - } - return pCopyGC_; -} - -GC X11SalGraphics::GetInvertGC() -{ - if( !pInvertGC_ ) - pInvertGC_ = CreateGC( GetDrawable(), - GCGraphicsExposures - | GCForeground - | GCFunction - | GCLineWidth ); - - if( !bInvertGC_ ) - { - SetClipRegion( pInvertGC_ ); - bInvertGC_ = true; - } - return pInvertGC_; -} - -GC X11SalGraphics::GetInvert50GC() -{ - if( !pInvert50GC_ ) - { - XGCValues values; - - values.graphics_exposures = False; - values.foreground = m_pColormap->GetWhitePixel(); - values.background = m_pColormap->GetBlackPixel(); - values.function = GXinvert; - values.line_width = 1; - values.line_style = LineSolid; - unsigned long nValueMask = - GCGraphicsExposures - | GCForeground - | GCBackground - | GCFunction - | GCLineWidth - | GCLineStyle - | GCFillStyle - | GCStipple; - - char* pEnv = getenv( "SAL_DO_NOT_USE_INVERT50" ); - if( pEnv && ! strcasecmp( pEnv, "true" ) ) - { - values.fill_style = FillSolid; - nValueMask &= ~ GCStipple; - } - else - { - values.fill_style = FillStippled; - values.stipple = GetDisplay()->GetInvert50( m_nXScreen ); - } - - pInvert50GC_ = XCreateGC( GetXDisplay(), GetDrawable(), - nValueMask, - &values ); - } - - if( !bInvert50GC_ ) - { - SetClipRegion( pInvert50GC_ ); - bInvert50GC_ = true; - } - return pInvert50GC_; -} - -inline GC X11SalGraphics::GetStippleGC() -{ - if( !pStippleGC_ ) - pStippleGC_ = CreateGC( GetDrawable(), - GCGraphicsExposures - | GCFillStyle - | GCLineWidth ); - - if( !bStippleGC_ ) - { - XSetFunction( GetXDisplay(), pStippleGC_, bXORMode_ ? GXxor : GXcopy ); - SetClipRegion( pStippleGC_ ); - bStippleGC_ = true; - } - - return pStippleGC_; -} - extern "C" { static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow ) @@ -281,456 +141,33 @@ void X11SalGraphics::YieldGraphicsExpose() void X11SalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSSrcGraphics ) { - X11SalGraphics* pSrcGraphics = pSSrcGraphics - ? static_cast<X11SalGraphics*>(pSSrcGraphics) - : this; - - if( rPosAry.mnSrcWidth <= 0 - || rPosAry.mnSrcHeight <= 0 - || rPosAry.mnDestWidth <= 0 - || rPosAry.mnDestHeight <= 0 ) - { - return; - } - - int n; - if( pSrcGraphics == this ) - { - n = 2; - } - else if( pSrcGraphics->bWindow_ ) - { - // window or compatible virtual device - if( pSrcGraphics->GetDisplay() == GetDisplay() && - pSrcGraphics->m_nXScreen == m_nXScreen && - pSrcGraphics->GetVisual().GetDepth() == GetVisual().GetDepth() - ) - n = 2; // same Display - else - n = 1; // printer or other display - } - else if( pSrcGraphics->bVirDev_ ) - { - // printer compatible virtual device - if( bPrinter_ ) - n = 2; // printer or compatible virtual device == same display - else - n = 1; // window or compatible virtual device - } - else - n = 0; - - if( n == 2 - && rPosAry.mnSrcWidth == rPosAry.mnDestWidth - && rPosAry.mnSrcHeight == rPosAry.mnDestHeight - ) - { - // #i60699# Need to generate graphics exposures (to repaint - // obscured areas beneath overlapping windows), src and dest - // are the same window. - const bool bNeedGraphicsExposures( pSrcGraphics == this && - !bVirDev_ && - pSrcGraphics->bWindow_ ); - - GC pCopyGC; - - if( bXORMode_ - && !pSrcGraphics->bVirDev_ - && (GetDisplay()->GetProperties() & PROPERTY_BUG_XCopyArea_GXxor) ) - { - Pixmap hPixmap = limitXCreatePixmap( GetXDisplay(), - pSrcGraphics->GetDrawable(), // source - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, - pSrcGraphics->GetBitCount() ); - - pCopyGC = GetDisplay()->GetCopyGC( m_nXScreen ); - - if( bNeedGraphicsExposures ) - XSetGraphicsExposures( GetXDisplay(), - pCopyGC, - True ); - - XCopyArea( GetXDisplay(), - pSrcGraphics->GetDrawable(), // source - hPixmap, // destination - pCopyGC, // no clipping - rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, - 0, 0 ); // destination - XCopyArea( GetXDisplay(), - hPixmap, // source - GetDrawable(), // destination - GetInvertGC(), // destination clipping - 0, 0, // source - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, - rPosAry.mnDestX, rPosAry.mnDestY ); - XFreePixmap( GetXDisplay(), hPixmap ); - } - else - { - pCopyGC = GetCopyGC(); - - if( bNeedGraphicsExposures ) - XSetGraphicsExposures( GetXDisplay(), - pCopyGC, - True ); - - XCopyArea( GetXDisplay(), - pSrcGraphics->GetDrawable(), // source - GetDrawable(), // destination - pCopyGC, // destination clipping - rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, - rPosAry.mnDestX, rPosAry.mnDestY ); - } - - if( bNeedGraphicsExposures ) - { - YieldGraphicsExpose(); - - if( pCopyGC ) - XSetGraphicsExposures( GetXDisplay(), - pCopyGC, - False ); - } - } - else if( n ) - { - // #i60699# No chance to handle graphics exposures - we copy - // to a temp bitmap first, into which no repaints are - // technically possible. - boost::scoped_ptr<SalBitmap> pDDB(pSrcGraphics->getBitmap( rPosAry.mnSrcX, - rPosAry.mnSrcY, - rPosAry.mnSrcWidth, - rPosAry.mnSrcHeight )); - - if( !pDDB ) - { - stderr0( "SalGraphics::CopyBits !pSrcGraphics->GetBitmap()\n" ); - return; - } - - SalTwoRect aPosAry( rPosAry ); - - aPosAry.mnSrcX = 0, aPosAry.mnSrcY = 0; - drawBitmap( aPosAry, *pDDB ); - } - else { - stderr0( "X11SalGraphics::CopyBits from Printer not yet implemented\n" ); - } + mpImpl->copyBits( rPosAry, pSSrcGraphics ); } void X11SalGraphics::copyArea ( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, - sal_uInt16 ) + sal_uInt16 n ) { - SalTwoRect aPosAry; - - aPosAry.mnDestX = nDestX; - aPosAry.mnDestY = nDestY; - aPosAry.mnDestWidth = nSrcWidth; - aPosAry.mnDestHeight = nSrcHeight; - - aPosAry.mnSrcX = nSrcX; - aPosAry.mnSrcY = nSrcY; - aPosAry.mnSrcWidth = nSrcWidth; - aPosAry.mnSrcHeight = nSrcHeight; - - copyBits ( aPosAry, 0 ); -} - -namespace -{ - void setForeBack(XGCValues& rValues, const SalColormap& rColMap, const SalBitmap& rSalBitmap) - { - rValues.foreground = rColMap.GetWhitePixel(); - rValues.background = rColMap.GetBlackPixel(); - - //fdo#33455 and fdo#80160 handle 1 bit depth pngs with palette entries - //to set fore/back colors - SalBitmap& rBitmap = const_cast<SalBitmap&>(rSalBitmap); - if (BitmapBuffer* pBitmapBuffer = rBitmap.AcquireBuffer(true)) - { - const BitmapPalette& rPalette = pBitmapBuffer->maPalette; - if (rPalette.GetEntryCount() == 2) - { - const BitmapColor aWhite(rPalette[rPalette.GetBestIndex(Color(COL_WHITE))]); - rValues.foreground = rColMap.GetPixel(ImplColorToSal(aWhite)); - - const BitmapColor aBlack(rPalette[rPalette.GetBestIndex(Color(COL_BLACK))]); - rValues.background = rColMap.GetPixel(ImplColorToSal(aBlack)); - } - rBitmap.ReleaseBuffer(pBitmapBuffer, true); - } - } + mpImpl->copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, n ); } void X11SalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap ) { - const SalDisplay* pSalDisp = GetDisplay(); - Display* pXDisp = pSalDisp->GetDisplay(); - const Drawable aDrawable( GetDrawable() ); - const SalColormap& rColMap = pSalDisp->GetColormap( m_nXScreen ); - const long nDepth = GetDisplay()->GetVisual( m_nXScreen ).GetDepth(); - GC aGC( GetCopyGC() ); - XGCValues aOldVal, aNewVal; - int nValues = GCForeground | GCBackground; - - if( rSalBitmap.GetBitCount() == 1 ) - { - // set foreground/background values for 1Bit bitmaps - XGetGCValues( pXDisp, aGC, nValues, &aOldVal ); - setForeBack(aNewVal, rColMap, rSalBitmap); - XChangeGC( pXDisp, aGC, nValues, &aNewVal ); - } - - static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aDrawable, m_nXScreen, nDepth, rPosAry, aGC ); - - if( rSalBitmap.GetBitCount() == 1 ) - XChangeGC( pXDisp, aGC, nValues, &aOldVal ); - XFlush( pXDisp ); + mpImpl->drawBitmap( rPosAry, rSalBitmap ); } void X11SalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSrcBitmap, const SalBitmap& rMaskBitmap ) { - DBG_ASSERT( !bPrinter_, "Drawing of transparent bitmaps on printer devices is strictly forbidden" ); - - // decide if alpha masking or transparency masking is needed - BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rMaskBitmap).AcquireBuffer( true ); - if( pAlphaBuffer != NULL ) - { - int nMaskFormat = pAlphaBuffer->mnFormat; - const_cast<SalBitmap&>(rMaskBitmap).ReleaseBuffer( pAlphaBuffer, true ); - if( nMaskFormat == BMP_FORMAT_8BIT_PAL ) - drawAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap ); - } - - drawMaskedBitmap( rPosAry, rSrcBitmap, rMaskBitmap ); -} - -void X11SalGraphics::drawMaskedBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - const SalBitmap& rTransBitmap ) -{ - const SalDisplay* pSalDisp = GetDisplay(); - Display* pXDisp = pSalDisp->GetDisplay(); - Drawable aDrawable( GetDrawable() ); - - // figure work mode depth. If this is a VDev Drawable, use its - // bitdepth to create pixmaps for, otherwise, XCopyArea will - // refuse to work. - const sal_uInt16 nDepth( m_pVDev ? - m_pVDev->GetDepth() : - pSalDisp->GetVisual( m_nXScreen ).GetDepth() ); - Pixmap aFG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth, - rPosAry.mnDestHeight, nDepth ) ); - Pixmap aBG( limitXCreatePixmap( pXDisp, aDrawable, rPosAry.mnDestWidth, - rPosAry.mnDestHeight, nDepth ) ); - - if( aFG && aBG ) - { - GC aTmpGC; - XGCValues aValues; - setForeBack(aValues, pSalDisp->GetColormap(m_nXScreen), rSalBitmap); - const int nValues = GCFunction | GCForeground | GCBackground; - SalTwoRect aTmpRect( rPosAry ); aTmpRect.mnDestX = aTmpRect.mnDestY = 0; - - // draw paint bitmap in pixmap #1 - aValues.function = GXcopy; - aTmpGC = XCreateGC( pXDisp, aFG, nValues, &aValues ); - static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aFG, m_nXScreen, nDepth, aTmpRect, aTmpGC ); - DBG_TESTTRANS( aFG ); - - // draw background in pixmap #2 - XCopyArea( pXDisp, aDrawable, aBG, aTmpGC, - rPosAry.mnDestX, rPosAry.mnDestY, - rPosAry.mnDestWidth, rPosAry.mnDestHeight, - 0, 0 ); - - DBG_TESTTRANS( aBG ); - - // mask out paint bitmap in pixmap #1 (transparent areas 0) - aValues.function = GXand, aValues.foreground = 0x00000000, aValues.background = 0xffffffff; - XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); - static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aFG, m_nXScreen, 1, aTmpRect, aTmpGC ); - - DBG_TESTTRANS( aFG ); - - // #105055# For XOR mode, keep background behind bitmap intact - if( !bXORMode_ ) - { - // mask out background in pixmap #2 (nontransparent areas 0) - aValues.function = GXand, aValues.foreground = 0xffffffff, aValues.background = 0x00000000; - XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); - static_cast<const X11SalBitmap&>(rTransBitmap).ImplDraw( aBG, m_nXScreen, 1, aTmpRect, aTmpGC ); - - DBG_TESTTRANS( aBG ); - } - - // merge pixmap #1 and pixmap #2 in pixmap #2 - aValues.function = GXxor, aValues.foreground = 0xffffffff, aValues.background = 0x00000000; - XChangeGC( pXDisp, aTmpGC, nValues, &aValues ); - XCopyArea( pXDisp, aFG, aBG, aTmpGC, - 0, 0, - rPosAry.mnDestWidth, rPosAry.mnDestHeight, - 0, 0 ); - DBG_TESTTRANS( aBG ); - - // #105055# Disable XOR temporarily - bool bOldXORMode( bXORMode_ ); - bXORMode_ = false; - - // copy pixmap #2 (result) to background - XCopyArea( pXDisp, aBG, aDrawable, GetCopyGC(), - 0, 0, - rPosAry.mnDestWidth, rPosAry.mnDestHeight, - rPosAry.mnDestX, rPosAry.mnDestY ); - - DBG_TESTTRANS( aBG ); - - bXORMode_ = bOldXORMode; - - XFreeGC( pXDisp, aTmpGC ); - XFlush( pXDisp ); - } - else - drawBitmap( rPosAry, rSalBitmap ); - - if( aFG ) - XFreePixmap( pXDisp, aFG ); - - if( aBG ) - XFreePixmap( pXDisp, aBG ); + mpImpl->drawBitmap( rPosAry, rSrcBitmap, rMaskBitmap ); } bool X11SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, const SalBitmap& rSrcBitmap, const SalBitmap& rAlphaBmp ) { - // non 8-bit alpha not implemented yet - if( rAlphaBmp.GetBitCount() != 8 ) - return false; - - // horizontal mirroring not implemented yet - if( rTR.mnDestWidth < 0 ) - return false; - - // stretched conversion is not implemented yet - if( rTR.mnDestWidth != rTR.mnSrcWidth ) - return false; - if( rTR.mnDestHeight!= rTR.mnSrcHeight ) - return false; - - // create destination picture - Picture aDstPic = GetXRenderPicture(); - if( !aDstPic ) - return false; - - const SalDisplay* pSalDisp = GetDisplay(); - const SalVisual& rSalVis = pSalDisp->GetVisual( m_nXScreen ); - Display* pXDisplay = pSalDisp->GetDisplay(); - - // create source Picture - int nDepth = m_pVDev ? m_pVDev->GetDepth() : rSalVis.GetDepth(); - const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( rSrcBitmap ); - ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( hDrawable_, m_nXScreen, nDepth, rTR ); - if( !pSrcDDB ) - return false; - - //#i75249# workaround for ImplGetDDB() giving us back a different depth than - // we requested. E.g. mask pixmaps are always compatible with the drawable - // TODO: find an appropriate picture format for these cases - // then remove the workaround below and the one for #i75531# - if( nDepth != pSrcDDB->ImplGetDepth() ) - return false; - - Pixmap aSrcPM = pSrcDDB->ImplGetPixmap(); - if( !aSrcPM ) - return false; - - // create source picture - // TODO: use scoped picture - Visual* pSrcXVisual = rSalVis.GetVisual(); - XRenderPeer& rPeer = XRenderPeer::GetInstance(); - XRenderPictFormat* pSrcVisFmt = rPeer.FindVisualFormat( pSrcXVisual ); - if( !pSrcVisFmt ) - return false; - Picture aSrcPic = rPeer.CreatePicture( aSrcPM, pSrcVisFmt, 0, NULL ); - if( !aSrcPic ) - return false; - - // create alpha Picture - - // TODO: use SalX11Bitmap functionality and caching for the Alpha Pixmap - // problem is that they don't provide an 8bit Pixmap on a non-8bit display - BitmapBuffer* pAlphaBuffer = const_cast<SalBitmap&>(rAlphaBmp).AcquireBuffer( true ); - - // an XImage needs its data top_down - // TODO: avoid wrongly oriented images in upper layers! - const int nImageSize = pAlphaBuffer->mnHeight * pAlphaBuffer->mnScanlineSize; - const char* pSrcBits = (char*)pAlphaBuffer->mpBits; - char* pAlphaBits = new char[ nImageSize ]; - if( BMP_SCANLINE_ADJUSTMENT( pAlphaBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN ) - memcpy( pAlphaBits, pSrcBits, nImageSize ); - else - { - char* pDstBits = pAlphaBits + nImageSize; - const int nLineSize = pAlphaBuffer->mnScanlineSize; - for(; (pDstBits -= nLineSize) >= pAlphaBits; pSrcBits += nLineSize ) - memcpy( pDstBits, pSrcBits, nLineSize ); - } - - // the alpha values need to be inverted for XRender - // TODO: make upper layers use standard alpha - long* pLDst = (long*)pAlphaBits; - for( int i = nImageSize/sizeof(long); --i >= 0; ++pLDst ) - *pLDst = ~*pLDst; - - char* pCDst = (char*)pLDst; - for( int i = nImageSize & (sizeof(long)-1); --i >= 0; ++pCDst ) - *pCDst = ~*pCDst; - - const XRenderPictFormat* pAlphaFormat = rPeer.GetStandardFormatA8(); - XImage* pAlphaImg = XCreateImage( pXDisplay, pSrcXVisual, 8, ZPixmap, 0, - pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight, - pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize ); - - Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, hDrawable_, - rTR.mnDestWidth, rTR.mnDestHeight, 8 ); - - XGCValues aAlphaGCV; - aAlphaGCV.function = GXcopy; - GC aAlphaGC = XCreateGC( pXDisplay, aAlphaPM, GCFunction, &aAlphaGCV ); - XPutImage( pXDisplay, aAlphaPM, aAlphaGC, pAlphaImg, - rTR.mnSrcX, rTR.mnSrcY, 0, 0, rTR.mnDestWidth, rTR.mnDestHeight ); - XFreeGC( pXDisplay, aAlphaGC ); - XFree( pAlphaImg ); - if( pAlphaBits != (char*)pAlphaBuffer->mpBits ) - delete[] pAlphaBits; - - const_cast<SalBitmap&>(rAlphaBmp).ReleaseBuffer( pAlphaBuffer, true ); - - XRenderPictureAttributes aAttr; - aAttr.repeat = int(true); - Picture aAlphaPic = rPeer.CreatePicture( aAlphaPM, pAlphaFormat, CPRepeat, &aAttr ); - if( !aAlphaPic ) - return false; - - // set clipping - if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) - rPeer.SetPictureClipRegion( aDstPic, mpClipRegion ); - - // paint source * mask over destination picture - rPeer.CompositePicture( PictOpOver, aSrcPic, aAlphaPic, aDstPic, - rTR.mnSrcX, rTR.mnSrcY, 0, 0, - rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight ); - - rPeer.FreePicture( aAlphaPic ); - XFreePixmap(pXDisplay, aAlphaPM); - rPeer.FreePicture( aSrcPic ); - return true; + return mpImpl->drawAlphaBitmap( rTR, rSrcBitmap, rAlphaBmp ); } bool X11SalGraphics::drawTransformedBitmap( @@ -740,191 +177,37 @@ bool X11SalGraphics::drawTransformedBitmap( const SalBitmap& rSourceBitmap, const SalBitmap* pAlphaBitmap) { - // here direct support for transformed bitmaps can be impemented - (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap; - return false; + return mpImpl->drawTransformedBitmap( rNull, rX, rY, rSourceBitmap, pAlphaBitmap ); } bool X11SalGraphics::drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) { - if( ! m_pFrame && ! m_pVDev ) - return false; - - if( bPenGC_ || !bBrushGC_ || bXORMode_ ) - return false; // can only perform solid fills without XOR. - - if( m_pVDev && m_pVDev->GetDepth() < 8 ) - return false; - - Picture aDstPic = GetXRenderPicture(); - if( !aDstPic ) - return false; - - const double fTransparency = (100 - nTransparency) * (1.0/100); - const XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency); - - XRenderPeer& rPeer = XRenderPeer::GetInstance(); - rPeer.FillRectangle( PictOpOver, - aDstPic, - &aRenderColor, - nX, nY, - nWidth, nHeight ); - - return true; + return mpImpl->drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency ); } -void X11SalGraphics::drawBitmap( const SalTwoRect&, - const SalBitmap&, - SalColor ) +void X11SalGraphics::drawBitmap( const SalTwoRect& rRect, + const SalBitmap& rBitmap, + SalColor nColor ) { - OSL_FAIL( "::DrawBitmap with transparent color not supported" ); + mpImpl->drawBitmap( rRect, rBitmap, nColor ); } void X11SalGraphics::drawMask( const SalTwoRect& rPosAry, const SalBitmap &rSalBitmap, SalColor nMaskColor ) { - const SalDisplay* pSalDisp = GetDisplay(); - Display* pXDisp = pSalDisp->GetDisplay(); - Drawable aDrawable( GetDrawable() ); - Pixmap aStipple( limitXCreatePixmap( pXDisp, aDrawable, - rPosAry.mnDestWidth, - rPosAry.mnDestHeight, 1 ) ); - - if( aStipple ) - { - SalTwoRect aTwoRect( rPosAry ); aTwoRect.mnDestX = aTwoRect.mnDestY = 0; - GC aTmpGC; - XGCValues aValues; - - // create a stipple bitmap first (set bits are changed to unset bits and vice versa) - aValues.function = GXcopyInverted; - aValues.foreground = 1, aValues.background = 0; - aTmpGC = XCreateGC( pXDisp, aStipple, GCFunction | GCForeground | GCBackground, &aValues ); - static_cast<const X11SalBitmap&>(rSalBitmap).ImplDraw( aStipple, m_nXScreen, 1, aTwoRect, aTmpGC ); - - XFreeGC( pXDisp, aTmpGC ); - - // Set stipple and draw rectangle - GC aStippleGC( GetStippleGC() ); - int nX = rPosAry.mnDestX, nY = rPosAry.mnDestY; - - XSetStipple( pXDisp, aStippleGC, aStipple ); - XSetTSOrigin( pXDisp, aStippleGC, nX, nY ); - XSetForeground( pXDisp, aStippleGC, GetPixel( nMaskColor ) ); - XFillRectangle( pXDisp, aDrawable, aStippleGC, - nX, nY, - rPosAry.mnDestWidth, rPosAry.mnDestHeight ); - XFreePixmap( pXDisp, aStipple ); - XFlush( pXDisp ); - } - else - drawBitmap( rPosAry, rSalBitmap ); + mpImpl->drawMask( rPosAry, rSalBitmap, nMaskColor ); } SalBitmap *X11SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY ) { - if( bPrinter_ && !bVirDev_ ) - return NULL; - - bool bFakeWindowBG = false; - - // normalize - if( nDX < 0 ) - { - nX += nDX; - nDX = -nDX; - } - if ( nDY < 0 ) - { - nY += nDY; - nDY = -nDY; - } - - if( bWindow_ && !bVirDev_ ) - { - XWindowAttributes aAttrib; - - XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib ); - if( aAttrib.map_state != IsViewable ) - bFakeWindowBG = true; - else - { - long nOrgDX = nDX, nOrgDY = nDY; - - // clip to window size - if ( nX < 0 ) - { - nDX += nX; - nX = 0; - } - if ( nY < 0 ) - { - nDY += nY; - nY = 0; - } - if( nX + nDX > aAttrib.width ) - nDX = aAttrib.width - nX; - if( nY + nDY > aAttrib.height ) - nDY = aAttrib.height - nY; - - // inside ? - if( nDX <= 0 || nDY <= 0 ) - { - bFakeWindowBG = true; - nDX = nOrgDX; - nDY = nOrgDY; - } - } - } - - X11SalBitmap* pSalBitmap = new X11SalBitmap; - sal_uInt16 nBitCount = GetBitCount(); - - if( &GetDisplay()->GetColormap( m_nXScreen ) != &GetColormap() ) - nBitCount = 1; - - if( ! bFakeWindowBG ) - pSalBitmap->ImplCreateFromDrawable( GetDrawable(), m_nXScreen, nBitCount, nX, nY, nDX, nDY ); - else - pSalBitmap->Create( Size( nDX, nDY ), (nBitCount > 8) ? 24 : nBitCount, BitmapPalette( nBitCount > 8 ? nBitCount : 0 ) ); - - return pSalBitmap; + return mpImpl->getBitmap( nX, nY, nDX, nDY ); } SalColor X11SalGraphics::getPixel( long nX, long nY ) { - if( bWindow_ && !bVirDev_ ) - { - XWindowAttributes aAttrib; - - XGetWindowAttributes( GetXDisplay(), GetDrawable(), &aAttrib ); - if( aAttrib.map_state != IsViewable ) - { - stderr0( "X11SalGraphics::GetPixel drawable not viewable\n" ); - return 0; - } - } - - XImage *pXImage = XGetImage( GetXDisplay(), - GetDrawable(), - nX, nY, - 1, 1, - AllPlanes, - ZPixmap ); - if( !pXImage ) - { - stderr0( "X11SalGraphics::GetPixel !XGetImage()\n" ); - return 0; - } - - XColor aXColor; - - aXColor.pixel = XGetPixel( pXImage, 0, 0 ); - XDestroyImage( pXImage ); - - return GetColormap().GetColor( aXColor.pixel ); + return mpImpl->getPixel( nX, nY ); } void X11SalGraphics::invert( long nX, @@ -933,25 +216,7 @@ void X11SalGraphics::invert( long nX, long nDY, SalInvert nFlags ) { - GC pGC; - if( SAL_INVERT_50 & nFlags ) - { - pGC = GetInvert50GC(); - XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY ); - } - else - { - if ( SAL_INVERT_TRACKFRAME & nFlags ) - { - pGC = GetTrackingGC(); - XDrawRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY ); - } - else - { - pGC = GetInvertGC(); - XFillRectangle( GetXDisplay(), GetDrawable(), pGC, nX, nY, nDX, nDY ); - } - } + mpImpl->invert( nX, nY, nDX, nDY, nFlags ); } bool X11SalGraphics::supportsOperation( OutDevSupportType eType ) const |