summaryrefslogtreecommitdiff
path: root/vcl/source/image
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-11-19 12:57:52 +0100
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2015-11-19 13:02:54 +0100
commit25d60232ff5d882017ffb88453f16fd6cef5534c (patch)
treeb62faddecbe82d0c75a51335c6518e3cdb20f558 /vcl/source/image
parent6480b4d11a0cf2dd489d30b6290aa6d831704a45 (diff)
vcl: move and split up "Image" related sources to "image" folder
This commit moves all sources related to Image class into its own "vcl/source/image" folder. Sources containing more classes were split up into its own source file. Change-Id: Ie6edcdb0a7caf936bccdc210c31f78bb15667945
Diffstat (limited to 'vcl/source/image')
-rw-r--r--vcl/source/image/Image.cxx277
-rw-r--r--vcl/source/image/ImageArrayData.cxx58
-rw-r--r--vcl/source/image/ImageList.cxx462
-rw-r--r--vcl/source/image/ImageRepository.cxx43
-rw-r--r--vcl/source/image/ImplImage.cxx53
-rw-r--r--vcl/source/image/ImplImageBmp.cxx287
-rw-r--r--vcl/source/image/ImplImageData.cxx48
-rw-r--r--vcl/source/image/ImplImageList.cxx75
-rw-r--r--vcl/source/image/ImplImageTree.cxx439
9 files changed, 1742 insertions, 0 deletions
diff --git a/vcl/source/image/Image.cxx b/vcl/source/image/Image.cxx
new file mode 100644
index 000000000000..cc1f46714ce3
--- /dev/null
+++ b/vcl/source/image/Image.cxx
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/file.hxx>
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <tools/rc.h>
+#include <tools/rc.hxx>
+#include <tools/resmgr.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/image.hxx>
+#include <vcl/imagerepository.hxx>
+#include <vcl/implimagetree.hxx>
+#include <image.h>
+
+#if OSL_DEBUG_LEVEL > 0
+#include <rtl/strbuf.hxx>
+#endif
+
+using namespace ::com::sun::star;
+
+Image::Image() :
+ mpImplData( nullptr )
+{
+}
+
+Image::Image( const ResId& rResId ) :
+ mpImplData( nullptr )
+{
+
+ rResId.SetRT( RSC_IMAGE );
+
+ ResMgr* pResMgr = rResId.GetResMgr();
+ if( pResMgr && pResMgr->GetResource( rResId ) )
+ {
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ BitmapEx aBmpEx;
+ sal_uLong nObjMask = pResMgr->ReadLong();
+
+ if( nObjMask & RSC_IMAGE_IMAGEBITMAP )
+ {
+ aBmpEx = BitmapEx( ResId( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()), *pResMgr ) );
+ pResMgr->Increment( ResMgr::GetObjSize( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()) ) );
+ }
+
+ if( nObjMask & RSC_IMAGE_MASKBITMAP )
+ {
+ if( !aBmpEx.IsEmpty() && aBmpEx.GetTransparentType() == TRANSPARENT_NONE )
+ {
+ const Bitmap aMaskBitmap( ResId( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()), *pResMgr ) );
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskBitmap );
+ }
+
+ pResMgr->Increment( ResMgr::GetObjSize( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()) ) );
+ }
+
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ {
+ if( !aBmpEx.IsEmpty() && aBmpEx.GetTransparentType() == TRANSPARENT_NONE )
+ {
+ const Color aMaskColor( ResId( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()), *pResMgr ) );
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskColor );
+ }
+
+ pResMgr->Increment( ResMgr::GetObjSize( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()) ) );
+ }
+ if( ! aBmpEx.IsEmpty() )
+ ImplInit( aBmpEx );
+ }
+}
+
+Image::Image( const Image& rImage ) :
+ mpImplData( rImage.mpImplData )
+{
+
+ if( mpImplData )
+ ++mpImplData->mnRefCount;
+}
+
+Image::Image( const BitmapEx& rBitmapEx ) :
+ mpImplData( nullptr )
+{
+
+ ImplInit( rBitmapEx );
+}
+
+Image::Image( const Bitmap& rBitmap ) :
+ mpImplData( nullptr )
+{
+
+ ImplInit( rBitmap );
+}
+
+Image::Image( const Bitmap& rBitmap, const Bitmap& rMaskBitmap ) :
+ mpImplData( nullptr )
+{
+
+ const BitmapEx aBmpEx( rBitmap, rMaskBitmap );
+
+ ImplInit( aBmpEx );
+}
+
+Image::Image( const Bitmap& rBitmap, const Color& rColor ) :
+ mpImplData( nullptr )
+{
+
+ const BitmapEx aBmpEx( rBitmap, rColor );
+
+ ImplInit( aBmpEx );
+}
+
+Image::Image( const uno::Reference< graphic::XGraphic >& rxGraphic ) :
+ mpImplData( nullptr )
+{
+
+ const Graphic aGraphic( rxGraphic );
+ ImplInit( aGraphic.GetBitmapEx() );
+}
+
+Image::Image( const OUString &rFileUrl ) :
+ mpImplData( nullptr )
+{
+ OUString aTmp;
+ osl::FileBase::getSystemPathFromFileURL( rFileUrl, aTmp );
+ Graphic aGraphic;
+ const OUString aFilterName( IMP_PNG );
+ if( GRFILTER_OK == GraphicFilter::LoadGraphic( aTmp, aFilterName, aGraphic ) )
+ {
+ ImplInit( aGraphic.GetBitmapEx() );
+ }
+}
+
+Image::~Image()
+{
+
+ if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
+ delete mpImplData;
+}
+
+void Image::ImplInit( const BitmapEx& rBmpEx )
+{
+ if( !rBmpEx.IsEmpty() )
+ {
+ mpImplData = new ImplImage;
+
+ if( rBmpEx.GetTransparentType() == TRANSPARENT_NONE )
+ {
+ mpImplData->meType = IMAGETYPE_BITMAP;
+ mpImplData->mpData = new Bitmap( rBmpEx.GetBitmap() );
+ }
+ else
+ {
+ mpImplData->meType = IMAGETYPE_IMAGE;
+ mpImplData->mpData = new ImplImageData( rBmpEx );
+ }
+ }
+}
+
+Size Image::GetSizePixel() const
+{
+
+ Size aRet;
+
+ if( mpImplData )
+ {
+ switch( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ aRet = static_cast< Bitmap* >( mpImplData->mpData )->GetSizePixel();
+ break;
+
+ case IMAGETYPE_IMAGE:
+ aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx.GetSizePixel();
+ break;
+ }
+ }
+
+ return aRet;
+}
+
+BitmapEx Image::GetBitmapEx() const
+{
+
+ BitmapEx aRet;
+
+ if( mpImplData )
+ {
+ switch( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ aRet = *static_cast< Bitmap* >( mpImplData->mpData );
+ break;
+
+ case IMAGETYPE_IMAGE:
+ aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx;
+ break;
+ }
+ }
+
+ return aRet;
+}
+
+uno::Reference< graphic::XGraphic > Image::GetXGraphic() const
+{
+ const Graphic aGraphic( GetBitmapEx() );
+
+ return aGraphic.GetXGraphic();
+}
+
+Image& Image::operator=( const Image& rImage )
+{
+
+ if( rImage.mpImplData )
+ ++rImage.mpImplData->mnRefCount;
+
+ if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
+ delete mpImplData;
+
+ mpImplData = rImage.mpImplData;
+
+ return *this;
+}
+
+bool Image::operator==( const Image& rImage ) const
+{
+
+ bool bRet = false;
+
+ if( rImage.mpImplData == mpImplData )
+ bRet = true;
+ else if( !rImage.mpImplData || !mpImplData )
+ bRet = false;
+ else if( rImage.mpImplData->mpData == mpImplData->mpData )
+ bRet = true;
+ else if( rImage.mpImplData->meType == mpImplData->meType )
+ {
+ switch( mpImplData->meType )
+ {
+ case IMAGETYPE_BITMAP:
+ bRet = ( *static_cast< Bitmap* >( rImage.mpImplData->mpData ) == *static_cast< Bitmap* >( mpImplData->mpData ) );
+ break;
+
+ case IMAGETYPE_IMAGE:
+ bRet = static_cast< ImplImageData* >( rImage.mpImplData->mpData )->IsEqual( *static_cast< ImplImageData* >( mpImplData->mpData ) );
+ break;
+
+ default:
+ bRet = false;
+ break;
+ }
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImageArrayData.cxx b/vcl/source/image/ImageArrayData.cxx
new file mode 100644
index 000000000000..d7b3bbbcf0ba
--- /dev/null
+++ b/vcl/source/image/ImageArrayData.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <image.h>
+#include <memory>
+
+ImageAryData::ImageAryData( const ImageAryData& rData ) :
+ maName( rData.maName ),
+ mnId( rData.mnId ),
+ maBitmapEx( rData.maBitmapEx )
+{
+}
+
+ImageAryData::ImageAryData( const OUString &aName,
+ sal_uInt16 nId, const BitmapEx &aBitmap )
+ : maName( aName ), mnId( nId ), maBitmapEx( aBitmap )
+{
+}
+
+ImageAryData::~ImageAryData()
+{
+}
+
+ImageAryData& ImageAryData::operator=( const ImageAryData& rData )
+{
+ maName = rData.maName;
+ mnId = rData.mnId;
+ maBitmapEx = rData.maBitmapEx;
+
+ return *this;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImageList.cxx b/vcl/source/image/ImageList.cxx
new file mode 100644
index 000000000000..6c2dff965074
--- /dev/null
+++ b/vcl/source/image/ImageList.cxx
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/file.hxx>
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <tools/rc.h>
+#include <tools/rc.hxx>
+#include <tools/resmgr.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/image.hxx>
+#include <vcl/imagerepository.hxx>
+#include <vcl/implimagetree.hxx>
+#include <image.h>
+
+#if OSL_DEBUG_LEVEL > 0
+#include <rtl/strbuf.hxx>
+#endif
+
+using namespace ::com::sun::star;
+
+ImageList::ImageList( sal_uInt16 nInit, sal_uInt16 nGrow ) :
+ mpImplData( nullptr ),
+ mnInitSize( nInit ),
+ mnGrowSize( nGrow )
+{
+}
+
+ImageList::ImageList( const ResId& rResId ) :
+ mpImplData( nullptr ),
+ mnInitSize( 1 ),
+ mnGrowSize( 4 )
+{
+ SAL_INFO( "vcl.gdi", "vcl: ImageList::ImageList( const ResId& rResId )" );
+
+ rResId.SetRT( RSC_IMAGELIST );
+
+ ResMgr* pResMgr = rResId.GetResMgr();
+
+ if( pResMgr && pResMgr->GetResource( rResId ) )
+ {
+ pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
+
+ sal_uLong nObjMask = pResMgr->ReadLong();
+ pResMgr->ReadString(); //skip string
+ std::unique_ptr< Color > xMaskColor;
+
+ if( nObjMask & RSC_IMAGE_MASKCOLOR )
+ xMaskColor.reset( new Color( ResId( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()), *pResMgr ) ) );
+
+ pResMgr->Increment( ResMgr::GetObjSize( static_cast<RSHEADER_TYPE*>(pResMgr->GetClass()) ) );
+
+ if( nObjMask & RSC_IMAGELIST_IDLIST )
+ {
+ for( sal_Int32 i = 0, nCount = pResMgr->ReadLong(); i < nCount; ++i )
+ pResMgr->ReadLong();
+ }
+
+ sal_Int32 nCount = pResMgr->ReadLong();
+ ImplInit( static_cast< sal_uInt16 >( nCount ), Size() );
+
+ BitmapEx aEmpty;
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ OUString aName = pResMgr->ReadString();
+ sal_uInt16 nId = static_cast< sal_uInt16 >( pResMgr->ReadLong() );
+ mpImplData->AddImage( aName, nId, aEmpty );
+ }
+
+ if( nObjMask & RSC_IMAGELIST_IDCOUNT )
+ pResMgr->ReadShort();
+ }
+}
+
+ImageList::ImageList( const ::std::vector< OUString >& rNameVector,
+ const OUString& rPrefix,
+ const Color* ) :
+ mpImplData( nullptr ),
+ mnInitSize( 1 ),
+ mnGrowSize( 4 )
+{
+ SAL_INFO( "vcl.gdi", "vcl: ImageList::ImageList(const vector< OUString >& ..." );
+
+ ImplInit( sal::static_int_cast< sal_uInt16 >( rNameVector.size() ), Size() );
+
+ mpImplData->maPrefix = rPrefix;
+ for( size_t i = 0; i < rNameVector.size(); ++i )
+ {
+ mpImplData->AddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
+ }
+}
+
+ImageList::ImageList( const ImageList& rImageList ) :
+ mpImplData( rImageList.mpImplData ),
+ mnInitSize( rImageList.mnInitSize ),
+ mnGrowSize( rImageList.mnGrowSize )
+{
+
+ if( mpImplData )
+ ++mpImplData->mnRefCount;
+}
+
+ImageList::~ImageList()
+{
+ if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
+ delete mpImplData;
+}
+
+void ImageList::ImplInit( sal_uInt16 nItems, const Size &rSize )
+{
+ mpImplData = new ImplImageList;
+ mpImplData->maImages.reserve( nItems );
+ mpImplData->maImageSize = rSize;
+}
+
+void ImageAryData::Load(const OUString &rPrefix)
+{
+ OUString aIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+
+ OUString aFileName = rPrefix;
+ aFileName += maName;
+#if OSL_DEBUG_LEVEL > 0
+ bool bSuccess =
+#endif
+ ImplImageTree::get().loadImage(aFileName, aIconTheme, maBitmapEx, true);
+#if OSL_DEBUG_LEVEL > 0
+ if ( !bSuccess )
+ {
+ OStringBuffer aMessage;
+ aMessage.append( "ImageAryData::Load: failed to load image '" );
+ aMessage.append( OUStringToOString( aFileName, RTL_TEXTENCODING_UTF8 ).getStr() );
+ aMessage.append( "'" );
+ OSL_FAIL( aMessage.makeStringAndClear().getStr() );
+ }
+#endif
+}
+
+// FIXME: Rather a performance hazard
+BitmapEx ImageList::GetAsHorizontalStrip() const
+{
+ Size aSize( mpImplData->maImageSize );
+ sal_uInt16 nCount = GetImageCount();
+ if( !nCount )
+ return BitmapEx();
+ aSize.Width() *= nCount;
+
+ // Load any stragglers
+ for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
+ {
+ ImageAryData *pData = mpImplData->maImages[ nIdx ];
+ if( pData->IsLoadable() )
+ pData->Load( mpImplData->maPrefix );
+ }
+
+ BitmapEx aTempl = mpImplData->maImages[ 0 ]->maBitmapEx;
+ BitmapEx aResult;
+ Bitmap aPixels( aSize, aTempl.GetBitmap().GetBitCount() );
+ if( aTempl.IsAlpha() )
+ aResult = BitmapEx( aPixels, AlphaMask( aSize ) );
+ else if( aTempl.IsTransparent() )
+ aResult = BitmapEx( aPixels, Bitmap( aSize, aTempl.GetMask().GetBitCount() ) );
+ else
+ aResult = BitmapEx( aPixels );
+
+ Rectangle aSrcRect( Point( 0, 0 ), mpImplData->maImageSize );
+ for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
+ {
+ Rectangle aDestRect( Point( nIdx * mpImplData->maImageSize.Width(), 0 ),
+ mpImplData->maImageSize );
+ ImageAryData *pData = mpImplData->maImages[ nIdx ];
+ aResult.CopyPixel( aDestRect, aSrcRect, &pData->maBitmapEx);
+ }
+
+ return aResult;
+}
+
+void ImageList::InsertFromHorizontalStrip( const BitmapEx &rBitmapEx,
+ const std::vector< OUString > &rNameVector )
+{
+ sal_uInt16 nItems = sal::static_int_cast< sal_uInt16 >( rNameVector.size() );
+
+ if (!nItems)
+ return;
+
+ Size aSize( rBitmapEx.GetSizePixel() );
+ DBG_ASSERT (rBitmapEx.GetSizePixel().Width() % nItems == 0,
+ "ImageList::InsertFromHorizontalStrip - very odd size");
+ aSize.Width() /= nItems;
+ ImplInit( nItems, aSize );
+
+ for (sal_uInt16 nIdx = 0; nIdx < nItems; nIdx++)
+ {
+ BitmapEx aBitmap( rBitmapEx, Point( nIdx * aSize.Width(), 0 ), aSize );
+ mpImplData->AddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
+ }
+}
+
+void ImageList::InsertFromHorizontalBitmap( const ResId& rResId,
+ sal_uInt16 nCount,
+ const Color *pMaskColor,
+ const Color *pSearchColors,
+ const Color *pReplaceColors,
+ sal_uLong nColorCount)
+{
+ BitmapEx aBmpEx( rResId );
+ if (!aBmpEx.IsTransparent())
+ {
+ if( pMaskColor )
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap(), *pMaskColor );
+ else
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap() );
+ }
+ if ( nColorCount && pSearchColors && pReplaceColors )
+ aBmpEx.Replace( pSearchColors, pReplaceColors, nColorCount );
+
+ std::vector< OUString > aNames( nCount );
+ InsertFromHorizontalStrip( aBmpEx, aNames );
+}
+
+sal_uInt16 ImageList::ImplGetImageId( const OUString& rImageName ) const
+{
+
+ ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
+ if( pImg )
+ return pImg->mnId;
+ else
+ return 0;
+}
+
+void ImageList::AddImage( const OUString& rImageName, const Image& rImage )
+{
+ DBG_ASSERT( GetImagePos( rImageName ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::AddImage() - ImageName already exists" );
+
+ if( !mpImplData )
+ ImplInit( 0, rImage.GetSizePixel() );
+
+ mpImplData->AddImage( rImageName, GetImageCount() + 1,
+ rImage.GetBitmapEx() );
+}
+
+void ImageList::ReplaceImage( const OUString& rImageName, const Image& rImage )
+{
+ const sal_uInt16 nId = ImplGetImageId( rImageName );
+
+ if( nId )
+ {
+ //Just replace the bitmap rather than doing RemoveImage / AddImage
+ //which breaks index-based iteration.
+ ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
+ pImg->maBitmapEx = rImage.GetBitmapEx();
+ }
+}
+
+void ImageList::RemoveImage( sal_uInt16 nId )
+{
+
+ for( size_t i = 0; i < mpImplData->maImages.size(); ++i )
+ {
+ if( mpImplData->maImages[ i ]->mnId == nId )
+ {
+ mpImplData->RemoveImage( static_cast< sal_uInt16 >( i ) );
+ break;
+ }
+ }
+}
+
+Image ImageList::GetImage( sal_uInt16 nId ) const
+{
+
+ Image aRet;
+
+ if( mpImplData )
+ {
+ std::vector<ImageAryData *>::iterator aIter;
+ for( aIter = mpImplData->maImages.begin();
+ aIter != mpImplData->maImages.end(); ++aIter)
+ {
+ if ((*aIter)->mnId == nId)
+ {
+ if( (*aIter)->IsLoadable() )
+ (*aIter)->Load( mpImplData->maPrefix );
+
+ aRet = Image( (*aIter)->maBitmapEx );
+ }
+ }
+ }
+
+ if (!aRet)
+ {
+ BitmapEx rBitmap;
+ bool res = vcl::ImageRepository::loadDefaultImage(rBitmap);
+ if (res)
+ aRet = Image(rBitmap);
+ }
+
+ return aRet;
+}
+
+Image ImageList::GetImage( const OUString& rImageName ) const
+{
+ if( mpImplData )
+ {
+ ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
+
+ if( pImg )
+ {
+ if( pImg->IsLoadable() )
+ pImg->Load( mpImplData->maPrefix );
+ return Image( pImg->maBitmapEx );
+ }
+ }
+
+ return Image();
+}
+
+sal_uInt16 ImageList::GetImageCount() const
+{
+
+ return mpImplData ? static_cast< sal_uInt16 >( mpImplData->maImages.size() ) : 0;
+}
+
+sal_uInt16 ImageList::GetImagePos( sal_uInt16 nId ) const
+{
+
+ if( mpImplData && nId )
+ {
+ for( size_t i = 0; i < mpImplData->maImages.size(); ++i )
+ {
+ if (mpImplData->maImages[ i ]->mnId == nId)
+ return static_cast< sal_uInt16 >( i );
+ }
+ }
+
+ return IMAGELIST_IMAGE_NOTFOUND;
+}
+
+bool ImageList::HasImageAtPos( sal_uInt16 nId ) const
+{
+ return GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND;
+}
+
+sal_uInt16 ImageList::GetImagePos( const OUString& rImageName ) const
+{
+
+ if( mpImplData && !rImageName.isEmpty() )
+ {
+ for( size_t i = 0; i < mpImplData->maImages.size(); i++ )
+ {
+ if (mpImplData->maImages[i]->maName == rImageName)
+ return static_cast< sal_uInt16 >( i );
+ }
+ }
+
+ return IMAGELIST_IMAGE_NOTFOUND;
+}
+
+sal_uInt16 ImageList::GetImageId( sal_uInt16 nPos ) const
+{
+
+ if( mpImplData && (nPos < GetImageCount()) )
+ return mpImplData->maImages[ nPos ]->mnId;
+
+ return 0;
+}
+
+OUString ImageList::GetImageName( sal_uInt16 nPos ) const
+{
+
+ if( mpImplData && (nPos < GetImageCount()) )
+ return mpImplData->maImages[ nPos ]->maName;
+
+ return OUString();
+}
+
+void ImageList::GetImageNames( ::std::vector< OUString >& rNames ) const
+{
+ SAL_INFO( "vcl.gdi", "vcl: ImageList::GetImageNames" );
+
+ rNames = ::std::vector< OUString >();
+
+ if( mpImplData )
+ {
+ for( size_t i = 0; i < mpImplData->maImages.size(); i++ )
+ {
+ const OUString& rName( mpImplData->maImages[ i ]->maName );
+ if( !rName.isEmpty())
+ rNames.push_back( rName );
+ }
+ }
+}
+
+Size ImageList::GetImageSize() const
+{
+
+ Size aRet;
+
+ if( mpImplData )
+ {
+ aRet = mpImplData->maImageSize;
+
+ // force load of 1st image to see - uncommon case.
+ if( aRet.Width() == 0 && aRet.Height() == 0 &&
+ !mpImplData->maImages.empty() )
+ {
+ Image aTmp = GetImage( mpImplData->maImages[ 0 ]->mnId );
+ aRet = mpImplData->maImageSize = aTmp.GetSizePixel();
+ }
+ }
+ return aRet;
+}
+
+ImageList& ImageList::operator=( const ImageList& rImageList )
+{
+
+ if( rImageList.mpImplData )
+ ++rImageList.mpImplData->mnRefCount;
+
+ if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
+ delete mpImplData;
+
+ mpImplData = rImageList.mpImplData;
+
+ return *this;
+}
+
+bool ImageList::operator==( const ImageList& rImageList ) const
+{
+
+ bool bRet = false;
+
+ if( rImageList.mpImplData == mpImplData )
+ bRet = true;
+ else if( !rImageList.mpImplData || !mpImplData )
+ bRet = false;
+ else if( rImageList.GetImageCount() == GetImageCount() &&
+ rImageList.mpImplData->maImageSize == mpImplData->maImageSize )
+ bRet = true; // strange semantic
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImageRepository.cxx b/vcl/source/image/ImageRepository.cxx
new file mode 100644
index 000000000000..dadc622cdcce
--- /dev/null
+++ b/vcl/source/image/ImageRepository.cxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/bitmapex.hxx>
+#include <vcl/imagerepository.hxx>
+#include <vcl/implimagetree.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+namespace vcl
+{
+ bool ImageRepository::loadImage( const OUString& _rName, BitmapEx& _out_rImage, bool _bSearchLanguageDependent, bool loadMissing )
+ {
+ OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+
+ return ImplImageTree::get().loadImage( _rName, sIconTheme, _out_rImage, _bSearchLanguageDependent, loadMissing );
+ }
+
+ bool ImageRepository::loadDefaultImage( BitmapEx& _out_rImage)
+ {
+ OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
+ return ImplImageTree::get().loadDefaultImage( sIconTheme,_out_rImage);
+ }
+
+} // namespace vcl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImage.cxx b/vcl/source/image/ImplImage.cxx
new file mode 100644
index 000000000000..9272cf07b4e1
--- /dev/null
+++ b/vcl/source/image/ImplImage.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <image.h>
+#include <memory>
+
+ImplImage::ImplImage()
+ : mnRefCount(1)
+ , mpData(nullptr)
+ , meType(IMAGETYPE_BITMAP)
+{
+}
+
+ImplImage::~ImplImage()
+{
+ switch( meType )
+ {
+ case IMAGETYPE_BITMAP:
+ delete static_cast< Bitmap* >( mpData );
+ break;
+
+ case IMAGETYPE_IMAGE:
+ delete static_cast< ImplImageData* >( mpData );
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImageBmp.cxx b/vcl/source/image/ImplImageBmp.cxx
new file mode 100644
index 000000000000..cb83cc3ae4ea
--- /dev/null
+++ b/vcl/source/image/ImplImageBmp.cxx
@@ -0,0 +1,287 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <image.h>
+#include <memory>
+
+#define IMPSYSIMAGEITEM_MASK ( 0x01 )
+#define IMPSYSIMAGEITEM_ALPHA ( 0x02 )
+
+ImplImageBmp::ImplImageBmp()
+ : maBitmapChecksum(0)
+ , mpDisplayBmp(nullptr)
+ , mpInfoAry(nullptr)
+ , mnSize(0)
+{
+}
+
+ImplImageBmp::~ImplImageBmp()
+{
+ delete[] mpInfoAry;
+ delete mpDisplayBmp;
+}
+
+void ImplImageBmp::Create( const BitmapEx& rBmpEx, long nItemWidth, long nItemHeight, sal_uInt16 nInitSize )
+{
+ maBmpEx = rBmpEx;
+ maDisabledBmpEx.SetEmpty();
+
+ delete mpDisplayBmp;
+ mpDisplayBmp = nullptr;
+
+ maSize = Size( nItemWidth, nItemHeight );
+ mnSize = nInitSize;
+
+ delete[] mpInfoAry;
+ mpInfoAry = new sal_uInt8[ mnSize ];
+ memset( mpInfoAry,
+ rBmpEx.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA : ( rBmpEx.IsTransparent() ? IMPSYSIMAGEITEM_MASK : 0 ),
+ mnSize );
+}
+
+void ImplImageBmp::Draw( OutputDevice* pOutDev,
+ const Point& rPos, DrawImageFlags nStyle,
+ const Size* pSize )
+{
+ if( pOutDev->IsDeviceOutputNecessary() )
+ {
+ const Point aSrcPos(0, 0);
+ Size aOutSize;
+
+ aOutSize = ( pSize ? *pSize : pOutDev->PixelToLogic( maSize ) );
+
+ if( nStyle & DrawImageFlags::Disable )
+ {
+ BitmapChecksum aChecksum = maBmpEx.GetChecksum();
+ if (maBitmapChecksum != aChecksum)
+ {
+ maBitmapChecksum = aChecksum;
+ ImplUpdateDisabledBmpEx();
+ }
+ pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, maDisabledBmpEx );
+ }
+ else
+ {
+ if( nStyle & ( DrawImageFlags::ColorTransform |
+ DrawImageFlags::Highlight | DrawImageFlags::Deactive | DrawImageFlags::SemiTransparent ) )
+ {
+ BitmapEx aTmpBmpEx;
+ const Rectangle aCropRect( aSrcPos, maSize );
+
+ if( mpInfoAry[0] & ( IMPSYSIMAGEITEM_MASK | IMPSYSIMAGEITEM_ALPHA ) )
+ aTmpBmpEx = maBmpEx;
+ else
+ aTmpBmpEx = maBmpEx.GetBitmap();
+
+ aTmpBmpEx.Crop( aCropRect );
+
+ Bitmap aTmpBmp( aTmpBmpEx.GetBitmap() );
+
+ if( nStyle & ( DrawImageFlags::Highlight | DrawImageFlags::Deactive ) )
+ {
+ BitmapWriteAccess* pAcc = aTmpBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
+ Color aColor;
+ BitmapColor aCol;
+ const long nW = pAcc->Width();
+ const long nH = pAcc->Height();
+ std::unique_ptr<sal_uInt8[]> pMapR(new sal_uInt8[ 256 ]);
+ std::unique_ptr<sal_uInt8[]> pMapG(new sal_uInt8[ 256 ]);
+ std::unique_ptr<sal_uInt8[]> pMapB(new sal_uInt8[ 256 ]);
+ long nX, nY;
+
+ if( nStyle & DrawImageFlags::Highlight )
+ aColor = rSettings.GetHighlightColor();
+ else
+ aColor = rSettings.GetDeactiveColor();
+
+ const sal_uInt8 cR = aColor.GetRed();
+ const sal_uInt8 cG = aColor.GetGreen();
+ const sal_uInt8 cB = aColor.GetBlue();
+
+ for( nX = 0L; nX < 256L; nX++ )
+ {
+ pMapR[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cR ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapG[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cG ) >> 1 ) > 255 ) ? 255 : nY );
+ pMapB[ nX ] = (sal_uInt8) ( ( ( nY = ( nX + cB ) >> 1 ) > 255 ) ? 255 : nY );
+ }
+
+ if( pAcc->HasPalette() )
+ {
+ for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( i );
+ aCol.SetRed( pMapR[ rCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ rCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ rCol.GetBlue() ] );
+ pAcc->SetPaletteColor( i, aCol );
+ }
+ }
+ else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ Scanline pScan = pAcc->GetScanline( nY );
+
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ *pScan = pMapB[ *pScan ]; pScan++;
+ *pScan = pMapG[ *pScan ]; pScan++;
+ *pScan = pMapR[ *pScan ]; pScan++;
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0L; nY < nH; nY++ )
+ {
+ for( nX = 0L; nX < nW; nX++ )
+ {
+ aCol = pAcc->GetPixel( nY, nX );
+ aCol.SetRed( pMapR[ aCol.GetRed() ] );
+ aCol.SetGreen( pMapG[ aCol.GetGreen() ] );
+ aCol.SetBlue( pMapB[ aCol.GetBlue() ] );
+ pAcc->SetPixel( nY, nX, aCol );
+ }
+ }
+ }
+
+ Bitmap::ReleaseAccess( pAcc );
+ }
+ }
+
+ if( nStyle & DrawImageFlags::SemiTransparent )
+ {
+ if( aTmpBmpEx.IsTransparent() )
+ {
+ Bitmap aAlphaBmp( aTmpBmpEx.GetAlpha().GetBitmap() );
+
+ aAlphaBmp.Adjust( 50 );
+ aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aAlphaBmp ) );
+ }
+ else
+ {
+ sal_uInt8 cErase = 128;
+ aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aTmpBmp.GetSizePixel(), &cErase ) );
+ }
+ }
+ else
+ {
+ if( aTmpBmpEx.IsAlpha() )
+ aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetAlpha() );
+ else if( aTmpBmpEx.IsTransparent() )
+ aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetMask() );
+ }
+
+ pOutDev->DrawBitmapEx( rPos, aOutSize, aTmpBmpEx );
+ }
+ else
+ {
+ const BitmapEx* pOutputBmp;
+
+ if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
+ {
+ ImplUpdateDisplayBmp( pOutDev );
+ pOutputBmp = mpDisplayBmp;
+ }
+ else
+ pOutputBmp = &maBmpEx;
+
+ if( pOutputBmp )
+ pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, *pOutputBmp );
+ }
+ }
+ }
+}
+
+void ImplImageBmp::ImplUpdateDisplayBmp(OutputDevice*)
+{
+ if (!mpDisplayBmp && !maBmpEx.IsEmpty())
+ {
+ mpDisplayBmp = new BitmapEx(maBmpEx);
+ }
+}
+
+void ImplImageBmp::ImplUpdateDisabledBmpEx()
+{
+ const Size aTotalSize( maBmpEx.GetSizePixel() );
+
+ if( maDisabledBmpEx.IsEmpty() )
+ {
+ Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
+ AlphaMask aGreyAlphaMask( aTotalSize );
+
+ maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );
+ }
+
+ Bitmap aBmp( maBmpEx.GetBitmap() );
+ BitmapReadAccess* pBmp( aBmp.AcquireReadAccess() );
+ AlphaMask aBmpAlphaMask( maBmpEx.GetAlpha() );
+ BitmapReadAccess* pBmpAlphaMask( aBmpAlphaMask.AcquireReadAccess() );
+ Bitmap aGrey( maDisabledBmpEx.GetBitmap() );
+ BitmapWriteAccess* pGrey( aGrey.AcquireWriteAccess() );
+ AlphaMask aGreyAlphaMask( maDisabledBmpEx.GetAlpha() );
+ BitmapWriteAccess* pGreyAlphaMask( aGreyAlphaMask.AcquireWriteAccess() );
+
+ if( pBmp && pBmpAlphaMask && pGrey && pGreyAlphaMask )
+ {
+ BitmapColor aGreyVal( 0 );
+ BitmapColor aGreyAlphaMaskVal( 0 );
+
+ const int nLeft = 0;
+ const int nRight = nLeft + maSize.Width();
+ const int nTop = 0;
+ const int nBottom = nTop + maSize.Height();
+
+ for( int nY = nTop; nY < nBottom; ++nY )
+ {
+ for( int nX = nLeft; nX < nRight; ++nX )
+ {
+ aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
+ pGrey->SetPixel( nY, nX, aGreyVal );
+
+ const BitmapColor aBmpAlphaMaskVal( pBmpAlphaMask->GetPixel( nY, nX ) );
+
+ aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( ::std::min( aBmpAlphaMaskVal.GetIndex() + 178ul, 255ul ) ) );
+ pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
+ }
+ }
+ }
+
+ Bitmap::ReleaseAccess( pBmp );
+ aBmpAlphaMask.ReleaseAccess( pBmpAlphaMask );
+ Bitmap::ReleaseAccess( pGrey );
+ aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
+
+ maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImageData.cxx b/vcl/source/image/ImplImageData.cxx
new file mode 100644
index 000000000000..6fc0747b2874
--- /dev/null
+++ b/vcl/source/image/ImplImageData.cxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <image.h>
+#include <memory>
+
+ImplImageData::ImplImageData( const BitmapEx& rBmpEx ) :
+ mpImageBitmap( nullptr ),
+ maBmpEx( rBmpEx )
+{
+}
+
+ImplImageData::~ImplImageData()
+{
+ delete mpImageBitmap;
+}
+
+bool ImplImageData::IsEqual( const ImplImageData& rData )
+{
+ return( maBmpEx == rData.maBmpEx );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImageList.cxx b/vcl/source/image/ImplImageList.cxx
new file mode 100644
index 000000000000..bc137fc9e2e8
--- /dev/null
+++ b/vcl/source/image/ImplImageList.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vcl/outdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/window.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+
+#include <image.h>
+#include <memory>
+
+ImplImageList::ImplImageList()
+ : mnRefCount(1)
+{
+}
+
+ImplImageList::ImplImageList( const ImplImageList &aSrc )
+ : maPrefix(aSrc.maPrefix)
+ , maImageSize(aSrc.maImageSize)
+ , mnRefCount(1)
+{
+ maImages.reserve( aSrc.maImages.size() );
+ for ( ImageAryDataVec::const_iterator aIt = aSrc.maImages.begin(), aEnd = aSrc.maImages.end(); aIt != aEnd; ++aIt )
+ {
+ ImageAryData* pAryData = new ImageAryData( **aIt );
+ maImages.push_back( pAryData );
+ if( !pAryData->maName.isEmpty() )
+ maNameHash [ pAryData->maName ] = pAryData;
+ }
+}
+
+ImplImageList::~ImplImageList()
+{
+ for ( ImageAryDataVec::iterator aIt = maImages.begin(), aEnd = maImages.end(); aIt != aEnd; ++aIt )
+ delete *aIt;
+}
+
+void ImplImageList::AddImage( const OUString &aName,
+ sal_uInt16 nId, const BitmapEx &aBitmapEx )
+{
+ ImageAryData *pImg = new ImageAryData( aName, nId, aBitmapEx );
+ maImages.push_back( pImg );
+ if( !aName.isEmpty() )
+ maNameHash [ aName ] = pImg;
+}
+
+void ImplImageList::RemoveImage( sal_uInt16 nPos )
+{
+ ImageAryData *pImg = maImages[ nPos ];
+ if( !pImg->maName.isEmpty() )
+ maNameHash.erase( pImg->maName );
+ maImages.erase( maImages.begin() + nPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/image/ImplImageTree.cxx b/vcl/source/image/ImplImageTree.cxx
new file mode 100644
index 000000000000..6726673c867d
--- /dev/null
+++ b/vcl/source/image/ImplImageTree.cxx
@@ -0,0 +1,439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_folders.h>
+
+#include "sal/config.h"
+
+#include "com/sun/star/container/XNameAccess.hpp"
+#include "com/sun/star/io/XInputStream.hpp"
+#include "com/sun/star/lang/Locale.hpp"
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/packages/zip/ZipFileAccess.hpp"
+#include "com/sun/star/uno/Any.hxx"
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/RuntimeException.hpp"
+#include "com/sun/star/uno/Sequence.hxx"
+#include "comphelper/processfactory.hxx"
+#include "osl/file.hxx"
+#include "osl/diagnose.h"
+#include "rtl/bootstrap.hxx"
+#include "rtl/uri.hxx"
+
+#include "tools/stream.hxx"
+#include "tools/urlobj.hxx"
+#include "vcl/bitmapex.hxx"
+#include <vcl/dibtools.hxx>
+#include <vcl/implimagetree.hxx>
+#include "vcl/pngread.hxx"
+#include "vcl/settings.hxx"
+#include "vcl/svapp.hxx"
+#include <vcldemo-debug.hxx>
+
+#include <vcl/BitmapProcessor.hxx>
+#include <vcl/BitmapTools.hxx>
+
+using namespace css;
+
+namespace {
+
+static OUString createPath(OUString const & name, sal_Int32 pos, OUString const & locale)
+{
+ return name.copy(0, pos + 1) + locale + name.copy(pos);
+}
+
+static std::shared_ptr<SvStream> wrapStream(css::uno::Reference< css::io::XInputStream > const & stream)
+{
+ // This could use SvInputStream instead if that did not have a broken
+ // SeekPos implementation for an XInputStream that is not also XSeekable
+ // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
+ // l. 593):
+ OSL_ASSERT(stream.is());
+ std::shared_ptr<SvStream> s(std::make_shared<SvMemoryStream>());
+ for (;;)
+ {
+ sal_Int32 const size = 2048;
+ css::uno::Sequence< sal_Int8 > data(size);
+ sal_Int32 n = stream->readBytes(data, size);
+ s->Write(data.getConstArray(), n);
+ if (n < size)
+ break;
+ }
+ s->Seek(0);
+ return s;
+}
+
+static void loadImageFromStream(std::shared_ptr<SvStream> xStream, OUString const & rPath, BitmapEx & rBitmap)
+{
+ if (rPath.endsWith(".png"))
+ {
+ vcl::PNGReader aPNGReader(*xStream);
+ aPNGReader.SetIgnoreGammaChunk( true );
+ rBitmap = aPNGReader.Read();
+ }
+ else if (rPath.endsWith(".svg"))
+ {
+ vcl::BitmapTools::loadFromSvg(*xStream.get(), rPath, rBitmap);
+ }
+ else
+ {
+ ReadDIBBitmapEx(rBitmap, *xStream);
+ }
+}
+
+}
+
+ImplImageTree & ImplImageTree::get() {
+ static ImplImageTree s_ImplImageTree;
+ return s_ImplImageTree;
+}
+
+ImplImageTree::ImplImageTree()
+{
+}
+
+ImplImageTree::~ImplImageTree()
+{
+}
+
+OUString ImplImageTree::getImageUrl(
+ OUString const & name, OUString const & style, OUString const & lang)
+{
+ OUString aStyle(style);
+ while (!aStyle.isEmpty())
+ {
+ try {
+ setStyle(aStyle);
+
+ std::vector< OUString > paths;
+ paths.push_back(getRealImageName(name));
+
+ if (!lang.isEmpty())
+ {
+ sal_Int32 pos = name.lastIndexOf('/');
+ if (pos != -1)
+ {
+ std::vector<OUString> aFallbacks(
+ LanguageTag(lang).getFallbackStrings(true));
+ for (std::vector< OUString >::reverse_iterator it( aFallbacks.rbegin());
+ it != aFallbacks.rend(); ++it)
+ {
+ paths.push_back( getRealImageName( createPath(name, pos, *it) ) );
+ }
+ }
+ }
+
+ try {
+ if (checkPathAccess()) {
+ const uno::Reference<container::XNameAccess> &rNameAccess = maIconSet[maCurrentStyle].maNameAccess;
+
+ for (std::vector<OUString>::const_reverse_iterator j(paths.rbegin()); j != paths.rend(); ++j)
+ {
+ if (rNameAccess->hasByName(*j))
+ {
+ return "vnd.sun.star.zip://"
+ + rtl::Uri::encode(
+ maIconSet[maCurrentStyle].maURL + ".zip",
+ rtl_UriCharClassRegName,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8)
+ + "/" + *j;
+ // assuming *j contains no problematic chars
+ }
+ }
+ }
+ } catch (css::uno::RuntimeException &) {
+ throw;
+ } catch (const css::uno::Exception & e) {
+ SAL_INFO("vcl", "exception " << e.Message);
+ }
+ }
+ catch (css::uno::RuntimeException &) {}
+
+ aStyle = fallbackStyle(aStyle);
+ }
+ return OUString();
+}
+
+OUString ImplImageTree::fallbackStyle(const OUString &style)
+{
+ if (style == "galaxy")
+ return OUString();
+ else if (style == "industrial")
+ return OUString("galaxy");
+ else if (style == "tango")
+ return OUString("galaxy");
+ else if (style == "breeze")
+ return OUString("galaxy");
+ else if (style == "sifr")
+ return OUString("breeze");
+
+ return OUString("tango");
+}
+
+bool ImplImageTree::loadImage(OUString const & name, OUString const & style, BitmapEx & bitmap,
+ bool localized, bool loadMissing)
+{
+ OUString aStyle(style);
+ while (!aStyle.isEmpty())
+ {
+ try {
+ if (doLoadImage(name, aStyle, bitmap, localized))
+ {
+ static bool bIconsForDarkTheme = !!getenv("VCL_ICONS_FOR_DARK_THEME");
+ if (bIconsForDarkTheme)
+ bitmap = BitmapProcessor::createLightImage(bitmap);
+ return true;
+ }
+ }
+ catch (css::uno::RuntimeException &) {}
+
+ aStyle = fallbackStyle(aStyle);
+ }
+
+ if (!loadMissing)
+ return false;
+
+ SAL_INFO("vcl", "ImplImageTree::loadImage couldn't load \"" << name << "\", fetching default image");
+
+ return loadDefaultImage(style, bitmap);
+}
+
+bool ImplImageTree::loadDefaultImage(OUString const & style, BitmapEx& bitmap)
+{
+ return doLoadImage(
+ "res/grafikde.png",
+ style, bitmap, false);
+}
+
+bool ImplImageTree::doLoadImage(OUString const & name, OUString const & style, BitmapEx & bitmap,
+ bool localized)
+{
+ setStyle(style);
+ if (iconCacheLookup(name, localized, bitmap))
+ return true;
+
+ if (!bitmap.IsEmpty())
+ bitmap.SetEmpty();
+
+ std::vector< OUString > paths;
+ paths.push_back(getRealImageName(name));
+
+ if (localized)
+ {
+ sal_Int32 pos = name.lastIndexOf('/');
+ if (pos != -1)
+ {
+ // findImage() uses a reverse iterator, so push in reverse order.
+ std::vector< OUString > aFallbacks( Application::GetSettings().GetUILanguageTag().getFallbackStrings(true));
+ for (std::vector< OUString >::reverse_iterator it( aFallbacks.rbegin());
+ it != aFallbacks.rend(); ++it)
+ {
+ paths.push_back( getRealImageName( createPath(name, pos, *it) ) );
+ }
+ }
+ }
+
+ bool found = false;
+ try {
+ found = findImage(paths, bitmap);
+ } catch (css::uno::RuntimeException &) {
+ throw;
+ } catch (const css::uno::Exception & e) {
+ SAL_INFO("vcl", "ImplImageTree::doLoadImage exception " << e.Message);
+ }
+
+ if (found)
+ maIconSet[maCurrentStyle].maIconCache[name] = std::make_pair(localized, bitmap);
+
+ return found;
+}
+
+void ImplImageTree::shutDown()
+{
+ maCurrentStyle.clear();
+ for (StyleIconSet::iterator it = maIconSet.begin(); it != maIconSet.end(); ++it)
+ {
+ it->second.maIconCache.clear();
+ it->second.maLinkHash.clear();
+ }
+}
+
+void ImplImageTree::setStyle(OUString const & style)
+{
+ assert(!style.isEmpty());
+ if (style != maCurrentStyle)
+ {
+ maCurrentStyle = style;
+ createStyle();
+ }
+}
+
+void ImplImageTree::createStyle()
+{
+ if (maIconSet.find(maCurrentStyle) != maIconSet.end())
+ return;
+
+ OUString url( "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/config/" );
+ rtl::Bootstrap::expandMacros(url);
+ if (maCurrentStyle != "default")
+ {
+ INetURLObject u(url);
+ OSL_ASSERT(!u.HasError());
+ bool ok = u.Append("images_" + maCurrentStyle, INetURLObject::ENCODE_ALL);
+ OSL_ASSERT(ok); (void) ok;
+ url = u.GetMainURL(INetURLObject::NO_DECODE);
+ }
+ else
+ url += "images";
+
+ maIconSet[maCurrentStyle] = IconSet(url);
+
+ loadImageLinks();
+}
+
+bool ImplImageTree::iconCacheLookup(OUString const & name, bool localized, BitmapEx & bitmap)
+{
+ IconCache &rIconCache = maIconSet[maCurrentStyle].maIconCache;
+
+ IconCache::iterator i(rIconCache.find(getRealImageName(name)));
+ if (i != rIconCache.end() && i->second.first == localized)
+ {
+ bitmap = i->second.second;
+ return true;
+ }
+ return false;
+}
+
+bool ImplImageTree::findImage(std::vector<OUString> const & paths, BitmapEx & bitmap)
+{
+ if (!checkPathAccess())
+ return false;
+
+ const uno::Reference<container::XNameAccess> &rNameAccess = maIconSet[maCurrentStyle].maNameAccess;
+
+ for (std::vector<OUString>::const_reverse_iterator j(paths.rbegin()); j != paths.rend(); ++j)
+ {
+ if (rNameAccess->hasByName(*j))
+ {
+ css::uno::Reference< css::io::XInputStream > s;
+ bool ok = rNameAccess->getByName(*j) >>= s;
+ assert(ok);
+ (void)ok; // prevent unused warning in release build
+
+ loadImageFromStream( wrapStream(s), *j, bitmap );
+ return true;
+ }
+ }
+ return false;
+}
+
+void ImplImageTree::loadImageLinks()
+{
+ const OUString aLinkFilename("links.txt");
+
+ if (!checkPathAccess())
+ return;
+
+ const uno::Reference<container::XNameAccess> &rNameAccess = maIconSet[maCurrentStyle].maNameAccess;
+
+ if (rNameAccess->hasByName(aLinkFilename))
+ {
+ css::uno::Reference< css::io::XInputStream > s;
+ bool ok = rNameAccess->getByName(aLinkFilename) >>= s;
+ assert(ok);
+ (void)ok; // prevent unused warning in release build
+
+ parseLinkFile( wrapStream(s) );
+ return;
+ }
+}
+
+void ImplImageTree::parseLinkFile(std::shared_ptr<SvStream> xStream)
+{
+ OString aLine;
+ OUString aLink, aOriginal;
+ int nLineNo = 0;
+ while (xStream->ReadLine(aLine))
+ {
+ ++nLineNo;
+ if ( aLine.isEmpty() )
+ continue;
+
+ sal_Int32 nIndex = 0;
+ aLink = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
+ aOriginal = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
+
+ // skip comments, or incomplete entries
+ if (aLink.isEmpty() || aLink[0] == '#' || aOriginal.isEmpty())
+ {
+ if (aLink.isEmpty() || aOriginal.isEmpty())
+ SAL_WARN("vcl", "ImplImageTree::parseLinkFile: icon links.txt parse error, incomplete link at line " << nLineNo);
+ continue;
+ }
+
+ maIconSet[maCurrentStyle].maLinkHash[aLink] = aOriginal;
+ }
+}
+
+OUString const & ImplImageTree::getRealImageName(OUString const & name)
+{
+ IconLinkHash &rLinkHash = maIconSet[maCurrentStyle].maLinkHash;
+
+ IconLinkHash::iterator it(rLinkHash.find(name));
+ if (it == rLinkHash.end())
+ return name;
+
+ return it->second;
+}
+
+bool ImplImageTree::checkPathAccess()
+{
+ uno::Reference<container::XNameAccess> &rNameAccess = maIconSet[maCurrentStyle].maNameAccess;
+ if (rNameAccess.is())
+ return true;
+
+ try {
+ rNameAccess = css::packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), maIconSet[maCurrentStyle].maURL + ".zip");
+ }
+ catch (const css::uno::RuntimeException &) {
+ throw;
+ }
+ catch (const css::uno::Exception & e) {
+ SAL_INFO("vcl", "ImplImageTree::zip file location exception " << e.Message << " for " << maIconSet[maCurrentStyle].maURL);
+ return false;
+ }
+ return rNameAccess.is();
+}
+
+css::uno::Reference<css::container::XNameAccess> ImplImageTree::getNameAccess()
+{
+ checkPathAccess();
+ return maIconSet[maCurrentStyle].maNameAccess;
+}
+
+/// Recursively dump all names ...
+css::uno::Sequence<OUString> ImageTree_getAllImageNames()
+{
+ css::uno::Reference<css::container::XNameAccess> xRef(ImplImageTree::get().getNameAccess());
+
+ return xRef->getElementNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */