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