Kaydet (Commit) dd547e4a authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Fix headless mode glyph cache memory handling

...the original code was riddled with errors.  It leaked memory, which if it
didn't it would have deleted multiple times.

Change-Id: Ic70b425fac02ef894e35b3dc15039d217f8870f5
üst 333b7fb3
......@@ -650,7 +650,6 @@ ImplFontEntry* ImplFTSFontData::CreateFontInstance( FontSelectPattern& rFSD ) co
ServerFont::ServerFont( const FontSelectPattern& rFSD, FtFontInfo* pFI )
: maGlyphList( 0),
maFontSelData(rFSD),
mnExtInfo(0),
mnRefCount(1),
mnBytesUsed( sizeof(ServerFont) ),
mpPrevGCFont( NULL ),
......@@ -1420,20 +1419,19 @@ bool ServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap ) const
if( rRawBitmap.mnAllocated < nNeededSize )
{
delete[] rRawBitmap.mpBits;
rRawBitmap.mnAllocated = 2*nNeededSize;
rRawBitmap.mpBits = new unsigned char[ rRawBitmap.mnAllocated ];
rRawBitmap.mpBits.reset(new unsigned char[ rRawBitmap.mnAllocated ]);
}
if( !mbArtBold || pFTEmbolden )
{
memcpy( rRawBitmap.mpBits, rBitmapFT.buffer, nNeededSize );
memcpy( rRawBitmap.mpBits.get(), rBitmapFT.buffer, nNeededSize );
}
else
{
memset( rRawBitmap.mpBits, 0, nNeededSize );
memset( rRawBitmap.mpBits.get(), 0, nNeededSize );
const unsigned char* pSrcLine = rBitmapFT.buffer;
unsigned char* pDstLine = rRawBitmap.mpBits;
unsigned char* pDstLine = rRawBitmap.mpBits.get();
for( int h = rRawBitmap.mnHeight; --h >= 0; )
{
memcpy( pDstLine, pSrcLine, rBitmapFT.pitch );
......@@ -1441,7 +1439,7 @@ bool ServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap ) const
pSrcLine += rBitmapFT.pitch;
}
unsigned char* p = rRawBitmap.mpBits;
unsigned char* p = rRawBitmap.mpBits.get();
for( sal_uLong y=0; y < rRawBitmap.mnHeight; y++ )
{
unsigned char nLastByte = 0;
......@@ -1549,13 +1547,12 @@ bool ServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap ) const
const sal_uLong nNeededSize = rRawBitmap.mnScanlineSize * rRawBitmap.mnHeight;
if( rRawBitmap.mnAllocated < nNeededSize )
{
delete[] rRawBitmap.mpBits;
rRawBitmap.mnAllocated = 2*nNeededSize;
rRawBitmap.mpBits = new unsigned char[ rRawBitmap.mnAllocated ];
rRawBitmap.mpBits.reset(new unsigned char[ rRawBitmap.mnAllocated ]);
}
const unsigned char* pSrc = rBitmapFT.buffer;
unsigned char* pDest = rRawBitmap.mpBits;
unsigned char* pDest = rRawBitmap.mpBits.get();
if( !bEmbedded )
{
for( int y = rRawBitmap.mnHeight, x; --y >= 0 ; )
......@@ -1585,7 +1582,7 @@ bool ServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap ) const
if( mbArtBold && !pFTEmbolden )
{
// overlay with glyph image shifted by one left pixel
unsigned char* p = rRawBitmap.mpBits;
unsigned char* p = rRawBitmap.mpBits.get();
for( sal_uLong y=0; y < rRawBitmap.mnHeight; y++ )
{
unsigned char nLastByte = 0;
......@@ -1601,7 +1598,7 @@ bool ServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap ) const
if( !bEmbedded && mbUseGamma )
{
unsigned char* p = rRawBitmap.mpBits;
unsigned char* p = rRawBitmap.mpBits.get();
for( sal_uLong y=0; y < rRawBitmap.mnHeight; y++ )
{
for( sal_uLong x=0; x < rRawBitmap.mnWidth; x++ )
......
......@@ -23,16 +23,12 @@
RawBitmap::RawBitmap()
: mpBits(0), mnAllocated(0)
: mnAllocated(0)
{}
RawBitmap::~RawBitmap()
{
delete[] mpBits;
mpBits = 0;
mnAllocated = 0;
}
{}
// used by 90 and 270 degree rotations on 8 bit deep bitmaps
......@@ -171,7 +167,7 @@ bool RawBitmap::Rotate( int nAngle )
mnYOffset = -(mnYOffset + mnHeight);
if( mnBitCount == 8 )
{
ImplRotate8_180( mpBits, mnWidth, mnHeight, mnScanlineSize-mnWidth );
ImplRotate8_180( mpBits.get(), mnWidth, mnHeight, mnScanlineSize-mnWidth );
return true;
}
nNewWidth = mnWidth;
......@@ -203,7 +199,7 @@ bool RawBitmap::Rotate( int nAngle )
{
case 1800: // rotate by 180 degrees
// we know we only need to deal with 1 bit depth
ImplRotate1_180( pBuf, mpBits + mnHeight * mnScanlineSize,
ImplRotate1_180( pBuf, mpBits.get() + mnHeight * mnScanlineSize,
mnWidth, mnHeight, mnScanlineSize - (mnWidth + 7) / 8 );
break;
case +900: // rotate left by 90 degrees
......@@ -211,11 +207,11 @@ bool RawBitmap::Rotate( int nAngle )
mnXOffset = mnYOffset;
mnYOffset = -nNewHeight - i;
if( mnBitCount == 8 )
ImplRotate8_90( pBuf, mpBits + mnWidth - 1,
ImplRotate8_90( pBuf, mpBits.get() + mnWidth - 1,
nNewWidth, nNewHeight, +mnScanlineSize, -1-mnHeight*mnScanlineSize,
nNewScanlineSize - nNewWidth );
else
ImplRotate1_90( pBuf, mpBits + (mnWidth - 1) / 8,
ImplRotate1_90( pBuf, mpBits.get() + (mnWidth - 1) / 8,
nNewWidth, nNewHeight, +mnScanlineSize,
(-mnWidth & 7), +1, nNewScanlineSize - (nNewWidth + 7) / 8 );
break;
......@@ -225,11 +221,11 @@ bool RawBitmap::Rotate( int nAngle )
mnXOffset = -(nNewWidth + mnYOffset);
mnYOffset = i;
if( mnBitCount == 8 )
ImplRotate8_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
ImplRotate8_90( pBuf, mpBits.get() + mnScanlineSize * (mnHeight-1),
nNewWidth, nNewHeight, -mnScanlineSize, +1+mnHeight*mnScanlineSize,
nNewScanlineSize - nNewWidth );
else
ImplRotate1_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
ImplRotate1_90( pBuf, mpBits.get() + mnScanlineSize * (mnHeight-1),
nNewWidth, nNewHeight, -mnScanlineSize,
+7, -1, nNewScanlineSize - (nNewWidth + 7) / 8 );
break;
......@@ -241,13 +237,12 @@ bool RawBitmap::Rotate( int nAngle )
if( nBufSize < mnAllocated )
{
memcpy( mpBits, pBuf, nBufSize );
memcpy( mpBits.get(), pBuf, nBufSize );
delete[] pBuf;
}
else
{
delete[] mpBits;
mpBits = pBuf;
mpBits.reset(pBuf);
mnAllocated = nBufSize;
}
......
......@@ -315,9 +315,9 @@ void GlyphCache::GrowNotify()
}
inline void GlyphCache::RemovingGlyph( ServerFont& rSF, GlyphData& rGD, int nGlyphIndex )
inline void GlyphCache::RemovingGlyph( GlyphData& rGD )
{
mrPeer.RemovingGlyph( rSF, rGD, nGlyphIndex );
mrPeer.RemovingGlyph( rGD );
mnBytesUsed -= sizeof( GlyphData );
--mnGlyphCount;
}
......@@ -372,7 +372,7 @@ void ServerFont::GarbageCollect( long nMinLruIndex )
{
OSL_ASSERT( mnBytesUsed >= sizeof(GlyphData) );
mnBytesUsed -= sizeof( GlyphData );
GlyphCache::GetInstance().RemovingGlyph( *this, rGD, it->first );
GlyphCache::GetInstance().RemovingGlyph( rGD );
maGlyphList.erase( it );
it_next = maGlyphList.begin();
}
......
......@@ -17,6 +17,10 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "sal/config.h"
#include <cassert>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/range/b2ibox.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
......@@ -50,7 +54,7 @@ public:
protected:
virtual void RemovingFont( ServerFont& );
virtual void RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
virtual void RemovingGlyph( GlyphData& );
class SvpGcpHelper
{
......@@ -113,14 +117,14 @@ BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
int nGlyphIndex, basebmp::Format nBmpFormat, B2IPoint& rTargetPos )
{
GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
// nothing to do if the GlyphPeer hasn't allocated resources for the glyph
if( rGlyphData.ExtDataRef().meInfo != nBmpFormat )
{
if( rGlyphData.ExtDataRef().meInfo == FORMAT_NONE )
SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
rGlyphData.ExtDataRef().mpData);
bool bNew = pGcpHelper == 0;
if( bNew )
pGcpHelper = new SvpGcpHelper;
RawBitmap& rRawBitmap = pGcpHelper->maRawBitmap;
// get glyph bitmap in matching format
bool bFound = false;
......@@ -143,22 +147,28 @@ BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
// return .notdef glyph if needed
if( !bFound && (nGlyphIndex != 0) )
{
delete pGcpHelper;
if( bNew )
delete pGcpHelper;
return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
}
// construct alpha mask from raw bitmap
const B2IVector aSize( rRawBitmap.mnScanlineSize, rRawBitmap.mnHeight );
const B2IVector aSize(
pGcpHelper->maRawBitmap.mnScanlineSize,
pGcpHelper->maRawBitmap.mnHeight );
if( aSize.getX() && aSize.getY() )
{
static PaletteMemorySharedVector aDummyPAL;
RawMemorySharedArray aRawPtr( rRawBitmap.mpBits );
pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aRawPtr, aDummyPAL );
pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, pGcpHelper->maRawBitmap.mpBits, aDummyPAL );
}
rServerFont.SetExtended( nBmpFormat, (void*)pGcpHelper );
rGlyphData.ExtDataRef().meInfo = nBmpFormat;
rGlyphData.ExtDataRef().mpData = pGcpHelper;
}
SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
rGlyphData.ExtDataRef().mpData);
assert(pGcpHelper != 0);
rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
return pGcpHelper->maBitmapDev;
}
......@@ -170,16 +180,13 @@ void SvpGlyphPeer::RemovingFont( ServerFont& )
}
void SvpGlyphPeer::RemovingGlyph( ServerFont&, GlyphData& rGlyphData, int /*nGlyphIndex*/ )
void SvpGlyphPeer::RemovingGlyph( GlyphData& rGlyphData )
{
if( rGlyphData.ExtDataRef().mpData != 0 )
{
// release the glyph related resources
DBG_ASSERT( (rGlyphData.ExtDataRef().meInfo <= FORMAT_MAX), "SVP::RG() invalid alpha format" );
SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
delete[] pGcpHelper->maRawBitmap.mpBits;
delete pGcpHelper;
}
SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
rGlyphData.ExtDataRef().mpData);
rGlyphData.ExtDataRef().meInfo = basebmp::FORMAT_NONE;
rGlyphData.ExtDataRef().mpData = 0;
delete pGcpHelper;
}
......
......@@ -34,6 +34,7 @@ struct ImplKernPairData;
class ImplFontOptions;
#include <tools/gen.hxx>
#include <basebmp/bitmapdevice.hxx>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <boost/shared_ptr.hpp>
......@@ -90,7 +91,7 @@ private:
friend class ServerFont;
// used by ServerFont class only
void AddedGlyph( ServerFont&, GlyphData& );
void RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
void RemovingGlyph( GlyphData& );
void UsingGlyph( ServerFont&, GlyphData& );
void GrowNotify();
......@@ -139,7 +140,9 @@ private:
// -----------------------------------------------------------------------
// the glyph specific data needed by a GlyphCachePeer is usually trivial,
// not attaching it to the corresponding GlyphData would be overkill
// not attaching it to the corresponding GlyphData would be overkill;
// this is currently only used by the headless (aka svp) plugin, where meInfo is
// basebmp::Format and mpData is SvpGcpHelper*
struct ExtGlyphData
{
int meInfo;
......@@ -219,10 +222,6 @@ public:
bool GetGlyphBitmap1( int nGlyphIndex, RawBitmap& ) const;
bool GetGlyphBitmap8( int nGlyphIndex, RawBitmap& ) const;
void SetExtended( int nInfo, void* ppVoid );
int GetExtInfo() { return mnExtInfo; }
void* GetExtPointer() { return mpExtData; }
private:
friend class GlyphCache;
friend class ServerFontLayout;
......@@ -248,10 +247,6 @@ private:
const FontSelectPattern maFontSelData;
// info for GlyphcachePeer
int mnExtInfo;
void* mpExtData;
// used by GlyphCache for cache LRU algorithm
mutable long mnRefCount;
mutable sal_uLong mnBytesUsed;
......@@ -351,7 +346,7 @@ protected:
public:
sal_Int32 GetByteCount() const { return mnBytesUsed; }
virtual void RemovingFont( ServerFont& ) {}
virtual void RemovingGlyph( ServerFont&, GlyphData&, int ) {}
virtual void RemovingGlyph( GlyphData& ) {}
protected:
sal_Int32 mnBytesUsed;
......@@ -367,7 +362,7 @@ public:
bool Rotate( int nAngle );
public:
unsigned char* mpBits;
basebmp::RawMemorySharedArray mpBits;
sal_uLong mnAllocated;
sal_uLong mnWidth;
......@@ -382,14 +377,6 @@ public:
// =======================================================================
inline void ServerFont::SetExtended( int nInfo, void* pVoid )
{
mnExtInfo = nInfo;
mpExtData = pVoid;
}
// =======================================================================
// ExtraKernInfo allows an on-demand query of extra kerning info #i29881#
// The kerning values have to be scaled to match the font size before use
class VCL_DLLPUBLIC ExtraKernInfo
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment