diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-10-06 18:16:16 +1100 |
---|---|---|
committer | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-10-13 09:19:04 +0000 |
commit | f6d61562d41b8a49449d881da66a3d8fa519487f (patch) | |
tree | 15571322cf3bf8475fe2e1c5d1d0ae9fd38f7c1d /vcl/source/gdi | |
parent | bb1d4f8c9a275a20e8795ee36ca3259376746e4f (diff) |
vcl: Make ImplFontCharMap a pImpl and move functions to FontCharMap
To do this, I've made FontCharMap a friend class for ImplFontCharMap,
and have moved the functions directly into FontCharMap. In this patch,
I am attempting to stop the direct use of ImplFontCharMap by anything
other than FontCharMap. However, FontCharMap itself requires a
refcounter, so we will use FontCharMapPtr to access the font character
map.
Change-Id: I509b990a8cbd911c5cc1572c7d24fc5348ca06d9
Reviewed-on: https://gerrit.libreoffice.org/11823
Reviewed-by: Chris Sherlock <chris.sherlock79@gmail.com>
Tested-by: Chris Sherlock <chris.sherlock79@gmail.com>
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r-- | vcl/source/gdi/impfont.cxx | 393 |
1 files changed, 184 insertions, 209 deletions
diff --git a/vcl/source/gdi/impfont.cxx b/vcl/source/gdi/impfont.cxx index 1bd7dcd0e4cb..223e9e1fd83b 100644 --- a/vcl/source/gdi/impfont.cxx +++ b/vcl/source/gdi/impfont.cxx @@ -33,6 +33,19 @@ CmapResult::CmapResult( bool bSymbolic, , mbRecoded( false) {} +static ImplFontCharMapPtr pDefaultImplFontCharMap; +static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0}; +static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100}; + +ImplFontCharMap::~ImplFontCharMap() +{ + if( isDefaultMap() ) + return; + delete[] mpRangeCodes; + delete[] mpStartGlyphs; + delete[] mpGlyphIds; +} + ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR ) : mpRangeCodes( rCR.mpRangeCodes ) , mpStartGlyphs( rCR.mpStartGlyphs ) @@ -50,26 +63,7 @@ ImplFontCharMap::ImplFontCharMap( const CmapResult& rCR ) } } -static ImplFontCharMapPtr pDefaultImplFontCharMap; -static const sal_UCS4 aDefaultUnicodeRanges[] = {0x0020,0xD800, 0xE000,0xFFF0}; -static const sal_UCS4 aDefaultSymbolRanges[] = {0x0020,0x0100, 0xF020,0xF100}; - -bool ImplFontCharMap::IsDefaultMap() const -{ - const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges); - return bIsDefault; -} - -ImplFontCharMap::~ImplFontCharMap() -{ - if( IsDefaultMap() ) - return; - delete[] mpRangeCodes; - delete[] mpStartGlyphs; - delete[] mpGlyphIds; -} - -ImplFontCharMapPtr ImplFontCharMap::GetDefaultMap( bool bSymbols) +ImplFontCharMapPtr ImplFontCharMap::getDefaultMap( bool bSymbols ) { const sal_UCS4* pRangeCodes = aDefaultUnicodeRanges; int nCodesCount = sizeof(aDefaultUnicodeRanges) / sizeof(*pRangeCodes); @@ -85,173 +79,10 @@ ImplFontCharMapPtr ImplFontCharMap::GetDefaultMap( bool bSymbols) return pDefaultImplFontCharMap; } -int ImplFontCharMap::ImplFindRangeIndex( sal_UCS4 cChar ) const -{ - int nLower = 0; - int nMid = mnRangeCount; - int nUpper = 2 * mnRangeCount - 1; - while( nLower < nUpper ) - { - if( cChar >= mpRangeCodes[ nMid ] ) - nLower = nMid; - else - nUpper = nMid - 1; - nMid = (nLower + nUpper + 1) / 2; - } - - return nMid; -} - -bool ImplFontCharMap::HasChar( sal_UCS4 cChar ) const -{ - bool bHasChar = false; - - if( mpStartGlyphs == NULL ) { // only the char-ranges are known - const int nRange = ImplFindRangeIndex( cChar ); - if( nRange==0 && cChar<mpRangeCodes[0] ) - return false; - bHasChar = ((nRange & 1) == 0); // inside a range - } else { // glyph mapping is available - const int nGlyphIndex = GetGlyphIndex( cChar ); - bHasChar = (nGlyphIndex != 0); // not the notdef-glyph - } - - return bHasChar; -} - -int ImplFontCharMap::GetGlyphIndex( sal_UCS4 cChar ) const -{ - // return -1 if the object doesn't know the glyph ids - if( !mpStartGlyphs ) - return -1; - - // return 0 if the unicode doesn't have a matching glyph - int nRange = ImplFindRangeIndex( cChar ); - // check that we are inside any range - if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) { - // symbol aliasing gives symbol fonts a second chance - const bool bSymbolic = cChar <= 0xFF && (mpRangeCodes[0]>=0xF000) && (mpRangeCodes[1]<=0xF0FF); - if( !bSymbolic ) - return 0; - // check for symbol aliasing (U+F0xx -> U+00xx) - cChar |= 0xF000; - nRange = ImplFindRangeIndex( cChar ); - if( (nRange == 0) && (cChar < mpRangeCodes[0]) ) { - return 0; - } - } - // check that we are inside a range - if( (nRange & 1) != 0 ) - return 0; - - // get glyph index directly or indirectly - int nGlyphIndex = cChar - mpRangeCodes[ nRange ]; - const int nStartIndex = mpStartGlyphs[ nRange/2 ]; - if( nStartIndex >= 0 ) { - // the glyph index can be calculated - nGlyphIndex += nStartIndex; - } else { - // the glyphid array has the glyph index - nGlyphIndex = mpGlyphIds[ nGlyphIndex - nStartIndex]; - } - - return nGlyphIndex; -} - -// returns the number of chars supported by the font, which -// are inside the unicode range from cMin to cMax (inclusive) -int ImplFontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const -{ - int nCount = 0; - - // find and adjust range and char count for cMin - int nRangeMin = ImplFindRangeIndex( cMin ); - if( nRangeMin & 1 ) - ++nRangeMin; - else if( cMin > mpRangeCodes[ nRangeMin ] ) - nCount -= cMin - mpRangeCodes[ nRangeMin ]; - - // find and adjust range and char count for cMax - int nRangeMax = ImplFindRangeIndex( cMax ); - if( nRangeMax & 1 ) - --nRangeMax; - else - nCount -= mpRangeCodes[ nRangeMax+1 ] - cMax - 1; - - // count chars in complete ranges between cMin and cMax - for( int i = nRangeMin; i <= nRangeMax; i+=2 ) - nCount += mpRangeCodes[i+1] - mpRangeCodes[i]; - - return nCount; -} - - -sal_UCS4 ImplFontCharMap::GetLastChar() const -{ - return (mpRangeCodes[ 2*mnRangeCount-1 ] - 1); -} - -sal_UCS4 ImplFontCharMap::GetNextChar( sal_UCS4 cChar ) const -{ - if( cChar < GetFirstChar() ) - return GetFirstChar(); - if( cChar >= GetLastChar() ) - return GetLastChar(); - - int nRange = ImplFindRangeIndex( cChar + 1 ); - if( nRange & 1 ) // outside of range? - return mpRangeCodes[ nRange + 1 ]; // => first in next range - return (cChar + 1); -} - -sal_UCS4 ImplFontCharMap::GetPrevChar( sal_UCS4 cChar ) const -{ - if( cChar <= GetFirstChar() ) - return GetFirstChar(); - if( cChar > GetLastChar() ) - return GetLastChar(); - - int nRange = ImplFindRangeIndex( cChar - 1 ); - if( nRange & 1 ) // outside a range? - return (mpRangeCodes[ nRange ] - 1); // => last in prev range - return (cChar - 1); -} - -int ImplFontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const -{ - // TODO: improve linear walk? - int nCharIndex = 0; - const sal_UCS4* pRange = &mpRangeCodes[0]; - for( int i = 0; i < mnRangeCount; ++i ) - { - sal_UCS4 cFirst = *(pRange++); - sal_UCS4 cLast = *(pRange++); - if( cChar >= cLast ) - nCharIndex += cLast - cFirst; - else if( cChar >= cFirst ) - return nCharIndex + (cChar - cFirst); - else - break; - } - - return -1; -} - -sal_UCS4 ImplFontCharMap::GetCharFromIndex( int nCharIndex ) const +bool ImplFontCharMap::isDefaultMap() const { - // TODO: improve linear walk? - const sal_UCS4* pRange = &mpRangeCodes[0]; - for( int i = 0; i < mnRangeCount; ++i ) - { - sal_UCS4 cFirst = *(pRange++); - sal_UCS4 cLast = *(pRange++); - nCharIndex -= cLast - cFirst; - if( nCharIndex < 0 ) - return (cLast + nCharIndex); - } - - // we can only get here with an out-of-bounds charindex - return mpRangeCodes[0]; + const bool bIsDefault = (mpRangeCodes == aDefaultUnicodeRanges) || (mpRangeCodes == aDefaultSymbolRanges); + return bIsDefault; } static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} @@ -543,74 +374,218 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) } FontCharMap::FontCharMap() -: mpImplFontCharMap( ImplFontCharMap::GetDefaultMap() ) +: mpImplFontCharMap( ImplFontCharMap::getDefaultMap() ) +{} + +FontCharMap::FontCharMap( ImplFontCharMapPtr pIFCMap ) +: mpImplFontCharMap( pIFCMap ) {} +FontCharMap::FontCharMap( const CmapResult& rCR ) +{ + ImplFontCharMapPtr pImplFontCharMap( new ImplFontCharMap(rCR) ); + mpImplFontCharMap = pImplFontCharMap; + + const sal_UCS4* pRangePtr = mpImplFontCharMap->mpRangeCodes; + for( int i = mpImplFontCharMap->mnRangeCount; --i >= 0; pRangePtr += 2 ) + { + sal_UCS4 cFirst = pRangePtr[0]; + sal_UCS4 cLast = pRangePtr[1]; + mpImplFontCharMap->mnCharCount += cLast - cFirst; + } +} + FontCharMap::~FontCharMap() { mpImplFontCharMap = 0; } -int FontCharMap::GetCharCount() const +FontCharMapPtr FontCharMap::GetDefaultMap( bool bSymbol ) { - return mpImplFontCharMap->GetCharCount(); + FontCharMapPtr pFontCharMap( new FontCharMap( ImplFontCharMap::getDefaultMap( bSymbol ) ) ); + return pFontCharMap; } -int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const +bool FontCharMap::IsDefaultMap() const { - return mpImplFontCharMap->CountCharsInRange( cMin, cMax ); + return mpImplFontCharMap->isDefaultMap(); } -void FontCharMap::Reset( const ImplFontCharMapPtr pNewMap ) +int FontCharMap::GetCharCount() const { - if( !pNewMap ) - { - mpImplFontCharMap = ImplFontCharMap::GetDefaultMap(); - } - else if( pNewMap != mpImplFontCharMap ) - { - mpImplFontCharMap = pNewMap; - } + return GetCharCount(); } -bool FontCharMap::IsDefaultMap() const +int FontCharMap::CountCharsInRange( sal_UCS4 cMin, sal_UCS4 cMax ) const { - return mpImplFontCharMap->IsDefaultMap(); + int nCount = 0; + + // find and adjust range and char count for cMin + int nRangeMin = findRangeIndex( cMin ); + if( nRangeMin & 1 ) + ++nRangeMin; + else if( cMin > mpImplFontCharMap->mpRangeCodes[ nRangeMin ] ) + nCount -= cMin - mpImplFontCharMap->mpRangeCodes[ nRangeMin ]; + + // find and adjust range and char count for cMax + int nRangeMax = findRangeIndex( cMax ); + if( nRangeMax & 1 ) + --nRangeMax; + else + nCount -= mpImplFontCharMap->mpRangeCodes[ nRangeMax+1 ] - cMax - 1; + + // count chars in complete ranges between cMin and cMax + for( int i = nRangeMin; i <= nRangeMax; i+=2 ) + nCount += mpImplFontCharMap->mpRangeCodes[i+1] - mpImplFontCharMap->mpRangeCodes[i]; + + return nCount; } bool FontCharMap::HasChar( sal_UCS4 cChar ) const { - return mpImplFontCharMap->HasChar( cChar ); + bool bHasChar = false; + + if( mpImplFontCharMap->mpStartGlyphs == NULL ) { // only the char-ranges are known + const int nRange = findRangeIndex( cChar ); + if( nRange==0 && cChar < mpImplFontCharMap->mpRangeCodes[0] ) + return false; + bHasChar = ((nRange & 1) == 0); // inside a range + } else { // glyph mapping is available + const int nGlyphIndex = GetGlyphIndex( cChar ); + bHasChar = (nGlyphIndex != 0); // not the notdef-glyph + } + + return bHasChar; } sal_UCS4 FontCharMap::GetFirstChar() const { - return mpImplFontCharMap->GetFirstChar(); + return mpImplFontCharMap->mpRangeCodes[0]; } sal_UCS4 FontCharMap::GetLastChar() const { - return mpImplFontCharMap->GetLastChar(); + return (mpImplFontCharMap->mpRangeCodes[ 2*mpImplFontCharMap->mnRangeCount-1 ] - 1); } sal_UCS4 FontCharMap::GetNextChar( sal_UCS4 cChar ) const { - return mpImplFontCharMap->GetNextChar( cChar ); + if( cChar < GetFirstChar() ) + return GetFirstChar(); + if( cChar >= GetLastChar() ) + return GetLastChar(); + + int nRange = findRangeIndex( cChar + 1 ); + if( nRange & 1 ) // outside of range? + return mpImplFontCharMap->mpRangeCodes[ nRange + 1 ]; // => first in next range + return (cChar + 1); } sal_UCS4 FontCharMap::GetPrevChar( sal_UCS4 cChar ) const { - return mpImplFontCharMap->GetPrevChar( cChar ); + if( cChar <= GetFirstChar() ) + return GetFirstChar(); + if( cChar > GetLastChar() ) + return GetLastChar(); + + int nRange = findRangeIndex( cChar - 1 ); + if( nRange & 1 ) // outside a range? + return (mpImplFontCharMap->mpRangeCodes[ nRange ] - 1); // => last in prev range + return (cChar - 1); } int FontCharMap::GetIndexFromChar( sal_UCS4 cChar ) const { - return mpImplFontCharMap->GetIndexFromChar( cChar ); + // TODO: improve linear walk? + int nCharIndex = 0; + const sal_UCS4* pRange = &mpImplFontCharMap->mpRangeCodes[0]; + for( int i = 0; i < mpImplFontCharMap->mnRangeCount; ++i ) + { + sal_UCS4 cFirst = *(pRange++); + sal_UCS4 cLast = *(pRange++); + if( cChar >= cLast ) + nCharIndex += cLast - cFirst; + else if( cChar >= cFirst ) + return nCharIndex + (cChar - cFirst); + else + break; + } + + return -1; } sal_UCS4 FontCharMap::GetCharFromIndex( int nIndex ) const { - return mpImplFontCharMap->GetCharFromIndex( nIndex ); + // TODO: improve linear walk? + const sal_UCS4* pRange = &mpImplFontCharMap->mpRangeCodes[0]; + for( int i = 0; i < mpImplFontCharMap->mnRangeCount; ++i ) + { + sal_UCS4 cFirst = *(pRange++); + sal_UCS4 cLast = *(pRange++); + nIndex -= cLast - cFirst; + if( nIndex < 0 ) + return (cLast + nIndex); + } + + // we can only get here with an out-of-bounds charindex + return mpImplFontCharMap->mpRangeCodes[0]; +} + +int FontCharMap::findRangeIndex( sal_UCS4 cChar ) const +{ + int nLower = 0; + int nMid = mpImplFontCharMap->mnRangeCount; + int nUpper = 2 * mpImplFontCharMap->mnRangeCount - 1; + while( nLower < nUpper ) + { + if( cChar >= mpImplFontCharMap->mpRangeCodes[ nMid ] ) + nLower = nMid; + else + nUpper = nMid - 1; + nMid = (nLower + nUpper + 1) / 2; + } + + return nMid; +} + +int FontCharMap::GetGlyphIndex( sal_UCS4 cChar ) const +{ + // return -1 if the object doesn't know the glyph ids + if( !mpImplFontCharMap->mpStartGlyphs ) + return -1; + + // return 0 if the unicode doesn't have a matching glyph + int nRange = findRangeIndex( cChar ); + // check that we are inside any range + if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) { + // symbol aliasing gives symbol fonts a second chance + const bool bSymbolic = cChar <= 0xFF && (mpImplFontCharMap->mpRangeCodes[0]>=0xF000) && + (mpImplFontCharMap->mpRangeCodes[1]<=0xF0FF); + if( !bSymbolic ) + return 0; + // check for symbol aliasing (U+F0xx -> U+00xx) + cChar |= 0xF000; + nRange = findRangeIndex( cChar ); + if( (nRange == 0) && (cChar < mpImplFontCharMap->mpRangeCodes[0]) ) { + return 0; + } + } + // check that we are inside a range + if( (nRange & 1) != 0 ) + return 0; + + // get glyph index directly or indirectly + int nGlyphIndex = cChar - mpImplFontCharMap->mpRangeCodes[ nRange ]; + const int nStartIndex = mpImplFontCharMap->mpStartGlyphs[ nRange/2 ]; + if( nStartIndex >= 0 ) { + // the glyph index can be calculated + nGlyphIndex += nStartIndex; + } else { + // the glyphid array has the glyph index + nGlyphIndex = mpImplFontCharMap->mpGlyphIds[ nGlyphIndex - nStartIndex]; + } + + return nGlyphIndex; } // on some systems we have to get the font attributes from the name table |