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