PageRenderTime 34ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/vcl/generic/glyphs/gcach_ftyp.cxx

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