PageRenderTime 103ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/OOO330_m20/vcl/source/glyphs/gcach_ftyp.cxx

https://bitbucket.org/tora/ooo-enum-attribute-packed-experiment-ooo330_m20-vcl
C++ | 2557 lines | 1902 code | 387 blank | 268 comment | 439 complexity | afa160770e84614e0347aee319233ea2 MD5 | raw file
  1. /*************************************************************************
  2. *
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * Copyright 2000, 2010 Oracle and/or its affiliates.
  6. *
  7. * OpenOffice.org - a multi-platform office productivity suite
  8. *
  9. * This file is part of OpenOffice.org.
  10. *
  11. * OpenOffice.org is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU Lesser General Public License version 3
  13. * only, as published by the Free Software Foundation.
  14. *
  15. * OpenOffice.org is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License version 3 for more details
  19. * (a copy is included in the LICENSE file that accompanied this code).
  20. *
  21. * You should have received a copy of the GNU Lesser General Public License
  22. * version 3 along with OpenOffice.org. If not, see
  23. * <http://www.openoffice.org/license.html>
  24. * for a copy of the LGPLv3 License.
  25. *
  26. ************************************************************************/
  27. // MARKER(update_precomp.py): autogen include statement, do not remove
  28. #include "precompiled_vcl.hxx"
  29. #ifdef WNT
  30. #include <svsys.h>
  31. #undef CreateFont
  32. #endif
  33. #include "gcach_ftyp.hxx"
  34. #include "vcl/svapp.hxx"
  35. #include "vcl/outfont.hxx"
  36. #include "vcl/impfont.hxx"
  37. #include "tools/poly.hxx"
  38. #include "basegfx/matrix/b2dhommatrix.hxx"
  39. #include <basegfx/matrix/b2dhommatrixtools.hxx>
  40. #include "basegfx/polygon/b2dpolypolygon.hxx"
  41. #include "osl/file.hxx"
  42. #include "osl/thread.hxx"
  43. #include <ft2build.h>
  44. #include FT_FREETYPE_H
  45. #include FT_GLYPH_H
  46. #include FT_OUTLINE_H
  47. #include FT_TRUETYPE_TABLES_H
  48. #include FT_TRUETYPE_TAGS_H
  49. #include FT_TRUETYPE_IDS_H
  50. #ifndef FT_RENDER_MODE_MONO // happens in the MACOSX build
  51. #define FT_RENDER_MODE_MONO ft_render_mode_mono
  52. #endif
  53. #include "rtl/instance.hxx"
  54. #ifndef FREETYPE_PATCH
  55. // VERSION_MINOR in freetype.h is too coarse
  56. // if patch-level is not available we need to fine-tune the version ourselves
  57. #define FTVERSION 2005
  58. #else
  59. #define FTVERSION (1000*FREETYPE_MAJOR + 100*FREETYPE_MINOR + FREETYPE_PATCH)
  60. #endif
  61. #if FTVERSION >= 2200
  62. typedef const FT_Vector* FT_Vector_CPtr;
  63. #else // FTVERSION < 2200
  64. typedef FT_Vector* FT_Vector_CPtr;
  65. #endif
  66. #include <vector>
  67. // TODO: move file mapping stuff to OSL
  68. #if defined(UNX)
  69. #if !defined(HPUX)
  70. // PORTERS: dlfcn is used for getting symbols from FT versions newer than baseline
  71. #include <dlfcn.h>
  72. #endif
  73. #include <unistd.h>
  74. #include <fcntl.h>
  75. #include <sys/stat.h>
  76. #include <sys/mman.h>
  77. #include "vcl/fontmanager.hxx"
  78. #elif defined(WNT)
  79. #include <io.h>
  80. #define strncasecmp strnicmp
  81. #endif
  82. typedef const unsigned char* CPU8;
  83. inline sal_uInt16 NEXT_U16( CPU8& p ) { p+=2; return (p[-2]<<8)|p[-1]; }
  84. inline sal_Int16 NEXT_S16( CPU8& p ) { return (sal_Int16)NEXT_U16(p); }
  85. inline sal_uInt32 NEXT_U32( CPU8& p ) { p+=4; return (p[-4]<<24)|(p[-3]<<16)|(p[-2]<<8)|p[-1]; }
  86. //inline sal_Int32 NEXT_S32( U8*& p ) { return (sal_Int32)NEXT_U32(p); }
  87. // -----------------------------------------------------------------------
  88. // the gamma table makes artificial bold look better for CJK glyphs
  89. static unsigned char aGammaTable[257];
  90. static void InitGammaTable()
  91. {
  92. static const int M_MAX = 255;
  93. static const int M_X = 128;
  94. static const int M_Y = 208;
  95. int x, a;
  96. for( x = 0; x < 256; x++)
  97. {
  98. if ( x <= M_X )
  99. a = ( x * M_Y + M_X / 2) / M_X;
  100. else
  101. a = M_Y + ( ( x - M_X ) * ( M_MAX - M_Y ) +
  102. ( M_MAX - M_X ) / 2 ) / ( M_MAX - M_X );
  103. aGammaTable[x] = (unsigned char)a;
  104. }
  105. }
  106. // -----------------------------------------------------------------------
  107. static FT_Library aLibFT = 0;
  108. // #110607# enable linking with old FT versions
  109. static int nFTVERSION = 0;
  110. static FT_Error (*pFTNewSize)(FT_Face,FT_Size*);
  111. static FT_Error (*pFTActivateSize)(FT_Size);
  112. static FT_Error (*pFTDoneSize)(FT_Size);
  113. FT_Error (*pFTEmbolden)(FT_GlyphSlot);
  114. FT_Error (*pFTOblique)(FT_GlyphSlot);
  115. static bool bEnableSizeFT = false;
  116. struct EqStr{ bool operator()(const char* a, const char* b) const { return !strcmp(a,b); } };
  117. typedef ::std::hash_map<const char*,FtFontFile*,::std::hash<const char*>, EqStr> FontFileList;
  118. namespace { struct vclFontFileList : public rtl::Static< FontFileList, vclFontFileList > {}; }
  119. // -----------------------------------------------------------------------
  120. // TODO: remove when the priorities are selected by UI
  121. // if (AH==0) => disable autohinting
  122. // if (AA==0) => disable antialiasing
  123. // if (EB==0) => disable embedded bitmaps
  124. // if (AA prio <= AH prio) => antialias + autohint
  125. // if (AH<AA) => do not autohint when antialiasing
  126. // if (EB<AH) => do not autohint for monochrome
  127. static int nDefaultPrioEmbedded = 2;
  128. static int nDefaultPrioAutoHint = 1;
  129. static int nDefaultPrioAntiAlias = 1;
  130. // =======================================================================
  131. // FreetypeManager
  132. // =======================================================================
  133. FtFontFile::FtFontFile( const ::rtl::OString& rNativeFileName )
  134. : maNativeFileName( rNativeFileName ),
  135. mpFileMap( NULL ),
  136. mnFileSize( 0 ),
  137. mnRefCount( 0 ),
  138. mnLangBoost( 0 )
  139. {
  140. // boost font preference if UI language is mentioned in filename
  141. int nPos = maNativeFileName.lastIndexOf( '_' );
  142. if( nPos == -1 || maNativeFileName[nPos+1] == '.' )
  143. mnLangBoost += 0x1000; // no langinfo => good
  144. else
  145. {
  146. static const char* pLangBoost = NULL;
  147. static bool bOnce = true;
  148. if( bOnce )
  149. {
  150. bOnce = false;
  151. LanguageType aLang = Application::GetSettings().GetUILanguage();
  152. switch( aLang )
  153. {
  154. case LANGUAGE_JAPANESE:
  155. pLangBoost = "jan";
  156. break;
  157. case LANGUAGE_CHINESE:
  158. case LANGUAGE_CHINESE_SIMPLIFIED:
  159. case LANGUAGE_CHINESE_SINGAPORE:
  160. pLangBoost = "zhs";
  161. break;
  162. case LANGUAGE_CHINESE_TRADITIONAL:
  163. case LANGUAGE_CHINESE_HONGKONG:
  164. case LANGUAGE_CHINESE_MACAU:
  165. pLangBoost = "zht";
  166. break;
  167. case LANGUAGE_KOREAN:
  168. case LANGUAGE_KOREAN_JOHAB:
  169. pLangBoost = "kor";
  170. break;
  171. }
  172. }
  173. if( pLangBoost && !strncasecmp( pLangBoost, &maNativeFileName.getStr()[nPos+1], 3 ) )
  174. mnLangBoost += 0x2000; // matching langinfo => better
  175. }
  176. }
  177. // -----------------------------------------------------------------------
  178. FtFontFile* FtFontFile::FindFontFile( const ::rtl::OString& rNativeFileName )
  179. {
  180. // font file already known? (e.g. for ttc, synthetic, aliased fonts)
  181. const char* pFileName = rNativeFileName.getStr();
  182. FontFileList &rFontFileList = vclFontFileList::get();
  183. FontFileList::const_iterator it = rFontFileList.find( pFileName );
  184. if( it != rFontFileList.end() )
  185. return (*it).second;
  186. // no => create new one
  187. FtFontFile* pFontFile = new FtFontFile( rNativeFileName );
  188. pFileName = pFontFile->maNativeFileName.getStr();
  189. rFontFileList[ pFileName ] = pFontFile;
  190. return pFontFile;
  191. }
  192. // -----------------------------------------------------------------------
  193. bool FtFontFile::Map()
  194. {
  195. if( mnRefCount++ <= 0 )
  196. {
  197. const char* pFileName = maNativeFileName.getStr();
  198. #if defined(UNX)
  199. int nFile = open( pFileName, O_RDONLY );
  200. if( nFile < 0 )
  201. return false;
  202. struct stat aStat;
  203. fstat( nFile, &aStat );
  204. mnFileSize = aStat.st_size;
  205. mpFileMap = (const unsigned char*)
  206. mmap( NULL, mnFileSize, PROT_READ, MAP_SHARED, nFile, 0 );
  207. if( mpFileMap == MAP_FAILED )
  208. mpFileMap = NULL;
  209. close( nFile );
  210. #elif defined(WNT)
  211. void* pFileDesc = ::CreateFile( pFileName, GENERIC_READ, FILE_SHARE_READ,
  212. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  213. if( pFileDesc == INVALID_HANDLE_VALUE)
  214. return false;
  215. mnFileSize = ::GetFileSize( pFileDesc, NULL );
  216. HANDLE aHandle = ::CreateFileMapping( pFileDesc, NULL, PAGE_READONLY, 0, mnFileSize, "TTF" );
  217. mpFileMap = (const unsigned char*)::MapViewOfFile( aHandle, FILE_MAP_READ, 0, 0, mnFileSize );
  218. ::CloseHandle( pFileDesc );
  219. #else
  220. FILE* pFile = fopen( pFileName, "rb" );
  221. if( !pFile )
  222. return false;
  223. struct stat aStat;
  224. stat( pFileName, &aStat );
  225. mnFileSize = aStat.st_size;
  226. mpFileMap = new unsigned char[ mnFileSize ];
  227. if( mnFileSize != fread( mpFileMap, 1, mnFileSize, pFile ) )
  228. {
  229. delete[] mpFileMap;
  230. mpFileMap = NULL;
  231. }
  232. fclose( pFile );
  233. #endif
  234. }
  235. return (mpFileMap != NULL);
  236. }
  237. // -----------------------------------------------------------------------
  238. void FtFontFile::Unmap()
  239. {
  240. if( (--mnRefCount > 0) || (mpFileMap == NULL) )
  241. return;
  242. #if defined(UNX)
  243. munmap( (char*)mpFileMap, mnFileSize );
  244. #elif defined(WNT)
  245. UnmapViewOfFile( (LPCVOID)mpFileMap );
  246. #else
  247. delete[] mpFileMap;
  248. #endif
  249. mpFileMap = NULL;
  250. }
  251. // =======================================================================
  252. FtFontInfo::FtFontInfo( const ImplDevFontAttributes& rDevFontAttributes,
  253. const ::rtl::OString& rNativeFileName, int nFaceNum, sal_IntPtr nFontId, int nSynthetic,
  254. const ExtraKernInfo* pExtraKernInfo )
  255. :
  256. maFaceFT( NULL ),
  257. mpFontFile( FtFontFile::FindFontFile( rNativeFileName ) ),
  258. mnFaceNum( nFaceNum ),
  259. mnRefCount( 0 ),
  260. mnSynthetic( nSynthetic ),
  261. mnFontId( nFontId ),
  262. maDevFontAttributes( rDevFontAttributes ),
  263. mpChar2Glyph( NULL ),
  264. mpGlyph2Char( NULL ),
  265. mpExtraKernInfo( pExtraKernInfo )
  266. {
  267. // prefer font with low ID
  268. maDevFontAttributes.mnQuality += 10000 - nFontId;
  269. // prefer font with matching file names
  270. maDevFontAttributes.mnQuality += mpFontFile->GetLangBoost();
  271. // prefer font with more external info
  272. if( pExtraKernInfo )
  273. maDevFontAttributes.mnQuality += 100;
  274. }
  275. // -----------------------------------------------------------------------
  276. FtFontInfo::~FtFontInfo()
  277. {
  278. delete mpExtraKernInfo;
  279. delete mpChar2Glyph;
  280. delete mpGlyph2Char;
  281. }
  282. void FtFontInfo::InitHashes() const
  283. {
  284. // TODO: avoid pointers when empty stl::hash_* objects become cheap
  285. mpChar2Glyph = new Int2IntMap();
  286. mpGlyph2Char = new Int2IntMap();
  287. }
  288. // -----------------------------------------------------------------------
  289. FT_FaceRec_* FtFontInfo::GetFaceFT()
  290. {
  291. // get faceFT once/multiple depending on availability of SizeFT APIs
  292. if( (mnRefCount++ <= 0) || !bEnableSizeFT )
  293. {
  294. if( !mpFontFile->Map() )
  295. return NULL;
  296. FT_Error rc = FT_New_Memory_Face( aLibFT,
  297. (FT_Byte*)mpFontFile->GetBuffer(),
  298. mpFontFile->GetFileSize(), mnFaceNum, &maFaceFT );
  299. if( (rc != FT_Err_Ok) || (maFaceFT->num_glyphs <= 0) )
  300. maFaceFT = NULL;
  301. }
  302. return maFaceFT;
  303. }
  304. // -----------------------------------------------------------------------
  305. void FtFontInfo::ReleaseFaceFT( FT_FaceRec_* pFaceFT )
  306. {
  307. // release last/each depending on SizeFT availability
  308. if( (--mnRefCount <= 0) || !bEnableSizeFT )
  309. {
  310. FT_Done_Face( pFaceFT );
  311. maFaceFT = NULL;
  312. mpFontFile->Unmap();
  313. }
  314. }
  315. // -----------------------------------------------------------------------
  316. bool FtFontInfo::HasExtraKerning() const
  317. {
  318. if( !mpExtraKernInfo )
  319. return false;
  320. // TODO: how to enable the line below without getting #i29881# back?
  321. // on the other hand being to optimistic doesn't cause problems
  322. // return mpExtraKernInfo->HasKernPairs();
  323. return true;
  324. }
  325. // -----------------------------------------------------------------------
  326. int FtFontInfo::GetExtraKernPairs( ImplKernPairData** ppKernPairs ) const
  327. {
  328. if( !mpExtraKernInfo )
  329. return 0;
  330. return mpExtraKernInfo->GetUnscaledKernPairs( ppKernPairs );
  331. }
  332. // -----------------------------------------------------------------------
  333. int FtFontInfo::GetExtraGlyphKernValue( int nLeftGlyph, int nRightGlyph ) const
  334. {
  335. if( !mpExtraKernInfo )
  336. return 0;
  337. if( !mpGlyph2Char )
  338. return 0;
  339. sal_Unicode cLeftChar = (*mpGlyph2Char)[ nLeftGlyph ];
  340. sal_Unicode cRightChar = (*mpGlyph2Char)[ nRightGlyph ];
  341. return mpExtraKernInfo->GetUnscaledKernValue( cLeftChar, cRightChar );
  342. }
  343. // -----------------------------------------------------------------------
  344. static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
  345. static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);}
  346. //static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));}
  347. // -----------------------------------------------------------------------
  348. const unsigned char* FtFontInfo::GetTable( const char* pTag, ULONG* pLength ) const
  349. {
  350. const unsigned char* pBuffer = mpFontFile->GetBuffer();
  351. int nFileSize = mpFontFile->GetFileSize();
  352. if( !pBuffer || nFileSize<1024 )
  353. return NULL;
  354. // we currently only handle TTF and TTC headers
  355. unsigned nFormat = GetUInt( pBuffer );
  356. const unsigned char* p = pBuffer + 12;
  357. if( nFormat == 0x74746366 ) // TTC_MAGIC
  358. p += GetUInt( p + 4 * mnFaceNum );
  359. else if( (nFormat!=0x00010000) && (nFormat!=0x74727565) ) // TTF_MAGIC and Apple TTF Magic
  360. return NULL;
  361. // walk table directory until match
  362. int nTables = GetUShort( p - 8 );
  363. if( nTables >= 64 ) // something fishy?
  364. return NULL;
  365. for( int i = 0; i < nTables; ++i, p+=16 )
  366. {
  367. if( p[0]==pTag[0] && p[1]==pTag[1] && p[2]==pTag[2] && p[3]==pTag[3] )
  368. {
  369. ULONG nLength = GetUInt( p + 12 );
  370. if( pLength != NULL )
  371. *pLength = nLength;
  372. const unsigned char* pTable = pBuffer + GetUInt( p + 8 );
  373. if( (pTable + nLength) <= (mpFontFile->GetBuffer() + nFileSize) )
  374. return pTable;
  375. }
  376. }
  377. return NULL;
  378. }
  379. // -----------------------------------------------------------------------
  380. void FtFontInfo::AnnounceFont( ImplDevFontList* pFontList )
  381. {
  382. ImplFTSFontData* pFD = new ImplFTSFontData( this, maDevFontAttributes );
  383. pFontList->Add( pFD );
  384. }
  385. // =======================================================================
  386. FreetypeManager::FreetypeManager()
  387. : mnMaxFontId( 0 ), mnNextFontId( 0x1000 )
  388. {
  389. /*FT_Error rcFT =*/ FT_Init_FreeType( &aLibFT );
  390. #ifdef RTLD_DEFAULT // true if a good dlfcn.h header was included
  391. // Get version of freetype library to enable workarounds.
  392. // Freetype <= 2.0.9 does not have FT_Library_Version().
  393. // Using dl_sym() instead of osl_getSymbol() because latter
  394. // isn't designed to work with oslModule=NULL
  395. void (*pFTLibraryVersion)(FT_Library library,
  396. FT_Int *amajor, FT_Int *aminor, FT_Int *apatch);
  397. pFTLibraryVersion = (void (*)(FT_Library library,
  398. FT_Int *amajor, FT_Int *aminor, FT_Int *apatch))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_Library_Version" );
  399. pFTNewSize = (FT_Error(*)(FT_Face,FT_Size*))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_New_Size" );
  400. pFTActivateSize = (FT_Error(*)(FT_Size))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_Activate_Size" );
  401. pFTDoneSize = (FT_Error(*)(FT_Size))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_Done_Size" );
  402. pFTEmbolden = (FT_Error(*)(FT_GlyphSlot))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_GlyphSlot_Embolden" );
  403. pFTOblique = (FT_Error(*)(FT_GlyphSlot))(sal_IntPtr)dlsym( RTLD_DEFAULT, "FT_GlyphSlot_Oblique" );
  404. bEnableSizeFT = (pFTNewSize!=NULL) && (pFTActivateSize!=NULL) && (pFTDoneSize!=NULL);
  405. FT_Int nMajor = 0, nMinor = 0, nPatch = 0;
  406. if( pFTLibraryVersion )
  407. pFTLibraryVersion( aLibFT, &nMajor, &nMinor, &nPatch );
  408. nFTVERSION = nMajor * 1000 + nMinor * 100 + nPatch;
  409. // disable embedded bitmaps for Freetype-2.1.3 unless explicitly
  410. // requested by env var below because it crashes StarOffice on RH9
  411. // reason: double free in freetype's embedded bitmap handling
  412. if( nFTVERSION == 2103 )
  413. nDefaultPrioEmbedded = 0;
  414. // disable artificial emboldening with the Freetype API for older versions
  415. if( nFTVERSION < 2110 )
  416. pFTEmbolden = NULL;
  417. #else // RTLD_DEFAULT
  418. // assume systems where dlsym is not possible use supplied library
  419. nFTVERSION = FTVERSION;
  420. #endif
  421. // TODO: remove when the priorities are selected by UI
  422. char* pEnv;
  423. pEnv = ::getenv( "SAL_EMBEDDED_BITMAP_PRIORITY" );
  424. if( pEnv )
  425. nDefaultPrioEmbedded = pEnv[0] - '0';
  426. pEnv = ::getenv( "SAL_ANTIALIASED_TEXT_PRIORITY" );
  427. if( pEnv )
  428. nDefaultPrioAntiAlias = pEnv[0] - '0';
  429. pEnv = ::getenv( "SAL_AUTOHINTING_PRIORITY" );
  430. if( pEnv )
  431. nDefaultPrioAutoHint = pEnv[0] - '0';
  432. InitGammaTable();
  433. }
  434. // -----------------------------------------------------------------------
  435. void* FreetypeServerFont::GetFtFace() const
  436. {
  437. if( maSizeFT )
  438. pFTActivateSize( maSizeFT );
  439. return maFaceFT;
  440. }
  441. // -----------------------------------------------------------------------
  442. FreetypeManager::~FreetypeManager()
  443. {
  444. // This crashes on Solaris 10
  445. // TODO: check which versions have this problem
  446. //
  447. // FT_Error rcFT = FT_Done_FreeType( aLibFT );
  448. }
  449. // -----------------------------------------------------------------------
  450. void FreetypeManager::AddFontFile( const rtl::OString& rNormalizedName,
  451. int nFaceNum, sal_IntPtr nFontId, const ImplDevFontAttributes& rDevFontAttr,
  452. const ExtraKernInfo* pExtraKernInfo )
  453. {
  454. if( !rNormalizedName.getLength() )
  455. return;
  456. if( maFontList.find( nFontId ) != maFontList.end() )
  457. return;
  458. FtFontInfo* pFontInfo = new FtFontInfo( rDevFontAttr,
  459. rNormalizedName, nFaceNum, nFontId, 0, pExtraKernInfo );
  460. maFontList[ nFontId ] = pFontInfo;
  461. if( mnMaxFontId < nFontId )
  462. mnMaxFontId = nFontId;
  463. }
  464. // -----------------------------------------------------------------------
  465. long FreetypeManager::AddFontDir( const String& rUrlName )
  466. {
  467. osl::Directory aDir( rUrlName );
  468. osl::FileBase::RC rcOSL = aDir.open();
  469. if( rcOSL != osl::FileBase::E_None )
  470. return 0;
  471. long nCount = 0;
  472. osl::DirectoryItem aDirItem;
  473. rtl_TextEncoding theEncoding = osl_getThreadTextEncoding();
  474. while( (rcOSL = aDir.getNextItem( aDirItem, 20 )) == osl::FileBase::E_None )
  475. {
  476. osl::FileStatus aFileStatus( FileStatusMask_FileURL );
  477. rcOSL = aDirItem.getFileStatus( aFileStatus );
  478. ::rtl::OUString aUSytemPath;
  479. OSL_VERIFY( osl::FileBase::E_None
  480. == osl::FileBase::getSystemPathFromFileURL( aFileStatus.getFileURL(), aUSytemPath ));
  481. ::rtl::OString aCFileName = rtl::OUStringToOString( aUSytemPath, theEncoding );
  482. const char* pszFontFileName = aCFileName.getStr();
  483. FT_FaceRec_* aFaceFT = NULL;
  484. for( int nFaceNum = 0, nMaxFaces = 1; nFaceNum < nMaxFaces; ++nFaceNum )
  485. {
  486. FT_Error rcFT = FT_New_Face( aLibFT, pszFontFileName, nFaceNum, &aFaceFT );
  487. if( (rcFT != FT_Err_Ok) || (aFaceFT == NULL) )
  488. break;
  489. if( !FT_IS_SCALABLE( aFaceFT ) ) // ignore non-scalabale fonts
  490. continue;
  491. nMaxFaces = aFaceFT->num_faces;
  492. ImplDevFontAttributes aDFA;
  493. // TODO: prefer unicode names if available
  494. // TODO: prefer locale specific names if available?
  495. if ( aFaceFT->family_name )
  496. aDFA.maName = String::CreateFromAscii( aFaceFT->family_name );
  497. if ( aFaceFT->style_name )
  498. aDFA.maStyleName = String::CreateFromAscii( aFaceFT->style_name );
  499. aDFA.mbSymbolFlag = false;
  500. for( int i = aFaceFT->num_charmaps; --i >= 0; )
  501. {
  502. const FT_CharMap aCM = aFaceFT->charmaps[i];
  503. #if (FTVERSION < 2000)
  504. if( aCM->encoding == FT_ENCODING_NONE )
  505. #else
  506. if( (aCM->platform_id == TT_PLATFORM_MICROSOFT)
  507. && (aCM->encoding_id == TT_MS_ID_SYMBOL_CS) )
  508. #endif
  509. aDFA.mbSymbolFlag = true;
  510. }
  511. // TODO: extract better font characterization data from font
  512. aDFA.meFamily = FAMILY_DONTKNOW;
  513. aDFA.mePitch = FT_IS_FIXED_WIDTH( aFaceFT ) ? PITCH_FIXED : PITCH_VARIABLE;
  514. aDFA.meWidthType = WIDTH_DONTKNOW;
  515. aDFA.meWeight = FT_STYLE_FLAG_BOLD & aFaceFT->style_flags ? WEIGHT_BOLD : WEIGHT_NORMAL;
  516. aDFA.meItalic = FT_STYLE_FLAG_ITALIC & aFaceFT->style_flags ? ITALIC_NORMAL : ITALIC_NONE;
  517. aDFA.mnQuality = 0;
  518. aDFA.mbOrientation= true;
  519. aDFA.mbDevice = true;
  520. aDFA.mbSubsettable= false;
  521. aDFA.mbEmbeddable = false;
  522. FT_Done_Face( aFaceFT );
  523. AddFontFile( aCFileName, nFaceNum, ++mnNextFontId, aDFA, NULL );
  524. ++nCount;
  525. }
  526. }
  527. aDir.close();
  528. return nCount;
  529. }
  530. // -----------------------------------------------------------------------
  531. void FreetypeManager::AnnounceFonts( ImplDevFontList* pToAdd ) const
  532. {
  533. for( FontList::const_iterator it = maFontList.begin(); it != maFontList.end(); ++it )
  534. {
  535. FtFontInfo* pFtFontInfo = it->second;
  536. pFtFontInfo->AnnounceFont( pToAdd );
  537. }
  538. }
  539. // -----------------------------------------------------------------------
  540. void FreetypeManager::ClearFontList( )
  541. {
  542. for( FontList::iterator it = maFontList.begin(); it != maFontList.end(); ++it )
  543. {
  544. FtFontInfo* pFtFontInfo = it->second;
  545. delete pFtFontInfo;
  546. }
  547. maFontList.clear();
  548. }
  549. // -----------------------------------------------------------------------
  550. FreetypeServerFont* FreetypeManager::CreateFont( const ImplFontSelectData& rFSD )
  551. {
  552. FtFontInfo* pFontInfo = NULL;
  553. // find a FontInfo matching to the font id
  554. sal_IntPtr nFontId = reinterpret_cast<sal_IntPtr>( rFSD.mpFontData );
  555. FontList::iterator it = maFontList.find( nFontId );
  556. if( it != maFontList.end() )
  557. pFontInfo = it->second;
  558. if( !pFontInfo )
  559. return NULL;
  560. FreetypeServerFont* pNew = new FreetypeServerFont( rFSD, pFontInfo );
  561. return pNew;
  562. }
  563. // =======================================================================
  564. ImplFTSFontData::ImplFTSFontData( FtFontInfo* pFI, const ImplDevFontAttributes& rDFA )
  565. : ImplFontData( rDFA, IFTSFONT_MAGIC ),
  566. mpFtFontInfo( pFI )
  567. {
  568. mbDevice = false;
  569. mbOrientation = true;
  570. }
  571. // -----------------------------------------------------------------------
  572. ImplFontEntry* ImplFTSFontData::CreateFontInstance( ImplFontSelectData& rFSD ) const
  573. {
  574. ImplServerFontEntry* pEntry = new ImplServerFontEntry( rFSD );
  575. return pEntry;
  576. }
  577. // =======================================================================
  578. // FreetypeServerFont
  579. // =======================================================================
  580. FreetypeServerFont::FreetypeServerFont( const ImplFontSelectData& rFSD, FtFontInfo* pFI )
  581. : ServerFont( rFSD ),
  582. mnPrioEmbedded(nDefaultPrioEmbedded),
  583. mnPrioAntiAlias(nDefaultPrioAntiAlias),
  584. mnPrioAutoHint(nDefaultPrioAutoHint),
  585. mpFontInfo( pFI ),
  586. maFaceFT( NULL ),
  587. maSizeFT( NULL ),
  588. mbFaceOk( false ),
  589. maRecodeConverter( NULL ),
  590. mpLayoutEngine( NULL )
  591. {
  592. maFaceFT = pFI->GetFaceFT();
  593. #ifdef HDU_DEBUG
  594. fprintf( stderr, "FTSF::FTSF(\"%s\", h=%d, w=%d, sy=%d) => %d\n",
  595. pFI->GetFontFileName()->getStr(), rFSD.mnHeight, rFSD.mnWidth, pFI->IsSymbolFont(), maFaceFT!=0 );
  596. #endif
  597. if( !maFaceFT )
  598. return;
  599. // set the pixel size of the font instance
  600. mnWidth = rFSD.mnWidth;
  601. if( !mnWidth )
  602. mnWidth = rFSD.mnHeight;
  603. mfStretch = (double)mnWidth / rFSD.mnHeight;
  604. // sanity check (e.g. #i66394#, #i66244#, #66537#)
  605. if( (mnWidth < 0) || (mfStretch > +64.0) || (mfStretch < -64.0) )
  606. return;
  607. // perf: use maSizeFT if available
  608. if( bEnableSizeFT )
  609. {
  610. pFTNewSize( maFaceFT, &maSizeFT );
  611. pFTActivateSize( maSizeFT );
  612. }
  613. FT_Error rc = FT_Set_Pixel_Sizes( maFaceFT, mnWidth, rFSD.mnHeight );
  614. if( rc != FT_Err_Ok )
  615. return;
  616. // prepare for font encodings other than unicode or symbol
  617. FT_Encoding eEncoding = FT_ENCODING_UNICODE;
  618. if( mpFontInfo->IsSymbolFont() )
  619. {
  620. #if (FTVERSION < 2000)
  621. eEncoding = FT_ENCODING_NONE;
  622. #else
  623. if( FT_IS_SFNT( maFaceFT ) )
  624. eEncoding = ft_encoding_symbol;
  625. else
  626. eEncoding = FT_ENCODING_ADOBE_CUSTOM; // freetype wants this for PS symbol fonts
  627. #endif
  628. }
  629. rc = FT_Select_Charmap( maFaceFT, eEncoding );
  630. // no standard encoding applies => we need an encoding converter
  631. if( rc != FT_Err_Ok )
  632. {
  633. rtl_TextEncoding eRecodeFrom = RTL_TEXTENCODING_UNICODE;
  634. for( int i = maFaceFT->num_charmaps; --i >= 0; )
  635. {
  636. const FT_CharMap aCM = maFaceFT->charmaps[i];
  637. if( aCM->platform_id == TT_PLATFORM_MICROSOFT )
  638. {
  639. switch( aCM->encoding_id )
  640. {
  641. case TT_MS_ID_SJIS:
  642. eEncoding = FT_ENCODING_SJIS;
  643. eRecodeFrom = RTL_TEXTENCODING_SHIFT_JIS;
  644. break;
  645. case TT_MS_ID_GB2312:
  646. eEncoding = FT_ENCODING_GB2312;
  647. eRecodeFrom = RTL_TEXTENCODING_GB_2312;
  648. break;
  649. case TT_MS_ID_BIG_5:
  650. eEncoding = FT_ENCODING_BIG5;
  651. eRecodeFrom = RTL_TEXTENCODING_BIG5;
  652. break;
  653. case TT_MS_ID_WANSUNG:
  654. eEncoding = FT_ENCODING_WANSUNG;
  655. eRecodeFrom = RTL_TEXTENCODING_MS_949;
  656. break;
  657. case TT_MS_ID_JOHAB:
  658. eEncoding = FT_ENCODING_JOHAB;
  659. eRecodeFrom = RTL_TEXTENCODING_MS_1361;
  660. break;
  661. }
  662. }
  663. else if( aCM->platform_id == TT_PLATFORM_MACINTOSH )
  664. {
  665. switch( aCM->encoding_id )
  666. {
  667. case TT_MAC_ID_ROMAN:
  668. eEncoding = FT_ENCODING_APPLE_ROMAN;
  669. eRecodeFrom = RTL_TEXTENCODING_UNICODE; // TODO: use better match
  670. break;
  671. // TODO: add other encodings when Mac-only
  672. // non-unicode fonts show up
  673. }
  674. }
  675. else if( aCM->platform_id == TT_PLATFORM_ADOBE )
  676. {
  677. switch( aCM->encoding_id )
  678. {
  679. #ifdef TT_ADOBE_ID_LATIN1
  680. case TT_ADOBE_ID_LATIN1: // better unicode than nothing
  681. eEncoding = FT_ENCODING_ADOBE_LATIN_1;
  682. eRecodeFrom = RTL_TEXTENCODING_ISO_8859_1;
  683. break;
  684. #endif // TT_ADOBE_ID_LATIN1
  685. case TT_ADOBE_ID_STANDARD: // better unicode than nothing
  686. eEncoding = FT_ENCODING_ADOBE_STANDARD;
  687. eRecodeFrom = RTL_TEXTENCODING_UNICODE; // TODO: use better match
  688. break;
  689. }
  690. }
  691. }
  692. if( FT_Err_Ok != FT_Select_Charmap( maFaceFT, eEncoding ) )
  693. return;
  694. if( eRecodeFrom != RTL_TEXTENCODING_UNICODE )
  695. maRecodeConverter = rtl_createUnicodeToTextConverter( eRecodeFrom );
  696. }
  697. mbFaceOk = true;
  698. ApplyGSUB( rFSD );
  699. // TODO: query GASP table for load flags
  700. mnLoadFlags = FT_LOAD_DEFAULT;
  701. #if 1 // #i97326# cairo sometimes uses FT_Set_Transform() on our FT_FACE
  702. // we are not using FT_Set_Transform() yet, so just ignore it for now
  703. mnLoadFlags |= FT_LOAD_IGNORE_TRANSFORM;
  704. #endif
  705. mbArtItalic = (rFSD.meItalic != ITALIC_NONE && pFI->GetFontAttributes().GetSlant() == ITALIC_NONE);
  706. mbArtBold = (rFSD.meWeight > WEIGHT_MEDIUM && pFI->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM);
  707. mbUseGamma = false;
  708. if( mbArtBold )
  709. {
  710. //static const int TT_CODEPAGE_RANGE_874 = (1L << 16); // Thai
  711. //static const int TT_CODEPAGE_RANGE_932 = (1L << 17); // JIS/Japan
  712. //static const int TT_CODEPAGE_RANGE_936 = (1L << 18); // Chinese: Simplified
  713. //static const int TT_CODEPAGE_RANGE_949 = (1L << 19); // Korean Wansung
  714. //static const int TT_CODEPAGE_RANGE_950 = (1L << 20); // Chinese: Traditional
  715. //static const int TT_CODEPAGE_RANGE_1361 = (1L << 21); // Korean Johab
  716. static const int TT_CODEPAGE_RANGES1_CJKT = 0x3F0000; // all of the above
  717. const TT_OS2* pOs2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 );
  718. if ((pOs2) && (pOs2->ulCodePageRange1 & TT_CODEPAGE_RANGES1_CJKT )
  719. && rFSD.mnHeight < 20)
  720. mbUseGamma = true;
  721. }
  722. if( ((mnCos != 0) && (mnSin != 0)) || (mnPrioEmbedded <= 0) )
  723. mnLoadFlags |= FT_LOAD_NO_BITMAP;
  724. }
  725. void FreetypeServerFont::SetFontOptions( const ImplFontOptions& rFontOptions)
  726. {
  727. FontAutoHint eHint = rFontOptions.GetUseAutoHint();
  728. if( eHint == AUTOHINT_DONTKNOW )
  729. eHint = mbUseGamma ? AUTOHINT_TRUE : AUTOHINT_FALSE;
  730. if( eHint == AUTOHINT_TRUE )
  731. mnLoadFlags |= FT_LOAD_FORCE_AUTOHINT;
  732. if( (mnSin != 0) && (mnCos != 0) ) // hinting for 0/90/180/270 degrees only
  733. mnLoadFlags |= FT_LOAD_NO_HINTING;
  734. mnLoadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; //#88334#
  735. if( rFontOptions.DontUseAntiAlias() )
  736. mnPrioAntiAlias = 0;
  737. if( rFontOptions.DontUseEmbeddedBitmaps() )
  738. mnPrioEmbedded = 0;
  739. if( rFontOptions.DontUseHinting() )
  740. mnPrioAutoHint = 0;
  741. #if (FTVERSION >= 2005) || defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER)
  742. if( mnPrioAutoHint <= 0 )
  743. #endif
  744. mnLoadFlags |= FT_LOAD_NO_HINTING;
  745. #if defined(FT_LOAD_TARGET_LIGHT) && defined(FT_LOAD_TARGET_NORMAL)
  746. if( !(mnLoadFlags & FT_LOAD_NO_HINTING) && (nFTVERSION >= 2103))
  747. {
  748. mnLoadFlags |= FT_LOAD_TARGET_NORMAL;
  749. switch( rFontOptions.GetHintStyle() )
  750. {
  751. case HINT_NONE:
  752. mnLoadFlags |= FT_LOAD_NO_HINTING;
  753. break;
  754. case HINT_SLIGHT:
  755. mnLoadFlags |= FT_LOAD_TARGET_LIGHT;
  756. break;
  757. case HINT_MEDIUM:
  758. break;
  759. case HINT_FULL:
  760. default:
  761. break;
  762. }
  763. }
  764. #endif
  765. }
  766. // -----------------------------------------------------------------------
  767. bool FreetypeServerFont::TestFont() const
  768. {
  769. return mbFaceOk;
  770. }
  771. // -----------------------------------------------------------------------
  772. FreetypeServerFont::~FreetypeServerFont()
  773. {
  774. if( mpLayoutEngine )
  775. delete mpLayoutEngine;
  776. if( maRecodeConverter )
  777. rtl_destroyUnicodeToTextConverter( maRecodeConverter );
  778. if( maSizeFT )
  779. pFTDoneSize( maSizeFT );
  780. mpFontInfo->ReleaseFaceFT( maFaceFT );
  781. }
  782. // -----------------------------------------------------------------------
  783. int FreetypeServerFont::GetEmUnits() const
  784. {
  785. return maFaceFT->units_per_EM;
  786. }
  787. // -----------------------------------------------------------------------
  788. void FreetypeServerFont::FetchFontMetric( ImplFontMetricData& rTo, long& rFactor ) const
  789. {
  790. static_cast<ImplFontAttributes&>(rTo) = mpFontInfo->GetFontAttributes();
  791. rTo.mbScalableFont = true;
  792. rTo.mbDevice = true;
  793. rTo.mbKernableFont = (FT_HAS_KERNING( maFaceFT ) != 0) || mpFontInfo->HasExtraKerning();
  794. rTo.mnOrientation = GetFontSelData().mnOrientation;
  795. //Always consider [star]symbol as symbol fonts
  796. if (
  797. (rTo.GetFamilyName().EqualsAscii("OpenSymbol")) ||
  798. (rTo.GetFamilyName().EqualsAscii("StarSymbol"))
  799. )
  800. {
  801. rTo.mbSymbolFlag = true;
  802. }
  803. if( maSizeFT )
  804. pFTActivateSize( maSizeFT );
  805. rFactor = 0x100;
  806. rTo.mnWidth = mnWidth;
  807. const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics;
  808. rTo.mnAscent = (+rMetrics.ascender + 32) >> 6;
  809. #if (FTVERSION < 2000)
  810. rTo.mnDescent = (+rMetrics.descender + 32) >> 6;
  811. #else
  812. rTo.mnDescent = (-rMetrics.descender + 32) >> 6;
  813. #endif
  814. rTo.mnIntLeading = ((rMetrics.height + 32) >> 6) - (rTo.mnAscent + rTo.mnDescent);
  815. rTo.mnSlant = 0;
  816. const TT_OS2* pOS2 = (const TT_OS2*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_os2 );
  817. const TT_HoriHeader* pHHEA = (const TT_HoriHeader*)FT_Get_Sfnt_Table( maFaceFT, ft_sfnt_hhea );
  818. if( pOS2 && (pOS2->version != 0xFFFF) )
  819. {
  820. // map the panose info from the OS2 table to their VCL counterparts
  821. switch( pOS2->panose[0] )
  822. {
  823. case 1: rTo.meFamily = FAMILY_ROMAN; break;
  824. case 2: rTo.meFamily = FAMILY_SWISS; break;
  825. case 3: rTo.meFamily = FAMILY_MODERN; break;
  826. case 4: rTo.meFamily = FAMILY_SCRIPT; break;
  827. case 5: rTo.meFamily = FAMILY_DECORATIVE; break;
  828. // TODO: is it reasonable to override the attribute with DONTKNOW?
  829. case 0: // fall through
  830. default: rTo.meFamilyType = FAMILY_DONTKNOW; break;
  831. }
  832. switch( pOS2->panose[3] )
  833. {
  834. case 2: // fall through
  835. case 3: // fall through
  836. case 4: // fall through
  837. case 5: // fall through
  838. case 6: // fall through
  839. case 7: // fall through
  840. case 8: rTo.mePitch = PITCH_VARIABLE; break;
  841. case 9: rTo.mePitch = PITCH_FIXED; break;
  842. // TODO: is it reasonable to override the attribute with DONTKNOW?
  843. case 0: // fall through
  844. case 1: // fall through
  845. default: rTo.mePitch = PITCH_DONTKNOW; break;
  846. }
  847. // #108862# sanity check, some fonts treat descent as signed !!!
  848. int nDescent = pOS2->usWinDescent;
  849. if( nDescent > 5*maFaceFT->units_per_EM )
  850. nDescent = (short)pOS2->usWinDescent; // interpret it as signed!
  851. const double fScale = (double)GetFontSelData().mnHeight / maFaceFT->units_per_EM;
  852. if( pOS2->usWinAscent || pOS2->usWinDescent ) // #i30551#
  853. {
  854. rTo.mnAscent = (long)( +pOS2->usWinAscent * fScale + 0.5 );
  855. rTo.mnDescent = (long)( +nDescent * fScale + 0.5 );
  856. rTo.mnIntLeading = (long)( (+pOS2->usWinAscent + pOS2->usWinDescent - maFaceFT->units_per_EM) * fScale + 0.5 );
  857. }
  858. rTo.mnExtLeading = 0;
  859. if( (pHHEA != NULL) && (pOS2->usWinAscent || pOS2->usWinDescent) )
  860. {
  861. int nExtLeading = pHHEA->Line_Gap;
  862. nExtLeading -= (pOS2->usWinAscent + pOS2->usWinDescent);
  863. nExtLeading += (pHHEA->Ascender - pHHEA->Descender);
  864. if( nExtLeading > 0 )
  865. rTo.mnExtLeading = (long)(nExtLeading * fScale + 0.5);
  866. }
  867. // Check for CJK capabilities of the current font
  868. // #107888# workaround for Asian...
  869. // TODO: remove when ExtLeading fully implemented
  870. BOOL bCJKCapable = ((pOS2->ulUnicodeRange2 & 0x2DF00000) != 0);
  871. if ( bCJKCapable && (pOS2->usWinAscent || pOS2->usWinDescent) )
  872. {
  873. rTo.mnIntLeading += rTo.mnExtLeading;
  874. // #109280# The line height for Asian fonts is too small.
  875. // Therefore we add half of the external leading to the
  876. // ascent, the other half is added to the descent.
  877. const long nHalfTmpExtLeading = rTo.mnExtLeading / 2;
  878. const long nOtherHalfTmpExtLeading = rTo.mnExtLeading -
  879. nHalfTmpExtLeading;
  880. // #110641# external leading for Asian fonts.
  881. // The factor 0.3 has been verified during experiments.
  882. const long nCJKExtLeading = (long)(0.30 * (rTo.mnAscent + rTo.mnDescent));
  883. if ( nCJKExtLeading > rTo.mnExtLeading )
  884. rTo.mnExtLeading = nCJKExtLeading - rTo.mnExtLeading;
  885. else
  886. rTo.mnExtLeading = 0;
  887. rTo.mnAscent += nHalfTmpExtLeading;
  888. rTo.mnDescent += nOtherHalfTmpExtLeading;
  889. }
  890. }
  891. // initialize kashida width
  892. // TODO: what if there are different versions of this glyph available
  893. rTo.mnMinKashida = rTo.mnAscent / 4; // a reasonable default
  894. const int nKashidaGlyphId = GetRawGlyphIndex( 0x0640 );
  895. if( nKashidaGlyphId )
  896. {
  897. GlyphData aGlyphData;
  898. InitGlyphData( nKashidaGlyphId, aGlyphData );
  899. rTo.mnMinKashida = aGlyphData.GetMetric().GetCharWidth();
  900. }
  901. }
  902. // -----------------------------------------------------------------------
  903. static inline void SplitGlyphFlags( const FreetypeServerFont& rFont, int& nGlyphIndex, int& nGlyphFlags )
  904. {
  905. nGlyphFlags = nGlyphIndex & GF_FLAGMASK;
  906. nGlyphIndex &= GF_IDXMASK;
  907. if( nGlyphIndex & GF_ISCHAR )
  908. nGlyphIndex = rFont.GetRawGlyphIndex( nGlyphIndex );
  909. }
  910. // -----------------------------------------------------------------------
  911. int FreetypeServerFont::ApplyGlyphTransform( int nGlyphFlags,
  912. FT_Glyph pGlyphFT, bool bForBitmapProcessing ) const
  913. {
  914. int nAngle = GetFontSelData().mnOrientation;
  915. // shortcut most common case
  916. if( !nAngle && !nGlyphFlags )
  917. return nAngle;
  918. const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics;
  919. FT_Vector aVector;
  920. FT_Matrix aMatrix;
  921. bool bStretched = false;
  922. switch( nGlyphFlags & GF_ROTMASK )
  923. {
  924. default: // straight
  925. aVector.x = 0;
  926. aVector.y = 0;
  927. aMatrix.xx = +mnCos;
  928. aMatrix.yy = +mnCos;
  929. aMatrix.xy = -mnSin;
  930. aMatrix.yx = +mnSin;
  931. break;
  932. case GF_ROTL: // left
  933. nAngle += 900;
  934. bStretched = (mfStretch != 1.0);
  935. aVector.x = (FT_Pos)(+rMetrics.descender * mfStretch);
  936. aVector.y = -rMetrics.ascender;
  937. aMatrix.xx = (FT_Pos)(-mnSin / mfStretch);
  938. aMatrix.yy = (FT_Pos)(-mnSin * mfStretch);
  939. aMatrix.xy = (FT_Pos)(-mnCos * mfStretch);
  940. aMatrix.yx = (FT_Pos)(+mnCos / mfStretch);
  941. break;
  942. case GF_ROTR: // right
  943. nAngle -= 900;
  944. bStretched = (mfStretch != 1.0);
  945. aVector.x = -maFaceFT->glyph->metrics.horiAdvance;
  946. aVector.x += (FT_Pos)(rMetrics.descender * mnSin/65536.0);
  947. aVector.y = (FT_Pos)(-rMetrics.descender * mfStretch * mnCos/65536.0);
  948. aMatrix.xx = (FT_Pos)(+mnSin / mfStretch);
  949. aMatrix.yy = (FT_Pos)(+mnSin * mfStretch);
  950. aMatrix.xy = (FT_Pos)(+mnCos * mfStretch);
  951. aMatrix.yx = (FT_Pos)(-mnCos / mfStretch);
  952. break;
  953. }
  954. while( nAngle < 0 )
  955. nAngle += 3600;
  956. if( pGlyphFT->format != FT_GLYPH_FORMAT_BITMAP )
  957. {
  958. FT_Glyph_Transform( pGlyphFT, NULL, &aVector );
  959. // orthogonal transforms are better handled by bitmap operations
  960. if( bStretched || (bForBitmapProcessing && (nAngle % 900) != 0) )
  961. {
  962. // workaround for compatibility with older FT versions
  963. if( nFTVERSION < 2102 )
  964. {
  965. FT_Fixed t = aMatrix.xy;
  966. aMatrix.xy = aMatrix.yx;
  967. aMatrix.yx = t;
  968. }
  969. // apply non-orthogonal or stretch transformations
  970. FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
  971. nAngle = 0;
  972. }
  973. }
  974. else
  975. {
  976. // FT<=2005 ignores transforms for bitmaps, so do it manually
  977. FT_BitmapGlyph pBmpGlyphFT = reinterpret_cast<FT_BitmapGlyph>(pGlyphFT);
  978. pBmpGlyphFT->left += (aVector.x + 32) >> 6;
  979. pBmpGlyphFT->top += (aVector.y + 32) >> 6;
  980. }
  981. return nAngle;
  982. }
  983. // -----------------------------------------------------------------------
  984. int FreetypeServerFont::GetRawGlyphIndex( sal_UCS4 aChar ) const
  985. {
  986. if( mpFontInfo->IsSymbolFont() )
  987. {
  988. if( !FT_IS_SFNT( maFaceFT ) )
  989. {
  990. if( (aChar & 0xFF00) == 0xF000 )
  991. aChar &= 0xFF; // PS font symbol mapping
  992. else if( aChar > 0xFF )
  993. return 0;
  994. }
  995. }
  996. // if needed recode from unicode to font encoding
  997. if( maRecodeConverter )
  998. {
  999. sal_Char aTempArray[8];
  1000. sal_Size nTempSize;
  1001. sal_uInt32 nCvtInfo;
  1002. // assume that modern UCS4 fonts have unicode CMAPs
  1003. // => no encoding remapping to unicode is needed
  1004. if( aChar > 0xFFFF )
  1005. return 0;
  1006. sal_Unicode aUCS2Char = static_cast<sal_Unicode>(aChar);
  1007. rtl_UnicodeToTextContext aContext = rtl_createUnicodeToTextContext( maRecodeConverter );
  1008. int nChars = rtl_convertUnicodeToText( maRecodeConverter, aContext,
  1009. &aUCS2Char, 1, aTempArray, sizeof(aTempArray),
  1010. RTL_UNICODETOTEXT_FLAGS_UNDEFINED_QUESTIONMARK
  1011. | RTL_UNICODETOTEXT_FLAGS_INVALID_QUESTIONMARK,
  1012. &nCvtInfo, &nTempSize );
  1013. rtl_destroyUnicodeToTextContext( maRecodeConverter, aContext );
  1014. aChar = 0;
  1015. for( int i = 0; i < nChars; ++i )
  1016. aChar = aChar*256 + (aTempArray[i] & 0xFF);
  1017. }
  1018. // cache glyph indexes in font info to share between different sizes
  1019. int nGlyphIndex = mpFontInfo->GetGlyphIndex( aChar );
  1020. if( nGlyphIndex < 0 )
  1021. {
  1022. nGlyphIndex = FT_Get_Char_Index( maFaceFT, aChar );
  1023. if( !nGlyphIndex)
  1024. {
  1025. // check if symbol aliasing helps
  1026. if( (aChar <= 0x00FF) && mpFontInfo->IsSymbolFont() )
  1027. nGlyphIndex = FT_Get_Char_Index( maFaceFT, aChar | 0xF000 );
  1028. #if 0 // disabled for now because it introduced ae bad side-effect (#i88376#)
  1029. // Finally try the postscript name table
  1030. if (!nGlyphIndex)
  1031. nGlyphIndex = psp::PrintFontManager::get().FreeTypeCharIndex( maFaceFT, aChar );
  1032. #endif
  1033. }
  1034. mpFontInfo->CacheGlyphIndex( aChar, nGlyphIndex );
  1035. }
  1036. return nGlyphIndex;
  1037. }
  1038. // -----------------------------------------------------------------------
  1039. int FreetypeServerFont::FixupGlyphIndex( int nGlyphIndex, sal_UCS4 aChar ) const
  1040. {
  1041. int nGlyphFlags = GF_NONE;
  1042. // do glyph substitution if necessary
  1043. // CJK vertical writing needs special treatment
  1044. if( GetFontSelData().mbVertical )
  1045. {
  1046. // TODO: rethink when GSUB is used for non-vertical case
  1047. GlyphSubstitution::const_iterator it = maGlyphSubstitution.find( nGlyphIndex );
  1048. if( it == maGlyphSubstitution.end() )
  1049. {
  1050. int nTemp = GetVerticalChar( aChar );
  1051. if( nTemp ) // is substitution possible
  1052. nTemp = GetRawGlyphIndex( nTemp );
  1053. if( nTemp ) // substitute manually if sensible
  1054. nGlyphIndex = nTemp | (GF_GSUB | GF_ROTL);
  1055. else
  1056. nGlyphFlags |= GetVerticalFlags( aChar );
  1057. }
  1058. else
  1059. {
  1060. // for vertical GSUB also compensate for nOrientation=2700
  1061. nGlyphIndex = (*it).second;
  1062. nGlyphFlags |= GF_GSUB | GF_ROTL;
  1063. }
  1064. }
  1065. #if 0
  1066. // #95556# autohinting not yet optimized for non-western glyph styles
  1067. if( !(mnLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_FORCE_AUTOHINT) )
  1068. && ( (aChar >= 0x0600 && aChar < 0x1E00) // south-east asian + arabic
  1069. ||(aChar >= 0x2900 && aChar < 0xD800) // CJKV
  1070. ||(aChar >= 0xF800) ) ) // presentation + symbols
  1071. {
  1072. nGlyphFlags |= GF_UNHINTED;
  1073. }
  1074. #endif
  1075. if( nGlyphIndex != 0 )
  1076. nGlyphIndex |= nGlyphFlags;
  1077. return nGlyphIndex;
  1078. }
  1079. // -----------------------------------------------------------------------
  1080. int FreetypeServerFont::GetGlyphIndex( sal_UCS4 aChar ) const
  1081. {
  1082. int nGlyphIndex = GetRawGlyphIndex( aChar );
  1083. nGlyphIndex = FixupGlyphIndex( nGlyphIndex, aChar );
  1084. return nGlyphIndex;
  1085. }
  1086. // -----------------------------------------------------------------------
  1087. static int lcl_GetCharWidth( FT_FaceRec_* pFaceFT, double fStretch, int nGlyphFlags )
  1088. {
  1089. int nCharWidth = pFaceFT->glyph->metrics.horiAdvance;
  1090. if( nGlyphFlags & GF_ROTMASK ) // for bVertical rotated glyphs
  1091. {
  1092. const FT_Size_Metrics& rMetrics = pFaceFT->size->metrics;
  1093. #if (FTVERSION < 2000)
  1094. nCharWidth = (int)((rMetrics.height - rMetrics.descender) * fStretch);
  1095. #else
  1096. nCharWidth = (int)((rMetrics.height + rMetrics.descender) * fStretch);
  1097. #endif
  1098. }
  1099. return (nCharWidth + 32) >> 6;
  1100. }
  1101. // -----------------------------------------------------------------------
  1102. void FreetypeServerFont::InitGlyphData( int nGlyphIndex, GlyphData& rGD ) const
  1103. {
  1104. if( maSizeFT )
  1105. pFTActivateSize( maSizeFT );
  1106. int nGlyphFlags;
  1107. SplitGlyphFlags( *this, nGlyphIndex, nGlyphFlags );
  1108. int nLoadFlags = mnLoadFlags;
  1109. // if( mbArtItalic )
  1110. // nLoadFlags |= FT_LOAD_NO_BITMAP;
  1111. FT_Error rc = -1;
  1112. #if (FTVERSION <= 2008)
  1113. // #88364# freetype<=2005 prefers autohinting to embedded bitmaps
  1114. // => first we have to try without hinting
  1115. if( (nLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) == 0 )
  1116. {
  1117. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags|FT_LOAD_NO_HINTING );
  1118. if( (rc==FT_Err_Ok) && (maFaceFT->glyph->format!=FT_GLYPH_FORMAT_BITMAP) )
  1119. rc = -1; // mark as "loading embedded bitmap" was unsuccessful
  1120. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1121. }
  1122. if( rc != FT_Err_Ok )
  1123. #endif
  1124. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags );
  1125. if( rc != FT_Err_Ok )
  1126. {
  1127. // we get here e.g. when a PS font lacks the default glyph
  1128. rGD.SetCharWidth( 0 );
  1129. rGD.SetDelta( 0, 0 );
  1130. rGD.SetOffset( 0, 0 );
  1131. rGD.SetSize( Size( 0, 0 ) );
  1132. return;
  1133. }
  1134. const bool bOriginallyZeroWidth = (maFaceFT->glyph->metrics.horiAdvance == 0);
  1135. if( mbArtBold && pFTEmbolden )
  1136. (*pFTEmbolden)( maFaceFT->glyph );
  1137. const int nCharWidth = bOriginallyZeroWidth ? 0 : lcl_GetCharWidth( maFaceFT, mfStretch, nGlyphFlags );
  1138. rGD.SetCharWidth( nCharWidth );
  1139. FT_Glyph pGlyphFT;
  1140. rc = FT_Get_Glyph( maFaceFT->glyph, &pGlyphFT );
  1141. ApplyGlyphTransform( nGlyphFlags, pGlyphFT, false );
  1142. if( mbArtBold && pFTEmbolden && (nFTVERSION < 2200) ) // #i71094# workaround staircase bug
  1143. pGlyphFT->advance.y = 0;
  1144. rGD.SetDelta( (pGlyphFT->advance.x + 0x8000) >> 16, -((pGlyphFT->advance.y + 0x8000) >> 16) );
  1145. FT_BBox aBbox;
  1146. FT_Glyph_Get_CBox( pGlyphFT, FT_GLYPH_BBOX_PIXELS, &aBbox );
  1147. if( aBbox.yMin > aBbox.yMax ) // circumvent freetype bug
  1148. {
  1149. int t=aBbox.yMin; aBbox.yMin=aBbox.yMax, aBbox.yMax=t;
  1150. }
  1151. rGD.SetOffset( aBbox.xMin, -aBbox.yMax );
  1152. rGD.SetSize( Size( (aBbox.xMax-aBbox.xMin+1), (aBbox.yMax-aBbox.yMin) ) );
  1153. FT_Done_Glyph( pGlyphFT );
  1154. }
  1155. // -----------------------------------------------------------------------
  1156. bool FreetypeServerFont::GetAntialiasAdvice( void ) const
  1157. {
  1158. if( GetFontSelData().mbNonAntialiased || (mnPrioAntiAlias<=0) )
  1159. return false;
  1160. bool bAdviseAA = true;
  1161. // TODO: also use GASP info
  1162. return bAdviseAA;
  1163. }
  1164. // -----------------------------------------------------------------------
  1165. bool FreetypeServerFont::GetGlyphBitmap1( int nGlyphIndex, RawBitmap& rRawBitmap ) const
  1166. {
  1167. if( maSizeFT )
  1168. pFTActivateSize( maSizeFT );
  1169. int nGlyphFlags;
  1170. SplitGlyphFlags( *this, nGlyphIndex, nGlyphFlags );
  1171. FT_Int nLoadFlags = mnLoadFlags;
  1172. // #i70930# force mono-hinting for monochrome text
  1173. if( nFTVERSION >= 2110 ) //#i71947# unless it looks worse
  1174. {
  1175. nLoadFlags &= ~0xF0000;
  1176. nLoadFlags |= FT_LOAD_TARGET_MONO;
  1177. }
  1178. if( mbArtItalic )
  1179. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1180. #if (FTVERSION >= 2002)
  1181. // for 0/90/180/270 degree fonts enable hinting even if not advisable
  1182. // non-hinted and non-antialiased bitmaps just look too ugly
  1183. if( (mnCos==0 || mnSin==0) && (mnPrioAutoHint > 0) )
  1184. nLoadFlags &= ~FT_LOAD_NO_HINTING;
  1185. #endif
  1186. if( mnPrioEmbedded <= mnPrioAutoHint )
  1187. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1188. FT_Error rc = -1;
  1189. #if (FTVERSION <= 2008)
  1190. // #88364# freetype<=2005 prefers autohinting to embedded bitmaps
  1191. // => first we have to try without hinting
  1192. if( (nLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) == 0 )
  1193. {
  1194. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags|FT_LOAD_NO_HINTING );
  1195. if( (rc==FT_Err_Ok) && (maFaceFT->glyph->format != FT_GLYPH_FORMAT_BITMAP) )
  1196. rc = -1; // mark as "loading embedded bitmap" was unsuccessful
  1197. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1198. }
  1199. if( rc != FT_Err_Ok )
  1200. #endif
  1201. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags );
  1202. if( rc != FT_Err_Ok )
  1203. return false;
  1204. if( mbArtBold && pFTEmbolden )
  1205. (*pFTEmbolden)( maFaceFT->glyph );
  1206. FT_Glyph pGlyphFT;
  1207. rc = FT_Get_Glyph( maFaceFT->glyph, &pGlyphFT );
  1208. if( rc != FT_Err_Ok )
  1209. return false;
  1210. int nAngle = ApplyGlyphTransform( nGlyphFlags, pGlyphFT, true );
  1211. if( mbArtItalic )
  1212. {
  1213. FT_Matrix aMatrix;
  1214. aMatrix.xx = aMatrix.yy = 0x10000L;
  1215. if( nFTVERSION >= 2102 ) // Freetype 2.1.2 API swapped xy with yx
  1216. aMatrix.xy = 0x6000L, aMatrix.yx = 0;
  1217. else
  1218. aMatrix.yx = 0x6000L, aMatrix.xy = 0;
  1219. FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
  1220. }
  1221. // Check for zero area bounding boxes as this crashes some versions of FT.
  1222. // This also provides a handy short cut as much of the code following
  1223. // becomes an expensive nop when a glyph covers no pixels.
  1224. FT_BBox cbox;
  1225. FT_Glyph_Get_CBox(pGlyphFT, ft_glyph_bbox_unscaled, &cbox);
  1226. if( (cbox.xMax - cbox.xMin) == 0 || (cbox.yMax - cbox.yMin == 0) )
  1227. {
  1228. nAngle = 0;
  1229. memset(&rRawBitmap, 0, sizeof rRawBitmap);
  1230. FT_Done_Glyph( pGlyphFT );
  1231. return true;
  1232. }
  1233. if( pGlyphFT->format != FT_GLYPH_FORMAT_BITMAP )
  1234. {
  1235. if( pGlyphFT->format == FT_GLYPH_FORMAT_OUTLINE )
  1236. ((FT_OutlineGlyphRec*)pGlyphFT)->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
  1237. // #i15743# freetype API 2.1.3 changed the FT_RENDER_MODE_MONO constant
  1238. FT_Render_Mode nRenderMode = (FT_Render_Mode)((nFTVERSION<2103) ? 1 : FT_RENDER_MODE_MONO);
  1239. rc = FT_Glyph_To_Bitmap( &pGlyphFT, nRenderMode, NULL, TRUE );
  1240. if( rc != FT_Err_Ok )
  1241. {
  1242. FT_Done_Glyph( pGlyphFT );
  1243. return false;
  1244. }
  1245. }
  1246. const FT_BitmapGlyph pBmpGlyphFT = reinterpret_cast<const FT_BitmapGlyph>(pGlyphFT);
  1247. // NOTE: autohinting in FT<=2.0.2 miscalculates the offsets below by +-1
  1248. rRawBitmap.mnXOffset = +pBmpGlyphFT->left;
  1249. rRawBitmap.mnYOffset = -pBmpGlyphFT->top;
  1250. const FT_Bitmap& rBitmapFT = pBmpGlyphFT->bitmap;
  1251. rRawBitmap.mnHeight = rBitmapFT.rows;
  1252. rRawBitmap.mnBitCount = 1;
  1253. if( mbArtBold && !pFTEmbolden )
  1254. {
  1255. rRawBitmap.mnWidth = rBitmapFT.width + 1;
  1256. int nLineBytes = (rRawBitmap.mnWidth + 7) >> 3;
  1257. rRawBitmap.mnScanlineSize = (nLineBytes > rBitmapFT.pitch) ? nLineBytes : rBitmapFT.pitch;
  1258. }
  1259. else
  1260. {
  1261. rRawBitmap.mnWidth = rBitmapFT.width;
  1262. rRawBitmap.mnScanlineSize = rBitmapFT.pitch;
  1263. }
  1264. const ULONG nNeededSize = rRawBitmap.mnScanlineSize * rRawBitmap.mnHeight;
  1265. if( rRawBitmap.mnAllocated < nNeededSize )
  1266. {
  1267. delete[] rRawBitmap.mpBits;
  1268. rRawBitmap.mnAllocated = 2*nNeededSize;
  1269. rRawBitmap.mpBits = new unsigned char[ rRawBitmap.mnAllocated ];
  1270. }
  1271. if( !mbArtBold || pFTEmbolden )
  1272. {
  1273. memcpy( rRawBitmap.mpBits, rBitmapFT.buffer, nNeededSize );
  1274. }
  1275. else
  1276. {
  1277. memset( rRawBitmap.mpBits, 0, nNeededSize );
  1278. const unsigned char* pSrcLine = rBitmapFT.buffer;
  1279. unsigned char* pDstLine = rRawBitmap.mpBits;
  1280. for( int h = rRawBitmap.mnHeight; --h >= 0; )
  1281. {
  1282. memcpy( pDstLine, pSrcLine, rBitmapFT.pitch );
  1283. pDstLine += rRawBitmap.mnScanlineSize;
  1284. pSrcLine += rBitmapFT.pitch;
  1285. }
  1286. unsigned char* p = rRawBitmap.mpBits;
  1287. for( ULONG y=0; y < rRawBitmap.mnHeight; y++ )
  1288. {
  1289. unsigned char nLastByte = 0;
  1290. for( ULONG x=0; x < rRawBitmap.mnScanlineSize; x++ )
  1291. {
  1292. unsigned char nTmp = p[x] << 7;
  1293. p[x] |= (p[x] >> 1) | nLastByte;
  1294. nLastByte = nTmp;
  1295. }
  1296. p += rRawBitmap.mnScanlineSize;
  1297. }
  1298. }
  1299. FT_Done_Glyph( pGlyphFT );
  1300. // special case for 0/90/180/270 degree orientation
  1301. switch( nAngle )
  1302. {
  1303. case -900:
  1304. case +900:
  1305. case +1800:
  1306. case +2700:
  1307. rRawBitmap.Rotate( nAngle );
  1308. break;
  1309. }
  1310. return true;
  1311. }
  1312. // -----------------------------------------------------------------------
  1313. bool FreetypeServerFont::GetGlyphBitmap8( int nGlyphIndex, RawBitmap& rRawBitmap ) const
  1314. {
  1315. if( maSizeFT )
  1316. pFTActivateSize( maSizeFT );
  1317. int nGlyphFlags;
  1318. SplitGlyphFlags( *this, nGlyphIndex, nGlyphFlags );
  1319. FT_Int nLoadFlags = mnLoadFlags;
  1320. if( mbArtItalic )
  1321. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1322. #if (FTVERSION <= 2004) && !defined(TT_CONFIG_OPTION_BYTECODE_INTERPRETER)
  1323. // autohinting in FT<=2.0.4 makes antialiased glyphs look worse
  1324. nLoadFlags |= FT_LOAD_NO_HINTING;
  1325. #else
  1326. if( (nGlyphFlags & GF_UNHINTED) || (mnPrioAutoHint < mnPrioAntiAlias) )
  1327. nLoadFlags |= FT_LOAD_NO_HINTING;
  1328. #endif
  1329. if( mnPrioEmbedded <= mnPrioAntiAlias )
  1330. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1331. FT_Error rc = -1;
  1332. #if (FTVERSION <= 2008)
  1333. // #88364# freetype<=2005 prefers autohinting to embedded bitmaps
  1334. // => first we have to try without hinting
  1335. if( (nLoadFlags & (FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) == 0 )
  1336. {
  1337. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags|FT_LOAD_NO_HINTING );
  1338. if( (rc==FT_Err_Ok) && (maFaceFT->glyph->format != FT_GLYPH_FORMAT_BITMAP) )
  1339. rc = -1; // mark as "loading embedded bitmap" was unsuccessful
  1340. nLoadFlags |= FT_LOAD_NO_BITMAP;
  1341. }
  1342. if( rc != FT_Err_Ok )
  1343. #endif
  1344. rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags );
  1345. if( rc != FT_Err_Ok )
  1346. return false;
  1347. if( mbArtBold && pFTEmbolden )
  1348. (*pFTEmbolden)( maFaceFT->glyph );
  1349. FT_Glyph pGlyphFT;
  1350. rc = FT_Get_Glyph( maFaceFT->glyph, &pGlyphFT );
  1351. if( rc != FT_Err_Ok )
  1352. return false;
  1353. int nAngle = ApplyGlyphTransform( nGlyphFlags, pGlyphFT, true );
  1354. if( mbArtItalic )
  1355. {
  1356. FT_Matrix aMatrix;
  1357. aMatrix.xx = aMatrix.yy = 0x10000L;
  1358. if( nFTVERSION >= 2102 ) // Freetype 2.1.2 API swapped xy with yx
  1359. aMatrix.xy = 0x6000L, aMatrix.yx = 0;
  1360. else
  1361. aMatrix.yx = 0x6000L, aMatrix.xy = 0;
  1362. FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
  1363. }
  1364. if( pGlyphFT->format == FT_GLYPH_FORMAT_OUTLINE )
  1365. ((FT_OutlineGlyph)pGlyphFT)->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
  1366. bool bEmbedded = (pGlyphFT->format == FT_GLYPH_FORMAT_BITMAP);
  1367. if( !bEmbedded )
  1368. {
  1369. rc = FT_Glyph_To_Bitmap( &pGlyphFT, FT_RENDER_MODE_NORMAL, NULL, TRUE );
  1370. if( rc != FT_Err_Ok )
  1371. {
  1372. FT_Done_Glyph( pGlyphFT );
  1373. return false;
  1374. }
  1375. }
  1376. const FT_BitmapGlyph pBmpGlyphFT = reinterpret_cast<const FT_BitmapGlyph>(pGlyphFT);
  1377. rRawBitmap.mnXOffset = +pBmpGlyphFT->left;
  1378. rRawBitmap.mnYOffset = -pBmpGlyphFT->top;
  1379. const FT_Bitmap& rBitmapFT = pBmpGlyphFT->bitmap;
  1380. rRawBitmap.mnHeight = rBitmapFT.rows;
  1381. rRawBitmap.mnWidth = rBitmapFT.width;
  1382. rRawBitmap.mnBitCount = 8;
  1383. rRawBitmap.mnScanlineSize = bEmbedded ? rBitmapFT.width : rBitmapFT.pitch;
  1384. if( mbArtBold && !pFTEmbolden )
  1385. {
  1386. ++rRawBitmap.mnWidth;
  1387. ++rRawBitmap.mnScanlineSize;
  1388. }
  1389. rRawBitmap.mnScanlineSize = (rRawBitmap.mnScanlineSize + 3) & -4;
  1390. const ULONG nNeededSize = rRawBitmap.mnScanlineSize * rRawBitmap.mnHeight;
  1391. if( rRawBitmap.mnAllocated < nNeededSize )
  1392. {
  1393. delete[] rRawBitmap.mpBits;
  1394. rRawBitmap.mnAllocated = 2*nNeededSize;
  1395. rRawBitmap.mpBits = new unsigned char[ rRawBitmap.mnAllocated ];
  1396. }
  1397. const unsigned char* pSrc = rBitmapFT.buffer;
  1398. unsigned char* pDest = rRawBitmap.mpBits;
  1399. if( !bEmbedded )
  1400. {
  1401. for( int y = rRawBitmap.mnHeight, x; --y >= 0 ; )
  1402. {
  1403. for( x = 0; x < rBitmapFT.width; ++x )
  1404. *(pDest++) = *(pSrc++);
  1405. for(; x < int(rRawBitmap.mnScanlineSize); ++x )
  1406. *(pDest++) = 0;
  1407. }
  1408. }
  1409. else
  1410. {
  1411. for( int y = rRawBitmap.mnHeight, x; --y >= 0 ; )
  1412. {
  1413. unsigned char nSrc = 0;
  1414. for( x = 0; x < rBitmapFT.width; ++x, nSrc+=nSrc )
  1415. {
  1416. if( (x & 7) == 0 )
  1417. nSrc = *(pSrc++);
  1418. *(pDest++) = (0x7F - nSrc) >> 8;
  1419. }
  1420. for(; x < int(rRawBitmap.mnScanlineSize); ++x )
  1421. *(pDest++) = 0;
  1422. }
  1423. }
  1424. if( mbArtBold && !pFTEmbolden )
  1425. {
  1426. // overlay with glyph image shifted by one left pixel
  1427. unsigned char* p = rRawBitmap.mpBits;
  1428. for( ULONG y=0; y < rRawBitmap.mnHeight; y++ )
  1429. {
  1430. unsigned char nLastByte = 0;
  1431. for( ULONG x=0; x < rRawBitmap.mnWidth; x++ )
  1432. {
  1433. unsigned char nTmp = p[x];
  1434. p[x] |= p[x] | nLastByte;
  1435. nLastByte = nTmp;
  1436. }
  1437. p += rRawBitmap.mnScanlineSize;
  1438. }
  1439. }
  1440. if( !bEmbedded && mbUseGamma )
  1441. {
  1442. unsigned char* p = rRawBitmap.mpBits;
  1443. for( ULONG y=0; y < rRawBitmap.mnHeight; y++ )
  1444. {
  1445. for( ULONG x=0; x < rRawBitmap.mnWidth; x++ )
  1446. {
  1447. p[x] = aGammaTable[ p[x] ];
  1448. }
  1449. p += rRawBitmap.mnScanlineSize;
  1450. }
  1451. }
  1452. FT_Done_Glyph( pGlyphFT );
  1453. // special case for 0/90/180/270 degree orientation
  1454. switch( nAngle )
  1455. {
  1456. case -900:
  1457. case +900:
  1458. case +1800:
  1459. case +2700:
  1460. rRawBitmap.Rotate( nAngle );
  1461. break;
  1462. }
  1463. return true;
  1464. }
  1465. // -----------------------------------------------------------------------
  1466. // determine unicode ranges in font
  1467. // -----------------------------------------------------------------------
  1468. // TODO: replace with GetFontCharMap()
  1469. bool FreetypeServerFont::GetFontCodeRanges( CmapResult& rResult ) const
  1470. {
  1471. rResult.mbSymbolic = mpFontInfo->IsSymbolFont();
  1472. // TODO: is the full CmapResult needed on platforms calling this?
  1473. if( FT_IS_SFNT( maFaceFT ) )
  1474. {
  1475. ULONG nLength = 0;
  1476. const unsigned char* pCmap = mpFontInfo->GetTable( "cmap", &nLength );
  1477. if( pCmap && (nLength > 0) )
  1478. if( ParseCMAP( pCmap, nLength, rResult ) )
  1479. return true;
  1480. }
  1481. typedef std::vector<sal_uInt32> U32Vector;
  1482. U32Vector aCodes;
  1483. // FT's coverage is available since FT>=2.1.0 (OOo-baseline>=2.1.4 => ok)
  1484. aCodes.reserve( 0x1000 );
  1485. FT_UInt nGlyphIndex;
  1486. for( sal_uInt32 cCode = FT_Get_First_Char( maFaceFT, &nGlyphIndex );; )
  1487. {
  1488. if( !nGlyphIndex )
  1489. break;
  1490. aCodes.push_back( cCode ); // first code inside range
  1491. sal_uInt32 cNext = cCode;
  1492. do cNext = FT_Get_Next_Char( maFaceFT, cCode, &nGlyphIndex ); while( cNext == ++cCode );
  1493. aCodes.push_back( cCode ); // first code outside range
  1494. cCode = cNext;
  1495. }
  1496. const int nCount = aCodes.size();
  1497. if( !nCount) {
  1498. if( !rResult.mbSymbolic )
  1499. return false;
  1500. // we usually get here for Type1 symbol fonts
  1501. aCodes.push_back( 0xF020 );
  1502. aCodes.push_back( 0xF100 );
  1503. }
  1504. sal_uInt32* pCodes = new sal_uInt32[ nCount ];
  1505. for( int i = 0; i < nCount; ++i )
  1506. pCodes[i] = aCodes[i];
  1507. rResult.mpRangeCodes = pCodes;
  1508. rResult.mnRangeCount = nCount / 2;
  1509. return true;
  1510. }
  1511. // -----------------------------------------------------------------------
  1512. // kerning stuff
  1513. // -----------------------------------------------------------------------
  1514. int FreetypeServerFont::GetGlyphKernValue( int nGlyphLeft, int nGlyphRight ) const
  1515. {
  1516. // if no kerning info is available from Freetype
  1517. // then we may have to use extra info provided by e.g. psprint
  1518. if( !FT_HAS_KERNING( maFaceFT ) || !FT_IS_SFNT( maFaceFT ) )
  1519. {
  1520. int nKernVal = mpFontInfo->GetExtraGlyphKernValue( nGlyphLeft, nGlyphRight );
  1521. if( !nKernVal )
  1522. return 0;
  1523. // scale the kern value to match the font size
  1524. const ImplFontSelectData& rFSD = GetFontSelData();
  1525. nKernVal *= rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight;
  1526. return (nKernVal + 500) / 1000;
  1527. }
  1528. // when font faces of different sizes share the same maFaceFT
  1529. // then we have to make sure that it uses the correct maSizeFT
  1530. if( maSizeFT )
  1531. pFTActivateSize( maSizeFT );
  1532. // use Freetype's kerning info
  1533. FT_Vector aKernVal;
  1534. FT_Error rcFT = FT_Get_Kerning( maFaceFT, nGlyphLeft, nGlyphRight,
  1535. FT_KERNING_DEFAULT, &aKernVal );
  1536. int nResult = (rcFT == FT_Err_Ok) ? (aKernVal.x + 32) >> 6 : 0;
  1537. return nResult;
  1538. }
  1539. // -----------------------------------------------------------------------
  1540. ULONG FreetypeServerFont::GetKernPairs( ImplKernPairData** ppKernPairs ) const
  1541. {
  1542. // if no kerning info is available in the font file
  1543. *ppKernPairs = NULL;
  1544. if( !FT_HAS_KERNING( maFaceFT ) || !FT_IS_SFNT( maFaceFT ) )
  1545. {
  1546. // then we have may have extra kerning info from e.g. psprint
  1547. int nCount = mpFontInfo->GetExtraKernPairs( ppKernPairs );
  1548. // scale the kern values to match the font size
  1549. const ImplFontSelectData& rFSD = GetFontSelData();
  1550. int nFontWidth = rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight;
  1551. ImplKernPairData* pKernPair = *ppKernPairs;
  1552. for( int i = nCount; --i >= 0; ++pKernPair )
  1553. {
  1554. long& rVal = pKernPair->mnKern;
  1555. rVal = ((rVal * nFontWidth) + 500) / 1000;
  1556. }
  1557. return nCount;
  1558. }
  1559. // when font faces of different sizes share the same maFaceFT
  1560. // then we have to make sure that it uses the correct maSizeFT
  1561. if( maSizeFT )
  1562. pFTActivateSize( maSizeFT );
  1563. // first figure out which glyph pairs are involved in kerning
  1564. ULONG nKernLength = 0;
  1565. const FT_Byte* const pKern = mpFontInfo->GetTable( "kern", &nKernLength );
  1566. if( !pKern )
  1567. return 0;
  1568. // combine TTF/OTF tables from the font file to build a vector of
  1569. // unicode kerning pairs using Freetype's glyph kerning calculation
  1570. // for the kerning value
  1571. // TODO: is it worth to share the glyph->unicode mapping between
  1572. // different instances of the same font face?
  1573. typedef std::vector<ImplKernPairData> KernVector;
  1574. KernVector aKernGlyphVector;
  1575. ImplKernPairData aKernPair;
  1576. aKernPair.mnKern = 0; // To prevent "is used uninitialized" warning...
  1577. const FT_Byte* pBuffer = pKern;
  1578. ULONG nVersion = GetUShort( pBuffer+0 );
  1579. USHORT nTableCnt = GetUShort( pBuffer+2 );
  1580. // Microsoft/Old TrueType style kern table
  1581. if ( nVersion == 0 )
  1582. {
  1583. pBuffer += 4;
  1584. for( USHORT nTableIdx = 0; nTableIdx < nTableCnt; ++nTableIdx )
  1585. {
  1586. // USHORT nSubVersion = GetUShort( pBuffer+0 );
  1587. // USHORT nSubLength = GetUShort( pBuffer+2 );
  1588. USHORT nSubCoverage = GetUShort( pBuffer+4 );
  1589. pBuffer += 6;
  1590. if( (nSubCoverage&0x03) != 0x01 ) // no interest in minimum info here
  1591. continue;
  1592. switch( nSubCoverage >> 8 )
  1593. {
  1594. case 0: // version 0, kerning format 0
  1595. {
  1596. USHORT nPairs = GetUShort( pBuffer );
  1597. pBuffer += 8; // skip search hints
  1598. aKernGlyphVector.reserve( aKernGlyphVector.size() + nPairs );
  1599. for( int i = 0; i < nPairs; ++i )
  1600. {
  1601. aKernPair.mnChar1 = GetUShort( pBuffer+0 );
  1602. aKernPair.mnChar2 = GetUShort( pBuffer+2 );
  1603. //long nUnscaledKern= GetSShort( pBuffer );
  1604. pBuffer += 6;
  1605. aKernGlyphVector.push_back( aKernPair );
  1606. }
  1607. }
  1608. break;
  1609. case 2: // version 0, kerning format 2
  1610. {
  1611. const FT_Byte* pSubTable = pBuffer;
  1612. //USHORT nRowWidth = GetUShort( pBuffer+0 );
  1613. USHORT nOfsLeft = GetUShort( pBuffer+2 );
  1614. USHORT nOfsRight = GetUShort( pBuffer+4 );
  1615. USHORT nOfsArray = GetUShort( pBuffer+6 );
  1616. pBuffer += 8;
  1617. const FT_Byte* pTmp = pSubTable + nOfsLeft;
  1618. USHORT nFirstLeft = GetUShort( pTmp+0 );
  1619. USHORT nLastLeft = GetUShort( pTmp+2 ) + nFirstLeft - 1;
  1620. pTmp = pSubTable + nOfsRight;
  1621. USHORT nFirstRight = GetUShort( pTmp+0 );
  1622. USHORT nLastRight = GetUShort( pTmp+2 ) + nFirstRight - 1;
  1623. ULONG nPairs = (ULONG)(nLastLeft - nFirstLeft + 1) * (nLastRight - nFirstRight + 1);
  1624. aKernGlyphVector.reserve( aKernGlyphVector.size() + nPairs );
  1625. pTmp = pSubTable + nOfsArray;
  1626. for( int nLeft = nFirstLeft; nLeft < nLastLeft; ++nLeft )
  1627. {
  1628. aKernPair.mnChar1 = nLeft;
  1629. for( int nRight = 0; nRight < nLastRight; ++nRight )
  1630. {
  1631. if( GetUShort( pTmp ) != 0 )
  1632. {
  1633. aKernPair.mnChar2 = nRight;
  1634. aKernGlyphVector.push_back( aKernPair );
  1635. }
  1636. pTmp += 2;
  1637. }
  1638. }
  1639. }
  1640. break;
  1641. }
  1642. }
  1643. }
  1644. // Apple New style kern table
  1645. pBuffer = pKern;
  1646. nVersion = NEXT_U32( pBuffer );
  1647. nTableCnt = NEXT_U32( pBuffer );
  1648. if ( nVersion == 0x00010000 )
  1649. {
  1650. for( USHORT nTableIdx = 0; nTableIdx < nTableCnt; ++nTableIdx )
  1651. {
  1652. /*ULONG nLength =*/ NEXT_U32( pBuffer );
  1653. USHORT nCoverage = NEXT_U16( pBuffer );
  1654. /*USHORT nTupleIndex =*/ NEXT_U16( pBuffer );
  1655. // Kerning sub-table format, 0 through 3
  1656. sal_uInt8 nSubTableFormat = nCoverage & 0x00FF;
  1657. switch( nSubTableFormat )
  1658. {
  1659. case 0: // version 0, kerning format 0
  1660. {
  1661. USHORT nPairs = NEXT_U16( pBuffer );
  1662. pBuffer += 6; // skip search hints
  1663. aKernGlyphVector.reserve( aKernGlyphVector.size() + nPairs );
  1664. for( int i = 0; i < nPairs; ++i )
  1665. {
  1666. aKernPair.mnChar1 = NEXT_U16( pBuffer );
  1667. aKernPair.mnChar2 = NEXT_U16( pBuffer );
  1668. /*long nUnscaledKern=*/ NEXT_S16( pBuffer );
  1669. aKernGlyphVector.push_back( aKernPair );
  1670. }
  1671. }
  1672. break;
  1673. case 2: // version 0, kerning format 2
  1674. {
  1675. const FT_Byte* pSubTable = pBuffer;
  1676. /*USHORT nRowWidth =*/ NEXT_U16( pBuffer );
  1677. USHORT nOfsLeft = NEXT_U16( pBuffer );
  1678. USHORT nOfsRight = NEXT_U16( pBuffer );
  1679. USHORT nOfsArray = NEXT_U16( pBuffer );
  1680. const FT_Byte* pTmp = pSubTable + nOfsLeft;
  1681. USHORT nFirstLeft = NEXT_U16( pTmp );
  1682. USHORT nLastLeft = NEXT_U16( pTmp ) + nFirstLeft - 1;
  1683. pTmp = pSubTable + nOfsRight;
  1684. USHORT nFirstRight = NEXT_U16( pTmp );
  1685. USHORT nLastRight = NEXT_U16( pTmp ) + nFirstRight - 1;
  1686. ULONG nPairs = (ULONG)(nLastLeft - nFirstLeft + 1) * (nLastRight - nFirstRight + 1);
  1687. aKernGlyphVector.reserve( aKernGlyphVector.size() + nPairs );
  1688. pTmp = pSubTable + nOfsArray;
  1689. for( int nLeft = nFirstLeft; nLeft < nLastLeft; ++nLeft )
  1690. {
  1691. aKernPair.mnChar1 = nLeft;
  1692. for( int nRight = 0; nRight < nLastRight; ++nRight )
  1693. {
  1694. if( NEXT_S16( pTmp ) != 0 )
  1695. {
  1696. aKernPair.mnChar2 = nRight;
  1697. aKernGlyphVector.push_back( aKernPair );
  1698. }
  1699. }
  1700. }
  1701. }
  1702. break;
  1703. default:
  1704. fprintf( stderr, "gcach_ftyp.cxx: Found unsupported Apple-style kern subtable type %d.\n", nSubTableFormat );
  1705. break;
  1706. }
  1707. }
  1708. }
  1709. // now create VCL's ImplKernPairData[] format for all glyph pairs
  1710. ULONG nKernCount = aKernGlyphVector.size();
  1711. if( nKernCount )
  1712. {
  1713. // prepare glyphindex to character mapping
  1714. // TODO: this is needed to support VCL's existing kerning infrastructure,
  1715. // eliminate it up by redesigning kerning infrastructure to work with glyph indizes
  1716. typedef std::hash_multimap<USHORT,sal_Unicode> Cmap;
  1717. Cmap aCmap;
  1718. for( sal_Unicode aChar = 0x0020; aChar < 0xFFFE; ++aChar )
  1719. {
  1720. USHORT nGlyphIndex = GetGlyphIndex( aChar );
  1721. if( nGlyphIndex )
  1722. aCmap.insert( Cmap::value_type( nGlyphIndex, aChar ) );
  1723. }
  1724. // translate both glyph indizes in kerning pairs to characters
  1725. // problem is that these are 1:n mappings...
  1726. KernVector aKernCharVector;
  1727. aKernCharVector.reserve( nKernCount );
  1728. KernVector::iterator it;
  1729. for( it = aKernGlyphVector.begin(); it != aKernGlyphVector.end(); ++it )
  1730. {
  1731. FT_Vector aKernVal;
  1732. FT_Error rcFT = FT_Get_Kerning( maFaceFT, it->mnChar1, it->mnChar2,
  1733. FT_KERNING_DEFAULT, &aKernVal );
  1734. aKernPair.mnKern = aKernVal.x >> 6;
  1735. if( (aKernPair.mnKern == 0) || (rcFT != FT_Err_Ok) )
  1736. continue;
  1737. typedef std::pair<Cmap::iterator,Cmap::iterator> CPair;
  1738. const CPair p1 = aCmap.equal_range( it->mnChar1 );
  1739. const CPair p2 = aCmap.equal_range( it->mnChar2 );
  1740. for( Cmap::const_iterator i1 = p1.first; i1 != p1.second; ++i1 )
  1741. {
  1742. aKernPair.mnChar1 = (*i1).second;
  1743. for( Cmap::const_iterator i2 = p2.first; i2 != p2.second; ++i2 )
  1744. {
  1745. aKernPair.mnChar2 = (*i2).second;
  1746. aKernCharVector.push_back( aKernPair );
  1747. }
  1748. }
  1749. }
  1750. // now move the resulting vector into VCL's ImplKernPairData[] format
  1751. nKernCount = aKernCharVector.size();
  1752. ImplKernPairData* pTo = new ImplKernPairData[ nKernCount ];
  1753. *ppKernPairs = pTo;
  1754. for( it = aKernCharVector.begin(); it != aKernCharVector.end(); ++it, ++pTo )
  1755. {
  1756. pTo->mnChar1 = it->mnChar1;
  1757. pTo->mnChar2 = it->mnChar2;
  1758. pTo->mnKern = it->mnKern;
  1759. }
  1760. }
  1761. return nKernCount;
  1762. }
  1763. // -----------------------------------------------------------------------
  1764. // outline stuff
  1765. // -----------------------------------------------------------------------
  1766. class PolyArgs
  1767. {
  1768. public:
  1769. PolyArgs( PolyPolygon& rPolyPoly, USHORT nMaxPoints );
  1770. ~PolyArgs();
  1771. void AddPoint( long nX, long nY, PolyFlags);
  1772. void ClosePolygon();
  1773. long GetPosX() const { return maPosition.x;}
  1774. long GetPosY() const { return maPosition.y;}
  1775. private:
  1776. PolyPolygon& mrPolyPoly;
  1777. Point* mpPointAry;
  1778. BYTE* mpFlagAry;
  1779. FT_Vector maPosition;
  1780. USHORT mnMaxPoints;
  1781. USHORT mnPoints;
  1782. USHORT mnPoly;
  1783. long mnHeight;
  1784. bool bHasOffline;
  1785. };
  1786. // -----------------------------------------------------------------------
  1787. PolyArgs::PolyArgs( PolyPolygon& rPolyPoly, USHORT nMaxPoints )
  1788. : mrPolyPoly(rPolyPoly),
  1789. mnMaxPoints(nMaxPoints),
  1790. mnPoints(0),
  1791. mnPoly(0),
  1792. bHasOffline(false)
  1793. {
  1794. mpPointAry = new Point[ mnMaxPoints ];
  1795. mpFlagAry = new BYTE [ mnMaxPoints ];
  1796. }
  1797. // -----------------------------------------------------------------------
  1798. PolyArgs::~PolyArgs()
  1799. {
  1800. delete[] mpFlagAry;
  1801. delete[] mpPointAry;
  1802. }
  1803. // -----------------------------------------------------------------------
  1804. void PolyArgs::AddPoint( long nX, long nY, PolyFlags aFlag )
  1805. {
  1806. DBG_ASSERT( (mnPoints < mnMaxPoints), "FTGlyphOutline: AddPoint overflow!" );
  1807. if( mnPoints >= mnMaxPoints )
  1808. return;
  1809. maPosition.x = nX;
  1810. maPosition.y = nY;
  1811. mpPointAry[ mnPoints ] = Point( nX, nY );
  1812. mpFlagAry[ mnPoints++ ]= aFlag;
  1813. bHasOffline |= (aFlag != POLY_NORMAL);
  1814. }
  1815. // -----------------------------------------------------------------------
  1816. void PolyArgs::ClosePolygon()
  1817. {
  1818. if( !mnPoly++ )
  1819. return;
  1820. // freetype seems to always close the polygon with an ON_CURVE point
  1821. // PolyPoly wants to close the polygon itself => remove last point
  1822. DBG_ASSERT( (mnPoints >= 2), "FTGlyphOutline: PolyFinishNum failed!" );
  1823. --mnPoints;
  1824. DBG_ASSERT( (mpPointAry[0]==mpPointAry[mnPoints]), "FTGlyphOutline: PolyFinishEq failed!" );
  1825. DBG_ASSERT( (mpFlagAry[0]==POLY_NORMAL), "FTGlyphOutline: PolyFinishFE failed!" );
  1826. DBG_ASSERT( (mpFlagAry[mnPoints]==POLY_NORMAL), "FTGlyphOutline: PolyFinishFS failed!" );
  1827. Polygon aPoly( mnPoints, mpPointAry, (bHasOffline ? mpFlagAry : NULL) );
  1828. // #i35928#
  1829. // This may be a invalid polygons, e.g. the last point is a control point.
  1830. // So close the polygon (and add the first point again) if the last point
  1831. // is a control point or different from first.
  1832. // #i48298#
  1833. // Now really duplicating the first point, to close or correct the
  1834. // polygon. Also no longer duplicating the flags, but enforcing
  1835. // POLY_NORMAL for the newly added last point.
  1836. const sal_uInt16 nPolySize(aPoly.GetSize());
  1837. if(nPolySize)
  1838. {
  1839. if((aPoly.HasFlags() && POLY_CONTROL == aPoly.GetFlags(nPolySize - 1))
  1840. || (aPoly.GetPoint(nPolySize - 1) != aPoly.GetPoint(0)))
  1841. {
  1842. aPoly.SetSize(nPolySize + 1);
  1843. aPoly.SetPoint(aPoly.GetPoint(0), nPolySize);
  1844. if(aPoly.HasFlags())
  1845. {
  1846. aPoly.SetFlags(nPolySize, POLY_NORMAL);
  1847. }
  1848. }
  1849. }
  1850. mrPolyPoly.Insert( aPoly );
  1851. mnPoints = 0;
  1852. bHasOffline = false;
  1853. }
  1854. // -----------------------------------------------------------------------
  1855. extern "C" {
  1856. // TODO: wait till all compilers accept that calling conventions
  1857. // for functions are the same independent of implementation constness,
  1858. // then uncomment the const-tokens in the function interfaces below
  1859. static int FT_move_to( FT_Vector_CPtr p0, void* vpPolyArgs )
  1860. {
  1861. PolyArgs& rA = *reinterpret_cast<PolyArgs*>(vpPolyArgs);
  1862. // move_to implies a new polygon => finish old polygon first
  1863. rA.ClosePolygon();
  1864. rA.AddPoint( p0->x, p0->y, POLY_NORMAL );
  1865. return 0;
  1866. }
  1867. static int FT_line_to( FT_Vector_CPtr p1, void* vpPolyArgs )
  1868. {
  1869. PolyArgs& rA = *reinterpret_cast<PolyArgs*>(vpPolyArgs);
  1870. rA.AddPoint( p1->x, p1->y, POLY_NORMAL );
  1871. return 0;
  1872. }
  1873. static int FT_conic_to( FT_Vector_CPtr p1, FT_Vector_CPtr p2, void* vpPolyArgs )
  1874. {
  1875. PolyArgs& rA = *reinterpret_cast<PolyArgs*>(vpPolyArgs);
  1876. // VCL's Polygon only knows cubic beziers
  1877. const long nX1 = (2 * rA.GetPosX() + 4 * p1->x + 3) / 6;
  1878. const long nY1 = (2 * rA.GetPosY() + 4 * p1->y + 3) / 6;
  1879. rA.AddPoint( nX1, nY1, POLY_CONTROL );
  1880. const long nX2 = (2 * p2->x + 4 * p1->x + 3) / 6;
  1881. const long nY2 = (2 * p2->y + 4 * p1->y + 3) / 6;
  1882. rA.AddPoint( nX2, nY2, POLY_CONTROL );
  1883. rA.AddPoint( p2->x, p2->y, POLY_NORMAL );
  1884. return 0;
  1885. }
  1886. static int FT_cubic_to( FT_Vector_CPtr p1, FT_Vector_CPtr p2, FT_Vector_CPtr p3, void* vpPolyArgs )
  1887. {
  1888. PolyArgs& rA = *reinterpret_cast<PolyArgs*>(vpPolyArgs);
  1889. rA.AddPoint( p1->x, p1->y, POLY_CONTROL );
  1890. rA.AddPoint( p2->x, p2->y, POLY_CONTROL );
  1891. rA.AddPoint( p3->x, p3->y, POLY_NORMAL );
  1892. return 0;
  1893. }
  1894. } // extern "C"
  1895. // -----------------------------------------------------------------------
  1896. bool FreetypeServerFont::GetGlyphOutline( int nGlyphIndex,
  1897. ::basegfx::B2DPolyPolygon& rB2DPolyPoly ) const
  1898. {
  1899. if( maSizeFT )
  1900. pFTActivateSize( maSizeFT );
  1901. rB2DPolyPoly.clear();
  1902. int nGlyphFlags;
  1903. SplitGlyphFlags( *this, nGlyphIndex, nGlyphFlags );
  1904. FT_Int nLoadFlags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_TRANSFORM;
  1905. #ifdef FT_LOAD_TARGET_LIGHT
  1906. // enable "light hinting" if available
  1907. if( nFTVERSION >= 2103 )
  1908. nLoadFlags |= FT_LOAD_TARGET_LIGHT;
  1909. #endif
  1910. FT_Error rc = FT_Load_Glyph( maFaceFT, nGlyphIndex, nLoadFlags );
  1911. if( rc != FT_Err_Ok )
  1912. return false;
  1913. if( mbArtBold && pFTEmbolden )
  1914. (*pFTEmbolden)( maFaceFT->glyph );
  1915. FT_Glyph pGlyphFT;
  1916. rc = FT_Get_Glyph( maFaceFT->glyph, &pGlyphFT );
  1917. if( rc != FT_Err_Ok )
  1918. return false;
  1919. if( pGlyphFT->format != FT_GLYPH_FORMAT_OUTLINE )
  1920. return false;
  1921. if( mbArtItalic )
  1922. {
  1923. FT_Matrix aMatrix;
  1924. aMatrix.xx = aMatrix.yy = 0x10000L;
  1925. if( nFTVERSION >= 2102 ) // Freetype 2.1.2 API swapped xy with yx
  1926. aMatrix.xy = 0x6000L, aMatrix.yx = 0;
  1927. else
  1928. aMatrix.yx = 0x6000L, aMatrix.xy = 0;
  1929. FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
  1930. }
  1931. FT_Outline& rOutline = reinterpret_cast<FT_OutlineGlyphRec*>(pGlyphFT)->outline;
  1932. if( !rOutline.n_points ) // blank glyphs are ok
  1933. return true;
  1934. long nMaxPoints = 1 + rOutline.n_points * 3;
  1935. PolyPolygon aToolPolyPolygon;
  1936. PolyArgs aPolyArg( aToolPolyPolygon, nMaxPoints );
  1937. /*int nAngle =*/ ApplyGlyphTransform( nGlyphFlags, pGlyphFT, false );
  1938. FT_Outline_Funcs aFuncs;
  1939. aFuncs.move_to = &FT_move_to;
  1940. aFuncs.line_to = &FT_line_to;
  1941. aFuncs.conic_to = &FT_conic_to;
  1942. aFuncs.cubic_to = &FT_cubic_to;
  1943. aFuncs.shift = 0;
  1944. aFuncs.delta = 0;
  1945. rc = FT_Outline_Decompose( &rOutline, &aFuncs, (void*)&aPolyArg );
  1946. aPolyArg.ClosePolygon(); // close last polygon
  1947. FT_Done_Glyph( pGlyphFT );
  1948. // convert to basegfx polypolygon
  1949. // TODO: get rid of the intermediate tools polypolygon
  1950. rB2DPolyPoly = aToolPolyPolygon.getB2DPolyPolygon();
  1951. rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix( +1.0/(1<<6), -1.0/(1<<6) ));
  1952. return true;
  1953. }
  1954. // -----------------------------------------------------------------------
  1955. bool FreetypeServerFont::ApplyGSUB( const ImplFontSelectData& rFSD )
  1956. {
  1957. #define MKTAG(s) ((((((s[0]<<8)+s[1])<<8)+s[2])<<8)+s[3])
  1958. typedef std::vector<ULONG> ReqFeatureTagList;
  1959. ReqFeatureTagList aReqFeatureTagList;
  1960. if( rFSD.mbVertical )
  1961. aReqFeatureTagList.push_back( MKTAG("vert") );
  1962. ULONG nRequestedScript = 0; //MKTAG("hani");//### TODO: where to get script?
  1963. ULONG nRequestedLangsys = 0; //MKTAG("ZHT"); //### TODO: where to get langsys?
  1964. // TODO: request more features depending on script and language system
  1965. if( aReqFeatureTagList.size() == 0) // nothing to do
  1966. return true;
  1967. // load GSUB table into memory
  1968. ULONG nLength = 0;
  1969. const FT_Byte* const pGsubBase = mpFontInfo->GetTable( "GSUB", &nLength );
  1970. if( !pGsubBase )
  1971. return false;
  1972. // parse GSUB header
  1973. const FT_Byte* pGsubHeader = pGsubBase;
  1974. const USHORT nOfsScriptList = GetUShort( pGsubHeader+4 );
  1975. const USHORT nOfsFeatureTable = GetUShort( pGsubHeader+6 );
  1976. const USHORT nOfsLookupList = GetUShort( pGsubHeader+8 );
  1977. pGsubHeader += 10;
  1978. typedef std::vector<USHORT> UshortList;
  1979. UshortList aFeatureIndexList;
  1980. UshortList aFeatureOffsetList;
  1981. // parse Script Table
  1982. const FT_Byte* pScriptHeader = pGsubBase + nOfsScriptList;
  1983. const USHORT nCntScript = GetUShort( pScriptHeader+0 );
  1984. pScriptHeader += 2;
  1985. for( USHORT nScriptIndex = 0; nScriptIndex < nCntScript; ++nScriptIndex )
  1986. {
  1987. const ULONG nScriptTag = GetUInt( pScriptHeader+0 ); // e.g. hani/arab/kana/hang
  1988. const USHORT nOfsScriptTable= GetUShort( pScriptHeader+4 );
  1989. pScriptHeader += 6; //###
  1990. if( (nScriptTag != nRequestedScript) && (nRequestedScript != 0) )
  1991. continue;
  1992. const FT_Byte* pScriptTable = pGsubBase + nOfsScriptList + nOfsScriptTable;
  1993. const USHORT nDefaultLangsysOfs = GetUShort( pScriptTable+0 );
  1994. const USHORT nCntLangSystem = GetUShort( pScriptTable+2 );
  1995. pScriptTable += 4;
  1996. USHORT nLangsysOffset = 0;
  1997. for( USHORT nLangsysIndex = 0; nLangsysIndex < nCntLangSystem; ++nLangsysIndex )
  1998. {
  1999. const ULONG nTag = GetUInt( pScriptTable+0 ); // e.g. KOR/ZHS/ZHT/JAN
  2000. const USHORT nOffset= GetUShort( pScriptTable+4 );
  2001. pScriptTable += 6;
  2002. if( (nTag != nRequestedLangsys) && (nRequestedLangsys != 0) )
  2003. continue;
  2004. nLangsysOffset = nOffset;
  2005. break;
  2006. }
  2007. if( (nDefaultLangsysOfs != 0) && (nDefaultLangsysOfs != nLangsysOffset) )
  2008. {
  2009. const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nDefaultLangsysOfs;
  2010. const USHORT nReqFeatureIdx = GetUShort( pLangSys+2 );
  2011. const USHORT nCntFeature = GetUShort( pLangSys+4 );
  2012. pLangSys += 6;
  2013. aFeatureIndexList.push_back( nReqFeatureIdx );
  2014. for( USHORT i = 0; i < nCntFeature; ++i )
  2015. {
  2016. const USHORT nFeatureIndex = GetUShort( pLangSys );
  2017. pLangSys += 2;
  2018. aFeatureIndexList.push_back( nFeatureIndex );
  2019. }
  2020. }
  2021. if( nLangsysOffset != 0 )
  2022. {
  2023. const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nLangsysOffset;
  2024. const USHORT nReqFeatureIdx = GetUShort( pLangSys+2 );
  2025. const USHORT nCntFeature = GetUShort( pLangSys+4 );
  2026. pLangSys += 6;
  2027. aFeatureIndexList.push_back( nReqFeatureIdx );
  2028. for( USHORT i = 0; i < nCntFeature; ++i )
  2029. {
  2030. const USHORT nFeatureIndex = GetUShort( pLangSys );
  2031. pLangSys += 2;
  2032. aFeatureIndexList.push_back( nFeatureIndex );
  2033. }
  2034. }
  2035. }
  2036. if( !aFeatureIndexList.size() )
  2037. return true;
  2038. UshortList aLookupIndexList;
  2039. UshortList aLookupOffsetList;
  2040. // parse Feature Table
  2041. const FT_Byte* pFeatureHeader = pGsubBase + nOfsFeatureTable;
  2042. const USHORT nCntFeature = GetUShort( pFeatureHeader );
  2043. pFeatureHeader += 2;
  2044. for( USHORT nFeatureIndex = 0; nFeatureIndex < nCntFeature; ++nFeatureIndex )
  2045. {
  2046. const ULONG nTag = GetUInt( pFeatureHeader+0 ); // e.g. locl/vert/trad/smpl/liga/fina/...
  2047. const USHORT nOffset= GetUShort( pFeatureHeader+4 );
  2048. pFeatureHeader += 6;
  2049. // short circuit some feature lookups
  2050. if( aFeatureIndexList[0] != nFeatureIndex ) // required feature?
  2051. {
  2052. const int nRequested = std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex);
  2053. if( !nRequested ) // ignore features that are not requested
  2054. continue;
  2055. const int nAvailable = std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag);
  2056. if( !nAvailable ) // some fonts don't provide features they request!
  2057. continue;
  2058. }
  2059. const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset;
  2060. const USHORT nCntLookups = GetUShort( pFeatureTable+0 );
  2061. pFeatureTable += 2;
  2062. for( USHORT i = 0; i < nCntLookups; ++i )
  2063. {
  2064. const USHORT nLookupIndex = GetUShort( pFeatureTable );
  2065. pFeatureTable += 2;
  2066. aLookupIndexList.push_back( nLookupIndex );
  2067. }
  2068. if( nCntLookups == 0 ) //### hack needed by Mincho/Gothic/Mingliu/Simsun/...
  2069. aLookupIndexList.push_back( 0 );
  2070. }
  2071. // parse Lookup List
  2072. const FT_Byte* pLookupHeader = pGsubBase + nOfsLookupList;
  2073. const USHORT nCntLookupTable = GetUShort( pLookupHeader );
  2074. pLookupHeader += 2;
  2075. for( USHORT nLookupIdx = 0; nLookupIdx < nCntLookupTable; ++nLookupIdx )
  2076. {
  2077. const USHORT nOffset = GetUShort( pLookupHeader );
  2078. pLookupHeader += 2;
  2079. if( std::count( aLookupIndexList.begin(), aLookupIndexList.end(), nLookupIdx ) )
  2080. aLookupOffsetList.push_back( nOffset );
  2081. }
  2082. UshortList::const_iterator lookup_it = aLookupOffsetList.begin();
  2083. for(; lookup_it != aLookupOffsetList.end(); ++lookup_it )
  2084. {
  2085. const USHORT nOfsLookupTable = *lookup_it;
  2086. const FT_Byte* pLookupTable = pGsubBase + nOfsLookupList + nOfsLookupTable;
  2087. const USHORT eLookupType = GetUShort( pLookupTable+0 );
  2088. const USHORT nCntLookupSubtable = GetUShort( pLookupTable+4 );
  2089. pLookupTable += 6;
  2090. // TODO: switch( eLookupType )
  2091. if( eLookupType != 1 ) // TODO: once we go beyond SingleSubst
  2092. continue;
  2093. for( USHORT nSubTableIdx = 0; nSubTableIdx < nCntLookupSubtable; ++nSubTableIdx )
  2094. {
  2095. const USHORT nOfsSubLookupTable = GetUShort( pLookupTable );
  2096. pLookupTable += 2;
  2097. const FT_Byte* pSubLookup = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable;
  2098. const USHORT nFmtSubstitution = GetUShort( pSubLookup+0 );
  2099. const USHORT nOfsCoverage = GetUShort( pSubLookup+2 );
  2100. pSubLookup += 4;
  2101. typedef std::pair<USHORT,USHORT> GlyphSubst;
  2102. typedef std::vector<GlyphSubst> SubstVector;
  2103. SubstVector aSubstVector;
  2104. const FT_Byte* pCoverage = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable + nOfsCoverage;
  2105. const USHORT nFmtCoverage = GetUShort( pCoverage+0 );
  2106. pCoverage += 2;
  2107. switch( nFmtCoverage )
  2108. {
  2109. case 1: // Coverage Format 1
  2110. {
  2111. const USHORT nCntGlyph = GetUShort( pCoverage );
  2112. pCoverage += 2;
  2113. aSubstVector.reserve( nCntGlyph );
  2114. for( USHORT i = 0; i < nCntGlyph; ++i )
  2115. {
  2116. const USHORT nGlyphId = GetUShort( pCoverage );
  2117. pCoverage += 2;
  2118. aSubstVector.push_back( GlyphSubst( nGlyphId, 0 ) );
  2119. }
  2120. }
  2121. break;
  2122. case 2: // Coverage Format 2
  2123. {
  2124. const USHORT nCntRange = GetUShort( pCoverage );
  2125. pCoverage += 2;
  2126. for( int i = nCntRange; --i >= 0; )
  2127. {
  2128. const UINT32 nGlyph0 = GetUShort( pCoverage+0 );
  2129. const UINT32 nGlyph1 = GetUShort( pCoverage+2 );
  2130. const USHORT nCovIdx = GetUShort( pCoverage+4 );
  2131. pCoverage += 6;
  2132. for( UINT32 j = nGlyph0; j <= nGlyph1; ++j )
  2133. aSubstVector.push_back( GlyphSubst( static_cast<USHORT>(j + nCovIdx), 0 ) );
  2134. }
  2135. }
  2136. break;
  2137. }
  2138. SubstVector::iterator it( aSubstVector.begin() );
  2139. switch( nFmtSubstitution )
  2140. {
  2141. case 1: // Single Substitution Format 1
  2142. {
  2143. const USHORT nDeltaGlyphId = GetUShort( pSubLookup );
  2144. pSubLookup += 2;
  2145. for(; it != aSubstVector.end(); ++it )
  2146. (*it).second = (*it).first + nDeltaGlyphId;
  2147. }
  2148. break;
  2149. case 2: // Single Substitution Format 2
  2150. {
  2151. const USHORT nCntGlyph = GetUShort( pSubLookup );
  2152. pSubLookup += 2;
  2153. for( int i = nCntGlyph; (it != aSubstVector.end()) && (--i>=0); ++it )
  2154. {
  2155. const USHORT nGlyphId = GetUShort( pSubLookup );
  2156. pSubLookup += 2;
  2157. (*it).second = nGlyphId;
  2158. }
  2159. }
  2160. break;
  2161. }
  2162. DBG_ASSERT( (it == aSubstVector.end()), "lookup<->coverage table mismatch" );
  2163. // now apply the glyph substitutions that have been collected in this subtable
  2164. for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it )
  2165. maGlyphSubstitution[ (*it).first ] = (*it).second;
  2166. }
  2167. }
  2168. return true;
  2169. }
  2170. // =======================================================================