1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_canvas.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <canvas/debug.hxx> 32*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #include <com/sun/star/util/Endianness.hpp> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include <rtl/logfile.hxx> 37*cdf0e10cSrcweir #include <rtl/math.hxx> 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir #include <tools/poly.hxx> 40*cdf0e10cSrcweir #include <vcl/window.hxx> 41*cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 42*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 43*cdf0e10cSrcweir #include <vcl/canvastools.hxx> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 46*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 47*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 48*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx> 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include <canvas/canvastools.hxx> 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #include "canvasbitmap.hxx" 53*cdf0e10cSrcweir #include "canvasbitmaphelper.hxx" 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir using namespace ::com::sun::star; 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir namespace vclcanvas 59*cdf0e10cSrcweir { 60*cdf0e10cSrcweir CanvasBitmapHelper::CanvasBitmapHelper() : 61*cdf0e10cSrcweir mpBackBuffer(), 62*cdf0e10cSrcweir mpOutDevReference() 63*cdf0e10cSrcweir { 64*cdf0e10cSrcweir } 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir void CanvasBitmapHelper::setBitmap( const BitmapEx& rBitmap ) 67*cdf0e10cSrcweir { 68*cdf0e10cSrcweir ENSURE_OR_THROW( mpOutDev, 69*cdf0e10cSrcweir "Invalid reference device" ); 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir mpBackBuffer.reset( new BitmapBackBuffer( rBitmap, 72*cdf0e10cSrcweir mpOutDev->getOutDev() ) ); 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir // tell canvas helper about the new target OutDev (don't 75*cdf0e10cSrcweir // protect state, it's our own VirDev, anyways) 76*cdf0e10cSrcweir setOutDev( mpBackBuffer, false ); 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir void CanvasBitmapHelper::init( const BitmapEx& rBitmap, 80*cdf0e10cSrcweir rendering::XGraphicDevice& rDevice, 81*cdf0e10cSrcweir const OutDevProviderSharedPtr& rOutDevReference ) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir mpOutDevReference = rOutDevReference; 84*cdf0e10cSrcweir mpBackBuffer.reset( new BitmapBackBuffer( rBitmap, rOutDevReference->getOutDev() )); 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir // forward new settings to base class (ref device, output 87*cdf0e10cSrcweir // surface, no protection (own backbuffer), alpha depends on 88*cdf0e10cSrcweir // whether BmpEx is transparent or not) 89*cdf0e10cSrcweir CanvasHelper::init( rDevice, 90*cdf0e10cSrcweir mpBackBuffer, 91*cdf0e10cSrcweir false, 92*cdf0e10cSrcweir rBitmap.IsTransparent() ); 93*cdf0e10cSrcweir } 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir void CanvasBitmapHelper::disposing() 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir mpBackBuffer.reset(); 98*cdf0e10cSrcweir mpOutDevReference.reset(); 99*cdf0e10cSrcweir 100*cdf0e10cSrcweir // forward to base class 101*cdf0e10cSrcweir CanvasHelper::disposing(); 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir 104*cdf0e10cSrcweir geometry::IntegerSize2D CanvasBitmapHelper::getSize() 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir if( !mpBackBuffer ) 107*cdf0e10cSrcweir return geometry::IntegerSize2D(); 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir return ::vcl::unotools::integerSize2DFromSize( mpBackBuffer->getBitmapSizePixel() ); 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir void CanvasBitmapHelper::clear() 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir // are we disposed? 115*cdf0e10cSrcweir if( mpBackBuffer ) 116*cdf0e10cSrcweir mpBackBuffer->clear(); // alpha vdev needs special treatment 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir uno::Reference< rendering::XBitmap > CanvasBitmapHelper::getScaledBitmap( const geometry::RealSize2D& newSize, 120*cdf0e10cSrcweir sal_Bool beFast ) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir ENSURE_OR_THROW( mpDevice, 123*cdf0e10cSrcweir "disposed CanvasHelper" ); 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getScaledBitmap()" ); 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir if( !mpBackBuffer || mpDevice ) 128*cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >(); // we're disposed 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir BitmapEx aRes( mpBackBuffer->getBitmapReference() ); 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir aRes.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize), 133*cdf0e10cSrcweir beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE ); 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >( 136*cdf0e10cSrcweir new CanvasBitmap( aRes, *mpDevice, mpOutDevReference ) ); 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasBitmapHelper::getData( rendering::IntegerBitmapLayout& rLayout, 140*cdf0e10cSrcweir const geometry::IntegerRectangle2D& rect ) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getData()" ); 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir if( !mpBackBuffer ) 145*cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); // we're disposed 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir rLayout = getMemoryLayout(); 148*cdf0e10cSrcweir Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() ); 149*cdf0e10cSrcweir Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() ); 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(), 152*cdf0e10cSrcweir aBitmap ); 153*cdf0e10cSrcweir ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ? 154*cdf0e10cSrcweir (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(), 155*cdf0e10cSrcweir aAlpha ); 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir ENSURE_OR_THROW( pReadAccess.get() != NULL, 158*cdf0e10cSrcweir "Could not acquire read access to bitmap" ); 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir // TODO(F1): Support more formats. 161*cdf0e10cSrcweir const Size aBmpSize( aBitmap.GetSizePixel() ); 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir rLayout.ScanLines = aBmpSize.Height(); 164*cdf0e10cSrcweir rLayout.ScanLineBytes = aBmpSize.Width()*4; 165*cdf0e10cSrcweir rLayout.ScanLineStride = rLayout.ScanLineBytes; 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir // for the time being, always return as BGRA 168*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes( 4*aBmpSize.Width()*aBmpSize.Height() ); 169*cdf0e10cSrcweir sal_Int8* pRes = aRes.getArray(); 170*cdf0e10cSrcweir 171*cdf0e10cSrcweir int nCurrPos(0); 172*cdf0e10cSrcweir for( int y=rect.Y1; 173*cdf0e10cSrcweir y<aBmpSize.Height() && y<rect.Y2; 174*cdf0e10cSrcweir ++y ) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir if( pAlphaReadAccess.get() != NULL ) 177*cdf0e10cSrcweir { 178*cdf0e10cSrcweir for( int x=rect.X1; 179*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 180*cdf0e10cSrcweir ++x ) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed(); 183*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen(); 184*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue(); 185*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pAlphaReadAccess->GetPixel( y, x ).GetIndex(); 186*cdf0e10cSrcweir } 187*cdf0e10cSrcweir } 188*cdf0e10cSrcweir else 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir for( int x=rect.X1; 191*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 192*cdf0e10cSrcweir ++x ) 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed(); 195*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen(); 196*cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue(); 197*cdf0e10cSrcweir pRes[ nCurrPos++ ] = sal_uInt8(255); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir return aRes; 203*cdf0e10cSrcweir } 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir void CanvasBitmapHelper::setData( const uno::Sequence< sal_Int8 >& data, 206*cdf0e10cSrcweir const rendering::IntegerBitmapLayout& rLayout, 207*cdf0e10cSrcweir const geometry::IntegerRectangle2D& rect ) 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setData()" ); 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir if( !mpBackBuffer ) 212*cdf0e10cSrcweir return; // we're disposed 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() ); 215*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride || 216*cdf0e10cSrcweir aRefLayout.ColorSpace != rLayout.ColorSpace || 217*cdf0e10cSrcweir aRefLayout.Palette != rLayout.Palette || 218*cdf0e10cSrcweir aRefLayout.IsMsbFirst != rLayout.IsMsbFirst, 219*cdf0e10cSrcweir "Mismatching memory layout" ); 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir // retrieve local copies from the BitmapEx, which are later 222*cdf0e10cSrcweir // stored back. Unfortunately, the BitmapEx does not permit 223*cdf0e10cSrcweir // in-place modifications, as they are necessary here. 224*cdf0e10cSrcweir Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() ); 225*cdf0e10cSrcweir Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() ); 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir bool bCopyBack( false ); // only copy something back, if we 228*cdf0e10cSrcweir // actually changed a pixel 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), 232*cdf0e10cSrcweir aBitmap ); 233*cdf0e10cSrcweir ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ? 234*cdf0e10cSrcweir (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(), 235*cdf0e10cSrcweir aAlpha ); 236*cdf0e10cSrcweir 237*cdf0e10cSrcweir if( pAlphaWriteAccess.get() ) 238*cdf0e10cSrcweir { 239*cdf0e10cSrcweir DBG_ASSERT( pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL || 240*cdf0e10cSrcweir pAlphaWriteAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK, 241*cdf0e10cSrcweir "non-8bit alpha not supported!" ); 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir ENSURE_OR_THROW( pWriteAccess.get() != NULL, 245*cdf0e10cSrcweir "Could not acquire write access to bitmap" ); 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir // TODO(F1): Support more formats. 248*cdf0e10cSrcweir const Size aBmpSize( aBitmap.GetSizePixel() ); 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir // for the time being, always read as BGRA 251*cdf0e10cSrcweir int x, y, nCurrPos(0); 252*cdf0e10cSrcweir for( y=rect.Y1; 253*cdf0e10cSrcweir y<aBmpSize.Height() && y<rect.Y2; 254*cdf0e10cSrcweir ++y ) 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir if( pAlphaWriteAccess.get() != NULL ) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir switch( pWriteAccess->GetScanlineFormat() ) 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir case BMP_FORMAT_8BIT_PAL: 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 263*cdf0e10cSrcweir Scanline pAScan = pAlphaWriteAccess->GetScanline( y ); 264*cdf0e10cSrcweir 265*cdf0e10cSrcweir for( x=rect.X1; 266*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 267*cdf0e10cSrcweir ++x ) 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex( 270*cdf0e10cSrcweir BitmapColor( data[ nCurrPos ], 271*cdf0e10cSrcweir data[ nCurrPos+1 ], 272*cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir nCurrPos += 3; 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir // cast to unsigned byte, for correct subtraction result 277*cdf0e10cSrcweir *pAScan++ = static_cast<sal_uInt8>(255 - 278*cdf0e10cSrcweir static_cast<sal_uInt8>(data[ nCurrPos++ ])); 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir } 281*cdf0e10cSrcweir break; 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_BGR: 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 286*cdf0e10cSrcweir Scanline pAScan = pAlphaWriteAccess->GetScanline( y ); 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir for( x=rect.X1; 289*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 290*cdf0e10cSrcweir ++x ) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 293*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 294*cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir nCurrPos += 3; 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir // cast to unsigned byte, for correct subtraction result 299*cdf0e10cSrcweir *pAScan++ = static_cast<sal_uInt8>(255 - 300*cdf0e10cSrcweir static_cast<sal_uInt8>(data[ nCurrPos++ ])); 301*cdf0e10cSrcweir } 302*cdf0e10cSrcweir } 303*cdf0e10cSrcweir break; 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_RGB: 306*cdf0e10cSrcweir { 307*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 308*cdf0e10cSrcweir Scanline pAScan = pAlphaWriteAccess->GetScanline( y ); 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir for( x=rect.X1; 311*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 312*cdf0e10cSrcweir ++x ) 313*cdf0e10cSrcweir { 314*cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 315*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 316*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir nCurrPos += 3; 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir // cast to unsigned byte, for correct subtraction result 321*cdf0e10cSrcweir *pAScan++ = static_cast<sal_uInt8>(255 - 322*cdf0e10cSrcweir static_cast<sal_uInt8>(data[ nCurrPos++ ])); 323*cdf0e10cSrcweir } 324*cdf0e10cSrcweir } 325*cdf0e10cSrcweir break; 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir default: 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir for( x=rect.X1; 330*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 331*cdf0e10cSrcweir ++x ) 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ], 334*cdf0e10cSrcweir data[ nCurrPos+1 ], 335*cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 336*cdf0e10cSrcweir nCurrPos += 3; 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir // cast to unsigned byte, for correct subtraction result 339*cdf0e10cSrcweir pAlphaWriteAccess->SetPixel( y, x, 340*cdf0e10cSrcweir BitmapColor( 341*cdf0e10cSrcweir static_cast<sal_uInt8>(255 - 342*cdf0e10cSrcweir static_cast<sal_uInt8>(data[ nCurrPos++ ])) ) ); 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir } 345*cdf0e10cSrcweir break; 346*cdf0e10cSrcweir } 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir else 349*cdf0e10cSrcweir { 350*cdf0e10cSrcweir // TODO(Q3): This is copy'n'pasted from 351*cdf0e10cSrcweir // canvashelper.cxx, unify! 352*cdf0e10cSrcweir switch( pWriteAccess->GetScanlineFormat() ) 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir case BMP_FORMAT_8BIT_PAL: 355*cdf0e10cSrcweir { 356*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 357*cdf0e10cSrcweir 358*cdf0e10cSrcweir for( x=rect.X1; 359*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 360*cdf0e10cSrcweir ++x ) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex( 363*cdf0e10cSrcweir BitmapColor( data[ nCurrPos ], 364*cdf0e10cSrcweir data[ nCurrPos+1 ], 365*cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir nCurrPos += 4; // skip three colors, _plus_ alpha 368*cdf0e10cSrcweir } 369*cdf0e10cSrcweir } 370*cdf0e10cSrcweir break; 371*cdf0e10cSrcweir 372*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_BGR: 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir for( x=rect.X1; 377*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 378*cdf0e10cSrcweir ++x ) 379*cdf0e10cSrcweir { 380*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 381*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 382*cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir nCurrPos += 4; // skip three colors, _plus_ alpha 385*cdf0e10cSrcweir } 386*cdf0e10cSrcweir } 387*cdf0e10cSrcweir break; 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_RGB: 390*cdf0e10cSrcweir { 391*cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 392*cdf0e10cSrcweir 393*cdf0e10cSrcweir for( x=rect.X1; 394*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 395*cdf0e10cSrcweir ++x ) 396*cdf0e10cSrcweir { 397*cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 398*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 399*cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir nCurrPos += 4; // skip three colors, _plus_ alpha 402*cdf0e10cSrcweir } 403*cdf0e10cSrcweir } 404*cdf0e10cSrcweir break; 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir default: 407*cdf0e10cSrcweir { 408*cdf0e10cSrcweir for( x=rect.X1; 409*cdf0e10cSrcweir x<aBmpSize.Width() && x<rect.X2; 410*cdf0e10cSrcweir ++x ) 411*cdf0e10cSrcweir { 412*cdf0e10cSrcweir pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ], 413*cdf0e10cSrcweir data[ nCurrPos+1 ], 414*cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 415*cdf0e10cSrcweir nCurrPos += 4; // skip three colors, _plus_ alpha 416*cdf0e10cSrcweir } 417*cdf0e10cSrcweir } 418*cdf0e10cSrcweir break; 419*cdf0e10cSrcweir } 420*cdf0e10cSrcweir } 421*cdf0e10cSrcweir 422*cdf0e10cSrcweir bCopyBack = true; 423*cdf0e10cSrcweir } 424*cdf0e10cSrcweir } 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir // copy back only here, since the BitmapAccessors must be 427*cdf0e10cSrcweir // destroyed beforehand 428*cdf0e10cSrcweir if( bCopyBack ) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir if( aAlpha.IsEmpty() ) 431*cdf0e10cSrcweir setBitmap( BitmapEx( aBitmap ) ); 432*cdf0e10cSrcweir else 433*cdf0e10cSrcweir setBitmap( BitmapEx( aBitmap, 434*cdf0e10cSrcweir AlphaMask( aAlpha ) ) ); 435*cdf0e10cSrcweir } 436*cdf0e10cSrcweir } 437*cdf0e10cSrcweir 438*cdf0e10cSrcweir void CanvasBitmapHelper::setPixel( const uno::Sequence< sal_Int8 >& color, 439*cdf0e10cSrcweir const rendering::IntegerBitmapLayout& rLayout, 440*cdf0e10cSrcweir const geometry::IntegerPoint2D& pos ) 441*cdf0e10cSrcweir { 442*cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::setPixel()" ); 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir if( !mpBackBuffer ) 445*cdf0e10cSrcweir return; // we're disposed 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() ); 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(), 450*cdf0e10cSrcweir "X coordinate out of bounds" ); 451*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(), 452*cdf0e10cSrcweir "Y coordinate out of bounds" ); 453*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( color.getLength() > 3, 454*cdf0e10cSrcweir "not enough color components" ); 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() ); 457*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride || 458*cdf0e10cSrcweir aRefLayout.ColorSpace != rLayout.ColorSpace || 459*cdf0e10cSrcweir aRefLayout.Palette != rLayout.Palette || 460*cdf0e10cSrcweir aRefLayout.IsMsbFirst != rLayout.IsMsbFirst, 461*cdf0e10cSrcweir "Mismatching memory layout" ); 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir // retrieve local copies from the BitmapEx, which are later 464*cdf0e10cSrcweir // stored back. Unfortunately, the BitmapEx does not permit 465*cdf0e10cSrcweir // in-place modifications, as they are necessary here. 466*cdf0e10cSrcweir Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() ); 467*cdf0e10cSrcweir Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() ); 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir bool bCopyBack( false ); // only copy something back, if we 470*cdf0e10cSrcweir // actually changed a pixel 471*cdf0e10cSrcweir 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), 474*cdf0e10cSrcweir aBitmap ); 475*cdf0e10cSrcweir ScopedBitmapWriteAccess pAlphaWriteAccess( aAlpha.IsEmpty() ? 476*cdf0e10cSrcweir (BitmapWriteAccess*)NULL : aAlpha.AcquireWriteAccess(), 477*cdf0e10cSrcweir aAlpha ); 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir ENSURE_OR_THROW( pWriteAccess.get() != NULL, 480*cdf0e10cSrcweir "Could not acquire write access to bitmap" ); 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir pWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( color[ 0 ], 483*cdf0e10cSrcweir color[ 1 ], 484*cdf0e10cSrcweir color[ 2 ] ) ); 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir if( pAlphaWriteAccess.get() != NULL ) 487*cdf0e10cSrcweir pAlphaWriteAccess->SetPixel( pos.Y, pos.X, BitmapColor( 255 - color[ 3 ] ) ); 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir bCopyBack = true; 490*cdf0e10cSrcweir } 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir // copy back only here, since the BitmapAccessors must be 493*cdf0e10cSrcweir // destroyed beforehand 494*cdf0e10cSrcweir if( bCopyBack ) 495*cdf0e10cSrcweir { 496*cdf0e10cSrcweir if( aAlpha.IsEmpty() ) 497*cdf0e10cSrcweir setBitmap( BitmapEx( aBitmap ) ); 498*cdf0e10cSrcweir else 499*cdf0e10cSrcweir setBitmap( BitmapEx( aBitmap, 500*cdf0e10cSrcweir AlphaMask( aAlpha ) ) ); 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir } 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasBitmapHelper::getPixel( rendering::IntegerBitmapLayout& rLayout, 505*cdf0e10cSrcweir const geometry::IntegerPoint2D& pos ) 506*cdf0e10cSrcweir { 507*cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::CanvasBitmapHelper::getPixel()" ); 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir if( !mpBackBuffer ) 510*cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); // we're disposed 511*cdf0e10cSrcweir 512*cdf0e10cSrcweir rLayout = getMemoryLayout(); 513*cdf0e10cSrcweir rLayout.ScanLines = 1; 514*cdf0e10cSrcweir rLayout.ScanLineBytes = 4; 515*cdf0e10cSrcweir rLayout.ScanLineStride = rLayout.ScanLineBytes; 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir const Size aBmpSize( mpBackBuffer->getBitmapReference().GetSizePixel() ); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(), 520*cdf0e10cSrcweir "X coordinate out of bounds" ); 521*cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(), 522*cdf0e10cSrcweir "Y coordinate out of bounds" ); 523*cdf0e10cSrcweir 524*cdf0e10cSrcweir Bitmap aBitmap( mpBackBuffer->getBitmapReference().GetBitmap() ); 525*cdf0e10cSrcweir Bitmap aAlpha( mpBackBuffer->getBitmapReference().GetAlpha().GetBitmap() ); 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(), 528*cdf0e10cSrcweir aBitmap ); 529*cdf0e10cSrcweir ScopedBitmapReadAccess pAlphaReadAccess( aAlpha.IsEmpty() ? 530*cdf0e10cSrcweir (BitmapReadAccess*)NULL : aAlpha.AcquireReadAccess(), 531*cdf0e10cSrcweir aAlpha ); 532*cdf0e10cSrcweir ENSURE_OR_THROW( pReadAccess.get() != NULL, 533*cdf0e10cSrcweir "Could not acquire read access to bitmap" ); 534*cdf0e10cSrcweir 535*cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes( 4 ); 536*cdf0e10cSrcweir sal_Int8* pRes = aRes.getArray(); 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir const BitmapColor aColor( pReadAccess->GetColor( pos.Y, pos.X ) ); 539*cdf0e10cSrcweir pRes[ 0 ] = aColor.GetRed(); 540*cdf0e10cSrcweir pRes[ 1 ] = aColor.GetGreen(); 541*cdf0e10cSrcweir pRes[ 2 ] = aColor.GetBlue(); 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir if( pAlphaReadAccess.get() != NULL ) 544*cdf0e10cSrcweir pRes[ 3 ] = pAlphaReadAccess->GetPixel( pos.Y, pos.X ).GetIndex(); 545*cdf0e10cSrcweir else 546*cdf0e10cSrcweir pRes[ 3 ] = sal_uInt8(255); 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir return aRes; 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir rendering::IntegerBitmapLayout CanvasBitmapHelper::getMemoryLayout() 552*cdf0e10cSrcweir { 553*cdf0e10cSrcweir if( !mpOutDev.get() ) 554*cdf0e10cSrcweir return rendering::IntegerBitmapLayout(); // we're disposed 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir return ::canvas::tools::getStdMemoryLayout(getSize()); 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir BitmapEx CanvasBitmapHelper::getBitmap() const 560*cdf0e10cSrcweir { 561*cdf0e10cSrcweir if( !mpBackBuffer ) 562*cdf0e10cSrcweir return BitmapEx(); // we're disposed 563*cdf0e10cSrcweir else 564*cdf0e10cSrcweir return mpBackBuffer->getBitmapReference(); 565*cdf0e10cSrcweir } 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir } 568