vcl: FontCharMap to use intrusive_ptr ImplFontCharMap

ImplFontCharMap was using it's own reference counting mechanism,
however we can use intrusive_ptr more effectively.

Added a unit test around FontCharMap.

Change-Id: Ifab6ce002fd1df8feb7e017dea3012ff9ea7f18a
Reviewed-on: https://gerrit.libreoffice.org/11804
Reviewed-by: Chris Sherlock <chris.sherlock79@gmail.com>
Tested-by: Chris Sherlock <chris.sherlock79@gmail.com>
diff --git a/include/vcl/metric.hxx b/include/vcl/metric.hxx
index c22c553..0bc977a 100644
--- a/include/vcl/metric.hxx
+++ b/include/vcl/metric.hxx
@@ -24,10 +24,13 @@
#include <vcl/font.hxx>
#include <vcl/outdev.hxx>

#include <boost/intrusive_ptr.hpp>

class ImplFontMetric;
class ImplFontCharMap;

typedef sal_uInt32 sal_UCS4;
typedef boost::intrusive_ptr< ImplFontCharMap > ImplFontCharMapPtr;

namespace vcl {

@@ -94,7 +97,7 @@ inline std::basic_ostream<charT, traits> & operator <<(
class VCL_DLLPUBLIC FontCharMap
{
private:
    const ImplFontCharMap* mpImpl;
    ImplFontCharMapPtr  mpImplFontCharMap;

public:
                        FontCharMap();
@@ -106,6 +109,7 @@ public:
    int                 GetCharCount( void ) const;

    sal_UCS4            GetFirstChar() const;
    sal_UCS4            GetLastChar() const;

    sal_UCS4            GetNextChar( sal_UCS4 ) const;
    sal_UCS4            GetPrevChar( sal_UCS4 ) const;
@@ -116,7 +120,7 @@ public:

private:
    friend class ::OutputDevice;
    void                Reset( const ImplFontCharMap* pNewMap = NULL );
    void                Reset( const ImplFontCharMapPtr pNewMap = NULL );

    // prevent assignment and copy construction
                        FontCharMap( const FontCharMap& );
diff --git a/vcl/CppunitTest_vcl_fontcharmap.mk b/vcl/CppunitTest_vcl_fontcharmap.mk
new file mode 100644
index 0000000..0a89f41
--- /dev/null
+++ b/vcl/CppunitTest_vcl_fontcharmap.mk
@@ -0,0 +1,53 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# 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/.
#

$(eval $(call gb_CppunitTest_CppunitTest,vcl_fontcharmap))

$(eval $(call gb_CppunitTest_set_include,vcl_fontcharmap,\
    $$(INCLUDE) \
    -I$(SRCDIR)/vcl/inc \
))

$(eval $(call gb_CppunitTest_add_exception_objects,vcl_fontcharmap, \
	vcl/qa/cppunit/fontcharmap \
))

$(eval $(call gb_CppunitTest_use_externals,vcl_fontcharmap,boost_headers))

$(eval $(call gb_CppunitTest_use_libraries,vcl_fontcharmap, \
	comphelper \
	cppu \
	cppuhelper \
	sal \
	svt \
	test \
	tl \
	tk \
	unotest \
	vcl \
	$(gb_UWINAPI) \
))

$(eval $(call gb_CppunitTest_use_api,vcl_fontcharmap,\
	udkapi \
	offapi \
))

$(eval $(call gb_CppunitTest_use_ure,vcl_fontcharmap))
$(eval $(call gb_CppunitTest_use_vcl,vcl_fontcharmap))

$(eval $(call gb_CppunitTest_use_components,vcl_fontcharmap,\
	configmgr/source/configmgr \
	i18npool/util/i18npool \
	ucb/source/core/ucb1 \
))

$(eval $(call gb_CppunitTest_use_configuration,vcl_fontcharmap))

# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index f2eef6f..d875016 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -94,6 +94,7 @@ $(eval $(call gb_Module_add_targets,vcl,\
endif

$(eval $(call gb_Module_add_check_targets,vcl,\
	CppunitTest_vcl_fontcharmap \
	CppunitTest_vcl_complextext \
	CppunitTest_vcl_filters_test \
	CppunitTest_vcl_app_test \
diff --git a/vcl/generic/fontmanager/fontmanager.cxx b/vcl/generic/fontmanager/fontmanager.cxx
index 2737076..05fc829 100644
--- a/vcl/generic/fontmanager/fontmanager.cxx
+++ b/vcl/generic/fontmanager/fontmanager.cxx
@@ -2088,11 +2088,11 @@ void PrintFontManager::getGlyphWidths( fontID nFont,
                CmapResult aCmapResult;
                if( ParseCMAP( pCmapData, nCmapSize, aCmapResult ) )
                {
                    const ImplFontCharMap aCharMap( aCmapResult );
                    const ImplFontCharMapPtr pCharMap( new ImplFontCharMap(aCmapResult) );
                    for( sal_uInt32 cOld = 0;;)
                    {
                        // get next unicode covered by font
                        const sal_uInt32 c = aCharMap.GetNextChar( cOld );
                        const sal_uInt32 c = pCharMap->GetNextChar( cOld );
                        if( c == cOld )
                            break;
                        cOld = c;
@@ -2101,7 +2101,7 @@ void PrintFontManager::getGlyphWidths( fontID nFont,
                            break;
#endif
                        // get the matching glyph index
                        const sal_GlyphId aGlyphId = aCharMap.GetGlyphIndex( c );
                        const sal_GlyphId aGlyphId = pCharMap->GetGlyphIndex( c );
                        // update the requested map
                        rUnicodeEnc[ (sal_Unicode)c ] = aGlyphId;
                    }
diff --git a/vcl/generic/glyphs/gcach_ftyp.cxx b/vcl/generic/glyphs/gcach_ftyp.cxx
index 9db574e..fa93fc6 100644
--- a/vcl/generic/glyphs/gcach_ftyp.cxx
+++ b/vcl/generic/glyphs/gcach_ftyp.cxx
@@ -242,7 +242,7 @@ FtFontInfo::FtFontInfo( const ImplDevFontAttributes& rDevFontAttributes,
FtFontInfo::~FtFontInfo()
{
    if( mpFontCharMap )
        mpFontCharMap->DeReference();
        mpFontCharMap = 0;
    delete mpChar2Glyph;
    delete mpGlyph2Char;
#if ENABLE_GRAPHITE
@@ -1265,13 +1265,13 @@ bool ServerFont::GetGlyphBitmap8( sal_GlyphId aGlyphId, RawBitmap& rRawBitmap ) 

// determine unicode ranges in font

const ImplFontCharMap* ServerFont::GetImplFontCharMap( void ) const
const ImplFontCharMapPtr ServerFont::GetImplFontCharMap( void ) const
{
    const ImplFontCharMap* pIFCMap = mpFontInfo->GetImplFontCharMap();
    const ImplFontCharMapPtr pIFCMap = mpFontInfo->GetImplFontCharMap();
    return pIFCMap;
}

const ImplFontCharMap* FtFontInfo::GetImplFontCharMap( void )
const ImplFontCharMapPtr FtFontInfo::GetImplFontCharMap( void )
{
    // check if the charmap is already cached
    if( mpFontCharMap )
@@ -1281,9 +1281,14 @@ const ImplFontCharMap* FtFontInfo::GetImplFontCharMap( void )
    CmapResult aCmapResult;
    bool bOK = GetFontCodeRanges( aCmapResult );
    if( bOK )
        mpFontCharMap = new ImplFontCharMap( aCmapResult );
    {
        ImplFontCharMapPtr pFontCharMap( new ImplFontCharMap( aCmapResult ) );
        mpFontCharMap = pFontCharMap;
    }
    else
    {
        mpFontCharMap = ImplFontCharMap::GetDefaultMap();
    }
    // mpFontCharMap on either branch now has a refcount of 1
    return mpFontCharMap;
}
diff --git a/vcl/generic/glyphs/gcach_ftyp.hxx b/vcl/generic/glyphs/gcach_ftyp.hxx
index b43d47b..803ce07 100644
--- a/vcl/generic/glyphs/gcach_ftyp.hxx
+++ b/vcl/generic/glyphs/gcach_ftyp.hxx
@@ -84,7 +84,7 @@ public:
    void                  CacheGlyphIndex( sal_UCS4 cChar, int nGI ) const;

    bool                  GetFontCodeRanges( CmapResult& ) const;
    const ImplFontCharMap* GetImplFontCharMap( void );
    const ImplFontCharMapPtr GetImplFontCharMap( void );

private:
    FT_FaceRec_*    maFaceFT;
@@ -99,7 +99,7 @@ private:
    sal_IntPtr      mnFontId;
    ImplDevFontAttributes maDevFontAttributes;

    const ImplFontCharMap* mpFontCharMap;
    ImplFontCharMapPtr mpFontCharMap;

    // cache unicode->glyphid mapping because looking it up is expensive
    // TODO: change to boost::unordered_multimap when a use case requires a m:n mapping
diff --git a/vcl/generic/print/genpspgraphics.cxx b/vcl/generic/print/genpspgraphics.cxx
index 401f5c7..759519b 100644
--- a/vcl/generic/print/genpspgraphics.cxx
+++ b/vcl/generic/print/genpspgraphics.cxx
@@ -777,12 +777,12 @@ void GenPspGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
    DrawPrinterLayout( rLayout, *m_pPrinterGfx, true );
}

const ImplFontCharMap* GenPspGraphics::GetImplFontCharMap() const
const ImplFontCharMapPtr GenPspGraphics::GetImplFontCharMap() const
{
    if( !m_pServerFont[0] )
        return NULL;

    const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
    const ImplFontCharMapPtr pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
    return pIFCMap;
}

diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx
index 3f2384c..905d78b 100644
--- a/vcl/headless/svptext.cxx
+++ b/vcl/headless/svptext.cxx
@@ -231,12 +231,12 @@ void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLe
    }
}

const ImplFontCharMap* SvpSalGraphics::GetImplFontCharMap() const
const ImplFontCharMapPtr SvpSalGraphics::GetImplFontCharMap() const
{
    if( !m_pServerFont[0] )
        return NULL;

    const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
    const ImplFontCharMapPtr pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
    return pIFCMap;
}

diff --git a/vcl/inc/generic/genpspgraphics.h b/vcl/inc/generic/genpspgraphics.h
index ec54d5b..66c7f31 100644
--- a/vcl/inc/generic/genpspgraphics.h
+++ b/vcl/inc/generic/genpspgraphics.h
@@ -89,7 +89,7 @@ public:
    virtual void            SetTextColor( SalColor nSalColor ) SAL_OVERRIDE;
    virtual sal_uInt16      SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual const ImplFontCharMap* GetImplFontCharMap() const SAL_OVERRIDE;
    virtual const ImplFontCharMapPtr GetImplFontCharMap() const SAL_OVERRIDE;
    virtual bool            GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE;
    virtual void            GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE;
    // graphics must drop any cached font info
diff --git a/vcl/inc/generic/glyphcache.hxx b/vcl/inc/generic/glyphcache.hxx
index a3b1c4f..40a07da 100644
--- a/vcl/inc/generic/glyphcache.hxx
+++ b/vcl/inc/generic/glyphcache.hxx
@@ -182,7 +182,7 @@ public:
    const unsigned char* GetTable( const char* pName, sal_uLong* pLength );
    int                 GetEmUnits() const { return maFaceFT->units_per_EM;}
    const FT_Size_Metrics& GetMetricsFT() const { return maSizeFT->metrics; }
    const ImplFontCharMap* GetImplFontCharMap() const;
    const ImplFontCharMapPtr GetImplFontCharMap() const;
    bool                GetFontCapabilities(vcl::FontCapabilities &) const;

    GlyphData&                  GetGlyphData( sal_GlyphId );
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 65a8fc2..aad4693d 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -156,7 +156,7 @@ public:
    virtual void            SetTextColor( SalColor nSalColor ) SAL_OVERRIDE;
    virtual sal_uInt16      SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual const ImplFontCharMap* GetImplFontCharMap() const SAL_OVERRIDE;
    virtual const ImplFontCharMapPtr GetImplFontCharMap() const SAL_OVERRIDE;
    virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE;
    virtual void            GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE;
    virtual void ClearDevFontCache() SAL_OVERRIDE;
diff --git a/vcl/inc/impfont.hxx b/vcl/inc/impfont.hxx
index 3c42f6e..af97677 100644
--- a/vcl/inc/impfont.hxx
+++ b/vcl/inc/impfont.hxx
@@ -29,6 +29,11 @@
#include <vcl/fntstyle.hxx>
#include <outfont.hxx>

#include <boost/intrusive_ptr.hpp>

class ImplFontCharMap;
typedef boost::intrusive_ptr< ImplFontCharMap > ImplFontCharMapPtr;

// - Impl_Font -

class Impl_Font
@@ -158,7 +163,7 @@ public:
    explicit            ImplFontCharMap( const CmapResult& );
    virtual             ~ImplFontCharMap();

    static ImplFontCharMap* GetDefaultMap( bool bSymbols=false);
    static ImplFontCharMapPtr GetDefaultMap( bool bSymbols=false);

    bool                IsDefaultMap() const;
    bool                HasChar( sal_uInt32 ) const;
@@ -174,12 +179,12 @@ public:
    int                 GetIndexFromChar( sal_uInt32 ) const;
    sal_uInt32          GetCharFromIndex( int ) const;

    void                AddReference() const;
    void                DeReference() const;

    int                 GetGlyphIndex( sal_uInt32 ) const;

private:
    friend void intrusive_ptr_add_ref(ImplFontCharMap* pImplFontCharMap);
    friend void intrusive_ptr_release(ImplFontCharMap* pImplFontCharMap);

    int                 ImplFindRangeIndex( sal_uInt32 ) const;

    // prevent assignment and copy construction
@@ -195,6 +200,17 @@ private:
    mutable sal_uInt32  mnRefCount;
};

inline void intrusive_ptr_add_ref(ImplFontCharMap* pImplFontCharMap)
{
    ++pImplFontCharMap->mnRefCount;
}

inline void intrusive_ptr_release(ImplFontCharMap* pImplFontCharMap)
{
    if (--pImplFontCharMap->mnRefCount == 0)
        delete pImplFontCharMap;
}

// CmapResult is a normalized version of the many CMAP formats
class VCL_PLUGIN_PUBLIC CmapResult
{
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index 8aad534..0c58ca7 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -73,7 +73,7 @@ public:
    CoreTextStyle*                  CreateTextStyle( const FontSelectPattern& ) const;
    int                             GetFontTable( const char pTagName[5], unsigned char* ) const;

    const ImplFontCharMap*          GetImplFontCharMap() const;
    const ImplFontCharMapPtr        GetImplFontCharMap() const;
    bool                            GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const;
    bool                            HasChar( sal_uInt32 cChar ) const;

@@ -85,7 +85,7 @@ protected:

private:
    const sal_IntPtr                mnFontId;
    mutable const ImplFontCharMap*  mpCharMap;
    mutable ImplFontCharMapPtr      mpCharMap;
    mutable vcl::FontCapabilities   maFontCapabilities;
    mutable bool                    mbOs2Read;       // true if OS2-table related info is valid
    mutable bool                    mbHasOs2Table;
@@ -330,7 +330,7 @@ public:
    // get the current font's metrics
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE;
    // get the repertoire of the current font
    virtual const ImplFontCharMap*
    virtual const ImplFontCharMapPtr
                            GetImplFontCharMap() const SAL_OVERRIDE;
    virtual bool            GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE;
    // graphics must fill supplied font list
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index bed8474..c2752b9 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -28,6 +28,7 @@
#include "vcl/salnativewidgets.hxx"
#include "salglyphid.hxx"
#include "sallayout.hxx"
#include <impfont.hxx>

#include <map>

@@ -36,7 +37,6 @@ class SalBitmap;
class FontSelectPattern;
class ImplFontMetricData;
class PhysicalFontFace;
class ImplFontCharMap;
class SalLayout;
class ImplLayoutArgs;
class Rectangle;
@@ -231,7 +231,7 @@ public:
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel = 0 ) = 0;

    // get the repertoire of the current font
    virtual const ImplFontCharMap*
    virtual const ImplFontCharMapPtr
                            GetImplFontCharMap() const = 0;

    // get the layout capabilities of the current font
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 978e514..ba0814b 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -229,7 +229,7 @@ public:
    virtual void            SetTextColor( SalColor nSalColor ) SAL_OVERRIDE;
    virtual sal_uInt16          SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE;
    virtual const ImplFontCharMap* GetImplFontCharMap() const SAL_OVERRIDE;
    virtual const ImplFontCharMapPtr GetImplFontCharMap() const SAL_OVERRIDE;
    virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE;
    virtual void            GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE;
    virtual void ClearDevFontCache() SAL_OVERRIDE;
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 957db91..ace973c 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -94,7 +94,7 @@ public:
    const gr_face*          GraphiteFace() const;
#endif

    const ImplFontCharMap*  GetImplFontCharMap() const;
    const ImplFontCharMapPtr GetImplFontCharMap() const;
    bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const;
    const Ucs2SIntMap* GetEncodingVector() const { return mpEncodingVector; }
    void SetEncodingVector( const Ucs2SIntMap* pNewVec ) const
@@ -116,7 +116,7 @@ private:
#endif
    mutable bool                    mbHasArabicSupport;
    mutable bool                    mbFontCapabilitiesRead;
    mutable ImplFontCharMap*        mpUnicodeMap;
    mutable ImplFontCharMapPtr      mpUnicodeMap;
    mutable const Ucs2SIntMap*      mpEncodingVector;
    mutable vcl::FontCapabilities   maFontCapabilities;

@@ -310,7 +310,7 @@ public:
    // get the current font's metrics
    virtual void            GetFontMetric( ImplFontMetricData*, int nFallbackLevel );
    // get the repertoire of the current font
    virtual const ImplFontCharMap* GetImplFontCharMap() const;
    virtual const ImplFontCharMapPtr GetImplFontCharMap() const;
    // get the layout capabilities of the current font
    virtual bool GetFontCapabilities(vcl::FontCapabilities &rGetFontCapabilities) const;
    // graphics must fill supplied font list
diff --git a/vcl/qa/cppunit/fontcharmap.cxx b/vcl/qa/cppunit/fontcharmap.cxx
new file mode 100644
index 0000000..1fee918
--- /dev/null
+++ b/vcl/qa/cppunit/fontcharmap.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/.
 */

#include <test/bootstrapfixture.hxx>

#include <osl/file.hxx>
#include <osl/process.h>

#include <vcl/metric.hxx>

class VclFontCharMapTest : public test::BootstrapFixture
{
public:
    VclFontCharMapTest() : BootstrapFixture(true, false) {}

    void testDefaultFontCharMap();

    CPPUNIT_TEST_SUITE(VclFontCharMapTest);
    CPPUNIT_TEST(testDefaultFontCharMap);
    CPPUNIT_TEST_SUITE_END();
};

void VclFontCharMapTest::testDefaultFontCharMap()
{
    FontCharMap *fcmap = new FontCharMap(); // gets default map

    CPPUNIT_ASSERT( fcmap->IsDefaultMap() );

    sal_uInt32 nStartBMPPlane = fcmap->GetFirstChar();
    sal_uInt32 nStartSupBMPPlane = fcmap->GetNextChar(0xD800);
    sal_uInt32 nEndBMPPlane = fcmap->GetLastChar();

    CPPUNIT_ASSERT( nStartBMPPlane == 0x0020 );
    CPPUNIT_ASSERT( nStartSupBMPPlane == 0xE000 );
    CPPUNIT_ASSERT( nEndBMPPlane == 0xFFF0-1 );
}

CPPUNIT_TEST_SUITE_REGISTRATION(VclFontCharMapTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 80d6d5e..b5f5251 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -62,19 +62,17 @@ using namespace vcl;
CoreTextFontData::CoreTextFontData( const CoreTextFontData& rSrc )
:   PhysicalFontFace( rSrc )
,   mnFontId( rSrc.mnFontId )
,   mpCharMap( rSrc.mpCharMap )
,   mbOs2Read( rSrc.mbOs2Read )
,   mbHasOs2Table( rSrc.mbHasOs2Table )
,   mbCmapEncodingRead( rSrc.mbCmapEncodingRead )
{
    if( mpCharMap )
        mpCharMap->AddReference();
    if( rSrc.mpCharMap )
        mpCharMap = rSrc.mpCharMap;
}

CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId )
:   PhysicalFontFace( rDFA, 0 )
,   mnFontId( nFontId )
,   mpCharMap( NULL )
,   mbOs2Read( false )
,   mbHasOs2Table( false )
,   mbCmapEncodingRead( false )
@@ -85,7 +83,7 @@ CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPt
CoreTextFontData::~CoreTextFontData()
{
    if( mpCharMap )
        mpCharMap->DeReference();
        mpCharMap = 0;
}

sal_IntPtr CoreTextFontData::GetFontId() const
@@ -95,7 +93,7 @@ sal_IntPtr CoreTextFontData::GetFontId() const

static unsigned GetUShort( const unsigned char* p ){return((p[0]<<8)+p[1]);}

const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const
const ImplFontCharMapPtr CoreTextFontData::GetImplFontCharMap() const
{
    // return the cached charmap
    if( mpCharMap )
@@ -103,7 +101,6 @@ const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const

    // set the default charmap
    mpCharMap = ImplFontCharMap::GetDefaultMap();
    mpCharMap->AddReference();

    // get the CMAP byte size
    // allocate a buffer for the CMAP raw data
@@ -124,10 +121,9 @@ const ImplFontCharMap* CoreTextFontData::GetImplFontCharMap() const
    CmapResult aCmapResult;
    if( ParseCMAP( &aBuffer[0], nRawLength, aCmapResult ) )
    {
        ImplFontCharMapPtr pCharMap(new ImplFontCharMap( aCmapResult ) );
        // create the matching charmap
        mpCharMap->DeReference();
        mpCharMap = new ImplFontCharMap( aCmapResult );
        mpCharMap->AddReference();
        mpCharMap = pCharMap;
    }

    return mpCharMap;
@@ -489,7 +485,7 @@ SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFal
    return pSalLayout;
}

const ImplFontCharMap* AquaSalGraphics::GetImplFontCharMap() const
const ImplFontCharMapPtr AquaSalGraphics::GetImplFontCharMap() const
{
    if( !mpFontData )
        return ImplFontCharMap::GetDefaultMap();
@@ -726,9 +722,8 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV
                free( (void*)pGlyphMetrics );
            }

            const ImplFontCharMap* pMap = mpFontData->GetImplFontCharMap();
            ImplFontCharMapPtr pMap = mpFontData->GetImplFontCharMap();
            DBG_ASSERT( pMap && pMap->GetCharCount(), "no charmap" );
            pMap->AddReference(); // TODO: add and use RAII object instead

            // get unicode<->glyph encoding
            // TODO? avoid sft mapping by using the pMap itself
@@ -744,7 +739,7 @@ void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bV
                    rUnicodeEnc[ nUcsChar ] = nGlyph;
            }

            pMap->DeReference(); // TODO: add and use RAII object instead
            pMap = 0;
        }

        ::CloseTTFont( pSftFont );
diff --git a/vcl/source/gdi/impfont.cxx b/vcl/source/gdi/impfont.cxx
index d0d285b..e4e6fc8 100644
--- a/vcl/source/gdi/impfont.cxx
+++ b/vcl/source/gdi/impfont.cxx
@@ -50,7 +50,7 @@ ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR )
    }
}

static ImplFontCharMap* pDefaultImplFontCharMap = NULL;
static ImplFontCharMapPtr pDefaultImplFontCharMap;
static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0};
static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100};

@@ -69,40 +69,22 @@ ImplFontCharMap::~ImplFontCharMap()
    delete[] mpGlyphIds;
}

ImplFontCharMap* ImplFontCharMap::GetDefaultMap( bool bSymbols)
ImplFontCharMapPtr ImplFontCharMap::GetDefaultMap( bool bSymbols)
{
    if( pDefaultImplFontCharMap )
        pDefaultImplFontCharMap->AddReference();
    else
    const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges;
    int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
    if( bSymbols )
    {
        const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges;
        int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes);
        if( bSymbols )
        {
            pRangeCodes = aDefaultSymbolRanges;
            nCodesCount = sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
        }

        CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
        pDefaultImplFontCharMap = new ImplFontCharMap( aDefaultCR );
        pRangeCodes = aDefaultSymbolRanges;
        nCodesCount = sizeof(aDefaultSymbolRanges) / sizeof(*pRangeCodes);
    }

    CmapResult aDefaultCR( bSymbols, pRangeCodes, nCodesCount/2 );
    pDefaultImplFontCharMap.reset( new ImplFontCharMap( aDefaultCR ) );

    return pDefaultImplFontCharMap;
}

void ImplFontCharMap::AddReference( void) const
{
    ++mnRefCount;
}

void ImplFontCharMap::DeReference( void) const
{
    if( --mnRefCount <= 0 )
        if( this != pDefaultImplFontCharMap )
            delete this;
}


int ImplFontCharMap::ImplFindRangeIndex( sal_UCS4 cChar ) const
{
    int nLower = 0;
@@ -561,73 +543,74 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult )
}

FontCharMap::FontCharMap()
:   mpImpl( ImplFontCharMap::GetDefaultMap() )
:   mpImplFontCharMap( ImplFontCharMap::GetDefaultMap() )
{}

FontCharMap::~FontCharMap()
{
    mpImpl->DeReference();
    mpImpl = NULL;
    mpImplFontCharMap = 0;
}

int FontCharMap::GetCharCount() const
{
    return mpImpl->GetCharCount();
    return mpImplFontCharMap->GetCharCount();
}

int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const
{
    return mpImpl->CountCharsInRange( cMin, cMax );
    return mpImplFontCharMap->CountCharsInRange( cMin, cMax );
}

void FontCharMap::Reset( const ImplFontCharMap* pNewMap )
void FontCharMap::Reset( const ImplFontCharMapPtr pNewMap )
{
    if( pNewMap == NULL )
    {
        mpImpl->DeReference();
        mpImpl = ImplFontCharMap::GetDefaultMap();
        mpImplFontCharMap = ImplFontCharMap::GetDefaultMap();
    }
    else if( pNewMap != mpImpl )
    else if( pNewMap != mpImplFontCharMap )
    {
        mpImpl->DeReference();
        mpImpl = pNewMap;
        mpImpl->AddReference();
        mpImplFontCharMap = pNewMap;
    }
}

bool FontCharMap::IsDefaultMap() const
{
    return mpImpl->IsDefaultMap();
    return mpImplFontCharMap->IsDefaultMap();
}

bool FontCharMap::HasChar( sal_UCS4 cChar ) const
{
    return mpImpl->HasChar( cChar );
    return mpImplFontCharMap->HasChar( cChar );
}

sal_UCS4 FontCharMap::GetFirstChar() const
{
    return mpImpl->GetFirstChar();
    return mpImplFontCharMap->GetFirstChar();
}

sal_UCS4 FontCharMap::GetLastChar() const
{
    return mpImplFontCharMap->GetLastChar();
}

sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const
{
    return mpImpl->GetNextChar( cChar );
    return mpImplFontCharMap->GetNextChar( cChar );
}

sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const
{
    return mpImpl->GetPrevChar( cChar );
    return mpImplFontCharMap->GetPrevChar( cChar );
}

int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const
{
    return mpImpl->GetIndexFromChar( cChar );
    return mpImplFontCharMap->GetIndexFromChar( cChar );
}

sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const
{
    return mpImpl->GetCharFromIndex( nIndex );
    return mpImplFontCharMap->GetCharFromIndex( nIndex );
}

// on some systems we have to get the font attributes from the name table
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index 7b83d04..0a7733d 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -231,7 +231,7 @@ bool OutputDevice::GetFontCharMap( FontCharMap& rFontCharMap ) const
    if( !mpFontEntry )
        return false;

    const ImplFontCharMap* pNewMap = mpGraphics->GetImplFontCharMap();
    const ImplFontCharMapPtr pNewMap = mpGraphics->GetImplFontCharMap();
    rFontCharMap.Reset( pNewMap );

    if( rFontCharMap.IsDefaultMap() )
diff --git a/vcl/unx/generic/gdi/salgdi3.cxx b/vcl/unx/generic/gdi/salgdi3.cxx
index 13d550e..f028597 100644
--- a/vcl/unx/generic/gdi/salgdi3.cxx
+++ b/vcl/unx/generic/gdi/salgdi3.cxx
@@ -431,12 +431,12 @@ void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
    cairo_destroy(cr);
}

const ImplFontCharMap* X11SalGraphics::GetImplFontCharMap() const
const ImplFontCharMapPtr X11SalGraphics::GetImplFontCharMap() const
{
    if( !mpServerFont[0] )
        return NULL;

    const ImplFontCharMap* pIFCMap = mpServerFont[0]->GetImplFontCharMap();
    const ImplFontCharMapPtr pIFCMap = mpServerFont[0]->GetImplFontCharMap();
    return pIFCMap;
}

diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index efa5417..cb5be79 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -444,7 +444,7 @@ void ImplGetLogFontFromFontSelect( HDC, const FontSelectPattern*,
bool WinGlyphFallbackSubstititution::HasMissingChars( const PhysicalFontFace* pFace, const OUString& rMissingChars ) const
{
    const ImplWinFontData* pWinFont = static_cast<const ImplWinFontData*>(pFace);
    const ImplFontCharMap* pCharMap = pWinFont->GetImplFontCharMap();
    ImplFontCharMapPtr pCharMap = pWinFont->GetImplFontCharMap();
    if( !pCharMap )
    {
        // construct a Size structure as the parameter of constructor of class FontSelectPattern
@@ -474,7 +474,6 @@ bool WinGlyphFallbackSubstititution::HasMissingChars( const PhysicalFontFace* pF
    // avoid fonts with unknown CMAP subtables for glyph fallback
    if( !pCharMap || pCharMap->IsDefaultMap() )
        return false;
        pCharMap->AddReference();

    int nMatchCount = 0;
    // static const int nMaxMatchCount = 1; // TODO: tolerate more missing characters?
@@ -485,7 +484,8 @@ bool WinGlyphFallbackSubstititution::HasMissingChars( const PhysicalFontFace* pF
        nMatchCount += pCharMap->HasChar( uChar );
        break; // for now
    }
        pCharMap->DeReference();

    pCharMap = 0;

    const bool bHasMatches = (nMatchCount > 0);
    return bHasMatches;
@@ -1137,7 +1137,7 @@ ImplWinFontData::~ImplWinFontData()
    delete[] mpFontCharSets;

    if( mpUnicodeMap )
        mpUnicodeMap->DeReference();
        mpUnicodeMap = 0;
#if ENABLE_GRAPHITE
    if (mpGraphiteData)
        mpGraphiteData->DeReference();
@@ -1224,7 +1224,7 @@ bool ImplWinFontData::IsGSUBstituted( sal_UCS4 cChar ) const
    return( maGsubTable.find( cChar ) != maGsubTable.end() );
}

const ImplFontCharMap* ImplWinFontData::GetImplFontCharMap() const
const ImplFontCharMapPtr ImplWinFontData::GetImplFontCharMap() const
{
    if( !mpUnicodeMap )
        return NULL;
@@ -1298,12 +1298,14 @@ void ImplWinFontData::ReadCmapTable( HDC hDC ) const
        mbDisableGlyphApi |= aResult.mbRecoded;
        aResult.mbSymbolic = bIsSymbolFont;
        if( aResult.mnRangeCount > 0 )
            mpUnicodeMap = new ImplFontCharMap( aResult );
        {
            ImplFontCharMapPtr pUnicodeMap( new ImplFontCharMap( aResult ) );
            mpUnicodeMap = pUnicodeMap;
        }
    }

    if( !mpUnicodeMap )
        mpUnicodeMap = ImplFontCharMap::GetDefaultMap( bIsSymbolFont );
    mpUnicodeMap->AddReference();
}

void ImplWinFontData::GetFontCapabilities( HDC hDC ) const
@@ -1697,7 +1699,7 @@ sal_uLong WinSalGraphics::GetKernPairs()
    return mnFontKernPairCount;
}

const ImplFontCharMap* WinSalGraphics::GetImplFontCharMap() const
const ImplFontCharMapPtr WinSalGraphics::GetImplFontCharMap() const
{
    if( !mpWinFontData[0] )
        return ImplFontCharMap::GetDefaultMap();
@@ -2480,8 +2482,7 @@ bool WinSalGraphics::CreateFontSubset( const OUString& rToFile,
    if( aRawCffData.get() )
    {
        pWinFontData->UpdateFromHDC( getHDC() );
        const ImplFontCharMap* pCharMap = pWinFontData->GetImplFontCharMap();
        pCharMap->AddReference();
        ImplFontCharMapPtr pCharMap = pWinFontData->GetImplFontCharMap();

        sal_GlyphId aRealGlyphIds[ 256 ];
        for( int i = 0; i < nGlyphCount; ++i )
@@ -2497,7 +2498,7 @@ bool WinSalGraphics::CreateFontSubset( const OUString& rToFile,
            aRealGlyphIds[i] = aGlyphId;
        }

        pCharMap->DeReference(); // TODO: and and use a RAII object
        pCharMap = 0;

        // provide a font subset from the CFF-table
        FILE* pOutFile = fopen( aToFile.getStr(), "wb" );
@@ -2731,9 +2732,8 @@ void WinSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
                rUnicodeEnc.clear();
            }
            const ImplWinFontData* pWinFont = static_cast<const ImplWinFontData*>(pFont);
            const ImplFontCharMap* pMap = pWinFont->GetImplFontCharMap();
            ImplFontCharMapPtr pMap = pWinFont->GetImplFontCharMap();
            DBG_ASSERT( pMap && pMap->GetCharCount(), "no map" );
            pMap->AddReference();

            int nCharCount = pMap->GetCharCount();
            sal_uInt32 nChar = pMap->GetFirstChar();
@@ -2750,7 +2750,7 @@ void WinSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
                nChar = pMap->GetNextChar( nChar );
            }

            pMap->DeReference(); // TODO: and and use a RAII object
            pMap = 0;
        }
    }
    else if( pFont->IsEmbeddable() )
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index eff3f9c..958348fd 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -2952,8 +2952,6 @@ bool ImplWinFontEntry::InitKashidaHandling( HDC hDC )

PhysicalFontFace* ImplWinFontData::Clone() const
{
    if( mpUnicodeMap )
        mpUnicodeMap->AddReference();
#if ENABLE_GRAPHITE
    if ( mpGraphiteData )
        mpGraphiteData->AddReference();