blob: 9c440ce9d0f5e7dae5dcd749d4ca61a7fb09268e [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// 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
//////////////////////////////////////////////////////////////////////////////////
}