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_bitmap.hxx"
28 #include "dx_graphicsprovider.hxx"
29 #include "dx_impltools.hxx"
30 
31 #include <canvas/debug.hxx>
32 #include <tools/diagnose_ex.h>
33 
34 #include <basegfx/matrix/b2dhommatrix.hxx>
35 #include <basegfx/range/b2irange.hxx>
36 
37 #if defined(DX_DEBUG_IMAGES)
38 # if OSL_DEBUG_LEVEL > 0
39 #  include <imdebug.h>
40 #  undef min
41 #  undef max
42 # endif
43 #endif
44 
45 using namespace ::com::sun::star;
46 
47 namespace dxcanvas
48 {
49 	//////////////////////////////////////////////////////////////////////////////////
50 	// DXBitmap::DXBitmap
51 	//////////////////////////////////////////////////////////////////////////////////
52 
DXBitmap(const BitmapSharedPtr & rBitmap,bool bWithAlpha)53     DXBitmap::DXBitmap( const BitmapSharedPtr& rBitmap,
54                         bool				   bWithAlpha ) :
55         mpGdiPlusUser( GDIPlusUser::createInstance() ),
56         maSize(rBitmap->GetWidth(),rBitmap->GetHeight()),
57 		mpBitmap(rBitmap),
58         mpGraphics(tools::createGraphicsFromBitmap(mpBitmap)),
59         mbAlpha(bWithAlpha)
60     {
61     }
62 
DXBitmap(const::basegfx::B2IVector & rSize,bool bWithAlpha)63 	DXBitmap::DXBitmap( const ::basegfx::B2IVector& rSize,
64 						bool						bWithAlpha ) :
65         mpGdiPlusUser( GDIPlusUser::createInstance() ),
66         maSize(rSize),
67 		mpBitmap(),
68         mpGraphics(),
69         mbAlpha(bWithAlpha)
70 	{
71 		// create container for pixel data
72 		if(mbAlpha)
73 		{
74 			mpBitmap.reset(
75 				new Gdiplus::Bitmap(
76 					maSize.getX(),
77 					maSize.getY(),
78 					PixelFormat32bppARGB));
79 		}
80 		else
81 		{
82 			mpBitmap.reset(
83 				new Gdiplus::Bitmap(
84 					maSize.getX(),
85 					maSize.getY(),
86 					PixelFormat24bppRGB));
87 		}
88 
89         mpGraphics.reset( tools::createGraphicsFromBitmap(mpBitmap) );
90 	}
91 
getBitmap() const92     BitmapSharedPtr DXBitmap::getBitmap() const
93     {
94         return mpBitmap;
95     }
96 
getGraphics()97     GraphicsSharedPtr DXBitmap::getGraphics()
98     {
99         return mpGraphics;
100     }
101 
getSize() const102     ::basegfx::B2IVector DXBitmap::getSize() const
103     {
104         return maSize;
105     }
106 
hasAlpha() const107     bool DXBitmap::hasAlpha() const
108     {
109         return mbAlpha;
110     }
111 
getData(rendering::IntegerBitmapLayout &,const geometry::IntegerRectangle2D & rect)112     uno::Sequence< sal_Int8 > DXBitmap::getData( rendering::IntegerBitmapLayout&     /*bitmapLayout*/,
113                                                  const geometry::IntegerRectangle2D& rect )
114     {
115         uno::Sequence< sal_Int8 > aRes( (rect.X2-rect.X1)*(rect.Y2-rect.Y1)*4 ); // TODO(F1): Be format-agnostic here
116 
117         const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
118 
119         Gdiplus::BitmapData aBmpData;
120         aBmpData.Width		 = rect.X2-rect.X1;
121         aBmpData.Height		 = rect.Y2-rect.Y1;
122         aBmpData.Stride 	 = 4*aBmpData.Width;
123         aBmpData.PixelFormat = PixelFormat32bppARGB;
124         aBmpData.Scan0		 = aRes.getArray();
125 
126         // TODO(F1): Support more pixel formats natively
127 
128         // read data from bitmap
129         if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
130                                                       Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf,
131                                                       PixelFormat32bppARGB, // TODO(F1): Adapt to
132                                                       // Graphics native
133                                                       // format/change
134                                                       // getMemoryLayout
135                                                       &aBmpData ) )
136         {
137             // failed to lock, bail out
138             return uno::Sequence< sal_Int8 >();
139         }
140 
141         mpBitmap->UnlockBits( &aBmpData );
142 
143         return aRes;
144     }
145 
setData(const uno::Sequence<sal_Int8> & data,const rendering::IntegerBitmapLayout &,const geometry::IntegerRectangle2D & rect)146     void DXBitmap::setData( const uno::Sequence< sal_Int8 >& 		data,
147                             const rendering::IntegerBitmapLayout&   /*bitmapLayout*/,
148                             const geometry::IntegerRectangle2D& 	rect )
149     {
150         const Gdiplus::Rect aRect( tools::gdiPlusRectFromIntegerRectangle2D( rect ) );
151 
152         Gdiplus::BitmapData aBmpData;
153         aBmpData.Width		 = rect.X2-rect.X1;
154         aBmpData.Height		 = rect.Y2-rect.Y1;
155         aBmpData.Stride 	 = 4*aBmpData.Width;
156         aBmpData.PixelFormat = PixelFormat32bppARGB;
157         aBmpData.Scan0		 = (void*)data.getConstArray();
158 
159         // TODO(F1): Support more pixel formats natively
160 
161         if( Gdiplus::Ok != mpBitmap->LockBits( &aRect,
162                                                       Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
163                                                       PixelFormat32bppARGB, // TODO: Adapt to
164                                                       // Graphics native
165                                                       // format/change
166                                                       // getMemoryLayout
167                                                       &aBmpData ) )
168         {
169             throw uno::RuntimeException();
170         }
171 
172         // commit data to bitmap
173         mpBitmap->UnlockBits( &aBmpData );
174     }
175 
setPixel(const uno::Sequence<sal_Int8> & color,const rendering::IntegerBitmapLayout &,const geometry::IntegerPoint2D & pos)176     void DXBitmap::setPixel( const uno::Sequence< sal_Int8 >&       color,
177                              const rendering::IntegerBitmapLayout&  /*bitmapLayout*/,
178                              const geometry::IntegerPoint2D&        pos )
179     {
180         const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
181 
182         ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
183                              "CanvasHelper::setPixel: X coordinate out of bounds" );
184         ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
185                              "CanvasHelper::setPixel: Y coordinate out of bounds" );
186         ENSURE_ARG_OR_THROW( color.getLength() > 3,
187                              "CanvasHelper::setPixel: not enough color components" );
188 
189         if( Gdiplus::Ok != mpBitmap->SetPixel( pos.X, pos.Y,
190                                                       Gdiplus::Color( tools::sequenceToArgb( color ))))
191         {
192             throw uno::RuntimeException();
193         }
194     }
195 
getPixel(rendering::IntegerBitmapLayout &,const geometry::IntegerPoint2D & pos)196     uno::Sequence< sal_Int8 > DXBitmap::getPixel( rendering::IntegerBitmapLayout&   /*bitmapLayout*/,
197                                                   const geometry::IntegerPoint2D&   pos )
198     {
199         const geometry::IntegerSize2D aSize( maSize.getX(),maSize.getY() );
200 
201         ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aSize.Width,
202                              "CanvasHelper::getPixel: X coordinate out of bounds" );
203         ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aSize.Height,
204                              "CanvasHelper::getPixel: Y coordinate out of bounds" );
205 
206         Gdiplus::Color aColor;
207 
208         if( Gdiplus::Ok != mpBitmap->GetPixel( pos.X, pos.Y, &aColor ) )
209             return uno::Sequence< sal_Int8 >();
210 
211         return tools::argbToIntSequence(aColor.GetValue());
212     }
213 
214 }
215 
216