xref: /trunk/main/canvas/source/directx/dx_surfacebitmap.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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