diff options
Diffstat (limited to 'vcl/source/helper')
-rw-r--r-- | vcl/source/helper/canvasbitmap.cxx | 1467 | ||||
-rw-r--r-- | vcl/source/helper/canvastools.cxx | 837 | ||||
-rw-r--r-- | vcl/source/helper/evntpost.cxx | 65 | ||||
-rw-r--r-- | vcl/source/helper/lazydelete.cxx | 125 | ||||
-rw-r--r-- | vcl/source/helper/makefile.mk | 56 | ||||
-rwxr-xr-x | vcl/source/helper/smartid.cxx | 264 | ||||
-rw-r--r-- | vcl/source/helper/strhelper.cxx | 442 | ||||
-rw-r--r-- | vcl/source/helper/threadex.cxx | 127 | ||||
-rw-r--r-- | vcl/source/helper/xconnection.cxx | 178 |
9 files changed, 3561 insertions, 0 deletions
diff --git a/vcl/source/helper/canvasbitmap.cxx b/vcl/source/helper/canvasbitmap.cxx new file mode 100644 index 000000000000..2bc0ab94d272 --- /dev/null +++ b/vcl/source/helper/canvasbitmap.cxx @@ -0,0 +1,1467 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <com/sun/star/util/Endianness.hpp> +#include <com/sun/star/rendering/ColorComponentTag.hpp> +#include <com/sun/star/rendering/ColorSpaceType.hpp> +#include <com/sun/star/rendering/RenderingIntent.hpp> + +#include <rtl/instance.hxx> +#include <vos/mutex.hxx> + +#include <tools/diagnose_ex.h> +#include <vcl/canvasbitmap.hxx> +#include <vcl/canvastools.hxx> +#include <vcl/bmpacc.hxx> +#include <vcl/svapp.hxx> + +#include <algorithm> + + +using namespace ::vcl::unotools; +using namespace ::com::sun::star; + +namespace +{ + // TODO(Q3): move to o3tl bithacks or somesuch. A similar method is in canvas/canvastools.hxx + + // Good ole HAKMEM tradition. Calc number of 1 bits in 32bit word, + // unrolled loop. See e.g. Hackers Delight, p. 66 + inline sal_Int32 bitcount( sal_uInt32 val ) + { + val = val - ((val >> 1) & 0x55555555); + val = (val & 0x33333333) + ((val >> 2) & 0x33333333); + val = (val + (val >> 4)) & 0x0F0F0F0F; + val = val + (val >> 8); + val = val + (val >> 16); + return sal_Int32(val & 0x0000003F); + } +} + +void VclCanvasBitmap::setComponentInfo( ULONG redShift, ULONG greenShift, ULONG blueShift ) +{ + // sort channels in increasing order of appearance in the pixel + // (starting with the least significant bits) + sal_Int8 redPos(0); + sal_Int8 greenPos(1); + sal_Int8 bluePos(2); + + if( redShift > greenShift ) + { + std::swap(redPos,greenPos); + if( redShift > blueShift ) + { + std::swap(redPos,bluePos); + if( greenShift > blueShift ) + std::swap(greenPos,bluePos); + } + } + else + { + if( greenShift > blueShift ) + { + std::swap(greenPos,bluePos); + if( redShift > blueShift ) + std::swap(redPos,bluePos); + } + } + + m_aComponentTags.realloc(3); + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[redPos] = rendering::ColorComponentTag::RGB_RED; + pTags[greenPos] = rendering::ColorComponentTag::RGB_GREEN; + pTags[bluePos] = rendering::ColorComponentTag::RGB_BLUE; + + m_aComponentBitCounts.realloc(3); + sal_Int32* pCounts = m_aComponentBitCounts.getArray(); + pCounts[redPos] = bitcount(sal::static_int_cast<sal_uInt32>(redShift)); + pCounts[greenPos] = bitcount(sal::static_int_cast<sal_uInt32>(greenShift)); + pCounts[bluePos] = bitcount(sal::static_int_cast<sal_uInt32>(blueShift)); +} + +VclCanvasBitmap::VclCanvasBitmap( const BitmapEx& rBitmap ) : + m_aBmpEx( rBitmap ), + m_aBitmap( rBitmap.GetBitmap() ), + m_aAlpha(), + m_pBmpAcc( m_aBitmap.AcquireReadAccess() ), + m_pAlphaAcc( NULL ), + m_aComponentTags(), + m_aComponentBitCounts(), + m_aLayout(), + m_nBitsPerInputPixel(0), + m_nBitsPerOutputPixel(0), + m_nRedIndex(-1), + m_nGreenIndex(-1), + m_nBlueIndex(-1), + m_nAlphaIndex(-1), + m_nIndexIndex(-1), + m_nEndianness(0), + m_bSwap(false), + m_bPalette(false) +{ + if( m_aBmpEx.IsTransparent() ) + { + m_aAlpha = m_aBmpEx.IsAlpha() ? m_aBmpEx.GetAlpha().GetBitmap() : m_aBmpEx.GetMask(); + m_pAlphaAcc = m_aAlpha.AcquireReadAccess(); + } + + m_aLayout.ScanLines = 0; + m_aLayout.ScanLineBytes = 0; + m_aLayout.ScanLineStride = 0; + m_aLayout.PlaneStride = 0; + m_aLayout.ColorSpace.clear(); + m_aLayout.Palette.clear(); + m_aLayout.IsMsbFirst = sal_False; + + if( m_pBmpAcc ) + { + m_aLayout.ScanLines = m_pBmpAcc->Height(); + m_aLayout.ScanLineBytes = (m_pBmpAcc->GetBitCount()*m_pBmpAcc->Width() + 7) / 8; + m_aLayout.ScanLineStride = m_pBmpAcc->GetScanlineSize(); + m_aLayout.PlaneStride = 0; + + switch( m_pBmpAcc->GetScanlineFormat() ) + { + case BMP_FORMAT_1BIT_MSB_PAL: + m_bPalette = true; + m_nBitsPerInputPixel = 1; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_True; + break; + + case BMP_FORMAT_1BIT_LSB_PAL: + m_bPalette = true; + m_nBitsPerInputPixel = 1; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_False; + break; + + case BMP_FORMAT_4BIT_MSN_PAL: + m_bPalette = true; + m_nBitsPerInputPixel = 4; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_True; + break; + + case BMP_FORMAT_4BIT_LSN_PAL: + m_bPalette = true; + m_nBitsPerInputPixel = 4; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_False; + break; + + case BMP_FORMAT_8BIT_PAL: + m_bPalette = true; + m_nBitsPerInputPixel = 8; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + break; + + case BMP_FORMAT_8BIT_TC_MASK: + m_bPalette = false; + m_nBitsPerInputPixel = 8; + m_nEndianness = util::Endianness::LITTLE; // doesn't matter + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(), + m_pBmpAcc->GetColorMask().GetGreenMask(), + m_pBmpAcc->GetColorMask().GetBlueMask() ); + break; + + case BMP_FORMAT_16BIT_TC_MSB_MASK: + m_bPalette = false; + m_nBitsPerInputPixel = 16; + m_nEndianness = util::Endianness::BIG; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(), + m_pBmpAcc->GetColorMask().GetGreenMask(), + m_pBmpAcc->GetColorMask().GetBlueMask() ); + break; + + case BMP_FORMAT_16BIT_TC_LSB_MASK: + m_bPalette = false; + m_nBitsPerInputPixel = 16; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(), + m_pBmpAcc->GetColorMask().GetGreenMask(), + m_pBmpAcc->GetColorMask().GetBlueMask() ); + break; + + case BMP_FORMAT_24BIT_TC_BGR: + m_bPalette = false; + m_nBitsPerInputPixel = 24; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( 0xff0000LL, + 0x00ff00LL, + 0x0000ffLL ); + break; + + case BMP_FORMAT_24BIT_TC_RGB: + m_bPalette = false; + m_nBitsPerInputPixel = 24; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( 0x0000ffLL, + 0x00ff00LL, + 0xff0000LL ); + break; + + case BMP_FORMAT_24BIT_TC_MASK: + m_bPalette = false; + m_nBitsPerInputPixel = 24; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(), + m_pBmpAcc->GetColorMask().GetGreenMask(), + m_pBmpAcc->GetColorMask().GetBlueMask() ); + break; + + case BMP_FORMAT_32BIT_TC_ABGR: + { + m_bPalette = false; + m_nBitsPerInputPixel = 32; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + + m_aComponentTags.realloc(4); + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[0] = rendering::ColorComponentTag::ALPHA; + pTags[1] = rendering::ColorComponentTag::RGB_BLUE; + pTags[2] = rendering::ColorComponentTag::RGB_GREEN; + pTags[3] = rendering::ColorComponentTag::RGB_RED; + + m_aComponentBitCounts.realloc(4); + sal_Int32* pCounts = m_aComponentBitCounts.getArray(); + pCounts[0] = 8; + pCounts[1] = 8; + pCounts[2] = 8; + pCounts[3] = 8; + + m_nRedIndex = 3; + m_nGreenIndex = 2; + m_nBlueIndex = 1; + m_nAlphaIndex = 0; + } + break; + + case BMP_FORMAT_32BIT_TC_ARGB: + { + m_bPalette = false; + m_nBitsPerInputPixel = 32; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + + m_aComponentTags.realloc(4); + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[0] = rendering::ColorComponentTag::ALPHA; + pTags[1] = rendering::ColorComponentTag::RGB_RED; + pTags[2] = rendering::ColorComponentTag::RGB_GREEN; + pTags[3] = rendering::ColorComponentTag::RGB_BLUE; + + m_aComponentBitCounts.realloc(4); + sal_Int32* pCounts = m_aComponentBitCounts.getArray(); + pCounts[0] = 8; + pCounts[1] = 8; + pCounts[2] = 8; + pCounts[3] = 8; + + m_nRedIndex = 1; + m_nGreenIndex = 2; + m_nBlueIndex = 3; + m_nAlphaIndex = 0; + } + break; + + case BMP_FORMAT_32BIT_TC_BGRA: + { + m_bPalette = false; + m_nBitsPerInputPixel = 32; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + + m_aComponentTags.realloc(4); + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_BLUE; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_RED; + pTags[3] = rendering::ColorComponentTag::ALPHA; + + m_aComponentBitCounts.realloc(4); + sal_Int32* pCounts = m_aComponentBitCounts.getArray(); + pCounts[0] = 8; + pCounts[1] = 8; + pCounts[2] = 8; + pCounts[3] = 8; + + m_nRedIndex = 2; + m_nGreenIndex = 1; + m_nBlueIndex = 0; + m_nAlphaIndex = 3; + } + break; + + case BMP_FORMAT_32BIT_TC_RGBA: + { + m_bPalette = false; + m_nBitsPerInputPixel = 32; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + + m_aComponentTags.realloc(4); + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_RED; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_BLUE; + pTags[3] = rendering::ColorComponentTag::ALPHA; + + m_aComponentBitCounts.realloc(4); + sal_Int32* pCounts = m_aComponentBitCounts.getArray(); + pCounts[0] = 8; + pCounts[1] = 8; + pCounts[2] = 8; + pCounts[3] = 8; + + m_nRedIndex = 0; + m_nGreenIndex = 1; + m_nBlueIndex = 2; + m_nAlphaIndex = 3; + } + break; + + case BMP_FORMAT_32BIT_TC_MASK: + m_bPalette = false; + m_nBitsPerInputPixel = 32; + m_nEndianness = util::Endianness::LITTLE; + m_aLayout.IsMsbFirst = sal_False; // doesn't matter + setComponentInfo( m_pBmpAcc->GetColorMask().GetRedMask(), + m_pBmpAcc->GetColorMask().GetGreenMask(), + m_pBmpAcc->GetColorMask().GetBlueMask() ); + break; + + default: + DBG_ERROR( "unsupported bitmap format" ); + break; + } + + if( m_bPalette ) + { + m_aComponentTags.realloc(1); + m_aComponentTags[0] = rendering::ColorComponentTag::INDEX; + + m_aComponentBitCounts.realloc(1); + m_aComponentBitCounts[0] = m_nBitsPerInputPixel; + + m_nIndexIndex = 0; + } + + m_nBitsPerOutputPixel = m_nBitsPerInputPixel; + if( m_aBmpEx.IsTransparent() ) + { + // TODO(P1): need to interleave alpha with bitmap data - + // won't fuss with less-than-8 bit for now + m_nBitsPerOutputPixel = std::max(sal_Int32(8),m_nBitsPerInputPixel); + + // check whether alpha goes in front or behind the + // bitcount sequence. If pixel format is little endian, + // put it behind all the other channels. If it's big + // endian, put it in front (because later, the actual data + // always gets written after the pixel data) + + // TODO(Q1): slight catch - in the case of the + // BMP_FORMAT_32BIT_XX_ARGB formats, duplicate alpha + // channels might happen! + m_aComponentTags.realloc(m_aComponentTags.getLength()+1); + m_aComponentTags[m_aComponentTags.getLength()-1] = rendering::ColorComponentTag::ALPHA; + + m_aComponentBitCounts.realloc(m_aComponentBitCounts.getLength()+1); + m_aComponentBitCounts[m_aComponentBitCounts.getLength()-1] = m_aBmpEx.IsAlpha() ? 8 : 1; + + if( m_nEndianness == util::Endianness::BIG ) + { + // put alpha in front of all the color channels + sal_Int8* pTags =m_aComponentTags.getArray(); + sal_Int32* pCounts=m_aComponentBitCounts.getArray(); + std::rotate(pTags, + pTags+m_aComponentTags.getLength()-1, + pTags+m_aComponentTags.getLength()); + std::rotate(pCounts, + pCounts+m_aComponentBitCounts.getLength()-1, + pCounts+m_aComponentBitCounts.getLength()); + ++m_nRedIndex; + ++m_nGreenIndex; + ++m_nBlueIndex; + ++m_nIndexIndex; + m_nAlphaIndex=0; + } + + // always add a full byte to the pixel size, otherwise + // pixel packing hell breaks loose. + m_nBitsPerOutputPixel += 8; + + // adapt scanline parameters + const Size aSize = m_aBitmap.GetSizePixel(); + m_aLayout.ScanLineBytes = + m_aLayout.ScanLineStride = (aSize.Width()*m_nBitsPerOutputPixel + 7)/8; + } + } +} + +VclCanvasBitmap::~VclCanvasBitmap() +{ + if( m_pAlphaAcc ) + m_aAlpha.ReleaseAccess(m_pAlphaAcc); + if( m_pBmpAcc ) + m_aBitmap.ReleaseAccess(m_pBmpAcc); +} + +// XBitmap +geometry::IntegerSize2D SAL_CALL VclCanvasBitmap::getSize() throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return integerSize2DFromSize( m_aBitmap.GetSizePixel() ); +} + +::sal_Bool SAL_CALL VclCanvasBitmap::hasAlpha() throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_aBmpEx.IsTransparent(); +} + +uno::Reference< rendering::XBitmap > SAL_CALL VclCanvasBitmap::getScaledBitmap( const geometry::RealSize2D& newSize, + sal_Bool beFast ) throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + BitmapEx aNewBmp( m_aBitmap ); + aNewBmp.Scale( sizeFromRealSize2D( newSize ), beFast ? BMP_SCALE_FAST : BMP_SCALE_INTERPOLATE ); + return uno::Reference<rendering::XBitmap>( new VclCanvasBitmap( aNewBmp ) ); +} + +// XIntegerReadOnlyBitmap +uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerBitmapLayout& bitmapLayout, + const geometry::IntegerRectangle2D& rect ) throw( lang::IndexOutOfBoundsException, + rendering::VolatileContentDestroyedException, + uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + bitmapLayout = getMemoryLayout(); + + const ::Rectangle aRequestedArea( vcl::unotools::rectangleFromIntegerRectangle2D(rect) ); + if( aRequestedArea.IsEmpty() ) + return uno::Sequence< sal_Int8 >(); + + // Invalid/empty bitmap: no data available + if( !m_pBmpAcc ) + throw lang::IndexOutOfBoundsException(); + if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc ) + throw lang::IndexOutOfBoundsException(); + + if( aRequestedArea.Left() < 0 || aRequestedArea.Top() < 0 || + aRequestedArea.Right() > m_pBmpAcc->Width() || + aRequestedArea.Bottom() > m_pBmpAcc->Height() ) + { + throw lang::IndexOutOfBoundsException(); + } + + uno::Sequence< sal_Int8 > aRet; + Rectangle aRequestedBytes( aRequestedArea ); + + // adapt to byte boundaries + aRequestedBytes.Left() = aRequestedArea.Left()*m_nBitsPerOutputPixel/8; + aRequestedBytes.Right() = (aRequestedArea.Right()*m_nBitsPerOutputPixel + 7)/8; + + // copy stuff to output sequence + aRet.realloc(aRequestedBytes.getWidth()*aRequestedBytes.getHeight()); + sal_Int8* pOutBuf = aRet.getArray(); + + bitmapLayout.ScanLines = aRequestedBytes.getHeight(); + bitmapLayout.ScanLineBytes = + bitmapLayout.ScanLineStride= aRequestedBytes.getWidth(); + + sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride; + if( !(m_pBmpAcc->GetScanlineFormat() & BMP_FORMAT_TOP_DOWN) ) + { + pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getHeight()-1); + nScanlineStride *= -1; + } + + if( !m_aBmpEx.IsTransparent() ) + { + OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access"); + + // can return bitmap data as-is + for( long y=aRequestedBytes.Top(); y<aRequestedBytes.Bottom(); ++y ) + { + Scanline pScan = m_pBmpAcc->GetScanline(y); + rtl_copyMemory(pOutBuf, pScan+aRequestedBytes.Left(), aRequestedBytes.getWidth()); + pOutBuf += nScanlineStride; + } + } + else + { + OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access"); + OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access"); + + // interleave alpha with bitmap data - note, bitcount is + // always integer multiple of 8 + OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0, + "Transparent bitmap bitcount not integer multiple of 8" ); + + for( long y=aRequestedArea.Top(); y<aRequestedArea.Bottom(); ++y ) + { + sal_Int8* pOutScan = pOutBuf; + + if( m_nBitsPerInputPixel < 8 ) + { + // input less than a byte - copy via GetPixel() + for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x ) + { + *pOutScan++ = m_pBmpAcc->GetPixel(y,x); + *pOutScan++ = m_pAlphaAcc->GetPixel(y,x); + } + } + else + { + const long nNonAlphaBytes( m_nBitsPerInputPixel/8 ); + const long nScanlineOffsetLeft(aRequestedArea.Left()*nNonAlphaBytes); + Scanline pScan = m_pBmpAcc->GetScanline(y) + nScanlineOffsetLeft; + + // input integer multiple of byte - copy directly + for( long x=aRequestedArea.Left(); x<aRequestedArea.Right(); ++x ) + { + for( long i=0; i<nNonAlphaBytes; ++i ) + *pOutScan++ = *pScan++; + *pOutScan++ = m_pAlphaAcc->GetPixel(y,x); + } + } + + pOutBuf += nScanlineStride; + } + } + + return aRet; +} + +uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getPixel( rendering::IntegerBitmapLayout& bitmapLayout, + const geometry::IntegerPoint2D& pos ) throw (lang::IndexOutOfBoundsException, + rendering::VolatileContentDestroyedException, + uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + bitmapLayout = getMemoryLayout(); + + // Invalid/empty bitmap: no data available + if( !m_pBmpAcc ) + throw lang::IndexOutOfBoundsException(); + if( m_aBmpEx.IsTransparent() && !m_pAlphaAcc ) + throw lang::IndexOutOfBoundsException(); + + if( pos.X < 0 || pos.Y < 0 || + pos.X > m_pBmpAcc->Width() || pos.Y > m_pBmpAcc->Height() ) + { + throw lang::IndexOutOfBoundsException(); + } + + uno::Sequence< sal_Int8 > aRet((m_nBitsPerOutputPixel + 7)/8); + sal_Int8* pOutBuf = aRet.getArray(); + + // copy stuff to output sequence + bitmapLayout.ScanLines = 1; + bitmapLayout.ScanLineBytes = + bitmapLayout.ScanLineStride= aRet.getLength(); + + const long nScanlineLeftOffset( pos.X*m_nBitsPerInputPixel/8 ); + if( !m_aBmpEx.IsTransparent() ) + { + OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access"); + + // can return bitmap data as-is + Scanline pScan = m_pBmpAcc->GetScanline(pos.Y); + rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, aRet.getLength() ); + } + else + { + OSL_ENSURE(m_pBmpAcc,"Invalid bmp read access"); + OSL_ENSURE(m_pAlphaAcc,"Invalid alpha read access"); + + // interleave alpha with bitmap data - note, bitcount is + // always integer multiple of 8 + OSL_ENSURE((m_nBitsPerOutputPixel & 0x07) == 0, + "Transparent bitmap bitcount not integer multiple of 8" ); + + if( m_nBitsPerInputPixel < 8 ) + { + // input less than a byte - copy via GetPixel() + *pOutBuf++ = m_pBmpAcc->GetPixel(pos.Y,pos.X); + *pOutBuf = m_pAlphaAcc->GetPixel(pos.Y,pos.X); + } + else + { + const long nNonAlphaBytes( m_nBitsPerInputPixel/8 ); + Scanline pScan = m_pBmpAcc->GetScanline(pos.Y); + + // input integer multiple of byte - copy directly + rtl_copyMemory(pOutBuf, pScan+nScanlineLeftOffset, nNonAlphaBytes ); + pOutBuf += nNonAlphaBytes; + *pOutBuf++ = m_pAlphaAcc->GetPixel(pos.Y,pos.X); + } + } + + return aRet; +} + +uno::Reference< rendering::XBitmapPalette > SAL_CALL VclCanvasBitmap::getPalette() throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + uno::Reference< XBitmapPalette > aRet; + if( m_bPalette ) + aRet.set(this); + + return aRet; +} + +rendering::IntegerBitmapLayout SAL_CALL VclCanvasBitmap::getMemoryLayout() throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + rendering::IntegerBitmapLayout aLayout( m_aLayout ); + + // only set references to self on separate copy of + // IntegerBitmapLayout - if we'd set that on m_aLayout, we'd have + // a circular reference! + if( m_bPalette ) + aLayout.Palette.set( this ); + + aLayout.ColorSpace.set( this ); + + return aLayout; +} + +sal_Int32 SAL_CALL VclCanvasBitmap::getNumberOfEntries() throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( !m_pBmpAcc ) + return 0; + + return m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ; +} + +sal_Bool SAL_CALL VclCanvasBitmap::getIndex( uno::Sequence< double >& o_entry, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const USHORT nCount( m_pBmpAcc ? + (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 ); + OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range"); + if( nIndex < 0 || nIndex >= nCount ) + throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"), + static_cast<rendering::XBitmapPalette*>(this)); + + const BitmapColor aCol = m_pBmpAcc->GetPaletteColor(sal::static_int_cast<USHORT>(nIndex)); + o_entry.realloc(3); + double* pColor=o_entry.getArray(); + pColor[0] = aCol.GetRed(); + pColor[1] = aCol.GetGreen(); + pColor[2] = aCol.GetBlue(); + + return sal_True; // no palette transparency here. +} + +sal_Bool SAL_CALL VclCanvasBitmap::setIndex( const uno::Sequence< double >&, sal_Bool, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const USHORT nCount( m_pBmpAcc ? + (m_pBmpAcc->HasPalette() ? m_pBmpAcc->GetPaletteEntryCount() : 0 ) : 0 ); + + OSL_ENSURE(nIndex >= 0 && nIndex < nCount,"Palette index out of range"); + if( nIndex < 0 || nIndex >= nCount ) + throw lang::IndexOutOfBoundsException(::rtl::OUString::createFromAscii("Palette index out of range"), + static_cast<rendering::XBitmapPalette*>(this)); + + return sal_False; // read-only implementation +} + +namespace +{ + struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>, + PaletteColorSpaceHolder> + { + uno::Reference<rendering::XColorSpace> operator()() + { + return vcl::unotools::createStandardColorSpace(); + } + }; +} + +uno::Reference< rendering::XColorSpace > SAL_CALL VclCanvasBitmap::getColorSpace( ) throw (uno::RuntimeException) +{ + // this is the method from XBitmapPalette. Return palette color + // space here + return PaletteColorSpaceHolder::get(); +} + +sal_Int8 SAL_CALL VclCanvasBitmap::getType( ) throw (uno::RuntimeException) +{ + return rendering::ColorSpaceType::RGB; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::getComponentTags( ) throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_aComponentTags; +} + +sal_Int8 SAL_CALL VclCanvasBitmap::getRenderingIntent( ) throw (uno::RuntimeException) +{ + return rendering::RenderingIntent::PERCEPTUAL; +} + +uno::Sequence< ::beans::PropertyValue > SAL_CALL VclCanvasBitmap::getProperties( ) throw (uno::RuntimeException) +{ + return uno::Sequence< ::beans::PropertyValue >(); +} + +uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (uno::RuntimeException) +{ + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence<rendering::ARGBColor> aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); +} + +uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, + "number of channels no multiple of pixel element count", + static_cast<rendering::XBitmapPalette*>(this), 01); + + uno::Sequence< rendering::RGBColor > aRes(nLen/nComponentsPerPixel); + rendering::RGBColor* pOut( aRes.getArray() ); + + if( m_bPalette ) + { + OSL_ENSURE(m_nIndexIndex != -1, + "Invalid color channel indices"); + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + const BitmapColor aCol = m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex])); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + } + } + else + { + OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1, + "Invalid color channel indices"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::RGBColor( + deviceColor[i+m_nRedIndex], + deviceColor[i+m_nGreenIndex], + deviceColor[i+m_nBlueIndex]); + } + } + + return aRes; +} + +uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, + "number of channels no multiple of pixel element count", + static_cast<rendering::XBitmapPalette*>(this), 01); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel); + rendering::ARGBColor* pOut( aRes.getArray() ); + + if( m_bPalette ) + { + OSL_ENSURE(m_nIndexIndex != -1, + "Invalid color channel indices"); + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + const BitmapColor aCol = m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex])); + + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = rendering::ARGBColor(nAlpha, + toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + } + } + else + { + OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1, + "Invalid color channel indices"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = rendering::ARGBColor( + nAlpha, + deviceColor[i+m_nRedIndex], + deviceColor[i+m_nGreenIndex], + deviceColor[i+m_nBlueIndex]); + } + } + + return aRes; +} + +uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, + "number of channels no multiple of pixel element count", + static_cast<rendering::XBitmapPalette*>(this), 01); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/nComponentsPerPixel); + rendering::ARGBColor* pOut( aRes.getArray() ); + + if( m_bPalette ) + { + OSL_ENSURE(m_nIndexIndex != -1, + "Invalid color channel indices"); + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + const BitmapColor aCol = m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex])); + + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = rendering::ARGBColor(nAlpha, + nAlpha*toDoubleColor(aCol.GetRed()), + nAlpha*toDoubleColor(aCol.GetGreen()), + nAlpha*toDoubleColor(aCol.GetBlue())); + } + } + else + { + OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1, + "Invalid color channel indices"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = rendering::ARGBColor( + nAlpha, + nAlpha*deviceColor[i+m_nRedIndex], + nAlpha*deviceColor[i+m_nGreenIndex], + nAlpha*deviceColor[i+m_nBlueIndex]); + } + } + + return aRes; +} + +uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + + uno::Sequence< double > aRes(nLen*nComponentsPerPixel); + double* pColors=aRes.getArray(); + + if( m_bPalette ) + { + for( sal_Size i=0; i<nLen; ++i ) + { + pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex( + BitmapColor(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue))); + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = 1.0; + + pColors += nComponentsPerPixel; + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + pColors[m_nRedIndex] = rgbColor[i].Red; + pColors[m_nGreenIndex] = rgbColor[i].Green; + pColors[m_nBlueIndex] = rgbColor[i].Blue; + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = 1.0; + + pColors += nComponentsPerPixel; + } + } + return aRes; +} + +uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + + uno::Sequence< double > aRes(nLen*nComponentsPerPixel); + double* pColors=aRes.getArray(); + + if( m_bPalette ) + { + for( sal_Size i=0; i<nLen; ++i ) + { + pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex( + BitmapColor(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue))); + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = rgbColor[i].Alpha; + + pColors += nComponentsPerPixel; + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + pColors[m_nRedIndex] = rgbColor[i].Red; + pColors[m_nGreenIndex] = rgbColor[i].Green; + pColors[m_nBlueIndex] = rgbColor[i].Blue; + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = rgbColor[i].Alpha; + + pColors += nComponentsPerPixel; + } + } + return aRes; +} + +uno::Sequence< double > SAL_CALL VclCanvasBitmap::convertFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + + uno::Sequence< double > aRes(nLen*nComponentsPerPixel); + double* pColors=aRes.getArray(); + + if( m_bPalette ) + { + for( sal_Size i=0; i<nLen; ++i ) + { + const double nAlpha( rgbColor[i].Alpha ); + pColors[m_nIndexIndex] = m_pBmpAcc->GetBestPaletteIndex( + BitmapColor(toByteColor(rgbColor[i].Red / nAlpha), + toByteColor(rgbColor[i].Green / nAlpha), + toByteColor(rgbColor[i].Blue / nAlpha))); + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = nAlpha; + + pColors += nComponentsPerPixel; + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + const double nAlpha( rgbColor[i].Alpha ); + pColors[m_nRedIndex] = rgbColor[i].Red / nAlpha; + pColors[m_nGreenIndex] = rgbColor[i].Green / nAlpha; + pColors[m_nBlueIndex] = rgbColor[i].Blue / nAlpha; + if( m_nAlphaIndex != -1 ) + pColors[m_nAlphaIndex] = nAlpha; + + pColors += nComponentsPerPixel; + } + } + return aRes; +} + +sal_Int32 SAL_CALL VclCanvasBitmap::getBitsPerPixel( ) throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_nBitsPerOutputPixel; +} + +uno::Sequence< ::sal_Int32 > SAL_CALL VclCanvasBitmap::getComponentBitCounts( ) throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_aComponentBitCounts; +} + +sal_Int8 SAL_CALL VclCanvasBitmap::getEndianness( ) throw (uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_nEndianness; +} + +uno::Sequence<double> SAL_CALL VclCanvasBitmap::convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< ::rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nComponentsPerPixel(m_aComponentTags.getLength()); + ENSURE_ARG_OR_THROW2(nLen%nComponentsPerPixel==0, + "number of channels no multiple of pixel element count", + static_cast<rendering::XBitmapPalette*>(this), 01); + + uno::Sequence<double> aRes(nLen); + double* pOut( aRes.getArray() ); + + if( m_bPalette ) + { + OSL_ENSURE(m_nIndexIndex != -1, + "Invalid color channel indices"); + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + const BitmapColor aCol = m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>(deviceColor[i+m_nIndexIndex])); + + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = toDoubleColor(aCol.GetRed()); + *pOut++ = toDoubleColor(aCol.GetGreen()); + *pOut++ = toDoubleColor(aCol.GetBlue()); + *pOut++ = nAlpha; + } + } + else + { + OSL_ENSURE(m_nRedIndex != -1 && m_nGreenIndex != -1 && m_nBlueIndex != -1, + "Invalid color channel indices"); + + for( sal_Size i=0; i<nLen; i+=nComponentsPerPixel ) + { + // TODO(F3): Convert result to sRGB color space + const double nAlpha( m_nAlphaIndex != -1 ? 1.0 - deviceColor[i+m_nAlphaIndex] : 1.0 ); + *pOut++ = deviceColor[i+m_nRedIndex]; + *pOut++ = deviceColor[i+m_nGreenIndex]; + *pOut++ = deviceColor[i+m_nBlueIndex]; + *pOut++ = nAlpha; + } + } + + return aRes; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence<rendering::ARGBColor> aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } +} + +uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< ::rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + if( dynamic_cast<VclCanvasBitmap*>(targetColorSpace.get()) ) + { + // it's us, so simply pass-through the data + return deviceColor; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence<rendering::ARGBColor> aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertIntegerFromARGB(aIntermediate); + } +} + +uno::Sequence<rendering::RGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) ); + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel); + + uno::Sequence< rendering::RGBColor > aRes(nNumColors); + rendering::RGBColor* pOut( aRes.getArray() ); + + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + if( m_aBmpEx.IsTransparent() ) + { + const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); + for( sal_Size i=0; i<nLen; i+=nBytesPerPixel ) + { + // if palette, index is guaranteed to be 8 bit + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor(*pIn) : + m_pBmpAcc->GetPixelFromData(pIn,0); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + // skips alpha + pIn += nBytesPerPixel; + } + } + else + { + for( sal_Int32 i=0; i<nNumColors; ++i ) + { + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>( + m_pBmpAcc->GetPixelFromData( + pIn, i ))) : + m_pBmpAcc->GetPixelFromData(pIn, i); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::RGBColor(toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + } + } + + return aRes; +} + +uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) ); + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel); + + uno::Sequence< rendering::ARGBColor > aRes(nNumColors); + rendering::ARGBColor* pOut( aRes.getArray() ); + + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + if( m_aBmpEx.IsTransparent() ) + { + const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); + const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); + const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 ); + for( sal_Size i=0; i<nLen; i+=nBytesPerPixel ) + { + // if palette, index is guaranteed to be 8 bit + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor(*pIn) : + m_pBmpAcc->GetPixelFromData(pIn,0); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::ARGBColor(1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]), + toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + pIn += nBytesPerPixel; + } + } + else + { + for( sal_Int32 i=0; i<nNumColors; ++i ) + { + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>( + m_pBmpAcc->GetPixelFromData( + pIn, i ))) : + m_pBmpAcc->GetPixelFromData(pIn, i); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::ARGBColor(1.0, + toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + } + } + + return aRes; +} + +uno::Sequence<rendering::ARGBColor> SAL_CALL VclCanvasBitmap::convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const BYTE* pIn( reinterpret_cast<const BYTE*>(deviceColor.getConstArray()) ); + const sal_Size nLen( deviceColor.getLength() ); + const sal_Int32 nNumColors((nLen*8 + m_nBitsPerOutputPixel-1)/m_nBitsPerOutputPixel); + + uno::Sequence< rendering::ARGBColor > aRes(nNumColors); + rendering::ARGBColor* pOut( aRes.getArray() ); + + ENSURE_OR_THROW(m_pBmpAcc, + "Unable to get BitmapAccess"); + + if( m_aBmpEx.IsTransparent() ) + { + const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); + const sal_Int32 nBytesPerPixel((m_nBitsPerOutputPixel+7)/8); + const sal_uInt8 nAlphaFactor( m_aBmpEx.IsAlpha() ? 1 : 255 ); + for( sal_Size i=0; i<nLen; i+=nBytesPerPixel ) + { + // if palette, index is guaranteed to be 8 bit + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor(*pIn) : + m_pBmpAcc->GetPixelFromData(pIn,0); + + // TODO(F3): Convert result to sRGB color space + const double nAlpha( 1.0 - toDoubleColor(nAlphaFactor*pIn[nNonAlphaBytes]) ); + *pOut++ = rendering::ARGBColor(nAlpha, + nAlpha*toDoubleColor(aCol.GetRed()), + nAlpha*toDoubleColor(aCol.GetGreen()), + nAlpha*toDoubleColor(aCol.GetBlue())); + pIn += nBytesPerPixel; + } + } + else + { + for( sal_Int32 i=0; i<nNumColors; ++i ) + { + const BitmapColor aCol = + m_bPalette ? + m_pBmpAcc->GetPaletteColor( + sal::static_int_cast<USHORT>( + m_pBmpAcc->GetPixelFromData( + pIn, i ))) : + m_pBmpAcc->GetPixelFromData(pIn, i); + + // TODO(F3): Convert result to sRGB color space + *pOut++ = rendering::ARGBColor(1.0, + toDoubleColor(aCol.GetRed()), + toDoubleColor(aCol.GetGreen()), + toDoubleColor(aCol.GetBlue())); + } + } + + return aRes; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromRGB( const uno::Sequence<rendering::RGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8); + + uno::Sequence< sal_Int8 > aRes(nNumBytes); + BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray()); + + if( m_aBmpEx.IsTransparent() ) + { + const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); + for( sal_Size i=0; i<nLen; ++i ) + { + const BitmapColor aCol(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,0,aCol2); + pColors += nNonAlphaBytes; + *pColors++ = BYTE(255); + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + const BitmapColor aCol(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,i,aCol2); + } + } + + return aRes; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8); + + uno::Sequence< sal_Int8 > aRes(nNumBytes); + BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray()); + + if( m_aBmpEx.IsTransparent() ) + { + const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); + for( sal_Size i=0; i<nLen; ++i ) + { + const BitmapColor aCol(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,0,aCol2); + pColors += nNonAlphaBytes; + *pColors++ = 255 - toByteColor(rgbColor[i].Alpha); + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + const BitmapColor aCol(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,i,aCol2); + } + } + + return aRes; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL VclCanvasBitmap::convertIntegerFromPARGB( const uno::Sequence<rendering::ARGBColor>& rgbColor ) throw (lang::IllegalArgumentException,uno::RuntimeException) +{ + vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Size nLen( rgbColor.getLength() ); + const sal_Int32 nNumBytes((nLen*m_nBitsPerOutputPixel+7)/8); + + uno::Sequence< sal_Int8 > aRes(nNumBytes); + BYTE* pColors=reinterpret_cast<BYTE*>(aRes.getArray()); + + if( m_aBmpEx.IsTransparent() ) + { + const long nNonAlphaBytes( (m_nBitsPerInputPixel+7)/8 ); + for( sal_Size i=0; i<nLen; ++i ) + { + const double nAlpha( rgbColor[i].Alpha ); + const BitmapColor aCol(toByteColor(rgbColor[i].Red / nAlpha), + toByteColor(rgbColor[i].Green / nAlpha), + toByteColor(rgbColor[i].Blue / nAlpha)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,0,aCol2); + pColors += nNonAlphaBytes; + *pColors++ = 255 - toByteColor(nAlpha); + } + } + else + { + for( sal_Size i=0; i<nLen; ++i ) + { + const BitmapColor aCol(toByteColor(rgbColor[i].Red), + toByteColor(rgbColor[i].Green), + toByteColor(rgbColor[i].Blue)); + const BitmapColor aCol2 = + m_bPalette ? + BitmapColor( + sal::static_int_cast<BYTE>(m_pBmpAcc->GetBestPaletteIndex( aCol ))) : + aCol; + + m_pBmpAcc->SetPixelOnData(pColors,i,aCol2); + } + } + + return aRes; +} + +BitmapEx VclCanvasBitmap::getBitmapEx() const +{ + return m_aBmpEx; +} diff --git a/vcl/source/helper/canvastools.cxx b/vcl/source/helper/canvastools.cxx new file mode 100644 index 000000000000..71c306ff9bbb --- /dev/null +++ b/vcl/source/helper/canvastools.cxx @@ -0,0 +1,837 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <rtl/logfile.hxx> +#include <cppuhelper/compbase1.hxx> + +#include <com/sun/star/geometry/RealSize2D.hpp> +#include <com/sun/star/geometry/RealPoint2D.hpp> +#include <com/sun/star/geometry/RealRectangle2D.hpp> +#include <com/sun/star/geometry/IntegerSize2D.hpp> +#include <com/sun/star/geometry/IntegerPoint2D.hpp> +#include <com/sun/star/geometry/IntegerRectangle2D.hpp> +#include <com/sun/star/geometry/RealBezierSegment2D.hpp> + +#include <com/sun/star/rendering/ColorSpaceType.hpp> +#include <com/sun/star/rendering/RenderingIntent.hpp> +#include <com/sun/star/rendering/XGraphicDevice.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/rendering/IntegerBitmapLayout.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/rendering/ColorComponentTag.hpp> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/vector/b2dsize.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/range/b2irectangle.hxx> + +// #i79917# +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/tools/canvastools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> + +#include <tools/poly.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/uuid.h> + +#include <vcl/salbtype.hxx> +#include <vcl/bmpacc.hxx> +#include <vcl/bitmapex.hxx> + +#include <vcl/canvasbitmap.hxx> +#include <vcl/canvastools.hxx> +#include <hash_map> + + +using namespace ::com::sun::star; + +namespace vcl +{ + namespace unotools + { + // #i79917# removed helpers bezierSequenceFromPolygon and + // pointSequenceFromPolygon here + // Also all helpers using tools Polygon and PolyPolygon will get mapped to the + // B2DPolygon helpers for these cases, see comments with the same TaskID below. + // TODO: Remove those wrapped methods + + //--------------------------------------------------------------------------------------- + + uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, + const ::Polygon& inputPolygon ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolygon()" ); + + // #i79917# map to basegfx + const basegfx::B2DPolygon aB2DPolygon(inputPolygon.getB2DPolygon()); + return basegfx::unotools::xPolyPolygonFromB2DPolygon(xGraphicDevice, aB2DPolygon); + } + + //--------------------------------------------------------------------------------------- + + uno::Reference< rendering::XPolyPolygon2D > xPolyPolygonFromPolyPolygon( const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice, + const ::PolyPolygon& inputPolyPolygon ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xPolyPolygonFromPolyPolygon()" ); + + // #i79917# map to basegfx + const basegfx::B2DPolyPolygon aB2DPolyPolygon(inputPolyPolygon.getB2DPolyPolygon()); + return basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xGraphicDevice, aB2DPolyPolygon); + } + + //--------------------------------------------------------------------------------------- + + ::Polygon polygonFromPoint2DSequence( const uno::Sequence< geometry::RealPoint2D >& points ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polygonFromPoint2DSequence()" ); + + const USHORT nCurrSize( sal::static_int_cast<USHORT>(points.getLength()) ); + + ::Polygon aPoly( nCurrSize ); + + USHORT nCurrPoint; + for( nCurrPoint=0; nCurrPoint<nCurrSize; ++nCurrPoint ) + aPoly[nCurrPoint] = pointFromRealPoint2D( points[nCurrPoint] ); + + return aPoly; + } + + //--------------------------------------------------------------------------------------- + + ::PolyPolygon polyPolygonFromPoint2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::polyPolygonFromPoint2DSequenceSequence()" ); + + ::PolyPolygon aRes; + + int nCurrPoly; + for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly ) + { + aRes.Insert( polygonFromPoint2DSequence( points[nCurrPoly] ) ); + } + + return aRes; + } + + //--------------------------------------------------------------------------------------- + + ::Polygon polygonFromBezier2DSequence( const uno::Sequence< geometry::RealBezierSegment2D >& curves ) + { + // #i79917# map to basegfx + const basegfx::B2DPolygon aB2DPolygon(basegfx::unotools::polygonFromBezier2DSequence(curves)); + return ::Polygon(aB2DPolygon); + } + + //--------------------------------------------------------------------------------------- + + ::PolyPolygon polyPolygonFromBezier2DSequenceSequence( const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& curves ) + { + // #i79917# map to basegfx + const basegfx::B2DPolyPolygon aB2DPolyPolygon(basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(curves)); + return ::PolyPolygon(aB2DPolyPolygon); + } + + //--------------------------------------------------------------------------------------- + + uno::Reference< rendering::XBitmap > xBitmapFromBitmap( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, + const ::Bitmap& inputBitmap ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmap()" ); + + return new vcl::unotools::VclCanvasBitmap( BitmapEx( inputBitmap ) ); + } + + //--------------------------------------------------------------------------------------- + + uno::Reference< rendering::XBitmap > xBitmapFromBitmapEx( const uno::Reference< rendering::XGraphicDevice >& /*xGraphicDevice*/, + const ::BitmapEx& inputBitmap ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::xBitmapFromBitmapEx()" ); + + return new vcl::unotools::VclCanvasBitmap( inputBitmap ); + } + + //--------------------------------------------------------------------------------------- + + const uno::Sequence< sal_Int8 > getTunnelIdentifier( TunnelIdentifierType eType ) + { + static std::hash_map< int, uno::Sequence< sal_Int8 > > aIds; + std::hash_map< int, uno::Sequence< sal_Int8 > >::iterator it = + aIds.find( eType ); + if( it == aIds.end() ) + { + uno::Sequence< sal_Int8 > aNewId( 16 ); + rtl_createUuid( (sal_uInt8*)aNewId.getArray(), NULL, sal_True ); + aIds[ eType ] = aNewId; + it = aIds.find( eType ); + } + return it->second; + } + + //--------------------------------------------------------------------------------------- + + namespace + { + inline bool operator==( const rendering::IntegerBitmapLayout& rLHS, + const rendering::IntegerBitmapLayout& rRHS ) + { + return + rLHS.ScanLineBytes == rRHS.ScanLineBytes && + rLHS.ScanLineStride == rRHS.ScanLineStride && + rLHS.PlaneStride == rRHS.PlaneStride && + rLHS.ColorSpace == rRHS.ColorSpace && + rLHS.Palette == rRHS.Palette && + rLHS.IsMsbFirst == rRHS.IsMsbFirst; + } + + bool readBmp( sal_Int32 nWidth, + sal_Int32 nHeight, + const rendering::IntegerBitmapLayout& rLayout, + const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap, + ScopedBitmapWriteAccess& rWriteAcc, + ScopedBitmapWriteAccess& rAlphaAcc ) + { + rendering::IntegerBitmapLayout aCurrLayout; + geometry::IntegerRectangle2D aRect; + uno::Sequence<sal_Int8> aPixelData; + uno::Sequence<rendering::RGBColor> aRGBColors; + uno::Sequence<rendering::ARGBColor> aARGBColors; + + for( aRect.Y1=0; aRect.Y1<nHeight; ++aRect.Y1 ) + { + aRect.X1 = 0; aRect.X2 = nWidth; aRect.Y2 = aRect.Y1+1; + try + { + aPixelData = xInputBitmap->getData(aCurrLayout,aRect); + } + catch( rendering::VolatileContentDestroyedException& ) + { + // re-read bmp from the start + return false; + } + if( !(aCurrLayout == rLayout) ) + return false; // re-read bmp from the start + + if( rAlphaAcc.get() ) + { + // read ARGB color + aARGBColors = rLayout.ColorSpace->convertIntegerToARGB(aPixelData); + + if( rWriteAcc->HasPalette() ) + { + for( sal_Int32 x=0; x<nWidth; ++x ) + { + const rendering::ARGBColor& rColor=aARGBColors[x]; + rWriteAcc->SetPixel( aRect.Y1, x, + (BYTE)rWriteAcc->GetBestPaletteIndex( + BitmapColor( toByteColor(rColor.Red), + toByteColor(rColor.Green), + toByteColor(rColor.Blue))) ); + rAlphaAcc->SetPixel( aRect.Y1, x, + BitmapColor( 255 - toByteColor(rColor.Alpha) )); + } + } + else + { + for( sal_Int32 x=0; x<nWidth; ++x ) + { + const rendering::ARGBColor& rColor=aARGBColors[x]; + rWriteAcc->SetPixel( aRect.Y1, x, + BitmapColor( toByteColor(rColor.Red), + toByteColor(rColor.Green), + toByteColor(rColor.Blue) )); + rAlphaAcc->SetPixel( aRect.Y1, x, + BitmapColor( 255 - toByteColor(rColor.Alpha) )); + } + } + } + else + { + // read RGB color + aRGBColors = rLayout.ColorSpace->convertIntegerToRGB(aPixelData); + if( rWriteAcc->HasPalette() ) + { + for( sal_Int32 x=0; x<nWidth; ++x ) + { + const rendering::RGBColor& rColor=aRGBColors[x]; + rWriteAcc->SetPixel( aRect.Y1, x, + (BYTE)rWriteAcc->GetBestPaletteIndex( + BitmapColor( toByteColor(rColor.Red), + toByteColor(rColor.Green), + toByteColor(rColor.Blue))) ); + } + } + else + { + for( sal_Int32 x=0; x<nWidth; ++x ) + { + const rendering::RGBColor& rColor=aRGBColors[x]; + rWriteAcc->SetPixel( aRect.Y1, x, + BitmapColor( toByteColor(rColor.Red), + toByteColor(rColor.Green), + toByteColor(rColor.Blue) )); + } + } + } + } + + return true; + } + } + + ::BitmapEx VCL_DLLPUBLIC bitmapExFromXBitmap( const uno::Reference< rendering::XIntegerReadOnlyBitmap >& xInputBitmap ) + { + RTL_LOGFILE_CONTEXT( aLog, "::vcl::unotools::bitmapExFromXBitmap()" ); + + if( !xInputBitmap.is() ) + return ::BitmapEx(); + + // tunnel directly for known implementation + // ---------------------------------------------------------------- + VclCanvasBitmap* pImplBitmap = dynamic_cast<VclCanvasBitmap*>(xInputBitmap.get()); + if( pImplBitmap ) + return pImplBitmap->getBitmapEx(); + + // retrieve data via UNO interface + // ---------------------------------------------------------------- + + // volatile bitmaps are a bit more complicated to read + // from.. + uno::Reference<rendering::XVolatileBitmap> xVolatileBitmap( + xInputBitmap, uno::UNO_QUERY); + + // loop a few times, until successfully read (for XVolatileBitmap) + for( int i=0; i<10; ++i ) + { + sal_Int32 nDepth=0; + sal_Int32 nAlphaDepth=0; + const rendering::IntegerBitmapLayout aLayout( + xInputBitmap->getMemoryLayout()); + + OSL_ENSURE(aLayout.ColorSpace.is(), + "Cannot convert image without color space!"); + if( !aLayout.ColorSpace.is() ) + return ::BitmapEx(); + + nDepth = aLayout.ColorSpace->getBitsPerPixel(); + + if( xInputBitmap->hasAlpha() ) + { + // determine alpha channel depth + const uno::Sequence<sal_Int8> aTags( + aLayout.ColorSpace->getComponentTags() ); + const uno::Sequence<sal_Int32> aDepths( + aLayout.ColorSpace->getComponentBitCounts() ); + const sal_Int8* pStart(aTags.getConstArray()); + const sal_Size nLen(aTags.getLength()); + const sal_Int8* pEnd(pStart+nLen); + + const std::ptrdiff_t nAlphaIndex = + std::find(pStart,pEnd, + rendering::ColorComponentTag::ALPHA) - pStart; + + if( nAlphaIndex < sal::static_int_cast<std::ptrdiff_t>(nLen) ) + { + nAlphaDepth = aLayout.ColorSpace->getComponentBitCounts()[nAlphaIndex] > 1 ? 8 : 1; + nDepth -= nAlphaDepth; + } + } + + BitmapPalette aPalette; + if( aLayout.Palette.is() ) + { + uno::Reference< rendering::XColorSpace > xPaletteColorSpace( + aLayout.Palette->getColorSpace()); + ENSURE_OR_THROW(xPaletteColorSpace.is(), + "Palette without color space"); + + const sal_Int32 nEntryCount( aLayout.Palette->getNumberOfEntries() ); + if( nEntryCount <= 256 ) + { + if( nEntryCount <= 2 ) + nDepth = 1; + else + nDepth = 8; + + const USHORT nPaletteEntries( + sal::static_int_cast<USHORT>( + std::min(sal_Int32(255), nEntryCount))); + + // copy palette entries + aPalette.SetEntryCount(nPaletteEntries); + uno::Reference<rendering::XBitmapPalette> xPalette( aLayout.Palette ); + uno::Reference<rendering::XColorSpace> xPalColorSpace( xPalette->getColorSpace() ); + + uno::Sequence<double> aPaletteEntry; + for( USHORT j=0; j<nPaletteEntries; ++j ) + { + if( !xPalette->getIndex(aPaletteEntry,j) && + nAlphaDepth == 0 ) + { + nAlphaDepth = 1; + } + uno::Sequence<rendering::RGBColor> aColors=xPalColorSpace->convertToRGB(aPaletteEntry); + ENSURE_OR_THROW(aColors.getLength() == 1, + "Palette returned more or less than one entry"); + const rendering::RGBColor& rColor=aColors[0]; + aPalette[j] = BitmapColor(toByteColor(rColor.Red), + toByteColor(rColor.Green), + toByteColor(rColor.Blue)); + } + } + } + + const ::Size aPixelSize( + sizeFromIntegerSize2D(xInputBitmap->getSize())); + + // normalize bitcount + nDepth = + ( nDepth <= 1 ) ? 1 : + ( nDepth <= 4 ) ? 4 : + ( nDepth <= 8 ) ? 8 : 24; + + ::Bitmap aBitmap( aPixelSize, + sal::static_int_cast<USHORT>(nDepth), + aLayout.Palette.is() ? &aPalette : NULL ); + ::Bitmap aAlpha; + if( nAlphaDepth ) + aAlpha = ::Bitmap( aPixelSize, + sal::static_int_cast<USHORT>(nAlphaDepth), + &::Bitmap::GetGreyPalette( + sal::static_int_cast<USHORT>(1L << nAlphaDepth)) ); + + { // limit scoped access + ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), + aBitmap ); + ScopedBitmapWriteAccess pAlphaWriteAccess( nAlphaDepth ? aAlpha.AcquireWriteAccess() : NULL, + aAlpha ); + + ENSURE_OR_THROW(pWriteAccess.get() != NULL, + "Cannot get write access to bitmap"); + + const sal_Int32 nWidth(aPixelSize.Width()); + const sal_Int32 nHeight(aPixelSize.Height()); + + if( !readBmp(nWidth,nHeight,aLayout,xInputBitmap, + pWriteAccess,pAlphaWriteAccess) ) + continue; + } // limit scoped access + + if( nAlphaDepth ) + return ::BitmapEx( aBitmap, + AlphaMask( aAlpha ) ); + else + return ::BitmapEx( aBitmap ); + } + + // failed to read data 10 times - bail out + return ::BitmapEx(); + } + + //--------------------------------------------------------------------------------------- + + geometry::RealSize2D size2DFromSize( const Size& rSize ) + { + return geometry::RealSize2D( rSize.Width(), + rSize.Height() ); + } + + geometry::RealPoint2D point2DFromPoint( const Point& rPoint ) + { + return geometry::RealPoint2D( rPoint.X(), + rPoint.Y() ); + } + + geometry::RealRectangle2D rectangle2DFromRectangle( const Rectangle& rRect ) + { + return geometry::RealRectangle2D( rRect.Left(), rRect.Top(), + rRect.Right(), rRect.Bottom() ); + } + + Size sizeFromRealSize2D( const geometry::RealSize2D& rSize ) + { + return Size( static_cast<long>(rSize.Width + .5), + static_cast<long>(rSize.Height + .5) ); + } + + Point pointFromRealPoint2D( const geometry::RealPoint2D& rPoint ) + { + return Point( static_cast<long>(rPoint.X + .5), + static_cast<long>(rPoint.Y + .5) ); + } + + Rectangle rectangleFromRealRectangle2D( const geometry::RealRectangle2D& rRect ) + { + return Rectangle( static_cast<long>(rRect.X1 + .5), + static_cast<long>(rRect.Y1 + .5), + static_cast<long>(rRect.X2 + .5), + static_cast<long>(rRect.Y2 + .5) ); + } + + ::Size sizeFromB2DSize( const ::basegfx::B2DVector& rVec ) + { + return ::Size( FRound( rVec.getX() ), + FRound( rVec.getY() ) ); + } + + ::Point pointFromB2DPoint( const ::basegfx::B2DPoint& rPoint ) + { + return ::Point( FRound( rPoint.getX() ), + FRound( rPoint.getY() ) ); + } + + ::Rectangle rectangleFromB2DRectangle( const ::basegfx::B2DRange& rRect ) + { + return ::Rectangle( FRound( rRect.getMinX() ), + FRound( rRect.getMinY() ), + FRound( rRect.getMaxX() ), + FRound( rRect.getMaxY() ) ); + } + + Size sizeFromB2ISize( const ::basegfx::B2IVector& rVec ) + { + return ::Size( rVec.getX(), + rVec.getY() ); + } + + Point pointFromB2IPoint( const ::basegfx::B2IPoint& rPoint ) + { + return ::Point( rPoint.getX(), + rPoint.getY() ); + } + + Rectangle rectangleFromB2IRectangle( const ::basegfx::B2IRange& rRect ) + { + return ::Rectangle( rRect.getMinX(), + rRect.getMinY(), + rRect.getMaxX(), + rRect.getMaxY() ); + } + + ::basegfx::B2DVector b2DSizeFromSize( const ::Size& rSize ) + { + return ::basegfx::B2DVector( rSize.Width(), + rSize.Height() ); + } + + ::basegfx::B2DPoint b2DPointFromPoint( const ::Point& rPoint ) + { + return ::basegfx::B2DPoint( rPoint.X(), + rPoint.Y() ); + } + + ::basegfx::B2DRange b2DRectangleFromRectangle( const ::Rectangle& rRect ) + { + return ::basegfx::B2DRange( rRect.Left(), + rRect.Top(), + rRect.Right(), + rRect.Bottom() ); + } + + basegfx::B2IVector b2ISizeFromSize( const Size& rSize ) + { + return ::basegfx::B2IVector( rSize.Width(), + rSize.Height() ); + } + + basegfx::B2IPoint b2IPointFromPoint( const Point& rPoint ) + { + return ::basegfx::B2IPoint( rPoint.X(), + rPoint.Y() ); + } + + basegfx::B2IRange b2IRectangleFromRectangle( const Rectangle& rRect ) + { + return ::basegfx::B2IRange( rRect.Left(), + rRect.Top(), + rRect.Right(), + rRect.Bottom() ); + } + + geometry::IntegerSize2D integerSize2DFromSize( const Size& rSize ) + { + return geometry::IntegerSize2D( rSize.Width(), + rSize.Height() ); + } + + geometry::IntegerPoint2D integerPoint2DFromPoint( const Point& rPoint ) + { + return geometry::IntegerPoint2D( rPoint.X(), + rPoint.Y() ); + } + + geometry::IntegerRectangle2D integerRectangle2DFromRectangle( const Rectangle& rRectangle ) + { + return geometry::IntegerRectangle2D( rRectangle.Left(), rRectangle.Top(), + rRectangle.Right(), rRectangle.Bottom() ); + } + + Size sizeFromIntegerSize2D( const geometry::IntegerSize2D& rSize ) + { + return Size( rSize.Width, + rSize.Height ); + } + + Point pointFromIntegerPoint2D( const geometry::IntegerPoint2D& rPoint ) + { + return Point( rPoint.X, + rPoint.Y ); + } + + Rectangle rectangleFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRectangle ) + { + return Rectangle( rRectangle.X1, rRectangle.Y1, + rRectangle.X2, rRectangle.Y2 ); + } + + namespace + { + class StandardColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XColorSpace > + { + private: + uno::Sequence< sal_Int8 > m_aComponentTags; + + virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) + { + return rendering::ColorSpaceType::RGB; + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) + { + return m_aComponentTags; + } + virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) + { + return rendering::RenderingIntent::PERCEPTUAL; + } + virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) + { + return uno::Sequence< beans::PropertyValue >(); + } + virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence<rendering::ARGBColor> aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast<rendering::XColorSpace*>(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i<nLen; i+=4 ) + { + *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]); + pIn += 4; + } + return aRes; + } + virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast<rendering::XColorSpace*>(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i<nLen; i+=4 ) + { + *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]); + pIn += 4; + } + return aRes; + } + virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast<rendering::XColorSpace*>(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i<nLen; i+=4 ) + { + *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]); + pIn += 4; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; i<nLen; ++i ) + { + *pColors++ = pIn->Red; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = 1.0; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; i<nLen; ++i ) + { + *pColors++ = pIn->Red; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; i<nLen; ++i ) + { + *pColors++ = pIn->Red/pIn->Alpha; + *pColors++ = pIn->Green/pIn->Alpha; + *pColors++ = pIn->Blue/pIn->Alpha; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + + public: + StandardColorSpace() : m_aComponentTags(4) + { + sal_Int8* pTags = m_aComponentTags.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_RED; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_BLUE; + pTags[3] = rendering::ColorComponentTag::ALPHA; + } + }; + } + + uno::Reference<rendering::XColorSpace> VCL_DLLPUBLIC createStandardColorSpace() + { + return new StandardColorSpace(); + } + + //--------------------------------------------------------------------------------------- + + uno::Sequence< double > colorToStdColorSpaceSequence( const Color& rColor ) + { + uno::Sequence< double > aRet(4); + double* pRet = aRet.getArray(); + + pRet[0] = toDoubleColor(rColor.GetRed()); + pRet[1] = toDoubleColor(rColor.GetGreen()); + pRet[2] = toDoubleColor(rColor.GetBlue()); + + // VCL's notion of alpha is different from the rest of the world's + pRet[3] = 1.0 - toDoubleColor(rColor.GetTransparency()); + + return aRet; + } + + Color stdColorSpaceSequenceToColor( const uno::Sequence< double >& rColor ) + { + ENSURE_ARG_OR_THROW( rColor.getLength() == 4, + "color must have 4 channels" ); + + Color aColor; + + aColor.SetRed ( toByteColor(rColor[0]) ); + aColor.SetGreen( toByteColor(rColor[1]) ); + aColor.SetBlue ( toByteColor(rColor[2]) ); + // VCL's notion of alpha is different from the rest of the world's + aColor.SetTransparency( 255 - toByteColor(rColor[3]) ); + + return aColor; + } + + uno::Sequence< double > VCL_DLLPUBLIC colorToDoubleSequence( + const Color& rColor, + const uno::Reference< rendering::XColorSpace >& xColorSpace ) + { + uno::Sequence<rendering::ARGBColor> aSeq(1); + aSeq[0] = rendering::ARGBColor( + 1.0-toDoubleColor(rColor.GetTransparency()), + toDoubleColor(rColor.GetRed()), + toDoubleColor(rColor.GetGreen()), + toDoubleColor(rColor.GetBlue()) ); + + return xColorSpace->convertFromARGB(aSeq); + } + + Color VCL_DLLPUBLIC doubleSequenceToColor( + const uno::Sequence< double > rColor, + const uno::Reference< rendering::XColorSpace >& xColorSpace ) + { + const rendering::ARGBColor& rARGBColor( + xColorSpace->convertToARGB(rColor)[0]); + + return Color( 255-toByteColor(rARGBColor.Alpha), + toByteColor(rARGBColor.Red), + toByteColor(rARGBColor.Green), + toByteColor(rARGBColor.Blue) ); + } + + //--------------------------------------------------------------------------------------- + + } // namespace vcltools + +} // namespace canvas + +// eof diff --git a/vcl/source/helper/evntpost.cxx b/vcl/source/helper/evntpost.cxx new file mode 100644 index 000000000000..9e200a3136c3 --- /dev/null +++ b/vcl/source/helper/evntpost.cxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + + + +#include <vcl/evntpost.hxx> +#include <vcl/svapp.hxx> + +namespace vcl +{ + +EventPoster::EventPoster( const Link& rLink ) + : m_aLink(rLink) +{ + m_nId = 0; +} + +EventPoster::~EventPoster() +{ + if ( m_nId ) + GetpApp()->RemoveUserEvent( m_nId ); +} + +void EventPoster::Post( UserEvent* pEvent ) + +{ + m_nId = GetpApp()->PostUserEvent( ( LINK( this, EventPoster, DoEvent_Impl ) ), pEvent ); +} + +IMPL_LINK_INLINE_START( EventPoster, DoEvent_Impl, UserEvent*, pEvent ) +{ + m_nId = 0; + m_aLink.Call( pEvent ); + return 0; +} +IMPL_LINK_INLINE_END( EventPoster, DoEvent_Impl, UserEvent*, pEvent ) + +} diff --git a/vcl/source/helper/lazydelete.cxx b/vcl/source/helper/lazydelete.cxx new file mode 100644 index 000000000000..7b244781c3c7 --- /dev/null +++ b/vcl/source/helper/lazydelete.cxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#ifndef LAZYDELETE_CXX +#define LAZYDELETE_CXX + +#include "vcl/window.hxx" +#include "vcl/menu.hxx" +#include "vcl/lazydelete.hxx" +#include "vcl/svdata.hxx" + +namespace vcl { + +LazyDeletorBase::LazyDeletorBase() +{ +} + +LazyDeletorBase::~LazyDeletorBase() +{ +} + +// instantiate instance pointers for LazyDeletor<Window,Menu> +template<> LazyDeletor<Window>* LazyDeletor<Window>::s_pOneInstance = NULL; +template<> LazyDeletor<Menu>* LazyDeletor<Menu>::s_pOneInstance = NULL; + +// a list for all LazyeDeletor<T> singletons +static std::vector< LazyDeletorBase* > lcl_aDeletors; + +void LazyDelete::addDeletor( LazyDeletorBase* i_pDel ) +{ + lcl_aDeletors.push_back( i_pDel ); +} + +void LazyDelete::flush() +{ + unsigned int nCount = lcl_aDeletors.size(); + for( unsigned int i = 0; i < nCount; i++ ) + delete lcl_aDeletors[i]; + lcl_aDeletors.clear(); +} + +// specialized is_less function for Window +template<> bool LazyDeletor<Window>::is_less( Window* left, Window* right ) +{ + return (left != right && right->IsChild( left, TRUE )) ? true : false; +} + +// specialized is_less function for Menu +template<> bool LazyDeletor<Menu>::is_less( Menu* left, Menu* right ) +{ + while( left && left != right ) + left = left->ImplGetStartedFrom(); + return left != NULL; +} + +DeleteOnDeinitBase::~DeleteOnDeinitBase() +{ + ImplSVData* pSVData = ImplGetSVData(); + if( pSVData && pSVData->mpDeinitDeleteList != NULL ) + pSVData->mpDeinitDeleteList->remove( this ); +} + +void DeleteOnDeinitBase::addDeinitContainer( DeleteOnDeinitBase* i_pContainer ) +{ + ImplSVData* pSVData = ImplGetSVData(); + if( ! pSVData ) + { + ImplInitSVData(); + pSVData = ImplGetSVData(); + } + + DBG_ASSERT( ! pSVData->mbDeInit, "DeleteOnDeinit added after DeiInitVCL !" ); + if( pSVData->mbDeInit ) + return; + + if( pSVData->mpDeinitDeleteList == NULL ) + pSVData->mpDeinitDeleteList = new std::list< DeleteOnDeinitBase* >(); + pSVData->mpDeinitDeleteList->push_back( i_pContainer ); +} + +void DeleteOnDeinitBase::ImplDeleteOnDeInit() +{ + ImplSVData* pSVData = ImplGetSVData(); + if( pSVData->mpDeinitDeleteList ) + { + for( std::list< vcl::DeleteOnDeinitBase* >::iterator it = pSVData->mpDeinitDeleteList->begin(); + it != pSVData->mpDeinitDeleteList->end(); ++it ) + { + (*it)->doCleanup(); + } + delete pSVData->mpDeinitDeleteList; + pSVData->mpDeinitDeleteList = NULL; + } +} + +} // namespace vcl + +#endif + diff --git a/vcl/source/helper/makefile.mk b/vcl/source/helper/makefile.mk new file mode 100644 index 000000000000..e708bdec9eaa --- /dev/null +++ b/vcl/source/helper/makefile.mk @@ -0,0 +1,56 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +ENABLE_EXCEPTIONS=TRUE +PRJNAME=vcl +TARGET=helper +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile2.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES=\ + $(SLO)$/strhelper.obj \ + $(SLO)$/evntpost.obj \ + $(SLO)$/canvasbitmap.obj \ + $(SLO)$/canvastools.obj \ + $(SLO)$/xconnection.obj \ + $(SLO)$/threadex.obj \ + $(SLO)$/smartid.obj \ + $(SLO)$/lazydelete.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.INCLUDE : $(PRJ)$/util$/target.pmk diff --git a/vcl/source/helper/smartid.cxx b/vcl/source/helper/smartid.cxx new file mode 100755 index 000000000000..c367aeb2bce5 --- /dev/null +++ b/vcl/source/helper/smartid.cxx @@ -0,0 +1,264 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" +#include <vcl/smartid.hxx> + +struct ImplSmartIdData +{ + String aUId; + ULONG nUId; + BOOL bHasStringId; + BOOL bHasNumericId; +}; + + +ImplSmartIdData* SmartId::GetSmartIdData() +{ + if ( !mpData ) + { + mpData = new ImplSmartIdData; +// mpData->aUId = ""; + mpData->nUId = 0; + mpData->bHasStringId = FALSE; + mpData->bHasNumericId = FALSE; + } + return mpData; +} + + +SmartId::SmartId( const String& rId ) +: mpData( NULL ) +{ + GetSmartIdData()->aUId = rId; + GetSmartIdData()->bHasStringId = TRUE; +} + +SmartId::SmartId( ULONG nId ) +: mpData( NULL ) +{ + GetSmartIdData()->nUId = nId; + GetSmartIdData()->bHasNumericId = TRUE; +} + +SmartId::SmartId( const String& rId, ULONG nId ) +: mpData( NULL ) +{ + GetSmartIdData()->aUId = rId; + GetSmartIdData()->bHasStringId = TRUE; + GetSmartIdData()->nUId = nId; + GetSmartIdData()->bHasNumericId = TRUE; +} + +SmartId::SmartId() +: mpData( NULL ) +{} + +SmartId::SmartId( const SmartId& rId ) +: mpData( NULL ) +{ + if ( rId.mpData ) + { + GetSmartIdData(); + mpData->aUId = rId.mpData->aUId; + mpData->bHasStringId = rId.mpData->bHasStringId; + mpData->nUId = rId.mpData->nUId; + mpData->bHasNumericId = rId.mpData->bHasNumericId; + } +} + +SmartId& SmartId::operator = ( const SmartId& rId ) +{ + if ( rId.mpData ) + GetSmartIdData(); + else + { + delete mpData; + mpData = NULL; + } + if ( mpData && rId.mpData ) + { + mpData->aUId = rId.mpData->aUId; + mpData->bHasStringId = rId.mpData->bHasStringId; + mpData->nUId = rId.mpData->nUId; + mpData->bHasNumericId = rId.mpData->bHasNumericId; + } + return *this; +} + +SmartId::~SmartId() +{ + if ( mpData ) + delete mpData; +#ifdef DBG_UTIL + if ( mpData ) + mpData = (ImplSmartIdData*)0xDeadBeef; +#endif +} + +void SmartId::UpdateId( const SmartId& rId, SmartIdUpdateMode aMode ) +{ + // Check if ImplData is needed + if ( aMode != SMART_SET_SMART || ( rId.HasString() || rId.HasNumeric() ) ) + GetSmartIdData(); + + if ( aMode == SMART_SET_STR || aMode == SMART_SET_ALL || ( aMode == SMART_SET_SMART && rId.HasString() ) ) + { + GetSmartIdData()->aUId = rId.GetStr(); + GetSmartIdData()->bHasStringId = rId.HasString(); + } + if ( aMode == SMART_SET_NUM || aMode == SMART_SET_ALL || ( aMode == SMART_SET_SMART && rId.HasNumeric() ) ) + { + GetSmartIdData()->nUId = rId.GetNum(); + GetSmartIdData()->bHasNumericId = rId.HasNumeric(); + } + + // remove ImplData when no IDs are set. This is Important because Implementation of Equals() Matches and HasAny relies on it + if ( mpData && !mpData->bHasStringId && !mpData->bHasNumericId ) + { + delete mpData; + mpData = NULL; + } +} + +BOOL SmartId::HasNumeric() const +{ + if ( !mpData ) + return FALSE; + else + return mpData->bHasNumericId; +} + +BOOL SmartId::HasString() const +{ + if ( !mpData ) + return FALSE; + else + return mpData->bHasStringId; +} + +BOOL SmartId::HasAny() const +{ + return mpData != NULL; +} + +ULONG SmartId::GetNum() const +{ + if ( !mpData ) + return 0; + else + return mpData->nUId; +} + +String SmartId::GetStr() const +{ + if ( !mpData ) + return String(); + else + return mpData->aUId; +} + + +String SmartId::GetText() const // return String for UI usage +{ + String aRes; + if ( HasNumeric() ) + aRes = String::CreateFromInt64( GetNum() ); + if ( HasString() ) + { + if ( HasNumeric() ) + aRes.AppendAscii( "/" ); + aRes.Append( GetStr() ); + } + return aRes; +} + +BOOL SmartId::Matches( const String &rId )const +{ + if ( HasString() ) + return GetStr().EqualsIgnoreCaseAscii( rId ); + else + return FALSE; +} + +BOOL SmartId::Matches( const ULONG nId ) const +{ + if ( HasNumeric() ) + return GetNum() == nId; + else + return FALSE; +} + +/****************************************************************************** +If Both Ids have nither Strings nor Numbers they don't match +If both Ids have Strings the result of Matching these is returned. +Numbers are then Ignored. +Else Matching Numbers is attempted. +******************************************************************************/ +BOOL SmartId::Matches( const SmartId &rId ) const +{ + if ( !mpData || !rId.mpData ) + return FALSE; + else if ( HasString() && rId.HasString() ) + return Matches( rId.GetStr() ); + else + return rId.HasNumeric() && Matches( rId.GetNum() ); +} + +BOOL SmartId::Equals( const SmartId &rId ) const +{ + if ( mpData && rId.mpData ) + return mpData->aUId.EqualsIgnoreCaseAscii( rId.mpData->aUId ) + && mpData->bHasStringId == rId.mpData->bHasStringId + && mpData->nUId == rId.mpData->nUId + && mpData->bHasNumericId == rId.mpData->bHasNumericId; + else if ( !mpData && !rId.mpData ) + return TRUE; + else + return FALSE; +} + +BOOL SmartId::operator == ( const SmartId& rRight ) const +{ + return Equals( rRight ); +} + +BOOL SmartId::operator < ( const SmartId& rRight ) const +{ + if ( HasString() && rRight.HasString() && GetStr() != rRight.GetStr() ) + return GetStr() < rRight.GetStr(); + else if ( HasNumeric() && rRight.HasNumeric() && GetNum() != rRight.GetNum() ) + return GetNum() < rRight.GetNum(); + else + { // Sort Strings to Front + if ( HasString() ) + return rRight.HasString() && rRight.HasNumeric(); + else + return rRight.HasString() || (!HasNumeric() && rRight.HasNumeric()); + } +} diff --git a/vcl/source/helper/strhelper.cxx b/vcl/source/helper/strhelper.cxx new file mode 100644 index 000000000000..db622073cea9 --- /dev/null +++ b/vcl/source/helper/strhelper.cxx @@ -0,0 +1,442 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include "vcl/strhelper.hxx" +#include "sal/alloca.h" + +namespace psp { + +inline int isSpace( char cChar ) +{ + return + cChar == ' ' || cChar == '\t' || + cChar == '\r' || cChar == '\n' || + cChar == 0x0c || cChar == 0x0b; +} + +inline int isSpace( sal_Unicode cChar ) +{ + return + cChar == ' ' || cChar == '\t' || + cChar == '\r' || cChar == '\n' || + cChar == 0x0c || cChar == 0x0b; +} + +inline int isProtect( char cChar ) +{ + return cChar == '`' || cChar == '\'' || cChar == '"'; +} + +inline int isProtect( sal_Unicode cChar ) +{ + return cChar == '`' || cChar == '\'' || cChar == '"'; +} + +inline void CopyUntil( char*& pTo, const char*& pFrom, char cUntil, int bIncludeUntil = 0 ) +{ + do + { + if( *pFrom == '\\' ) + { + pFrom++; + if( *pFrom ) + { + *pTo = *pFrom; + pTo++; + } + } + else if( bIncludeUntil || ! isProtect( *pFrom ) ) + { + *pTo = *pFrom; + pTo++; + } + pFrom++; + } while( *pFrom && *pFrom != cUntil ); + // copy the terminating character unless zero or protector + if( ! isProtect( *pFrom ) || bIncludeUntil ) + { + *pTo = *pFrom; + if( *pTo ) + pTo++; + } + if( *pFrom ) + pFrom++; +} + +inline void CopyUntil( sal_Unicode*& pTo, const sal_Unicode*& pFrom, sal_Unicode cUntil, int bIncludeUntil = 0 ) +{ + do + { + if( *pFrom == '\\' ) + { + pFrom++; + if( *pFrom ) + { + *pTo = *pFrom; + pTo++; + } + } + else if( bIncludeUntil || ! isProtect( *pFrom ) ) + { + *pTo = *pFrom; + pTo++; + } + pFrom++; + } while( *pFrom && *pFrom != cUntil ); + // copy the terminating character unless zero or protector + if( ! isProtect( *pFrom ) || bIncludeUntil ) + { + *pTo = *pFrom; + if( *pTo ) + pTo++; + } + if( *pFrom ) + pFrom++; +} + +String GetCommandLineToken( int nToken, const String& rLine ) +{ + int nLen = rLine.Len(); + if( ! nLen ) + return String(); + + int nActualToken = 0; + sal_Unicode* pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*( nLen + 1 ) ); + const sal_Unicode* pRun = rLine.GetBuffer(); + sal_Unicode* pLeap = NULL; + + while( *pRun && nActualToken <= nToken ) + { + while( *pRun && isSpace( *pRun ) ) + pRun++; + pLeap = pBuffer; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + *pLeap = *pRun; + pLeap++; + if( *pRun ) + pRun++; + } + else if( *pRun == '`' ) + CopyUntil( pLeap, pRun, '`' ); + else if( *pRun == '\'' ) + CopyUntil( pLeap, pRun, '\'' ); + else if( *pRun == '"' ) + CopyUntil( pLeap, pRun, '"' ); + else + { + *pLeap = *pRun; + pLeap++; + pRun++; + } + } + if( nActualToken != nToken ) + pBuffer[0] = 0; + nActualToken++; + } + + *pLeap = 0; + + String aRet( pBuffer ); + return aRet; +} + +ByteString GetCommandLineToken( int nToken, const ByteString& rLine ) +{ + int nLen = rLine.Len(); + if( ! nLen ) + return ByteString(); + + int nActualToken = 0; + char* pBuffer = (char*)alloca( nLen + 1 ); + const char* pRun = rLine.GetBuffer(); + char* pLeap = NULL; + + while( *pRun && nActualToken <= nToken ) + { + while( *pRun && isSpace( *pRun ) ) + pRun++; + pLeap = pBuffer; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + *pLeap = *pRun; + pLeap++; + if( *pRun ) + pRun++; + } + else if( *pRun == '`' ) + CopyUntil( pLeap, pRun, '`' ); + else if( *pRun == '\'' ) + CopyUntil( pLeap, pRun, '\'' ); + else if( *pRun == '"' ) + CopyUntil( pLeap, pRun, '"' ); + else + { + *pLeap = *pRun; + pLeap++; + pRun++; + } + } + if( nActualToken != nToken ) + pBuffer[0] = 0; + nActualToken++; + } + + *pLeap = 0; + + ByteString aRet( pBuffer ); + return aRet; +} + +int GetCommandLineTokenCount( const String& rLine ) +{ + if( ! rLine.Len() ) + return 0; + + int nTokenCount = 0; + const sal_Unicode *pRun = rLine.GetBuffer(); + + + while( *pRun ) + { + while( *pRun && isSpace( *pRun ) ) + pRun++; + if( ! *pRun ) + break; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + if( *pRun ) + pRun++; + } + else if( *pRun == '`' ) + { + do pRun++; while( *pRun && *pRun != '`' ); + if( *pRun ) + pRun++; + } + else if( *pRun == '\'' ) + { + do pRun++; while( *pRun && *pRun != '\'' ); + if( *pRun ) + pRun++; + } + else if( *pRun == '"' ) + { + do pRun++; while( *pRun && *pRun != '"' ); + if( *pRun ) + pRun++; + } + else + pRun++; + } + nTokenCount++; + } + + return nTokenCount; +} + +int GetCommandLineTokenCount( const ByteString& rLine ) +{ + if( ! rLine.Len() ) + return 0; + + int nTokenCount = 0; + const char *pRun = rLine.GetBuffer(); + + + while( *pRun ) + { + while( *pRun && isSpace( *pRun ) ) + pRun++; + if( ! *pRun ) + break; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + if( *pRun ) + pRun++; + } + else if( *pRun == '`' ) + { + do pRun++; while( *pRun && *pRun != '`' ); + if( *pRun ) + pRun++; + } + else if( *pRun == '\'' ) + { + do pRun++; while( *pRun && *pRun != '\'' ); + if( *pRun ) + pRun++; + } + else if( *pRun == '"' ) + { + do pRun++; while( *pRun && *pRun != '"' ); + if( *pRun ) + pRun++; + } + else + pRun++; + } + nTokenCount++; + } + + return nTokenCount; +} + +String WhitespaceToSpace( const String& rLine, BOOL bProtect ) +{ + int nLen = rLine.Len(); + if( ! nLen ) + return String(); + + sal_Unicode *pBuffer = (sal_Unicode*)alloca( sizeof(sal_Unicode)*(nLen + 1) ); + const sal_Unicode *pRun = rLine.GetBuffer(); + sal_Unicode *pLeap = pBuffer; + + while( *pRun ) + { + if( *pRun && isSpace( *pRun ) ) + { + *pLeap = ' '; + pLeap++; + pRun++; + } + while( *pRun && isSpace( *pRun ) ) + pRun++; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + *pLeap = *pRun; + pLeap++; + if( *pRun ) + pRun++; + } + else if( bProtect && *pRun == '`' ) + CopyUntil( pLeap, pRun, '`', TRUE ); + else if( bProtect && *pRun == '\'' ) + CopyUntil( pLeap, pRun, '\'', TRUE ); + else if( bProtect && *pRun == '"' ) + CopyUntil( pLeap, pRun, '"', TRUE ); + else + { + *pLeap = *pRun; + *pLeap++; + *pRun++; + } + } + } + + *pLeap = 0; + + // there might be a space at beginning or end + pLeap--; + if( *pLeap == ' ' ) + *pLeap = 0; + + String aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer ); + return aRet; +} + +ByteString WhitespaceToSpace( const ByteString& rLine, BOOL bProtect ) +{ + int nLen = rLine.Len(); + if( ! nLen ) + return ByteString(); + + char *pBuffer = (char*)alloca( nLen + 1 ); + const char *pRun = rLine.GetBuffer(); + char *pLeap = pBuffer; + + while( *pRun ) + { + if( *pRun && isSpace( *pRun ) ) + { + *pLeap = ' '; + pLeap++; + pRun++; + } + while( *pRun && isSpace( *pRun ) ) + pRun++; + while( *pRun && ! isSpace( *pRun ) ) + { + if( *pRun == '\\' ) + { + // escapement + pRun++; + *pLeap = *pRun; + pLeap++; + if( *pRun ) + pRun++; + } + else if( bProtect && *pRun == '`' ) + CopyUntil( pLeap, pRun, '`', TRUE ); + else if( bProtect && *pRun == '\'' ) + CopyUntil( pLeap, pRun, '\'', TRUE ); + else if( bProtect && *pRun == '"' ) + CopyUntil( pLeap, pRun, '"', TRUE ); + else + { + *pLeap = *pRun; + *pLeap++; + *pRun++; + } + } + } + + *pLeap = 0; + + // there might be a space at beginning or end + pLeap--; + if( *pLeap == ' ' ) + *pLeap = 0; + + ByteString aRet( *pBuffer == ' ' ? pBuffer+1 : pBuffer ); + return aRet; +} + +} // namespace diff --git a/vcl/source/helper/threadex.cxx b/vcl/source/helper/threadex.cxx new file mode 100644 index 000000000000..133b19aa0538 --- /dev/null +++ b/vcl/source/helper/threadex.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#define THREADEX_IMPLEMENTATION +#include <vcl/threadex.hxx> +#include <vcl/svapp.hxx> + +using namespace vcl; + +ThreadExecutor::ThreadExecutor() +{ + m_aFinish = osl_createCondition(); + m_aThread = NULL; +} + +ThreadExecutor::~ThreadExecutor() +{ + osl_destroyCondition( m_aFinish ); + if( m_aThread ) + osl_destroyThread( m_aThread ); +} + +extern "C" +{ + static void call_worker( void* pInstance ) + { + ThreadExecutor::worker( pInstance ); + } +} + +void ThreadExecutor::worker( void* pInstance ) +{ + ThreadExecutor* pThis = ((ThreadExecutor*)pInstance); + pThis->m_nReturn = pThis->doIt(); + osl_setCondition( pThis->m_aFinish ); +} + +long ThreadExecutor::execute() +{ + osl_resetCondition( m_aFinish ); + if( m_aThread ) + osl_destroyThread( m_aThread ), m_aThread = NULL; + m_aThread = osl_createThread( call_worker, this ); + while( ! osl_checkCondition( m_aFinish ) ) + Application::Reschedule(); + return m_nReturn; +} + + +SolarThreadExecutor::SolarThreadExecutor() + :m_nReturn( 0 ) + ,m_bTimeout( false ) +{ + m_aStart = osl_createCondition(); + m_aFinish = osl_createCondition(); +} + +SolarThreadExecutor::~SolarThreadExecutor() +{ + osl_destroyCondition( m_aStart ); + osl_destroyCondition( m_aFinish ); +} + +IMPL_LINK( SolarThreadExecutor, worker, void*, EMPTYARG ) +{ + if ( !m_bTimeout ) + { + osl_setCondition( m_aStart ); + m_nReturn = doIt(); + osl_setCondition( m_aFinish ); + } + return m_nReturn; +} + +long SolarThreadExecutor::impl_execute( const TimeValue* _pTimeout ) +{ + if( ::vos::OThread::getCurrentIdentifier() == Application::GetMainThreadIdentifier() ) + { + osl_setCondition( m_aStart ); + m_nReturn = doIt(); + osl_setCondition( m_aFinish ); + } + else + { + osl_resetCondition( m_aStart ); + osl_resetCondition( m_aFinish ); + ULONG nSolarMutexCount = Application::ReleaseSolarMutex(); + ULONG nEvent = Application::PostUserEvent( LINK( this, SolarThreadExecutor, worker ) ); + if ( osl_cond_result_timeout == osl_waitCondition( m_aStart, _pTimeout ) ) + { + m_bTimeout = true; + Application::RemoveUserEvent( nEvent ); + } + else + osl_waitCondition( m_aFinish, NULL ); + if( nSolarMutexCount ) + Application::AcquireSolarMutex( nSolarMutexCount ); + } + return m_nReturn; +} diff --git a/vcl/source/helper/xconnection.cxx b/vcl/source/helper/xconnection.cxx new file mode 100644 index 000000000000..caf7ee237d67 --- /dev/null +++ b/vcl/source/helper/xconnection.cxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include "svsys.h" +#include "vcl/xconnection.hxx" +#include "vcl/svdata.hxx" +#include "vcl/salinst.hxx" +#include "vcl/svapp.hxx" + +namespace vcl +{ + class SolarMutexReleaser + { + ULONG mnReleased; + public: + SolarMutexReleaser() + { + mnReleased = Application::ReleaseSolarMutex(); + } + + ~SolarMutexReleaser() + { + if( mnReleased ) + Application::AcquireSolarMutex( mnReleased ); + } + }; +} + +using namespace rtl; +using namespace osl; +using namespace vcl; +using namespace com::sun::star::uno; +using namespace com::sun::star::awt; + + +DisplayConnection::DisplayConnection() +{ + ImplSVData* pSVData = ImplGetSVData(); + pSVData->mpDefInst->SetEventCallback( this, dispatchEvent ); + pSVData->mpDefInst->SetErrorEventCallback( this, dispatchErrorEvent ); + + SalInstance::ConnectionIdentifierType eType; + int nBytes; + void* pBytes = pSVData->mpDefInst->GetConnectionIdentifier( eType, nBytes ); + switch( eType ) + { + case SalInstance::AsciiCString: + m_aAny <<= OUString::createFromAscii( (sal_Char*)pBytes ); + break; + case SalInstance::Blob: + m_aAny <<= Sequence< sal_Int8 >( (sal_Int8*)pBytes, nBytes ); + break; + } +} + +DisplayConnection::~DisplayConnection() +{ + ImplSVData* pSVData = ImplGetSVData(); + + if( pSVData ) + { + pSVData->mpDefInst->SetEventCallback( NULL, NULL ); + pSVData->mpDefInst->SetErrorEventCallback( NULL, NULL ); + } +} + + +void SAL_CALL DisplayConnection::addEventHandler( const Any& /*window*/, const Reference< XEventHandler >& handler, sal_Int32 /*eventMask*/ ) throw() +{ + MutexGuard aGuard( m_aMutex ); + + m_aHandlers.push_back( handler ); +} + +void SAL_CALL DisplayConnection::removeEventHandler( const Any& /*window*/, const Reference< XEventHandler >& handler ) throw() +{ + MutexGuard aGuard( m_aMutex ); + + m_aHandlers.remove( handler ); +} + +void SAL_CALL DisplayConnection::addErrorHandler( const Reference< XEventHandler >& handler ) throw() +{ + MutexGuard aGuard( m_aMutex ); + + m_aErrorHandlers.push_back( handler ); +} + +void SAL_CALL DisplayConnection::removeErrorHandler( const Reference< XEventHandler >& handler ) throw() +{ + MutexGuard aGuard( m_aMutex ); + + m_aErrorHandlers.remove( handler ); +} + +Any SAL_CALL DisplayConnection::getIdentifier() throw() +{ + return m_aAny; +} + +void DisplayConnection::dispatchDowningEvent() +{ + SolarMutexReleaser aRel; + + MutexGuard aGuard( m_aMutex ); + Any aEvent; + std::list< Reference< XEventHandler > > aLocalList( m_aHandlers ); + for( ::std::list< Reference< XEventHandler > >::const_iterator it = aLocalList.begin(); it != aLocalList.end(); ++it ) + (*it)->handleEvent( aEvent ); +} + +bool DisplayConnection::dispatchEvent( void* pThis, void* pData, int nBytes ) +{ + SolarMutexReleaser aRel; + + DisplayConnection* This = (DisplayConnection*)pThis; + + Sequence< sal_Int8 > aSeq( (sal_Int8*)pData, nBytes ); + Any aEvent; + aEvent <<= aSeq; + ::std::list< Reference< XEventHandler > > handlers; + { + MutexGuard aGuard( This->m_aMutex ); + handlers = This->m_aHandlers; + } + for( ::std::list< Reference< XEventHandler > >::const_iterator it = handlers.begin(); it != handlers.end(); ++it ) + if( (*it)->handleEvent( aEvent ) ) + return true; + return false; +} + +bool DisplayConnection::dispatchErrorEvent( void* pThis, void* pData, int nBytes ) +{ + SolarMutexReleaser aRel; + + DisplayConnection* This = (DisplayConnection*)pThis; + + Sequence< sal_Int8 > aSeq( (sal_Int8*)pData, nBytes ); + Any aEvent; + aEvent <<= aSeq; + ::std::list< Reference< XEventHandler > > handlers; + { + MutexGuard aGuard( This->m_aMutex ); + handlers = This->m_aErrorHandlers; + } + for( ::std::list< Reference< XEventHandler > >::const_iterator it = handlers.begin(); it != handlers.end(); ++it ) + if( (*it)->handleEvent( aEvent ) ) + return true; + + return false; +} |