xref: /AOO41X/main/canvas/source/directx/dx_surfacebitmap.cxx (revision 25ea7f451e822ec0589487f23a9b6cc31f03fcc3)
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::__anon010351ed0111::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::__anon010351ed0111::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