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 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 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 92 BitmapSharedPtr DXBitmap::getBitmap() const 93 { 94 return mpBitmap; 95 } 96 97 GraphicsSharedPtr DXBitmap::getGraphics() 98 { 99 return mpGraphics; 100 } 101 102 ::basegfx::B2IVector DXBitmap::getSize() const 103 { 104 return maSize; 105 } 106 107 bool DXBitmap::hasAlpha() const 108 { 109 return mbAlpha; 110 } 111 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 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 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 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