1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
30 
31 #include "dx_surfacebitmap.hxx"
32 #include "dx_impltools.hxx"
33 #include "dx_surfacegraphics.hxx"
34 #include "dx_graphicsprovider.hxx"
35 
36 #include <canvas/debug.hxx>
37 #include <tools/diagnose_ex.h>
38 
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <basegfx/range/b2irange.hxx>
41 
42 #if defined(DX_DEBUG_IMAGES)
43 # if OSL_DEBUG_LEVEL > 0
44 #  include <imdebug.h>
45 #  undef min
46 #  undef max
47 # endif
48 #endif
49 
50 using namespace ::com::sun::star;
51 
52 namespace dxcanvas
53 {
54 	namespace
55 	{
56 		//////////////////////////////////////////////////////////////////////////////////
57 		// DXColorBuffer
58 		//////////////////////////////////////////////////////////////////////////////////
59 
60 		struct DXColorBuffer : public canvas::IColorBuffer
61 		{
62         public:
63             DXColorBuffer( const COMReference<surface_type>& rSurface,
64 						   const ::basegfx::B2IVector&       rSize ) :
65                 mpSurface(rSurface),
66                 maSize(rSize),
67                 mbAlpha(false)
68             {
69             }
70 
71 		// implementation of the 'IColorBuffer' interface
72         public:
73 
74             virtual sal_uInt8* lock() const;
75             virtual void       unlock() const;
76             virtual sal_uInt32 getWidth() const;
77             virtual sal_uInt32 getHeight() const;
78             virtual sal_uInt32 getStride() const;
79             virtual Format     getFormat() const;
80 
81         private:
82 
83             ::basegfx::B2IVector maSize;
84 #if DIRECTX_VERSION < 0x0900
85 			mutable DDSURFACEDESC aSurfaceDesc;
86 #else
87 			mutable D3DLOCKED_RECT maLockedRect;
88 #endif
89 			mutable COMReference<surface_type> mpSurface;
90             bool mbAlpha;
91 		};
92 
93 		sal_uInt8* DXColorBuffer::lock() const
94 		{
95 #if DIRECTX_VERSION < 0x0900
96 			rtl_fillMemory((void *)&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
97 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
98 			const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
99 			if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
100 				return static_cast<sal_uInt8 *>(aSurfaceDesc.lpSurface);
101 #else
102 			if(SUCCEEDED(mpSurface->LockRect(&maLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
103 				return static_cast<sal_uInt8 *>(maLockedRect.pBits);
104 #endif
105 			return NULL;
106 		}
107 
108 		void DXColorBuffer::unlock() const
109 		{
110 #if DIRECTX_VERSION < 0x0900
111 			mpSurface->Unlock(NULL);
112 #else
113 			mpSurface->UnlockRect();
114 #endif
115 		}
116 
117 		sal_uInt32 DXColorBuffer::getWidth() const
118 		{
119 			return maSize.getX();
120 		}
121 
122 		sal_uInt32 DXColorBuffer::getHeight() const
123 		{
124 			return maSize.getY();
125 		}
126 
127 		sal_uInt32 DXColorBuffer::getStride() const
128 		{
129 #if DIRECTX_VERSION < 0x0900
130 			return aSurfaceDesc.lPitch;
131 #else
132 			return maLockedRect.Pitch;
133 #endif
134 		}
135 
136 		canvas::IColorBuffer::Format DXColorBuffer::getFormat() const
137 		{
138 			return canvas::IColorBuffer::FMT_X8R8G8B8;
139 		}
140 
141 		//////////////////////////////////////////////////////////////////////////////////
142 		// GDIColorBuffer
143 		//////////////////////////////////////////////////////////////////////////////////
144 
145 		struct GDIColorBuffer : public canvas::IColorBuffer
146 		{
147         public:
148 
149 			GDIColorBuffer( const BitmapSharedPtr&		rSurface,
150 							const ::basegfx::B2IVector& rSize ) :
151                 mpGDIPlusBitmap(rSurface),
152                 maSize(rSize),
153                 mbAlpha(true)
154             {
155             }
156 
157 		// implementation of the 'IColorBuffer' interface
158         public:
159 
160             virtual sal_uInt8* lock() const;
161             virtual void       unlock() const;
162             virtual sal_uInt32 getWidth() const;
163             virtual sal_uInt32 getHeight() const;
164             virtual sal_uInt32 getStride() const;
165             virtual Format     getFormat() const;
166 
167         private:
168 
169             ::basegfx::B2IVector maSize;
170             mutable Gdiplus::BitmapData aBmpData;
171 			BitmapSharedPtr mpGDIPlusBitmap;
172             bool mbAlpha;
173 		};
174 
175 		sal_uInt8* GDIColorBuffer::lock() const
176 		{
177             aBmpData.Width = maSize.getX();
178             aBmpData.Height = maSize.getY();
179             aBmpData.Stride = 4*aBmpData.Width;
180             aBmpData.PixelFormat = PixelFormat32bppARGB;
181             aBmpData.Scan0 = NULL;
182             const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
183             if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
184                                                           Gdiplus::ImageLockModeRead,
185                                                           PixelFormat32bppARGB,
186                                                           &aBmpData ) )
187             {
188                 return NULL;
189             }
190 
191 			return static_cast<sal_uInt8*>(aBmpData.Scan0);
192 		}
193 
194 		void GDIColorBuffer::unlock() const
195 		{
196             mpGDIPlusBitmap->UnlockBits( &aBmpData );
197 		}
198 
199 		sal_uInt32 GDIColorBuffer::getWidth() const
200 		{
201 			return maSize.getX();
202 		}
203 
204 		sal_uInt32 GDIColorBuffer::getHeight() const
205 		{
206 			return maSize.getY();
207 		}
208 
209 		sal_uInt32 GDIColorBuffer::getStride() const
210 		{
211 			return aBmpData.Stride;
212 		}
213 
214 		canvas::IColorBuffer::Format GDIColorBuffer::getFormat() const
215 		{
216 			return canvas::IColorBuffer::FMT_A8R8G8B8;
217 		}
218 	}
219 
220 	//////////////////////////////////////////////////////////////////////////////////
221 	// DXSurfaceBitmap::DXSurfaceBitmap
222 	//////////////////////////////////////////////////////////////////////////////////
223 
224 	DXSurfaceBitmap::DXSurfaceBitmap( const ::basegfx::B2IVector&					rSize,
225                                       const canvas::ISurfaceProxyManagerSharedPtr&	rMgr,
226                                       const IDXRenderModuleSharedPtr&				rRenderModule,
227                                       bool											bWithAlpha ) :
228         mpGdiPlusUser( GDIPlusUser::createInstance() ),
229         maSize(rSize),
230         mpRenderModule(rRenderModule),
231         mpSurfaceManager(rMgr),
232         mpSurfaceProxy(),
233         mpSurface(),
234 		mpGDIPlusBitmap(),
235         mpGraphics(),
236         mpColorBuffer(),
237         mbIsSurfaceDirty(true),
238         mbAlpha(bWithAlpha)
239 	{
240 		init();
241 	}
242 
243 	//////////////////////////////////////////////////////////////////////////////////
244 	// DXSurfaceBitmap::getSize
245 	//////////////////////////////////////////////////////////////////////////////////
246 
247     ::basegfx::B2IVector DXSurfaceBitmap::getSize() const
248     {
249         return maSize;
250     }
251 
252 	//////////////////////////////////////////////////////////////////////////////////
253 	// DXSurfaceBitmap::init
254 	//////////////////////////////////////////////////////////////////////////////////
255 
256 	void DXSurfaceBitmap::init()
257 	{
258 		// create container for pixel data
259 		if(mbAlpha)
260 		{
261 			mpGDIPlusBitmap.reset(
262 				new Gdiplus::Bitmap(
263 					maSize.getX(),
264 					maSize.getY(),
265 					PixelFormat32bppARGB
266 					));
267             mpGraphics.reset( tools::createGraphicsFromBitmap(mpGDIPlusBitmap) );
268 
269 			// create the colorbuffer object, which is basically a simple
270 			// wrapper around the directx surface. the colorbuffer is the
271 			// interface which is used by the surfaceproxy to support any
272 			// kind of underlying structure for the pixel data container.
273 			mpColorBuffer.reset(new GDIColorBuffer(mpGDIPlusBitmap,maSize));
274 		}
275 		else
276 		{
277 			mpSurface = mpRenderModule->createSystemMemorySurface(maSize);
278 
279 			// create the colorbuffer object, which is basically a simple
280 			// wrapper around the directx surface. the colorbuffer is the
281 			// interface which is used by the surfaceproxy to support any
282 			// kind of underlying structure for the pixel data container.
283 			mpColorBuffer.reset(new DXColorBuffer(mpSurface,maSize));
284 		}
285 
286 		// create a (possibly hardware accelerated) mirror surface.
287 		mpSurfaceProxy = mpSurfaceManager->createSurfaceProxy(mpColorBuffer);
288 	}
289 
290 	//////////////////////////////////////////////////////////////////////////////////
291 	// DXSurfaceBitmap::resize
292 	//////////////////////////////////////////////////////////////////////////////////
293 
294 	bool DXSurfaceBitmap::resize( const ::basegfx::B2IVector& rSize )
295 	{
296 		if(maSize != rSize)
297 		{
298 			maSize = rSize;
299 			init();
300 		}
301 
302 		return true;
303 	}
304 
305 	//////////////////////////////////////////////////////////////////////////////////
306 	// DXSurfaceBitmap::clear
307 	//////////////////////////////////////////////////////////////////////////////////
308 
309 	void DXSurfaceBitmap::clear()
310 	{
311 		GraphicsSharedPtr pGraphics(getGraphics());
312         Gdiplus::Color transColor(255,0,0,0);
313 		pGraphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy );
314 		pGraphics->Clear( transColor );
315 	}
316 
317 	//////////////////////////////////////////////////////////////////////////////////
318 	// DXSurfaceBitmap::hasAlpha
319 	//////////////////////////////////////////////////////////////////////////////////
320 
321 	bool DXSurfaceBitmap::hasAlpha() const
322 	{
323 		return mbAlpha;
324 	}
325 
326 	//////////////////////////////////////////////////////////////////////////////////
327 	// DXSurfaceBitmap::getGraphics
328 	//////////////////////////////////////////////////////////////////////////////////
329 
330 	GraphicsSharedPtr DXSurfaceBitmap::getGraphics()
331 	{
332 		// since clients will most probably draw directly
333 		// to the GDI+ bitmap, we need to mark it as dirty
334 		// to ensure that the corrosponding dxsurface will
335 		// be updated.
336 		mbIsSurfaceDirty = true;
337 
338 		if(hasAlpha())
339             return mpGraphics;
340         else
341             return createSurfaceGraphics(mpSurface);
342 	}
343 
344 	//////////////////////////////////////////////////////////////////////////////////
345 	// DXSurfaceBitmap::getBitmap
346 	//////////////////////////////////////////////////////////////////////////////////
347 
348 	BitmapSharedPtr DXSurfaceBitmap::getBitmap() const
349 	{
350 		if(hasAlpha())
351 			return mpGDIPlusBitmap;
352 
353 		BitmapSharedPtr pResult;
354 
355 #if DIRECTX_VERSION < 0x0900
356 		DDSURFACEDESC aSurfaceDesc;
357 		rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
358 		aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
359 		const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
360 
361 		// lock the directx surface to receive the pointer to the surface memory.
362 		if(SUCCEEDED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
363         {
364 			// decide about the format we pass the gdi+, the directx surface is always
365 			// 32bit, either with or without alpha component.
366 			Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
367 
368 			// construct a gdi+ bitmap from the raw pixel data.
369 			pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
370                                                aSurfaceDesc.lPitch,
371                                                nFormat,
372                                                (BYTE *)aSurfaceDesc.lpSurface ));
373 
374 			// unlock the directx surface
375 			mpSurface->Unlock(NULL);
376 		}
377 #else
378 		D3DLOCKED_RECT aLockedRect;
379 		if(SUCCEEDED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
380 		{
381 			// decide about the format we pass the gdi+, the directx surface is always
382 			// 32bit, either with or without alpha component.
383 			Gdiplus::PixelFormat nFormat = hasAlpha() ? PixelFormat32bppARGB : PixelFormat32bppRGB;
384 
385 			// construct a gdi+ bitmap from the raw pixel data.
386 			pResult.reset(new Gdiplus::Bitmap( maSize.getX(),maSize.getY(),
387 												aLockedRect.Pitch,
388 												nFormat,
389 												(BYTE *)aLockedRect.pBits ));
390 
391 			mpSurface->UnlockRect();
392 		}
393 #endif
394 
395 		return pResult;
396 	}
397 
398 	//////////////////////////////////////////////////////////////////////////////////
399 	// DXSurfaceBitmap::draw
400 	//////////////////////////////////////////////////////////////////////////////////
401 
402 	bool DXSurfaceBitmap::draw( double                           fAlpha,
403                                 const ::basegfx::B2DPoint&       rPos,
404                                 const ::basegfx::B2DPolyPolygon& rClipPoly,
405                                 const ::basegfx::B2DHomMatrix&   rTransform )
406     {
407         if( mbIsSurfaceDirty )
408         {
409             mpSurfaceProxy->setColorBufferDirty();
410             mbIsSurfaceDirty = false;
411         }
412 
413         return mpSurfaceProxy->draw( fAlpha, rPos, rClipPoly, rTransform );
414     }
415 
416 	//////////////////////////////////////////////////////////////////////////////////
417 	// DXSurfaceBitmap::draw
418 	//////////////////////////////////////////////////////////////////////////////////
419 
420 	bool DXSurfaceBitmap::draw( double                         fAlpha,
421                                 const ::basegfx::B2DPoint&     rPos,
422                                 const ::basegfx::B2DRange&     rArea,
423                                 const ::basegfx::B2DHomMatrix& rTransform )
424     {
425         if( mbIsSurfaceDirty )
426         {
427             mpSurfaceProxy->setColorBufferDirty();
428             mbIsSurfaceDirty = false;
429         }
430 
431         return mpSurfaceProxy->draw( fAlpha, rPos, rArea, rTransform );
432     }
433 
434 	//////////////////////////////////////////////////////////////////////////////////
435 	// DXSurfaceBitmap::draw
436 	//////////////////////////////////////////////////////////////////////////////////
437 
438 	bool DXSurfaceBitmap::draw( double                         fAlpha,
439                                 const ::basegfx::B2DPoint&     rPos,
440                                 const ::basegfx::B2DHomMatrix& rTransform )
441     {
442         if( mbIsSurfaceDirty )
443         {
444             mpSurfaceProxy->setColorBufferDirty();
445             mbIsSurfaceDirty = false;
446         }
447 
448         return mpSurfaceProxy->draw( fAlpha, rPos, rTransform );
449     }
450 
451 	//////////////////////////////////////////////////////////////////////////////////
452 	// DXSurfaceBitmap::draw
453 	//////////////////////////////////////////////////////////////////////////////////
454 
455 	bool DXSurfaceBitmap::draw( const ::basegfx::B2IRange& rArea )
456 	{
457         if( mbIsSurfaceDirty )
458         {
459             mpSurfaceProxy->setColorBufferDirty();
460             mbIsSurfaceDirty = false;
461         }
462 
463 		const double                  fAlpha(1.0);
464 		const ::basegfx::B2DHomMatrix aTransform;
465 		const ::basegfx::B2DRange     aIEEEArea( rArea );
466 		return mpSurfaceProxy->draw(fAlpha,
467                                     ::basegfx::B2DPoint(),
468                                     aIEEEArea,
469                                     aTransform);
470 	}
471 
472 	//////////////////////////////////////////////////////////////////////////////////
473 	// DXSurfaceBitmap::imageDebugger
474 	//////////////////////////////////////////////////////////////////////////////////
475 #if defined(DX_DEBUG_IMAGES)
476 # if OSL_DEBUG_LEVEL > 0
477 	void DXSurfaceBitmap::imageDebugger()
478 	{
479 #if DIRECTX_VERSION < 0x0900
480 		DDSURFACEDESC aSurfaceDesc;
481 		rtl_fillMemory( &aSurfaceDesc,sizeof(DDSURFACEDESC),0 );
482 		aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
483 
484 		if( FAILED(mpSurface->Lock( NULL,
485 									&aSurfaceDesc,
486 									DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY,
487 									NULL)) )
488 			return;
489 
490         imdebug("bgra w=%d h=%d %p", aSurfaceDesc.dwWidth, aSurfaceDesc.dwHeight, aSurfaceDesc.lpSurface);
491 
492         mpSurface->Unlock(NULL);
493 #else
494 		D3DLOCKED_RECT aLockedRect;
495 		if( FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)) )
496             return;
497 
498         imdebug("bgra w=%d h=%d %p", maSize.getX(),
499                 maSize.getY(), aLockedRect.pBits);
500         mpSurface->UnlockRect();
501 #endif
502 	}
503 # endif
504 #endif
505 
506 	//////////////////////////////////////////////////////////////////////////////////
507 	// DXSurfaceBitmap::getData
508 	//////////////////////////////////////////////////////////////////////////////////
509 
510     uno::Sequence< sal_Int8 > DXSurfaceBitmap::getData( rendering::IntegerBitmapLayout&     /*bitmapLayout*/,
511                                                         const geometry::IntegerRectangle2D& rect )
512     {
513 		if(hasAlpha())
514 		{
515 			uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
516 
517 			const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
518 
519 			Gdiplus::BitmapData aBmpData;
520 			aBmpData.Width		 = rect.X2-rect.X1;
521 			aBmpData.Height		 = rect.Y2-rect.Y1;
522 			aBmpData.Stride 	 = 4*aBmpData.Width;
523 			aBmpData.PixelFormat = PixelFormat32bppARGB;
524 			aBmpData.Scan0		 = aRes.getArray();
525 
526 			// TODO(F1): Support more pixel formats natively
527 
528 			// read data from bitmap
529 			if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
530 												Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
531 												PixelFormat32bppARGB, // TODO(F1): Adapt to
532                                                							// Graphics native
533 				                    									// format/change
534                 														// getMemoryLayout
535 												&aBmpData ) )
536 			{
537 				// failed to lock, bail out
538 				return uno::Sequence< sal_Int8 >();
539 			}
540 
541 			mpGDIPlusBitmap->UnlockBits( &aBmpData );
542 
543 			return aRes;
544 		}
545 		else
546 		{
547 			sal_uInt32 nWidth = rect.X2-rect.X1;
548 			sal_uInt32 nHeight = rect.Y2-rect.Y1;
549 
550 			uno::Sequence< sal_Int8 > aRes(nWidth*nHeight*4);
551 
552 #if DIRECTX_VERSION < 0x0900
553 			DDSURFACEDESC aSurfaceDesc;
554 			rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
555 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
556 			const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
557 
558 			// lock the directx surface to receive the pointer to the surface memory.
559 			if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
560 				return uno::Sequence< sal_Int8 >();
561 
562 			sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
563 			sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
564 			sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
565 			for(sal_uInt32 y=0; y<nHeight; ++y)
566 			{
567 				rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
568 				pDst += nSegmentSizeInBytes;
569 				pSrc += aSurfaceDesc.lPitch;
570 			}
571 
572 			mpSurface->Unlock(NULL);
573 #else
574 			D3DLOCKED_RECT aLockedRect;
575 			if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
576 				return uno::Sequence< sal_Int8 >();
577 
578 			sal_uInt8 *pSrc = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
579 			sal_uInt8 *pDst = (sal_uInt8 *)aRes.getArray();
580 			sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
581 			for(sal_uInt32 y=0; y<nHeight; ++y)
582 			{
583 				rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
584 				pDst += nSegmentSizeInBytes;
585 				pSrc += aLockedRect.Pitch;
586 			}
587 
588 			mpSurface->UnlockRect();
589 #endif
590 			return aRes;
591 		}
592     }
593 
594 	//////////////////////////////////////////////////////////////////////////////////
595 	// DXSurfaceBitmap::setData
596 	//////////////////////////////////////////////////////////////////////////////////
597 
598     void DXSurfaceBitmap::setData( const uno::Sequence< sal_Int8 >& 	 data,
599                                    const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
600                                    const geometry::IntegerRectangle2D& 	 rect )
601     {
602 		if(hasAlpha())
603 		{
604 			const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
605 
606 			Gdiplus::BitmapData aBmpData;
607 			aBmpData.Width		 = rect.X2-rect.X1;
608 			aBmpData.Height		 = rect.Y2-rect.Y1;
609 			aBmpData.Stride 	 = 4*aBmpData.Width;
610 			aBmpData.PixelFormat = PixelFormat32bppARGB;
611 			aBmpData.Scan0		 = (void*)data.getConstArray();
612 
613 			// TODO(F1): Support more pixel formats natively
614 
615 			if( Gdiplus::Ok != mpGDIPlusBitmap->LockBits( &aRect,
616 												Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
617 												PixelFormat32bppARGB, // TODO: Adapt to
618                                                							// Graphics native
619                                                   						// format/change
620                                                   						// getMemoryLayout
621 												&aBmpData ) )
622 			{
623 				throw uno::RuntimeException();
624 			}
625 
626 			// commit data to bitmap
627 			mpGDIPlusBitmap->UnlockBits( &aBmpData );
628 		}
629 		else
630 		{
631 			sal_uInt32 nWidth = rect.X2-rect.X1;
632 			sal_uInt32 nHeight = rect.Y2-rect.Y1;
633 
634 #if DIRECTX_VERSION < 0x0900
635 			DDSURFACEDESC aSurfaceDesc;
636 			rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
637 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
638 			const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
639 
640 			// lock the directx surface to receive the pointer to the surface memory.
641 			if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
642 				throw uno::RuntimeException();
643 
644 			sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
645 			sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aSurfaceDesc.lpSurface)+(rect.Y1*aSurfaceDesc.lPitch))+rect.X1);
646 			sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
647 			for(sal_uInt32 y=0; y<nHeight; ++y)
648 			{
649 				rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
650 				pSrc += nSegmentSizeInBytes;
651 				pDst += aSurfaceDesc.lPitch;
652 			}
653 
654 			mpSurface->Unlock(NULL);
655 #else
656 			// lock the directx surface to receive the pointer to the surface memory.
657 			D3DLOCKED_RECT aLockedRect;
658 			if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
659 				throw uno::RuntimeException();
660 
661 			sal_uInt8 *pSrc = (sal_uInt8 *)data.getConstArray();
662 			sal_uInt8 *pDst = (sal_uInt8 *)((((BYTE *)aLockedRect.pBits)+(rect.Y1*aLockedRect.Pitch))+rect.X1);
663 			sal_uInt32 nSegmentSizeInBytes = nWidth<<4;
664 			for(sal_uInt32 y=0; y<nHeight; ++y)
665 			{
666 				rtl_copyMemory(pDst,pSrc,nSegmentSizeInBytes);
667 				pSrc += nSegmentSizeInBytes;
668 				pDst += aLockedRect.Pitch;
669 			}
670 
671 			mpSurface->UnlockRect();
672 #endif
673 		}
674 
675         mbIsSurfaceDirty = true;
676     }
677 
678 	//////////////////////////////////////////////////////////////////////////////////
679 	// DXSurfaceBitmap::setPixel
680 	//////////////////////////////////////////////////////////////////////////////////
681 
682     void DXSurfaceBitmap::setPixel( const uno::Sequence< sal_Int8 >&      color,
683                                     const rendering::IntegerBitmapLayout& /*bitmapLayout*/,
684                                     const geometry::IntegerPoint2D&       pos )
685     {
686 		if(hasAlpha())
687 		{
688 			const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
689 
690 			ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
691 							"CanvasHelper::setPixel: X coordinate out of bounds" );
692 			ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
693 							"CanvasHelper::setPixel: Y coordinate out of bounds" );
694 			ENSURE_ARG_OR_THROW( color.getLength() > 3,
695 							"CanvasHelper::setPixel: not enough color components" );
696 
697 			if( Gdiplus::Ok != mpGDIPlusBitmap->SetPixel( pos.X, pos.Y,
698 												Gdiplus::Color( tools::sequenceToArgb( color ))))
699 			{
700 				throw uno::RuntimeException();
701 			}
702 		}
703 		else
704 		{
705 			ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
706 							"CanvasHelper::setPixel: X coordinate out of bounds" );
707 			ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
708 							"CanvasHelper::setPixel: Y coordinate out of bounds" );
709 			ENSURE_ARG_OR_THROW( color.getLength() > 3,
710 							"CanvasHelper::setPixel: not enough color components" );
711 
712 			Gdiplus::Color aColor(tools::sequenceToArgb(color));
713 
714 #if DIRECTX_VERSION < 0x0900
715 			DDSURFACEDESC aSurfaceDesc;
716 			rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
717 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
718 			const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_WRITEONLY;
719 
720 			// lock the directx surface to receive the pointer to the surface memory.
721 			if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
722 				throw uno::RuntimeException();
723 
724 			sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
725 			*pDst = aColor.GetValue();
726 			mpSurface->Unlock(NULL);
727 #else
728 			// lock the directx surface to receive the pointer to the surface memory.
729 			D3DLOCKED_RECT aLockedRect;
730 			if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
731 				throw uno::RuntimeException();
732 
733 			sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
734 			*pDst = aColor.GetValue();
735 			mpSurface->UnlockRect();
736 #endif
737 		}
738 
739         mbIsSurfaceDirty = true;
740     }
741 
742 	//////////////////////////////////////////////////////////////////////////////////
743 	// DXSurfaceBitmap::getPixel
744 	//////////////////////////////////////////////////////////////////////////////////
745 
746     uno::Sequence< sal_Int8 > DXSurfaceBitmap::getPixel( rendering::IntegerBitmapLayout&   /*bitmapLayout*/,
747                                                          const geometry::IntegerPoint2D&   pos )
748     {
749 		if(hasAlpha())
750 		{
751 			const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
752 
753 			ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
754 							"CanvasHelper::getPixel: X coordinate out of bounds" );
755 			ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
756 							"CanvasHelper::getPixel: Y coordinate out of bounds" );
757 
758 			Gdiplus::Color aColor;
759 
760 			if( Gdiplus::Ok != mpGDIPlusBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
761 				return uno::Sequence< sal_Int8 >();
762 
763 			return tools::argbToIntSequence(aColor.GetValue());
764 		}
765 		else
766 		{
767 			ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < maSize.getX(),
768 							"CanvasHelper::getPixel: X coordinate out of bounds" );
769 			ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < maSize.getY(),
770 							"CanvasHelper::getPixel: Y coordinate out of bounds" );
771 
772 #if DIRECTX_VERSION < 0x0900
773 			DDSURFACEDESC aSurfaceDesc;
774 			rtl_fillMemory(&aSurfaceDesc,sizeof(DDSURFACEDESC),0);
775 			aSurfaceDesc.dwSize = sizeof(DDSURFACEDESC);
776 			const DWORD dwFlags = DDLOCK_NOSYSLOCK|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY;
777 
778 			// lock the directx surface to receive the pointer to the surface memory.
779 			if(FAILED(mpSurface->Lock(NULL,&aSurfaceDesc,dwFlags,NULL)))
780 				throw uno::RuntimeException();
781 
782 			sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aSurfaceDesc.lpSurface)+(pos.Y*aSurfaceDesc.lPitch))+pos.X);
783 			Gdiplus::Color aColor(*pDst);
784 			mpSurface->Unlock(NULL);
785 #else
786 			// lock the directx surface to receive the pointer to the surface memory.
787 			D3DLOCKED_RECT aLockedRect;
788 			if(FAILED(mpSurface->LockRect(&aLockedRect,NULL,D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
789 				throw uno::RuntimeException();
790 
791 			sal_uInt32 *pDst = (sal_uInt32 *)((((BYTE *)aLockedRect.pBits)+(pos.Y*aLockedRect.Pitch))+pos.X);
792 			Gdiplus::Color aColor(*pDst);
793 			mpSurface->UnlockRect();
794 #endif
795 
796 			return tools::argbToIntSequence(aColor.GetValue());
797 		}
798     }
799 
800 	//////////////////////////////////////////////////////////////////////////////////
801 	// End of file
802 	//////////////////////////////////////////////////////////////////////////////////
803 }
804 
805