Return-Path: X-Original-To: apmail-openoffice-commits-archive@www.apache.org Delivered-To: apmail-openoffice-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0A40CE626 for ; Tue, 5 Feb 2013 14:16:51 +0000 (UTC) Received: (qmail 23748 invoked by uid 500); 5 Feb 2013 14:16:50 -0000 Delivered-To: apmail-openoffice-commits-archive@openoffice.apache.org Received: (qmail 23702 invoked by uid 500); 5 Feb 2013 14:16:50 -0000 Mailing-List: contact commits-help@openoffice.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openoffice.apache.org Delivered-To: mailing list commits@openoffice.apache.org Received: (qmail 23690 invoked by uid 99); 5 Feb 2013 14:16:50 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Feb 2013 14:16:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Feb 2013 14:16:42 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 403B12388AB9; Tue, 5 Feb 2013 14:16:21 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1442597 [3/3] - in /openoffice/branches/alg/sysdepgs/main: basegfx/inc/basegfx/polygon/ basegfx/inc/basegfx/tools/ basegfx/prj/ basegfx/source/polygon/ basegfx/source/tools/ drawinglayer/ drawinglayer/inc/drawinglayer/processor2d/ drawingl... Date: Tue, 05 Feb 2013 14:16:19 -0000 To: commits@openoffice.apache.org From: alg@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130205141621.403B12388AB9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: openoffice/branches/alg/sysdepgs/main/svx/source/sdr/primitive2d/sdrellipseprimitive2d.cxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/svx/source/sdr/primitive2d/sdrellipseprimitive2d.cxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/svx/source/sdr/primitive2d/sdrellipseprimitive2d.cxx (original) +++ openoffice/branches/alg/sysdepgs/main/svx/source/sdr/primitive2d/sdrellipseprimitive2d.cxx Tue Feb 5 14:16:19 2013 @@ -50,22 +50,25 @@ namespace drawinglayer // Do use createPolygonFromUnitCircle, but let create from first quadrant to mimic old geometry creation. // This is needed to have the same look when stroke is used since the polygon start point defines the // stroke start, too. - basegfx::B2DPolygon aUnitOutline(basegfx::tools::createPolygonFromUnitCircle(1)); + const basegfx::B2DPolygon aUnitOutlinePolygon(basegfx::tools::createPolygonFromUnitCircle(1)); - // scale and move UnitEllipse to UnitObject (-1,-1 1,1) -> (0,0 1,1) - const basegfx::B2DHomMatrix aUnitCorrectionMatrix( - basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5)); + // also prepare a single PolyPolygon from it to have a single reference + const basegfx::B2DPolyPolygon aUnitOutlinePolyPolygon(aUnitOutlinePolygon); - // apply to the geometry - aUnitOutline.transform(aUnitCorrectionMatrix); + // create transformation. Scale and move UnitEllipse to + // UnitObject (-1,-1 1,1) -> (0,0 1,1), then multiply with + // given geometry transformation. This avoids modifying the + // unit outline polygon, thus all will use the same instance + const basegfx::B2DHomMatrix aTransform( + getTransform() * basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5)); // add fill if(!getSdrLFSTAttribute().getFill().isDefault()) { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createPolyPolygonFillPrimitive( - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform(), + aUnitOutlinePolyPolygon, + aTransform, getSdrLFSTAttribute().getFill(), getSdrLFSTAttribute().getFillFloatTransGradient())); } @@ -77,15 +80,15 @@ namespace drawinglayer appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createHiddenGeometryPrimitives2D( false, - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform())); + aUnitOutlinePolyPolygon, + aTransform)); } else { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createPolygonLinePrimitive( - aUnitOutline, - getTransform(), + aUnitOutlinePolygon, + aTransform, getSdrLFSTAttribute().getLine(), attribute::SdrLineStartEndAttribute())); } @@ -95,8 +98,8 @@ namespace drawinglayer { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createTextPrimitive( - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform(), + aUnitOutlinePolyPolygon, + aTransform, getSdrLFSTAttribute().getText(), getSdrLFSTAttribute().getLine(), false, @@ -154,34 +157,40 @@ namespace drawinglayer Primitive2DSequence aRetval; // create unit outline polygon - basegfx::B2DPolygon aUnitOutline(basegfx::tools::createPolygonFromUnitEllipseSegment(mfStartAngle, mfEndAngle)); + basegfx::B2DPolygon aUnitOutlinePolygon( + basegfx::tools::createPolygonFromUnitEllipseSegment( + getStartAngle(), + getEndAngle())); - if(mbCloseSegment) + if(getCloseSegment()) { - if(mbCloseUsingCenter) + if(getCloseUsingCenter()) { // for compatibility, insert the center point at polygon start to get the same // line stroking pattern as the old painting mechanisms. - aUnitOutline.insert(0L, basegfx::B2DPoint(0.0, 0.0)); + aUnitOutlinePolygon.insert(0, basegfx::B2DPoint(0.0, 0.0)); } - aUnitOutline.setClosed(true); + aUnitOutlinePolygon.setClosed(true); } - // move and scale UnitEllipse to UnitObject (-1,-1 1,1) -> (0,0 1,1) - const basegfx::B2DHomMatrix aUnitCorrectionMatrix( - basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5)); + // also prepare a single PolyPolygon from it to have a single reference + const basegfx::B2DPolyPolygon aUnitOutlinePolyPolygon(aUnitOutlinePolygon); - // apply to the geometry - aUnitOutline.transform(aUnitCorrectionMatrix); + // create transformation. Scale and move UnitEllipse to + // UnitObject (-1,-1 1,1) -> (0,0 1,1), then multiply with + // given geometry transformation. This avoids modifying the + // unit outline polygon, thus all will use the same instance + const basegfx::B2DHomMatrix aTransform( + getTransform() * basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5)); // add fill - if(!getSdrLFSTAttribute().getFill().isDefault() && aUnitOutline.isClosed()) + if(!getSdrLFSTAttribute().getFill().isDefault() && aUnitOutlinePolygon.isClosed()) { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createPolyPolygonFillPrimitive( - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform(), + aUnitOutlinePolyPolygon, + aTransform, getSdrLFSTAttribute().getFill(), getSdrLFSTAttribute().getFillFloatTransGradient())); } @@ -193,15 +202,15 @@ namespace drawinglayer appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createHiddenGeometryPrimitives2D( false, - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform())); + aUnitOutlinePolyPolygon, + aTransform)); } else { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createPolygonLinePrimitive( - aUnitOutline, - getTransform(), + aUnitOutlinePolygon, + aTransform, getSdrLFSTAttribute().getLine(), getSdrLFSTAttribute().getLineStartEnd())); } @@ -211,8 +220,8 @@ namespace drawinglayer { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createTextPrimitive( - basegfx::B2DPolyPolygon(aUnitOutline), - getTransform(), + aUnitOutlinePolyPolygon, + aTransform, getSdrLFSTAttribute().getText(), getSdrLFSTAttribute().getLine(), false, @@ -252,10 +261,10 @@ namespace drawinglayer { const SdrEllipseSegmentPrimitive2D& rCompare = (SdrEllipseSegmentPrimitive2D&)rPrimitive; - if( mfStartAngle == rCompare.mfStartAngle - && mfEndAngle == rCompare.mfEndAngle - && mbCloseSegment == rCompare.mbCloseSegment - && mbCloseUsingCenter == rCompare.mbCloseUsingCenter) + if( getStartAngle() == rCompare.getStartAngle() + && getEndAngle() == rCompare.getEndAngle() + && getCloseSegment() == rCompare.getCloseSegment() + && getCloseUsingCenter() == rCompare.getCloseUsingCenter()) { return true; } Modified: openoffice/branches/alg/sysdepgs/main/vcl/inc/vcl/svapp.hxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/inc/vcl/svapp.hxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/inc/vcl/svapp.hxx (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/inc/vcl/svapp.hxx Tue Feb 5 14:16:19 2013 @@ -514,4 +514,16 @@ inline void Application::EndYield() PostUserEvent( Link() ); } +////////////////////////////////////////////////////////////////////////////// +// support for access to buffered instances of BitmapEx and basegfx Polygons +// as Gdiplus objects +#ifdef WNT +namespace Gdiplus { class Bitmap; class GraphicsPath; } +namespace basegfx { class B2DPolygon; class B2DPolyPolygon; } +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::Bitmap > getBufferedGdiPlusBitmapFromBitmapEx(const BitmapEx& rBitmapEx); +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::GraphicsPath > getBufferedGdiPlusGraphicsPathFromB2DPolygon(const basegfx::B2DPolygon& rSource); +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::GraphicsPath > getBufferedGdiPlusGraphicsPathFromB2DPolyPolygon(const basegfx::B2DPolyPolygon& rSource); +#endif +////////////////////////////////////////////////////////////////////////////// + #endif // _APP_HXX Added: openoffice/branches/alg/sysdepgs/main/vcl/inc/win/gdiplusobjectbuffer.hxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/inc/win/gdiplusobjectbuffer.hxx?rev=1442597&view=auto ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/inc/win/gdiplusobjectbuffer.hxx (added) +++ openoffice/branches/alg/sysdepgs/main/vcl/inc/win/gdiplusobjectbuffer.hxx Tue Feb 5 14:16:19 2013 @@ -0,0 +1,76 @@ +/************************************************************** + * + * 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 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef _SV_GDIPLUSOBJECTBUFFER_HXX +#define _SV_GDIPLUSOBJECTBUFFER_HXX + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace Gdiplus +{ + class Bitmap; + class GraphicsPath; +} + +namespace basegfx +{ + class B2DPolygon; + class B2DPolyPolygon; +} + +class WinSalBitmap; + +////////////////////////////////////////////////////////////////////////////// +// Helper class to manage Gdiplus::Bitmap instances created from WinSalBitmap + +class GdiPlusObjectBuffer : public basegfx::cache::cmanager, public Timer +{ +private: +protected: +public: + GdiPlusObjectBuffer(); + virtual ~GdiPlusObjectBuffer(); + + // access to buffered Gdiplus::Bitmap instances created from WinSalBitmap(s) + boost::shared_ptr< Gdiplus::Bitmap > getGdiPlusBitmapFromWinSalBitmap( + const WinSalBitmap& rBitmapSource, + const WinSalBitmap* pAlphaSource); + + // access to Gdiplus::GraphicsPath instances created from basegfx::B2DPolygon/B2DPolyPolygon + boost::shared_ptr< Gdiplus::GraphicsPath > getGdiPlusGraphicsPathFromB2DPolygon( + const basegfx::B2DPolygon& rPolygonSource); + boost::shared_ptr< Gdiplus::GraphicsPath > getGdiPlusGraphicsPathFromB2DPolyPolygon( + const basegfx::B2DPolyPolygon& rPolyPolygonSource); + + virtual void onEmpty(); + virtual void onFilled(); + virtual void Timeout(); +}; + +#endif // _SV_GDIPLUSOBJECTBUFFER_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof Propchange: openoffice/branches/alg/sysdepgs/main/vcl/inc/win/gdiplusobjectbuffer.hxx ------------------------------------------------------------------------------ svn:executable = * Modified: openoffice/branches/alg/sysdepgs/main/vcl/inc/win/salbmp.h URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/inc/win/salbmp.h?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/inc/win/salbmp.h (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/inc/win/salbmp.h Tue Feb 5 14:16:19 2013 @@ -28,6 +28,7 @@ #include #include #include +#include // -------------- // - SalBitmap - @@ -37,34 +38,19 @@ struct BitmapBuffer; class BitmapColor; class BitmapPalette; class SalGraphics; -namespace Gdiplus { class Bitmap; } -typedef boost::shared_ptr< Gdiplus::Bitmap > GdiPlusBmpPtr; -class WinSalBitmap : public SalBitmap +class WinSalBitmap : public SalBitmap, public basegfx::cache::cacheable { private: - friend class GdiPlusBuffer; // allow buffer to remove maGdiPlusBitmap eventually - Size maSize; HGLOBAL mhDIB; HBITMAP mhDDB; - - // the buffered evtl. used Gdiplus::Bitmap instance. It is managed by - // GdiPlusBuffer. To make this safe, it is only handed out as shared - // pointer; the GdiPlusBuffer may delete the local instance - GdiPlusBmpPtr maGdiPlusBitmap; - sal_uInt16 mnBitCount; - Gdiplus::Bitmap* ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource); - Gdiplus::Bitmap* ImplCreateGdiPlusBitmap(); - public: - HGLOBAL ImplGethDIB() const { return mhDIB; } HBITMAP ImplGethDDB() const { return mhDDB; } - GdiPlusBmpPtr ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource = 0) const; static HGLOBAL ImplCreateDIB( const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal ); static HANDLE ImplCopyDIBOrDDB( HANDLE hHdl, bool bDIB ); Modified: openoffice/branches/alg/sysdepgs/main/vcl/inc/win/saldata.hxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/inc/win/saldata.hxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/inc/win/saldata.hxx (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/inc/win/saldata.hxx Tue Feb 5 14:16:19 2013 @@ -19,19 +19,15 @@ * *************************************************************/ - - #ifndef _SV_SALDATA_HXX #define _SV_SALDATA_HXX #include "osl/module.h" - #include #include - #include - -#include // for hMenu validation +#include +#include #include class AutoTimer; @@ -136,6 +132,9 @@ public: // for GdiPlus GdiplusStartup/GdiplusShutdown ULONG_PTR gdiplusToken; + // cache for Gdiplus objects + GdiPlusObjectBuffer maGdiPlusObjectBuffer; + std::set< HMENU > mhMenuSet; // keeps track of menu handles created by VCL, used by IsKnownMenuHandle() std::map< UINT,USHORT > maVKMap; // map some dynamic VK_* entries oslModule maDwmLib; Modified: openoffice/branches/alg/sysdepgs/main/vcl/win/source/app/salinst.cxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/win/source/app/salinst.cxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/win/source/app/salinst.cxx (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/win/source/app/salinst.cxx Tue Feb 5 14:16:19 2013 @@ -470,6 +470,12 @@ void DeInitSalData() CoUninitialize(); SalData* pSalData = GetSalData(); + // flush evtl. cached Gdiplus objects + if(pSalData) + { + pSalData->maGdiPlusObjectBuffer.flush(); + } + // deinit GDIPlus if(pSalData) { Modified: openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salbmp.cxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salbmp.cxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salbmp.cxx (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salbmp.cxx Tue Feb 5 14:16:19 2013 @@ -34,15 +34,6 @@ #include #include -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#include - // ------------------------------------------------------------------ // - Inlines - @@ -54,138 +45,14 @@ inline void ImplSetPixel4( const HPBYTE ( rByte &= 0x0f, rByte |= ( cIndex << 4 ) ); } -// ------------------------------------------------------------------ -// Helper class to manage Gdiplus::Bitmap instances inside of -// WinSalBitmap - -struct Comparator -{ - bool operator()(WinSalBitmap* pA, WinSalBitmap* pB) const - { - return pA < pB; - } -}; - -typedef ::std::map< WinSalBitmap*, sal_uInt32, Comparator > EntryMap; -static const sal_uInt32 nDefaultCycles(60); - -class GdiPlusBuffer : protected comphelper::OBaseMutex, public Timer -{ -private: - EntryMap maEntries; - -public: - GdiPlusBuffer() - : Timer(), - maEntries() - { - SetTimeout(1000); - Stop(); - } - - ~GdiPlusBuffer() - { - Stop(); - } - - void addEntry(WinSalBitmap& rEntry) - { - ::osl::MutexGuard aGuard(m_aMutex); - EntryMap::iterator aFound = maEntries.find(&rEntry); - - if(aFound == maEntries.end()) - { - if(maEntries.empty()) - { - Start(); - } - - maEntries[&rEntry] = nDefaultCycles; - } - } - - void remEntry(WinSalBitmap& rEntry) - { - ::osl::MutexGuard aGuard(m_aMutex); - EntryMap::iterator aFound = maEntries.find(&rEntry); - - if(aFound != maEntries.end()) - { - maEntries.erase(aFound); - - if(maEntries.empty()) - { - Stop(); - } - } - } - - void touchEntry(WinSalBitmap& rEntry) - { - ::osl::MutexGuard aGuard(m_aMutex); - EntryMap::iterator aFound = maEntries.find(&rEntry); - - if(aFound != maEntries.end()) - { - aFound->second = nDefaultCycles; - } - } - - // from parent Timer - virtual void Timeout() - { - ::osl::MutexGuard aGuard(m_aMutex); - EntryMap::iterator aIter(maEntries.begin()); - - while(aIter != maEntries.end()) - { - if(aIter->second) - { - aIter->second--; - aIter++; - } - else - { - EntryMap::iterator aDelete(aIter); - WinSalBitmap* pSource = aDelete->first; - aIter++; - maEntries.erase(aDelete); - - if(maEntries.empty()) - { - Stop(); - } - - // delete at WinSalBitmap after entry is removed; this - // way it would not hurt to call remEntry from there, too - if(pSource->maGdiPlusBitmap.get()) - { - pSource->maGdiPlusBitmap.reset(); - } - } - } - - if(!maEntries.empty()) - { - Start(); - } - } -}; - -// ------------------------------------------------------------------ -// Global instance of GdiPlusBuffer which manages Gdiplus::Bitmap -// instances - -static GdiPlusBuffer aGdiPlusBuffer; - -// ------------------------------------------------------------------ +////////////////////////////////////////////////////////////////////////////// // - WinSalBitmap - WinSalBitmap::WinSalBitmap() -: maSize(), +: basegfx::cache::cacheable(), + maSize(), mhDIB(0), mhDDB(0), - maGdiPlusBitmap(), mnBitCount(0) { } @@ -201,11 +68,6 @@ WinSalBitmap::~WinSalBitmap() void WinSalBitmap::Destroy() { - if(maGdiPlusBitmap.get()) - { - aGdiPlusBuffer.remEntry(*this); - } - if( mhDIB ) GlobalFree( mhDIB ); else if( mhDDB ) @@ -217,274 +79,6 @@ void WinSalBitmap::Destroy() // ------------------------------------------------------------------ -GdiPlusBmpPtr WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource) const -{ - if(maGdiPlusBitmap.get()) - { - aGdiPlusBuffer.touchEntry(const_cast< WinSalBitmap& >(*this)); - } - else - { - if(maSize.Width() > 0 && maSize.Height() > 0) - { - WinSalBitmap* pThat = const_cast< WinSalBitmap* >(this); - - if(pAlphaSource) - { - pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap(*pAlphaSource)); - } - else - { - pThat->maGdiPlusBitmap.reset(pThat->ImplCreateGdiPlusBitmap()); - } - - if(maGdiPlusBitmap.get()) - { - aGdiPlusBuffer.addEntry(*pThat); - } - } - } - - return maGdiPlusBitmap; -} - -// ------------------------------------------------------------------ - -Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap() -{ - Gdiplus::Bitmap* pRetval(0); - WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this); - WinSalBitmap* pExtraWinSalRGB = 0; - - if(!pSalRGB->ImplGethDIB()) - { - // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap - pExtraWinSalRGB = new WinSalBitmap(); - pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); - pSalRGB = pExtraWinSalRGB; - } - - BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); - BitmapBuffer* pExtraRGB = 0; - - if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) - { - // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format - SalTwoRect aSalTwoRect; - - aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; - aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; - aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; - - pExtraRGB = StretchAndConvert( - *pRGB, - aSalTwoRect, - BMP_FORMAT_24BIT_TC_BGR, - 0); - - pSalRGB->ReleaseBuffer(pRGB, true); - pRGB = pExtraRGB; - } - - if(pRGB - && pRGB->mnWidth > 0 - && pRGB->mnHeight > 0 - && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) - { - const sal_uInt32 nW(pRGB->mnWidth); - const sal_uInt32 nH(pRGB->mnHeight); - - pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat24bppRGB); - - if(pRetval) - { - sal_uInt8* pSrcRGB(pRGB->mpBits); - const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); - const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); - - for(sal_uInt32 y(0); y < nH; y++) - { - const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); - - for(sal_uInt32 x(0); x < nW; x++) - { - const sal_uInt8 nB(*pSrcRGB++); - const sal_uInt8 nG(*pSrcRGB++); - const sal_uInt8 nR(*pSrcRGB++); - - pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nR, nG, nB)); - } - - pSrcRGB += nExtraRGB; - } - } - } - - if(pExtraRGB) - { - delete pExtraRGB; - } - else - { - pSalRGB->ReleaseBuffer(pRGB, true); - } - - if(pExtraWinSalRGB) - { - delete pExtraWinSalRGB; - } - - return pRetval; -} - -// ------------------------------------------------------------------ - -Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlphaSource) -{ - Gdiplus::Bitmap* pRetval(0); - WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(this); - WinSalBitmap* pExtraWinSalRGB = 0; - - if(!pSalRGB->ImplGethDIB()) - { - // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap - pExtraWinSalRGB = new WinSalBitmap(); - pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); - pSalRGB = pExtraWinSalRGB; - } - - BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); - BitmapBuffer* pExtraRGB = 0; - - if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) - { - // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format - SalTwoRect aSalTwoRect; - - aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; - aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; - aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; - - pExtraRGB = StretchAndConvert( - *pRGB, - aSalTwoRect, - BMP_FORMAT_24BIT_TC_BGR, - 0); - - pSalRGB->ReleaseBuffer(pRGB, true); - pRGB = pExtraRGB; - } - - WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource); - WinSalBitmap* pExtraWinSalA = 0; - - if(!pSalA->ImplGethDIB()) - { - // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap - pExtraWinSalA = new WinSalBitmap(); - pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount()); - pSalA = pExtraWinSalA; - } - - BitmapBuffer* pA = pSalA->AcquireBuffer(true); - BitmapBuffer* pExtraA = 0; - - if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) - { - // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format - SalTwoRect aSalTwoRect; - - aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; - aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth; - aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight; - const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256); - - pExtraA = StretchAndConvert( - *pA, - aSalTwoRect, - BMP_FORMAT_8BIT_PAL, - &rTargetPalette); - - pSalA->ReleaseBuffer(pA, true); - pA = pExtraA; - } - - if(pRGB - && pA - && pRGB->mnWidth > 0 - && pRGB->mnHeight > 0 - && pRGB->mnWidth == pA->mnWidth - && pRGB->mnHeight == pA->mnHeight - && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN) - && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) - { - // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB - const sal_uInt32 nW(pRGB->mnWidth); - const sal_uInt32 nH(pRGB->mnHeight); - - pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB); - - if(pRetval) - { - sal_uInt8* pSrcRGB(pRGB->mpBits); - sal_uInt8* pSrcA(pA->mpBits); - const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); - const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); - const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); - - for(sal_uInt32 y(0); y < nH; y++) - { - const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); - - for(sal_uInt32 x(0); x < nW; x++) - { - const sal_uInt8 nB(*pSrcRGB++); - const sal_uInt8 nG(*pSrcRGB++); - const sal_uInt8 nR(*pSrcRGB++); - const sal_uInt8 nA(0xff - *pSrcA++); - - pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nA, nR, nG, nB)); - } - - pSrcRGB += nExtraRGB; - pSrcA += nExtraA; - } - } - } - - if(pExtraA) - { - delete pExtraA; - } - else - { - pSalA->ReleaseBuffer(pA, true); - } - - if(pExtraWinSalA) - { - delete pExtraWinSalA; - } - - if(pExtraRGB) - { - delete pExtraRGB; - } - else - { - pSalRGB->ReleaseBuffer(pRGB, true); - } - - if(pExtraWinSalRGB) - { - delete pExtraWinSalRGB; - } - - return pRetval; -} - -// ------------------------------------------------------------------ - bool WinSalBitmap::Create( HANDLE hBitmap, bool bDIB, bool bCopyHandle ) { bool bRet = TRUE; Modified: openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salgdi_gdiplus.cxx URL: http://svn.apache.org/viewvc/openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salgdi_gdiplus.cxx?rev=1442597&r1=1442596&r2=1442597&view=diff ============================================================================== --- openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salgdi_gdiplus.cxx (original) +++ openoffice/branches/alg/sysdepgs/main/vcl/win/source/gdi/salgdi_gdiplus.cxx Tue Feb 5 14:16:19 2013 @@ -51,137 +51,613 @@ #endif #include +#include +#include +#include +#include +#include +#include -// ----------------------------------------------------------------------- +////////////////////////////////////////////////////////////////////////////// -void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin) +class GdiPlusBitmapBufferNode : public basegfx::cache::node { - sal_uInt32 nCount(rPolygon.count()); +private: + boost::shared_ptr< Gdiplus::Bitmap > maGdiPlusBitmapPtr; - if(nCount) +protected: + Gdiplus::Bitmap* createGdiPlusBitmap(const WinSalBitmap& rBitmapSource); + Gdiplus::Bitmap* createGdiPlusBitmap(const WinSalBitmap& rBitmapSource, const WinSalBitmap& rAlphaSource); + +public: + GdiPlusBitmapBufferNode( + GdiPlusObjectBuffer& rBuffer, + const WinSalBitmap& rBitmapSource, + const WinSalBitmap* pAlphaSource); + virtual ~GdiPlusBitmapBufferNode(); + + boost::shared_ptr< Gdiplus::Bitmap > getGdiPlusBitmapPtr() const { return maGdiPlusBitmapPtr; } +}; + +////////////////////////////////////////////////////////////////////////////// + +class GdiPlusGraphicsPathBufferNode : public basegfx::cache::node +{ +private: + boost::shared_ptr< Gdiplus::GraphicsPath > maGdiPlusGraphicsPathPtr; + +protected: + Gdiplus::GraphicsPath* createGdiPlusGraphicsPath(const basegfx::B2DPolygon& rSource); + Gdiplus::GraphicsPath* createGdiPlusGraphicsPath(const basegfx::B2DPolyPolygon& rSource); + +public: + GdiPlusGraphicsPathBufferNode( + GdiPlusObjectBuffer& rBuffer, + const basegfx::B2DPolygon& rSource); + GdiPlusGraphicsPathBufferNode( + GdiPlusObjectBuffer& rBuffer, + const basegfx::B2DPolyPolygon& rSource); + virtual ~GdiPlusGraphicsPathBufferNode(); + + boost::shared_ptr< Gdiplus::GraphicsPath > getGdiPlusGraphicsPathPtr() const { return maGdiPlusGraphicsPathPtr; } +}; + +////////////////////////////////////////////////////////////////////////////// + +GdiPlusObjectBuffer::GdiPlusObjectBuffer() +: basegfx::cache::cmanager(30), // keep for 30 seconds + Timer() +{ + SetTimeout(1000); // one second + Stop(); +} + +GdiPlusObjectBuffer::~GdiPlusObjectBuffer() +{ + Stop(); +} + +boost::shared_ptr< Gdiplus::Bitmap > GdiPlusObjectBuffer::getGdiPlusBitmapFromWinSalBitmap( + const WinSalBitmap& rBitmapSource, + const WinSalBitmap* pAlphaSource) +{ + const Size aSize(rBitmapSource.GetSize()); + + if(aSize.Width() && aSize.Height()) { - const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1); - const bool bControls(rPolygon.areControlPointsUsed()); - basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0)); - Gdiplus::PointF aFCurr(Gdiplus::REAL(aCurr.getX()), Gdiplus::REAL(aCurr.getY())); + const GdiPlusBitmapBufferNode* pEntry = static_cast< const GdiPlusBitmapBufferNode* >(getEntry(rBitmapSource)); - for(sal_uInt32 a(0); a < nEdgeCount; a++) + if(!pEntry) { - const sal_uInt32 nNextIndex((a + 1) % nCount); - const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex)); - const Gdiplus::PointF aFNext(Gdiplus::REAL(aNext.getX()), Gdiplus::REAL(aNext.getY())); + pEntry = new GdiPlusBitmapBufferNode(*this, rBitmapSource, pAlphaSource); + } + else + { + const_cast< GdiPlusBitmapBufferNode* >(pEntry)->touch(); + } - if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex))) - { - const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a)); - const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex)); + return pEntry->getGdiPlusBitmapPtr(); + } - rPath.AddBezier( - aFCurr, - Gdiplus::PointF(Gdiplus::REAL(aCa.getX()), Gdiplus::REAL(aCa.getY())), - Gdiplus::PointF(Gdiplus::REAL(aCb.getX()), Gdiplus::REAL(aCb.getY())), - aFNext); - } - else - { - rPath.AddLine(aFCurr, aFNext); - } + return boost::shared_ptr< Gdiplus::Bitmap >(); +} - if(a + 1 < nEdgeCount) - { - aFCurr = aFNext; +boost::shared_ptr< Gdiplus::GraphicsPath > GdiPlusObjectBuffer::getGdiPlusGraphicsPathFromB2DPolygon( + const basegfx::B2DPolygon& rPolygonSource) +{ + if(rPolygonSource.count()) + { + const GdiPlusGraphicsPathBufferNode* pEntry = static_cast< const GdiPlusGraphicsPathBufferNode* >(getEntry(rPolygonSource.getCacheable())); - if(bNoLineJoin) - { - rPath.StartFigure(); - } - } + if(!pEntry) + { + pEntry = new GdiPlusGraphicsPathBufferNode(*this, rPolygonSource); } + else + { + const_cast< GdiPlusGraphicsPathBufferNode* >(pEntry)->touch(); + } + + return pEntry->getGdiPlusGraphicsPathPtr(); } + + return boost::shared_ptr< Gdiplus::GraphicsPath >(); } -void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin) +boost::shared_ptr< Gdiplus::GraphicsPath > GdiPlusObjectBuffer::getGdiPlusGraphicsPathFromB2DPolyPolygon( + const basegfx::B2DPolyPolygon& rPolyPolygonSource) { - sal_uInt32 nCount(rPolygon.count()); + if(rPolyPolygonSource.count()) + { + const GdiPlusGraphicsPathBufferNode* pEntry = static_cast< const GdiPlusGraphicsPathBufferNode* >(getEntry(rPolyPolygonSource.getCacheable())); - if(nCount) + if(!pEntry) + { + pEntry = new GdiPlusGraphicsPathBufferNode(*this, rPolyPolygonSource); + } + else + { + const_cast< GdiPlusGraphicsPathBufferNode* >(pEntry)->touch(); + } + + return pEntry->getGdiPlusGraphicsPathPtr(); + } + + return boost::shared_ptr< Gdiplus::GraphicsPath >(); +} + +void GdiPlusObjectBuffer::onEmpty() +{ + Stop(); +} + +void GdiPlusObjectBuffer::onFilled() +{ + Start(); +} + +void GdiPlusObjectBuffer::Timeout() +{ + trigger(); + + if(!empty()) { - const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1); - const bool bControls(rPolygon.areControlPointsUsed()); - basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0)); - Gdiplus::Point aICurr(INT(aCurr.getX()), INT(aCurr.getY())); - - for(sal_uInt32 a(0); a < nEdgeCount; a++) - { - const sal_uInt32 nNextIndex((a + 1) % nCount); - const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex)); - const Gdiplus::Point aINext(INT(aNext.getX()), INT(aNext.getY())); - - if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex))) - { - const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a)); - const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex)); - - rPath.AddBezier( - aICurr, - Gdiplus::Point(INT(aCa.getX()), INT(aCa.getY())), - Gdiplus::Point(INT(aCb.getX()), INT(aCb.getY())), - aINext); - } - else - { - rPath.AddLine(aICurr, aINext); - } - - if(a + 1 < nEdgeCount) - { - aICurr = aINext; - - if(bNoLineJoin) - { - rPath.StartFigure(); - } - } + Start(); + } +} + +////////////////////////////////////////////////////////////////////////////// + +Gdiplus::Bitmap* GdiPlusBitmapBufferNode::createGdiPlusBitmap( + const WinSalBitmap& rBitmapSource) +{ + Gdiplus::Bitmap* pRetval(0); + WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(&rBitmapSource); + WinSalBitmap* pExtraWinSalRGB = 0; + + if(!pSalRGB->ImplGethDIB()) + { + // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap + pExtraWinSalRGB = new WinSalBitmap(); + pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); + pSalRGB = pExtraWinSalRGB; + } + + BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); + BitmapBuffer* pExtraRGB = 0; + + if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) + { + // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format + SalTwoRect aSalTwoRect; + + aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; + aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; + aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; + + pExtraRGB = StretchAndConvert( + *pRGB, + aSalTwoRect, + BMP_FORMAT_24BIT_TC_BGR, + 0); + + pSalRGB->ReleaseBuffer(pRGB, true); + pRGB = pExtraRGB; + } + + if(pRGB + && pRGB->mnWidth > 0 + && pRGB->mnHeight > 0 + && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) + { + const sal_uInt32 nW(pRGB->mnWidth); + const sal_uInt32 nH(pRGB->mnHeight); + + pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat24bppRGB); + + if(pRetval) + { + sal_uInt8* pSrcRGB(pRGB->mpBits); + const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); + const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); + + for(sal_uInt32 y(0); y < nH; y++) + { + const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); + + for(sal_uInt32 x(0); x < nW; x++) + { + const sal_uInt8 nB(*pSrcRGB++); + const sal_uInt8 nG(*pSrcRGB++); + const sal_uInt8 nR(*pSrcRGB++); + + pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nR, nG, nB)); + } + + pSrcRGB += nExtraRGB; + } } } + + if(pExtraRGB) + { + delete pExtraRGB; + } + else + { + pSalRGB->ReleaseBuffer(pRGB, true); + } + + if(pExtraWinSalRGB) + { + delete pExtraWinSalRGB; + } + + return pRetval; } -bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency) +Gdiplus::Bitmap* GdiPlusBitmapBufferNode::createGdiPlusBitmap( + const WinSalBitmap& rBitmapSource, + const WinSalBitmap& rAlphaSource) { - const sal_uInt32 nCount(rPolyPolygon.count()); + Gdiplus::Bitmap* pRetval(0); + WinSalBitmap* pSalRGB = const_cast< WinSalBitmap* >(&rBitmapSource); + WinSalBitmap* pExtraWinSalRGB = 0; - if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0)) - { - Gdiplus::Graphics aGraphics(getHDC()); - const sal_uInt8 aTrans((sal_uInt8)255 - (sal_uInt8)basegfx::fround(fTransparency * 255.0)); - Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maFillColor), SALCOLOR_GREEN(maFillColor), SALCOLOR_BLUE(maFillColor)); - Gdiplus::SolidBrush aTestBrush(aTestColor); - Gdiplus::GraphicsPath aPath; + if(!pSalRGB->ImplGethDIB()) + { + // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap + pExtraWinSalRGB = new WinSalBitmap(); + pExtraWinSalRGB->Create(*pSalRGB, pSalRGB->GetBitCount()); + pSalRGB = pExtraWinSalRGB; + } + + BitmapBuffer* pRGB = pSalRGB->AcquireBuffer(true); + BitmapBuffer* pExtraRGB = 0; + + if(pRGB && BMP_FORMAT_24BIT_TC_BGR != (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN)) + { + // convert source bitmap to BMP_FORMAT_24BIT_TC_BGR format if not yet in that format + SalTwoRect aSalTwoRect; + + aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; + aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pRGB->mnWidth; + aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pRGB->mnHeight; + + pExtraRGB = StretchAndConvert( + *pRGB, + aSalTwoRect, + BMP_FORMAT_24BIT_TC_BGR, + 0); + + pSalRGB->ReleaseBuffer(pRGB, true); + pRGB = pExtraRGB; + } - for(sal_uInt32 a(0); a < nCount; a++) - { - if(0 != a) + WinSalBitmap* pSalA = const_cast< WinSalBitmap* >(&rAlphaSource); + WinSalBitmap* pExtraWinSalA = 0; + + if(!pSalA->ImplGethDIB()) + { + // we need DIB for success with AcquireBuffer, create a replacement WinSalBitmap + pExtraWinSalA = new WinSalBitmap(); + pExtraWinSalA->Create(*pSalA, pSalA->GetBitCount()); + pSalA = pExtraWinSalA; + } + + BitmapBuffer* pA = pSalA->AcquireBuffer(true); + BitmapBuffer* pExtraA = 0; + + if(pA && BMP_FORMAT_8BIT_PAL != (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) + { + // convert alpha bitmap to BMP_FORMAT_8BIT_PAL format if not yet in that format + SalTwoRect aSalTwoRect; + + aSalTwoRect.mnSrcX = aSalTwoRect.mnSrcY = aSalTwoRect.mnDestX = aSalTwoRect.mnDestY = 0; + aSalTwoRect.mnSrcWidth = aSalTwoRect.mnDestWidth = pA->mnWidth; + aSalTwoRect.mnSrcHeight = aSalTwoRect.mnDestHeight = pA->mnHeight; + const BitmapPalette& rTargetPalette = Bitmap::GetGreyPalette(256); + + pExtraA = StretchAndConvert( + *pA, + aSalTwoRect, + BMP_FORMAT_8BIT_PAL, + &rTargetPalette); + + pSalA->ReleaseBuffer(pA, true); + pA = pExtraA; + } + + if(pRGB + && pA + && pRGB->mnWidth > 0 + && pRGB->mnHeight > 0 + && pRGB->mnWidth == pA->mnWidth + && pRGB->mnHeight == pA->mnHeight + && BMP_FORMAT_24BIT_TC_BGR == (pRGB->mnFormat & ~BMP_FORMAT_TOP_DOWN) + && BMP_FORMAT_8BIT_PAL == (pA->mnFormat & ~BMP_FORMAT_TOP_DOWN)) + { + // we have alpha and bitmap in known formats, create GdiPlus Bitmap as 32bit ARGB + const sal_uInt32 nW(pRGB->mnWidth); + const sal_uInt32 nH(pRGB->mnHeight); + + pRetval = new Gdiplus::Bitmap(nW, nH, PixelFormat32bppARGB); + + if(pRetval) + { + sal_uInt8* pSrcRGB(pRGB->mpBits); + sal_uInt8* pSrcA(pA->mpBits); + const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3)); + const sal_uInt32 nExtraA(pA->mnScanlineSize - nW); + const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN); + + for(sal_uInt32 y(0); y < nH; y++) { - aPath.StartFigure(); // #i101491# not needed for first run + const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1); + + for(sal_uInt32 x(0); x < nW; x++) + { + const sal_uInt8 nB(*pSrcRGB++); + const sal_uInt8 nG(*pSrcRGB++); + const sal_uInt8 nR(*pSrcRGB++); + const sal_uInt8 nA(0xff - *pSrcA++); + + pRetval->SetPixel(x, nYInsert, Gdiplus::Color(nA, nR, nG, nB)); + } + + pSrcRGB += nExtraRGB; + pSrcA += nExtraA; } + } + } - impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolyPolygon.getB2DPolygon(a), false); - aPath.CloseFigure(); - } + if(pExtraA) + { + delete pExtraA; + } + else + { + pSalA->ReleaseBuffer(pA, true); + } - if(getAntiAliasB2DDraw()) + if(pExtraWinSalA) + { + delete pExtraWinSalA; + } + + if(pExtraRGB) + { + delete pExtraRGB; + } + else + { + pSalRGB->ReleaseBuffer(pRGB, true); + } + + if(pExtraWinSalRGB) + { + delete pExtraWinSalRGB; + } + + return pRetval; +} + +GdiPlusBitmapBufferNode::GdiPlusBitmapBufferNode( + GdiPlusObjectBuffer& rBuffer, + const WinSalBitmap& rBitmapSource, + const WinSalBitmap* pAlphaSource) +: basegfx::cache::node(rBuffer, rBitmapSource), + maGdiPlusBitmapPtr() +{ + if(pAlphaSource) + { + maGdiPlusBitmapPtr.reset(createGdiPlusBitmap(rBitmapSource, *pAlphaSource)); + } + else + { + maGdiPlusBitmapPtr.reset(createGdiPlusBitmap(rBitmapSource)); + } +} + +GdiPlusBitmapBufferNode::~GdiPlusBitmapBufferNode() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + void addGdiPlusGraphicsPath( + Gdiplus::GraphicsPath* pRetval, const basegfx::B2DPolygon& rSource, + bool bForceSingleEdges) + { + const sal_uInt32 nCount(rSource.count()); + + if(nCount) { - aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + const sal_uInt32 nEdgeCount(rSource.isClosed() ? nCount : nCount - 1); + const bool bControls(rSource.areControlPointsUsed()); + basegfx::B2DPoint aCurr(rSource.getB2DPoint(0)); + Gdiplus::PointF aFCurr(Gdiplus::REAL(aCurr.getX()), Gdiplus::REAL(aCurr.getY())); + + for(sal_uInt32 a(0); a < nEdgeCount; a++) + { + const sal_uInt32 nNextIndex((a + 1) % nCount); + const basegfx::B2DPoint aNext(rSource.getB2DPoint(nNextIndex)); + const Gdiplus::PointF aFNext(Gdiplus::REAL(aNext.getX()), Gdiplus::REAL(aNext.getY())); + + if(bControls && (rSource.isNextControlPointUsed(a) || rSource.isPrevControlPointUsed(nNextIndex))) + { + const basegfx::B2DPoint aCa(rSource.getNextControlPoint(a)); + const basegfx::B2DPoint aCb(rSource.getPrevControlPoint(nNextIndex)); + + pRetval->AddBezier( + aFCurr, + Gdiplus::PointF(Gdiplus::REAL(aCa.getX()), Gdiplus::REAL(aCa.getY())), + Gdiplus::PointF(Gdiplus::REAL(aCb.getX()), Gdiplus::REAL(aCb.getY())), + aFNext); + } + else + { + pRetval->AddLine(aFCurr, aFNext); + } + + if(a + 1 < nEdgeCount) + { + aFCurr = aFNext; + + if(bForceSingleEdges) + { + pRetval->StartFigure(); + } + } + } } - else + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// + +Gdiplus::GraphicsPath* GdiPlusGraphicsPathBufferNode::createGdiPlusGraphicsPath(const basegfx::B2DPolygon& rSource) +{ + Gdiplus::GraphicsPath* pRetval = 0; + const sal_uInt32 nCount(rSource.count()); + + if(nCount) + { + pRetval = new Gdiplus::GraphicsPath; + + addGdiPlusGraphicsPath(pRetval, rSource, false); + + if(rSource.isClosed()) + { + pRetval->CloseFigure(); + } + } + + return pRetval; +} + +Gdiplus::GraphicsPath* GdiPlusGraphicsPathBufferNode::createGdiPlusGraphicsPath(const basegfx::B2DPolyPolygon& rSource) +{ + Gdiplus::GraphicsPath* pRetval = 0; + const sal_uInt32 nCount(rSource.count()); + + if(nCount) + { + pRetval = new Gdiplus::GraphicsPath; + bool bFirst(true); + + for(sal_uInt32 a(0); a < nCount; a++) { - aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); + const basegfx::B2DPolygon aPolygon(rSource.getB2DPolygon(a)); + + // try to get an already existing and buffered Gdiplus::GraphicsPath from the single B2DPolygon + boost::shared_ptr< Gdiplus::GraphicsPath > aSource(GetSalData()->maGdiPlusObjectBuffer.getGdiPlusGraphicsPathFromB2DPolygon(aPolygon)); + + if(aSource.get()) + { + if(bFirst) + { + pRetval->StartFigure(); + bFirst = false; + } + + // concatenate partial path + pRetval->AddPath(aSource.get(), FALSE); + + // for PolyPolygon, always close + pRetval->CloseFigure(); + } } + } + + return pRetval; +} + +GdiPlusGraphicsPathBufferNode::GdiPlusGraphicsPathBufferNode( + GdiPlusObjectBuffer& rBuffer, + const basegfx::B2DPolygon& rSource) +: basegfx::cache::node(rBuffer, rSource.getCacheable()), + maGdiPlusGraphicsPathPtr() +{ + maGdiPlusGraphicsPathPtr.reset(createGdiPlusGraphicsPath(rSource)); +} + +GdiPlusGraphicsPathBufferNode::GdiPlusGraphicsPathBufferNode( + GdiPlusObjectBuffer& rBuffer, + const basegfx::B2DPolyPolygon& rSource) +: basegfx::cache::node(rBuffer, rSource.getCacheable()), + maGdiPlusGraphicsPathPtr() +{ + maGdiPlusGraphicsPathPtr.reset(createGdiPlusGraphicsPath(rSource)); +} + +GdiPlusGraphicsPathBufferNode::~GdiPlusGraphicsPathBufferNode() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::Bitmap > getBufferedGdiPlusBitmapFromBitmapEx( + const BitmapEx& rBitmapEx) +{ + const SalBitmap& rSalSrcBmp = *rBitmapEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap(); + const SalBitmap* pSalAlphaBmp = 0; - aGraphics.FillPath(&aTestBrush, &aPath); - } + if(rBitmapEx.IsTransparent()) + { + pSalAlphaBmp = rBitmapEx.ImplGetMaskImpBitmap()->ImplGetSalBitmap(); + } + + return GetSalData()->maGdiPlusObjectBuffer.getGdiPlusBitmapFromWinSalBitmap( + static_cast< const WinSalBitmap& >(rSalSrcBmp), + static_cast< const WinSalBitmap* >(pSalAlphaBmp)); +} - return true; +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::GraphicsPath > getBufferedGdiPlusGraphicsPathFromB2DPolygon( + const basegfx::B2DPolygon& rSource) +{ + return GetSalData()->maGdiPlusObjectBuffer.getGdiPlusGraphicsPathFromB2DPolygon(rSource); +} + +VCL_DLLPUBLIC boost::shared_ptr< Gdiplus::GraphicsPath > getBufferedGdiPlusGraphicsPathFromB2DPolyPolygon( + const basegfx::B2DPolyPolygon& rSource) +{ + return GetSalData()->maGdiPlusObjectBuffer.getGdiPlusGraphicsPathFromB2DPolyPolygon(rSource); +} + +////////////////////////////////////////////////////////////////////////////// + +bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency) +{ + const sal_uInt32 nCount(rPolyPolygon.count()); + + if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0)) + { + const boost::shared_ptr< Gdiplus::GraphicsPath > aPath(getBufferedGdiPlusGraphicsPathFromB2DPolyPolygon(rPolyPolygon)); + + if(aPath.get()) + { + Gdiplus::Graphics aGraphics(getHDC()); + const sal_uInt8 aTrans((sal_uInt8)255 - (sal_uInt8)basegfx::fround(fTransparency * 255.0)); + Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maFillColor), SALCOLOR_GREEN(maFillColor), SALCOLOR_BLUE(maFillColor)); + Gdiplus::SolidBrush aTestBrush(aTestColor); + + if(getAntiAliasB2DDraw()) + { + aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + } + else + { + aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); + } + + aGraphics.FillPath(&aTestBrush, aPath.get()); + } + } + + return true; } bool WinSalGraphics::drawPolyLine( @@ -193,94 +669,104 @@ bool WinSalGraphics::drawPolyLine( { const sal_uInt32 nCount(rPolygon.count()); - if(mbPen && nCount) - { - Gdiplus::Graphics aGraphics(getHDC()); - const sal_uInt8 aTrans = (sal_uInt8)basegfx::fround( 255 * (1.0 - fTransparency) ); - Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor)); - Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX())); - Gdiplus::GraphicsPath aPath; - bool bNoLineJoin(false); - - switch(eLineJoin) - { - default : // basegfx::B2DLINEJOIN_NONE : - { - if(basegfx::fTools::more(rLineWidths.getX(), 0.0)) - { - bNoLineJoin = true; - } - break; - } - case basegfx::B2DLINEJOIN_BEVEL : - { - aTestPen.SetLineJoin(Gdiplus::LineJoinBevel); - break; - } - case basegfx::B2DLINEJOIN_MIDDLE : - case basegfx::B2DLINEJOIN_MITER : - { - const Gdiplus::REAL aMiterLimit(15.0); - aTestPen.SetMiterLimit(aMiterLimit); - aTestPen.SetLineJoin(Gdiplus::LineJoinMiter); - break; - } - case basegfx::B2DLINEJOIN_ROUND : - { - aTestPen.SetLineJoin(Gdiplus::LineJoinRound); - break; - } - } + if(mbPen && nCount) + { + boost::shared_ptr< Gdiplus::GraphicsPath > aPath; + const sal_uInt8 aTrans = (sal_uInt8)basegfx::fround( 255 * (1.0 - fTransparency) ); + Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor)); + Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX())); + bool bNoLineJoin(false); - switch(eLineCap) + switch(eLineJoin) { - default: /*com::sun::star::drawing::LineCap_BUTT*/ + default : // basegfx::B2DLINEJOIN_NONE : + { + if(basegfx::fTools::more(rLineWidths.getX(), 0.0)) + { + bNoLineJoin = true; + } + break; + } + case basegfx::B2DLINEJOIN_BEVEL : { - // nothing to do + aTestPen.SetLineJoin(Gdiplus::LineJoinBevel); break; } - case com::sun::star::drawing::LineCap_ROUND: + case basegfx::B2DLINEJOIN_MIDDLE : + case basegfx::B2DLINEJOIN_MITER : { - aTestPen.SetStartCap(Gdiplus::LineCapRound); - aTestPen.SetEndCap(Gdiplus::LineCapRound); + const Gdiplus::REAL aMiterLimit(15.0); + aTestPen.SetMiterLimit(aMiterLimit); + aTestPen.SetLineJoin(Gdiplus::LineJoinMiter); break; } - case com::sun::star::drawing::LineCap_SQUARE: + case basegfx::B2DLINEJOIN_ROUND : { - aTestPen.SetStartCap(Gdiplus::LineCapSquare); - aTestPen.SetEndCap(Gdiplus::LineCapSquare); + aTestPen.SetLineJoin(Gdiplus::LineJoinRound); break; } } - if(nCount > 250 && basegfx::fTools::more(rLineWidths.getX(), 1.5)) + if(bNoLineJoin) { - impAddB2DPolygonToGDIPlusGraphicsPathInteger(aPath, rPolygon, bNoLineJoin); + // need to create a special version to support the line join mode 'none'. This + // is simply done by creating single edges, so no line joins will be visualized + Gdiplus::GraphicsPath* pNew = new Gdiplus::GraphicsPath; + + addGdiPlusGraphicsPath(pNew, rPolygon, true); + + if(rPolygon.isClosed()) + { + pNew->CloseFigure(); + } + + aPath.reset(pNew); } else { - impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolygon, bNoLineJoin); + // use the buffered common geometry version + aPath = getBufferedGdiPlusGraphicsPathFromB2DPolygon(rPolygon); } - if(rPolygon.isClosed() && !bNoLineJoin) - { - // #i101491# needed to create the correct line joins - aPath.CloseFigure(); - } - - if(getAntiAliasB2DDraw()) + if(aPath.get()) { - aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); - } - else - { - aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); - } + Gdiplus::Graphics aGraphics(getHDC()); + + switch(eLineCap) + { + default: /*com::sun::star::drawing::LineCap_BUTT*/ + { + // nothing to do + break; + } + case com::sun::star::drawing::LineCap_ROUND: + { + aTestPen.SetStartCap(Gdiplus::LineCapRound); + aTestPen.SetEndCap(Gdiplus::LineCapRound); + break; + } + case com::sun::star::drawing::LineCap_SQUARE: + { + aTestPen.SetStartCap(Gdiplus::LineCapSquare); + aTestPen.SetEndCap(Gdiplus::LineCapSquare); + break; + } + } - aGraphics.DrawPath(&aTestPen, &aPath); - } + if(getAntiAliasB2DDraw()) + { + aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + } + else + { + aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); + } + + aGraphics.DrawPath(&aTestPen, aPath.get()); + } + } - return true; + return true; } // ----------------------------------------------------------------------- @@ -354,7 +840,9 @@ bool WinSalGraphics::tryDrawBitmapGdiPlu if(rTR.mnSrcWidth && rTR.mnSrcHeight && rTR.mnDestWidth && rTR.mnDestHeight) { const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSrcBitmap); - GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap()); + boost::shared_ptr< Gdiplus::Bitmap > aARGB(GetSalData()->maGdiPlusObjectBuffer.getGdiPlusBitmapFromWinSalBitmap( + rSalBitmap, + 0)); if(aARGB.get()) { @@ -388,7 +876,9 @@ bool WinSalGraphics::drawAlphaBitmap( { const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSrcBitmap); const WinSalBitmap& rSalAlpha = static_cast< const WinSalBitmap& >(rAlphaBmp); - GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap(&rSalAlpha)); + boost::shared_ptr< Gdiplus::Bitmap > aARGB(GetSalData()->maGdiPlusObjectBuffer.getGdiPlusBitmapFromWinSalBitmap( + rSalBitmap, + &rSalAlpha)); if(aARGB.get()) { @@ -424,7 +914,9 @@ bool WinSalGraphics::drawTransformedBitm { const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSourceBitmap); const WinSalBitmap* pSalAlpha = static_cast< const WinSalBitmap* >(pAlphaBitmap); - GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap(pSalAlpha)); + boost::shared_ptr< Gdiplus::Bitmap > aARGB(GetSalData()->maGdiPlusObjectBuffer.getGdiPlusBitmapFromWinSalBitmap( + rSalBitmap, + pSalAlpha)); if(aARGB.get()) {