diff options
author | Herbert Duerr <hdu@openoffice.org> | 2001-07-06 12:58:01 +0000 |
---|---|---|
committer | Herbert Duerr <hdu@openoffice.org> | 2001-07-06 12:58:01 +0000 |
commit | 0801ad4c1825ed932cb66f2a47aff9e545863483 (patch) | |
tree | 54cd76e470351e4ae8cd47fe15510283c836599d /vcl | |
parent | bd7fee2bb03f9d879994ccd0c64919e538da6774 (diff) |
#81268# implement GetTable() and GetFontCodeRanges()
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/glyphs/gcach_ftyp.cxx | 247 |
1 files changed, 135 insertions, 112 deletions
diff --git a/vcl/source/glyphs/gcach_ftyp.cxx b/vcl/source/glyphs/gcach_ftyp.cxx index 3eb4c8673aca..baa717526cbd 100644 --- a/vcl/source/glyphs/gcach_ftyp.cxx +++ b/vcl/source/glyphs/gcach_ftyp.cxx @@ -2,8 +2,8 @@ * * $RCSfile: gcach_ftyp.cxx,v $ * - * $Revision: 1.48 $ - * last change: $Author: cp $ $Date: 2001-07-05 15:37:21 $ + * $Revision: 1.49 $ + * last change: $Author: hdu $ $Date: 2001-07-06 13:58:01 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -224,7 +224,7 @@ FtFontInfo::FtFontInfo( const ImplFontData& rFontData, // using unicode emulation for non-symbol fonts if( maFontData.meCharSet != RTL_TEXTENCODING_SYMBOL ) - maFontData.meCharSet = RTL_TEXTENCODING_UNICODE; + maFontData.meCharSet = RTL_TEXTENCODING_UNICODE; } // ----------------------------------------------------------------------- @@ -244,6 +244,49 @@ bool std::equal_to<FtFontInfo*>::operator()( const FtFontInfo* pA, const FtFontI // ----------------------------------------------------------------------- +static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} +static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);} +static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));} + +// ----------------------------------------------------------------------- + +const unsigned char* FtFontInfo::GetTable( const char* pTag, ULONG* pLength ) const +{ + const unsigned char* pBuffer = GetBuffer(); + int nFileSize = GetFileSize(); + if( !pBuffer || nFileSize<1024 ) + return NULL; + + // we currently only handle TTF and TTC headers + unsigned nFormat = GetUInt( pBuffer ); + const unsigned char* p = pBuffer + 12; + if( nFormat == 0x74746366 ) // TTC_MAGIC + p += GetUInt( p + 4 * mnFaceNum ); + else if( nFormat != 0x00010000 ) // TTF_MAGIC + return NULL; + + // walk table directory until match + int nTables = GetUShort( p - 8 ); + if( nTables >= 64 ) // something fishy? + return NULL; + for( int i = 0; i < nTables; ++i, p+=16 ) + { + if( p[0]==pTag[0] && p[1]==pTag[1] && p[2]==pTag[2] && p[3]==pTag[3] ) + { + ULONG nLength = GetUInt( p + 12 ); + if( pLength != NULL ) + *pLength = nLength; + const unsigned char* pTable = pBuffer + GetUInt( p + 8 ); + if( (pTable + nLength) <= (GetBuffer() + nFileSize) ) + return pTable; + } + } + + return NULL; +} + +// ======================================================================= + FreetypeManager::FreetypeManager() { FT_Error rcFT = FT_Init_FreeType( &aLibFT ); @@ -424,10 +467,10 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn #if (FTVERSION < 200) eEncoding = ft_encoding_none; #else - if (FT_IS_SFNT( maFaceFT )) + if( FT_IS_SFNT( maFaceFT ) ) eEncoding = ft_encoding_symbol; else - eEncoding = ft_encoding_adobe_custom; + eEncoding = ft_encoding_adobe_custom; // freetype wants this for PS symbol fonts #endif } rc = FT_Select_Charmap( maFaceFT, eEncoding ); @@ -446,9 +489,9 @@ FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontIn mnLoadFlags |= FT_LOAD_NO_BITMAP; if( nSin != 0 && nCos != 0 ) // hinting for 0/90/180/270 degrees only mnLoadFlags |= FT_LOAD_NO_HINTING; - mnLoadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; //#88334# + mnLoadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; //#88334# -#if (FTVERSION < 203) && !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) +#if (FTVERSION < 205) && !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) mnLoadFlags |= FT_LOAD_NO_HINTING; // TODO: enable when AH improves #endif } @@ -591,12 +634,11 @@ int FreetypeServerFont::GetGlyphIndex( sal_Unicode aChar ) const if( mpFontInfo->GetFontData().meCharSet == RTL_TEXTENCODING_SYMBOL ) if( FT_IS_SFNT( maFaceFT ) ) aChar |= 0xF000; // emulate W2K high/low mapping of symbols - else { - if( (aChar&0xFF00) == 0xF000) - aChar &= 0x00FF; // PS font symbol mapping - if (aChar<256) - return FT_Get_Char_Index( maFaceFT, aChar ); - else + else + { + if( (aChar&0xFF00) == 0xF000 ) + aChar &= 0xFF; // PS font symbol mapping + else if( aChar > 0xFF ) return 0; } @@ -730,8 +772,8 @@ bool FreetypeServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap const unsigned char* pSrc = rBitmapFT.buffer; unsigned char* pDest = rRawBitmap.mpBits; - for( int i = nNeededSize; --i >= 0; ) - *(pDest++) = ~*(pSrc++); + for( int i = nNeededSize; --i >= 0; ) + *(pDest++) = ~*(pSrc++); FT_Done_Glyph( aGlyphFT ); return true; @@ -746,8 +788,8 @@ bool FreetypeServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap FT_Int nLoadFlags = mnLoadFlags; if( nGlyphFlags != 0 ) nLoadFlags |= FT_LOAD_NO_BITMAP; -#if (FTVERSION < 203) && !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) - // autohinting in FT<=2.0.2 makes antialiased glyphs look worse +#if (FTVERSION < 205) && !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER) + // autohinting in FT<=2.0.4 makes antialiased glyphs look worse nLoadFlags |= FT_LOAD_NO_HINTING; #endif @@ -828,6 +870,74 @@ bool FreetypeServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap } // ----------------------------------------------------------------------- +// determine unicode ranges in font +// ----------------------------------------------------------------------- + +ULONG FreetypeServerFont::GetFontCodeRanges( sal_uInt32* pCodes ) const +{ + int nRangeCount = 0; + + const unsigned char* pCmap = NULL; + ULONG nLength = 0; + if( FT_IS_SFNT( maFaceFT ) ) + pCmap = mpFontInfo->GetTable( "cmap", &nLength ); + + if( pCmap && GetUShort( pCmap )==0 ) + { + int nSubTables = GetUShort( pCmap + 2 ); + const unsigned char* p = pCmap + 4; + int nOffset = 0; + int nFormat = -1; + for( ; --nSubTables>=0; p+=8 ) + { + int nPlatform = GetUShort( p ); + int nEncoding = GetUShort( p+2 ); + if( nEncoding!=0 && nEncoding!=1 ) // unicode encodings? + continue; + nOffset = GetUInt( p+4 ); + nFormat = GetUShort( pCmap + nOffset ); + if( nFormat==4 ) + break; + } + + if( nFormat==4 && (nOffset+16)<nLength ) + { + // analyze most common unicode mapping table + int nSegCount = GetUShort( pCmap + nOffset + 6 ); + nRangeCount = nSegCount/2 - 1; + if( pCodes ) + { + const unsigned char* pLimit = pCmap + nOffset + 14; + const unsigned char* pBegin = pLimit + 2 + nSegCount; + for( int i = 0; i < nRangeCount; ++i ) + { + *(pCodes++) = GetUShort( pBegin + 2*i ); + *(pCodes++) = GetUShort( pLimit + 2*i ) + 1; + } + } + } + } + + if( !nRangeCount ) + { + // unknown format, platform or encoding => use the brute force method + for( sal_uInt32 cCode = 0x0020;; ) + { + for(; cCode<0xFFF0 && !GetGlyphIndex( cCode ); ++cCode ); + if( cCode >= 0xFFF0 ) + break; + ++nRangeCount; + if( pCodes ) + *(pCodes++) = cCode; + for(; cCode<0xFFF0 && GetGlyphIndex( cCode ); ++cCode ); + if( pCodes ) + *(pCodes++) = cCode; + } + } + + return nRangeCount; +} +// ----------------------------------------------------------------------- // kerning stuff // ----------------------------------------------------------------------- @@ -838,18 +948,11 @@ ULONG FreetypeServerFont::GetKernPairs( ImplKernPairData** ppKernPairs ) const return 0; // first figure out which glyph pairs are involved in kerning - SFNT_Interface* pSFNT = (SFNT_Interface*) FT_Get_Module_Interface( aLibFT, "sfnt" ); - if( !pSFNT ) + ULONG nKernLength = 0; + const FT_Byte* const pKern = mpFontInfo->GetTable( "kern", &nKernLength ); + if( !pKern ) return 0; - FT_ULong nKernLength = 0; - FT_Error rcFT = pSFNT->load_any( (TT_Face)maFaceFT, TTAG_kern, 0, NULL, &nKernLength ); - if( rcFT != FT_Err_Ok ) - return 0; - - FT_Byte* const pKern = new FT_Byte[ nKernLength ]; - rcFT = pSFNT->load_any( (TT_Face)maFaceFT, TTAG_kern, 0, pKern, &nKernLength ); - typedef std::vector<ImplKernPairData> KernVector; KernVector aKernGlyphVector; ImplKernPairData aKernPair; @@ -920,8 +1023,6 @@ ULONG FreetypeServerFont::GetKernPairs( ImplKernPairData** ppKernPairs ) const } } - delete[] pKern; - // now create VCL's ImplKernPairData[] format for all glyph pairs ULONG nKernCount = aKernGlyphVector.size(); if( nKernCount ) @@ -931,7 +1032,7 @@ ULONG FreetypeServerFont::GetKernPairs( ImplKernPairData** ppKernPairs ) const // eliminate it up by redesigning kerning infrastructure to work with glyph indizes typedef std::hash_multimap<USHORT,sal_Unicode> Cmap; Cmap aCmap; - for( sal_Unicode aChar = 0x0001; aChar < 0xFFFE; ++aChar ) + for( sal_Unicode aChar = 0x0020; aChar < 0xFFFE; ++aChar ) { USHORT nGlyphIndex = GetGlyphIndex( aChar ); if( nGlyphIndex ) @@ -1158,18 +1259,6 @@ bool FreetypeServerFont::GetGlyphOutline( int nGlyphIndex, PolyPolygon& rPolyPol bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) { - if( !FT_IS_SFNT( maFaceFT ) ) - return false; - SFNT_Interface* pSFNT = (SFNT_Interface*) FT_Get_Module_Interface( aLibFT, "sfnt" ); - if( !pSFNT ) - return false; - - // get length of GSUB table if it exists - FT_ULong nLength = 0; - FT_Error rcFT = pSFNT->load_any( (TT_Face)maFaceFT, TTAG_GSUB, 0, NULL, &nLength ); - if( rcFT != FT_Err_Ok ) - return false; - #define MKTAG(s) ((((((s[0]<<8)+s[1])<<8)+s[2])<<8)+s[3]) typedef std::vector<ULONG> ReqFeatureTagList; @@ -1184,8 +1273,10 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) return true; // load GSUB table into memory - FT_Byte* const pGsubBase = new FT_Byte[ nLength ]; - rcFT = pSFNT->load_any( (TT_Face)maFaceFT, TTAG_GSUB, 0, pGsubBase, &nLength ); + ULONG nLength = 0; + const FT_Byte* const pGsubBase = mpFontInfo->GetTable( "GSUB", &nLength ); + if( !pGsubBase ) + return false; // parse GSUB header const FT_Byte* pGsubHeader = pGsubBase; @@ -1198,9 +1289,6 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) UshortList aFeatureIndexList; UshortList aFeatureOffsetList; -#ifdef DEBUG - fprintf(stderr,"***GSUB\n"); -#endif // parse Script Table const FT_Byte* pScriptHeader = pGsubBase + nOfsScriptList; const USHORT nCntScript = NEXT_UShort( pScriptHeader ); @@ -1208,9 +1296,6 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) { const ULONG nTag = NEXT_Long( pScriptHeader ); // e.g. hani/arab/kana/hang const USHORT nOfsScriptTable= NEXT_UShort( pScriptHeader ); -#ifdef DEBUG - fprintf(stderr,"Script[%d] tag=%.4s, ofs=%d\n", nScriptIndex, &nTag, nOfsScriptTable); -#endif if( (nTag != nRequestedScript) && (nRequestedScript != 0) ) continue; @@ -1218,16 +1303,10 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nDefaultLangsysOfs = NEXT_UShort( pScriptTable ); const USHORT nCntLangSystem = NEXT_UShort( pScriptTable ); USHORT nLangsysOffset = 0; -#ifdef DEBUG - fprintf(stderr,"ofs=%d => def=%d, cnt=%d\n", nOfsScriptTable, nDefaultLangsysOfs, nCntLangSystem ); -#endif for( USHORT nLangsysIndex = 0; nLangsysIndex < nCntLangSystem; ++nLangsysIndex ) { const ULONG nTag = NEXT_Long( pScriptTable ); // e.g. KOR/ZHS/ZHT/JAN const USHORT nOffset= NEXT_UShort( pScriptTable ); -#ifdef DEBUG - fprintf(stderr,"Langsys[%d] tag=%.4s, ofs=%d\n", nLangsysIndex, &nTag, nOffset); -#endif if( (nTag != nRequestedLangsys) && (nRequestedLangsys != 0) ) continue; nLangsysOffset = nOffset; @@ -1241,15 +1320,9 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys ); const USHORT nCntFeature = NEXT_UShort( pLangSys ); aFeatureIndexList.push_back( nReqFeatureIdx ); -#ifdef DEBUG - fprintf(stderr,"Feature defreq=%d, ofs=%d cnt=%d\n", nReqFeatureIdx, nDefaultLangsysOfs, nCntFeature ); -#endif for( USHORT i = 0; i < nCntFeature; ++i ) { const USHORT nFeatureIndex = NEXT_UShort( pLangSys ); -#ifdef DEBUG - fprintf(stderr,"Feature defopt=%d\n", nFeatureIndex); -#endif aFeatureIndexList.push_back( nFeatureIndex ); } } @@ -1261,15 +1334,9 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys ); const USHORT nCntFeature = NEXT_UShort( pLangSys ); aFeatureIndexList.push_back( nReqFeatureIdx ); -#ifdef DEBUG - fprintf(stderr,"Feature req=%d, ofs=%d cnt=%d\n", nReqFeatureIdx, nLangsysOffset, nCntFeature ); -#endif for( USHORT i = 0; i < nCntFeature; ++i ) { const USHORT nFeatureIndex = NEXT_UShort( pLangSys ); -#ifdef DEBUG - fprintf(stderr,"Feature opt=%d\n", nFeatureIndex); -#endif aFeatureIndexList.push_back( nFeatureIndex ); } } @@ -1281,24 +1348,14 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) UshortList aLookupIndexList; UshortList aLookupOffsetList; -#ifdef DEBUG - fprintf(stderr,"*parsing Feature Table ofs=%d\n", nOfsFeatureTable); -#endif // parse Feature Table const FT_Byte* pFeatureHeader = pGsubBase + nOfsFeatureTable; const USHORT nCntFeature = NEXT_UShort( pFeatureHeader ); -#ifdef DEBUG - fprintf(stderr,"nFeatureCount=%d\n", nCntFeature); -#endif for( USHORT nFeatureIndex = 0; nFeatureIndex < nCntFeature; ++nFeatureIndex ) { const ULONG nTag = NEXT_Long( pFeatureHeader ); // e.g. locl/vert/trad/smpl/liga/fina/... const USHORT nOffset= NEXT_UShort( pFeatureHeader ); -#ifdef DEBUG - fprintf(stderr,"Feature[%d] tag=%.4s, ofs=%d\n", nFeatureIndex, &nTag, nOffset ); -#endif - // feature (required && (requested || available))? if( (aFeatureIndexList[0] != nFeatureIndex) && (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag)) @@ -1307,34 +1364,21 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset; const USHORT nCntLookups = NEXT_UShort( pFeatureTable ); -#ifdef DEBUG - fprintf(stderr,"=> FeatLookup cnt=%d\n", nCntLookups); -#endif for( USHORT i = 0; i < nCntLookups; ++i ) { const USHORT nLookupIndex = NEXT_UShort( pFeatureTable ); -#ifdef DEBUG - fprintf(stderr,"=> FeatLookup[%d][%d] idx=%d\n", nFeatureIndex, i, nLookupIndex); -#endif aLookupIndexList.push_back( nLookupIndex ); } if( nCntLookups == 0 ) //### hack needed by Mincho/Gothic/Mingliu/Simsun/... aLookupIndexList.push_back( 0 ); } - // parse Lookup List -#ifdef DEBUG - fprintf(stderr,"*parsing Lookup Table ofs=%d\n", nOfsLookupList); -#endif const FT_Byte* pLookupHeader = pGsubBase + nOfsLookupList; const USHORT nCntLookupTable = NEXT_UShort( pLookupHeader ); for( USHORT nLookupIdx = 0; nLookupIdx < nCntLookupTable; ++nLookupIdx ) { const USHORT nOffset = NEXT_UShort( pLookupHeader ); -#ifdef DEBUG - fprintf(stderr,"=> Lookup[%d] ofs=%d\n", nLookupIdx, nOffset); -#endif if( std::count( aLookupIndexList.begin(), aLookupIndexList.end(), nLookupIdx ) ) aLookupOffsetList.push_back( nOffset ); } @@ -1347,9 +1391,6 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT eLookupType = NEXT_UShort( pLookupTable ); const USHORT eLookupFlag = NEXT_UShort( pLookupTable ); const USHORT nCntLookupSubtable = NEXT_UShort( pLookupTable ); -#ifdef DEBUG - fprintf(stderr,"Lookup.ofs=%d type=%d flag=0x%02X, cnt=%d\n", nOfsLookupTable, eLookupType, eLookupFlag, nCntLookupSubtable ); -#endif // TODO: switch( eLookupType ) if( eLookupType != 1 ) // TODO: once we go beyond SingleSubst @@ -1376,9 +1417,6 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) { const USHORT nCntGlyph = NEXT_UShort( pCoverage ); aSubstVector.reserve( nCntGlyph ); -#ifdef DEBUG - fprintf(stderr,"cov1.count = %d\n", nCntGlyph ); -#endif for( USHORT i = 0; i < nCntGlyph; ++i ) { const USHORT nGlyphId = NEXT_UShort( pCoverage ); @@ -1397,9 +1435,6 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nCovIdx = NEXT_UShort( pCoverage ); for( USHORT j = nGlyph0; j <= nGlyph1; ++j ) aSubstVector.push_back( GlyphSubst( j + nCovIdx, 0 ) ); -#ifdef DEBUG - fprintf(stderr,"cov2 0x%04X - 0x%04X\n", nGlyph0, nGlyph1 ); -#endif } } break; @@ -1414,18 +1449,12 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) const USHORT nDeltaGlyphId = NEXT_UShort( pSubLookup ); for(; it != aSubstVector.end(); ++it ) (*it).second = (*it).first + nDeltaGlyphId; -#ifdef DEBUG - fprintf(stderr,"ssub1 delta = 0x%04X\n", nDeltaGlyphId ); -#endif } break; case 2: // Single Substitution Format 2 { const USHORT nCntGlyph = NEXT_UShort( pSubLookup ); -#ifdef DEBUG - fprintf(stderr,"ssub2.count = %d\n", nCntGlyph ); -#endif for( int i = nCntGlyph; (it != aSubstVector.end()) && (--i>=0); ++it ) { const USHORT nGlyphId = NEXT_UShort( pSubLookup ); @@ -1439,15 +1468,9 @@ bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD ) // now apply the glyph substitutions that have been collected in this subtable for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it ) aGlyphSubstitution[ (*it).first ] = (*it).second; -#ifdef DEBUG - fprintf(stderr,"SingleSubst.count=%d, buckets=%d\n", aSubstVector.size(), aGlyphSubstitution.bucket_count() ); -// for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it ) -// fprintf(stderr,"\t0x%04X => 0x%04X\n", (*it).first, (*it).second ); -#endif } } - delete[] pGsubBase; return true; } |