summaryrefslogtreecommitdiff
path: root/canvas/source/directx
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/directx')
-rwxr-xr-xcanvas/source/directx/dx_5rm.cxx2286
-rwxr-xr-xcanvas/source/directx/dx_9rm.cxx1366
-rwxr-xr-xcanvas/source/directx/dx_bitmap.cxx222
-rwxr-xr-xcanvas/source/directx/dx_bitmap.hxx96
-rwxr-xr-xcanvas/source/directx/dx_bitmapcanvashelper.cxx249
-rwxr-xr-xcanvas/source/directx/dx_bitmapcanvashelper.hxx139
-rw-r--r--canvas/source/directx/dx_bitmapprovider.hxx48
-rw-r--r--canvas/source/directx/dx_canvas.cxx258
-rw-r--r--canvas/source/directx/dx_canvas.hxx179
-rwxr-xr-xcanvas/source/directx/dx_canvasbitmap.cxx280
-rwxr-xr-xcanvas/source/directx/dx_canvasbitmap.hxx107
-rwxr-xr-xcanvas/source/directx/dx_canvascustomsprite.cxx126
-rwxr-xr-xcanvas/source/directx/dx_canvascustomsprite.hxx142
-rwxr-xr-xcanvas/source/directx/dx_canvasfont.cxx183
-rwxr-xr-xcanvas/source/directx/dx_canvasfont.hxx107
-rwxr-xr-xcanvas/source/directx/dx_canvashelper.cxx815
-rwxr-xr-xcanvas/source/directx/dx_canvashelper.hxx260
-rwxr-xr-xcanvas/source/directx/dx_canvashelper_texturefill.cxx740
-rwxr-xr-xcanvas/source/directx/dx_config.cxx179
-rw-r--r--canvas/source/directx/dx_config.hxx92
-rwxr-xr-xcanvas/source/directx/dx_devicehelper.cxx239
-rwxr-xr-xcanvas/source/directx/dx_devicehelper.hxx124
-rwxr-xr-xcanvas/source/directx/dx_gdiplususer.cxx84
-rwxr-xr-xcanvas/source/directx/dx_gdiplususer.hxx58
-rw-r--r--canvas/source/directx/dx_graphicsprovider.hxx56
-rw-r--r--canvas/source/directx/dx_ibitmap.hxx73
-rwxr-xr-xcanvas/source/directx/dx_impltools.cxx628
-rwxr-xr-xcanvas/source/directx/dx_impltools.hxx138
-rwxr-xr-xcanvas/source/directx/dx_linepolypolygon.cxx68
-rwxr-xr-xcanvas/source/directx/dx_linepolypolygon.hxx59
-rwxr-xr-xcanvas/source/directx/dx_rendermodule.hxx93
-rwxr-xr-xcanvas/source/directx/dx_sprite.hxx54
-rwxr-xr-xcanvas/source/directx/dx_spritecanvas.cxx214
-rwxr-xr-xcanvas/source/directx/dx_spritecanvas.hxx159
-rwxr-xr-xcanvas/source/directx/dx_spritecanvashelper.cxx385
-rwxr-xr-xcanvas/source/directx/dx_spritecanvashelper.hxx164
-rw-r--r--canvas/source/directx/dx_spritedevicehelper.cxx262
-rw-r--r--canvas/source/directx/dx_spritedevicehelper.hxx117
-rwxr-xr-xcanvas/source/directx/dx_spritehelper.cxx219
-rwxr-xr-xcanvas/source/directx/dx_spritehelper.hxx114
-rw-r--r--canvas/source/directx/dx_surfacebitmap.cxx807
-rw-r--r--canvas/source/directx/dx_surfacebitmap.hxx150
-rwxr-xr-xcanvas/source/directx/dx_surfacegraphics.cxx88
-rwxr-xr-xcanvas/source/directx/dx_surfacegraphics.hxx48
-rwxr-xr-xcanvas/source/directx/dx_textlayout.cxx283
-rwxr-xr-xcanvas/source/directx/dx_textlayout.hxx118
-rwxr-xr-xcanvas/source/directx/dx_textlayout_drawhelper.cxx315
-rwxr-xr-xcanvas/source/directx/dx_textlayout_drawhelper.hxx89
-rwxr-xr-xcanvas/source/directx/dx_vcltools.cxx526
-rwxr-xr-xcanvas/source/directx/dx_vcltools.hxx67
-rwxr-xr-xcanvas/source/directx/dx_winstuff.hxx222
-rw-r--r--canvas/source/directx/exports.dxp3
-rw-r--r--canvas/source/directx/makefile.mk223
53 files changed, 14121 insertions, 0 deletions
diff --git a/canvas/source/directx/dx_5rm.cxx b/canvas/source/directx/dx_5rm.cxx
new file mode 100755
index 000000000000..4937934732cd
--- /dev/null
+++ b/canvas/source/directx/dx_5rm.cxx
@@ -0,0 +1,2286 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_5rm.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#if DIRECTX_VERSION < 0x0900
+
+// Nvidia GeForce Go 6800 crashes with a bluescreen if we take the
+// maximum texture size, which would be twice as large. this behaviors
+// has only been observed on directx5.
+// This value is simply the maximum size for textures we request from
+// the system, it has absolutely nothing to do with the size of primitives
+// we're able to render, both concepts are totally independent from each other.
+#define MAX_TEXTURE_SIZE (2048)
+#define MIN_TEXTURE_SIZE (32)
+//#define FAKE_MAX_NUMBER_TEXTURES (2)
+//#define FAKE_MAX_TEXTURE_SIZE (512)
+
+//////////////////////////////////////////////////////////////////////////////////
+// includes
+//////////////////////////////////////////////////////////////////////////////////
+#include <vcl/syschild.hxx>
+#include <vcl/window.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/elapsedtime.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/isurface.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <tools/diagnose_ex.h>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#define COMPILE_MULTIMON_STUBS
+
+#include "dx_rendermodule.hxx"
+#include "dx_surfacegraphics.hxx"
+#include <vcl/sysdata.hxx>
+
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#include "dx_impltools.hxx"
+#include <malloc.h>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+#undef COMPILE_MULTIMON_STUBS
+
+#include <stdio.h>
+
+#define MONITOR_DEFAULTTONULL 0x00000000
+#define MONITOR_DEFAULTTOPRIMARY 0x00000001
+#define MONITOR_DEFAULTTONEAREST 0x00000002
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////////
+// 'dxcanvas' namespace
+//////////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ namespace
+ {
+ bool doBlit( const ::basegfx::B2IPoint& rDestPos,
+ IDirectDrawSurface& rOutSurface,
+ const ::basegfx::B2IRange& rSourceArea,
+ IDirectDrawSurface& rSourceSurface,
+ DDBLTFX* pBltFx,
+ bool bForceSoftware )
+ {
+ if( !bForceSoftware )
+ {
+ // blit surface to backbuffer
+ RECT aOutRect =
+ {
+ rDestPos.getX(),
+ rDestPos.getY(),
+ rDestPos.getX() + static_cast<sal_Int32>(rSourceArea.getWidth()),
+ rDestPos.getY() + static_cast<sal_Int32>(rSourceArea.getHeight()),
+ };
+ RECT aSourceRect =
+ {
+ rSourceArea.getMinX(),
+ rSourceArea.getMinY(),
+ rSourceArea.getMaxX(),
+ rSourceArea.getMaxY()
+ };
+
+ if( SUCCEEDED(rOutSurface.Blt( &aOutRect,
+ &rSourceSurface,
+ &aSourceRect,
+ DDBLT_WAIT,
+ pBltFx )) )
+ {
+ return true;
+ }
+ }
+
+ // failed, or forced to use SW copy. attempt manual copy.
+ bool bResult = false;
+
+ // lock source surface
+ DDSURFACEDESC aDescSrc;
+ rtl_fillMemory(&aDescSrc,sizeof(DDSURFACEDESC),0);
+ aDescSrc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwSrcFlags = DDLOCK_NOSYSLOCK|
+ DDLOCK_SURFACEMEMORYPTR|
+ DDLOCK_WAIT|
+ DDLOCK_READONLY;
+ if(SUCCEEDED(rSourceSurface.Lock(NULL,
+ &aDescSrc,
+ dwSrcFlags,
+ NULL)))
+ {
+ // lock destination surface
+ DDSURFACEDESC aDescDst;
+ rtl_fillMemory(&aDescDst,sizeof(DDSURFACEDESC),0);
+ aDescDst.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwDstFlags = DDLOCK_NOSYSLOCK|
+ DDLOCK_SURFACEMEMORYPTR|
+ DDLOCK_WAIT|
+ DDLOCK_WRITEONLY;
+ if(SUCCEEDED(rOutSurface.Lock(NULL,
+ &aDescDst,
+ dwDstFlags,
+ NULL)))
+ {
+ sal_uInt32 nSrcFormat;
+ nSrcFormat = ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwRBitMask)<<8;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwGBitMask)<<4;
+ nSrcFormat |= ::canvas::tools::bitcount32(aDescSrc.ddpfPixelFormat.dwBBitMask);
+
+ sal_uInt32 nDstFormat;
+ nDstFormat = ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwRBitMask)<<8;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwGBitMask)<<4;
+ nDstFormat |= ::canvas::tools::bitcount32(aDescDst.ddpfPixelFormat.dwBBitMask);
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ const sal_uInt32 nWidth( static_cast<sal_uInt32>(
+ rSourceArea.getWidth() ) );
+ const sal_uInt32 nHeight( static_cast<sal_uInt32>(
+ rSourceArea.getHeight() ) );
+
+ if((nSrcFormat == 0x8888) && (nDstFormat == 0x0565))
+ {
+ // medium range 8888 to 0565 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<1);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ sal_uInt32 srcPixel = *pSrcScanline++;
+ sal_uInt16 dstPixel;
+ dstPixel = (sal_uInt16)((srcPixel & 0x0000F8) >> 3);
+ dstPixel |= (srcPixel & 0x00FC00) >> 5;
+ dstPixel |= (srcPixel & 0xF80000) >> 8;
+ *pDstScanline++ = dstPixel;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+ else if((nSrcFormat == 0x8888) && (nDstFormat == 0x0888))
+ {
+ // medium range 8888 to 0888 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<2);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32 *)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ *pDstScanline++ = (sal_uInt16)*pSrcScanline++;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+ else if((nSrcFormat == 0x8888) && (nDstFormat == 0x1555))
+ {
+ // medium range 8888 to 1555 pixel format conversion.
+ bResult = true;
+ sal_uInt8 *pSrcSurface = (sal_uInt8 *)aDescSrc.lpSurface +
+ rSourceArea.getMinY()*aDescSrc.lPitch +
+ (rSourceArea.getMinX()<<2);
+ sal_uInt8 *pDstSurface = (sal_uInt8 *)aDescDst.lpSurface +
+ rDestPos.getY()*aDescDst.lPitch +
+ (rDestPos.getX()<<1);
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ sal_uInt32 *pSrcScanline = (sal_uInt32*)pSrcSurface;
+ sal_uInt16 *pDstScanline = (sal_uInt16 *)pDstSurface;
+ for(sal_uInt32 x=0; x<nWidth; ++x)
+ {
+ sal_uInt32 srcPixel = *pSrcScanline++;
+ sal_uInt16 dstPixel;
+ dstPixel = (sal_uInt16)((srcPixel & 0x000000F8) >> 3);
+ dstPixel |= (srcPixel & 0x0000F800) >> 6;
+ dstPixel |= (srcPixel & 0x00F80000) >> 9;
+ dstPixel |= (srcPixel & 0x80000000) >> 16;
+ *pDstScanline++ = dstPixel;
+ }
+ pSrcSurface += aDescSrc.lPitch;
+ pDstSurface += aDescDst.lPitch;
+ }
+ }
+
+ // unlock destination surface
+ rOutSurface.Unlock(NULL);
+ }
+
+ // unlock source surface
+ rSourceSurface.Unlock(NULL);
+ }
+
+ return bResult;
+ }
+
+ void dumpSurface( const COMReference<IDirectDrawSurface> &pSurface, const char *szFilename )
+ {
+ if(!(pSurface.get()))
+ return;
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( FAILED(pSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ return;
+
+ const std::size_t dwBitmapSize(aSurfaceDesc.dwWidth*aSurfaceDesc.dwHeight*4);
+ sal_uInt8 *pBuffer = static_cast<sal_uInt8 *>(_alloca(dwBitmapSize));
+ if(pBuffer)
+ {
+ sal_uInt8 *pSource = reinterpret_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
+ sal_uInt8 *pDest = reinterpret_cast<sal_uInt8 *>(pBuffer);
+ const std::size_t dwDestPitch(aSurfaceDesc.dwWidth<<2);
+ pDest += aSurfaceDesc.dwHeight*dwDestPitch;
+ for(sal_uInt32 y=0; y<aSurfaceDesc.dwHeight; ++y)
+ {
+ pDest -= dwDestPitch;
+ rtl_copyMemory( pDest, pSource, dwDestPitch );
+ pSource += aSurfaceDesc.lPitch;
+ }
+
+ if(FILE *fp = fopen(szFilename,"wb"))
+ {
+ BITMAPINFOHEADER bitmapInfo;
+
+ bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.biWidth = aSurfaceDesc.dwWidth;
+ bitmapInfo.biHeight = aSurfaceDesc.dwHeight;
+ bitmapInfo.biPlanes = 1;
+ bitmapInfo.biBitCount = 32;
+ bitmapInfo.biCompression = BI_RGB;
+ bitmapInfo.biSizeImage = 0;
+ bitmapInfo.biXPelsPerMeter = 0;
+ bitmapInfo.biYPelsPerMeter = 0;
+ bitmapInfo.biClrUsed = 0;
+ bitmapInfo.biClrImportant = 0;
+
+ const std::size_t dwFileSize(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwBitmapSize);
+
+ BITMAPFILEHEADER header;
+ header.bfType = 'MB';
+ header.bfSize = dwFileSize;
+ header.bfReserved1 = 0;
+ header.bfReserved2 = 0;
+ header.bfOffBits = sizeof(BITMAPFILEHEADER) + bitmapInfo.biSize;
+
+ fwrite(&header,1,sizeof(BITMAPFILEHEADER),fp);
+ fwrite(&bitmapInfo,1,sizeof(BITMAPINFOHEADER),fp);
+ fwrite(pBuffer,1,dwBitmapSize,fp);
+
+ fclose(fp);
+ }
+ }
+
+ pSurface->Unlock(NULL);
+ }
+
+ void clearSurface( const COMReference<IDirectDrawSurface>& pSurface )
+ {
+ if(!(pSurface.is()))
+ return;
+
+ DDBLTFX aBltFx;
+
+ rtl_fillMemory( &aBltFx,
+ sizeof(DDBLTFX), 0 );
+ aBltFx.dwSize = sizeof(DDBLTFX);
+ aBltFx.dwFillColor = 0;
+
+ pSurface->Blt( NULL,
+ NULL,
+ NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT,
+ &aBltFx );
+ }
+
+ // Define struct for MonitorEntry
+ struct MonitorEntry
+ {
+ GUID mnGUID;
+ HMONITOR mhMonitor;
+ MONITORINFO maMonitorInfo;
+ };
+
+ // define type for MonitorList
+ typedef ::std::vector< MonitorEntry > MonitorList;
+
+ // Win32 system callback for DirectDrawEnumerateExA call
+ BOOL WINAPI EnumerateExA_Callback( GUID FAR* lpGUID,
+ LPSTR /*lpDriverDescription*/,
+ LPSTR /*lpDriverName*/,
+ LPVOID lpContext,
+ HMONITOR hMonitor )
+ {
+ if(lpGUID)
+ {
+ MonitorList* pMonitorList = (MonitorList*)lpContext;
+ MonitorEntry aEntry;
+
+ aEntry.mnGUID = *lpGUID;
+ aEntry.mhMonitor = hMonitor;
+ aEntry.maMonitorInfo.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfo( hMonitor,
+ &aEntry.maMonitorInfo );
+
+ pMonitorList->push_back(aEntry);
+ }
+
+ return DDENUMRET_OK;
+ }
+
+ void fillMonitorList( MonitorList& rMonitorList )
+ {
+ // Try to fill MonitorList. If neither lib or call to
+ // DirectDrawEnumerateExA does not exist, it's an old
+ // DX version (< 5.0), or system does not support
+ // multiple monitors.
+ HINSTANCE hInstance = LoadLibrary("ddraw.dll");
+
+ if(hInstance)
+ {
+ LPDIRECTDRAWENUMERATEEX lpDDEnumEx =
+ (LPDIRECTDRAWENUMERATEEX)GetProcAddress(hInstance,"DirectDrawEnumerateExA");
+
+ if(lpDDEnumEx)
+ lpDDEnumEx( (LPDDENUMCALLBACKEXA) EnumerateExA_Callback,
+ &rMonitorList,
+ DDENUM_ATTACHEDSECONDARYDEVICES );
+
+ FreeLibrary(hInstance);
+ }
+ }
+
+ IDirectDraw2* createDirectDraw( const MonitorList& rMonitorList,
+ MONITORINFO& rMonitorInfo,
+ HWND renderWindow )
+ {
+ GUID* gpSelectedDriverGUID = NULL;
+
+ // if we have multiple monitors, choose a gpSelectedDriverGUID from monitor list
+ HMONITOR hMonitor = MonitorFromWindow(renderWindow,
+ MONITOR_DEFAULTTONEAREST);
+
+ MonitorList::const_iterator aCurr = rMonitorList.begin();
+ const MonitorList::const_iterator aEnd = rMonitorList.end();
+ while( !gpSelectedDriverGUID && aCurr != aEnd )
+ {
+ if(hMonitor == aCurr->mhMonitor)
+ {
+ // This is the monitor we are running on
+ gpSelectedDriverGUID = const_cast<GUID*>(&aCurr->mnGUID);
+ rMonitorInfo = aCurr->maMonitorInfo;
+ }
+
+ ++aCurr;
+ }
+
+ IDirectDraw* pDirectDraw;
+ if( FAILED( DirectDrawCreate( gpSelectedDriverGUID, &pDirectDraw, NULL )))
+ return NULL;
+
+ IDirectDraw2* pDirectDraw2;
+ if( FAILED( pDirectDraw->QueryInterface( IID_IDirectDraw2, (LPVOID*)&pDirectDraw2 )))
+ return NULL;
+
+ // queryInterface bumped up the refcount, so release the
+ // reference to the original IDirectDraw interface.
+ pDirectDraw->Release();
+
+ return pDirectDraw2;
+ }
+
+ HRESULT WINAPI EnumTextureFormatsCallback( LPDDSURFACEDESC pSurfaceDesc,
+ LPVOID pContext )
+ {
+ // dirty cast of given context back to result ModeSelectContext
+ DDPIXELFORMAT* pResult = (DDPIXELFORMAT*)pContext;
+
+ if( pResult == NULL || pSurfaceDesc == NULL )
+ return DDENUMRET_CANCEL;
+
+ VERBOSE_TRACE( "EnumTextureFormatsCallback: advertised texture format has dwRGBBitCount %d, dwRBitMask %x, "
+ "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The format uses %s alpha.",
+ pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
+ pSurfaceDesc->ddpfPixelFormat.dwRBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwGBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwBBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwRGBAlphaBitMask,
+ pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
+
+ // Only accept RGB surfaces with alpha channel
+ if( (DDPF_ALPHAPIXELS | DDPF_RGB) ==
+ (pSurfaceDesc->ddpfPixelFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) )
+ {
+ // ignore formats with the DDPF_ALPHAPREMULT flag
+ if(!(pSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_ALPHAPREMULT))
+ {
+ // take widest alpha channel available
+ if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth > pResult->dwAlphaBitDepth )
+ {
+ // take new format
+ rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
+ }
+ else if( pSurfaceDesc->ddpfPixelFormat.dwAlphaBitDepth == pResult->dwAlphaBitDepth )
+ {
+ // tie-breaking: take highest bitcount
+ if( pSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > pResult->dwRGBBitCount )
+ {
+ // take new format
+ rtl_copyMemory( pResult, &pSurfaceDesc->ddpfPixelFormat, sizeof(DDPIXELFORMAT) );
+ }
+ }
+ }
+ }
+
+ return DDENUMRET_OK;
+ }
+
+ class DXRenderModule;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** ISurface implemenation.
+
+ @attention holds the DXRenderModule via non-refcounted
+ reference! This is safe with current state of affairs, since
+ the canvas::PageManager holds surface and render module via
+ shared_ptr (and makes sure all surfaces are deleted before its
+ render module member goes out of scope).
+ */
+ class DXSurface : public canvas::ISurface
+ {
+ public:
+ DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize );
+ ~DXSurface();
+
+ virtual bool selectTexture();
+ virtual bool isValid();
+ virtual bool update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource );
+ virtual ::basegfx::B2IVector getSize();
+
+ private:
+ /// Guard local methods against concurrent acces to RenderModule
+ class ImplRenderModuleGuard : private ::boost::noncopyable
+ {
+ public:
+ explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule );
+ inline ~ImplRenderModuleGuard();
+
+ private:
+ DXRenderModule& mrRenderModule;
+ };
+
+ DXRenderModule& mrRenderModule;
+
+ COMReference<IDirectDrawSurface> mpSurface;
+ COMReference<IDirect3DTexture2> mpTexture;
+
+ ::basegfx::B2IVector maSize;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /// Default implementation of IDXRenderModule
+ class DXRenderModule : public IDXRenderModule
+ {
+ public:
+ explicit DXRenderModule( const ::Window& rWindow );
+
+ virtual void lock() const { maMutex.acquire(); }
+ virtual void unlock() const { maMutex.release(); }
+
+ virtual COMReference<IDirectDrawSurface>
+ createSystemMemorySurface( const ::basegfx::B2IVector& rSize );
+
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea );
+
+ virtual void resize( const ::basegfx::B2IRange& rect );
+ virtual HWND getHWND() const { return mhWnd; }
+ virtual void disposing();
+ virtual void screenShot();
+ virtual ::basegfx::B2IVector getPageSize();
+ virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize );
+ virtual void beginPrimitive( PrimitiveType eType );
+ virtual void endPrimitive();
+ virtual void pushVertex( const ::canvas::Vertex& vertex );
+ virtual bool isError();
+
+ const D3DDEVICEDESC& getDeviceDesc() const { return maDeviceDesc; }
+ const DDPIXELFORMAT& getTextureFormat() const { return maTextureFormat; }
+ COMReference<IDirectDraw2> getDirectDraw() { return mpDirectDraw; }
+ COMReference< IDirect3DDevice2 > getDevice() { return mpDirect3DDevice; }
+
+ void flushVertexCache();
+
+ struct ModeSelectContext
+ {
+ DDSURFACEDESC selectedDesc;
+ ::basegfx::B2ISize requestedSize;
+ };
+
+ /** Query actual size of the device
+
+ This is especially interesting for fullscreen devices
+ */
+ ::basegfx::B2ISize getFramebufferSize() const;
+
+ /** Query the amount of memory available for new surfaces
+
+ This might differ from getAvailableTextureMem()
+ @see getAvailableTextureMem()
+
+ @param bWithAGPMema
+ When true, returned value includes non-local,
+ i.e. AGP-able memory, too.
+
+ @return the amount of free surface mem
+ */
+ std::size_t getAvailableSurfaceMem( bool bWithAGPMem=true ) const;
+
+ /** Query the amount of memory available for new textures
+
+ This might differ from getAvailableSurfaceMem()
+ @see getAvailableSurfaceMem()
+
+ @param bWithAGPMema
+ When true, returned value includes non-local,
+ i.e. AGP-able memory, too.
+
+ @return the amount of free texture mem
+ */
+ std::size_t getAvailableTextureMem( bool bWithAGPMem=true ) const;
+
+ private:
+ bool queryCaps();
+ bool validateCaps();
+ bool setup3DDevice();
+ unsigned int getDisplayFormat() const;
+
+ void convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
+ ::basegfx::B2IRange& io_rDestArea );
+
+ void renderInfoText( const ::rtl::OUString& rStr,
+ const Gdiplus::PointF& rPos ) const;
+ void renderFPSCounter() const;
+ void renderMemAvailable() const;
+
+ bool create( const ::Window& rWindow );
+ bool validateMainSurfaces();
+
+ /** This object represents the DirectX state machine. In order
+ to serialize access to DirectX's global state, a global
+ mutex is required.
+ */
+ static ::osl::Mutex maMutex;
+
+ HWND mhWnd;
+ ::boost::scoped_ptr<SystemChildWindow> mpWindow;
+ ::basegfx::B2IVector maSize;
+
+ ModeSelectContext maSelectedFullscreenMode;
+ DDPIXELFORMAT maTextureFormat;
+
+ MONITORINFO maMonitorInfo; // monitor info for mpDirectDraw's monitor
+ COMReference<IDirectDraw2> mpDirectDraw;
+ COMReference<IDirectDrawSurface> mpPrimarySurface;
+ COMReference<IDirectDrawSurface> mpBackBufferSurface;
+
+ COMReference< IDirect3D2 > mpDirect3D;
+ COMReference< IDirect3DDevice2 > mpDirect3DDevice;
+
+ mutable ::canvas::tools::ElapsedTime maLastUpdate; // for the frame counter
+
+ D3DDEVICEDESC maDeviceDesc;
+
+ typedef std::vector<canvas::Vertex> vertexCache_t;
+ vertexCache_t maVertexCache;
+ std::size_t mnCount;
+
+ int mnBeginSceneCount;
+
+ const bool mbPageFlipping;
+ bool mbHasNoTearingBlt;
+ bool mbError;
+ PrimitiveType meType;
+
+ ::canvas::ISurfaceSharedPtr mpTexture;
+ ::basegfx::B2IVector maPageSize;
+ };
+
+ ::osl::Mutex DXRenderModule::maMutex;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::ImplRenderModuleGuard
+ //////////////////////////////////////////////////////////////////////////////////
+
+ inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard(
+ DXRenderModule& rRenderModule ) :
+ mrRenderModule( rRenderModule )
+ {
+ mrRenderModule.lock();
+ }
+
+ inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard()
+ {
+ mrRenderModule.unlock();
+ }
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ static sal_uInt32 gNumSurfaces = 0;
+#endif
+
+ void fillRect( sal_uInt32 *pDest,
+ sal_uInt32 dwWidth,
+ sal_uInt32 dwHeight,
+ sal_uInt32 dwPitch,
+ sal_uInt32 dwColor )
+ {
+ for(sal_uInt32 i=0; i<dwWidth; ++i)
+ {
+ pDest[i]=dwColor;
+ pDest[((dwHeight-1)*dwPitch)+i]=dwColor;
+ }
+
+ for(sal_uInt32 j=0; j<dwHeight; ++j)
+ {
+ pDest[0]=dwColor;
+ pDest[dwWidth-1]=dwColor;
+ pDest += dwPitch;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize ) :
+ mrRenderModule(rRenderModule),
+ mpTexture(NULL),
+ mpSurface(NULL),
+ maSize()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ ++gNumSurfaces;
+ if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES)
+ return;
+#endif
+
+#ifdef FAKE_MAX_TEXTURE_SIZE
+ if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+ if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+#endif
+
+ ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0,
+ "DXSurface::DXSurface(): request for zero-sized surface");
+
+ const D3DDEVICEDESC &deviceDesc = rRenderModule.getDeviceDesc();
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+ aSurfaceDesc.dwWidth = ::std::min(deviceDesc.dwMaxTextureWidth,::canvas::tools::nextPow2(rSize.getX()));
+ aSurfaceDesc.dwHeight = ::std::min(deviceDesc.dwMaxTextureHeight,::canvas::tools::nextPow2(rSize.getY()));
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
+ DDSCAPS_VIDEOMEMORY |
+ DDSCAPS_LOCALVIDMEM;
+ rtl_copyMemory(&aSurfaceDesc.ddpfPixelFormat,&rRenderModule.getTextureFormat(),sizeof(DDPIXELFORMAT));
+
+ IDirectDrawSurface *pSurface;
+ COMReference<IDirectDraw2> pDirectDraw(rRenderModule.getDirectDraw());
+ HRESULT hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ if(FAILED(hr))
+ {
+ // if the call failed due to 'out of videomemory',
+ // retry with request for AGP memory.
+ if(DDERR_OUTOFVIDEOMEMORY == hr)
+ {
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE |
+ DDSCAPS_VIDEOMEMORY |
+ DDSCAPS_NONLOCALVIDMEM;
+ hr = pDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ }
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ IDirect3DTexture2* pTexture;
+ if( FAILED(pSurface->QueryInterface(IID_IDirect3DTexture2, (LPVOID *)&pTexture)) )
+ {
+ pSurface->Release();
+ return;
+ }
+
+ maSize.setX(aSurfaceDesc.dwWidth);
+ maSize.setY(aSurfaceDesc.dwHeight);
+
+ mpSurface=COMReference<IDirectDrawSurface>(pSurface);
+ mpTexture=COMReference<IDirect3DTexture2>(pTexture);
+
+ // #122683# Clear texture, to avoid ugly artifacts at the
+ // border to invisible sprite areas (note that the textures
+ // are usually only partly utilized).
+ clearSurface( mpSurface );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::~DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::~DXSurface()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ gNumSurfaces--;
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::selectTexture
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::selectTexture()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ mrRenderModule.flushVertexCache();
+
+ D3DTEXTUREHANDLE aTextureHandle;
+ if(FAILED(mpTexture->GetHandle(
+ mrRenderModule.getDevice().get(),
+ &aTextureHandle)))
+ {
+ return false;
+ }
+
+ // select texture for next primitive
+ if(FAILED(mrRenderModule.getDevice()->SetRenderState(
+ D3DRENDERSTATE_TEXTUREHANDLE,aTextureHandle)))
+ {
+ return false;
+ }
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ if( mpSurface.is() )
+ {
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( SUCCEEDED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ {
+ imdebug( "rgba w=%d h=%d %p",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight,
+ aSurfaceDesc.lpSurface );
+
+ mpSurface->Unlock(NULL);
+ }
+ }
+# endif
+#endif
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::isValid
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::isValid()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ if(!(mpSurface.is()))
+ return false;
+
+ if(mpSurface->IsLost() == DDERR_SURFACELOST)
+ {
+ mpSurface->Restore();
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::update
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource )
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ // can't update if surface is not valid, that means
+ // either not existent nor restored...
+ if(!(isValid()))
+ return false;
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ // TODO(P2): only lock the region we want to update
+ if( FAILED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY,
+ NULL)) )
+ return false;
+
+ if(sal_uInt8* pImage = rSource.lock())
+ {
+ switch( rSource.getFormat() )
+ {
+ case ::canvas::IColorBuffer::FMT_A8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt32 nNumBytesToCopy(
+ static_cast<sal_uInt32>(
+ rSourceRect.getWidth())*
+ nSourceBytesPerPixel);
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ rtl_copyMemory(pDst,pImage,nNumBytesToCopy);
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(3);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt64 nNumColumns(rSourceRect.getWidth());
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst);
+ sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage);
+ for(sal_uInt32 x=0; x<nNumColumns; ++x)
+ {
+ sal_uInt32 color(0xFF000000);
+ color |= pSrcScanline[2]<<16;
+ color |= pSrcScanline[1]<<8;
+ color |= pSrcScanline[0];
+ pSrcScanline += 3;
+ *pDstScanline++ = color;
+ }
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_X8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = ((sal_uInt8*)aSurfaceDesc.lpSurface+
+ (rDestPos.getY()*aSurfaceDesc.lPitch) +
+ (4*rDestPos.getX()));
+
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage);
+ sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst);
+ for(sal_uInt32 j=0; j<rSourceRect.getWidth(); ++j)
+ pDst32[j] = 0xFF000000 | pSrc32[j];
+
+ pDst += aSurfaceDesc.lPitch;
+ pImage += nSourcePitchInBytes;
+ }
+ }
+ break;
+
+ default:
+ ENSURE_OR_RETURN(false,
+ "DXSurface::update(): Unknown/unimplemented buffer format" );
+ break;
+ }
+
+ rSource.unlock();
+ }
+
+ return SUCCEEDED(mpSurface->Unlock(NULL));
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurface::getSize()
+ {
+ return maSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::DXRenderModule( const ::Window& rWindow ) :
+ mhWnd(0),
+ mpWindow(),
+ maSize(),
+ maSelectedFullscreenMode(),
+ maTextureFormat(),
+ maMonitorInfo(),
+ mpDirectDraw(),
+ mpPrimarySurface(),
+ mpBackBufferSurface(),
+ mpDirect3D(),
+ mpDirect3DDevice(),
+ maLastUpdate(),
+ maDeviceDesc(),
+ maVertexCache(),
+ mnCount(0),
+ mnBeginSceneCount(0),
+ mbPageFlipping( false ),
+ mbHasNoTearingBlt( false ),
+ mbError( false ),
+ meType( PRIMITIVE_TYPE_UNKNOWN ),
+ mpTexture(),
+ maPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(!(create(rWindow)))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+
+ // allocate a single texture surface which can be used later.
+ // we also use this to calibrate the page size.
+ ::basegfx::B2IVector aPageSize(
+ ::std::min(
+ static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureWidth),
+ static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)),
+ ::std::min(
+ static_cast<sal_uInt32>(maDeviceDesc.dwMaxTextureHeight),
+ static_cast<sal_uInt32>(MAX_TEXTURE_SIZE)));
+ while(true)
+ {
+ mpTexture = ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,aPageSize));
+ if(mpTexture->isValid())
+ break;
+
+ aPageSize.setX(aPageSize.getX()>>1);
+ aPageSize.setY(aPageSize.getY()>>1);
+ if((aPageSize.getX() < MIN_TEXTURE_SIZE) ||
+ (aPageSize.getY() < MIN_TEXTURE_SIZE))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+ }
+ maPageSize=aPageSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::create
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::create( const ::Window& rWindow )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maVertexCache.reserve(1024);
+
+ mpWindow.reset(
+ new SystemChildWindow(
+ const_cast<Window *>(&rWindow), 0) );
+
+ // system child window must not receive mouse events
+ mpWindow->SetMouseTransparent( TRUE );
+
+ // parent should receive paint messages as well
+ // [PARENTCLIPMODE_NOCLIP], the argument is here
+ // passed as plain numeric value since the stupid
+ // define utilizes a USHORT cast.
+ mpWindow->SetParentClipMode(0x0002);
+
+ // the system child window must not clear its background
+ mpWindow->EnableEraseBackground( FALSE );
+
+ mpWindow->SetControlForeground();
+ mpWindow->SetControlBackground();
+ mpWindow->EnablePaint(FALSE);
+
+ const SystemEnvData *pData = mpWindow->GetSystemData();
+ const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd));
+ mhWnd = const_cast<HWND>(hwnd);
+
+ ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ),
+ "DXRenderModuleDXRenderModuleWin32() No valid HWND given." );
+
+ // retrieve position and size of the parent window
+ const ::Size &rSizePixel(rWindow.GetSizePixel());
+
+ // remember the size of the parent window, since we
+ // need to use this for our child window.
+ maSize.setX(static_cast<sal_Int32>(rSizePixel.Width()));
+ maSize.setY(static_cast<sal_Int32>(rSizePixel.Height()));
+
+ // let the child window cover the same size as the parent window.
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ MonitorList aMonitorList;
+ fillMonitorList( aMonitorList );
+
+ mpDirectDraw = COMReference<IDirectDraw2>(
+ createDirectDraw(aMonitorList, maMonitorInfo, mhWnd));
+
+ if(!mpDirectDraw.is())
+ return false;
+
+ if( !queryCaps() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): GetCaps failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ if( !validateCaps() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Insufficient DirectX capabilities, failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ if( FAILED( mpDirectDraw->SetCooperativeLevel( mhWnd,
+ DDSCL_NORMAL|DDSCL_MULTITHREADED|DDSCL_FPUPRESERVE ) ) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): SetCooperativeLevel failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // setup query struct
+ rtl_fillMemory( &maSelectedFullscreenMode.selectedDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ maSelectedFullscreenMode.selectedDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ // read current display mode, e.g. for screen dimension
+ if( FAILED( mpDirectDraw->GetDisplayMode( &maSelectedFullscreenMode.selectedDesc )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): GetDisplayMode failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // check for supported primary surface formats...
+ unsigned int nDisplayFormat = getDisplayFormat() & 0x00000FFF;
+ if(nDisplayFormat != 0x888 && nDisplayFormat != 0x565)
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Unsupported DisplayFormat" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // create primary surface reference
+ DDSURFACEDESC aSurfaceDesc;
+ IDirectDrawSurface* pPrimarySurface;
+
+ rtl_fillMemory( &aSurfaceDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(aSurfaceDesc);
+ aSurfaceDesc.dwFlags = DDSD_CAPS;
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
+
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pPrimarySurface, NULL)) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface failed" );
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ mpPrimarySurface = COMReference< IDirectDrawSurface >(pPrimarySurface);
+
+ // create a Clipper and associate it with the primary surface
+ // and the render window
+ LPDIRECTDRAWCLIPPER pClipper;
+ if( FAILED(mpDirectDraw->CreateClipper( 0, &pClipper, NULL )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateClipper failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ if( FAILED(pClipper->SetHWnd(0, mhWnd)) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): Clipper->SetHWnd failed" );
+ pClipper->Release();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ if( FAILED(mpPrimarySurface->SetClipper( pClipper )) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): SetClipper failed" );
+ pClipper->Release();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ // clipper is now owned by mpPrimarySurface, release our reference
+ pClipper->Release();
+
+ // TODO(F3): Check whether palette needs any setup here
+
+ // get us a backbuffer for simulated flipping
+ IDirectDrawSurface* pSurface;
+
+ // Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with
+ // the current window size, but this will make it
+ // necessary to temporarily have two buffers while copying
+ // from the old to the new one. What's more, at the time
+ // we need a larger buffer, DX might not have sufficient
+ // resources available, and we're then left with too small
+ // a back buffer, and no way of falling back to a
+ // different canvas implementation.
+ const ::basegfx::B2ISize aSize( getFramebufferSize() );
+
+ rtl_fillMemory( &aSurfaceDesc,
+ sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ aSurfaceDesc.dwHeight= aSize.getY();
+ aSurfaceDesc.dwWidth = aSize.getX();
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+
+ if( FAILED( nRes ) )
+ {
+ if( nRes == DDERR_OUTOFVIDEOMEMORY )
+ {
+ // local vid mem failed. Maybe AGP mem works?
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
+ {
+ // no chance, go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
+ }
+ else
+ {
+ // no chance, go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+ }
+
+ VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight );
+
+ mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
+ clearSurface(mpBackBufferSurface);
+
+ if( !setup3DDevice() )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::Device(): setup3DDevice failed" );
+ mpBackBufferSurface.reset();
+ mpPrimarySurface.reset();
+ mpDirectDraw.reset();
+ return false;
+ }
+
+ mpWindow->Show();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2ISize DXRenderModule::getFramebufferSize() const
+ {
+ return mpDirectDraw.is() ?
+ ::basegfx::B2ISize( maSelectedFullscreenMode.selectedDesc.dwWidth,
+ maSelectedFullscreenMode.selectedDesc.dwHeight ) :
+ ::basegfx::B2ISize();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::setup3DDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::setup3DDevice()
+ {
+ // create and setup 3D device
+ // ==========================
+ LPDIRECT3D2 pDirect3D;
+ if( FAILED( mpDirectDraw->QueryInterface( IID_IDirect3D2, (LPVOID*)&pDirect3D ) ) )
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): QueryInterface() for Direct3D failed" );
+ return false;
+ }
+
+ mpDirect3D = COMReference< IDirect3D2 >(pDirect3D);
+
+ LPDIRECT3DDEVICE2 pDirect3DDevice;
+ // try HW-accelerated device first
+ if( FAILED(mpDirect3D->CreateDevice( IID_IDirect3DHALDevice,
+ mpBackBufferSurface.get(),
+ &pDirect3DDevice )) )
+ {
+ // no HW 3D support - go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): CreateDevice() for HW Direct3D rendering failed" );
+ mpDirect3D.reset();
+ return false;
+ }
+
+ D3DDEVICEDESC aHELDeviceDesc;
+ rtl_fillMemory(&maDeviceDesc,sizeof(maDeviceDesc),0);
+ rtl_fillMemory(&aHELDeviceDesc,sizeof(aHELDeviceDesc),0);
+ maDeviceDesc.dwSize = sizeof(maDeviceDesc);
+ aHELDeviceDesc.dwSize = sizeof(aHELDeviceDesc);
+ if(FAILED(pDirect3DDevice->GetCaps(&maDeviceDesc,&aHELDeviceDesc)))
+ {
+ // go defunct, and exit
+ VERBOSE_TRACE( "Device::setup3DDevice(): GetCaps() for Direct3DDevice failed" );
+ mpDirect3D.reset();
+ return false;
+ }
+
+ mpDirect3DDevice = COMReference< IDirect3DDevice2 >(pDirect3DDevice);
+
+ // select appropriate texture format (_need_ alpha channel here)
+ rtl_fillMemory( &maTextureFormat,
+ sizeof(DDPIXELFORMAT), 0 );
+ maTextureFormat.dwSize = sizeof(DDPIXELFORMAT);
+ if( SUCCEEDED(mpDirect3DDevice->EnumTextureFormats( EnumTextureFormatsCallback, &maTextureFormat )) )
+ {
+ bool bSupportedFormat = true;
+ if((maTextureFormat.dwFlags & (DDPF_ALPHAPIXELS | DDPF_RGB)) != (DDPF_ALPHAPIXELS | DDPF_RGB))
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwRGBAlphaBitMask != 0xFF000000)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwRBitMask != 0x00FF0000)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwGBitMask != 0x0000FF00)
+ bSupportedFormat = false;
+ else if(maTextureFormat.dwBBitMask != 0x000000FF)
+ bSupportedFormat = false;
+
+ if(bSupportedFormat)
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): chose texture format dwRGBBitCount %d, dwRBitMask %x, "
+ "dwGBitMask %x, dwBBitMask %x and dwRGBAlphaBitMask %x. The texture uses %s alpha.",
+ maTextureFormat.dwRGBBitCount,
+ maTextureFormat.dwRBitMask,
+ maTextureFormat.dwGBitMask,
+ maTextureFormat.dwBBitMask,
+ maTextureFormat.dwRGBAlphaBitMask,
+ maTextureFormat.dwFlags & DDPF_ALPHAPREMULT ? "premultiplied" : "non-premultiplied" );
+
+ // setup the device (with as much as we can possibly do here)
+ // ==========================================================
+
+ LPDIRECT3DVIEWPORT2 pViewport;
+
+ if( SUCCEEDED(mpDirect3D->CreateViewport( &pViewport, NULL )) )
+ {
+ if( SUCCEEDED(mpDirect3DDevice->AddViewport( pViewport )) )
+ {
+ // setup viewport (to whole backbuffer)
+ D3DVIEWPORT2 aViewport;
+
+ aViewport.dwSize = sizeof(D3DVIEWPORT2);
+ aViewport.dwX = 0;
+ aViewport.dwY = 0;
+ aViewport.dwWidth = maSelectedFullscreenMode.selectedDesc.dwWidth;
+ aViewport.dwHeight = maSelectedFullscreenMode.selectedDesc.dwHeight;
+ aViewport.dvClipX = -1.0;
+ aViewport.dvClipY = -1.0;
+ aViewport.dvClipWidth = 2.0;
+ aViewport.dvClipHeight = 2.0;
+ aViewport.dvMinZ = 0.0;
+ aViewport.dvMaxZ = 1.0;
+
+ if( SUCCEEDED(pViewport->SetViewport2( &aViewport )) )
+ {
+ if( SUCCEEDED(mpDirect3DDevice->SetCurrentViewport( pViewport )) )
+ {
+ // Viewport was handed over to 3DDevice, thus we can release now
+ pViewport->Release();
+
+ // currently, no need for any
+ // matrix or light source
+ // setup, since we only render
+ // transformed&lighted
+ // vertices
+
+ // done; successfully
+ return true;
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): SetCurrentViewport failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): SetViewport2 failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): AddViewport failed" );
+ }
+
+ pViewport->Release();
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): CreateViewport failed" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): No supported pixelformat" );
+ }
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::setup3DDevice(): EnumTextureFormats failed" );
+ }
+
+ // go defunct, and exit
+ mpDirect3DDevice.reset();
+ mpDirect3D.reset();
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::queryCaps
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::queryCaps()
+ {
+ DDCAPS aHWCaps;
+ DDCAPS aHELCaps;
+
+ rtl_fillMemory( &aHWCaps,
+ sizeof(aHWCaps), 0 );
+ rtl_fillMemory( &aHELCaps,
+ sizeof(aHELCaps), 0 );
+ aHWCaps.dwSize = sizeof( aHWCaps );
+ aHELCaps.dwSize = sizeof( aHELCaps );
+
+ if( FAILED( mpDirectDraw->GetCaps( &aHWCaps,
+ &aHELCaps ) ) )
+ {
+ return false;
+ }
+
+ mbHasNoTearingBlt = aHWCaps.dwFXCaps & DDBLTFX_NOTEARING;
+
+ VERBOSE_TRACE( "dxcanvas initialization: %d bytes VRAM free for surfaces (%d with AGP mem), "
+ "%d bytes VRAM free for textures (%d with AGP mem)",
+ getAvailableSurfaceMem( false ),
+ getAvailableSurfaceMem( true ),
+ getAvailableTextureMem( false ),
+ getAvailableTextureMem( true ) );
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::validateCaps
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::validateCaps()
+ {
+ // TODO(E3): Validate HW capabilities. Depending on primary
+ // surface size, reject HW e.g. on the grounds of insufficient
+ // VRAM.
+
+ // setup query struct
+ DDSURFACEDESC desc;
+ rtl_fillMemory(&desc,sizeof(DDSURFACEDESC),0);
+ desc.dwSize = sizeof(DDSURFACEDESC);
+
+ // read current display mode, e.g. for screen dimension
+ if(FAILED( mpDirectDraw->GetDisplayMode(&desc)))
+ return false;
+
+ // simple heuristic: we need at least 3 times the desktop
+ // resolution based on ARGB color values...
+ std::size_t nMinimumVRAMSize = ((desc.dwWidth*desc.dwHeight)<<2)*3;
+ if(getAvailableSurfaceMem() < nMinimumVRAMSize)
+ return false;
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getDisplayFormat
+ //////////////////////////////////////////////////////////////////////////////////
+
+ unsigned int DXRenderModule::getDisplayFormat() const
+ {
+ unsigned int nFormat;
+ nFormat = ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRGBAlphaBitMask)<<12;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwRBitMask)<<8;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwGBitMask)<<4;
+ nFormat |= ::canvas::tools::bitcount32(maSelectedFullscreenMode.selectedDesc.ddpfPixelFormat.dwBBitMask);
+ return nFormat;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAvailableSurfaceMem
+ //////////////////////////////////////////////////////////////////////////////////
+
+ std::size_t DXRenderModule::getAvailableSurfaceMem( bool bWithAGPMem ) const
+ {
+ if( !mpDirectDraw.is() )
+ return 0;
+
+ std::size_t nRes( 0 );
+
+ DDSCAPS aSurfaceCaps;
+ DWORD nTotal, nFree;
+
+ // real VRAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+
+ if( bWithAGPMem )
+ {
+ // AGP RAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+ }
+
+ return nRes;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAvailableTextureMem
+ //////////////////////////////////////////////////////////////////////////////////
+
+ std::size_t DXRenderModule::getAvailableTextureMem( bool bWithAGPMem ) const
+ {
+ if( !mpDirectDraw.is() )
+ return 0;
+
+ std::size_t nRes( 0 );
+
+ DDSCAPS aSurfaceCaps;
+ DWORD nTotal, nFree;
+
+ // TODO(F1): Check if flags are applicable
+
+ // real VRAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+
+ if( bWithAGPMem )
+ {
+ // AGP RAM (const_cast, since GetAvailableVidMem is non-const)
+ aSurfaceCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(const_cast<IDirectDraw2&>(*mpDirectDraw).GetAvailableVidMem( &aSurfaceCaps, &nTotal, &nFree )) )
+ return 0;
+
+ nRes += nFree;
+ }
+
+ // TODO(F1): Add pool mem
+
+ return nRes;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::convert2Screen
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::convert2Screen( ::basegfx::B2IPoint& io_rDestPos,
+ ::basegfx::B2IRange& io_rDestArea )
+ {
+ POINT aPoint = { 0, 0 };
+ ClientToScreen( mhWnd, &aPoint );
+
+ // i52230 make sure given screen coordinate is relative to
+ // this monitor's area (the device rendering is always
+ // contained to a single monitor)
+ aPoint.x -= maMonitorInfo.rcMonitor.left;
+ aPoint.y -= maMonitorInfo.rcMonitor.top;
+
+ io_rDestPos.setX( io_rDestPos.getX() + aPoint.x );
+ io_rDestPos.setY( io_rDestPos.getY() + aPoint.y );
+
+ const ::basegfx::B2ISize& rSize( getFramebufferSize() );
+
+ // calc output bounds (clip against framebuffer bounds)
+ io_rDestArea = ::basegfx::B2IRange(
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getX()),
+ sal_Int32(io_rDestArea.getMinX() + aPoint.x) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getY()),
+ sal_Int32(io_rDestArea.getMinY() + aPoint.y) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getX()),
+ sal_Int32(io_rDestArea.getMaxX() + aPoint.x) ) ),
+ ::std::max( sal_Int32(0),
+ ::std::min( sal_Int32(rSize.getY()),
+ sal_Int32(io_rDestArea.getMaxY() + aPoint.y) ) ) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSystemMemorySurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ COMReference<IDirectDrawSurface> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize )
+ {
+ DDSURFACEDESC aSurfaceDesc;
+ IDirectDrawSurface* pSurface;
+
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;;
+ aSurfaceDesc.dwWidth = rSize.getX();
+ aSurfaceDesc.dwHeight= rSize.getY();
+
+ rtl_copyMemory( &aSurfaceDesc.ddpfPixelFormat, &maTextureFormat, sizeof(DDPIXELFORMAT) );
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ if(FAILED(nRes))
+ return COMReference<IDirectDrawSurface>(NULL);
+
+ return COMReference<IDirectDrawSurface>(pSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flip
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ // see if the main surfaces got lost. if so, try to
+ // restore them. bail out if this operation fails.
+ if(!(validateMainSurfaces()))
+ return false;
+
+ flushVertexCache();
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "Device::flip(): within 3D scene" );
+
+ // TODO(E3): handle DX errors more thoroughly. For fullscreen
+ // exclusive mode, actually even our primary surface can get
+ // lost and needs restore!
+
+ if( mpDirectDraw.is() &&
+ mpPrimarySurface.is() &&
+ mpBackBufferSurface.is() )
+ {
+ // ignore area and offset for page flipping device
+ if( mbPageFlipping )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ renderFPSCounter();
+ renderMemAvailable();
+#endif
+ VERBOSE_TRACE( "Device::flip(): Using true page flipping" );
+
+ // use true page flipping. Hopefully, the 3D hardware
+ // is flushed on this flip call (rumours have it that
+ // way), otherwise, perform the Lock hack as for the
+ // Blt below.
+ if( SUCCEEDED(mpPrimarySurface->Flip( NULL, DDFLIP_WAIT )) )
+ return true;
+ }
+ else
+ {
+ VERBOSE_TRACE( "Device::flip(): Using blt for page flipping" );
+
+ // determine actual window position
+ ::basegfx::B2IPoint aDestPoint( rUpdateArea.getMinimum() );
+ ::basegfx::B2IRange aSourceArea( rUpdateArea );
+ ::basegfx::B2IRange aDestArea( 0,0,
+ static_cast<sal_Int32>(rCurrWindowArea.getWidth()),
+ static_cast<sal_Int32>(rCurrWindowArea.getHeight()) );
+ convert2Screen( aDestPoint, aDestArea );
+
+ // perform clipping
+ if( !::canvas::tools::clipBlit( aSourceArea,
+ aDestPoint,
+ rUpdateArea,
+ aDestArea ) )
+ return true; // fully clipped, but still, in a way,
+ // successful.
+
+ // TODO(P1): Rumours have it that the 3D hardware
+ // _might_ still be rendering with flaky drivers,
+ // which don't flush properly on Blt(). It was said,
+ // that 'usually', it works to lock the 3D render
+ // target (the backbuffer in this case). OTOH, I've
+ // found that this tends to degrade performance
+ // significantly on complying cards...
+
+ // TODO(P1): Up until rev. 1.3, this method contained
+ // code to make sure the blit will start _immediately_
+ // after the Blt call. If this is not warranted, wait
+ // for the next vsync. As this case was found to be
+ // extremely seldom, kicked out (what's more, there's
+ // simply no guarantee that the blitter will be
+ // available at any point in the code - Windows still
+ // is a preemptive multi-processing environment. And
+ // _if_ we're competing with someone over the blitter,
+ // we will do so the next VBLANK interval, and the
+ // following...)
+
+ // screen update seems to be smoother when waiting
+ // for vblank in every case - even when blitter
+ // supports the DDBLTFX_NOTEARING flag.
+ if( FAILED(mpDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,
+ NULL)) )
+ return false;
+
+ DDBLTFX aBltFx;
+ DDBLTFX* pBltFX = NULL;
+ if( mbHasNoTearingBlt )
+ {
+ // Blt can internally schedule for no-tearing
+ // ===========================================
+
+ rtl_fillMemory( &aBltFx,
+ sizeof(aBltFx), 0 );
+ aBltFx.dwSize = sizeof(aBltFx);
+ aBltFx.dwDDFX = DDBLTFX_NOTEARING;
+
+ pBltFX = &aBltFx;
+ }
+
+ if( doBlit( aDestPoint,
+ *mpPrimarySurface,
+ aSourceArea,
+ *mpBackBufferSurface,
+ pBltFX,false ) )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ renderFPSCounter();
+ renderMemAvailable();
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::disposing
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::disposing()
+ {
+ if(!(mhWnd))
+ return;
+
+ mpTexture.reset();
+ mpWindow.reset();
+ mhWnd=NULL;
+
+ // refrain from releasing the DX5 objects - deleting the
+ // DX5 device seems to kill the whole engine, including
+ // all objects we might still hold references to
+ // (surfaces, e.g.)
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::screenshot
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::screenShot()
+ {
+ if(!(mpBackBufferSurface.get()))
+ return;
+ char filename[256];
+ static sal_uInt32 counter = 0;
+ sprintf(filename,"c:\\shot%d.bmp",counter++);
+ dumpSurface(mpBackBufferSurface,filename);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::validateMainSurfaces
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::validateMainSurfaces()
+ {
+ if(mpPrimarySurface.get()) {
+ if(mpPrimarySurface->IsLost() == DDERR_SURFACELOST) {
+ if(FAILED(mpPrimarySurface->Restore()))
+ return false;
+ }
+ }
+
+ if(mpBackBufferSurface.get()) {
+ if(mpBackBufferSurface->IsLost() == DDERR_SURFACELOST)
+ {
+ // TODO(F1): simply restoring the backbuffer does not
+ // work as expected, we need to re-create everything
+ // from scratch. find out why...
+ //if(SUCCEEDED(mpBackBufferSurface->Restore()))
+ // return setup3DDevice();
+
+ mpBackBufferSurface.reset();
+
+ // get us a backbuffer for simulated flipping
+ IDirectDrawSurface* pSurface;
+
+ // TODO(P2): Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with the current
+ // window size, but this will make it necessary to temporarily have two
+ // buffers while copying from the old to the new one. YMMV.
+ const ::basegfx::B2ISize aSize( getFramebufferSize() );
+
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc, sizeof(DDSURFACEDESC), 0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ aSurfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ aSurfaceDesc.dwHeight= aSize.getY();
+ aSurfaceDesc.dwWidth = aSize.getX();
+
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
+
+ HRESULT nRes = mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+
+ if( FAILED( nRes ) )
+ {
+ if( nRes == DDERR_OUTOFVIDEOMEMORY )
+ {
+ // local vid mem failed. Maybe AGP mem works?
+ aSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
+ if( FAILED(mpDirectDraw->CreateSurface(&aSurfaceDesc, &pSurface, NULL)) )
+ {
+ // no chance
+ return false;
+ }
+
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer reverted to non-local video mem" );
+ }
+ else
+ {
+ // no chance
+ VERBOSE_TRACE( "Device::Device(): CreateSurface for backbuffer failed" );
+ return false;
+ }
+ }
+
+ VERBOSE_TRACE( "Device::Device(): created backbuffer of size %d times %d pixel",
+ aSurfaceDesc.dwWidth,
+ aSurfaceDesc.dwHeight );
+
+ mpBackBufferSurface = COMReference< IDirectDrawSurface >(pSurface);
+
+ return setup3DDevice();
+ }
+ }
+
+ return true;
+ }
+
+ void DXRenderModule::renderInfoText( const ::rtl::OUString& rStr,
+ const Gdiplus::PointF& rPos ) const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "Device::renderInfoText(): within 3D scene" );
+
+ // render text directly to primary surface
+ GraphicsSharedPtr pGraphics;
+
+ if( mbPageFlipping )
+ {
+ // render on top of backbuffer. We have
+ // page flipping, anyway, thus this will
+ // cost us nothing.
+ pGraphics = createSurfaceGraphics( mpBackBufferSurface );
+ }
+ else
+ {
+ // render FPS directly to front buffer.
+ // That saves us another explicit blit,
+ // and for me, the FPS counter can blink,
+ // if it likes to...
+ pGraphics = createSurfaceGraphics( mpPrimarySurface );
+ }
+
+ if( !mbPageFlipping )
+ {
+ // clear background. We might be doing optimized redraws,
+ // and the background under the FPS count will then not be
+ // cleared.
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color( 255, 255, 255 ) );
+
+ pGraphics->FillRectangle( &aBrush,
+ rPos.X, rPos.Y, 80.0, 20.0 );
+ }
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color( 255, 0, 255 ) );
+ Gdiplus::Font aFont( NULL,
+ 16,
+ Gdiplus::FontStyleRegular,
+ Gdiplus::UnitWorld,
+ NULL );
+ pGraphics->DrawString( reinterpret_cast<LPCWSTR>(rStr.getStr()),
+ rStr.getLength(),
+ &aFont,
+ rPos,
+ &aBrush );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::renderMemAvailable
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::renderMemAvailable() const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::renderMemAvailable(): within 3D scene" );
+
+ const double nSurfaceMem( getAvailableSurfaceMem()/1024 );
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( nSurfaceMem,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("S: ")) + text;
+
+ renderInfoText( text,
+ Gdiplus::PointF( 0.0, 20) );
+
+
+ const double nTexMem( getAvailableTextureMem()/1024 );
+
+ text = ::rtl::math::doubleToUString( nTexMem,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ');
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("T: ")) + text;
+
+ renderInfoText( text,
+ Gdiplus::PointF( 0.0, 40) );
+
+ VERBOSE_TRACE( "dxcanvas: %f free surface mem, %f free texture mem",
+ nSurfaceMem, nTexMem );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::renderFPSCounter
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::renderFPSCounter() const
+ {
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::ren derFPSCounter(): within 3D scene" );
+
+ const double denominator( maLastUpdate.getElapsedTime() );
+ maLastUpdate.reset();
+
+ ::rtl::OUString text( ::rtl::math::doubleToUString( denominator == 0.0 ? 100.0 : 1.0/denominator,
+ rtl_math_StringFormat_F,
+ 2,'.',NULL,' ') );
+
+ // pad with leading space
+ while( text.getLength() < 6 )
+ text = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" ")) + text;
+
+ text += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM (" fps"));
+
+ renderInfoText( text,
+ Gdiplus::PointF() );
+
+ VERBOSE_TRACE( "dxcanvas: %f FPS",
+ denominator == 0.0 ? 100.0 : 1.0/denominator );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::resize( const ::basegfx::B2IRange& rect )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if( mhWnd==0 )
+ return;
+
+ // don't do anything if the size didn't change.
+ if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) &&
+ maSize.getY() == static_cast<sal_Int32>(rect.getHeight()))
+ return;
+
+ // TODO(Q2): use numeric cast to prevent overflow
+ maSize.setX(static_cast<sal_Int32>(rect.getWidth()));
+ maSize.setY(static_cast<sal_Int32>(rect.getHeight()));
+
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getPageSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXRenderModule::getPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+ return maPageSize;
+ }
+
+ ::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ const ::basegfx::B2IVector& rPageSize( getPageSize() );
+ ::basegfx::B2ISize aSize(surfaceSize);
+ if(!(aSize.getX()))
+ aSize.setX(rPageSize.getX());
+ if(!(aSize.getY()))
+ aSize.setY(rPageSize.getY());
+
+ if(mpTexture.use_count() == 1)
+ return mpTexture;
+
+ return ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,
+ aSize) );
+ }
+
+ void DXRenderModule::beginPrimitive( PrimitiveType eType )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::beginPrimitive(): nested call" );
+
+ ++mnBeginSceneCount;
+ meType=eType;
+ mnCount=0;
+ }
+
+ void DXRenderModule::endPrimitive()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ --mnBeginSceneCount;
+ meType=PRIMITIVE_TYPE_UNKNOWN;
+ mnCount=0;
+ }
+
+ void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ switch(meType)
+ {
+ case PRIMITIVE_TYPE_TRIANGLE:
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ mnCount &= 3;
+ break;
+ }
+
+ case PRIMITIVE_TYPE_QUAD:
+ {
+ if(mnCount == 3)
+ {
+ const std::size_t size(maVertexCache.size());
+ ::canvas::Vertex v0(maVertexCache[size-1]);
+ ::canvas::Vertex v2(maVertexCache[size-3]);
+ maVertexCache.push_back(v0);
+ maVertexCache.push_back(vertex);
+ maVertexCache.push_back(v2);
+ mnCount=0;
+ }
+ else
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE( false,
+ "DXRenderModule::pushVertex(): unexpected primitive types" );
+ break;
+ }
+ }
+
+ bool DXRenderModule::isError()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ return mbError;
+ }
+
+ void DXRenderModule::flushVertexCache()
+ {
+ if(!(maVertexCache.size()))
+ return;
+
+ mbError=true;
+
+ if( FAILED(mpDirect3DDevice->BeginScene()) )
+ return;
+
+ // enable texture alpha blending
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE,TRUE)))
+ return;
+
+ // enable texture alpha modulation, for honoring fAlpha
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND,
+ D3DTBLEND_MODULATEALPHA)) )
+ return;
+
+ // enable texture magnification filtering (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMAG,
+ D3DFILTER_LINEAR);
+
+ // enable texture minification filtering (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREMIN,
+ D3DFILTER_LINEAR);
+
+ // enable subpixel texture output (don't care if this
+ // fails, it's just visually more pleasant)
+ mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SUBPIXEL,
+ TRUE);
+
+ // normal combination of object...
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND,
+ D3DBLEND_SRCALPHA)) )
+ return;
+
+ // ..and background color
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND,
+ D3DBLEND_INVSRCALPHA)) )
+ return;
+
+ // disable backface culling; this enables us to mirror sprites
+ // by simply reverting the triangles, which, with enabled
+ // culling, would be invisible otherwise
+ if( FAILED(mpDirect3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE,
+ D3DCULL_NONE)) )
+ return;
+
+ mbError=false;
+
+ const float nHalfPixelSizeX(0.5f/maPageSize.getX());
+ const float nHalfPixelSizeY(0.5f/maPageSize.getY());
+ sal_uInt32 nIndex(0);
+ const std::size_t size(maVertexCache.size());
+ D3DTLVERTEX *vertices = static_cast<D3DTLVERTEX *>(_alloca(sizeof(D3DTLVERTEX)*size));
+ vertexCache_t::const_iterator it(maVertexCache.begin());
+ while(it != maVertexCache.end())
+ {
+ vertices[nIndex++] = D3DTLVERTEX(
+ D3DVECTOR(static_cast<D3DVALUE>(it->x),
+ static_cast<D3DVALUE>(it->y),
+ static_cast<D3DVALUE>(it->z)),
+ 1,
+ D3DRGBA(1,1,1,it->a),
+ D3DRGBA(0,0,0,0),
+ static_cast<float>(it->u + nHalfPixelSizeX),
+ static_cast<float>(it->v + nHalfPixelSizeY));
+ ++it;
+ }
+
+ maVertexCache.clear();
+
+ mbError |= FAILED(mpDirect3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DVT_TLVERTEX,
+ (LPVOID)vertices,
+ size,
+ 0));
+
+ mbError |= FAILED(mpDirect3DDevice->EndScene());
+ }
+ }
+
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent )
+ {
+ return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) );
+ }
+}
+
+#endif
diff --git a/canvas/source/directx/dx_9rm.cxx b/canvas/source/directx/dx_9rm.cxx
new file mode 100755
index 000000000000..acef323ddc1b
--- /dev/null
+++ b/canvas/source/directx/dx_9rm.cxx
@@ -0,0 +1,1366 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_9rm.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#if DIRECTX_VERSION == 0x0900
+
+#define MAX_TEXTURE_SIZE (2048)
+#define MIN_TEXTURE_SIZE (32)
+//#define FAKE_MAX_NUMBER_TEXTURES (2)
+//#define FAKE_MAX_TEXTURE_SIZE (4096)
+
+#define VERTEX_BUFFER_SIZE (341*3) // 1023, the size of the internal
+ // vertex buffer (must be divisable
+ // by 3, as each triangle primitive
+ // has 3 vertices)
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// includes
+//////////////////////////////////////////////////////////////////////////////////
+#include <vcl/syschild.hxx>
+#include <vcl/window.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <canvas/elapsedtime.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/rendering/icolorbuffer.hxx>
+#include <canvas/rendering/isurface.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <boost/scoped_ptr.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_config.hxx"
+
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#include "dx_impltools.hxx"
+#include <vcl/sysdata.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////////
+// 'dxcanvas' namespace
+//////////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ namespace
+ {
+ //////////////////////////////////////////////////////////////////////////////////
+ // monitorSupport
+ //////////////////////////////////////////////////////////////////////////////////
+
+ class monitorSupport
+ {
+ public:
+
+ monitorSupport() :
+ mhLibrary(LoadLibrary("user32.dll")),
+ mpMonitorFromWindow(NULL)
+ {
+ if(mhLibrary)
+ mpMonitorFromWindow = reinterpret_cast<fMonitorFromWindow>(
+ GetProcAddress(
+ mhLibrary,"MonitorFromWindow"));
+ }
+
+ ~monitorSupport()
+ {
+ if(mhLibrary)
+ FreeLibrary(mhLibrary);
+ mhLibrary=0;
+ }
+
+ HMONITOR MonitorFromWindow( HWND hwnd )
+ {
+ // return adapter_default in case something went wrong...
+ if(!(mpMonitorFromWindow))
+ return HMONITOR(0);
+ // MONITOR_DEFAULTTONEAREST
+ const DWORD dwFlags(0x00000002);
+ return mpMonitorFromWindow(hwnd,dwFlags);
+ }
+ private:
+
+ HINSTANCE mhLibrary;
+ typedef HMONITOR (WINAPI *fMonitorFromWindow )( HWND hwnd, DWORD dwFlags );
+ fMonitorFromWindow mpMonitorFromWindow;
+ };
+
+ monitorSupport aMonitorSupport;
+
+
+ class DXRenderModule;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /** ISurface implemenation.
+
+ @attention holds the DXRenderModule via non-refcounted
+ reference! This is safe with current state of affairs, since
+ the canvas::PageManager holds surface and render module via
+ shared_ptr (and makes sure all surfaces are deleted before its
+ render module member goes out of scope).
+ */
+ class DXSurface : public canvas::ISurface
+ {
+ public:
+ DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize );
+ ~DXSurface();
+
+ virtual bool selectTexture();
+ virtual bool isValid();
+ virtual bool update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource );
+ virtual ::basegfx::B2IVector getSize();
+ COMReference<IDirect3DTexture9> getTexture() const;
+
+ private:
+ /// Guard local methods against concurrent acces to RenderModule
+ class ImplRenderModuleGuard : private ::boost::noncopyable
+ {
+ public:
+ explicit inline ImplRenderModuleGuard( DXRenderModule& rRenderModule );
+ inline ~ImplRenderModuleGuard();
+
+ private:
+ DXRenderModule& mrRenderModule;
+ };
+
+ DXRenderModule& mrRenderModule;
+ COMReference<IDirect3DTexture9> mpTexture;
+
+ ::basegfx::B2IVector maSize;
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /// Default implementation of IDXRenderModule
+ class DXRenderModule : public IDXRenderModule
+ {
+ public:
+ explicit DXRenderModule( const ::Window& rWindow );
+ ~DXRenderModule();
+
+ virtual void lock() const { maMutex.acquire(); }
+ virtual void unlock() const { maMutex.release(); }
+
+ virtual COMReference<IDirect3DSurface9>
+ createSystemMemorySurface( const ::basegfx::B2IVector& rSize );
+ virtual void disposing();
+ virtual HWND getHWND() const { return mhWnd; }
+ virtual void screenShot();
+
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea );
+
+ virtual void resize( const ::basegfx::B2IRange& rect );
+ virtual ::basegfx::B2IVector getPageSize();
+ virtual ::canvas::ISurfaceSharedPtr createSurface( const ::basegfx::B2IVector& surfaceSize );
+ virtual void beginPrimitive( PrimitiveType eType );
+ virtual void endPrimitive();
+ virtual void pushVertex( const ::canvas::Vertex& vertex );
+ virtual bool isError();
+
+ COMReference<IDirect3DDevice9> getDevice() { return mpDevice; }
+
+ void flushVertexCache();
+ void commitVertexCache();
+
+ private:
+
+ bool create( const ::Window& rWindow );
+ bool createDevice();
+ bool verifyDevice( const UINT nAdapter );
+ UINT getAdapterFromWindow();
+
+ /** This object represents the DirectX state machine. In order
+ to serialize access to DirectX's global state, a global
+ mutex is required.
+ */
+ static ::osl::Mutex maMutex;
+
+ HWND mhWnd;
+ COMReference<IDirect3DDevice9> mpDevice;
+ COMReference<IDirect3D9> mpDirect3D9;
+ COMReference<IDirect3DSwapChain9> mpSwapChain;
+ COMReference<IDirect3DVertexBuffer9> mpVertexBuffer;
+ ::canvas::ISurfaceSharedPtr mpTexture;
+ ::boost::scoped_ptr<SystemChildWindow> mpWindow;
+ ::basegfx::B2IVector maSize;
+ typedef std::vector<canvas::Vertex> vertexCache_t;
+ vertexCache_t maVertexCache;
+ std::size_t mnCount;
+ int mnBeginSceneCount;
+ bool mbCanUseDynamicTextures;
+ bool mbError;
+ PrimitiveType meType;
+ ::basegfx::B2IVector maPageSize;
+ D3DPRESENT_PARAMETERS mad3dpp;
+
+ inline bool isDisposed() const { return (mhWnd==NULL); }
+
+ struct dxvertex
+ {
+ float x,y,z,rhw;
+ DWORD diffuse;
+ float u,v;
+ };
+
+ std::size_t maNumVertices;
+ std::size_t maWriteIndex;
+ std::size_t maReadIndex;
+ };
+
+ ::osl::Mutex DXRenderModule::maMutex;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::ImplRenderModuleGuard
+ //////////////////////////////////////////////////////////////////////////////////
+
+ inline DXSurface::ImplRenderModuleGuard::ImplRenderModuleGuard(
+ DXRenderModule& rRenderModule ) :
+ mrRenderModule( rRenderModule )
+ {
+ mrRenderModule.lock();
+ }
+
+ inline DXSurface::ImplRenderModuleGuard::~ImplRenderModuleGuard()
+ {
+ mrRenderModule.unlock();
+ }
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ static sal_uInt32 gNumSurfaces = 0;
+#endif
+
+ void fillRect( sal_uInt32 *pDest,
+ sal_uInt32 dwWidth,
+ sal_uInt32 dwHeight,
+ sal_uInt32 dwPitch,
+ sal_uInt32 dwColor )
+ {
+ for(sal_uInt32 i=0; i<dwWidth; ++i)
+ {
+ pDest[i]=dwColor;
+ pDest[((dwHeight-1)*dwPitch)+i]=dwColor;
+ }
+
+ for(sal_uInt32 j=0; j<dwHeight; ++j)
+ {
+ pDest[0]=dwColor;
+ pDest[dwWidth-1]=dwColor;
+ pDest += dwPitch;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::DXSurface( DXRenderModule& rRenderModule,
+ const ::basegfx::B2ISize& rSize ) :
+ mrRenderModule(rRenderModule),
+ mpTexture(NULL),
+ maSize()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ ++gNumSurfaces;
+ if(gNumSurfaces >= FAKE_MAX_NUMBER_TEXTURES)
+ return;
+#endif
+
+#ifdef FAKE_MAX_TEXTURE_SIZE
+ if(rSize.getX() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+ if(rSize.getY() > FAKE_MAX_TEXTURE_SIZE)
+ return;
+#endif
+
+ ENSURE_ARG_OR_THROW(rSize.getX() > 0 && rSize.getY() > 0,
+ "DXSurface::DXSurface(): request for zero-sized surface");
+
+ COMReference<IDirect3DDevice9> pDevice(rRenderModule.getDevice());
+
+ IDirect3DTexture9 *pTexture(NULL);
+ if(FAILED(pDevice->CreateTexture(
+ rSize.getX(),
+ rSize.getY(),
+ 1,0,D3DFMT_A8R8G8B8,
+ D3DPOOL_MANAGED,
+ &pTexture,NULL)))
+ return;
+
+ mpTexture=COMReference<IDirect3DTexture9>(pTexture);
+ maSize = rSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::~DXSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurface::~DXSurface()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+#ifdef FAKE_MAX_NUMBER_TEXTURES
+ gNumSurfaces--;
+#endif
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::selectTexture
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::selectTexture()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+ mrRenderModule.flushVertexCache();
+ COMReference<IDirect3DDevice9> pDevice(mrRenderModule.getDevice());
+
+ if( FAILED(pDevice->SetTexture(0,mpTexture.get())) )
+ return false;
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::isValid
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::isValid()
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ if(!(mpTexture.is()))
+ return false;
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::update
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurface::update( const ::basegfx::B2IPoint& rDestPos,
+ const ::basegfx::B2IRange& rSourceRect,
+ ::canvas::IColorBuffer& rSource )
+ {
+ ImplRenderModuleGuard aGuard( mrRenderModule );
+
+ // can't update if surface is not valid, that means
+ // either not existent nor restored...
+ if(!(isValid()))
+ return false;
+
+ D3DLOCKED_RECT aLockedRect;
+ RECT rect;
+ rect.left = std::max(sal_Int32(0),rDestPos.getX());
+ rect.top = std::max(sal_Int32(0),rDestPos.getY());
+ // to avoid interpolation artifacts from other textures,
+ // the surface manager allocates one pixel gap between
+ // them. Clear that to transparent.
+ rect.right = std::min(maSize.getX(),
+ rect.left + sal_Int32(rSourceRect.getWidth()+1));
+ rect.bottom = std::min(maSize.getY(),
+ rect.top + sal_Int32(rSourceRect.getHeight()+1));
+ const bool bClearRightColumn( rect.right < maSize.getX() );
+ const bool bClearBottomRow( rect.bottom < maSize.getY() );
+
+ if(SUCCEEDED(mpTexture->LockRect(0,&aLockedRect,&rect,D3DLOCK_NOSYSLOCK)))
+ {
+ if(sal_uInt8* pImage = rSource.lock())
+ {
+ switch( rSource.getFormat() )
+ {
+ case ::canvas::IColorBuffer::FMT_A8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_uInt32 nNumBytesToCopy(
+ static_cast<sal_uInt32>(
+ rSourceRect.getWidth())*
+ nSourceBytesPerPixel);
+ const sal_uInt64 nNumLines(rSourceRect.getHeight());
+
+ for(sal_uInt32 i=0; i<nNumLines; ++i)
+ {
+ rtl_copyMemory(pDst,pImage,nNumBytesToCopy);
+
+ if( bClearRightColumn )
+ {
+ // to avoid interpolation artifacts
+ // from other textures, the surface
+ // manager allocates one pixel gap
+ // between them. Clear that to
+ // transparent.
+ pDst[nNumBytesToCopy] =
+ pDst[nNumBytesToCopy+1] =
+ pDst[nNumBytesToCopy+2] =
+ pDst[nNumBytesToCopy+3] = 0x00;
+ }
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,nNumBytesToCopy+4);
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(3);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_Int32 nNumColumns(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getWidth()));
+ const sal_Int32 nNumLines(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getHeight()));
+ for(sal_Int32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pDstScanline = reinterpret_cast<sal_uInt32 *>(pDst);
+ sal_uInt8 *pSrcScanline = reinterpret_cast<sal_uInt8 *>(pImage);
+
+ for(sal_Int32 x=0; x<nNumColumns; ++x)
+ {
+ sal_uInt32 color(0xFF000000);
+ color |= pSrcScanline[2]<<16;
+ color |= pSrcScanline[1]<<8;
+ color |= pSrcScanline[0];
+ pSrcScanline += 3;
+ *pDstScanline++ = color;
+ }
+ if( bClearRightColumn )
+ *pDstScanline++ = 0xFF000000;
+
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,4*(nNumColumns+1));
+ }
+ break;
+
+ case ::canvas::IColorBuffer::FMT_X8R8G8B8:
+ {
+ const std::size_t nSourceBytesPerPixel(4);
+ const std::size_t nSourcePitchInBytes(rSource.getStride());
+ pImage += rSourceRect.getMinY()*nSourcePitchInBytes;
+ pImage += rSourceRect.getMinX()*nSourceBytesPerPixel;
+
+ // calculate the destination memory address
+ sal_uInt8 *pDst = (sal_uInt8*)aLockedRect.pBits;
+
+ const sal_Int32 nNumLines(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getHeight()));
+ const sal_Int32 nNumColumns(
+ sal::static_int_cast<sal_Int32>(rSourceRect.getWidth()));
+ for(sal_Int32 i=0; i<nNumLines; ++i)
+ {
+ sal_uInt32 *pSrc32 = reinterpret_cast<sal_uInt32 *>(pImage);
+ sal_uInt32 *pDst32 = reinterpret_cast<sal_uInt32 *>(pDst);
+ for(sal_Int32 j=0; j<nNumColumns; ++j)
+ pDst32[j] = 0xFF000000 | pSrc32[j];
+
+ if( bClearRightColumn )
+ pDst32[nNumColumns] = 0xFF000000;
+
+ pDst += aLockedRect.Pitch;
+ pImage += nSourcePitchInBytes;
+ }
+
+ if( bClearBottomRow )
+ rtl_zeroMemory(pDst,4*(nNumColumns+1));
+ }
+ break;
+
+ default:
+ ENSURE_OR_RETURN(false,
+ "DXSurface::update(): Unknown/unimplemented buffer format" );
+ break;
+ }
+
+ rSource.unlock();
+ }
+
+ return SUCCEEDED(mpTexture->UnlockRect(0));
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurface::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurface::getSize()
+ {
+ return maSize;
+ }
+
+ COMReference<IDirect3DTexture9> DXSurface::getTexture() const
+ {
+ return mpTexture;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::DXRenderModule( const ::Window& rWindow ) :
+ mhWnd(0),
+ mpDevice(),
+ mpDirect3D9(),
+ mpSwapChain(),
+ mpVertexBuffer(),
+ mpTexture(),
+ maSize(),
+ maVertexCache(),
+ mnCount(0),
+ mnBeginSceneCount(0),
+ mbCanUseDynamicTextures(false),
+ mbError( false ),
+ meType( PRIMITIVE_TYPE_UNKNOWN ),
+ maPageSize(),
+ mad3dpp(),
+ maNumVertices( VERTEX_BUFFER_SIZE ),
+ maWriteIndex(0),
+ maReadIndex(0)
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(!(create(rWindow)))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),NULL);
+ }
+
+ // allocate a single texture surface which can be used later.
+ // we also use this to calibrate the page size.
+ ::basegfx::B2IVector aPageSize(maPageSize);
+ while(true)
+ {
+ mpTexture = ::canvas::ISurfaceSharedPtr(
+ new DXSurface(*this,aPageSize));
+ if(mpTexture->isValid())
+ break;
+
+ aPageSize.setX(aPageSize.getX()>>1);
+ aPageSize.setY(aPageSize.getY()>>1);
+ if((aPageSize.getX() < MIN_TEXTURE_SIZE) ||
+ (aPageSize.getY() < MIN_TEXTURE_SIZE))
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - "
+ "insufficient texture space!") ),NULL);
+ }
+ }
+ maPageSize=aPageSize;
+
+ IDirect3DVertexBuffer9 *pVB(NULL);
+ DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
+ if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices,
+ D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
+ aFVF,
+ D3DPOOL_DEFAULT,
+ &pVB,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - out of memory!")),NULL);
+ }
+
+ mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::~DXRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXRenderModule::~DXRenderModule()
+ {
+ disposing();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::disposing
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::disposing()
+ {
+ if(!(mhWnd))
+ return;
+
+ mpTexture.reset();
+ mpWindow.reset();
+ mhWnd=NULL;
+
+ // refrain from releasing the DX9 objects. We're the only
+ // ones holding references to them, and it might be
+ // dangerous to destroy the DX9 device, before all other
+ // objects are dead.
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::create
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::create( const ::Window& rWindow )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ maVertexCache.reserve(1024);
+
+ mpWindow.reset(
+ new SystemChildWindow(
+ const_cast<Window *>(&rWindow), 0) );
+
+ // system child window must not receive mouse events
+ mpWindow->SetMouseTransparent( TRUE );
+
+ // parent should receive paint messages as well
+ // [PARENTCLIPMODE_NOCLIP], the argument is here
+ // passed as plain numeric value since the stupid
+ // define utilizes a USHORT cast.
+ mpWindow->SetParentClipMode(0x0002);
+
+ // the system child window must not clear its background
+ mpWindow->EnableEraseBackground( FALSE );
+
+ mpWindow->SetControlForeground();
+ mpWindow->SetControlBackground();
+ mpWindow->EnablePaint(FALSE);
+
+ const SystemEnvData *pData = mpWindow->GetSystemData();
+ const HWND hwnd(reinterpret_cast<HWND>(pData->hWnd));
+ mhWnd = const_cast<HWND>(hwnd);
+
+ ENSURE_OR_THROW( IsWindow( reinterpret_cast<HWND>(mhWnd) ),
+ "DXRenderModule::create() No valid HWND given." );
+
+ // retrieve position and size of the parent window
+ const ::Size &rSizePixel(rWindow.GetSizePixel());
+
+ // remember the size of the parent window, since we
+ // need to use this for our child window.
+ maSize.setX(static_cast<sal_Int32>(rSizePixel.Width()));
+ maSize.setY(static_cast<sal_Int32>(rSizePixel.Height()));
+
+ // let the child window cover the same size as the parent window.
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ // TODO(F2): since we would like to share precious hardware
+ // resources, the direct3d9 object should be global. each new
+ // request for a canvas should only create a new swapchain.
+ mpDirect3D9 = COMReference<IDirect3D9>(
+ Direct3DCreate9(D3D_SDK_VERSION));
+ if(!mpDirect3D9.is())
+ return false;
+
+ // create a device from the direct3d9 object.
+ if(!(createDevice()))
+ return false;
+
+ mpWindow->Show();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::verifyDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::verifyDevice( const UINT nAdapter )
+ {
+ ENSURE_OR_THROW( mpDirect3D9.is(),
+ "DXRenderModule::verifyDevice() No valid device." );
+
+ // ask direct3d9 about the capabilities of hardware devices on a specific adapter.
+ // here we decide if the underlying hardware of the machine 'is good enough'.
+ // since we only need a tiny little fraction of what could be used, this
+ // is basically a no-op.
+ D3DCAPS9 aCaps;
+ if(FAILED(mpDirect3D9->GetDeviceCaps(nAdapter,D3DDEVTYPE_HAL,&aCaps)))
+ return false;
+ if(!(aCaps.MaxTextureWidth))
+ return false;
+ if(!(aCaps.MaxTextureHeight))
+ return false;
+ maPageSize = ::basegfx::B2IVector(aCaps.MaxTextureWidth,aCaps.MaxTextureHeight);
+
+ // check device against white & blacklist entries
+ D3DADAPTER_IDENTIFIER9 aIdent;
+ if(FAILED(mpDirect3D9->GetAdapterIdentifier(nAdapter,0,&aIdent)))
+ return false;
+
+ DXCanvasItem aConfigItem;
+ DXCanvasItem::DeviceInfo aInfo;
+ aInfo.nVendorId = aIdent.VendorId;
+ aInfo.nDeviceId = aIdent.DeviceId;
+ aInfo.nDeviceSubSysId = aIdent.SubSysId;
+ aInfo.nDeviceRevision = aIdent.Revision;
+
+ aInfo.nDriverId = HIWORD(aIdent.DriverVersion.HighPart);
+ aInfo.nDriverVersion = LOWORD(aIdent.DriverVersion.HighPart);
+ aInfo.nDriverSubVersion = HIWORD(aIdent.DriverVersion.LowPart);
+ aInfo.nDriverBuildId = LOWORD(aIdent.DriverVersion.LowPart);
+
+ if( !aConfigItem.isDeviceUsable(aInfo) )
+ return false;
+
+ if( aConfigItem.isBlacklistCurrentDevice() )
+ {
+ aConfigItem.blacklistDevice(aInfo);
+ return false;
+ }
+
+ aConfigItem.adaptMaxTextureSize(maPageSize);
+
+ mbCanUseDynamicTextures = (aCaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0;
+
+ return true;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createDevice
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::createDevice()
+ {
+ // we expect that the caller provides us with a valid HWND
+ ENSURE_OR_THROW( IsWindow(mhWnd),
+ "DXRenderModule::createDevice() No valid HWND given." );
+
+ // we expect that the caller already created the direct3d9 object.
+ ENSURE_OR_THROW( mpDirect3D9.is(),
+ "DXRenderModule::createDevice() no direct3d?." );
+
+ // find the adapter identifier from the window.
+ const UINT aAdapter(getAdapterFromWindow());
+ if(aAdapter == static_cast<UINT>(-1))
+ return false;
+
+ // verify that device possibly works
+ if( !verifyDevice(aAdapter) )
+ return false;
+
+ // query the display mode from the selected adapter.
+ // we'll later request the backbuffer format to be same
+ // same as the display format.
+ D3DDISPLAYMODE d3ddm;
+ mpDirect3D9->GetAdapterDisplayMode(aAdapter,&d3ddm);
+
+ // we need to use D3DSWAPEFFECT_COPY here since the canvas-api has
+ // basically nothing to do with efficient resource handling. it tries
+ // to avoid drawing whenevery possible, which is simply not the most
+ // efficient way we could leverage the hardware in this case. it would
+ // be far better to redraw the backbuffer each time we would like to
+ // display the content of the backbuffer, but we need to face reality
+ // here and follow how the canvas was designed.
+
+ // Strictly speaking, we don't need a full screen worth of
+ // backbuffer here. We could also scale dynamically with
+ // the current window size, but this will make it
+ // necessary to temporarily have two buffers while copying
+ // from the old to the new one. What's more, at the time
+ // we need a larger buffer, DX might not have sufficient
+ // resources available, and we're then left with too small
+ // a back buffer, and no way of falling back to a
+ // different canvas implementation.
+ ZeroMemory( &mad3dpp, sizeof(mad3dpp) );
+ mad3dpp.BackBufferWidth = std::max(sal_Int32(maSize.getX()),
+ sal_Int32(d3ddm.Width));
+ mad3dpp.BackBufferHeight = std::max(sal_Int32(maSize.getY()),
+ sal_Int32(d3ddm.Height));
+ mad3dpp.BackBufferCount = 1;
+ mad3dpp.Windowed = TRUE;
+ mad3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
+ mad3dpp.BackBufferFormat = d3ddm.Format;
+ mad3dpp.EnableAutoDepthStencil = FALSE;
+ mad3dpp.hDeviceWindow = mhWnd;
+ mad3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+
+ // now create the device, first try hardware vertex processing,
+ // then software vertex processing. if both queries fail, we give up
+ // and indicate failure.
+ IDirect3DDevice9 *pDevice(NULL);
+ if(FAILED(mpDirect3D9->CreateDevice(aAdapter,
+ D3DDEVTYPE_HAL,
+ mhWnd,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING|
+ D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE,
+ &mad3dpp,
+ &pDevice)))
+ if(FAILED(mpDirect3D9->CreateDevice(aAdapter,
+ D3DDEVTYPE_HAL,
+ mhWnd,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING|
+ D3DCREATE_MULTITHREADED|D3DCREATE_FPU_PRESERVE,
+ &mad3dpp,
+ &pDevice)))
+ return false;
+
+ // got it, store it in a safe place...
+ mpDevice=COMReference<IDirect3DDevice9>(pDevice);
+
+ // After CreateDevice, the first swap chain already exists, so just get it...
+ IDirect3DSwapChain9 *pSwapChain(NULL);
+ pDevice->GetSwapChain(0,&pSwapChain);
+ mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain);
+ if( !mpSwapChain.is() )
+ return false;
+
+ // clear the render target [which is the backbuffer in this case].
+ // we are forced to do this once, and furthermore right now.
+ // please note that this is only possible since we created the
+ // backbuffer with copy semantics [the content is preserved after
+ // calls to Present()], which is an unnecessarily expensive operation.
+ LPDIRECT3DSURFACE9 pBackBuffer = NULL;
+ mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
+ mpDevice->SetRenderTarget( 0, pBackBuffer );
+ mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L);
+ pBackBuffer->Release();
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSystemMemorySurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ COMReference<IDirect3DSurface9> DXRenderModule::createSystemMemorySurface( const ::basegfx::B2IVector& rSize )
+ {
+ if(isDisposed())
+ return COMReference<IDirect3DSurface9>(NULL);
+
+ // please note that D3DFMT_X8R8G8B8 is the only format we're
+ // able to choose here, since GetDC() doesn't support any
+ // other 32bit-format.
+ IDirect3DSurface9 *pSurface(NULL);
+ if( FAILED(mpDevice->CreateOffscreenPlainSurface(
+ rSize.getX(),
+ rSize.getY(),
+ D3DFMT_X8R8G8B8,
+ D3DPOOL_SYSTEMMEM,
+ &pSurface,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create offscreen surface - out of mem!") ),NULL);
+ }
+
+ return COMReference<IDirect3DSurface9>(pSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flip
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& /*rCurrWindowArea*/ )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed() || !mpSwapChain.is())
+ return false;
+
+ flushVertexCache();
+
+ // TODO(P2): Might be faster to actually pass update area here
+ RECT aRect =
+ {
+ rUpdateArea.getMinX(),
+ rUpdateArea.getMinY(),
+ rUpdateArea.getMaxX(),
+ rUpdateArea.getMaxY()
+ };
+ HRESULT hr(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0));
+ if(FAILED(hr))
+ {
+ if(hr != D3DERR_DEVICELOST)
+ return false;
+
+ // interestingly enough, sometimes the Reset() below
+ // *still* causes DeviceLost errors. So, cycle until
+ // DX was kind enough to really reset the device...
+ do
+ {
+ mpVertexBuffer.reset();
+ hr = mpDevice->Reset(&mad3dpp);
+ if(SUCCEEDED(hr))
+ {
+ IDirect3DVertexBuffer9 *pVB(NULL);
+ DWORD aFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
+ if( FAILED(mpDevice->CreateVertexBuffer(sizeof(dxvertex)*maNumVertices,
+ D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
+ aFVF,
+ D3DPOOL_DEFAULT,
+ &pVB,
+ NULL)) )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device - out of memory!")),NULL);
+ }
+ mpVertexBuffer=COMReference<IDirect3DVertexBuffer9>(pVB);
+
+ // retry after the restore
+ if(SUCCEEDED(mpSwapChain->Present(&aRect,&aRect,NULL,NULL,0)))
+ return true;
+ }
+
+ TimeValue aTimeout;
+ aTimeout.Seconds=1;
+ aTimeout.Nanosec=0;
+ osl_waitThread(&aTimeout);
+ }
+ while(hr == D3DERR_DEVICELOST);
+
+ return false;
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::screenShot
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::screenShot()
+ {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::resize( const ::basegfx::B2IRange& rect )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ // don't do anything if the size didn't change.
+ if(maSize.getX() == static_cast<sal_Int32>(rect.getWidth()) &&
+ maSize.getY() == static_cast<sal_Int32>(rect.getHeight()))
+ return;
+
+ // TODO(Q2): use numeric cast to prevent overflow
+ maSize.setX(static_cast<sal_Int32>(rect.getWidth()));
+ maSize.setY(static_cast<sal_Int32>(rect.getHeight()));
+
+ mpWindow->SetPosSizePixel(0,0,maSize.getX(),maSize.getY());
+
+ // resize back buffer, if necessary
+ // -------------------------------------------------------------
+
+ // don't attempt to create anything if the
+ // requested size is NULL.
+ if(!(maSize.getX()))
+ return;
+ if(!(maSize.getY()))
+ return;
+
+ // backbuffer too small (might happen, if window is
+ // maximized across multiple monitors)
+ if( sal_Int32(mad3dpp.BackBufferWidth) < maSize.getX() ||
+ sal_Int32(mad3dpp.BackBufferHeight) < maSize.getY() )
+ {
+ mad3dpp.BackBufferWidth = maSize.getX();
+ mad3dpp.BackBufferHeight = maSize.getY();
+
+ // clear before, save resources
+ mpSwapChain.reset();
+
+ IDirect3DSwapChain9 *pSwapChain(NULL);
+ if(FAILED(mpDevice->CreateAdditionalSwapChain(&mad3dpp,&pSwapChain)))
+ return;
+ mpSwapChain=COMReference<IDirect3DSwapChain9>(pSwapChain);
+
+ // clear the render target [which is the backbuffer in this case].
+ // we are forced to do this once, and furthermore right now.
+ // please note that this is only possible since we created the
+ // backbuffer with copy semantics [the content is preserved after
+ // calls to Present()], which is an unnecessarily expensive operation.
+ LPDIRECT3DSURFACE9 pBackBuffer = NULL;
+ mpSwapChain->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer);
+ mpDevice->SetRenderTarget( 0, pBackBuffer );
+ mpDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,1.0f,0L);
+ pBackBuffer->Release();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getPageSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXRenderModule::getPageSize()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+ return maPageSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::createSurface
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::canvas::ISurfaceSharedPtr DXRenderModule::createSurface( const ::basegfx::B2IVector& surfaceSize )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return ::canvas::ISurfaceSharedPtr();
+
+ const ::basegfx::B2IVector& rPageSize( getPageSize() );
+ ::basegfx::B2ISize aSize(surfaceSize);
+ if(!(aSize.getX()))
+ aSize.setX(rPageSize.getX());
+ if(!(aSize.getY()))
+ aSize.setY(rPageSize.getY());
+
+ if(mpTexture.use_count() == 1)
+ return mpTexture;
+
+ return ::canvas::ISurfaceSharedPtr( new DXSurface(*this,aSize) );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::beginPrimitive
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::beginPrimitive( PrimitiveType eType )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ ENSURE_OR_THROW( !mnBeginSceneCount,
+ "DXRenderModule::beginPrimitive(): nested call" );
+
+ ++mnBeginSceneCount;
+ meType=eType;
+ mnCount=0;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::endPrimitive
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::endPrimitive()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ --mnBeginSceneCount;
+ meType=PRIMITIVE_TYPE_UNKNOWN;
+ mnCount=0;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::pushVertex
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::pushVertex( const ::canvas::Vertex& vertex )
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if(isDisposed())
+ return;
+
+ switch(meType)
+ {
+ case PRIMITIVE_TYPE_TRIANGLE:
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ mnCount &= 3;
+ break;
+ }
+
+ case PRIMITIVE_TYPE_QUAD:
+ {
+ if(mnCount == 3)
+ {
+ const std::size_t size(maVertexCache.size());
+ ::canvas::Vertex v0(maVertexCache[size-1]);
+ ::canvas::Vertex v2(maVertexCache[size-3]);
+ maVertexCache.push_back(v0);
+ maVertexCache.push_back(vertex);
+ maVertexCache.push_back(v2);
+ mnCount=0;
+ }
+ else
+ {
+ maVertexCache.push_back(vertex);
+ ++mnCount;
+ }
+ break;
+ }
+
+ default:
+ OSL_ENSURE(false,
+ "DXRenderModule::pushVertex(): unexpected primitive type");
+ break;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::isError
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXRenderModule::isError()
+ {
+ // TODO(P2): get rid of those fine-grained locking
+ ::osl::MutexGuard aGuard( maMutex );
+
+ return mbError;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::getAdapterFromWindow
+ //////////////////////////////////////////////////////////////////////////////////
+
+ UINT DXRenderModule::getAdapterFromWindow()
+ {
+ HMONITOR hMonitor(aMonitorSupport.MonitorFromWindow(mhWnd));
+ UINT aAdapterCount(mpDirect3D9->GetAdapterCount());
+ for(UINT i=0; i<aAdapterCount; ++i)
+ if(hMonitor == mpDirect3D9->GetAdapterMonitor(i))
+ return i;
+ return static_cast<UINT>(-1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::commitVertexCache
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::commitVertexCache()
+ {
+ if(maReadIndex != maWriteIndex)
+ {
+ const std::size_t nVertexStride = sizeof(dxvertex);
+ const unsigned int nNumVertices = maWriteIndex-maReadIndex;
+ const unsigned int nNumPrimitives = nNumVertices / 3;
+
+ if(FAILED(mpDevice->SetStreamSource(0,mpVertexBuffer.get(),0,nVertexStride)))
+ return;
+
+ if(FAILED(mpDevice->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)))
+ return;
+
+ if(FAILED(mpDevice->BeginScene()))
+ return;
+
+ mbError |= FAILED(mpDevice->DrawPrimitive(D3DPT_TRIANGLELIST,maReadIndex,nNumPrimitives));
+ mbError |= FAILED(mpDevice->EndScene());
+
+ maReadIndex += nNumVertices;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXRenderModule::flushVertexCache
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXRenderModule::flushVertexCache()
+ {
+ if(!(maVertexCache.size()))
+ return;
+
+ mbError=true;
+
+ if( FAILED(mpDevice->SetRenderState(D3DRS_LIGHTING,FALSE)))
+ return;
+
+ // enable texture alpha blending
+ if( FAILED(mpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE)))
+ return;
+
+ mpDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
+ mpDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
+ mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSU ,D3DTADDRESS_CLAMP );
+ mpDevice->SetSamplerState(0,D3DSAMP_ADDRESSV ,D3DTADDRESS_CLAMP );
+
+ // configure the fixed-function pipeline.
+ // the only 'feature' we need here is to modulate the alpha-channels
+ // from the texture and the interpolated diffuse color. the result
+ // will then be blended with the backbuffer.
+ // fragment color = texture color * diffuse.alpha.
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
+ mpDevice->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
+
+ // normal combination of object...
+ if( FAILED(mpDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA)) )
+ return;
+
+ // ..and background color
+ if( FAILED(mpDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA)) )
+ return;
+
+ // disable backface culling; this enables us to mirror sprites
+ // by simply reverting the triangles, which, with enabled
+ // culling, would be invisible otherwise
+ if( FAILED(mpDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE)) )
+ return;
+
+ mbError=false;
+
+ std::size_t nSize(maVertexCache.size());
+ const std::size_t nVertexStride = sizeof(dxvertex);
+
+ const ::basegfx::B2IVector aPageSize(getPageSize());
+ const float nHalfPixelSizeX(0.5f/aPageSize.getX());
+ const float nHalfPixelSizeY(0.5f/aPageSize.getY());
+ vertexCache_t::const_iterator it(maVertexCache.begin());
+
+ while( nSize )
+ {
+ DWORD dwLockFlags(D3DLOCK_NOOVERWRITE);
+
+ // Check to see if there's space for the current set of
+ // vertices in the buffer.
+ if( maNumVertices - maWriteIndex < nSize )
+ {
+ commitVertexCache();
+ dwLockFlags = D3DLOCK_DISCARD;
+ maWriteIndex = 0;
+ maReadIndex = 0;
+ }
+
+ dxvertex *vertices(NULL);
+ const std::size_t nNumVertices(
+ std::min(maNumVertices - maWriteIndex,
+ nSize));
+ if(FAILED(mpVertexBuffer->Lock(maWriteIndex*nVertexStride,
+ nNumVertices*nVertexStride,
+ (void **)&vertices,
+ dwLockFlags)))
+ return;
+
+ std::size_t nIndex(0);
+ while( nIndex < nNumVertices )
+ {
+ dxvertex &dest = vertices[nIndex++];
+ dest.x=it->x;
+ dest.y=it->y;
+ dest.z=it->z;
+ dest.rhw=1;
+ const sal_uInt32 alpha(static_cast<sal_uInt32>(it->a*255.0f));
+ dest.diffuse=D3DCOLOR_ARGB(alpha,255,255,255);
+ dest.u=static_cast<float>(it->u + nHalfPixelSizeX);
+ dest.v=static_cast<float>(it->v + nHalfPixelSizeY);
+ ++it;
+ }
+
+ mpVertexBuffer->Unlock();
+
+ // Advance to the next position in the vertex buffer.
+ maWriteIndex += nNumVertices;
+ nSize -= nNumVertices;
+
+ commitVertexCache();
+ }
+
+ maVertexCache.clear();
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // createRenderModule
+ //////////////////////////////////////////////////////////////////////////////////
+
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent )
+ {
+ return IDXRenderModuleSharedPtr( new DXRenderModule(rParent) );
+ }
+}
+
+#endif
diff --git a/canvas/source/directx/dx_bitmap.cxx b/canvas/source/directx/dx_bitmap.cxx
new file mode 100755
index 000000000000..7f2af1020bca
--- /dev/null
+++ b/canvas/source/directx/dx_bitmap.cxx
@@ -0,0 +1,222 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_bitmap.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include "dx_bitmap.hxx"
+#include "dx_graphicsprovider.hxx"
+#include "dx_impltools.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irange.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXBitmap::DXBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXBitmap::DXBitmap( const BitmapSharedPtr& rBitmap,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rBitmap->GetWidth(),rBitmap->GetHeight()),
+ mpBitmap(rBitmap),
+ mpGraphics(tools::createGraphicsFromBitmap(mpBitmap)),
+ mbAlpha(bWithAlpha)
+ {
+ }
+
+ DXBitmap::DXBitmap( const ::basegfx::B2IVector& rSize,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rSize),
+ mpBitmap(),
+ mpGraphics(),
+ mbAlpha(bWithAlpha)
+ {
+ // create container for pixel data
+ if(mbAlpha)
+ {
+ mpBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat32bppARGB));
+ }
+ else
+ {
+ mpBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat24bppRGB));
+ }
+
+ mpGraphics.reset( tools::createGraphicsFromBitmap(mpBitmap) );
+ }
+
+ BitmapSharedPtr DXBitmap::getBitmap() const
+ {
+ return mpBitmap;
+ }
+
+ GraphicsSharedPtr DXBitmap::getGraphics()
+ {
+ return mpGraphics;
+ }
+
+ ::basegfx::B2IVector DXBitmap::getSize() const
+ {
+ return maSize;
+ }
+
+ bool DXBitmap::hasAlpha() const
+ {
+ return mbAlpha;
+ }
+
+ uno::Sequence< sal_Int8 > DXBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
+
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = aRes.getArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ // read data from bitmap
+ if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO(F1): Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ mpBitmap->UnlockBits( &aBmpData );
+
+ return aRes;
+ }
+
+ void DXBitmap::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = (void*)data.getConstArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO: Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ // commit data to bitmap
+ mpBitmap->UnlockBits( &aBmpData );
+ }
+
+ void DXBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ if( Gdiplus::Ok != mpBitmap->SetPixel( pos.X, pos.Y,
+ Gdiplus::Color( tools::sequenceToArgb( color ))))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+
+ uno::Sequence< sal_Int8 > DXBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+ Gdiplus::Color aColor;
+
+ if( Gdiplus::Ok != mpBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
+ return uno::Sequence< sal_Int8 >();
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+
+}
+
diff --git a/canvas/source/directx/dx_bitmap.hxx b/canvas/source/directx/dx_bitmap.hxx
new file mode 100755
index 000000000000..1745e3d4f779
--- /dev/null
+++ b/canvas/source/directx/dx_bitmap.hxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_bitmap.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_DXBITMAP_HXX
+#define _DXCANVAS_DXBITMAP_HXX
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "dx_winstuff.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_graphicsprovider.hxx"
+#include "dx_gdiplususer.hxx"
+
+namespace dxcanvas
+{
+ class DXBitmap : public IBitmap
+ {
+ public:
+ DXBitmap( const BitmapSharedPtr& rBitmap,
+ bool bWithAlpha );
+ DXBitmap( const ::basegfx::B2IVector& rSize,
+ bool bWithAlpha );
+
+ virtual GraphicsSharedPtr getGraphics();
+
+ virtual BitmapSharedPtr getBitmap() const;
+ virtual ::basegfx::B2IVector getSize() const;
+ virtual bool hasAlpha() const;
+
+ ::com::sun::star::uno::Sequence< sal_Int8 > getData(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setData(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setPixel(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 > getPixel(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ private:
+ // Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ // size of this image in pixels [integral unit]
+ ::basegfx::B2IVector maSize;
+
+ BitmapSharedPtr mpBitmap;
+ GraphicsSharedPtr mpGraphics;
+
+ // true if the bitmap contains an alpha channel
+ bool mbAlpha;
+ };
+
+ typedef ::boost::shared_ptr< DXBitmap > DXBitmapSharedPtr;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_bitmapcanvashelper.cxx b/canvas/source/directx/dx_bitmapcanvashelper.cxx
new file mode 100755
index 000000000000..467b91dec1d7
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapcanvashelper.cxx
@@ -0,0 +1,249 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_bitmapcanvashelper.cxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/RepaintResult.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ BitmapCanvasHelper::BitmapCanvasHelper() :
+ mpTarget()
+ {}
+
+ void BitmapCanvasHelper::disposing()
+ {
+ mpTarget.reset();
+ CanvasHelper::disposing();
+ }
+
+ void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "BitmapCanvasHelper::setTarget(): Invalid target" );
+ ENSURE_OR_THROW( !mpTarget.get(),
+ "BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpTarget = rTarget;
+ CanvasHelper::setTarget(rTarget);
+ }
+
+ void BitmapCanvasHelper::setTarget( const IBitmapSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "BitmapCanvasHelper::setTarget(): invalid target" );
+ ENSURE_OR_THROW( !mpTarget.get(),
+ "BitmapCanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpTarget = rTarget;
+ CanvasHelper::setTarget(rTarget,rOutputOffset);
+ }
+
+ void BitmapCanvasHelper::clear()
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpTarget->getGraphics() );
+
+ Gdiplus::Color aClearColor = hasAlpha() ?
+ Gdiplus::Color( 0,255,255,255 ) : Gdiplus::Color((Gdiplus::ARGB)Gdiplus::Color::White);
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->SetCompositingMode(
+ Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
+ "BitmapCanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->Clear( aClearColor ),
+ "BitmapCanvasHelper::clear(): GDI+ Clear call failed" );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > BitmapCanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xLayoutetText.is(),
+ "BitmapCanvasHelper::drawTextLayout: layout is NULL");
+
+ if( needOutput() )
+ {
+ TextLayout* pTextLayout =
+ dynamic_cast< TextLayout* >( xLayoutetText.get() );
+
+ ENSURE_OR_THROW( pTextLayout,
+ "BitmapCanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+
+ pTextLayout->draw( mpTarget->getGraphics(),
+ viewState,
+ renderState,
+ maOutputOffset,
+ mpDevice,
+ mpTarget->hasAlpha() );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ void BitmapCanvasHelper::copyRect( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmapCanvas >& /*sourceCanvas*/,
+ const geometry::RealRectangle2D& /*sourceRect*/,
+ const rendering::ViewState& /*sourceViewState*/,
+ const rendering::RenderState& /*sourceRenderState*/,
+ const geometry::RealRectangle2D& /*destRect*/,
+ const rendering::ViewState& /*destViewState*/,
+ const rendering::RenderState& /*destRenderState*/ )
+ {
+ // TODO(F2): copyRect NYI
+ }
+
+ geometry::IntegerSize2D BitmapCanvasHelper::getSize()
+ {
+ if( !mpTarget )
+ return geometry::IntegerSize2D(1, 1);
+
+ return basegfx::unotools::integerSize2DFromB2ISize(mpTarget->getSize());
+ }
+
+ uno::Reference< rendering::XBitmap > BitmapCanvasHelper::getScaledBitmap( const geometry::RealSize2D& /*newSize*/,
+ sal_Bool /*beFast*/ )
+ {
+ // TODO(F1):
+ return uno::Reference< rendering::XBitmap >();
+ }
+
+ uno::Sequence< sal_Int8 > BitmapCanvasHelper::getData( rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::getData()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::getData(): disposed" );
+
+ if( !mpTarget )
+ return uno::Sequence< sal_Int8 >();
+
+ bitmapLayout = getMemoryLayout();
+ return mpTarget->getData(bitmapLayout,rect);
+ }
+
+ void BitmapCanvasHelper::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::setData()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::setData(): disposed" );
+
+ if( !mpTarget )
+ return;
+
+ mpTarget->setData(data,bitmapLayout,rect);
+ }
+
+ void BitmapCanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::setPixel()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::setPixel(): disposed" );
+
+ if( !mpTarget )
+ return;
+
+ mpTarget->setPixel(color,bitmapLayout,pos);
+ }
+
+ uno::Sequence< sal_Int8 > BitmapCanvasHelper::getPixel( rendering::IntegerBitmapLayout& bitmapLayout,
+ const geometry::IntegerPoint2D& pos )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::dxcanvas::BitmapCanvasHelper::getPixel()" );
+
+ ENSURE_OR_THROW( mpTarget,
+ "::dxcanvas::BitmapCanvasHelper::getPixel(): disposed" );
+
+ if( !mpTarget )
+ return uno::Sequence< sal_Int8 >();
+
+ bitmapLayout = getMemoryLayout();
+ return mpTarget->getPixel(bitmapLayout,pos);
+ }
+
+ uno::Reference< rendering::XBitmapPalette > BitmapCanvasHelper::getPalette()
+ {
+ // TODO(F1): Palette bitmaps NYI
+ return uno::Reference< rendering::XBitmapPalette >();
+ }
+
+ rendering::IntegerBitmapLayout BitmapCanvasHelper::getMemoryLayout()
+ {
+ if( !mpTarget )
+ return rendering::IntegerBitmapLayout(); // we're disposed
+
+ return ::canvas::tools::getStdMemoryLayout(getSize());
+ }
+ bool BitmapCanvasHelper::hasAlpha() const
+ {
+ return mpTarget ? mpTarget->hasAlpha() : false;
+ }
+}
diff --git a/canvas/source/directx/dx_bitmapcanvashelper.hxx b/canvas/source/directx/dx_bitmapcanvashelper.hxx
new file mode 100755
index 000000000000..6291adefc707
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapcanvashelper.hxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_bitmapcanvashelper.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_BITMAPCANVASHELPER_HXX_
+#define _DXCANVAS_BITMAPCANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+#include "dx_canvashelper.hxx"
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ HDC to render into.
+ */
+ class BitmapCanvasHelper : public CanvasHelper
+ {
+ public:
+ BitmapCanvasHelper();
+
+ /// Release all references
+ void disposing();
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+ */
+ void setTarget( const IBitmapSharedPtr& rTarget );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+
+ @param rOutputOffset
+ Output offset in pixel
+ */
+ void setTarget( const IBitmapSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+
+ // CanvasHelper functionality is implementation-inherited. yuck.
+ // =============================================================
+ void clear();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawTextLayout( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XTextLayout >& layoutetText,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ // BitmapCanvasHelper functionality
+ // ================================
+
+ void copyRect( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmapCanvas >& sourceCanvas,
+ const ::com::sun::star::geometry::RealRectangle2D& sourceRect,
+ const ::com::sun::star::rendering::ViewState& sourceViewState,
+ const ::com::sun::star::rendering::RenderState& sourceRenderState,
+ const ::com::sun::star::geometry::RealRectangle2D& destRect,
+ const ::com::sun::star::rendering::ViewState& destViewState,
+ const ::com::sun::star::rendering::RenderState& destRenderState );
+
+ ::com::sun::star::geometry::IntegerSize2D getSize();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap >
+ getScaledBitmap( const ::com::sun::star::geometry::RealSize2D& newSize,
+ sal_Bool beFast );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getData( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setData( const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ void setPixel( const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::uno::Sequence< sal_Int8 >
+ getPixel( ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapPalette > getPalette();
+
+ ::com::sun::star::rendering::IntegerBitmapLayout getMemoryLayout();
+
+ bool hasAlpha() const;
+
+ protected:
+ /// Render target
+ IBitmapSharedPtr mpTarget;
+ };
+}
+
+#endif /* _DXCANVAS_BITMAPCANVASHELPER_HXX_ */
diff --git a/canvas/source/directx/dx_bitmapprovider.hxx b/canvas/source/directx/dx_bitmapprovider.hxx
new file mode 100644
index 000000000000..09147eebcf8d
--- /dev/null
+++ b/canvas/source/directx/dx_bitmapprovider.hxx
@@ -0,0 +1,48 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_bitmapprovider.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_BITMAPPROVIDER_HXX_
+#define _DXCANVAS_BITMAPPROVIDER_HXX_
+
+#include "dx_ibitmap.hxx"
+#include <boost/shared_ptr.hpp>
+
+namespace dxcanvas
+{
+ struct BitmapProvider
+ {
+ virtual ~BitmapProvider() {}
+ virtual IBitmapSharedPtr getBitmap() const = 0;
+ };
+
+ typedef boost::shared_ptr<BitmapProvider> BitmapProviderSharedPtr;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_canvas.cxx b/canvas/source/directx/dx_canvas.cxx
new file mode 100644
index 000000000000..26dd88b0b538
--- /dev/null
+++ b/canvas/source/directx/dx_canvas.cxx
@@ -0,0 +1,258 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvas.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_winstuff.hxx"
+#include "dx_canvas.hxx"
+
+#include <vcl/sysdata.hxx>
+
+#define CANVAS_TECH "GDI+"
+#define CANVAS_SERVICE_NAME "com.sun.star.rendering.Canvas." CANVAS_TECH
+#define CANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.Canvas." CANVAS_TECH
+#define BITMAPCANVAS_SERVICE_NAME "com.sun.star.rendering.BitmapCanvas." CANVAS_TECH
+#define BITMAPCANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.BitmapCanvas." CANVAS_TECH
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ /// Actual canonical implementation of the GraphicsProvider interface
+ class GraphicsProviderImpl : public GraphicsProvider
+ {
+ GraphicsSharedPtr mpGraphics;
+ public:
+ explicit GraphicsProviderImpl( Gdiplus::Graphics* pGraphics ) : mpGraphics( pGraphics ) {}
+ virtual GraphicsSharedPtr getGraphics() { return mpGraphics; }
+ };
+
+ Canvas::Canvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void Canvas::initialize()
+ {
+ // #i64742# Only perform initialization when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "Canvas::initialize called" );
+
+ // At index 1, we expect a HWND handle here, containing a
+ // pointer to a valid window, on which to output
+ // At index 2, we expect the current window bound rect
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
+ "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Sequence<sal_Int8> aSeq;
+ maArguments[5] >>= aSeq;
+
+ const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
+ if( !pSysData || !pSysData->hDC )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed SystemGraphicsData or HDC invalid!")),
+ NULL);
+
+ // setup helper
+ maDeviceHelper.init( pSysData->hDC,
+ *this );
+ maCanvasHelper.setDevice( *this );
+ maCanvasHelper.setTarget(
+ GraphicsProviderSharedPtr(
+ new GraphicsProviderImpl(
+ Gdiplus::Graphics::FromHDC(pSysData->hDC))));
+
+ maArguments.realloc(0);
+ }
+
+ void SAL_CALL Canvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxComponentContext.clear();
+
+ // forward to parent
+ CanvasBaseT::disposing();
+ }
+
+ ::rtl::OUString SAL_CALL Canvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CANVAS_SERVICE_NAME ) );
+ }
+
+ BitmapCanvas::BitmapCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext ),
+ mpTarget()
+ {
+ }
+
+ void BitmapCanvas::initialize()
+ {
+ // #i64742# Only perform initialization when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "BitmapCanvas::initialize called" );
+
+ // At index 1, we expect a HWND handle here, containing a
+ // pointer to a valid window, on which to output
+ // At index 2, we expect the current window bound rect
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 6 &&
+ maArguments[5].getValueTypeClass() == uno::TypeClass_SEQUENCE,
+ "SpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Sequence<sal_Int8> aSeq;
+ maArguments[5] >>= aSeq;
+
+ const SystemGraphicsData* pSysData=reinterpret_cast<const SystemGraphicsData*>(aSeq.getConstArray());
+ if( !pSysData || !pSysData->hDC )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed SystemGraphicsData or HDC invalid!")),
+ NULL);
+
+ // setup helper
+ maDeviceHelper.init( pSysData->hDC,
+ *this );
+ maCanvasHelper.setDevice( *this );
+
+ // check whether we can actually provide a BitmapCanvas
+ // here. for this, check whether the HDC has a bitmap
+ // selected.
+ HBITMAP hBmp;
+ hBmp=(HBITMAP)GetCurrentObject(pSysData->hDC, OBJ_BITMAP);
+ if( !hBmp || GetObjectType(pSysData->hDC) != OBJ_MEMDC )
+ {
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed HDC is no mem DC/has no bitmap selected!")),
+ NULL);
+ }
+
+ mpTarget.reset( new DXBitmap(
+ BitmapSharedPtr(
+ Gdiplus::Bitmap::FromHBITMAP(
+ hBmp, 0) ),
+ false ));
+
+ maCanvasHelper.setTarget( mpTarget );
+
+ maArguments.realloc(0);
+ }
+
+ void SAL_CALL BitmapCanvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpTarget.reset();
+ mxComponentContext.clear();
+
+ // forward to parent
+ BitmapCanvasBaseT::disposing();
+ }
+
+ ::rtl::OUString SAL_CALL BitmapCanvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( BITMAPCANVAS_SERVICE_NAME ) );
+ }
+
+ IBitmapSharedPtr BitmapCanvas::getBitmap() const
+ {
+ return mpTarget;
+ }
+
+ static uno::Reference<uno::XInterface> initCanvas( Canvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_<Canvas, sdecl::with_args<true> > serviceImpl1(&initCanvas);
+ const sdecl::ServiceDecl dxCanvasDecl(
+ serviceImpl1,
+ CANVAS_IMPLEMENTATION_NAME,
+ CANVAS_SERVICE_NAME );
+
+ static uno::Reference<uno::XInterface> initBitmapCanvas( BitmapCanvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_<BitmapCanvas, sdecl::with_args<true> > serviceImpl2(&initBitmapCanvas);
+ const sdecl::ServiceDecl dxBitmapCanvasDecl(
+ serviceImpl2,
+ BITMAPCANVAS_IMPLEMENTATION_NAME,
+ BITMAPCANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS2(dxcanvas::dxCanvasDecl,
+ dxcanvas::dxBitmapCanvasDecl);
diff --git a/canvas/source/directx/dx_canvas.hxx b/canvas/source/directx/dx_canvas.hxx
new file mode 100644
index 000000000000..ab2aa398757d
--- /dev/null
+++ b/canvas/source/directx/dx_canvas.hxx
@@ -0,0 +1,179 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvas.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_CANVAS_HXX_
+#define _DXCANVAS_CANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
+
+#include <cppuhelper/compbase7.hxx>
+#include <cppuhelper/compbase6.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/integerbitmapbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/graphicdevicebase.hxx>
+
+#include "dx_bitmapprovider.hxx"
+#include "dx_canvashelper.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_devicehelper.hxx"
+
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper6< ::com::sun::star::rendering::XCanvas,
+ ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::util::XUpdatable,
+ ::com::sun::star::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > GraphicDeviceBase1_Base;
+ typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase1_Base >,
+ DeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBase1_Base;
+ typedef ::canvas::CanvasBase< CanvasBase1_Base,
+ CanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBaseT;
+
+ /** Product of this component's factory.
+
+ The Canvas object combines the actual Window canvas with
+ the XGraphicDevice interface. This is because there's a
+ one-to-one relation between them, anyway, since each window
+ can have exactly one canvas and one associated
+ XGraphicDevice. And to avoid messing around with circular
+ references, this is implemented as one single object.
+ */
+ class Canvas : public CanvasBaseT
+ {
+ public:
+ Canvas( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Any >& aArguments,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ void initialize();
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( Canvas, GraphicDeviceBase1_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ };
+
+ typedef ::rtl::Reference< Canvas > CanvasRef;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::util::XUpdatable,
+ ::com::sun::star::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > GraphicDeviceBase2_Base;
+ typedef ::canvas::GraphicDeviceBase< ::canvas::BaseMutexHelper< GraphicDeviceBase2_Base >,
+ DeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBase2_Base;
+ typedef ::canvas::IntegerBitmapBase< CanvasBase2_Base,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > BitmapCanvasBaseT;
+
+ /** Product of this component's factory.
+
+ The Canvas object combines the actual Window canvas with
+ the XGraphicDevice interface. This is because there's a
+ one-to-one relation between them, anyway, since each window
+ can have exactly one canvas and one associated
+ XGraphicDevice. And to avoid messing around with circular
+ references, this is implemented as one single object.
+ */
+ class BitmapCanvas : public BitmapCanvasBaseT, public BitmapProvider
+ {
+ public:
+ BitmapCanvas( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Any >& aArguments,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ void initialize();
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( BitmapCanvas, GraphicDeviceBase2_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const;
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ IBitmapSharedPtr mpTarget;
+ };
+
+ typedef ::rtl::Reference< BitmapCanvas > BitmapCanvasRef;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_canvasbitmap.cxx b/canvas/source/directx/dx_canvasbitmap.cxx
new file mode 100755
index 000000000000..5e4b61e6d104
--- /dev/null
+++ b/canvas/source/directx/dx_canvasbitmap.cxx
@@ -0,0 +1,280 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvasbitmap.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vcl/bitmapex.hxx>
+
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/scoped_array.hpp>
+
+#include "dx_canvasbitmap.hxx"
+#include "dx_impltools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap,
+ const DeviceRef& rDevice ) :
+ mpDevice( rDevice ),
+ mpBitmap( rBitmap )
+ {
+ ENSURE_OR_THROW( mpDevice.is() && mpBitmap,
+ "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
+
+ maCanvasHelper.setDevice( *mpDevice.get() );
+ maCanvasHelper.setTarget( mpBitmap );
+ }
+
+ void SAL_CALL CanvasBitmap::disposing()
+ {
+ mpBitmap.reset();
+ mpDevice.clear();
+
+ // forward to parent
+ CanvasBitmap_Base::disposing();
+ }
+
+ struct AlphaDIB
+ {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[256];
+ };
+
+ uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
+ {
+ uno::Any aRes;
+ // 0 ... get BitmapEx
+ // 1 ... get Pixbuf with bitmap RGB content
+ // 2 ... get Pixbuf with bitmap alpha mask
+ switch( nHandle )
+ {
+ // sorry, no BitmapEx here...
+ case 0:
+ aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
+ break;
+
+ case 1:
+ {
+ if(!mpBitmap->hasAlpha())
+ {
+ HBITMAP aHBmp;
+ mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(aHBmp) );
+
+ aRes <<= args;
+ }
+ else
+ {
+ // need to copy&convert the bitmap, since dx
+ // canvas uses inline alpha channel
+ HDC hScreenDC=GetDC(NULL);
+ const basegfx::B2IVector aSize(mpBitmap->getSize());
+ HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
+ aSize.getX(),
+ aSize.getY() );
+ if( !hBmpBitmap )
+ return aRes;
+
+ BITMAPINFOHEADER aBIH;
+
+ aBIH.biSize = sizeof( BITMAPINFOHEADER );
+ aBIH.biWidth = aSize.getX();
+ aBIH.biHeight = -aSize.getY();
+ aBIH.biPlanes = 1;
+ aBIH.biBitCount = 32;
+ aBIH.biCompression = BI_RGB; // expects pixel in
+ // bbggrrxx format
+ // (little endian)
+ aBIH.biSizeImage = 0;
+ aBIH.biXPelsPerMeter = 0;
+ aBIH.biYPelsPerMeter = 0;
+ aBIH.biClrUsed = 0;
+ aBIH.biClrImportant = 0;
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = aSize.getX();
+ aBmpData.Height = aSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
+ BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
+ if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB, // outputs ARGB (big endian)
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return aRes;
+ }
+
+ // now aBmpData.Scan0 contains our bits - push
+ // them into HBITMAP, ignoring alpha
+ SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS );
+
+ pGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(hBmpBitmap) );
+
+ aRes <<= args;
+ }
+ }
+ break;
+
+ case 2:
+ {
+ if(!mpBitmap->hasAlpha())
+ {
+ return aRes;
+ }
+ else
+ {
+ static AlphaDIB aDIB=
+ {
+ {0,0,0,1,8,BI_RGB,0,0,0,0,0},
+ {
+ // this here fills palette with grey
+ // level colors, starting from 0,0,0
+ // up to 255,255,255
+#define BOOST_PP_LOCAL_MACRO(n_) \
+ BOOST_PP_COMMA_IF(n_) \
+ {n_,n_,n_,n_}
+#define BOOST_PP_LOCAL_LIMITS (0, 255)
+#include BOOST_PP_LOCAL_ITERATE()
+ }
+ };
+
+ // need to copy&convert the bitmap, since dx
+ // canvas uses inline alpha channel
+ HDC hScreenDC=GetDC(NULL);
+ const basegfx::B2IVector aSize(mpBitmap->getSize());
+ HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() );
+ if( !hBmpBitmap )
+ return aRes;
+
+ aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+ aDIB.bmiHeader.biWidth = aSize.getX();
+ aDIB.bmiHeader.biHeight = -aSize.getY();
+ aDIB.bmiHeader.biPlanes = 1;
+ aDIB.bmiHeader.biBitCount = 8;
+ aDIB.bmiHeader.biCompression = BI_RGB;
+ aDIB.bmiHeader.biSizeImage = 0;
+ aDIB.bmiHeader.biXPelsPerMeter = 0;
+ aDIB.bmiHeader.biYPelsPerMeter = 0;
+ aDIB.bmiHeader.biClrUsed = 0;
+ aDIB.bmiHeader.biClrImportant = 0;
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = aSize.getX();
+ aBmpData.Height = aSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() );
+ BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap();
+ if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB, // outputs ARGB (big endian)
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return aRes;
+ }
+
+ // copy only alpha channel to pAlphaBits
+ const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3);
+ boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] );
+ const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0;
+ pInBits+=3;
+ sal_uInt8* pOutBits;
+ for( sal_Int32 y=0; y<aSize.getY(); ++y )
+ {
+ pOutBits=pAlphaBits.get()+y*nScanWidth;
+ for( sal_Int32 x=0; x<aSize.getX(); ++x )
+ {
+ *pOutBits++ = 255-*pInBits;
+ pInBits += 4;
+ }
+ }
+
+ pGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ // set bits to newly create HBITMAP
+ SetDIBits( hScreenDC, hBmpBitmap, 0,
+ aSize.getY(), pAlphaBits.get(),
+ (PBITMAPINFO)&aDIB, DIB_RGB_COLORS );
+
+ uno::Sequence< uno::Any > args(1);
+ args[0] = uno::Any( sal_Int64(hBmpBitmap) );
+
+ aRes <<= args;
+ }
+ }
+ break;
+ }
+
+ return aRes;
+ }
+
+#define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap"
+#define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
+
+ ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException)
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+}
diff --git a/canvas/source/directx/dx_canvasbitmap.hxx b/canvas/source/directx/dx_canvasbitmap.hxx
new file mode 100755
index 000000000000..1d3b223f5827
--- /dev/null
+++ b/canvas/source/directx/dx_canvasbitmap.hxx
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvasbitmap.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_CANVASBITMAP_HXX
+#define _DXCANVAS_CANVASBITMAP_HXX
+
+#include <cppuhelper/compbase4.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XBitmapCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include <cppuhelper/compbase3.hxx>
+#include <comphelper/uno3.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/integerbitmapbase.hxx>
+
+#include "dx_bitmapprovider.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_devicehelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_ibitmap.hxx"
+
+
+/* Definition of CanvasBitmap class */
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::lang::XServiceInfo,
+ ::com::sun::star::beans::XFastPropertySet > CanvasBitmapBase_Base;
+ typedef ::canvas::IntegerBitmapBase< ::canvas::BaseMutexHelper< CanvasBitmapBase_Base >,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasBitmap_Base;
+
+ class CanvasBitmap : public CanvasBitmap_Base, public BitmapProvider
+ {
+ public:
+ /** Create a canvas bitmap for the given surface
+
+ @param rSurface
+ Surface to create API object for.
+
+ @param rDevice
+ Reference device, with which bitmap should be compatible
+ */
+ CanvasBitmap( const IBitmapSharedPtr& rSurface,
+ const DeviceRef& rDevice );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const { return mpBitmap; }
+
+ virtual ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setFastPropertyValue(sal_Int32, const ::com::sun::star::uno::Any&) throw (::com::sun::star::uno::RuntimeException) {}
+
+ private:
+ /** MUST hold here, too, since CanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ DeviceRef mpDevice;
+ IBitmapSharedPtr mpBitmap;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASBITMAP_HXX */
diff --git a/canvas/source/directx/dx_canvascustomsprite.cxx b/canvas/source/directx/dx_canvascustomsprite.cxx
new file mode 100755
index 000000000000..a63f7cb74011
--- /dev/null
+++ b/canvas/source/directx/dx_canvascustomsprite.cxx
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvascustomsprite.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+#include "dx_canvascustomsprite.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ CanvasCustomSprite::CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ bool bShowSpriteBounds ) :
+ mpSpriteCanvas( rRefDevice ),
+ mpSurface()
+ {
+ ENSURE_OR_THROW( rRefDevice.get(),
+ "CanvasCustomSprite::CanvasCustomSprite(): Invalid sprite canvas" );
+
+ mpSurface.reset(
+ new DXSurfaceBitmap(
+ ::basegfx::B2IVector(
+ ::canvas::tools::roundUp( rSpriteSize.Width ),
+ ::canvas::tools::roundUp( rSpriteSize.Height )),
+ rSurfaceProxy,
+ rRenderModule,
+ true));
+
+ maCanvasHelper.setDevice( *rRefDevice.get() );
+ maCanvasHelper.setTarget( mpSurface );
+
+ maSpriteHelper.init( rSpriteSize,
+ rRefDevice,
+ rRenderModule,
+ mpSurface,
+ bShowSpriteBounds );
+
+ // clear sprite to 100% transparent
+ maCanvasHelper.clear();
+ }
+
+ void SAL_CALL CanvasCustomSprite::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpSurface.reset();
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteBaseT::disposing();
+ }
+
+#define IMPLEMENTATION_NAME "DXCanvas.CanvasCustomSprite"
+#define SERVICE_NAME "com.sun.star.rendering.CanvasCustomSprite"
+
+ ::rtl::OUString SAL_CALL CanvasCustomSprite::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+ void CanvasCustomSprite::redraw() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ maSpriteHelper.redraw( mbSurfaceDirty );
+ }
+}
diff --git a/canvas/source/directx/dx_canvascustomsprite.hxx b/canvas/source/directx/dx_canvascustomsprite.hxx
new file mode 100755
index 000000000000..73a4b88b19f6
--- /dev/null
+++ b/canvas/source/directx/dx_canvascustomsprite.hxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvascustomsprite.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_CANVASCUSTOMSPRITE_HXX
+#define _DXCANVAS_CANVASCUSTOMSPRITE_HXX
+
+#include <cppuhelper/compbase4.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/canvascustomspritebase.hxx>
+
+#include "dx_sprite.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_spritehelper.hxx"
+#include "dx_spritecanvas.hxx"
+
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::rendering::XCustomSprite,
+ ::com::sun::star::rendering::XBitmapCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::lang::XServiceInfo > CanvasCustomSpriteBase_Base;
+ /** Mixin Sprite
+
+ Have to mixin the Sprite interface before deriving from
+ ::canvas::CanvasCustomSpriteBase, as this template should
+ already implement some of those interface methods.
+
+ The reason why this appears kinda convoluted is the fact that
+ we cannot specify non-IDL types as WeakComponentImplHelperN
+ template args, and furthermore, don't want to derive
+ ::canvas::CanvasCustomSpriteBase directly from
+ ::canvas::Sprite (because derivees of
+ ::canvas::CanvasCustomSpriteBase have to explicitely forward
+ the XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS)
+ anyway). Basically, ::canvas::CanvasCustomSpriteBase should
+ remain a base class that provides implementation, not to
+ enforce any specific interface on its derivees.
+ */
+ class CanvasCustomSpriteSpriteBase_Base : public ::canvas::BaseMutexHelper< CanvasCustomSpriteBase_Base >,
+ public Sprite
+ {
+ };
+
+ typedef ::canvas::CanvasCustomSpriteBase< CanvasCustomSpriteSpriteBase_Base,
+ SpriteHelper,
+ BitmapCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > CanvasCustomSpriteBaseT;
+
+ /* Definition of CanvasCustomSprite class */
+
+ class CanvasCustomSprite : public CanvasCustomSpriteBaseT
+ {
+ public:
+ /** Create a custom sprite
+
+ @param rSpriteSize
+ Size of the sprite in pixel
+
+ @param rRefDevice
+ Associated output device
+
+ @param rSpriteCanvas
+ Target canvas
+
+ @param rDevice
+ Target DX device
+ */
+ CanvasCustomSprite( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rRefDevice,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ bool bShowSpriteBounds );
+
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcount Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( CanvasCustomSprite, CanvasCustomSpriteBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ // Sprite
+ virtual void redraw() const;
+
+ private:
+ /** MUST hold here, too, since BitmapCanvasHelper only contains a
+ raw pointer (without refcounting)
+ */
+ SpriteCanvasRef mpSpriteCanvas;
+ DXSurfaceBitmapSharedPtr mpSurface;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASCUSTOMSPRITE_HXX */
diff --git a/canvas/source/directx/dx_canvasfont.cxx b/canvas/source/directx/dx_canvasfont.cxx
new file mode 100755
index 000000000000..f041642e51aa
--- /dev/null
+++ b/canvas/source/directx/dx_canvasfont.cxx
@@ -0,0 +1,183 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvasfont.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include "dx_winstuff.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/PanoseWeight.hpp>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ INT calcFontStyle( const rendering::FontRequest& rFontRequest )
+ {
+ INT nFontStyle( Gdiplus::FontStyleRegular );
+
+ if( rFontRequest.FontDescription.FontDescription.Weight > rendering::PanoseWeight::BOOK )
+ nFontStyle = Gdiplus::FontStyleBold;
+
+ return nFontStyle;
+ }
+ }
+
+ CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest,
+ const uno::Sequence< beans::PropertyValue >& /*extraFontProperties*/,
+ const geometry::Matrix2D& fontMatrix ) :
+ CanvasFont_Base( m_aMutex ),
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ // TODO(F1): extraFontProperties, fontMatrix
+ mpFontFamily(),
+ mpFont(),
+ maFontRequest( rFontRequest ),
+ maFontMatrix( fontMatrix )
+ {
+ const sal_Int32 nLen(rFontRequest.FontDescription.FamilyName.getLength());
+ const sal_Unicode* pStr(rFontRequest.FontDescription.FamilyName.getStr());
+ std::vector< sal_Unicode > pStrBuf(nLen+1,0);
+ std::copy(pStr,pStr+nLen,&pStrBuf[0]);
+
+ mpFontFamily.reset( new Gdiplus::FontFamily(reinterpret_cast<LPCWSTR>(&pStrBuf[0]),NULL) );
+ if( !mpFontFamily->IsAvailable() )
+ mpFontFamily.reset( new Gdiplus::FontFamily(L"Arial",NULL) );
+
+ mpFont.reset( new Gdiplus::Font( mpFontFamily.get(),
+ static_cast<Gdiplus::REAL>(rFontRequest.CellSize),
+ calcFontStyle( rFontRequest ),
+ Gdiplus::UnitWorld ));
+ }
+
+ void SAL_CALL CanvasFont::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mpFont.reset();
+ mpFontFamily.reset();
+ mpGdiPlusUser.reset();
+ }
+
+ uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return new TextLayout( aText, nDirection, nRandomSeed, ImplRef( this ) );
+ }
+
+ uno::Sequence< double > SAL_CALL CanvasFont::getAvailableSizes( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< double >();
+ }
+
+ uno::Sequence< beans::PropertyValue > SAL_CALL CanvasFont::getExtraFontProperties( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+ rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maFontRequest;
+ }
+
+ rendering::FontMetrics SAL_CALL CanvasFont::getFontMetrics( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::FontMetrics();
+ }
+
+#define SERVICE_NAME "com.sun.star.rendering.CanvasFont"
+#define IMPLEMENTATION_NAME "DXCanvas::CanvasFont"
+
+ ::rtl::OUString SAL_CALL CanvasFont::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL CanvasFont::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL CanvasFont::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+
+ double CanvasFont::getCellAscent() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFontFamily->GetCellAscent(0); // TODO(F1): rFontRequest.styleName
+ }
+
+ double CanvasFont::getEmHeight() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFontFamily->GetEmHeight(0); // TODO(F1): rFontRequest.styleName
+ }
+
+ FontSharedPtr CanvasFont::getFont() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFont;
+ }
+
+ const ::com::sun::star::geometry::Matrix2D& CanvasFont::getFontMatrix() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maFontMatrix;
+ }
+}
diff --git a/canvas/source/directx/dx_canvasfont.hxx b/canvas/source/directx/dx_canvasfont.hxx
new file mode 100755
index 000000000000..cbd7c273192d
--- /dev/null
+++ b/canvas/source/directx/dx_canvasfont.hxx
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvasfont.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_CANVASFONT_HXX
+#define _DXCANVAS_CANVASFONT_HXX
+
+#include <comphelper/implementationreference.hxx>
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+
+#include <rtl/ref.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+/* Definition of CanvasFont class */
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+
+ typedef ::boost::shared_ptr< Gdiplus::Font > FontSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::FontFamily > FontFamilySharedPtr;
+
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XCanvasFont,
+ ::com::sun::star::lang::XServiceInfo > CanvasFont_Base;
+
+ class CanvasFont : public ::comphelper::OBaseMutex,
+ public CanvasFont_Base,
+ private ::boost::noncopyable
+ {
+ public:
+ typedef ::comphelper::ImplementationReference<
+ CanvasFont,
+ ::com::sun::star::rendering::XCanvasFont > ImplRef;
+
+ CanvasFont( const ::com::sun::star::rendering::FontRequest& fontRequest,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& extraFontProperties,
+ const ::com::sun::star::geometry::Matrix2D& fontMatrix );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XCanvasFont
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > SAL_CALL createTextLayout( const ::com::sun::star::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontRequest SAL_CALL getFontRequest( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::FontMetrics SAL_CALL getFontMetrics( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getAvailableSizes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getExtraFontProperties( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ double getCellAscent() const;
+ double getEmHeight() const;
+ FontSharedPtr getFont() const;
+ const ::com::sun::star::geometry::Matrix2D& getFontMatrix() const;
+
+ private:
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+ FontFamilySharedPtr mpFontFamily;
+ FontSharedPtr mpFont;
+ ::com::sun::star::rendering::FontRequest maFontRequest;
+ ::com::sun::star::geometry::Matrix2D maFontMatrix;
+ };
+
+}
+
+#endif /* _DXCANVAS_CANVASFONT_HXX */
diff --git a/canvas/source/directx/dx_canvashelper.cxx b/canvas/source/directx/dx_canvashelper.cxx
new file mode 100755
index 000000000000..0642b6c50efb
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper.cxx
@@ -0,0 +1,815 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvashelper.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/CompositeOperation.hpp>
+#include <com/sun/star/rendering/RepaintResult.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <comphelper/sequence.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_impltools.hxx"
+#include "dx_vcltools.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_canvashelper.hxx"
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ Gdiplus::LineCap gdiCapFromCap( sal_Int8 nCapType )
+ {
+ switch( nCapType )
+ {
+ case rendering::PathCapType::BUTT:
+ return Gdiplus::LineCapFlat;
+
+ case rendering::PathCapType::ROUND:
+ return Gdiplus::LineCapRound;
+
+ case rendering::PathCapType::SQUARE:
+ return Gdiplus::LineCapSquare;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "gdiCapFromCap(): Unexpected cap type" );
+ }
+
+ return Gdiplus::LineCapFlat;
+ }
+
+ Gdiplus::LineJoin gdiJoinFromJoin( sal_Int8 nJoinType )
+ {
+ switch( nJoinType )
+ {
+ case rendering::PathJoinType::NONE:
+ OSL_ENSURE( false,
+ "gdiJoinFromJoin(): Join NONE not possible, mapping to MITER" );
+ // FALLTHROUGH intended
+ case rendering::PathJoinType::MITER:
+ return Gdiplus::LineJoinMiter;
+
+ case rendering::PathJoinType::ROUND:
+ return Gdiplus::LineJoinRound;
+
+ case rendering::PathJoinType::BEVEL:
+ return Gdiplus::LineJoinBevel;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "gdiJoinFromJoin(): Unexpected join type" );
+ }
+
+ return Gdiplus::LineJoinMiter;
+ }
+ }
+
+ CanvasHelper::CanvasHelper() :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ mpDevice( NULL ),
+ mpGraphicsProvider(),
+ maOutputOffset()
+ {
+ }
+
+ void CanvasHelper::disposing()
+ {
+ mpGraphicsProvider.reset();
+ mpDevice = NULL;
+ mpGdiPlusUser.reset();
+ }
+
+ void CanvasHelper::setDevice( rendering::XGraphicDevice& rDevice )
+ {
+ mpDevice = &rDevice;
+ }
+
+ void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "CanvasHelper::setTarget(): Invalid target" );
+ ENSURE_OR_THROW( !mpGraphicsProvider.get(),
+ "CanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpGraphicsProvider = rTarget;
+ }
+
+ void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ ENSURE_OR_THROW( rTarget,
+ "CanvasHelper::setTarget(): invalid target" );
+ ENSURE_OR_THROW( !mpGraphicsProvider.get(),
+ "CanvasHelper::setTarget(): target set, old target would be overwritten" );
+
+ mpGraphicsProvider = rTarget;
+ maOutputOffset = rOutputOffset;
+ }
+
+ void CanvasHelper::clear()
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+ Gdiplus::Color aClearColor = Gdiplus::Color((Gdiplus::ARGB)Gdiplus::Color::White);
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->SetCompositingMode(
+ Gdiplus::CompositingModeSourceCopy ), // force set, don't blend
+ "CanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->Clear( aClearColor ),
+ "CanvasHelper::clear(): GDI+ Clear call failed" );
+ }
+ }
+
+ void CanvasHelper::drawPoint( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& aPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)) );
+
+ // determine size of one-by-one device pixel ellipse
+ Gdiplus::Matrix aMatrix;
+ pGraphics->GetTransform(&aMatrix);
+ aMatrix.Invert();
+ Gdiplus::PointF vector(1, 1);
+ aMatrix.TransformVectors(&vector);
+
+ // paint a one-by-one circle, with the given point
+ // in the middle (rounded to float)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->FillEllipse( &aBrush,
+ // disambiguate call
+ Gdiplus::REAL(aPoint.X),
+ Gdiplus::REAL(aPoint.Y),
+ Gdiplus::REAL(vector.X),
+ Gdiplus::REAL(vector.Y) ),
+ "CanvasHelper::drawPoint(): GDI+ call failed" );
+ }
+ }
+
+ void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealPoint2D& aStartPoint,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ Gdiplus::Status hr = pGraphics->DrawLine( &aPen,
+ Gdiplus::REAL(aStartPoint.X), // disambiguate call
+ Gdiplus::REAL(aStartPoint.Y),
+ Gdiplus::REAL(aEndPoint.X),
+ Gdiplus::REAL(aEndPoint.Y) );
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawLine(): GDI+ call failed" );
+ }
+ }
+
+ void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/,
+ const geometry::RealBezierSegment2D& aBezierSegment,
+ const geometry::RealPoint2D& aEndPoint,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ Gdiplus::Status hr = pGraphics->DrawBezier( &aPen,
+ Gdiplus::REAL(aBezierSegment.Px), // disambiguate call
+ Gdiplus::REAL(aBezierSegment.Py),
+ Gdiplus::REAL(aBezierSegment.C1x),
+ Gdiplus::REAL(aBezierSegment.C1y),
+ Gdiplus::REAL(aEndPoint.X),
+ Gdiplus::REAL(aEndPoint.Y),
+ Gdiplus::REAL(aBezierSegment.C2x),
+ Gdiplus::REAL(aBezierSegment.C2y) );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawBezier(): GDI+ call failed" );
+ }
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::drawPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ Gdiplus::REAL(0.0) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+
+ // TODO(E1): Return value
+ Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::drawPolyPolygon(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const rendering::StrokeAttributes& strokeAttributes )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::drawPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+
+ // Setup stroke pen
+ // ----------------
+
+ Gdiplus::Pen aPen(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)),
+ static_cast< Gdiplus::REAL >(strokeAttributes.StrokeWidth) );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ const Gdiplus::PixelOffsetMode aOldMode(
+ pGraphics->GetPixelOffsetMode() );
+ pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) );
+
+ const ::std::vector< Gdiplus::REAL >& rDashArray(
+ ::comphelper::sequenceToContainer< ::std::vector< Gdiplus::REAL > >(
+ strokeAttributes.DashArray ) );
+ if( !rDashArray.empty() )
+ {
+ aPen.SetDashPattern( &rDashArray[0],
+ rDashArray.size() );
+ }
+ aPen.SetLineCap( gdiCapFromCap(strokeAttributes.StartCapType),
+ gdiCapFromCap(strokeAttributes.EndCapType),
+ Gdiplus::DashCapFlat );
+ aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+
+ // TODO(E1): Return value
+ Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() );
+
+ pGraphics->SetPixelOffsetMode( aOldMode );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == hr,
+ "CanvasHelper::strokePolyPolygon(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const rendering::StrokeAttributes& /*strokeAttributes*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillPolyPolygon: polygon is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ tools::sequenceToArgb(renderState.DeviceColor));
+
+ GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) );
+
+ // TODO(F1): FillRule
+ ENSURE_OR_THROW( Gdiplus::Ok == pGraphics->FillPath( &aBrush, pPath.get() ),
+ "CanvasHelper::fillPolyPolygon(): GDI+ call failed " );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
+ const rendering::ViewState& /*viewState*/,
+ const rendering::RenderState& /*renderState*/,
+ const uno::Sequence< rendering::Texture >& /*textures*/,
+ const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
+ {
+ // TODO
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontRequest& fontRequest,
+ const uno::Sequence< beans::PropertyValue >& extraFontProperties,
+ const geometry::Matrix2D& fontMatrix )
+ {
+ if( needOutput() )
+ {
+ return uno::Reference< rendering::XCanvasFont >(
+ new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
+ }
+
+ return uno::Reference< rendering::XCanvasFont >();
+ }
+
+ uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::FontInfo& /*aFilter*/,
+ const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
+ {
+ // TODO
+ return uno::Sequence< rendering::FontInfo >();
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/,
+ const rendering::StringContext& text,
+ const uno::Reference< rendering::XCanvasFont >& xFont,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ sal_Int8 /*textDirection*/ )
+ {
+ ENSURE_OR_THROW( xFont.is(),
+ "CanvasHelper::drawText: font is NULL");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ Gdiplus::SolidBrush aBrush(
+ Gdiplus::Color(
+ tools::sequenceToArgb(renderState.DeviceColor)));
+
+ CanvasFont::ImplRef pFont(
+ tools::canvasFontFromXFont(xFont) );
+
+ // Move glyphs up, such that output happens at the font
+ // baseline.
+ Gdiplus::PointF aPoint( 0.0,
+ static_cast<Gdiplus::REAL>(-(pFont->getFont()->GetSize()*
+ pFont->getCellAscent() /
+ pFont->getEmHeight())) );
+
+ // TODO(F1): According to
+ // http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q307208,
+ // we might have to revert to GDI and ExTextOut here,
+ // since GDI+ takes the scalability a little bit too
+ // far...
+
+ // TODO(F2): Proper layout (BiDi, CTL)! IMHO must use
+ // DrawDriverString here, and perform layouting myself...
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->DrawString( reinterpret_cast<LPCWSTR>(
+ text.Text.copy( text.StartPosition,
+ text.Length ).getStr()),
+ text.Length,
+ pFont->getFont().get(),
+ aPoint,
+ &aBrush ),
+ "CanvasHelper::drawText(): GDI+ call failed" );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XTextLayout >& xLayoutetText,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xLayoutetText.is(),
+ "CanvasHelper::drawTextLayout: layout is NULL");
+
+ if( needOutput() )
+ {
+ TextLayout* pTextLayout =
+ dynamic_cast< TextLayout* >( xLayoutetText.get() );
+
+ ENSURE_OR_THROW( pTextLayout,
+ "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
+
+ pTextLayout->draw( mpGraphicsProvider->getGraphics(),
+ viewState,
+ renderState,
+ maOutputOffset,
+ mpDevice,
+ false );
+ }
+
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xBitmap.is(),
+ "CanvasHelper::drawBitmap: bitmap is NULL");
+
+ if( needOutput() )
+ {
+ // check whether one of our own objects - need to retrieve
+ // bitmap _before_ calling
+ // GraphicsProvider::getGraphics(), to avoid locking our
+ // own surface.
+ BitmapSharedPtr pGdiBitmap;
+ BitmapProvider* pBitmap = dynamic_cast< BitmapProvider* >(xBitmap.get());
+ if( pBitmap )
+ {
+ IBitmapSharedPtr pDXBitmap( pBitmap->getBitmap() );
+ if( pDXBitmap )
+ pGdiBitmap = pDXBitmap->getBitmap();
+ }
+
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ if( pGdiBitmap )
+ tools::drawGdiPlusBitmap(pGraphics,pGdiBitmap);
+ else
+ tools::drawVCLBitmapFromXBitmap(pGraphics,
+ xBitmap);
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( xBitmap.is(),
+ "CanvasHelper::drawBitmap: bitmap is NULL");
+
+ // no color set -> this is equivalent to a plain drawBitmap(), then
+ if( renderState.DeviceColor.getLength() < 3 )
+ return drawBitmap( pCanvas, xBitmap, viewState, renderState );
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ BitmapSharedPtr pBitmap( tools::bitmapFromXBitmap( xBitmap ) );
+ Gdiplus::Rect aRect( 0, 0,
+ pBitmap->GetWidth(),
+ pBitmap->GetHeight() );
+
+ // Setup an ImageAttributes with an alpha-modulating
+ // color matrix.
+ const rendering::ARGBColor& rARGBColor(
+ mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0]);
+
+ Gdiplus::ImageAttributes aImgAttr;
+ tools::setModulateImageAttributes( aImgAttr,
+ rARGBColor.Red,
+ rARGBColor.Green,
+ rARGBColor.Blue,
+ rARGBColor.Alpha );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == pGraphics->DrawImage( pBitmap.get(),
+ aRect,
+ 0, 0,
+ pBitmap->GetWidth(),
+ pBitmap->GetHeight(),
+ Gdiplus::UnitPixel,
+ &aImgAttr,
+ NULL,
+ NULL ),
+ "CanvasHelper::drawBitmapModulated(): GDI+ call failed" );
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+
+ uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
+ {
+ return uno::Reference< rendering::XGraphicDevice >(mpDevice);
+ }
+
+ // private helper
+ // --------------------------------------------------
+
+ Gdiplus::CompositingMode CanvasHelper::calcCompositingMode( sal_Int8 nMode )
+ {
+ Gdiplus::CompositingMode aRet( Gdiplus::CompositingModeSourceOver );
+
+ switch( nMode )
+ {
+ case rendering::CompositeOperation::OVER:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::CLEAR:
+ aRet = Gdiplus::CompositingModeSourceOver;
+ break;
+
+ case rendering::CompositeOperation::SOURCE:
+ aRet = Gdiplus::CompositingModeSourceCopy;
+ break;
+
+ case rendering::CompositeOperation::DESTINATION:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::UNDER:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::INSIDE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::INSIDE_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::OUTSIDE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::OUTSIDE_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ATOP:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ATOP_REVERSE:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::XOR:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::ADD:
+ // FALLTHROUGH intended
+ case rendering::CompositeOperation::SATURATE:
+ // TODO(F2): Problem, because GDI+ only knows about two compositing modes
+ aRet = Gdiplus::CompositingModeSourceOver;
+ break;
+
+ default:
+ ENSURE_OR_THROW( false, "CanvasHelper::calcCompositingMode: unexpected mode" );
+ break;
+ }
+
+ return aRet;
+ }
+
+ void CanvasHelper::setupGraphicsState( GraphicsSharedPtr& rGraphics,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
+ {
+ ENSURE_OR_THROW( needOutput(),
+ "CanvasHelper::setupGraphicsState: primary graphics invalid" );
+ ENSURE_OR_THROW( mpDevice,
+ "CanvasHelper::setupGraphicsState: reference device invalid" );
+
+ // setup view transform first. Clipping e.g. depends on it
+ ::basegfx::B2DHomMatrix aTransform;
+ ::canvas::tools::getViewStateTransform(aTransform, viewState);
+
+ // add output offset
+ if( !maOutputOffset.equalZero() )
+ {
+ ::basegfx::B2DHomMatrix aOutputOffset;
+ aOutputOffset.translate( maOutputOffset.getX(),
+ maOutputOffset.getY() );
+
+ aTransform = aOutputOffset * aTransform;
+ }
+
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
+ "CanvasHelper::setupGraphicsState(): Failed to set GDI+ transformation" );
+
+ // setup view and render state clipping
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->ResetClip(),
+ "CanvasHelper::setupGraphicsState(): Failed to reset GDI+ clip" );
+
+ if( viewState.Clip.is() )
+ {
+ GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( viewState.Clip ) );
+
+ // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
+ // Try SetClip( Rect ) or similar for simple clip paths (need some support in
+ // LinePolyPolygon, then)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
+ Gdiplus::CombineModeIntersect ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
+ }
+
+ // setup overall transform only now. View clip above was relative to
+ // view transform
+ ::canvas::tools::mergeViewAndRenderTransform(aTransform,
+ viewState,
+ renderState);
+
+ // add output offset
+ if( !maOutputOffset.equalZero() )
+ {
+ ::basegfx::B2DHomMatrix aOutputOffset;
+ aOutputOffset.translate( maOutputOffset.getX(),
+ maOutputOffset.getY() );
+
+ aTransform = aOutputOffset * aTransform;
+ }
+
+ tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform );
+
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ transformation" );
+
+ if( renderState.Clip.is() )
+ {
+ GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( renderState.Clip ) );
+
+ // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+.
+ // Try SetClip( Rect ) or similar for simple clip paths (need some support in
+ // LinePolyPolygon, then)
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
+ Gdiplus::CombineModeIntersect ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
+ }
+
+ // setup compositing
+ const Gdiplus::CompositingMode eCompositing( calcCompositingMode( renderState.CompositeOperation ) );
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ),
+ "CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" );
+ }
+
+ void CanvasHelper::flush() const
+ {
+ if( needOutput() )
+ mpGraphicsProvider->getGraphics()->Flush( Gdiplus::FlushIntentionSync );
+ }
+}
diff --git a/canvas/source/directx/dx_canvashelper.hxx b/canvas/source/directx/dx_canvashelper.hxx
new file mode 100755
index 000000000000..57de9b3d28f0
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper.hxx
@@ -0,0 +1,260 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvashelper.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_CANVASHELPER_HXX_
+#define _DXCANVAS_CANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+
+#include "dx_graphicsprovider.hxx"
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ /** Helper class for basic canvas functionality. Also offers
+ optional backbuffer painting, when providing it with a second
+ HDC to render into.
+ */
+ class CanvasHelper : private ::boost::noncopyable
+ {
+ public:
+ CanvasHelper();
+
+ /// Release all references
+ void disposing();
+
+ /** Initialize canvas helper
+
+ This method late-initializes the canvas helper, providing
+ it with the necessary device and output objects. Note that
+ the CanvasHelper does <em>not</em> take ownership of the
+ passed rDevice reference, nor does it perform any
+ reference counting. Thus, to prevent the reference counted
+ SpriteCanvas object from deletion, the user of this class
+ is responsible for holding ref-counted references itself!
+
+ @param rDevice
+ Reference device this canvas is associated with
+
+ */
+ void setDevice( com::sun::star::rendering::XGraphicDevice& rDevice );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+ */
+ void setTarget( const GraphicsProviderSharedPtr& rTarget );
+
+ /** Set the target for rendering operations
+
+ @param rTarget
+ Render target
+
+ @param rOutputOffset
+ Output offset in pixel
+ */
+ void setTarget( const GraphicsProviderSharedPtr& rTarget,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+
+ // CanvasHelper functionality
+ // ==========================
+
+ // XCanvas (only providing, not implementing the
+ // interface. Also note subtle method parameter differences)
+ void clear();
+ void drawPoint( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::geometry::RealPoint2D& aPoint,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ void drawLine( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::geometry::RealPoint2D& aStartPoint,
+ const ::com::sun::star::geometry::RealPoint2D& aEndPoint,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ void drawBezier( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::geometry::RealBezierSegment2D& aBezierSegment,
+ const ::com::sun::star::geometry::RealPoint2D& aEndPoint,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ strokePolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ strokeTexturedPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::rendering::Texture >& textures,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ strokeTextureMappedPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::rendering::Texture >& textures,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::geometry::XMapping2D >& xMapping,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >
+ queryStrokeShapes( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::rendering::StrokeAttributes& strokeAttributes );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ fillPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ fillTexturedPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::rendering::Texture >& textures );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ fillTextureMappedPolyPolygon( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& xPolyPolygon,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::rendering::Texture >& textures,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::geometry::XMapping2D >& xMapping );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > SAL_CALL
+ createFont( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::rendering::FontRequest& fontRequest,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue >& extraFontProperties,
+ const ::com::sun::star::geometry::Matrix2D& fontMatrix );
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::rendering::FontInfo >
+ queryAvailableFonts( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::rendering::FontInfo& aFilter,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue >& aFontProperties );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawText( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::rendering::StringContext& text,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& xFont,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState,
+ sal_Int8 textDirection );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawTextLayout( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XTextLayout >& layoutetText,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawBitmap( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCachedPrimitive >
+ drawBitmapModulated( const ::com::sun::star::rendering::XCanvas* pCanvas,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >
+ getDevice();
+
+ // Flush drawing queue to screen
+ void flush() const;
+
+ /** Called from XCanvas base classes, to notify that content
+ is _about_ to change
+ */
+ void modifying() {}
+
+ protected:
+ /// Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for spritecanvas.
+ */
+ com::sun::star::rendering::XGraphicDevice* mpDevice;
+
+ /// Provides the Gdiplus::Graphics to render into
+ GraphicsProviderSharedPtr mpGraphicsProvider;
+
+ bool needOutput() const { return mpGraphicsProvider.get() != NULL; };
+
+ // returns transparency of color
+ void setupGraphicsState( GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& viewState,
+ const ::com::sun::star::rendering::RenderState& renderState );
+
+ Gdiplus::CompositingMode calcCompositingMode( sal_Int8 nMode );
+
+ /// Current (transformation-independent) output buffer offset
+ ::basegfx::B2ISize maOutputOffset;
+ };
+}
+
+#endif /* _DXCANVAS_CANVASHELPER_HXX_ */
diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx
new file mode 100755
index 000000000000..f291d197c4de
--- /dev/null
+++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx
@@ -0,0 +1,740 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_canvashelper_texturefill.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/TexturingMode.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <canvas/parametricpolypolygon.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_canvashelper.hxx"
+#include "dx_impltools.hxx"
+
+#include <boost/scoped_ptr.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ typedef ::boost::shared_ptr< Gdiplus::PathGradientBrush > PathGradientBrushSharedPtr;
+
+ bool fillLinearGradient( GraphicsSharedPtr& rGraphics,
+ const Gdiplus::Color& rColor1,
+ const Gdiplus::Color& rColor2,
+ const GraphicsPathSharedPtr& rFillPath,
+ const rendering::Texture& texture )
+ {
+ // setup a linear gradient with two colors
+ // ---------------------------------------
+
+ Gdiplus::LinearGradientBrush aBrush(
+ Gdiplus::PointF(0.0f,
+ 0.5f),
+ Gdiplus::PointF(1.0f,
+ 0.5f),
+ rColor1,
+ rColor2 );
+
+ // render background color, as LinearGradientBrush does not
+ // properly support the WrapModeClamp repeat mode
+ Gdiplus::SolidBrush aBackgroundBrush( rColor1 );
+ rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() );
+
+ // TODO(F2): This does not yet support other repeat modes
+ // except clamp, and probably also no multi-texturing
+
+ // calculate parallelogram of gradient in object space, extend
+ // top and bottom of it such that they cover the whole fill
+ // path bound area
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+ texture.AffineTransform );
+
+ ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
+ ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
+ ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
+ ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
+
+ aLeftTop *= aTextureTransform;
+ aLeftBottom *= aTextureTransform;
+ aRightTop *= aTextureTransform;
+ aRightBottom*= aTextureTransform;
+
+ Gdiplus::RectF aBounds;
+ rFillPath->GetBounds( &aBounds, NULL, NULL );
+
+ // now, we potentially have to enlarge our gradient area
+ // atop and below the transformed [0,1]x[0,1] unit rect,
+ // for the gradient to fill the complete bound rect.
+ ::basegfx::tools::infiniteLineFromParallelogram( aLeftTop,
+ aLeftBottom,
+ aRightTop,
+ aRightBottom,
+ tools::b2dRangeFromGdiPlusRectF( aBounds ) );
+
+ // calc length of bound rect diagonal
+ const double nDiagonalLength(
+ hypot( aBounds.Width,
+ aBounds.Height ) );
+
+ // generate a path which covers the 'right' side of the
+ // gradient, extending two times the bound rect diagonal to
+ // the right (and thus covering the whole half plane 'right'
+ // of the gradient). Take the middle of the gradient as the
+ // 'left' side of the polygon, to not fall victim to rounding
+ // errors at the edge.
+ ::basegfx::B2DVector aDirection( aLeftTop - aLeftBottom );
+ aDirection = ::basegfx::getNormalizedPerpendicular( aDirection );
+ aDirection *= nDiagonalLength;
+
+ const ::basegfx::B2DPoint aHalfPlaneLeftTop( (aLeftTop + aRightTop) * 0.5 );
+ const ::basegfx::B2DPoint aHalfPlaneLeftBottom( (aLeftBottom + aRightBottom) * 0.5 );
+ const ::basegfx::B2DPoint aHalfPlaneRightTop( aRightTop + aDirection );
+ const ::basegfx::B2DPoint aHalfPlaneRightBottom( aRightBottom + aDirection );
+
+ Gdiplus::GraphicsPath aSolidFillPath;
+ aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftTop.getY()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightTop.getY()) );
+ aSolidFillPath.AddLine( static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneRightBottom.getY()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getX()),
+ static_cast<Gdiplus::REAL>(aHalfPlaneLeftBottom.getY()) );
+ aSolidFillPath.CloseFigure();
+
+ // limit output to fill path, we've just generated a path that
+ // might be substantially larger
+ if( Gdiplus::Ok != rGraphics->SetClip( rFillPath.get(),
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ Gdiplus::SolidBrush aBackgroundBrush2( rColor2 );
+ rGraphics->FillPath( &aBackgroundBrush2, &aSolidFillPath );
+
+ // generate clip polygon from the extended parallelogram
+ // (exploit the feature that distinct lines in a figure are
+ // automatically closed by a straight line)
+ Gdiplus::GraphicsPath aClipPath;
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aLeftTop.getX()),
+ static_cast<Gdiplus::REAL>(aLeftTop.getY()),
+ static_cast<Gdiplus::REAL>(aRightTop.getX()),
+ static_cast<Gdiplus::REAL>(aRightTop.getY()) );
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aRightBottom.getX()),
+ static_cast<Gdiplus::REAL>(aRightBottom.getY()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getX()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getY()) );
+ aClipPath.CloseFigure();
+
+ // limit output to a _single_ strip of the gradient (have to
+ // clip here, since GDI+ wrapmode clamp does not work here)
+ if( Gdiplus::Ok != rGraphics->SetClip( &aClipPath,
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ // now, finally, output the gradient
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
+ texture.AffineTransform );
+ aBrush.SetTransform( &aMatrix );
+
+ rGraphics->FillRectangle( &aBrush, aBounds );
+
+ return true;
+ }
+
+ bool fillAxialGradient( GraphicsSharedPtr& rGraphics,
+ const Gdiplus::Color& rColor1,
+ const Gdiplus::Color& rColor2,
+ const GraphicsPathSharedPtr& rFillPath,
+ const rendering::Texture& texture )
+ {
+ // setup a linear gradient with three colors
+ // -----------------------------------------
+
+ Gdiplus::LinearGradientBrush aBrush(
+ Gdiplus::PointF(0.0f,
+ 0.5f),
+ Gdiplus::PointF(1.0f,
+ 0.5f),
+ rColor1,
+ rColor1 );
+
+ Gdiplus::Color aColors[] =
+ {
+ rColor1, // at 0.0
+ rColor2, // at 0.5
+ rColor1 // at 1.0
+ };
+
+ Gdiplus::REAL aPositions[] =
+ {
+ 0.0,
+ 0.5,
+ 1.0
+ };
+
+ if( Gdiplus::Ok != aBrush.SetInterpolationColors( aColors,
+ aPositions,
+ sizeof( aPositions ) / sizeof(Gdiplus::REAL) ) )
+ {
+ return false;
+ }
+
+ // render background color, as LinearGradientBrush does not
+ // properly support the WrapModeClamp repeat mode
+ Gdiplus::SolidBrush aBackgroundBrush( rColor1 );
+ rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() );
+
+ // TODO(F2): This does not yet support other repeat modes
+ // except clamp, and probably also no multi-texturing
+
+ // calculate parallelogram of gradient in object space, extend
+ // top and bottom of it such that they cover the whole fill
+ // path bound area
+ ::basegfx::B2DHomMatrix aTextureTransform;
+ ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
+ texture.AffineTransform );
+
+ ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 );
+ ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 );
+ ::basegfx::B2DPoint aRightTop( 1.0, 0.0 );
+ ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 );
+
+ aLeftTop *= aTextureTransform;
+ aLeftBottom *= aTextureTransform;
+ aRightTop *= aTextureTransform;
+ aRightBottom*= aTextureTransform;
+
+ Gdiplus::RectF aBounds;
+ rFillPath->GetBounds( &aBounds, NULL, NULL );
+
+ // now, we potentially have to enlarge our gradient area
+ // atop and below the transformed [0,1]x[0,1] unit rect,
+ // for the gradient to fill the complete bound rect.
+ ::basegfx::tools::infiniteLineFromParallelogram( aLeftTop,
+ aLeftBottom,
+ aRightTop,
+ aRightBottom,
+ tools::b2dRangeFromGdiPlusRectF( aBounds ) );
+
+ // generate clip polygon from the extended parallelogram
+ // (exploit the feature that distinct lines in a figure are
+ // automatically closed by a straight line)
+ Gdiplus::GraphicsPath aClipPath;
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aLeftTop.getX()),
+ static_cast<Gdiplus::REAL>(aLeftTop.getY()),
+ static_cast<Gdiplus::REAL>(aRightTop.getX()),
+ static_cast<Gdiplus::REAL>(aRightTop.getY()) );
+ aClipPath.AddLine( static_cast<Gdiplus::REAL>(aRightBottom.getX()),
+ static_cast<Gdiplus::REAL>(aRightBottom.getY()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getX()),
+ static_cast<Gdiplus::REAL>(aLeftBottom.getY()) );
+ aClipPath.CloseFigure();
+
+ // limit output to a _single_ strip of the gradient (have to
+ // clip here, since GDI+ wrapmode clamp does not work here)
+ if( Gdiplus::Ok != rGraphics->SetClip( rFillPath.get(),
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+ if( Gdiplus::Ok != rGraphics->SetClip( &aClipPath,
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ // now, finally, output the gradient
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
+ texture.AffineTransform );
+ aBrush.SetTransform( &aMatrix );
+
+ rGraphics->FillRectangle( &aBrush, aBounds );
+
+ return true;
+ }
+
+ PathGradientBrushSharedPtr createPathGradientBrush( const GraphicsPathSharedPtr& rGradientPath,
+ const Gdiplus::Color& rColor1,
+ const Gdiplus::Color& rColor2 )
+ {
+ PathGradientBrushSharedPtr pGradientBrush(
+ new Gdiplus::PathGradientBrush( rGradientPath.get() ) );
+
+ Gdiplus::Color aColors[] =
+ {
+ rColor1
+ };
+
+ INT nCount(1);
+
+ pGradientBrush->SetSurroundColors( aColors,
+ &nCount );
+ pGradientBrush->SetCenterColor( rColor2 );
+
+ return pGradientBrush;
+ }
+
+ bool fillPolygonalGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
+ GraphicsSharedPtr& rGraphics,
+ const Gdiplus::Color& rColor1,
+ const Gdiplus::Color& rColor2,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::Texture& texture )
+ {
+ Gdiplus::Matrix aMatrix;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix,
+ texture.AffineTransform );
+
+ // copy original fill path object, might have to change it
+ // below
+ GraphicsPathSharedPtr pFillPath( rPath );
+
+ // clone original gradient path object, we need to change it
+ // below
+ GraphicsPathSharedPtr pGradientPath(
+ tools::graphicsPathFromB2DPolygon( rValues.maGradientPoly ) );
+
+ ENSURE_OR_RETURN( pGradientPath.get(),
+ "ParametricPolyPolygon::fillPolygonalGradient(): Could not clone path" );
+
+ PathGradientBrushSharedPtr pGradientBrush;
+
+ // fill background uniformly with end color
+ Gdiplus::SolidBrush aBackgroundBrush( rColor1 );
+ rGraphics->FillPath( &aBackgroundBrush, pFillPath.get() );
+
+ // scale focus according to aspect ratio: for wider-than-tall
+ // bounds (nAspectRatio > 1.0), the focus must have non-zero
+ // width. Specifically, a bound rect twice as wide as tall has
+ // a focus of half it's width.
+ if( !::rtl::math::approxEqual(rValues.mnAspectRatio,
+ 1.0) )
+ {
+ // KLUDGE 1:
+ //
+ // And here comes the greatest shortcoming of the GDI+
+ // gradients ever: SetFocusScales completely ignores
+ // transformations, both when set at the PathGradientBrush
+ // and for the world coordinate system. Thus, to correctly
+ // display anisotrophic path gradients, we have to render
+ // them by hand. WTF.
+
+ // TODO(F2): This does not yet support other repeat modes
+ // except clamp, and probably also no multi-texturing
+
+ // limit output to to-be-filled polygon
+ if( Gdiplus::Ok != rGraphics->SetClip( pFillPath.get(),
+ Gdiplus::CombineModeIntersect ) )
+ {
+ return false;
+ }
+
+ rGraphics->MultiplyTransform( &aMatrix );
+
+ // disable anti-aliasing, if any
+ const Gdiplus::SmoothingMode eOldAAMode( rGraphics->GetSmoothingMode() );
+ rGraphics->SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed );
+
+
+ // determine number of steps to use
+ // --------------------------------
+
+ // TODO(Q2): Unify step calculations with VCL canvas
+ const int nColorSteps(
+ ::std::max(
+ labs( rColor1.GetRed() - rColor2.GetRed() ),
+ ::std::max(
+ labs( rColor1.GetGreen() - rColor2.GetGreen() ),
+ labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) ) );
+
+ Gdiplus::Matrix aWorldTransformMatrix;
+ rGraphics->GetTransform( &aWorldTransformMatrix );
+
+ Gdiplus::RectF aBounds;
+ pGradientPath->GetBounds( &aBounds, &aWorldTransformMatrix, NULL );
+
+ // longest line in gradient bound rect
+ const int nGradientSize(
+ static_cast<int>( hypot( aBounds.Width, aBounds.Height ) + 1.0 ) );
+
+ // typical number for pixel of the same color (strip size)
+ const int nStripSize( 2 );
+
+ // use at least three steps, and at utmost the number of
+ // color steps.
+ const int nStepCount(
+ ::std::max(
+ 3,
+ ::std::min(
+ nGradientSize / nStripSize,
+ nColorSteps ) ) + 1 );
+
+
+ Gdiplus::SolidBrush aFillBrush( rColor1 );
+ Gdiplus::Matrix aGDIScaleMatrix;
+ ::basegfx::B2DHomMatrix aScaleMatrix;
+
+ // calc relative size for anisotrophic polygon scaling:
+ // when the aspect ratio is e.g. 2.0, that denotes a
+ // gradient which is twice as wide as high. Then, to
+ // generate a symmetric gradient, the x direction is only
+ // scaled to 0.5 times the gradient width. Similarly, when
+ // the aspect ratio is 4.0, the focus has 3/4 the width of
+ // the overall gradient.
+ const double nRelativeFocusSize( rValues.mnAspectRatio > 1.0 ?
+ 1.0 - 1.0/rValues.mnAspectRatio :
+ 1.0 - rValues.mnAspectRatio );
+
+ for( int i=1; i<nStepCount; ++i )
+ {
+ // lerp color. Funnily, the straight-forward integer
+ // lerp ((nStepCount - i)*val + i*val)/nStepCount gets
+ // fully botched by MSVC, at least for anything that
+ // really inlines inlines (i.e. every compile without
+ // debug=t)
+ const double nFrac( (double)i/nStepCount );
+
+ const Gdiplus::Color aFillColor(
+ static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetRed() + nFrac*rColor2.GetRed() ),
+ static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetGreen() + nFrac*rColor2.GetGreen() ),
+ static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetBlue() + nFrac*rColor2.GetBlue() ) );
+
+ aFillBrush.SetColor( aFillColor );
+
+ const double nCurrScale( (nStepCount-i)/(double)nStepCount );
+ aScaleMatrix.identity();
+ aScaleMatrix.translate( -0.5, -0.5 );
+
+ // handle anisotrophic polygon scaling
+ if( rValues.mnAspectRatio < 1.0 )
+ {
+ // height > width case
+ aScaleMatrix.scale( nCurrScale,
+ // lerp with nCurrScale
+ // between 1.0 and
+ // relative focus height
+ nCurrScale + (1.0-nCurrScale)*nRelativeFocusSize );
+ }
+ else if( rValues.mnAspectRatio > 1.0 )
+ {
+ // width > height case
+ aScaleMatrix.scale( nCurrScale + (1.0-nCurrScale)*nRelativeFocusSize,
+ // lerp with nCurrScale
+ // between 1.0 and
+ // relative focus width
+ nCurrScale );
+ }
+ else
+ {
+ aScaleMatrix.scale( nCurrScale,
+ nCurrScale );
+ }
+
+ aScaleMatrix.translate( 0.5, 0.5 );
+
+ tools::gdiPlusMatrixFromB2DHomMatrix( aGDIScaleMatrix,
+ aScaleMatrix );
+
+ GraphicsPathSharedPtr pScaledGradientPath(
+ tools::graphicsPathFromB2DPolygon( rValues.maGradientPoly ) );
+ pScaledGradientPath->Transform( &aGDIScaleMatrix );
+
+ rGraphics->FillPath( &aFillBrush, pScaledGradientPath.get() );
+ }
+
+ // reset to old anti-alias mode
+ rGraphics->SetSmoothingMode( eOldAAMode );
+ }
+ else
+ {
+ // KLUDGE 2:
+ //
+ // We're generating a PathGradientBrush from scratch here,
+ // and put in a transformed GraphicsPath (transformed with
+ // the texture transform). This is because the
+ // straight-forward approach to store a Brush pointer at
+ // this class and set a texture transform via
+ // PathGradientBrush::SetTransform() is spoiled by MS: it
+ // seems that _either_ the texture transform, _or_ the
+ // transform at the Graphics can be set, but not both. If
+ // one sets both, only the translational components of the
+ // texture is respected.
+
+ pGradientPath->Transform( &aMatrix );
+
+ pGradientBrush = createPathGradientBrush(
+ pGradientPath,
+ rColor1,
+ rColor2 );
+
+ // explicitely setup center point. Since the center of GDI+
+ // gradients are by default the _centroid_ of the path
+ // (i.e. the weighted sum of edge points), it will not
+ // necessarily coincide with our notion of center.
+ Gdiplus::PointF aCenterPoint(0.5, 0.5);
+ aMatrix.TransformPoints( &aCenterPoint );
+ pGradientBrush->SetCenterPoint( aCenterPoint );
+
+ const bool bTileX( texture.RepeatModeX != rendering::TexturingMode::CLAMP );
+ const bool bTileY( texture.RepeatModeY != rendering::TexturingMode::CLAMP );
+
+ if( bTileX && bTileY )
+ pGradientBrush->SetWrapMode( Gdiplus::WrapModeTile );
+ else
+ {
+ OSL_ENSURE( bTileY == bTileX,
+ "ParametricPolyPolygon::fillPolygonalGradient(): Cannot have repeat x and repeat y differ!" );
+
+ pGradientBrush->SetWrapMode( Gdiplus::WrapModeClamp );
+ }
+
+ // render actual gradient
+ rGraphics->FillPath( pGradientBrush.get(), pFillPath.get() );
+ }
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ rGraphics->MultiplyTransform( &aMatrix );
+
+ Gdiplus::Pen aPen( Gdiplus::Color( 255, 255, 0, 0 ),
+ 0.0001f );
+
+ rGraphics->DrawRectangle( &aPen,
+ Gdiplus::RectF( 0.0f, 0.0f,
+ 1.0f, 1.0f ) );
+#endif
+
+ return true;
+ }
+
+ bool fillGradient( const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const Gdiplus::Color& rColor1,
+ const Gdiplus::Color& rColor2,
+ GraphicsSharedPtr& rGraphics,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::Texture& texture )
+ {
+ switch( rValues.meType )
+ {
+ case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
+ fillLinearGradient( rGraphics,
+ rColor1,
+ rColor2,
+ rPath,
+ texture );
+ break;
+
+ case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL:
+ fillAxialGradient( rGraphics,
+ rColor1,
+ rColor2,
+ rPath,
+ texture );
+ break;
+
+ case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
+ // FALLTHROUGH intended
+ case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
+ fillPolygonalGradient( rValues,
+ rGraphics,
+ rColor1,
+ rColor2,
+ rPath,
+ texture );
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "CanvasHelper::fillGradient(): Unexpected case" );
+ }
+
+ return true;
+ }
+
+ void fillBitmap( const uno::Reference< rendering::XBitmap >& xBitmap,
+ GraphicsSharedPtr& rGraphics,
+ const GraphicsPathSharedPtr& rPath,
+ const rendering::Texture& rTexture )
+ {
+ OSL_ENSURE( rTexture.RepeatModeX ==
+ rTexture.RepeatModeY,
+ "CanvasHelper::fillBitmap(): GDI+ cannot handle differing X/Y repeat mode." );
+
+ const bool bClamp( rTexture.RepeatModeX == rendering::TexturingMode::CLAMP &&
+ rTexture.RepeatModeY == rendering::TexturingMode::CLAMP );
+
+ const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
+ ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 &&
+ aBmpSize.Height != 0,
+ "CanvasHelper::fillBitmap(): zero-sized texture bitmap" );
+
+ // TODO(P3): Detect case that path is rectangle and
+ // bitmap is just scaled into that. Then, we can
+ // render directly, without generating a temporary
+ // GDI+ bitmap (this is significant, because drawing
+ // layer presents background object bitmap in that
+ // way!)
+ BitmapSharedPtr pBitmap(
+ tools::bitmapFromXBitmap( xBitmap ) );
+
+ TextureBrushSharedPtr pBrush;
+
+ if( ::rtl::math::approxEqual( rTexture.Alpha,
+ 1.0 ) )
+ {
+ pBrush.reset(
+ new Gdiplus::TextureBrush(
+ pBitmap.get(),
+ bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile ) );
+ }
+ else
+ {
+ Gdiplus::ImageAttributes aImgAttr;
+
+ tools::setModulateImageAttributes( aImgAttr,
+ 1.0,
+ 1.0,
+ 1.0,
+ rTexture.Alpha );
+
+ Gdiplus::Rect aRect(0,0,
+ aBmpSize.Width,
+ aBmpSize.Height);
+ pBrush.reset(
+ new Gdiplus::TextureBrush(
+ pBitmap.get(),
+ aRect,
+ &aImgAttr ) );
+
+ pBrush->SetWrapMode(
+ bClamp ? Gdiplus::WrapModeClamp : Gdiplus::WrapModeTile );
+ }
+
+ Gdiplus::Matrix aTextureTransform;
+ tools::gdiPlusMatrixFromAffineMatrix2D( aTextureTransform,
+ rTexture.AffineTransform );
+
+ // scale down bitmap to [0,1]x[0,1] rect, as required
+ // from the XCanvas interface.
+ pBrush->ScaleTransform( static_cast< Gdiplus::REAL >(1.0/aBmpSize.Width),
+ static_cast< Gdiplus::REAL >(1.0/aBmpSize.Height) );
+ pBrush->MultiplyTransform( &aTextureTransform );
+
+ // TODO(F1): FillRule
+ ENSURE_OR_THROW(
+ Gdiplus::Ok == rGraphics->FillPath( pBrush.get(),
+ rPath.get() ),
+ "CanvasHelper::fillTexturedPolyPolygon(): GDI+ call failed" );
+ }
+ }
+
+ // -------------------------------------------------------------
+
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
+ const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState,
+ const uno::Sequence< rendering::Texture >& textures )
+ {
+ ENSURE_OR_THROW( xPolyPolygon.is(),
+ "CanvasHelper::fillTexturedPolyPolygon: polygon is NULL");
+ ENSURE_OR_THROW( textures.getLength(),
+ "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence");
+
+ if( needOutput() )
+ {
+ GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() );
+
+ setupGraphicsState( pGraphics, viewState, renderState );
+
+ // TODO(F1): Multi-texturing
+ if( textures[0].Gradient.is() )
+ {
+ // try to cast XParametricPolyPolygon2D reference to
+ // our implementation class.
+ ::canvas::ParametricPolyPolygon* pGradient =
+ dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
+
+ if( pGradient )
+ {
+ const ::canvas::ParametricPolyPolygon::Values& rValues(
+ pGradient->getValues() );
+
+ // TODO: use all the colors and place them on given positions/stops
+ const Gdiplus::Color aColor1(tools::sequenceToArgb(rValues.maColors[0]));
+ const Gdiplus::Color aColor2(tools::sequenceToArgb(rValues.maColors[rValues.maColors.getLength () - 1] ));
+
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ fillGradient( rValues,
+ aColor1,
+ aColor2,
+ pGraphics,
+ tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
+ textures[0] );
+ }
+ }
+ else if( textures[0].Bitmap.is() )
+ {
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ fillBitmap( textures[0].Bitmap,
+ pGraphics,
+ tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ),
+ textures[0] );
+ }
+ }
+
+ // TODO(P1): Provide caching here.
+ return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ }
+}
diff --git a/canvas/source/directx/dx_config.cxx b/canvas/source/directx/dx_config.cxx
new file mode 100755
index 000000000000..e124d4d78e6a
--- /dev/null
+++ b/canvas/source/directx/dx_config.cxx
@@ -0,0 +1,179 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_config.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include "dx_config.hxx"
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <comphelper/anytostring.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+using namespace com::sun::star;
+
+namespace dxcanvas
+{
+ DXCanvasItem::DXCanvasItem() :
+ ConfigItem(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "Office.Canvas/DXCanvas" )),
+ CONFIG_MODE_IMMEDIATE_UPDATE ),
+ maValues(),
+ maMaxTextureSize(),
+ mbBlacklistCurrentDevice(false),
+ mbValuesDirty(false)
+ {
+ try
+ {
+ uno::Sequence< ::rtl::OUString > aName(1);
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DeviceBlacklist" ));
+
+ uno::Sequence< uno::Any > aProps( GetProperties( aName ));
+ uno::Sequence< sal_Int32 > aValues;
+
+ if( aProps.getLength() > 0 &&
+ (aProps[0] >>= aValues) )
+ {
+ const sal_Int32* pValues = aValues.getConstArray();
+ const sal_Int32 nNumEntries( aValues.getLength()*sizeof(sal_Int32)/sizeof(DeviceInfo) );
+ for( sal_Int32 i=0; i<nNumEntries; ++i )
+ {
+ DeviceInfo aInfo;
+ aInfo.nVendorId = *pValues++;
+ aInfo.nDeviceId = *pValues++;
+ aInfo.nDeviceSubSysId = *pValues++;
+ aInfo.nDeviceRevision = *pValues++;
+ aInfo.nDriverId = *pValues++;
+ aInfo.nDriverVersion = *pValues++;
+ aInfo.nDriverSubVersion = *pValues++;
+ aInfo.nDriverBuildId = *pValues++;
+ maValues.insert(aInfo);
+ }
+ }
+
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlacklistCurrentDevice" ));
+ aProps = GetProperties( aName );
+ if( aProps.getLength() > 0 )
+ aProps[0] >>= mbBlacklistCurrentDevice;
+
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxTextureSize" ));
+ aProps = GetProperties( aName );
+ if( aProps.getLength() > 0 )
+ maMaxTextureSize.reset( aProps[0].get<sal_Int32>() );
+ else
+ maMaxTextureSize.reset();
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ DXCanvasItem::~DXCanvasItem()
+ {
+ if( !mbValuesDirty )
+ return;
+
+ try
+ {
+ uno::Sequence< ::rtl::OUString > aName(1);
+ aName[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DeviceBlacklist" ));
+
+ uno::Sequence< sal_Int32 > aValues( sizeof(DeviceInfo)/sizeof(sal_Int32)*maValues.size() );
+
+ sal_Int32* pValues = aValues.getArray();
+ ValueSet::const_iterator aIter( maValues.begin() );
+ const ValueSet::const_iterator aEnd( maValues.end() );
+ while( aIter != aEnd )
+ {
+ const DeviceInfo& rInfo( *aIter );
+ *pValues++ = rInfo.nVendorId;
+ *pValues++ = rInfo.nDeviceId;
+ *pValues++ = rInfo.nDeviceSubSysId;
+ *pValues++ = rInfo.nDeviceRevision;
+ *pValues++ = rInfo.nDriverId;
+ *pValues++ = rInfo.nDriverVersion;
+ *pValues++ = rInfo.nDriverSubVersion;
+ *pValues++ = rInfo.nDriverBuildId;
+ ++aIter;
+ }
+
+ uno::Sequence< uno::Any > aValue(1);
+ aValue[0] <<= aValues;
+ PutProperties( aName, aValue );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ void DXCanvasItem::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& ) {}
+ void DXCanvasItem::Commit() {}
+
+ bool DXCanvasItem::isDeviceUsable( const DeviceInfo& rDeviceInfo ) const
+ {
+ return maValues.find(rDeviceInfo) == maValues.end();
+ }
+
+ bool DXCanvasItem::isBlacklistCurrentDevice() const
+ {
+ return mbBlacklistCurrentDevice;
+ }
+
+ void DXCanvasItem::blacklistDevice( const DeviceInfo& rDeviceInfo )
+ {
+ mbValuesDirty = true;
+ maValues.insert(rDeviceInfo);
+ }
+
+ void DXCanvasItem::adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const
+ {
+ if( maMaxTextureSize )
+ {
+ io_maxTextureSize.setX(
+ std::min( *maMaxTextureSize,
+ io_maxTextureSize.getX() ));
+ io_maxTextureSize.setY(
+ std::min( *maMaxTextureSize,
+ io_maxTextureSize.getY() ));
+ }
+ }
+
+}
diff --git a/canvas/source/directx/dx_config.hxx b/canvas/source/directx/dx_config.hxx
new file mode 100644
index 000000000000..1fffcb2ed56e
--- /dev/null
+++ b/canvas/source/directx/dx_config.hxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_config.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_DXCONFIG_HXX
+#define _DXCANVAS_DXCONFIG_HXX
+
+#include <unotools/configitem.hxx>
+#include <boost/optional.hpp>
+#include <set>
+
+namespace basegfx { class B2IVector; }
+
+namespace dxcanvas
+{
+ /** Provide DX canvas config data
+ */
+ class DXCanvasItem : public ::utl::ConfigItem
+ {
+ public:
+ DXCanvasItem();
+
+ struct DeviceInfo
+ {
+ sal_Int32 nVendorId;
+ sal_Int32 nDeviceId;
+ sal_Int32 nDeviceSubSysId;
+ sal_Int32 nDeviceRevision;
+
+ sal_Int32 nDriverId;
+ sal_Int32 nDriverVersion;
+ sal_Int32 nDriverSubVersion;
+ sal_Int32 nDriverBuildId;
+
+ bool operator<( const DeviceInfo& rRHS ) const
+ {
+ return nVendorId != rRHS.nVendorId ? nVendorId < rRHS.nVendorId :
+ (nDeviceId != rRHS.nDeviceId ? nDeviceId < rRHS.nDeviceId :
+ (nDeviceSubSysId != rRHS.nDeviceSubSysId ? nDeviceSubSysId < rRHS.nDeviceSubSysId :
+ (nDeviceRevision != rRHS.nDeviceRevision ? nDeviceRevision < rRHS.nDeviceRevision :
+ (nDriverId != rRHS.nDriverId ? nDriverId < rRHS.nDriverId :
+ (nDriverVersion != rRHS.nDriverVersion ? nDriverVersion < rRHS.nDriverVersion :
+ (nDriverSubVersion != rRHS.nDriverSubVersion ? nDriverSubVersion < rRHS.nDriverSubVersion :
+ (nDriverBuildId != rRHS.nDriverBuildId ? nDriverBuildId < rRHS.nDriverBuildId : false)))))));
+ }
+ };
+
+ ~DXCanvasItem();
+
+ bool isDeviceUsable( const DeviceInfo& rDeviceInfo ) const;
+ bool isBlacklistCurrentDevice() const;
+ void blacklistDevice( const DeviceInfo& rDeviceInfo );
+ void adaptMaxTextureSize( basegfx::B2IVector& io_maxTextureSize ) const;
+ virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames);
+ virtual void Commit();
+
+ private:
+ typedef std::set< DeviceInfo > ValueSet;
+ ValueSet maValues;
+ boost::optional<sal_Int32> maMaxTextureSize;
+ bool mbBlacklistCurrentDevice;
+ bool mbValuesDirty;
+ };
+}
+
+#endif /* #ifndef _DXCANVAS_DXCONFIG_HXX */
diff --git a/canvas/source/directx/dx_devicehelper.cxx b/canvas/source/directx/dx_devicehelper.cxx
new file mode 100755
index 000000000000..f08609a3b1f9
--- /dev/null
+++ b/canvas/source/directx/dx_devicehelper.cxx
@@ -0,0 +1,239 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_devicehelper.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <vcl/window.hxx>
+#include <vcl/canvastools.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include "dx_linepolypolygon.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_devicehelper.hxx"
+
+
+#undef WB_LEFT
+#undef WB_RIGHT
+#include "dx_winstuff.hxx"
+
+
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ DeviceHelper::DeviceHelper() :
+ mpDevice( NULL ),
+ mnHDC(0)
+ {
+ }
+
+ void DeviceHelper::init( HDC hdc,
+ rendering::XGraphicDevice& rDevice )
+ {
+ mnHDC = hdc;
+ mpDevice = &rDevice;
+ }
+
+ void DeviceHelper::disposing()
+ {
+ // release all references
+ mnHDC = 0;
+ mpDevice = NULL;
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalResolution()
+ {
+ if( !mpDevice )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ HDC hDC = getHDC();
+ ENSURE_OR_THROW( hDC,
+ "DeviceHelper::getPhysicalResolution(): cannot retrieve HDC from window" );
+
+ const int nHorzRes( GetDeviceCaps( hDC,
+ LOGPIXELSX ) );
+ const int nVertRes( GetDeviceCaps( hDC,
+ LOGPIXELSY ) );
+
+ return geometry::RealSize2D( nHorzRes*25.4,
+ nVertRes*25.4 );
+ }
+
+ geometry::RealSize2D DeviceHelper::getPhysicalSize()
+ {
+ if( !mpDevice )
+ return ::canvas::tools::createInfiniteSize2D(); // we're disposed
+
+ HDC hDC=getHDC();
+ ENSURE_OR_THROW( hDC,
+ "DeviceHelper::getPhysicalSize(): cannot retrieve HDC from window" );
+
+ const int nHorzSize( GetDeviceCaps( hDC,
+ HORZSIZE ) );
+ const int nVertSize( GetDeviceCaps( hDC,
+ VERTSIZE ) );
+
+ return geometry::RealSize2D( nHorzSize,
+ nVertSize );
+ }
+
+ uno::Reference< rendering::XLinePolyPolygon2D > DeviceHelper::createCompatibleLinePolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XLinePolyPolygon2D >(
+ new LinePolyPolygon(
+ ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBezierPolyPolygon2D > DeviceHelper::createCompatibleBezierPolyPolygon(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
+
+ return uno::Reference< rendering::XBezierPolyPolygon2D >(
+ new LinePolyPolygon(
+ ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXBitmapSharedPtr pBitmap(
+ new DXBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ false));
+
+ // create a 24bit RGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ uno::Reference< rendering::XBitmap > DeviceHelper::createCompatibleAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !mpDevice )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXBitmapSharedPtr pBitmap(
+ new DXBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ true));
+
+ // create a 32bit ARGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,mpDevice));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > DeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool DeviceHelper::hasFullScreenMode()
+ {
+ return false;
+ }
+
+ sal_Bool DeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
+ {
+ return false;
+ }
+
+ uno::Any DeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(false);
+ }
+
+ uno::Any DeviceHelper::getDeviceHandle() const
+ {
+ HDC hdc( getHDC() );
+ if( hdc )
+ return uno::makeAny( reinterpret_cast< sal_Int64 >(hdc) );
+ else
+ return uno::Any();
+ }
+
+ uno::Any DeviceHelper::getSurfaceHandle() const
+ {
+ // TODO(F1): expose DirectDraw object
+ //return mpBackBuffer->getBitmap().get();
+ return uno::Any();
+ }
+
+ namespace
+ {
+ struct DeviceColorSpace: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
+ DeviceColorSpace>
+ {
+ uno::Reference<rendering::XColorSpace> operator()()
+ {
+ return vcl::unotools::createStandardColorSpace();
+ }
+ };
+ }
+
+ uno::Reference<rendering::XColorSpace> DeviceHelper::getColorSpace() const
+ {
+ // always the same
+ return DeviceColorSpace::get();
+ }
+}
diff --git a/canvas/source/directx/dx_devicehelper.hxx b/canvas/source/directx/dx_devicehelper.hxx
new file mode 100755
index 000000000000..79ffee0562b0
--- /dev/null
+++ b/canvas/source/directx/dx_devicehelper.hxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_devicehelper.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_DEVICEHELPER_HXX
+#define _DXCANVAS_DEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_bitmap.hxx"
+
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include <boost/utility.hpp>
+
+
+/* Definition of DeviceHelper class */
+
+namespace dxcanvas
+{
+ class DeviceHelper : private ::boost::noncopyable
+ {
+ public:
+ DeviceHelper();
+
+ /** Init the device helper
+
+ @param hdc
+ private or class dc of the output device. is only stored,
+ not release
+
+ @param rDevice
+ Ref back to owning UNO device
+ */
+ void init( HDC hdc,
+ com::sun::star::rendering::XGraphicDevice& rDevice );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // XWindowGraphicDevice
+ ::com::sun::star::geometry::RealSize2D getPhysicalResolution();
+ ::com::sun::star::geometry::RealSize2D getPhysicalSize();
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XLinePolyPolygon2D > createCompatibleLinePolyPolygon(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& points );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBezierPolyPolygon2D > createCompatibleBezierPolyPolygon(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > >& points );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+
+ sal_Bool hasFullScreenMode();
+ sal_Bool enterFullScreenMode( sal_Bool bEnter );
+
+ ::com::sun::star::uno::Any isAccelerated() const;
+ ::com::sun::star::uno::Any getDeviceHandle() const;
+ ::com::sun::star::uno::Any getSurfaceHandle() const;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XColorSpace > getColorSpace() const;
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const {}
+
+ protected:
+ HDC getHDC() const { return mnHDC; }
+ com::sun::star::rendering::XGraphicDevice* getDevice() const { return mpDevice; }
+
+ private:
+ /** Phyical output device
+
+ Deliberately not a refcounted reference, because of
+ potential circular references for canvas. Needed to
+ create bitmaps
+ */
+ com::sun::star::rendering::XGraphicDevice* mpDevice;
+ HDC mnHDC;
+ };
+
+ typedef ::rtl::Reference< com::sun::star::rendering::XGraphicDevice > DeviceRef;
+}
+
+#endif /* _DXCANVAS_DEVICEHELPER_HXX */
diff --git a/canvas/source/directx/dx_gdiplususer.cxx b/canvas/source/directx/dx_gdiplususer.cxx
new file mode 100755
index 000000000000..0a070e5e67df
--- /dev/null
+++ b/canvas/source/directx/dx_gdiplususer.cxx
@@ -0,0 +1,84 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_gdiplususer.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <osl/mutex.hxx>
+
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+namespace dxcanvas
+{
+ namespace
+ {
+ ::osl::Mutex* p_gdiPlusUsageCountMutex( osl::Mutex::getGlobalMutex() );
+ int n_gdiPlusUsageCount( 0 );
+
+ ULONG_PTR a_GdiPlusToken; // GDI+ handle. Owned by this object
+ }
+
+ GDIPlusUserSharedPtr GDIPlusUser::createInstance()
+ {
+ return GDIPlusUserSharedPtr( new GDIPlusUser() );
+ }
+
+ GDIPlusUser::~GDIPlusUser()
+ {
+ ::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
+
+ --n_gdiPlusUsageCount;
+
+ if( n_gdiPlusUsageCount == 0 )
+ Gdiplus::GdiplusShutdown( a_GdiPlusToken );
+ }
+
+ GDIPlusUser::GDIPlusUser()
+ {
+ ::osl::MutexGuard aGuard( *p_gdiPlusUsageCountMutex );
+
+ if( n_gdiPlusUsageCount == 0 )
+ {
+ // Setup GDI+
+
+ // No extras here, simply taking GdiplusStartupInput's
+ // default constructor
+ Gdiplus::GdiplusStartupInput gdiPlusStartupInput;
+
+ Gdiplus::GdiplusStartup( &a_GdiPlusToken,
+ &gdiPlusStartupInput,
+ NULL );
+ }
+
+ ++n_gdiPlusUsageCount;
+ }
+}
diff --git a/canvas/source/directx/dx_gdiplususer.hxx b/canvas/source/directx/dx_gdiplususer.hxx
new file mode 100755
index 000000000000..c80a9f1aedc0
--- /dev/null
+++ b/canvas/source/directx/dx_gdiplususer.hxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_gdiplususer.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_GDIPLUSUSER_HXX
+#define _DXCANVAS_GDIPLUSUSER_HXX
+
+#include <sal/config.h>
+
+#include <boost/shared_ptr.hpp>
+
+/* Definition of GDIPlusUser class */
+
+namespace dxcanvas
+{
+ class GDIPlusUser
+ {
+ public:
+ typedef ::boost::shared_ptr< GDIPlusUser > GDIPlusUserSharedPtr;
+
+ static GDIPlusUserSharedPtr createInstance();
+ ~GDIPlusUser();
+
+ private:
+ GDIPlusUser(); // create us via factory method
+ };
+
+ typedef GDIPlusUser::GDIPlusUserSharedPtr GDIPlusUserSharedPtr;
+
+}
+
+#endif /* _DXCANVAS_GDIPLUSUSER_HXX */
diff --git a/canvas/source/directx/dx_graphicsprovider.hxx b/canvas/source/directx/dx_graphicsprovider.hxx
new file mode 100644
index 000000000000..977795e7583f
--- /dev/null
+++ b/canvas/source/directx/dx_graphicsprovider.hxx
@@ -0,0 +1,56 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_graphicsprovider.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_GRAPHICSPROVIDER_HXX
+#define _DXCANVAS_GRAPHICSPROVIDER_HXX
+
+#include "dx_winstuff.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+namespace Gdiplus{ class Graphics; }
+
+namespace dxcanvas
+{
+ /** Provider of a Gdiplus::Graphics. Interface
+ */
+ class GraphicsProvider : private ::boost::noncopyable
+ {
+ public:
+ virtual ~GraphicsProvider() {}
+
+ virtual GraphicsSharedPtr getGraphics() = 0;
+ };
+
+ typedef ::boost::shared_ptr< GraphicsProvider > GraphicsProviderSharedPtr;
+}
+
+#endif /* _DXCANVAS_GRAPHICSPROVIDER_HXX */
diff --git a/canvas/source/directx/dx_ibitmap.hxx b/canvas/source/directx/dx_ibitmap.hxx
new file mode 100644
index 000000000000..9d78562765e4
--- /dev/null
+++ b/canvas/source/directx/dx_ibitmap.hxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_ibitmap.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_DXIBITMAP_HXX
+#define _DXCANVAS_DXIBITMAP_HXX
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <boost/shared_ptr.hpp>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include "dx_graphicsprovider.hxx"
+
+namespace dxcanvas
+{
+ /// Interface for internal canvas bitmap objects
+ struct IBitmap : public GraphicsProvider
+ {
+ virtual BitmapSharedPtr getBitmap() const = 0;
+ virtual ::basegfx::B2IVector getSize() const = 0;
+ virtual bool hasAlpha() const = 0;
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getData(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) = 0;
+
+ virtual void setData(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect ) = 0;
+
+ virtual void setPixel(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) = 0;
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getPixel(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos ) = 0;
+ };
+
+ typedef boost::shared_ptr<IBitmap> IBitmapSharedPtr;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_impltools.cxx b/canvas/source/directx/dx_impltools.cxx
new file mode 100755
index 000000000000..40164c9a1d87
--- /dev/null
+++ b/canvas/source/directx/dx_impltools.cxx
@@ -0,0 +1,628 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_impltools.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <canvas/verifyinput.hxx>
+
+#include "dx_impltools.hxx"
+#include "dx_vcltools.hxx"
+#include "dx_linepolypolygon.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_canvasfont.hxx"
+#include "dx_canvas.hxx"
+#include "dx_spritecanvas.hxx"
+
+#include <boost/scoped_array.hpp>
+
+#include <vector>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
+ {
+ LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
+
+ if( pPolyImpl )
+ {
+ return pPolyImpl->getPolyPolygon();
+ }
+ else
+ {
+ const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );
+
+ // not a known implementation object - try data source
+ // interfaces
+ uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
+ xPoly,
+ uno::UNO_QUERY );
+
+ if( xBezierPoly.is() )
+ {
+ return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
+ xBezierPoly->getBezierSegments( 0,
+ nPolys,
+ 0,
+ -1 ) );
+ }
+ else
+ {
+ uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
+ xPoly,
+ uno::UNO_QUERY );
+
+ // no implementation class and no data provider
+ // found - contract violation.
+ ENSURE_ARG_OR_THROW( xLinePoly.is(),
+ "VCLCanvas::polyPolygonFromXPolyPolygon2D(): Invalid input "
+ "poly-polygon, cannot retrieve vertex data" );
+
+ return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
+ xLinePoly->getPoints( 0,
+ nPolys,
+ 0,
+ -1 ) );
+ }
+ }
+ }
+
+ void setupGraphics( Gdiplus::Graphics& rGraphics )
+ {
+ // setup graphics with (somewhat arbitrary) defaults
+ //rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighQuality );
+ rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
+ //rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear ); // with prefiltering for shrinks
+ rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );
+
+ // #122683# Switched precedence of pixel offset
+ // mode. Seemingly, polygon stroking needs
+ // PixelOffsetModeNone to achieve visually pleasing
+ // results, whereas all other operations (e.g. polygon
+ // fills, bitmaps) look better with PixelOffsetModeHalf.
+ rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf ); // Pixel center at (0.5, 0.5) etc.
+ //rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
+
+ //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed ); // no line/curve antialiasing
+ //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
+ rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
+ //rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
+ rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintSystemDefault );
+ rGraphics.SetPageUnit(Gdiplus::UnitPixel);
+ }
+
+ Gdiplus::Graphics* createGraphicsFromHDC(HDC aHDC)
+ {
+ Gdiplus::Graphics* pRet = new Gdiplus::Graphics(aHDC);
+ if( pRet )
+ setupGraphics( *pRet );
+ return pRet;
+ }
+
+ Gdiplus::Graphics* createGraphicsFromBitmap(const BitmapSharedPtr& rBitmap)
+ {
+ Gdiplus::Graphics* pRet = Gdiplus::Graphics::FromImage(rBitmap.get());
+ if( pRet )
+ setupGraphics( *pRet );
+ return pRet;
+ }
+
+ void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix, const ::basegfx::B2DHomMatrix& rMatrix )
+ {
+ rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.get(0,0)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,0)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(0,1)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,1)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(0,2)),
+ static_cast<Gdiplus::REAL>(rMatrix.get(1,2)) );
+ }
+
+ void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
+ const geometry::AffineMatrix2D& rMatrix )
+ {
+ rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.m00),
+ static_cast<Gdiplus::REAL>(rMatrix.m10),
+ static_cast<Gdiplus::REAL>(rMatrix.m01),
+ static_cast<Gdiplus::REAL>(rMatrix.m11),
+ static_cast<Gdiplus::REAL>(rMatrix.m02),
+ static_cast<Gdiplus::REAL>(rMatrix.m12) );
+ }
+
+ namespace
+ {
+ // TODO(P2): Check whether this gets inlined. If not, make functor
+ // out of it
+ inline Gdiplus::PointF implGdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
+ {
+ return Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.X),
+ static_cast<Gdiplus::REAL>(rPoint.Y) );
+ }
+
+ void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr& rOutput,
+ ::std::vector< Gdiplus::PointF >& rPoints,
+ const ::basegfx::B2DPolygon& rPoly )
+ {
+ const sal_uInt32 nPoints( rPoly.count() );
+
+ if( !nPoints )
+ return;
+
+ rOutput->StartFigure();
+
+ const bool bClosedPolygon( rPoly.isClosed() );
+
+ if( rPoly.areControlPointsUsed() )
+ {
+ // control points used -> for now, add all
+ // segments as curves to GraphicsPath
+
+ // If the polygon is closed, we need to add the
+ // first point, thus, one more (can't simply
+ // GraphicsPath::CloseFigure() it, since the last
+ // point cannot have any control points for GDI+)
+ rPoints.resize( 3*nPoints + bClosedPolygon );
+
+ sal_uInt32 nCurrOutput=0;
+ for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
+ {
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+
+ const ::basegfx::B2DPoint& rControlPointA( rPoly.getNextControlPoint( nCurrPoint ) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointA.getX()),
+ static_cast<Gdiplus::REAL>(rControlPointA.getY()) );
+
+ const ::basegfx::B2DPoint& rControlPointB( rPoly.getPrevControlPoint( (nCurrPoint + 1) % nPoints) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointB.getX()),
+ static_cast<Gdiplus::REAL>(rControlPointB.getY()) );
+ }
+
+ if( bClosedPolygon )
+ {
+ // add first point again (to be able to pass
+ // control points for the last point, see
+ // above)
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint(0) );
+ rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput );
+ }
+ else
+ {
+ // GraphicsPath expects 3(n-1)+1 points (i.e. the
+ // last point must not have any trailing control
+ // points after it).
+ // Therefore, simply don't pass the last two
+ // points here.
+ if( nCurrOutput > 3 )
+ rOutput->AddBeziers( &rPoints[0], nCurrOutput-2 );
+ }
+ }
+ else
+ {
+ // no control points -> no curves, simply add
+ // straigt lines to GraphicsPath
+ rPoints.resize( nPoints );
+
+ for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
+ {
+ const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
+ rPoints[nCurrPoint] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
+ static_cast<Gdiplus::REAL>(rPoint.getY()) );
+ }
+
+ rOutput->AddLines( &rPoints[0], nPoints );
+ }
+
+ if( bClosedPolygon )
+ rOutput->CloseFigure();
+ }
+ }
+
+ Gdiplus::PointF gdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
+ {
+ return implGdiPlusPointFromRealPoint2D( rPoint );
+ }
+
+ Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRect )
+ {
+ return Gdiplus::Rect( rRect.X1,
+ rRect.Y1,
+ rRect.X2 - rRect.X1,
+ rRect.Y2 - rRect.Y1 );
+ }
+
+ Gdiplus::RectF gdiPlusRectFFromRectangle2D( const geometry::RealRectangle2D& rRect )
+ {
+ return Gdiplus::RectF( static_cast<Gdiplus::REAL>(rRect.X1),
+ static_cast<Gdiplus::REAL>(rRect.Y1),
+ static_cast<Gdiplus::REAL>(rRect.X2 - rRect.X1),
+ static_cast<Gdiplus::REAL>(rRect.Y2 - rRect.Y1) );
+ }
+
+ RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& rRect )
+ {
+ RECT aRect = {rRect.getMinX(),
+ rRect.getMinY(),
+ rRect.getMaxX(),
+ rRect.getMaxY()};
+
+ return aRect;
+ }
+
+ geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
+ {
+ return geometry::RealPoint2D( rPoint.X, rPoint.Y );
+ }
+
+ geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& rRect )
+ {
+ return geometry::RealRectangle2D( rRect.X, rRect.Y,
+ rRect.X + rRect.Width,
+ rRect.Y + rRect.Height );
+ }
+
+ ::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
+ {
+ return ::basegfx::B2DPoint( rPoint.X, rPoint.Y );
+ }
+
+ ::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& rRect )
+ {
+ return ::basegfx::B2DRange( rRect.X, rRect.Y,
+ rRect.X + rRect.Width,
+ rRect.Y + rRect.Height );
+ }
+
+ uno::Sequence< double > argbToDoubleSequence( const Gdiplus::ARGB& rColor )
+ {
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ uno::Sequence< double > aRet(4);
+
+ aRet[0] = ((rColor >> 16) & 0xFF) / 255.0; // red
+ aRet[1] = ((rColor >> 8) & 0xFF) / 255.0; // green
+ aRet[2] = (rColor & 0xFF) / 255.0; // blue
+ aRet[3] = ((rColor >> 24) & 0xFF) / 255.0; // alpha
+
+ return aRet;
+ }
+
+ uno::Sequence< sal_Int8 > argbToIntSequence( const Gdiplus::ARGB& rColor )
+ {
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ uno::Sequence< sal_Int8 > aRet(4);
+
+ aRet[0] = static_cast<sal_Int8>((rColor >> 16) & 0xFF); // red
+ aRet[1] = static_cast<sal_Int8>((rColor >> 8) & 0xFF); // green
+ aRet[2] = static_cast<sal_Int8>(rColor & 0xFF); // blue
+ aRet[3] = static_cast<sal_Int8>((rColor >> 24) & 0xFF); // alpha
+
+ return aRet;
+ }
+
+ Gdiplus::ARGB sequenceToArgb( const uno::Sequence< sal_Int8 >& rColor )
+ {
+ ENSURE_OR_THROW( rColor.getLength() > 2,
+ "sequenceToArgb: need at least three channels" );
+
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ Gdiplus::ARGB aColor;
+
+ aColor = (static_cast<sal_uInt8>(rColor[0]) << 16) | (static_cast<sal_uInt8>(rColor[1]) << 8) | static_cast<sal_uInt8>(rColor[2]);
+
+ if( rColor.getLength() > 3 )
+ aColor |= static_cast<sal_uInt8>(rColor[3]) << 24;
+
+ return aColor;
+ }
+
+ Gdiplus::ARGB sequenceToArgb( const uno::Sequence< double >& rColor )
+ {
+ ENSURE_OR_THROW( rColor.getLength() > 2,
+ "sequenceToColor: need at least three channels" );
+
+ // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
+ Gdiplus::ARGB aColor;
+
+ ::canvas::tools::verifyRange(rColor[0],0.0,1.0);
+ ::canvas::tools::verifyRange(rColor[1],0.0,1.0);
+ ::canvas::tools::verifyRange(rColor[2],0.0,1.0);
+
+ aColor =
+ (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[0] ) ) << 16) |
+ (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[1] ) ) << 8) |
+ static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[2] ) );
+
+ if( rColor.getLength() > 3 )
+ {
+ ::canvas::tools::verifyRange(rColor[3],0.0,1.0);
+ aColor |= static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[3] ) ) << 24;
+ }
+
+ return aColor;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ sal_Int32 nCurrPoly;
+ for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
+ {
+ const sal_Int32 nCurrSize( points[nCurrPoly].getLength() );
+ if( nCurrSize )
+ {
+ aPoints.resize( nCurrSize );
+
+ // TODO(F1): Closed/open polygons
+
+ // convert from RealPoint2D array to Gdiplus::PointF array
+ ::std::transform( const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray(),
+ const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray()+nCurrSize,
+ aPoints.begin(),
+ implGdiPlusPointFromRealPoint2D );
+
+ pRes->AddLines( &aPoints[0], nCurrSize );
+ }
+ }
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ graphicsPathFromB2DPolygon( pRes, aPoints, rPoly );
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
+ {
+ GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
+ ::std::vector< Gdiplus::PointF > aPoints;
+
+ const sal_uInt32 nPolies( rPoly.count() );
+ for( sal_uInt32 nCurrPoly=0; nCurrPoly<nPolies; ++nCurrPoly )
+ {
+ graphicsPathFromB2DPolygon( pRes,
+ aPoints,
+ rPoly.getB2DPolygon( nCurrPoly ) );
+ }
+
+ return pRes;
+ }
+
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
+ {
+ LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
+
+ if( pPolyImpl )
+ {
+ return pPolyImpl->getGraphicsPath();
+ }
+ else
+ {
+ return tools::graphicsPathFromB2DPolyPolygon(
+ polyPolygonFromXPolyPolygon2D( xPoly ) );
+ }
+ }
+
+ bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
+ const BitmapSharedPtr& rBitmap )
+ {
+ Gdiplus::PointF aPoint;
+ return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
+ aPoint ) );
+ }
+
+ bool drawDIBits( const GraphicsSharedPtr& rGraphics,
+ const BITMAPINFO& rBI,
+ const void* pBits )
+ {
+ BitmapSharedPtr pBitmap(
+ Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
+ (void*)pBits ) );
+
+ return drawGdiPlusBitmap( rGraphics,
+ pBitmap );
+ }
+
+ bool drawRGBABits( const GraphicsSharedPtr& rGraphics,
+ const RawRGBABitmap& rRawRGBAData )
+ {
+ BitmapSharedPtr pBitmap( new Gdiplus::Bitmap( rRawRGBAData.mnWidth,
+ rRawRGBAData.mnHeight,
+ PixelFormat32bppARGB ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rRawRGBAData.mnWidth;
+ aBmpData.Height = rRawRGBAData.mnHeight;
+ aBmpData.Stride = 4*aBmpData.Width; // bottom-up format
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = rRawRGBAData.mpBitmapData.get();
+
+ const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
+ if( Gdiplus::Ok != pBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB,
+ &aBmpData ) )
+ {
+ return false;
+ }
+
+ // commit data to bitmap
+ pBitmap->UnlockBits( &aBmpData );
+
+ return drawGdiPlusBitmap( rGraphics,
+ pBitmap );
+ }
+
+ BitmapSharedPtr bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ BitmapProvider* pBitmapProvider = dynamic_cast< BitmapProvider* >(xBitmap.get());
+
+ if( pBitmapProvider )
+ {
+ IBitmapSharedPtr pBitmap( pBitmapProvider->getBitmap() );
+ return pBitmap->getBitmap();
+ }
+ else
+ {
+ // not a native CanvasBitmap, extract VCL bitmap and
+ // render into GDI+ bitmap of similar size
+ // =================================================
+
+ const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
+ BitmapSharedPtr pBitmap;
+
+ if( xBitmap->hasAlpha() )
+ {
+ // TODO(P2): At least for the alpha bitmap case, it
+ // would be possible to generate the corresponding
+ // bitmap directly
+ pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
+ aBmpSize.Height,
+ PixelFormat32bppARGB ) );
+ }
+ else
+ {
+ // TODO(F2): Might be wise to create bitmap compatible
+ // to the VCL bitmap. Also, check whether the VCL
+ // bitmap's system handles can be used to create the
+ // GDI+ bitmap (currently, it does not seem so).
+ pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
+ aBmpSize.Height,
+ PixelFormat24bppRGB ) );
+ }
+
+ GraphicsSharedPtr pGraphics(createGraphicsFromBitmap(pBitmap));
+ tools::setupGraphics(*pGraphics);
+ if( !drawVCLBitmapFromXBitmap(
+ pGraphics,
+ xBitmap) )
+ {
+ pBitmap.reset();
+ }
+
+ return pBitmap;
+ }
+ }
+
+ CanvasFont::ImplRef canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >& xFont )
+ {
+ CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get());
+
+ ENSURE_ARG_OR_THROW( pCanvasFont,
+ "canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" );
+
+ return CanvasFont::ImplRef( pCanvasFont );
+ }
+
+ void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
+ double nRedModulation,
+ double nGreenModulation,
+ double nBlueModulation,
+ double nAlphaModulation )
+ {
+ // This gets rather verbose, but we have to setup a color
+ // transformation matrix, in order to incorporate the global
+ // alpha value mfAlpha into the bitmap rendering.
+ Gdiplus::ColorMatrix aColorMatrix;
+
+ aColorMatrix.m[0][0] = static_cast<Gdiplus::REAL>(nRedModulation);
+ aColorMatrix.m[0][1] = 0.0;
+ aColorMatrix.m[0][2] = 0.0;
+ aColorMatrix.m[0][3] = 0.0;
+ aColorMatrix.m[0][4] = 0.0;
+
+ aColorMatrix.m[1][0] = 0.0;
+ aColorMatrix.m[1][1] = static_cast<Gdiplus::REAL>(nGreenModulation);
+ aColorMatrix.m[1][2] = 0.0;
+ aColorMatrix.m[1][3] = 0.0;
+ aColorMatrix.m[1][4] = 0.0;
+
+ aColorMatrix.m[2][0] = 0.0;
+ aColorMatrix.m[2][1] = 0.0;
+ aColorMatrix.m[2][2] = static_cast<Gdiplus::REAL>(nBlueModulation);
+ aColorMatrix.m[2][3] = 0.0;
+ aColorMatrix.m[2][4] = 0.0;
+
+ aColorMatrix.m[3][0] = 0.0;
+ aColorMatrix.m[3][1] = 0.0;
+ aColorMatrix.m[3][2] = 0.0;
+ aColorMatrix.m[3][3] = static_cast<Gdiplus::REAL>(nAlphaModulation);
+ aColorMatrix.m[3][4] = 0.0;
+
+ aColorMatrix.m[4][0] = 0.0;
+ aColorMatrix.m[4][1] = 0.0;
+ aColorMatrix.m[4][2] = 0.0;
+ aColorMatrix.m[4][3] = 0.0;
+ aColorMatrix.m[4][4] = 1.0;
+
+ o_rAttr.SetColorMatrix( &aColorMatrix,
+ Gdiplus::ColorMatrixFlagsDefault,
+ Gdiplus::ColorAdjustTypeDefault );
+ }
+
+ } // namespace tools
+} // namespace dxcanvas
diff --git a/canvas/source/directx/dx_impltools.hxx b/canvas/source/directx/dx_impltools.hxx
new file mode 100755
index 000000000000..072d1063235d
--- /dev/null
+++ b/canvas/source/directx/dx_impltools.hxx
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_impltools.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_IMPLTOOLS_HXX
+#define _DXCANVAS_IMPLTOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/util/TriState.hpp>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include "dx_canvasfont.hxx"
+
+namespace basegfx
+{
+ class B2DPoint;
+ class B2DRange;
+ class B2DHomMatrix;
+ class B2IPoint;
+ class B2IRange;
+ class B2DPolyPolygon;
+};
+
+namespace com { namespace sun { namespace star { namespace geometry
+{
+ struct IntegerRectangle2D;
+ struct RealPoint2D;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XCanvas;
+ class XGraphicDevice;
+ class XBitmap;
+ class XPolyPolygon2D;
+ class XCanvasFont;
+} } } }
+
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ struct RawRGBABitmap;
+
+ ::basegfx::B2DPolyPolygon
+ polyPolygonFromXPolyPolygon2D( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& );
+
+ Gdiplus::Graphics* createGraphicsFromHDC(HDC);
+ Gdiplus::Graphics* createGraphicsFromBitmap(const BitmapSharedPtr&);
+
+ void setupGraphics( Gdiplus::Graphics& rGraphics );
+
+ void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix,
+ const ::basegfx::B2DHomMatrix& rMatrix );
+ void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& rGdiplusMatrix,
+ const ::com::sun::star::geometry::AffineMatrix2D& rMatrix );
+
+ Gdiplus::PointF gdiPlusPointFFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& );
+ Gdiplus::RectF gdiPlusRectFFromRectangle2D( const ::com::sun::star::geometry::RealRectangle2D& );
+ Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const ::com::sun::star::geometry::IntegerRectangle2D& );
+ RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& );
+
+ ::com::sun::star::geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& );
+ ::com::sun::star::geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& );
+
+ ::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& );
+ ::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& );
+
+ ::com::sun::star::uno::Sequence< double > argbToDoubleSequence( const Gdiplus::ARGB& rColor );
+ ::com::sun::star::uno::Sequence< sal_Int8 > argbToIntSequence( const Gdiplus::ARGB& rColor );
+ Gdiplus::ARGB sequenceToArgb( const ::com::sun::star::uno::Sequence< sal_Int8 >& rColor );
+ Gdiplus::ARGB sequenceToArgb( const ::com::sun::star::uno::Sequence< double >& rColor );
+
+ GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& );
+
+ GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly );
+ GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly );
+
+ GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XPolyPolygon2D >& );
+ bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
+ const BitmapSharedPtr& rBitmap );
+ bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const BITMAPINFO& rBI,
+ const void* pBits );
+
+ bool drawRGBABits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const RawRGBABitmap& rRawRGBAData );
+
+ BitmapSharedPtr bitmapFromXBitmap( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap );
+
+ CanvasFont::ImplRef canvasFontFromXFont( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& xFont );
+
+ void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
+ double nRedModulation,
+ double nGreenModulation,
+ double nBlueModulation,
+ double nAlphaModulation );
+ }
+}
+
+#endif /* _DXCANVAS_IMPLTOOLS_HXX */
diff --git a/canvas/source/directx/dx_linepolypolygon.cxx b/canvas/source/directx/dx_linepolypolygon.cxx
new file mode 100755
index 000000000000..e63adc3dc613
--- /dev/null
+++ b/canvas/source/directx/dx_linepolypolygon.cxx
@@ -0,0 +1,68 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_linepolypolygon.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <basegfx/tools/canvastools.hxx>
+#include "dx_linepolypolygon.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ LinePolyPolygon::LinePolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ) :
+ ::basegfx::unotools::UnoPolyPolygon( rPolyPoly ),
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ mpPath()
+ {
+ }
+
+ GraphicsPathSharedPtr LinePolyPolygon::getGraphicsPath() const
+ {
+ // generate GraphicsPath only on demand (gets deleted as soon
+ // as any of the modifying methods above touches the
+ // B2DPolyPolygon).
+ if( !mpPath )
+ {
+ mpPath = tools::graphicsPathFromB2DPolyPolygon( getPolyPolygonUnsafe() );
+ mpPath->SetFillMode( const_cast<LinePolyPolygon*>(this)->getFillRule() == rendering::FillRule_EVEN_ODD ?
+ Gdiplus::FillModeAlternate : Gdiplus::FillModeWinding );
+ }
+
+ return mpPath;
+ }
+
+ void LinePolyPolygon::modifying() const
+ {
+ mpPath.reset();
+ }
+}
diff --git a/canvas/source/directx/dx_linepolypolygon.hxx b/canvas/source/directx/dx_linepolypolygon.hxx
new file mode 100755
index 000000000000..431cd1b87b4f
--- /dev/null
+++ b/canvas/source/directx/dx_linepolypolygon.hxx
@@ -0,0 +1,59 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_linepolypolygon.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_LINEPOLYPOLYGON_HXX_
+#define _DXCANVAS_LINEPOLYPOLYGON_HXX_
+
+#include <canvas/canvastools.hxx>
+#include <basegfx/tools/unopolypolygon.hxx>
+
+#include "dx_gdiplususer.hxx"
+#include "dx_impltools.hxx"
+
+
+namespace dxcanvas
+{
+ class LinePolyPolygon : public ::basegfx::unotools::UnoPolyPolygon
+ {
+ public:
+ explicit LinePolyPolygon( const ::basegfx::B2DPolyPolygon& );
+
+ GraphicsPathSharedPtr getGraphicsPath() const;
+
+ private:
+ // overridden, to clear mpPath
+ virtual void modifying() const;
+
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+ mutable GraphicsPathSharedPtr mpPath;
+ };
+}
+
+#endif /* _DXCANVAS_LINEPOLYPOLYGON_HXX_ */
diff --git a/canvas/source/directx/dx_rendermodule.hxx b/canvas/source/directx/dx_rendermodule.hxx
new file mode 100755
index 000000000000..11f8cf6e4261
--- /dev/null
+++ b/canvas/source/directx/dx_rendermodule.hxx
@@ -0,0 +1,93 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_rendermodule.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_RENDERMODULE_HXX
+#define _DXCANVAS_RENDERMODULE_HXX
+
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/range/b2irectangle.hxx>
+#include <canvas/rendering/irendermodule.hxx>
+#include <boost/shared_ptr.hpp>
+#include "dx_winstuff.hxx"
+
+class Window;
+namespace basegfx
+{
+ class B2IRange;
+ class B2DVector;
+}
+
+namespace dxcanvas
+{
+ /// Specialization of IRenderModule for DirectX
+ struct IDXRenderModule : public canvas::IRenderModule
+ {
+ /** Flip front- and backbuffer, update only given area
+
+ Note: Both update area and offset are ignored for
+ fullscreen canvas, that uses page flipping (cannot, by
+ definition, do anything else there except displaying the
+ full backbuffer instead of the front buffer)
+
+ @param rUpdateArea
+ Area to copy from backbuffer to front
+
+ @param rCurrWindowArea
+ Current area of VCL window (coordinates relative to VCL
+ HWND)
+ */
+ virtual bool flip( const ::basegfx::B2IRectangle& rUpdateArea,
+ const ::basegfx::B2IRectangle& rCurrWindowArea ) = 0;
+
+ /** Resize backbuffer area for this render module
+ */
+ virtual void resize( const ::basegfx::B2IRange& rect ) = 0;
+
+ /// Write a snapshot of the screen to disk
+ virtual void screenShot() = 0;
+
+ virtual COMReference<surface_type>
+ createSystemMemorySurface(
+ const ::basegfx::B2IVector& rSize ) = 0;
+
+ virtual void disposing() = 0;
+ virtual HWND getHWND() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< IDXRenderModule > IDXRenderModuleSharedPtr;
+
+
+ /** Factory method, to create an IRenderModule instance for the
+ given VCL window instance
+ */
+ IDXRenderModuleSharedPtr createRenderModule( const ::Window& rParent );
+}
+
+#endif
diff --git a/canvas/source/directx/dx_sprite.hxx b/canvas/source/directx/dx_sprite.hxx
new file mode 100755
index 000000000000..6ff6af1bc701
--- /dev/null
+++ b/canvas/source/directx/dx_sprite.hxx
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_sprite.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_DXCANVAS_SPRITE_HXX
+#define INCLUDED_DXCANVAS_SPRITE_HXX
+
+#include <canvas/base/sprite.hxx>
+
+namespace dxcanvas
+{
+ /** Specialization of ::canvas::Sprite interface, to also provide
+ redraw methods.
+ */
+ class Sprite : public ::canvas::Sprite
+ {
+ public:
+
+ /** Redraw sprite using the hardware
+
+ This method will silently fail, if the previous
+ restoreTextures() call failed.
+ */
+ virtual void redraw() const = 0;
+ };
+}
+
+#endif /* INCLUDED_DXCANVAS_SPRITE_HXX */
diff --git a/canvas/source/directx/dx_spritecanvas.cxx b/canvas/source/directx/dx_spritecanvas.cxx
new file mode 100755
index 000000000000..8ffeae3715ab
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvas.cxx
@@ -0,0 +1,214 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritecanvas.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <canvas/canvastools.hxx>
+
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <comphelper/servicedecl.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "dx_winstuff.hxx"
+#include "dx_spritecanvas.hxx"
+
+#if DIRECTX_VERSION < 0x0900
+# define CANVAS_TECH "DX5"
+#else
+# define CANVAS_TECH "DX9"
+#endif
+
+#define SPRITECANVAS_SERVICE_NAME "com.sun.star.rendering.SpriteCanvas." CANVAS_TECH
+#define SPRITECANVAS_IMPLEMENTATION_NAME "com.sun.star.comp.rendering.SpriteCanvas." CANVAS_TECH
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteCanvas::SpriteCanvas( const uno::Sequence< uno::Any >& aArguments,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ maArguments(aArguments),
+ mxComponentContext( rxContext )
+ {
+ }
+
+ void SpriteCanvas::initialize()
+ {
+ // #i64742# Only call initialize when not in probe mode
+ if( maArguments.getLength() == 0 )
+ return;
+
+ VERBOSE_TRACE( "SpriteCanvas::initialize called" );
+
+ /* aArguments:
+ 0: ptr to creating instance (Window or VirtualDevice)
+ 1: SystemEnvData as a streamed Any (or empty for VirtualDevice)
+ 2: current bounds of creating instance
+ 3: bool, denoting always on top state for Window (always false for VirtualDevice)
+ 4: XWindow for creating Window (or empty for VirtualDevice)
+ 5: SystemGraphicsData as a streamed Any
+ */
+ ENSURE_ARG_OR_THROW( maArguments.getLength() >= 5 &&
+ maArguments[4].getValueTypeClass() == uno::TypeClass_INTERFACE,
+ "VCLSpriteCanvas::initialize: wrong number of arguments, or wrong types" );
+
+ uno::Reference< awt::XWindow > xParentWindow;
+ maArguments[4] >>= xParentWindow;
+ Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
+ if( !pParentWindow )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Parent window not VCL window, or canvas out-of-process!")),
+ NULL);
+
+ awt::Rectangle aRect;
+ maArguments[2] >>= aRect;
+
+ sal_Bool bIsFullscreen( sal_False );
+ maArguments[3] >>= bIsFullscreen;
+
+ // setup helper
+ maDeviceHelper.init( *pParentWindow,
+ *this,
+ aRect,
+ bIsFullscreen );
+ maCanvasHelper.init( *this,
+ maRedrawManager,
+ maDeviceHelper.getRenderModule(),
+ maDeviceHelper.getSurfaceProxy(),
+ maDeviceHelper.getBackBuffer(),
+ ::basegfx::B2ISize() );
+ maArguments.realloc(0);
+ }
+
+ void SAL_CALL SpriteCanvas::disposing()
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxComponentContext.clear();
+
+ // forward to parent
+ SpriteCanvasBaseT::disposing();
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::showBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // avoid repaints on hidden window (hidden: not mapped to
+ // screen). Return failure, since the screen really has _not_
+ // been updated (caller should try again later)
+ return !mbIsVisible ? false : SpriteCanvasBaseT::showBuffer( bUpdateAll );
+ }
+
+ ::sal_Bool SAL_CALL SpriteCanvas::switchBuffer( ::sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // avoid repaints on hidden window (hidden: not mapped to
+ // screen). Return failure, since the screen really has _not_
+ // been updated (caller should try again later)
+ return !mbIsVisible ? false : SpriteCanvasBaseT::switchBuffer( bUpdateAll );
+ }
+
+ sal_Bool SAL_CALL SpriteCanvas::updateScreen( sal_Bool bUpdateAll ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // avoid repaints on hidden window (hidden: not mapped to
+ // screen). Return failure, since the screen really has _not_
+ // been updated (caller should try again later)
+ return !mbIsVisible ? false : maCanvasHelper.updateScreen(
+ ::basegfx::unotools::b2IRectangleFromAwtRectangle(maBounds),
+ bUpdateAll,
+ mbSurfaceDirty );
+ }
+
+ ::rtl::OUString SAL_CALL SpriteCanvas::getServiceName( ) throw (uno::RuntimeException)
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SPRITECANVAS_SERVICE_NAME ) );
+ }
+
+ const IDXRenderModuleSharedPtr& SpriteCanvas::getRenderModule() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maDeviceHelper.getRenderModule();
+ }
+
+ const DXSurfaceBitmapSharedPtr& SpriteCanvas::getBackBuffer() const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maDeviceHelper.getBackBuffer();
+ }
+
+ IBitmapSharedPtr SpriteCanvas::getBitmap() const
+ {
+ return maDeviceHelper.getBackBuffer();
+ }
+
+ static uno::Reference<uno::XInterface> initCanvas( SpriteCanvas* pCanvas )
+ {
+ uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pCanvas));
+ pCanvas->initialize();
+ return xRet;
+ }
+
+ namespace sdecl = comphelper::service_decl;
+ sdecl::class_<SpriteCanvas, sdecl::with_args<true> > serviceImpl(&initCanvas);
+ const sdecl::ServiceDecl dxSpriteCanvasDecl(
+ serviceImpl,
+ SPRITECANVAS_IMPLEMENTATION_NAME,
+ SPRITECANVAS_SERVICE_NAME );
+}
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(dxcanvas::dxSpriteCanvasDecl);
diff --git a/canvas/source/directx/dx_spritecanvas.hxx b/canvas/source/directx/dx_spritecanvas.hxx
new file mode 100755
index 000000000000..555316d14b9f
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvas.hxx
@@ -0,0 +1,159 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritecanvas.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_SPRITECANVAS_HXX_
+#define _DXCANVAS_SPRITECANVAS_HXX_
+
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
+
+#include <cppuhelper/compbase9.hxx>
+#include <comphelper/uno3.hxx>
+
+#include <canvas/base/spritecanvasbase.hxx>
+#include <canvas/base/basemutexhelper.hxx>
+#include <canvas/base/bufferedgraphicdevicebase.hxx>
+
+#include "dx_bitmapprovider.hxx"
+#include "dx_spritecanvashelper.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_impltools.hxx"
+#include "dx_spritedevicehelper.hxx"
+
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
+ ::com::sun::star::rendering::XIntegerBitmap,
+ ::com::sun::star::rendering::XGraphicDevice,
+ ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::rendering::XBufferController,
+ ::com::sun::star::awt::XWindowListener,
+ ::com::sun::star::util::XUpdatable,
+ ::com::sun::star::beans::XPropertySet,
+ ::com::sun::star::lang::XServiceName > WindowGraphicDeviceBase_Base;
+ typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::BaseMutexHelper< WindowGraphicDeviceBase_Base >,
+ SpriteDeviceHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > SpriteCanvasBase_Base;
+ /** Mixin SpriteSurface
+
+ Have to mixin the SpriteSurface before deriving from
+ ::canvas::SpriteCanvasBase, as this template should already
+ implement some of those interface methods.
+
+ The reason why this appears kinda convoluted is the fact that
+ we cannot specify non-IDL types as WeakComponentImplHelperN
+ template args, and furthermore, don't want to derive
+ ::canvas::SpriteCanvasBase directly from
+ ::canvas::SpriteSurface (because derivees of
+ ::canvas::SpriteCanvasBase have to explicitely forward the
+ XInterface methods (e.g. via DECLARE_UNO3_AGG_DEFAULTS)
+ anyway). Basically, ::canvas::CanvasCustomSpriteBase should
+ remain a base class that provides implementation, not to
+ enforce any specific interface on its derivees.
+ */
+ class SpriteCanvasBaseSpriteSurface_Base : public SpriteCanvasBase_Base,
+ public ::canvas::SpriteSurface
+ {
+ };
+
+ typedef ::canvas::SpriteCanvasBase< SpriteCanvasBaseSpriteSurface_Base,
+ SpriteCanvasHelper,
+ ::osl::MutexGuard,
+ ::cppu::OWeakObject > SpriteCanvasBaseT;
+
+ /** Product of this component's factory.
+
+ The SpriteCanvas object combines the actual Window canvas with
+ the XGraphicDevice interface. This is because there's a
+ one-to-one relation between them, anyway, since each window
+ can have exactly one canvas and one associated
+ XGraphicDevice. And to avoid messing around with circular
+ references, this is implemented as one single object.
+ */
+ class SpriteCanvas : public SpriteCanvasBaseT, public BitmapProvider
+ {
+ public:
+ SpriteCanvas( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Any >& aArguments,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ void initialize();
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // Forwarding the XComponent implementation to the
+ // cppu::ImplHelper templated base
+ // Classname Base doing refcounting Base implementing the XComponent interface
+ // | | |
+ // V V V
+ DECLARE_UNO3_XCOMPONENT_AGG_DEFAULTS( SpriteCanvas, WindowGraphicDeviceBase_Base, ::cppu::WeakComponentImplHelperBase );
+
+ // XBufferController (partial)
+ virtual ::sal_Bool SAL_CALL showBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL switchBuffer( ::sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XSpriteCanvas (partial)
+ virtual sal_Bool SAL_CALL updateScreen( sal_Bool bUpdateAll ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName( ) throw (::com::sun::star::uno::RuntimeException);
+
+ /// Retrieve rendermodule object for this Canvas
+ const IDXRenderModuleSharedPtr& getRenderModule() const;
+
+ /// Get backbuffer for this canvas
+ const DXSurfaceBitmapSharedPtr& getBackBuffer() const;
+
+ // BitmapProvider
+ virtual IBitmapSharedPtr getBitmap() const;
+
+ private:
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > maArguments;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxComponentContext;
+ };
+
+ typedef ::rtl::Reference< SpriteCanvas > SpriteCanvasRef;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_spritecanvashelper.cxx b/canvas/source/directx/dx_spritecanvashelper.cxx
new file mode 100755
index 000000000000..3217089a3543
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvashelper.cxx
@@ -0,0 +1,385 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritecanvashelper.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/scopeguard.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <boost/cast.hpp>
+
+#include "dx_spritecanvashelper.hxx"
+#include "dx_canvascustomsprite.hxx"
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ void repaintBackground( const ::basegfx::B2DRange& rUpdateArea,
+ const ::basegfx::B2IRange& rOutputArea,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer )
+ {
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(rOutputArea.getWidth()),
+ static_cast<sal_Int32>(rOutputArea.getHeight()) );
+ aActualArea.intersect( fround( rUpdateArea ) );
+
+ // repaint the given area of the screen with background content
+ rBackBuffer->draw(aActualArea);
+ }
+
+ void spriteRedraw( const ::canvas::Sprite::Reference& rSprite )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw();
+ }
+
+ void spriteRedrawStub( const ::canvas::Sprite::Reference& rSprite )
+ {
+ if( rSprite.is() )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rSprite.get() )->redraw();
+ }
+ }
+
+ void spriteRedrawStub2( const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
+ {
+ if( rComponent.second.getSprite().is() )
+ {
+ // downcast to derived dxcanvas::Sprite interface, which
+ // provides the actual redraw methods.
+ ::boost::polymorphic_downcast< Sprite* >(
+ rComponent.second.getSprite().get() )->redraw();
+ }
+ }
+ }
+
+ SpriteCanvasHelper::SpriteCanvasHelper() :
+ mpSpriteSurface( NULL ),
+ mpRedrawManager( NULL ),
+ mpRenderModule(),
+ mpSurfaceProxy(),
+ mpBackBuffer(),
+ maUpdateRect(),
+ maScrapRect(),
+ mbShowSpriteBounds( false )
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ // inverse default for verbose debug mode
+ mbShowSpriteBounds = true;
+#endif
+ }
+
+ void SpriteCanvasHelper::init( SpriteCanvas& rParent,
+ ::canvas::SpriteRedrawManager& rManager,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer,
+ const ::basegfx::B2ISize& rOutputOffset )
+ {
+ // init base
+ setDevice( rParent );
+ setTarget( rBackBuffer, rOutputOffset );
+
+ mpSpriteSurface = &rParent;
+ mpRedrawManager = &rManager;
+ mpRenderModule = rRenderModule;
+ mpSurfaceProxy = rSurfaceProxy;
+ mpBackBuffer = rBackBuffer;
+ }
+
+ void SpriteCanvasHelper::disposing()
+ {
+ if(mpRenderModule)
+ mpRenderModule->disposing();
+
+ mpBackBuffer.reset();
+ mpRenderModule.reset();
+ mpRedrawManager = NULL;
+ mpSpriteSurface = NULL;
+
+ // forward to base
+ CanvasHelper::disposing();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation(
+ const uno::Reference< rendering::XAnimation >& /*animation*/ )
+ {
+ return uno::Reference< rendering::XAnimatedSprite >();
+ }
+
+ uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps(
+ const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/,
+ sal_Int8 /*interpolationMode*/ )
+ {
+ return uno::Reference< rendering::XAnimatedSprite >();
+ }
+
+ uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
+ {
+ if( !mpRedrawManager )
+ return uno::Reference< rendering::XCustomSprite >(); // we're disposed
+
+ return uno::Reference< rendering::XCustomSprite >(
+ new CanvasCustomSprite( spriteSize,
+ mpSpriteSurface,
+ mpRenderModule,
+ mpSurfaceProxy,
+ mbShowSpriteBounds ) );
+ }
+
+ uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
+ {
+ return uno::Reference< rendering::XSprite >();
+ }
+
+ sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
+ sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty )
+ {
+ if( !mpRedrawManager ||
+ !mpRenderModule ||
+ !mpBackBuffer )
+ {
+ return sal_False; // disposed, or otherwise dysfunctional
+ }
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ mpBackBuffer->imageDebugger();
+# endif
+#endif
+
+ // store current output area (need to tunnel that to the
+ // background, scroll, opaque and general sprite repaint
+ // routines)
+ maScrapRect = rCurrArea;
+
+ // clear area that needs to be blitted to screen beforehand
+ maUpdateRect.reset();
+
+ // TODO(P1): Might be worthwile to track areas of background
+ // changes, too.
+
+ // TODO(P2): Might be worthwhile to use page-flipping only if
+ // a certain percentage of screen area has changed - and
+ // compose directly to the front buffer otherwise.
+ if( !bUpdateAll && !io_bSurfaceDirty )
+ {
+ // background has not changed, so we're free to optimize
+ // repaint to areas where a sprite has changed
+
+ // process each independent area of overlapping sprites
+ // separately.
+ mpRedrawManager->forEachSpriteArea( *this );
+
+ // flip primary surface to screen
+ // ==============================
+
+ // perform buffer flipping
+ mpRenderModule->flip( maUpdateRect,
+ rCurrArea );
+ }
+ else
+ {
+ // limit update to parent window area (ignored for fullscreen)
+ // TODO(E1): Use numeric_cast to catch overflow here
+ const ::basegfx::B2IRectangle aUpdateArea( 0,0,
+ static_cast<sal_Int32>(rCurrArea.getWidth()),
+ static_cast<sal_Int32>(rCurrArea.getHeight()) );
+
+ // background has changed, or called requested full
+ // update, or we're performing double buffering via page
+ // flipping, so we currently have no choice but repaint
+ // everything
+
+ // repaint the whole screen with background content
+ mpBackBuffer->draw(aUpdateArea);
+
+ // redraw sprites
+ mpRedrawManager->forEachSprite(::std::ptr_fun( &spriteRedraw ) );
+
+ // flip primary surface to screen
+ // ==============================
+
+ // perform buffer flipping
+ mpRenderModule->flip( aUpdateArea,
+ rCurrArea );
+ }
+
+ // change record vector must be cleared, for the next turn of
+ // rendering and sprite changing
+ mpRedrawManager->clearChangeRecords();
+
+ io_bSurfaceDirty = false;
+
+ return sal_True;
+ }
+
+ void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );
+
+ repaintBackground( rUpdateRect,
+ maScrapRect,
+ mpBackBuffer );
+ }
+
+ void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& /*rMoveStart*/,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );
+
+ // round rectangles to integer pixel. Note: have to be
+ // extremely careful here, to avoid off-by-one errors for
+ // the destination area: otherwise, the next scroll update
+ // would copy pixel that are not supposed to be part of
+ // the sprite.
+ const ::basegfx::B2IRange& rDestRect(
+ ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );
+
+ // not much sense in really implementing scrollUpdate here,
+ // since outputting a sprite only partially would result in
+ // expensive clipping. Furthermore, we cannot currently render
+ // 3D directly to the front buffer, thus, would have to blit
+ // the full sprite area, anyway. But at least optimized in the
+ // sense that unnecessary background paints behind the sprites
+ // are avoided.
+ ::std::for_each( rUpdateArea.maComponentList.begin(),
+ rUpdateArea.maComponentList.end(),
+ ::std::ptr_fun( &spriteRedrawStub2 ) );
+
+ // repaint uncovered areas from backbuffer - take the
+ // _rounded_ rectangles from above, to have the update
+ // consistent with the scroll above.
+ ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
+ ::basegfx::computeSetDifference( aUncoveredAreas,
+ rUpdateArea.maTotalBounds,
+ ::basegfx::B2DRange( rDestRect ) );
+ ::std::for_each( aUncoveredAreas.begin(),
+ aUncoveredAreas.end(),
+ ::boost::bind( &repaintBackground,
+ _1,
+ ::boost::cref(maScrapRect),
+ ::boost::cref(mpBackBuffer) ) );
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+
+ void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );
+
+ // TODO(P2): optimize this by truly rendering to the front
+ // buffer. Currently, we've the 3D device only for the back
+ // buffer.
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::std::ptr_fun( &spriteRedrawStub ) );
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rTotalArea ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+
+ void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
+ {
+ ENSURE_OR_THROW( mpRenderModule &&
+ mpBackBuffer,
+ "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );
+
+ // paint background
+ // ================
+
+ // TODO(E1): Use numeric_cast to catch overflow here
+ ::basegfx::B2IRange aActualArea( 0, 0,
+ static_cast<sal_Int32>(maScrapRect.getWidth()),
+ static_cast<sal_Int32>(maScrapRect.getHeight()) );
+ aActualArea.intersect( fround( rTotalArea ) );
+
+ // repaint the given area of the screen with background content
+ mpBackBuffer->draw(aActualArea);
+
+ // paint sprite
+ // ============
+
+ ::std::for_each( rSortedUpdateSprites.begin(),
+ rSortedUpdateSprites.end(),
+ ::std::ptr_fun( &spriteRedrawStub ) );
+
+ // add given update area to the 'blit to foreground' rect
+ maUpdateRect.expand( aActualArea );
+ }
+}
diff --git a/canvas/source/directx/dx_spritecanvashelper.hxx b/canvas/source/directx/dx_spritecanvashelper.hxx
new file mode 100755
index 000000000000..d1825670cafc
--- /dev/null
+++ b/canvas/source/directx/dx_spritecanvashelper.hxx
@@ -0,0 +1,164 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritecanvashelper.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_SPRITECANVASHELPER_HXX_
+#define _DXCANVAS_SPRITECANVASHELPER_HXX_
+
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <canvas/spriteredrawmanager.hxx>
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include "dx_bitmapcanvashelper.hxx"
+#include "dx_impltools.hxx"
+#include "dx_rendermodule.hxx"
+#include "dx_surfacebitmap.hxx"
+
+#include <basegfx/range/b2irectangle.hxx>
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+
+ class SpriteCanvasHelper : public BitmapCanvasHelper
+ {
+ public:
+ SpriteCanvasHelper();
+
+ void init( SpriteCanvas& rParent,
+ ::canvas::SpriteRedrawManager& rManager,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const ::canvas::ISurfaceProxyManagerSharedPtr& rSurfaceProxy,
+ const DXSurfaceBitmapSharedPtr& rBackBuffer,
+ const ::basegfx::B2ISize& rOutputOffset );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // XSpriteCanvas
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XAnimatedSprite > createSpriteFromAnimation(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimation >& animation );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XAnimatedSprite > createSpriteFromBitmaps(
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > >& animationBitmaps,
+ sal_Int8 interpolationMode );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCustomSprite > createCustomSprite(
+ const ::com::sun::star::geometry::RealSize2D& spriteSize );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XSprite > createClonedSprite(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite >& original );
+
+ /** Actually perform the screen update
+
+ @param rCurrArea
+ Current window area in absolute screen coordinates
+
+ @param bUpdateAll
+ sal_True, if everything must be updated, not only changed
+ sprites
+
+ @param io_bSurfaceDirty
+ In/out parameter, whether backbuffer surface is dirty (if
+ yes, we're performing a full update, anyway)
+ */
+ sal_Bool updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
+ sal_Bool bUpdateAll,
+ bool& io_bSurfaceDirty );
+
+
+ // SpriteRedrawManager functor calls
+ // -------------------------------------------------
+
+ /** Gets called for simple background repaints
+ */
+ void backgroundPaint( const ::basegfx::B2DRange& rUpdateRect );
+
+ /** Gets called when area can be handled by scrolling.
+
+ Called method must copy screen content from rMoveStart to
+ rMoveEnd, and restore the background in the uncovered
+ areas.
+
+ @param rMoveStart
+ Source rect of the scroll
+
+ @param rMoveEnd
+ Dest rect of the scroll
+
+ @param rUpdateArea
+ All info necessary, should rMoveStart be partially or
+ fully outside the outdev
+ */
+ void scrollUpdate( const ::basegfx::B2DRange& rMoveStart,
+ const ::basegfx::B2DRange& rMoveEnd,
+ const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea );
+
+ void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
+
+ void genericUpdate( const ::basegfx::B2DRange& rTotalArea,
+ const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites );
+
+ private:
+ /// For generating sprites
+ SpriteCanvas* mpSpriteSurface;
+
+ /// Set from the SpriteCanvas: instance coordinating sprite redraw
+ ::canvas::SpriteRedrawManager* mpRedrawManager;
+
+ /// DX device, handling all low-level rendering
+ IDXRenderModuleSharedPtr mpRenderModule;
+
+ ::canvas::ISurfaceProxyManagerSharedPtr mpSurfaceProxy;
+
+ /// Backbuffer, contains the static canvas render output
+ DXSurfaceBitmapSharedPtr mpBackBuffer;
+
+ /// Completely temporary rect storage (used by sprite repaint)
+ mutable ::basegfx::B2IRange maUpdateRect;
+
+ /// Completely temporary rect storage (used by sprite repaint)
+ mutable ::basegfx::B2IRange maScrapRect;
+
+ /// When true, show small bound rects around each sprite
+ bool mbShowSpriteBounds;
+ };
+}
+
+#endif /* _DXCANVAS_SPRITECANVASHELPER_HXX_ */
diff --git a/canvas/source/directx/dx_spritedevicehelper.cxx b/canvas/source/directx/dx_spritedevicehelper.cxx
new file mode 100644
index 000000000000..ba997f18f8b6
--- /dev/null
+++ b/canvas/source/directx/dx_spritedevicehelper.cxx
@@ -0,0 +1,262 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritedevicehelper.cxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <vcl/window.hxx>
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include "dx_linepolypolygon.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_canvasbitmap.hxx"
+#include "dx_spritedevicehelper.hxx"
+
+
+#undef WB_LEFT
+#undef WB_RIGHT
+#include "dx_winstuff.hxx"
+
+
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteDeviceHelper::SpriteDeviceHelper() :
+ DeviceHelper(),
+ mpSpriteCanvas( NULL ),
+ mpSurfaceProxyManager(),
+ mpRenderModule(),
+ mpBackBuffer()
+ {
+ }
+
+ void SpriteDeviceHelper::init( Window& rWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const awt::Rectangle& rRect,
+ bool /*bFullscreen*/ )
+ {
+ // #i60490# ensure backbuffer has sensible minimal size
+ const sal_Int32 w( ::std::max(sal_Int32(1),sal_Int32(rRect.Width)));
+ const sal_Int32 h( ::std::max(sal_Int32(1),sal_Int32(rRect.Height)));
+
+ rSpriteCanvas.setWindow(
+ uno::Reference<awt::XWindow2>(
+ VCLUnoHelper::GetInterface(&rWindow),
+ uno::UNO_QUERY_THROW) );
+
+ const SystemEnvData *pData = rWindow.GetSystemData();
+ const HWND hWnd = reinterpret_cast<HWND>(pData->hWnd);
+ if( !IsWindow( hWnd ) )
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Passed window has invalid system window, or canvas out-of-process!")),
+ NULL);
+
+ mpSpriteCanvas = &rSpriteCanvas;
+
+ try
+ {
+ // setup directx rendermodule
+ mpRenderModule = createRenderModule( rWindow );
+ }
+ catch (...) {
+
+ throw lang::NoSupportException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "Could not create DirectX device!") ),
+ static_cast< ::cppu::OWeakObject* >(&rSpriteCanvas) );
+ }
+
+ // create the surfaceproxy manager
+ mpSurfaceProxyManager = ::canvas::createSurfaceProxyManager( mpRenderModule );
+
+ // #i60490# ensure backbuffer has sensible minimal size
+ mpBackBuffer.reset(new DXSurfaceBitmap(
+ ::basegfx::B2ISize(w,h),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ false));
+
+ // Assumes: SystemChildWindow() has CS_OWNDC
+ DeviceHelper::init(GetDC(mpRenderModule->getHWND()),
+ rSpriteCanvas);
+ }
+
+ void SpriteDeviceHelper::disposing()
+ {
+ // release all references
+ mpBackBuffer.reset();
+ mpSurfaceProxyManager.reset();
+ mpRenderModule.reset();
+ mpSpriteCanvas = NULL;
+
+ DeviceHelper::disposing();
+ }
+
+ uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !getDevice() )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXSurfaceBitmapSharedPtr pBitmap(
+ new DXSurfaceBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ false));
+
+ // create a 24bit RGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& size )
+ {
+ if( !getDevice() )
+ return uno::Reference< rendering::XBitmap >(); // we're disposed
+
+ DXSurfaceBitmapSharedPtr pBitmap(
+ new DXSurfaceBitmap(
+ ::basegfx::unotools::b2ISizeFromIntegerSize2D(size),
+ mpSurfaceProxyManager,
+ mpRenderModule,
+ true));
+
+ // create a 32bit ARGB system memory surface
+ return uno::Reference< rendering::XBitmap >(new CanvasBitmap(pBitmap,getDevice()));
+ }
+
+ uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
+ const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
+ const geometry::IntegerSize2D& /*size*/ )
+ {
+ return uno::Reference< rendering::XVolatileBitmap >();
+ }
+
+ sal_Bool SpriteDeviceHelper::hasFullScreenMode()
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ sal_Bool SpriteDeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
+ {
+ // TODO(F3): offer fullscreen mode the XCanvas way
+ return false;
+ }
+
+ ::sal_Int32 SpriteDeviceHelper::createBuffers( ::sal_Int32 /*nBuffers*/ )
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ return 1;
+ }
+
+ void SpriteDeviceHelper::destroyBuffers()
+ {
+ // TODO(F3): implement XBufferStrategy interface. For now, we
+ // _always_ will have exactly one backbuffer
+ }
+
+ ::sal_Bool SpriteDeviceHelper::showBuffer( bool, ::sal_Bool )
+ {
+ OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
+ return sal_False;
+ }
+
+ ::sal_Bool SpriteDeviceHelper::switchBuffer( bool, ::sal_Bool )
+ {
+ OSL_ENSURE(false,"Not supposed to be called, handled by SpriteCanvas");
+ return sal_False;
+ }
+
+ uno::Any SpriteDeviceHelper::isAccelerated() const
+ {
+ return ::com::sun::star::uno::makeAny(true);
+ }
+
+ void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
+ {
+ // #i60490# ensure backbuffer has sensible minimal size
+ const sal_Int32 x(rBounds.X);
+ const sal_Int32 y(rBounds.Y);
+ const sal_Int32 w(::std::max(sal_Int32(1),sal_Int32(rBounds.Width)));
+ const sal_Int32 h(::std::max(sal_Int32(1),sal_Int32(rBounds.Height)));
+
+ if( mpRenderModule )
+ mpRenderModule->resize(::basegfx::B2IRange(x,y,x+w,y+h));
+
+ resizeBackBuffer(::basegfx::B2ISize(w,h));
+ }
+
+ void SpriteDeviceHelper::resizeBackBuffer( const ::basegfx::B2ISize& rNewSize )
+ {
+ // disposed?
+ if(!(mpBackBuffer))
+ return;
+
+ mpBackBuffer->resize(rNewSize);
+ mpBackBuffer->clear();
+ }
+
+ HWND SpriteDeviceHelper::getHwnd() const
+ {
+ if( mpRenderModule )
+ return mpRenderModule->getHWND();
+ else
+ return 0;
+ }
+
+ void SpriteDeviceHelper::dumpScreenContent() const
+ {
+ if( mpRenderModule )
+ mpRenderModule->screenShot();
+ }
+}
diff --git a/canvas/source/directx/dx_spritedevicehelper.hxx b/canvas/source/directx/dx_spritedevicehelper.hxx
new file mode 100644
index 000000000000..9e3f4727cfce
--- /dev/null
+++ b/canvas/source/directx/dx_spritedevicehelper.hxx
@@ -0,0 +1,117 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritedevicehelper.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_SPRITEDEVICEHELPER_HXX
+#define _DXCANVAS_SPRITEDEVICEHELPER_HXX
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+#include <com/sun/star/rendering/XBufferController.hpp>
+
+#include "dx_rendermodule.hxx"
+#include "dx_surfacebitmap.hxx"
+#include "dx_devicehelper.hxx"
+
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+
+#include <boost/utility.hpp>
+
+
+namespace dxcanvas
+{
+ class SpriteCanvas;
+ class SpriteCanvasHelper;
+
+ class SpriteDeviceHelper : public DeviceHelper
+ {
+ public:
+ SpriteDeviceHelper();
+
+ void init( Window& rWindow,
+ SpriteCanvas& rSpriteCanvas,
+ const ::com::sun::star::awt::Rectangle& rRect,
+ bool bFullscreen );
+
+ /// Dispose all internal references
+ void disposing();
+
+ // partial override XWindowGraphicDevice
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmap > createCompatibleAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XVolatileBitmap > createVolatileAlphaBitmap(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& rDevice,
+ const ::com::sun::star::geometry::IntegerSize2D& size );
+
+ sal_Bool hasFullScreenMode( );
+ sal_Bool enterFullScreenMode( sal_Bool bEnter );
+
+ ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
+ void destroyBuffers( );
+ ::sal_Bool showBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+ ::sal_Bool switchBuffer( bool bIsVisible, ::sal_Bool bUpdateAll );
+
+ const IDXRenderModuleSharedPtr& getRenderModule() const { return mpRenderModule; }
+ const DXSurfaceBitmapSharedPtr& getBackBuffer() const { return mpBackBuffer; }
+ const ::canvas::ISurfaceProxyManagerSharedPtr &getSurfaceProxy() const { return mpSurfaceProxyManager; }
+
+ ::com::sun::star::uno::Any isAccelerated() const;
+
+ void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
+
+ /** called when DumpScreenContent property is enabled on
+ XGraphicDevice, and writes out bitmaps of current screen.
+ */
+ void dumpScreenContent() const;
+
+ private:
+ void resizeBackBuffer( const ::basegfx::B2ISize& rNewSize );
+ HWND getHwnd() const;
+
+ /// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
+ SpriteCanvas* mpSpriteCanvas;
+
+ DXSurfaceBitmapSharedPtr mpBackBuffer;
+
+ /// Instance passing out HW textures
+ ::canvas::ISurfaceProxyManagerSharedPtr mpSurfaceProxyManager;
+
+ /// Our encapsulation interface to DirectX
+ IDXRenderModuleSharedPtr mpRenderModule;
+ };
+}
+
+#endif /* _DXCANVAS_SPRITEDEVICEHELPER_HXX */
diff --git a/canvas/source/directx/dx_spritehelper.cxx b/canvas/source/directx/dx_spritehelper.cxx
new file mode 100755
index 000000000000..f68c703b9e12
--- /dev/null
+++ b/canvas/source/directx/dx_spritehelper.cxx
@@ -0,0 +1,219 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritehelper.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
+
+#include "dx_canvascustomsprite.hxx"
+#include "dx_spritehelper.hxx"
+#include "dx_impltools.hxx"
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ SpriteHelper::SpriteHelper() :
+ mpSpriteCanvas(),
+ mpBitmap(),
+ mbTextureDirty( true ),
+ mbShowSpriteBounds( false )
+ {
+ }
+
+ void SpriteHelper::init( const geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rSpriteCanvas,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const DXSurfaceBitmapSharedPtr rBitmap,
+ bool bShowSpriteBounds )
+ {
+ ENSURE_OR_THROW( rSpriteCanvas.get() &&
+ rRenderModule &&
+ rBitmap,
+ "SpriteHelper::init(): Invalid device, sprite canvas or surface" );
+
+ mpSpriteCanvas = rSpriteCanvas;
+ mpBitmap = rBitmap;
+ mbTextureDirty = true;
+ mbShowSpriteBounds = bShowSpriteBounds;
+
+ // also init base class
+ CanvasCustomSpriteHelper::init( rSpriteSize,
+ rSpriteCanvas.get() );
+ }
+
+ void SpriteHelper::disposing()
+ {
+ mpBitmap.reset();
+ mpSpriteCanvas.clear();
+
+ // forward to parent
+ CanvasCustomSpriteHelper::disposing();
+ }
+
+ ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
+ {
+ return tools::polyPolygonFromXPolyPolygon2D( xPoly );
+ }
+
+ bool SpriteHelper::needRedraw() const
+ {
+ if( !mpBitmap ||
+ !mpSpriteCanvas.get() )
+ {
+ return false; // we're disposed, no redraw necessary
+ }
+
+ if( !isActive() ||
+ ::basegfx::fTools::equalZero( getAlpha() ) )
+ {
+ return false; // sprite is invisible
+ }
+
+ return true;
+ }
+
+ void SpriteHelper::redraw( bool& io_bSurfaceDirty ) const
+ {
+ if( !mpBitmap ||
+ !mpSpriteCanvas.get() )
+ {
+ return; // we're disposed
+ }
+
+ const ::basegfx::B2DPoint& rPos( getPosPixel() );
+ const double fAlpha( getAlpha() );
+
+ if( isActive() &&
+ !::basegfx::fTools::equalZero( fAlpha ) )
+ {
+
+ // TODO(Q2): For the time being, Device does not take a target
+ // surface, but always unconditionally renders to the
+ // background buffer.
+
+ // log output pos in device pixel
+ VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
+ rPos.getX(),
+ rPos.getY() );
+
+ const double fAlpha( getAlpha() );
+ const ::basegfx::B2DVector& rSize( getSizePixel() );
+ const ::basegfx::B2DHomMatrix& rTransform( getTransformation() );
+ const uno::Reference< rendering::XPolyPolygon2D >& xClip( getClip() );
+
+ mbTextureDirty = false;
+ io_bSurfaceDirty = false; // state taken, and processed.
+
+ ::basegfx::B2DPolyPolygon aClipPath; // empty for no clip
+ bool bIsClipRectangular( false ); // false, if no
+ // clip, or clip
+ // is complex
+
+ // setup and apply clip (if any)
+ // =================================
+
+ if( xClip.is() )
+ {
+ aClipPath = tools::polyPolygonFromXPolyPolygon2D( xClip );
+
+ const sal_Int32 nNumClipPolygons( aClipPath.count() );
+ if( nNumClipPolygons )
+ {
+ // TODO(P2): hold rectangle attribute directly
+ // at the XPolyPolygon2D
+
+ // check whether the clip is rectangular
+ if( nNumClipPolygons == 1 )
+ if( ::basegfx::tools::isRectangle( aClipPath.getB2DPolygon( 0 ) ) )
+ bIsClipRectangular = true;
+ }
+ }
+
+ const ::basegfx::B2DRectangle aSourceRect( 0.0,
+ 0.0,
+ rSize.getX(),
+ rSize.getY() );
+
+ // draw simple rectangular area if no clip is set.
+ if( !aClipPath.count() )
+ {
+ mpBitmap->draw(fAlpha,rPos,rTransform);
+ }
+ else if( bIsClipRectangular )
+ {
+ // apply a simple rect clip
+ // ========================
+
+ ::basegfx::B2DRectangle aClipBounds(
+ ::basegfx::tools::getRange( aClipPath ) );
+ aClipBounds.intersect( aSourceRect );
+
+ mpBitmap->draw(fAlpha,rPos,aClipBounds,rTransform);
+ }
+ else
+ {
+ // apply clip the hard way
+ // =======================
+
+ mpBitmap->draw(fAlpha,rPos,aClipPath,rTransform);
+ }
+
+ if( mbShowSpriteBounds )
+ {
+ if( aClipPath.count() )
+ {
+ // TODO(F2): Re-enable debug output
+ }
+ }
+ }
+ }
+}
diff --git a/canvas/source/directx/dx_spritehelper.hxx b/canvas/source/directx/dx_spritehelper.hxx
new file mode 100755
index 000000000000..c246467b8eb8
--- /dev/null
+++ b/canvas/source/directx/dx_spritehelper.hxx
@@ -0,0 +1,114 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_spritehelper.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_SPRITEHELPER_HXX
+#define _DXCANVAS_SPRITEHELPER_HXX
+
+#include <com/sun/star/rendering/XCustomSprite.hpp>
+
+#include <canvas/base/canvascustomspritehelper.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2isize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include "dx_spritecanvas.hxx"
+#include "dx_surfacebitmap.hxx"
+
+namespace dxcanvas
+{
+ /* Definition of SpriteHelper class */
+
+ /** Helper class for canvas sprites.
+
+ This class implements all sprite-related functionality, like
+ that available on the XSprite interface.
+ */
+ class SpriteHelper : public ::canvas::CanvasCustomSpriteHelper
+ {
+ public:
+ /** Create sprite helper
+ */
+ SpriteHelper();
+
+ /** Late-init the sprite helper
+
+ @param rSpriteSize
+ Size of the sprite
+
+ @param rSpriteCanvas
+ Sprite canvas this sprite is part of. Object stores
+ ref-counted reference to it, thus, don't forget to pass on
+ disposing()!
+
+ @param rRenderModule
+ rendermodule to use
+
+ @param rSpriteSurface
+ The surface of the sprite (not the DX texture, but the
+ persistent target of content rendering)
+
+ @param bShowSpriteBounds
+ When true, little debug bound rects for sprites are shown
+ */
+ void init( const ::com::sun::star::geometry::RealSize2D& rSpriteSize,
+ const SpriteCanvasRef& rSpriteCanvas,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ const DXSurfaceBitmapSharedPtr rBitmap,
+ bool bShowSpriteBounds );
+
+ void disposing();
+
+ /** Repaint sprite content via hardware to associated sprite
+ canvas
+
+ @param io_bSurfaceDirty
+ Input/output parameter, whether the sprite content is
+ dirty or not. If texture was updated, set to false
+
+ */
+ void redraw( bool& io_bSurfaceDirty ) const;
+
+ private:
+ virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(
+ ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& xPoly ) const;
+
+ /// Returns true, if the sprite _really_ needs redraw
+ bool needRedraw() const;
+
+ SpriteCanvasRef mpSpriteCanvas;
+
+ DXSurfaceBitmapSharedPtr mpBitmap;
+ mutable bool mbTextureDirty; // when true, texture needs update
+ bool mbShowSpriteBounds; // when true, debug bound rect for sprites is shown
+ };
+}
+
+#endif /* _DXCANVAS_SPRITEHELPER_HXX */
diff --git a/canvas/source/directx/dx_surfacebitmap.cxx b/canvas/source/directx/dx_surfacebitmap.cxx
new file mode 100644
index 000000000000..e82f814d3b23
--- /dev/null
+++ b/canvas/source/directx/dx_surfacebitmap.cxx
@@ -0,0 +1,807 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_surfacebitmap.cxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include "dx_surfacebitmap.hxx"
+#include "dx_impltools.hxx"
+#include "dx_surfacegraphics.hxx"
+#include "dx_graphicsprovider.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irange.hxx>
+
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+# include <imdebug.h>
+# undef min
+# undef max
+# endif
+#endif
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXColorBuffer
+ //////////////////////////////////////////////////////////////////////////////////
+
+ struct DXColorBuffer : public canvas::IColorBuffer
+ {
+ public:
+ DXColorBuffer( const COMReference<surface_type>& rSurface,
+ const ::basegfx::B2IVector& rSize ) :
+ mpSurface(rSurface),
+ maSize(rSize),
+ mbAlpha(false)
+ {
+ }
+
+ // implementation of the 'IColorBuffer' interface
+ public:
+
+ virtual sal_uInt8* lock() const;
+ virtual void unlock() const;
+ virtual sal_uInt32 getWidth() const;
+ virtual sal_uInt32 getHeight() const;
+ virtual sal_uInt32 getStride() const;
+ virtual Format getFormat() const;
+
+ private:
+
+ ::basegfx::B2IVector maSize;
+#if DIRECTX_VERSION < 0x0900
+ mutable DDSURFACEDESC aSurfaceDesc;
+#else
+ mutable D3DLOCKED_RECT maLockedRect;
+#endif
+ mutable COMReference<surface_type> mpSurface;
+ bool mbAlpha;
+ };
+
+ sal_uInt8* DXColorBuffer::lock() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ rtl_fillMemory((void *)&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+ if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ return static_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
+#else
+ if(SUCCEEDED(mpSurface->LockRect(&maLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ return static_cast<sal_uInt8 *>(maLockedRect.pBits);
+#endif
+ return NULL;
+ }
+
+ void DXColorBuffer::unlock() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ mpSurface->Unlock(NULL);
+#else
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ sal_uInt32 DXColorBuffer::getWidth() const
+ {
+ return maSize.getX();
+ }
+
+ sal_uInt32 DXColorBuffer::getHeight() const
+ {
+ return maSize.getY();
+ }
+
+ sal_uInt32 DXColorBuffer::getStride() const
+ {
+#if DIRECTX_VERSION < 0x0900
+ return aSurfaceDesc.lPitch;
+#else
+ return maLockedRect.Pitch;
+#endif
+ }
+
+ canvas::IColorBuffer::Format DXColorBuffer::getFormat() const
+ {
+ return canvas::IColorBuffer::FMT_X8R8G8B8;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // GDIColorBuffer
+ //////////////////////////////////////////////////////////////////////////////////
+
+ struct GDIColorBuffer : public canvas::IColorBuffer
+ {
+ public:
+
+ GDIColorBuffer( const BitmapSharedPtr& rSurface,
+ const ::basegfx::B2IVector& rSize ) :
+ mpGDIPlusBitmap(rSurface),
+ maSize(rSize),
+ mbAlpha(true)
+ {
+ }
+
+ // implementation of the 'IColorBuffer' interface
+ public:
+
+ virtual sal_uInt8* lock() const;
+ virtual void unlock() const;
+ virtual sal_uInt32 getWidth() const;
+ virtual sal_uInt32 getHeight() const;
+ virtual sal_uInt32 getStride() const;
+ virtual Format getFormat() const;
+
+ private:
+
+ ::basegfx::B2IVector maSize;
+ mutable Gdiplus::BitmapData aBmpData;
+ BitmapSharedPtr mpGDIPlusBitmap;
+ bool mbAlpha;
+ };
+
+ sal_uInt8* GDIColorBuffer::lock() const
+ {
+ aBmpData.Width = maSize.getX();
+ aBmpData.Height = maSize.getY();
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = NULL;
+ const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead,
+ PixelFormat32bppARGB,
+ &aBmpData ) )
+ {
+ return NULL;
+ }
+
+ return static_cast<sal_uInt8*>(aBmpData.Scan0);
+ }
+
+ void GDIColorBuffer::unlock() const
+ {
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+ }
+
+ sal_uInt32 GDIColorBuffer::getWidth() const
+ {
+ return maSize.getX();
+ }
+
+ sal_uInt32 GDIColorBuffer::getHeight() const
+ {
+ return maSize.getY();
+ }
+
+ sal_uInt32 GDIColorBuffer::getStride() const
+ {
+ return aBmpData.Stride;
+ }
+
+ canvas::IColorBuffer::Format GDIColorBuffer::getFormat() const
+ {
+ return canvas::IColorBuffer::FMT_A8R8G8B8;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::DXSurfaceBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ DXSurfaceBitmap::DXSurfaceBitmap( const ::basegfx::B2IVector& rSize,
+ const canvas::ISurfaceProxyManagerSharedPtr& rMgr,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ bool bWithAlpha ) :
+ mpGdiPlusUser( GDIPlusUser::createInstance() ),
+ maSize(rSize),
+ mpRenderModule(rRenderModule),
+ mpSurfaceManager(rMgr),
+ mpSurfaceProxy(),
+ mpSurface(),
+ mpGDIPlusBitmap(),
+ mpGraphics(),
+ mpColorBuffer(),
+ mbIsSurfaceDirty(true),
+ mbAlpha(bWithAlpha)
+ {
+ init();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getSize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ ::basegfx::B2IVector DXSurfaceBitmap::getSize() const
+ {
+ return maSize;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::init
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::init()
+ {
+ // create container for pixel data
+ if(mbAlpha)
+ {
+ mpGDIPlusBitmap.reset(
+ new Gdiplus::Bitmap(
+ maSize.getX(),
+ maSize.getY(),
+ PixelFormat32bppARGB
+ ));
+ mpGraphics.reset( tools::createGraphicsFromBitmap(mpGDIPlusBitmap) );
+
+ // create the colorbuffer object, which is basically a simple
+ // wrapper around the directx surface. the colorbuffer is the
+ // interface which is used by the surfaceproxy to support any
+ // kind of underlying structure for the pixel data container.
+ mpColorBuffer.reset(new GDIColorBuffer(mpGDIPlusBitmap,maSize));
+ }
+ else
+ {
+ mpSurface = mpRenderModule->createSystemMemorySurface(maSize);
+
+ // create the colorbuffer object, which is basically a simple
+ // wrapper around the directx surface. the colorbuffer is the
+ // interface which is used by the surfaceproxy to support any
+ // kind of underlying structure for the pixel data container.
+ mpColorBuffer.reset(new DXColorBuffer(mpSurface,maSize));
+ }
+
+ // create a (possibly hardware accelerated) mirror surface.
+ mpSurfaceProxy = mpSurfaceManager->createSurfaceProxy(mpColorBuffer);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::resize
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::resize( const ::basegfx::B2IVector& rSize )
+ {
+ if(maSize != rSize)
+ {
+ maSize = rSize;
+ init();
+ }
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::clear
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::clear()
+ {
+ GraphicsSharedPtr pGraphics(getGraphics());
+ Gdiplus::Color transColor(255,0,0,0);
+ pGraphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy );
+ pGraphics->Clear( transColor );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::hasAlpha
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::hasAlpha() const
+ {
+ return mbAlpha;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getGraphics
+ //////////////////////////////////////////////////////////////////////////////////
+
+ GraphicsSharedPtr DXSurfaceBitmap::getGraphics()
+ {
+ // since clients will most probably draw directly
+ // to the GDI+ bitmap, we need to mark it as dirty
+ // to ensure that the corrosponding dxsurface will
+ // be updated.
+ mbIsSurfaceDirty = true;
+
+ if(hasAlpha())
+ return mpGraphics;
+ else
+ return createSurfaceGraphics(mpSurface);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getBitmap
+ //////////////////////////////////////////////////////////////////////////////////
+
+ BitmapSharedPtr DXSurfaceBitmap::getBitmap() const
+ {
+ if(hasAlpha())
+ return mpGDIPlusBitmap;
+
+ BitmapSharedPtr pResult;
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ {
+ // decide about the format we pass the gdi+, the directx surface is always
+ // 32bit, either with or without alpha component.
+ Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
+
+ // construct a gdi+ bitmap from the raw pixel data.
+ pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
+ aSurfaceDesc.lPitch,
+ nFormat,
+ (BYTE *)aSurfaceDesc.lpSurface ));
+
+ // unlock the directx surface
+ mpSurface->Unlock(NULL);
+ }
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if(SUCCEEDED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ {
+ // decide about the format we pass the gdi+, the directx surface is always
+ // 32bit, either with or without alpha component.
+ Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
+
+ // construct a gdi+ bitmap from the raw pixel data.
+ pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
+ aLockedRect.Pitch,
+ nFormat,
+ (BYTE *)aLockedRect.pBits ));
+
+ mpSurface->UnlockRect();
+ }
+#endif
+
+ return pResult;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rClipPoly, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rArea, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ return mpSurfaceProxy->draw( fAlpha, rPos, rTransform );
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::draw
+ //////////////////////////////////////////////////////////////////////////////////
+
+ bool DXSurfaceBitmap::draw( const ::basegfx::B2IRange& rArea )
+ {
+ if( mbIsSurfaceDirty )
+ {
+ mpSurfaceProxy->setColorBufferDirty();
+ mbIsSurfaceDirty = false;
+ }
+
+ const double fAlpha(1.0);
+ const ::basegfx::B2DHomMatrix aTransform;
+ const ::basegfx::B2DRange aIEEEArea( rArea );
+ return mpSurfaceProxy->draw(fAlpha,
+ ::basegfx::B2DPoint(),
+ aIEEEArea,
+ aTransform);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::imageDebugger
+ //////////////////////////////////////////////////////////////////////////////////
+#if defined(DX_DEBUG_IMAGES)
+# if OSL_DEBUG_LEVEL > 0
+ void DXSurfaceBitmap::imageDebugger()
+ {
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+
+ if( FAILED(mpSurface->Lock( NULL,
+ &aSurfaceDesc,
+ DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
+ NULL)) )
+ return;
+
+ imdebug("bgra w=%d h=%d %p", aSurfaceDesc.dwWidth, aSurfaceDesc.dwHeight, aSurfaceDesc.lpSurface);
+
+ mpSurface->Unlock(NULL);
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if( FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)) )
+ return;
+
+ imdebug("bgra w=%d h=%d %p", maSize.getX(),
+ maSize.getY(), aLockedRect.pBits);
+ mpSurface->UnlockRect();
+#endif
+ }
+# endif
+#endif
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getData
+ //////////////////////////////////////////////////////////////////////////////////
+
+ uno::Sequence< sal_Int8 > DXSurfaceBitmap::getData( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if(hasAlpha())
+ {
+ uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
+
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = aRes.getArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ // read data from bitmap
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO(F1): Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ // failed to lock, bail out
+ return uno::Sequence< sal_Int8 >();
+ }
+
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+
+ return aRes;
+ }
+ else
+ {
+ sal_uInt32 nWidth = rect.X2-rect.X1;
+ sal_uInt32 nHeight = rect.Y2-rect.Y1;
+
+ uno::Sequence< sal_Int8 > aRes(nWidth*nHeight*4);
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ return uno::Sequence< sal_Int8 >();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
+ sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pDst += nSegmentSizeInBytes;
+ pSrc += aSurfaceDesc.lPitch;
+ }
+
+ mpSurface->Unlock(NULL);
+#else
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ return uno::Sequence< sal_Int8 >();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
+ sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pDst += nSegmentSizeInBytes;
+ pSrc += aLockedRect.Pitch;
+ }
+
+ mpSurface->UnlockRect();
+#endif
+ return aRes;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::setData
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::setData( const uno::Sequence< sal_Int8 >& data,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerRectangle2D& rect )
+ {
+ if(hasAlpha())
+ {
+ const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
+
+ Gdiplus::BitmapData aBmpData;
+ aBmpData.Width = rect.X2-rect.X1;
+ aBmpData.Height = rect.Y2-rect.Y1;
+ aBmpData.Stride = 4*aBmpData.Width;
+ aBmpData.PixelFormat = PixelFormat32bppARGB;
+ aBmpData.Scan0 = (void*)data.getConstArray();
+
+ // TODO(F1): Support more pixel formats natively
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
+ Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
+ PixelFormat32bppARGB, // TODO: Adapt to
+ // Graphics native
+ // format/change
+ // getMemoryLayout
+ &aBmpData ) )
+ {
+ throw uno::RuntimeException();
+ }
+
+ // commit data to bitmap
+ mpGDIPlusBitmap->UnlockBits( &aBmpData );
+ }
+ else
+ {
+ sal_uInt32 nWidth = rect.X2-rect.X1;
+ sal_uInt32 nHeight = rect.Y2-rect.Y1;
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
+ sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pSrc += nSegmentSizeInBytes;
+ pDst += aSurfaceDesc.lPitch;
+ }
+
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
+ sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
+ sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
+ for(sal_uInt32 y=0; y<nHeight; ++y)
+ {
+ rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
+ pSrc += nSegmentSizeInBytes;
+ pDst += aLockedRect.Pitch;
+ }
+
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ mbIsSurfaceDirty = true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::setPixel
+ //////////////////////////////////////////////////////////////////////////////////
+
+ void DXSurfaceBitmap::setPixel( const uno::Sequence< sal_Int8 >& color,
+ const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if(hasAlpha())
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->SetPixel( pos.X, pos.Y,
+ Gdiplus::Color( tools::sequenceToArgb( color ))))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
+ "CanvasHelper::setPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
+ "CanvasHelper::setPixel: Y coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( color.getLength() > 3,
+ "CanvasHelper::setPixel: not enough color components" );
+
+ Gdiplus::Color aColor(tools::sequenceToArgb(color));
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
+ *pDst = aColor.GetValue();
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
+ *pDst = aColor.GetValue();
+ mpSurface->UnlockRect();
+#endif
+ }
+
+ mbIsSurfaceDirty = true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // DXSurfaceBitmap::getPixel
+ //////////////////////////////////////////////////////////////////////////////////
+
+ uno::Sequence< sal_Int8 > DXSurfaceBitmap::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
+ const geometry::IntegerPoint2D& pos )
+ {
+ if(hasAlpha())
+ {
+ const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
+
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+ Gdiplus::Color aColor;
+
+ if( Gdiplus::Ok != mpGDIPlusBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
+ return uno::Sequence< sal_Int8 >();
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+ else
+ {
+ ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
+ "CanvasHelper::getPixel: X coordinate out of bounds" );
+ ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
+ "CanvasHelper::getPixel: Y coordinate out of bounds" );
+
+#if DIRECTX_VERSION < 0x0900
+ DDSURFACEDESC aSurfaceDesc;
+ rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
+ aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
+ const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
+
+ // lock the directx surface to receive the pointer to the surface memory.
+ if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
+ Gdiplus::Color aColor(*pDst);
+ mpSurface->Unlock(NULL);
+#else
+ // lock the directx surface to receive the pointer to the surface memory.
+ D3DLOCKED_RECT aLockedRect;
+ if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
+ throw uno::RuntimeException();
+
+ sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
+ Gdiplus::Color aColor(*pDst);
+ mpSurface->UnlockRect();
+#endif
+
+ return tools::argbToIntSequence(aColor.GetValue());
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // End of file
+ //////////////////////////////////////////////////////////////////////////////////
+}
+
diff --git a/canvas/source/directx/dx_surfacebitmap.hxx b/canvas/source/directx/dx_surfacebitmap.hxx
new file mode 100644
index 000000000000..7519635d5ccc
--- /dev/null
+++ b/canvas/source/directx/dx_surfacebitmap.hxx
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_surfacebitmap.hxx,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_DXSURFACEBITMAP_HXX
+#define _DXCANVAS_DXSURFACEBITMAP_HXX
+
+#include <canvas/rendering/isurfaceproxy.hxx>
+#include <canvas/rendering/isurfaceproxymanager.hxx>
+#include "dx_ibitmap.hxx"
+#include "dx_canvasfont.hxx" //winstuff
+#include "dx_gdiplususer.hxx"
+#include "dx_rendermodule.hxx"
+
+namespace dxcanvas
+{
+ class DXSurfaceBitmap : public IBitmap
+ {
+ public:
+ DXSurfaceBitmap( const ::basegfx::B2IVector& rSize,
+ const canvas::ISurfaceProxyManagerSharedPtr& rMgr,
+ const IDXRenderModuleSharedPtr& rRenderModule,
+ bool bWithAlpha );
+
+ bool resize( const ::basegfx::B2IVector& rSize );
+ void clear();
+
+ virtual GraphicsSharedPtr getGraphics();
+
+ virtual BitmapSharedPtr getBitmap() const;
+ virtual ::basegfx::B2IVector getSize() const;
+ virtual bool hasAlpha() const;
+
+ COMReference<surface_type> getSurface() const { return mpSurface; }
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ bool draw( const ::basegfx::B2IRange& rArea );
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DRange& rArea,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ bool draw( double fAlpha,
+ const ::basegfx::B2DPoint& rPos,
+ const ::basegfx::B2DPolyPolygon& rClipPoly,
+ const ::basegfx::B2DHomMatrix& rTransform );
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getData(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ virtual void setData(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& data,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerRectangle2D& rect );
+
+ virtual void setPixel(
+ const ::com::sun::star::uno::Sequence< sal_Int8 >& color,
+ const ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int8 > getPixel(
+ ::com::sun::star::rendering::IntegerBitmapLayout& bitmapLayout,
+ const ::com::sun::star::geometry::IntegerPoint2D& pos );
+
+#ifdef DX_DEBUG_IMAGES
+ void imageDebugger();
+#endif
+ private:
+ void init();
+
+ // Refcounted global GDI+ state container
+ GDIPlusUserSharedPtr mpGdiPlusUser;
+
+ // size of this image in pixels [integral unit]
+ ::basegfx::B2IVector maSize;
+
+ // pointer to the rendermodule, needed to create surfaces
+ // which are used as container for the actual pixel data.
+ // generally we could use any kind of storage, but GDI+
+ // is not willing to render antialiased fonts unless we
+ // use this special kind of container, don't ask me why...
+ IDXRenderModuleSharedPtr mpRenderModule;
+
+ // pointer to the surface manager, needed in case clients
+ // want to resize the bitmap.
+ canvas::ISurfaceProxyManagerSharedPtr mpSurfaceManager;
+
+ // access point to the surface proxy which handles
+ // the hardware-dependent rendering stuff.
+ canvas::ISurfaceProxySharedPtr mpSurfaceProxy;
+
+ // container for pixel data, we need to use a directx
+ // surface since GDI+ sucks...
+ COMReference<surface_type> mpSurface;
+
+ // since GDI+ does not work correctly in case we
+ // run on a 16bit display [don't ask me why] we need
+ // to occasionally render to a native GDI+ bitmap.
+ BitmapSharedPtr mpGDIPlusBitmap;
+ // Graphics for the mpGDIPlusBitmap
+ GraphicsSharedPtr mpGraphics;
+
+ // internal implementation of the iColorBuffer interface
+ canvas::IColorBufferSharedPtr mpColorBuffer;
+
+ // indicates wether the associated surface needs
+ // to refresh its contents or not. in other words,
+ // this flag is set iff both representations are
+ // out of sync.
+ mutable bool mbIsSurfaceDirty;
+
+ // true if the bitmap contains an alpha channel
+ bool mbAlpha;
+ };
+
+ typedef ::boost::shared_ptr< DXSurfaceBitmap > DXSurfaceBitmapSharedPtr;
+}
+
+#endif
diff --git a/canvas/source/directx/dx_surfacegraphics.cxx b/canvas/source/directx/dx_surfacegraphics.cxx
new file mode 100755
index 000000000000..8b9af6be6827
--- /dev/null
+++ b/canvas/source/directx/dx_surfacegraphics.cxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_surfacegraphics.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include "dx_surfacegraphics.hxx"
+#include "dx_impltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace
+ {
+ struct GraphicsDeleter
+ {
+ COMReference<surface_type> mpSurface;
+ HDC maHDC;
+
+ GraphicsDeleter(const COMReference<surface_type>& rSurface, HDC hdc) :
+ mpSurface(rSurface),
+ maHDC(hdc)
+ {}
+
+ void operator()( Gdiplus::Graphics* pGraphics )
+ {
+ if(!pGraphics)
+ return;
+
+ pGraphics->Flush(Gdiplus::FlushIntentionSync);
+ delete pGraphics;
+
+ if(mpSurface.is())
+ mpSurface->ReleaseDC( maHDC );
+ }
+ };
+ }
+
+ GraphicsSharedPtr createSurfaceGraphics(const COMReference<surface_type>& rSurface )
+ {
+ Gdiplus::Graphics* pGraphics;
+ GraphicsSharedPtr pRet;
+ HDC aHDC;
+ if( SUCCEEDED(rSurface->GetDC( &aHDC )) )
+ {
+ pGraphics = Gdiplus::Graphics::FromHDC( aHDC );
+ if(pGraphics)
+ {
+ tools::setupGraphics( *pGraphics );
+ pRet.reset(pGraphics,
+ GraphicsDeleter(rSurface, aHDC));
+ return pRet;
+ }
+ else
+ rSurface->ReleaseDC( aHDC );
+ }
+
+ throw uno::RuntimeException();
+ }
+}
diff --git a/canvas/source/directx/dx_surfacegraphics.hxx b/canvas/source/directx/dx_surfacegraphics.hxx
new file mode 100755
index 000000000000..696f2de338d3
--- /dev/null
+++ b/canvas/source/directx/dx_surfacegraphics.hxx
@@ -0,0 +1,48 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_surfacegraphics.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_SURFACEGRAPHICS_HXX
+#define _DXCANVAS_SURFACEGRAPHICS_HXX
+
+#include "dx_graphicsprovider.hxx"
+
+namespace dxcanvas
+{
+ /** Container providing a Gdiplus::Graphics for a Surface
+
+ This wrapper class transparently handles allocation and
+ release of surface resources the RAII way (the
+ GraphicsSharedPtr returned has a deleter that does all the
+ necessary DX cleanup work).
+ */
+ GraphicsSharedPtr createSurfaceGraphics(const COMReference<surface_type>& rSurface );
+}
+
+#endif /* _DXCANVAS_SURFACEGRAPHICS_HXX */
diff --git a/canvas/source/directx/dx_textlayout.cxx b/canvas/source/directx/dx_textlayout.cxx
new file mode 100755
index 000000000000..e1fd917ed772
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout.cxx
@@ -0,0 +1,283 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_textlayout.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <ctype.h> // don't ask. msdev breaks otherwise...
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include "dx_bitmap.hxx"
+#include "dx_textlayout.hxx"
+#include "dx_spritecanvas.hxx"
+#include "dx_textlayout_drawhelper.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ TextLayout::TextLayout( const rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 /*nRandomSeed*/,
+ const CanvasFont::ImplRef& rFont ) :
+ TextLayout_Base( m_aMutex ),
+ maText( aText ),
+ maLogicalAdvancements(),
+ mpFont( rFont ),
+ mnTextDirection( nDirection )
+ {
+ }
+
+ TextLayout::~TextLayout()
+ {
+ }
+
+ void SAL_CALL TextLayout::disposing()
+ {
+ mpFont.reset();
+ }
+
+ // XTextLayout
+ uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< geometry::RealRectangle2D >();
+ }
+
+ uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Sequence< geometry::RealRectangle2D >();
+ }
+
+ uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maLogicalAdvancements;
+ }
+
+ void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if( aAdvancements.getLength() != maText.Length )
+ {
+ OSL_TRACE( "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
+ throw lang::IllegalArgumentException();
+ }
+
+ maLogicalAdvancements = aAdvancements;
+ }
+
+ geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
+ ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
+
+ // render text
+ const geometry::RealRectangle2D aBounds(
+ aDrawHelper.queryTextBounds(
+ maText,
+ maLogicalAdvancements,
+ mpFont.getRef(),
+ mpFont->getFontMatrix()));
+
+ return aBounds;
+ }
+
+ double SAL_CALL TextLayout::justify( double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
+ double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::TextHit();
+ }
+
+ rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
+ sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return rendering::Caret();
+ }
+
+ sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nCaretAdvancement*/,
+ sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0;
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
+ sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return uno::Reference< rendering::XPolyPolygon2D >();
+ }
+
+ double SAL_CALL TextLayout::getBaselineOffset( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // TODO
+ return 0.0;
+ }
+
+ sal_Int8 SAL_CALL TextLayout::getMainTextDirection( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mnTextDirection;
+ }
+
+ uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return mpFont.getRef();
+ }
+
+ rendering::StringContext SAL_CALL TextLayout::getText( ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return maText;
+ }
+
+ namespace
+ {
+ // TODO(P2): Check whether this gets inlined. If not, make functor
+ // out of it
+ inline Gdiplus::PointF gdiPlusPointFromDx( const double& dx )
+ {
+ return Gdiplus::PointF( static_cast<Gdiplus::REAL>(dx),
+ 0.0f );
+ }
+ }
+
+ bool TextLayout::draw( const GraphicsSharedPtr& rGraphics,
+ const rendering::ViewState& rViewState,
+ const rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
+ bool bAlphaSurface ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);
+
+ // render text
+ aDrawHelper.drawText(
+ rGraphics,
+ rViewState,
+ rRenderState,
+ rOutputOffset,
+ maText,
+ maLogicalAdvancements,
+ mpFont.getRef(),
+ mpFont->getFontMatrix(),
+ bAlphaSurface);
+
+ return true;
+ }
+
+
+#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
+#define IMPLEMENTATION_NAME "DXCanvas::TextLayout"
+
+ ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
+ {
+ return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
+ }
+
+ sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
+ {
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+ }
+
+ uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames() throw( uno::RuntimeException )
+ {
+ uno::Sequence< ::rtl::OUString > aRet(1);
+ aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+
+ return aRet;
+ }
+}
diff --git a/canvas/source/directx/dx_textlayout.hxx b/canvas/source/directx/dx_textlayout.hxx
new file mode 100755
index 000000000000..a8562ed34f7a
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout.hxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_textlayout.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_TEXTLAYOUT_HXX
+#define _DXCANVAS_TEXTLAYOUT_HXX
+
+#include <cppuhelper/compbase2.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <com/sun/star/rendering/XTextLayout.hpp>
+
+#include <basegfx/vector/b2isize.hxx>
+
+#include <boost/utility.hpp>
+
+#include "dx_canvasfont.hxx"
+#include "dx_ibitmap.hxx"
+#include "dx_winstuff.hxx"
+#include "dx_gdiplususer.hxx"
+
+
+/* Definition of TextLayout class */
+class DXBitmapSharedPtr;
+
+namespace dxcanvas
+{
+ typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XTextLayout,
+ ::com::sun::star::lang::XServiceInfo > TextLayout_Base;
+
+ class TextLayout : public ::comphelper::OBaseMutex,
+ public TextLayout_Base,
+ private ::boost::noncopyable
+ {
+ public:
+ TextLayout( const ::com::sun::star::rendering::StringContext& aText,
+ sal_Int8 nDirection,
+ sal_Int64 nRandomSeed,
+ const CanvasFont::ImplRef& rFont );
+
+ /// Dispose all internal references
+ virtual void SAL_CALL disposing();
+
+ // XTextLayout
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > > SAL_CALL queryTextShapes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealRectangle2D > SAL_CALL queryInkMeasures( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealRectangle2D > SAL_CALL queryMeasures( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< double > SAL_CALL queryLogicalAdvancements( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL applyLogicalAdvancements( const ::com::sun::star::uno::Sequence< double >& aAdvancements ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::geometry::RealRectangle2D SAL_CALL queryTextBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL justify( double nSize ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL combinedJustify( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XTextLayout > >& aNextLayouts, double nSize ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::TextHit SAL_CALL getTextHit( const ::com::sun::star::geometry::RealPoint2D& aHitPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::Caret SAL_CALL getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > SAL_CALL queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual double SAL_CALL getBaselineOffset( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int8 SAL_CALL getMainTextDirection( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XCanvasFont > SAL_CALL getFont( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::rendering::StringContext SAL_CALL getText( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ bool draw( const GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice,
+ bool bAlphaSurface ) const;
+
+ protected:
+ ~TextLayout(); // we're a ref-counted UNO class. _We_ destroy ourselves.
+
+ private:
+ // NOTE: no need for GDIPlusUserSharedPtr, mpFont implicitely has one already
+
+ ::com::sun::star::rendering::StringContext maText;
+ ::com::sun::star::uno::Sequence< double > maLogicalAdvancements;
+ CanvasFont::ImplRef mpFont;
+ sal_Int8 mnTextDirection;
+ };
+
+}
+
+#endif /* _DXCANVAS_TEXTLAYOUT_HXX */
diff --git a/canvas/source/directx/dx_textlayout_drawhelper.cxx b/canvas/source/directx/dx_textlayout_drawhelper.cxx
new file mode 100755
index 000000000000..358bd1e9d74f
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout_drawhelper.cxx
@@ -0,0 +1,315 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_textlayout_drawhelper.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <tools/poly.hxx>
+
+#include <vcl/metric.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/canvastools.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <boost/scoped_array.hpp>
+#include <boost/bind.hpp>
+#include <com/sun/star/rendering/FontRequest.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <tools/color.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <canvas/canvastools.hxx>
+#include <canvas/debug.hxx>
+#include "dx_impltools.hxx"
+#include <vcl/sysdata.hxx>
+#include <i18npool/mslangid.hxx>
+#include "dx_textlayout_drawhelper.hxx"
+#include "dx_bitmap.hxx"
+#include "dx_canvasfont.hxx"
+
+class ::com::sun::star::rendering::XCanvasFont;
+
+using namespace ::com::sun::star;
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace dxcanvas
+{
+ class DXBitmap;
+ TextLayoutDrawHelper::TextLayoutDrawHelper(
+ const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice ) :
+ mxGraphicDevice(xGraphicDevice)
+ {
+ }
+
+ TextLayoutDrawHelper::~TextLayoutDrawHelper()
+ {
+ }
+
+ void TextLayoutDrawHelper::drawText(
+ const GraphicsSharedPtr& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
+ bool bAlphaSurface )
+ {
+ HDC hdc = rGraphics->GetHDC();
+
+ // issue an ReleaseHDC() when leaving the scope
+ const ::comphelper::ScopeGuard aGuard(
+ boost::bind( &Gdiplus::Graphics::ReleaseHDC,
+ rGraphics.get(),
+ hdc ));
+
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(hdc);
+ VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
+
+ // disable font antialiasing - GDI does not handle alpha
+ // surfaces properly.
+ if( bAlphaSurface )
+ aVirtualDevice.SetAntialiasing(ANTIALIASING_DISABLE_TEXT);
+
+ if(rText.Length)
+ {
+ sal_Bool test = mxGraphicDevice.is();
+ ENSURE_OR_THROW( test,
+ "TextLayoutDrawHelper::drawText(): Invalid GraphicDevice" );
+
+ // set text color. Make sure to remove transparence part first.
+ Color aColor( COL_WHITE );
+
+ if( rRenderState.DeviceColor.getLength() > 2 )
+ aColor = ::vcl::unotools::doubleSequenceToColor(
+ rRenderState.DeviceColor,
+ mxGraphicDevice->getDeviceColorSpace());
+ aColor.SetTransparency(0);
+ aVirtualDevice.SetTextColor(aColor);
+
+ // create the font
+ const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
+ Font aFont(
+ rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
+
+ aFont.SetAlign( ALIGN_BASELINE );
+ aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
+ aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+ aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+
+ aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
+
+ // setup font color
+ aFont.SetColor( aColor );
+ aFont.SetFillColor( aColor );
+
+ // adjust to stretched font
+ if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
+ {
+ const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
+ const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+ double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+ if( !::basegfx::fTools::equalZero( fDividend) )
+ fStretch /= fDividend;
+
+ const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+ aFont.SetWidth( nNewWidth );
+ }
+
+ // set font
+ aVirtualDevice.SetFont(aFont);
+
+ // create world transformation matrix
+ ::basegfx::B2DHomMatrix aWorldTransform;
+ ::canvas::tools::mergeViewAndRenderTransform(aWorldTransform, rViewState, rRenderState);
+
+ if(!rOutputOffset.equalZero())
+ {
+ aWorldTransform.translate(rOutputOffset.getX(), rOutputOffset.getY());
+ }
+
+ // set ViewState clipping
+ if(rViewState.Clip.is())
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rViewState.Clip));
+ ::basegfx::B2DHomMatrix aMatrix;
+ ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, rViewState.AffineTransform );
+
+ if(!rOutputOffset.equalZero())
+ {
+ aMatrix.translate(rOutputOffset.getX(), rOutputOffset.getY());
+ }
+
+ aClipPoly.transform(aMatrix);
+ const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
+ aVirtualDevice.IntersectClipRegion(rClipRegion);
+ }
+
+ if(rRenderState.Clip.is())
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rRenderState.Clip));
+ aClipPoly.transform(aWorldTransform);
+ const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
+ aVirtualDevice.IntersectClipRegion(rClipRegion);
+ }
+
+ // set world transform
+ XFORM aXForm;
+ aXForm.eM11 = (FLOAT)aWorldTransform.get(0, 0);
+ aXForm.eM12 = (FLOAT)aWorldTransform.get(1, 0);
+ aXForm.eM21 = (FLOAT)aWorldTransform.get(0, 1);
+ aXForm.eM22 = (FLOAT)aWorldTransform.get(1, 1);
+ aXForm.eDx = (FLOAT)aWorldTransform.get(0, 2);
+ aXForm.eDy = (FLOAT)aWorldTransform.get(1, 2);
+
+ // TODO(F3): This is NOT supported on 95/98/ME!
+ SetGraphicsMode(hdc, GM_ADVANCED);
+ SetTextAlign(hdc, TA_BASELINE);
+ SetWorldTransform(hdc, &aXForm);
+
+ // use a empty StartPosition for text rendering
+ const Point aEmptyPoint(0, 0);
+
+ // create the String
+ const String aText(rText.Text.getStr());
+
+ if( rLogicalAdvancements.getLength() )
+ {
+ // create the DXArray
+ const sal_Int32 nLen( rLogicalAdvancements.getLength() );
+ ::boost::scoped_array<sal_Int32> pDXArray( new sal_Int32[nLen] );
+ for( sal_Int32 i=0; i<nLen; ++i )
+ pDXArray[i] = basegfx::fround( rLogicalAdvancements[i] );
+
+ // draw the String
+ aVirtualDevice.DrawTextArray( aEmptyPoint,
+ aText,
+ pDXArray.get(),
+ (xub_StrLen)rText.StartPosition,
+ (xub_StrLen)rText.Length );
+ }
+ else
+ {
+ // draw the String
+ aVirtualDevice.DrawText( aEmptyPoint,
+ aText,
+ (xub_StrLen)rText.StartPosition,
+ (xub_StrLen)rText.Length );
+ }
+ }
+ }
+
+ geometry::RealRectangle2D TextLayoutDrawHelper::queryTextBounds( const rendering::StringContext& rText,
+ const uno::Sequence< double >& rLogicalAdvancements,
+ const uno::Reference< rendering::XCanvasFont >& rCanvasFont,
+ const geometry::Matrix2D& rFontMatrix )
+ {
+ if(!(rText.Length))
+ return geometry::RealRectangle2D();
+
+ // TODO(F1): Fetching default screen DC here, will yield wrong
+ // metrics when e.g. formatting for a printer!
+ SystemGraphicsData aSystemGraphicsData;
+ aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
+ aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(GetDC( NULL ));
+ VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
+
+ // create the font
+ const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
+ Font aFont(
+ rFontRequest.FontDescription.FamilyName,
+ rFontRequest.FontDescription.StyleName,
+ Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
+
+ aFont.SetAlign( ALIGN_BASELINE );
+ aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
+ aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+ aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+
+ // adjust to stretched font
+ if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
+ {
+ const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
+ const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
+ double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
+
+ if( !::basegfx::fTools::equalZero( fDividend) )
+ fStretch /= fDividend;
+
+ const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
+
+ aFont.SetWidth( nNewWidth );
+ }
+
+ // set font
+ aVirtualDevice.SetFont(aFont);
+
+ // need metrics for Y offset, the XCanvas always renders
+ // relative to baseline
+ const ::FontMetric& aMetric( aVirtualDevice.GetFontMetric() );
+
+ const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
+ const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
+
+ if( rLogicalAdvancements.getLength() )
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ rLogicalAdvancements[ rLogicalAdvancements.getLength()-1 ],
+ nBelowBaseline );
+ }
+ else
+ {
+ return geometry::RealRectangle2D( 0, nAboveBaseline,
+ aVirtualDevice.GetTextWidth(
+ rText.Text,
+ ::canvas::tools::numeric_cast<USHORT>(rText.StartPosition),
+ ::canvas::tools::numeric_cast<USHORT>(rText.Length) ),
+ nBelowBaseline );
+ }
+ }
+}
+
+
+// eof
diff --git a/canvas/source/directx/dx_textlayout_drawhelper.hxx b/canvas/source/directx/dx_textlayout_drawhelper.hxx
new file mode 100755
index 000000000000..b6e4cd60a64f
--- /dev/null
+++ b/canvas/source/directx/dx_textlayout_drawhelper.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_textlayout_drawhelper.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _TEXTLAYOUT_DRAWHELPER_HXX
+#define _TEXTLAYOUT_DRAWHELPER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/rendering/StringContext.hpp>
+#include <com/sun/star/rendering/XCanvasFont.hpp>
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/rendering/XGraphicDevice.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+class ::com::sun::star::rendering::XCanvasFont;
+
+namespace Gdiplus { class Graphics; }
+
+namespace dxcanvas
+{
+ struct Bitmap;
+ class TextLayoutDrawHelper
+ {
+ public:
+ TextLayoutDrawHelper(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice);
+ ~TextLayoutDrawHelper();
+
+ // draw text
+ void drawText( const boost::shared_ptr<Gdiplus::Graphics>& rGraphics,
+ const ::com::sun::star::rendering::ViewState& rViewState,
+ const ::com::sun::star::rendering::RenderState& rRenderState,
+ const ::basegfx::B2ISize& rOutputOffset,
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
+ bool bAlphaSurface );
+
+ ::com::sun::star::geometry::RealRectangle2D queryTextBounds(
+ const ::com::sun::star::rendering::StringContext& rText,
+ const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
+ const ::com::sun::star::geometry::Matrix2D& rFontMatrix );
+
+#ifdef DBG_UTIL
+ void test();
+#endif
+
+ protected:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XGraphicDevice > mxGraphicDevice;
+ };
+}
+
+#endif /* _TEXTLAYOUT_DRAWHELPER_HXX */
+// eof
diff --git a/canvas/source/directx/dx_vcltools.cxx b/canvas/source/directx/dx_vcltools.cxx
new file mode 100755
index 000000000000..e4d8ac04d5ba
--- /dev/null
+++ b/canvas/source/directx/dx_vcltools.cxx
@@ -0,0 +1,526 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_vcltools.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_canvas.hxx"
+
+#include <vcl/canvastools.hxx>
+
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/bmpacc.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "dx_impltools.hxx"
+#include <basegfx/numeric/ftools.hxx>
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+
+#include <boost/scoped_array.hpp>
+
+#include "dx_vcltools.hxx"
+
+using namespace ::com::sun::star;
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ namespace
+ {
+ /// Calc number of colors in given BitmapInfoHeader
+ sal_Int32 calcDIBColorCount( const BITMAPINFOHEADER& rBIH )
+ {
+ if( rBIH.biSize != sizeof( BITMAPCOREHEADER ) )
+ {
+ if( rBIH.biBitCount <= 8 )
+ {
+ if( rBIH.biClrUsed )
+ return rBIH.biClrUsed;
+ else
+ return 1L << rBIH.biBitCount;
+ }
+ }
+ else
+ {
+ BITMAPCOREHEADER* pCoreHeader = (BITMAPCOREHEADER*)&rBIH;
+
+ if( pCoreHeader->bcBitCount <= 8 )
+ return 1L << pCoreHeader->bcBitCount;
+ }
+
+ return 0; // nothing known
+ }
+
+ /// Draw DI bits to given Graphics
+ bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const void* hDIB )
+ {
+ bool bRet( false );
+ BitmapSharedPtr pBitmap;
+
+ const BITMAPINFO* pBI = (BITMAPINFO*)GlobalLock( (HGLOBAL)hDIB );
+
+ if( pBI )
+ {
+ const BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)pBI;
+ const BYTE* pBits = (BYTE*) pBI + *(DWORD*)pBI +
+ calcDIBColorCount( *pBIH ) * sizeof( RGBQUAD );
+
+ // forward to outsourced GDI+ rendering method
+ // (header clashes)
+ bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
+
+ GlobalUnlock( (HGLOBAL)hDIB );
+ }
+
+ return bRet;
+ }
+
+ /** Draw VCL bitmap to given Graphics
+
+ @param rBmp
+ Reference to bitmap. Might get modified, in such a way
+ that it will hold a DIB after a successful function call.
+ */
+ bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ ::Bitmap& rBmp )
+ {
+ BitmapSystemData aBmpSysData;
+
+ if( !rBmp.GetSystemData( aBmpSysData ) ||
+ !aBmpSysData.pDIB )
+ {
+ // first of all, ensure that Bitmap contains a DIB, by
+ // aquiring a read access
+ BitmapReadAccess* pReadAcc = rBmp.AcquireReadAccess();
+
+ // TODO(P2): Acquiring a read access can actually
+ // force a read from VRAM, thus, avoiding this
+ // step somehow will increase performance
+ // here.
+ if( pReadAcc )
+ {
+ // try again: now, WinSalBitmap must have
+ // generated a DIB
+ if( rBmp.GetSystemData( aBmpSysData ) &&
+ aBmpSysData.pDIB )
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ rBmp.ReleaseAccess( pReadAcc );
+ }
+ }
+ else
+ {
+ return drawDIBits( rGraphics,
+ aBmpSysData.pDIB );
+ }
+
+ // failed to generate DIBits from vcl bitmap
+ return false;
+ }
+
+ /** Create a chunk of raw RGBA data GDI+ Bitmap from VCL BbitmapEX
+ */
+ RawRGBABitmap bitmapFromVCLBitmapEx( const ::BitmapEx& rBmpEx )
+ {
+ // TODO(P2): Avoid temporary bitmap generation, maybe
+ // even ensure that created DIBs are copied back to
+ // BmpEx (currently, every AcquireReadAccess() will
+ // make the local bitmap copy unique, effectively
+ // duplicating the memory used)
+
+ ENSURE_OR_THROW( rBmpEx.IsTransparent(),
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "BmpEx not transparent" );
+
+ // convert transparent bitmap to 32bit RGBA
+ // ========================================
+
+ const ::Size aBmpSize( rBmpEx.GetSizePixel() );
+
+ RawRGBABitmap aBmpData;
+ aBmpData.mnWidth = aBmpSize.Width();
+ aBmpData.mnHeight = aBmpSize.Height();
+ aBmpData.mpBitmapData.reset( new sal_uInt8[ 4*aBmpData.mnWidth*aBmpData.mnHeight ] );
+
+ Bitmap aBitmap( rBmpEx.GetBitmap() );
+
+ ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(),
+ aBitmap );
+
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+
+ ENSURE_OR_THROW( pReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to bitmap" );
+
+ if( rBmpEx.IsAlpha() )
+ {
+ Bitmap aAlpha( rBmpEx.GetAlpha().GetBitmap() );
+
+ ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.AcquireReadAccess(),
+ aAlpha );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pAlphaReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to alpha" );
+
+ ENSURE_OR_THROW( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
+ pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported alpha scanline format" );
+
+ BitmapColor aCol;
+ const sal_Int32 nWidth( aBmpSize.Width() );
+ const sal_Int32 nHeight( aBmpSize.Height() );
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ for( x=0; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pAScan = pAlphaReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ // out notion of alpha is
+ // different from the rest
+ // of the world's
+ *pCurrOutput++ = 255 - (BYTE)*pAScan++;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+ else
+ {
+ Bitmap aMask( rBmpEx.GetMask() );
+
+ ScopedBitmapReadAccess pMaskReadAccess( aMask.AcquireReadAccess(),
+ aMask );
+
+ // By convention, the access buffer always has
+ // one of the following formats:
+ //
+ // BMP_FORMAT_1BIT_MSB_PAL
+ // BMP_FORMAT_4BIT_MSN_PAL
+ // BMP_FORMAT_8BIT_PAL
+ // BMP_FORMAT_16BIT_TC_LSB_MASK
+ // BMP_FORMAT_24BIT_TC_BGR
+ // BMP_FORMAT_32BIT_TC_MASK
+ //
+ // and is always BMP_FORMAT_BOTTOM_UP
+ //
+ // This is the way
+ // WinSalBitmap::AcquireBuffer() sets up the
+ // buffer
+
+ ENSURE_OR_THROW( pMaskReadAccess.get() != NULL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unable to acquire read acces to mask" );
+
+ ENSURE_OR_THROW( pMaskReadAccess->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unsupported mask scanline format" );
+
+ BitmapColor aCol;
+ int nCurrBit;
+ const int nMask( 1L );
+ const int nInitialBit(7);
+ sal_uInt8* pCurrOutput( aBmpData.mpBitmapData.get() );
+ int x, y;
+
+ // mapping table, to get from mask index color to
+ // alpha value (which depends on the mask's palette)
+ sal_uInt8 aColorMap[2];
+
+ const BitmapColor& rCol0( pMaskReadAccess->GetPaletteColor( 0 ) );
+ const BitmapColor& rCol1( pMaskReadAccess->GetPaletteColor( 1 ) );
+
+ // shortcut for true luminance calculation
+ // (assumes that palette is grey-level). Note the
+ // swapped the indices here, to account for the
+ // fact that VCL's notion of alpha is inverted to
+ // the rest of the world's.
+ aColorMap[0] = rCol1.GetRed();
+ aColorMap[1] = rCol0.GetRed();
+
+ for( y=0; y<nHeight; ++y )
+ {
+ switch( pReadAccess->GetScanlineFormat() )
+ {
+ case BMP_FORMAT_8BIT_PAL:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ aCol = pReadAccess->GetPaletteColor( *pScan++ );
+
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ Scanline pScan = pReadAccess->GetScanline( y );
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // store as RGBA
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+ *pCurrOutput++ = *pScan++;
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ // TODO(P2): Might be advantageous
+ // to hand-formulate the following
+ // formats, too.
+ case BMP_FORMAT_1BIT_MSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_MSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_LSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_MASK:
+ {
+ Scanline pMScan = pMaskReadAccess->GetScanline( y );
+
+ // using fallback for those
+ // seldom formats
+ for( x=0, nCurrBit=nInitialBit; x<nWidth; ++x )
+ {
+ // yes. x and y are swapped on Get/SetPixel
+ aCol = pReadAccess->GetColor(y,x);
+
+ // store as RGBA
+ *pCurrOutput++ = aCol.GetBlue();
+ *pCurrOutput++ = aCol.GetGreen();
+ *pCurrOutput++ = aCol.GetRed();
+
+ *pCurrOutput++ = aColorMap[ (pMScan[ (x & ~7L) >> 3L ] >> nCurrBit ) & nMask ];
+ nCurrBit = ((nCurrBit - 1) % 8L) & 7L;
+ }
+ }
+ break;
+
+ case BMP_FORMAT_1BIT_LSB_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_4BIT_LSN_PAL:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_8BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_RGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_24BIT_TC_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_16BIT_TC_MSB_MASK:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ABGR:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_ARGB:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_BGRA:
+ // FALLTHROUGH intended
+ case BMP_FORMAT_32BIT_TC_RGBA:
+ // FALLTHROUGH intended
+ default:
+ ENSURE_OR_THROW( false,
+ "::dxcanvas::tools::bitmapFromVCLBitmapEx(): "
+ "Unexpected scanline format - has "
+ "WinSalBitmap::AcquireBuffer() changed?" );
+ }
+ }
+ }
+
+ return aBmpData;
+ }
+
+ bool drawVCLBitmapEx( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const ::BitmapEx& rBmpEx )
+ {
+ if( !rBmpEx.IsTransparent() )
+ {
+ Bitmap aBmp( rBmpEx.GetBitmap() );
+ return drawVCLBitmap( rGraphics, aBmp );
+ }
+ else
+ {
+ return drawRGBABits( rGraphics,
+ bitmapFromVCLBitmapEx( rBmpEx ) );
+ }
+ }
+ }
+
+ bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const uno::Reference< rendering::XBitmap >& xBitmap )
+ {
+ // TODO(F2): add support for floating point bitmap formats
+ uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
+ xBitmap, uno::UNO_QUERY );
+
+ if( !xIntBmp.is() )
+ return false;
+
+ ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
+ if( !aBmpEx )
+ return false;
+
+ return drawVCLBitmapEx( rGraphics, aBmpEx );
+ }
+ }
+}
diff --git a/canvas/source/directx/dx_vcltools.hxx b/canvas/source/directx/dx_vcltools.hxx
new file mode 100755
index 000000000000..c3566951d46a
--- /dev/null
+++ b/canvas/source/directx/dx_vcltools.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_vcltools.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_VCLTOOLS_HXX
+#define _DXCANVAS_VCLTOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/util/TriState.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+
+namespace com { namespace sun { namespace star { namespace lang
+{
+ class XUnoTunnel;
+} } } }
+
+namespace Gdiplus { class Graphics; }
+
+namespace dxcanvas
+{
+ namespace tools
+ {
+ /** Raw RGBA bitmap data,
+ contiguous in memory
+ */
+ struct RawRGBABitmap
+ {
+ sal_Int32 mnWidth;
+ sal_Int32 mnHeight;
+ ::boost::shared_ptr< sal_uInt8 > mpBitmapData;
+ };
+
+ bool drawVCLBitmapFromXBitmap( const ::boost::shared_ptr< Gdiplus::Graphics >& rGraphics,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap >& xBitmap );
+ }
+}
+
+#endif /* _DXCANVAS_VCLTOOLS_HXX */
diff --git a/canvas/source/directx/dx_winstuff.hxx b/canvas/source/directx/dx_winstuff.hxx
new file mode 100755
index 000000000000..1c64506c0f21
--- /dev/null
+++ b/canvas/source/directx/dx_winstuff.hxx
@@ -0,0 +1,222 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: dx_winstuff.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DXCANVAS_WINSTUFF_HXX
+#define _DXCANVAS_WINSTUFF_HXX
+
+#include <algorithm>
+
+#include <boost/shared_ptr.hpp>
+
+#include <basegfx/numeric/ftools.hxx>
+
+#ifdef _WINDOWS_
+#error someone else included <windows.h>
+#endif
+
+// Enabling Direct3D Debug Information Further more, with registry key
+// \\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Direct3D\D3D9Debugging\\EnableCreationStack
+// set to 1, sets a backtrace each time an object is created to the
+// following global variable: LPCWSTR CreationCallStack
+#if OSL_DEBUG_LEVEL > 0
+# define D3D_DEBUG_INFO
+#endif
+
+#ifndef DIRECTX_VERSION
+#error please define for which directx version we should compile
+#endif
+
+#if defined _MSC_VER
+#pragma warning(push,1)
+#endif
+
+
+#define BOOL win32BOOL
+#define INT32 win32INT32
+#define UINT32 win32UINT32
+#define GradientStyle_RECT win32GradientStyle_RECT
+#define Polygon win32Polygon
+#define PolyPolygon win32PolyPolygon
+#undef WB_LEFT
+#undef WB_RIGHT
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h> // TODO(Q1): extract minimal set of required headers for gdiplus
+
+#if DIRECTX_VERSION < 0x0900
+
+ #include <multimon.h>
+
+ // Be compatible with directdraw 3.0. Lets see how far this takes us
+ #define DIRECTDRAW_VERSION 0x0300
+ #include <ddraw.h>
+
+ // Be compatible with direct3d 5.0. Lets see how far this takes us
+ #define DIRECT3D_VERSION 0x0500
+ #define D3D_OVERLOADS
+ #include <d3d.h>
+
+ typedef IDirectDrawSurface surface_type;
+
+#else
+
+ #include <d3d9.h>
+ #include <d3dx9.h>
+ #include <dxerr9.h>
+
+ typedef IDirect3DSurface9 surface_type;
+
+#endif
+
+#undef DrawText
+
+#ifdef __MINGW32__
+using ::std::max;
+using ::std::min;
+#endif
+
+#include <gdiplus.h>
+
+#ifdef min
+# undef min
+#endif
+#ifdef max
+# undef max
+#endif
+
+namespace dxcanvas
+{
+ // some shared pointer typedefs to Gdiplus objects
+ typedef ::boost::shared_ptr< Gdiplus::Graphics > GraphicsSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::GraphicsPath > GraphicsPathSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Bitmap > BitmapSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::CachedBitmap > CachedBitmapSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Font > FontSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::Brush > BrushSharedPtr;
+ typedef ::boost::shared_ptr< Gdiplus::TextureBrush > TextureBrushSharedPtr;
+
+ /** COM object RAII wrapper
+
+ This template wraps a Windows COM object, transparently
+ handling lifetime issues the C++ way (i.e. releasing the
+ reference when the object is destroyed)
+ */
+ template< typename T > class COMReference
+ {
+ public:
+ typedef T Wrappee;
+
+ COMReference() :
+ mp( NULL )
+ {
+ }
+
+ /** Create from raw pointer
+
+ @attention This constructor assumes the interface is
+ already acquired (unless p is NULL), no additional AddRef
+ is called here.
+
+ This caters e.g. for all DirectX factory methods, which
+ return the created interfaces pre-acquired, into a raw
+ pointer. Simply pass the pointer to this class, but don't
+ call Release manually on it!
+
+ @example IDirectDrawSurface* pSurface;
+ pDD->CreateSurface(&aSurfaceDesc, &pSurface, NULL);
+ mpSurface = COMReference< IDirectDrawSurface >(pSurface);
+
+ */
+ explicit COMReference( T* p ) :
+ mp( p )
+ {
+ }
+
+ COMReference( const COMReference& rNew ) :
+ mp( NULL )
+ {
+ if( rNew.mp == NULL )
+ return;
+
+ rNew.mp->AddRef(); // do that _before_ assigning the
+ // pointer. Just in case...
+ mp = rNew.mp;
+ }
+
+ COMReference& operator=( const COMReference& rRHS )
+ {
+ COMReference aTmp(rRHS);
+ ::std::swap( mp, aTmp.mp );
+
+ return *this;
+ }
+
+ ~COMReference()
+ {
+ reset();
+ }
+
+ int reset()
+ {
+ int refcount = 0;
+ if( mp )
+ refcount = mp->Release();
+
+ mp = NULL;
+ return refcount;
+ }
+
+ bool is() const { return mp != NULL; }
+ T* get() const { return mp; }
+ T* operator->() const { return mp; }
+ T& operator*() const { return *mp; }
+
+ private:
+ T* mp;
+ };
+
+ // get_pointer() enables boost::mem_fn to recognize COMReference
+ template<class T> inline T * get_pointer(COMReference<T> const& p)
+ {
+ return p.get();
+ }
+}
+
+#if defined _MSC_VER
+#pragma warning(pop)
+#endif
+
+#undef DELETE
+#undef BOOL
+#undef INT32
+#undef UINT32
+#undef PolyPolygon
+
+#endif /* _DXCANVAS_WINSTUFF_HXX */
diff --git a/canvas/source/directx/exports.dxp b/canvas/source/directx/exports.dxp
new file mode 100644
index 000000000000..9630d7e06768
--- /dev/null
+++ b/canvas/source/directx/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory
diff --git a/canvas/source/directx/makefile.mk b/canvas/source/directx/makefile.mk
new file mode 100644
index 000000000000..1a9db2ec51c0
--- /dev/null
+++ b/canvas/source/directx/makefile.mk
@@ -0,0 +1,223 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.9 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=canvas
+TARGET=directx9canvas
+TARGET2=directx5canvas
+TARGET3=gdipluscanvas
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+DLLPRE =
+
+# --- Nothing to do if we're compiling with --disable-directx -----------
+.IF "$(ENABLE_DIRECTX)" == ""
+@all:
+ @echo "Building without DirectX support..."
+.ENDIF
+
+
+# --- Common ----------------------------------------------------------
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+CDEFS+= -DDX_DEBUG_IMAGES
+.ENDIF
+
+# --- This is Windows only! { ----------------------------------------------------------------
+
+.IF "$(GUI)" == "WNT"
+
+SHARED_SLOFILES = \
+ $(SLO)$/dx_bitmap.obj \
+ $(SLO)$/dx_bitmapcanvashelper.obj \
+ $(SLO)$/dx_canvasbitmap.obj \
+ $(SLO)$/dx_canvasfont.obj \
+ $(SLO)$/dx_canvashelper.obj \
+ $(SLO)$/dx_canvashelper_texturefill.obj \
+ $(SLO)$/dx_devicehelper.obj \
+ $(SLO)$/dx_gdiplususer.obj \
+ $(SLO)$/dx_impltools.obj \
+ $(SLO)$/dx_linepolypolygon.obj \
+ $(SLO)$/dx_textlayout.obj \
+ $(SLO)$/dx_textlayout_drawhelper.obj \
+ $(SLO)$/dx_vcltools.obj
+
+DX_SLOFILES = \
+ $(SLO)$/dx_5rm.obj \
+ $(SLO)$/dx_9rm.obj \
+ $(SLO)$/dx_canvascustomsprite.obj \
+ $(SLO)$/dx_config.obj \
+ $(SLO)$/dx_spritecanvas.obj \
+ $(SLO)$/dx_spritecanvashelper.obj \
+ $(SLO)$/dx_spritedevicehelper.obj \
+ $(SLO)$/dx_spritehelper.obj \
+ $(SLO)$/dx_surfacebitmap.obj \
+ $(SLO)$/dx_surfacegraphics.obj
+DX_SLOFILES += $(SHARED_SLOFILES)
+
+GDIPLUS_SLOFILES = \
+ $(SLO)$/dx_canvas.obj
+GDIPLUS_SLOFILES += $(SHARED_SLOFILES)
+
+STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+
+
+########################################################
+# DX9
+########################################################
+
+# Indicates the source obj files for the dx5 lib
+LIB1TARGET= $(SLB)$/$(TARGET).lib
+LIB1OBJFILES = $(DX_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL1TARGET=$(TARGET).uno
+
+# Links import libraries.
+SHL1STDLIBS= $(STDLIBS)
+
+# Specifies an import library to create. For Win32 only.
+SHL1IMPLIB=i$(TARGET)
+
+# Specifies libraries from the same module to put into the shared library.
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+CDEFS+=-DDIRECTX_VERSION=0x0900
+
+SHL1STDLIBS += $(GDI32LIB)
+.IF "$(COM)" == "GCC"
+SHL1STDLIBS += $(DIRECTXSDK_LIB)/d3d9.lib
+.ELSE
+SHL1STDLIBS += d3d9.lib
+.ENDIF
+SHL1STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL1STDLIBS += imdebug.lib
+.ENDIF
+
+
+########################################################
+# DX5
+########################################################
+
+.IF "$(USE_DIRECTX5)" != ""
+SECOND_BUILD=DX5
+DX5_SLOFILES=$(DX_SLOFILES)
+DX5CDEFS += -DDIRECTX_VERSION=0x0500
+
+LIB2TARGET= $(SLB)$/$(TARGET2).lib
+LIB2OBJFILES = $(REAL_DX5_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL2TARGET=$(TARGET2).uno
+
+# Links import libraries.
+SHL2STDLIBS= $(STDLIBS)
+
+# Specifies an import library to create. For Win32 only.
+SHL2IMPLIB=i$(TARGET2).lib
+
+# Specifies libraries from the same module to put into the shared library.
+SHL2LIBS=$(SLB)$/$(TARGET2).lib
+SHL2DEF=$(MISC)$/$(SHL2TARGET).def
+
+DEF2NAME=$(SHL2TARGET)
+DEF2EXPORTFILE=exports.dxp
+
+SHL2STDLIBS += $(GDI32LIB)
+SHL2STDLIBS += $(DDRAWLIB)
+SHL2STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(COM)" == "GCC"
+SHL2STDLIBS += $(DIRECTXSDK_LIB)/d3dx.lib
+.ELSE
+SHL2STDLIBS += d3dx.lib
+.ENDIF
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL2STDLIBS += imdebug.lib
+.ENDIF
+.ENDIF # IF "$(USE_DIRECTX5)" != ""
+
+
+########################################################
+# GDI+
+########################################################
+
+LIB3TARGET= $(SLB)$/$(TARGET3).lib
+LIB3OBJFILES = $(GDIPLUS_SLOFILES)
+
+# Indicates the filename of the shared library.
+SHL3TARGET=$(TARGET3).uno
+
+# Links import libraries.
+SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+
+# Specifies an import library to create. For Win32 only.
+SHL3IMPLIB=i$(TARGET3).lib
+
+# Specifies libraries from the same module to put into the shared library.
+SHL3LIBS=$(SLB)$/$(TARGET3).lib
+SHL3DEF=$(MISC)$/$(SHL3TARGET).def
+
+DEF3NAME=$(SHL3TARGET)
+DEF3EXPORTFILE=exports.dxp
+
+SHL3STDLIBS += $(GDI32LIB)
+SHL3STDLIBS += $(GDIPLUSLIB)
+
+.IF "$(dx_debug_images)"!="" || "$(DX_DEBUG_IMAGES)"!=""
+SHL3STDLIBS += imdebug.lib
+.ENDIF
+
+.ENDIF # IF "$(GUI)" == "WNT"
+
+# --- This is Windows only! } ----------------------------------------------------------------
+
+# ==========================================================================
+
+.INCLUDE : target.mk
+