vcl/Library_vclplug_gen.mk | 1 vcl/inc/salgdiimpl.hxx | 26 vcl/inc/unx/salgdi.h | 62 - vcl/unx/generic/gdi/gdiimpl.cxx | 1779 ++++++++++++++++++++++++++++++++++++++++ vcl/unx/generic/gdi/gdiimpl.hxx | 262 +++++ vcl/unx/generic/gdi/salgdi.cxx | 842 ------------------ vcl/unx/generic/gdi/salgdi2.cxx | 769 ----------------- 7 files changed, 2127 insertions(+), 1614 deletions(-)
New commits: commit ad1119c4e978858cb9e4f47a23db587d792669af Author: Markus Mohrhard <markus.mohrh...@collabora.co.uk> Date: Wed Oct 22 17:24:48 2014 +0200 no need for these methods to be virtual Change-Id: I23413704b27474f6a59121bb1cbf24ee7484acd2 diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx index 86990f5..254eaa9 100644 --- a/vcl/unx/generic/gdi/gdiimpl.hxx +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -84,9 +84,9 @@ private: ); XID GetXRenderPicture(); - virtual bool drawFilledTrapezoids( const ::basegfx::B2DTrapezoid*, int nTrapCount, double fTransparency ); + bool drawFilledTrapezoids( const ::basegfx::B2DTrapezoid*, int nTrapCount, double fTransparency ); - virtual long GetGraphicsHeight() const; + long GetGraphicsHeight() const; void drawMaskedBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, commit d1da933407de3112fe766c2d05e8b6fd5464b4e2 Author: Markus Mohrhard <markus.mohrh...@collabora.co.uk> Date: Wed Oct 22 16:49:24 2014 +0200 we need to export the SalGraphicsImpl class Change-Id: I569a1aacdb7a87b0e8045863a8569520bd0df09a diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx index 7375240..1230d1c 100644 --- a/vcl/inc/salgdiimpl.hxx +++ b/vcl/inc/salgdiimpl.hxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <vcl/dllapi.h> + #include <rtl/ustring.hxx> #include <tools/solar.h> @@ -30,7 +32,7 @@ class SalGraphics; class SalBitmap; -class SalGraphicsImpl +class VCL_PLUGIN_PUBLIC SalGraphicsImpl { public: commit 492768e3a4e9d497d4b6784ab59f239301542eea Author: Markus Mohrhard <markus.mohrh...@collabora.co.uk> Date: Tue Oct 21 15:15:47 2014 +0200 use Impl for unix vcl plugins Change-Id: I110df787e1d4b817ab6e682fd9bf50a24332fafd diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk index c3f00aa..634fa74 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 58d6c1a..7375240 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 d34c5d1..0d1a584 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 0000000..e95bee5 --- /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 0000000..86990f5 --- /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 4441458..539856d 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; ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits