PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/OOO330_m20/vcl/os2/source/gdi/salgdi3.cxx

https://bitbucket.org/tora/ooo-enum-attribute-packed-experiment-ooo330_m20-vcl
C++ | 1769 lines | 1250 code | 291 blank | 228 comment | 221 complexity | 066bb093c093057b9e4841faf444c566 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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. #define INCL_GRE_STRINGS
  28. #define INCL_GPI
  29. #define INCL_DOS
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #include <svpm.h>
  34. #define _SV_SALGDI3_CXX
  35. #include <tools/svwin.h>
  36. #include <rtl/tencinfo.h>
  37. #ifndef _OSL_FILE_HXX
  38. #include <osl/file.hxx>
  39. #endif
  40. #ifndef _OSL_THREAD_HXX
  41. #include <osl/thread.hxx>
  42. #endif
  43. #ifndef _OSL_PROCESS_HXX
  44. #include <osl/process.h>
  45. #endif
  46. #include <vcl/svapp.hxx>
  47. #include <saldata.hxx>
  48. #include <salgdi.h>
  49. #include <vcl/font.hxx>
  50. #include <vcl/sallayout.hxx>
  51. #include <tools/poly.hxx>
  52. #include <tools/debug.hxx>
  53. #include <rtl/textcvt.h>
  54. #include <tools/debug.hxx>
  55. #include <saldata.hxx>
  56. #include <salgdi.h>
  57. #ifndef _SV_OUTFONT_HXX
  58. #include <vcl/outfont.hxx>
  59. #endif
  60. #include <sallayout.h>
  61. #include <tools/poly.hxx>
  62. #include <basegfx/polygon/b2dpolygon.hxx>
  63. #include <basegfx/polygon/b2dpolypolygon.hxx>
  64. #include <basegfx/matrix/b2dhommatrix.hxx>
  65. #ifndef __H_FT2LIB
  66. #include <wingdi.h>
  67. #include <ft2lib.h>
  68. #endif
  69. #include "sft.hxx"
  70. #ifdef GCP_KERN_HACK
  71. #include <algorithm>
  72. #endif
  73. using namespace vcl;
  74. // -----------
  75. // - Inlines -
  76. // -----------
  77. inline W32FIXED FixedFromDouble( double d )
  78. {
  79. const long l = (long) ( d * 65536. );
  80. return *(W32FIXED*) &l;
  81. }
  82. // -----------------------------------------------------------------------
  83. inline int IntTimes256FromFixed(W32FIXED f)
  84. {
  85. int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8);
  86. return nFixedTimes256;
  87. }
  88. // -----------
  89. // - Defines -
  90. // -----------
  91. // this is a special codepage code, used to identify OS/2 symbol font.
  92. #define SYMBOL_CHARSET 65400
  93. // =======================================================================
  94. UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen = STRING_LEN)
  95. {
  96. return UniString( pStr, nLen, gsl_getSystemTextEncoding(),
  97. RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
  98. RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
  99. RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
  100. }
  101. // =======================================================================
  102. static USHORT ImplSalToCharSet( CharSet eCharSet )
  103. {
  104. // !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0
  105. // !!! zurueckgegeben werden, solange die DBCS-Charsets nicht
  106. // !!! durchgereicht werden
  107. switch ( eCharSet )
  108. {
  109. case RTL_TEXTENCODING_IBM_437:
  110. return 437;
  111. case RTL_TEXTENCODING_IBM_850:
  112. return 850;
  113. case RTL_TEXTENCODING_IBM_860:
  114. return 860;
  115. case RTL_TEXTENCODING_IBM_861:
  116. return 861;
  117. case RTL_TEXTENCODING_IBM_863:
  118. return 863;
  119. case RTL_TEXTENCODING_IBM_865:
  120. return 865;
  121. case RTL_TEXTENCODING_MS_1252:
  122. return 1004;
  123. case RTL_TEXTENCODING_SYMBOL:
  124. return 65400;
  125. }
  126. return 0;
  127. }
  128. // -----------------------------------------------------------------------
  129. static CharSet ImplCharSetToSal( USHORT usCodePage )
  130. {
  131. switch ( usCodePage )
  132. {
  133. case 437:
  134. return RTL_TEXTENCODING_IBM_437;
  135. case 850:
  136. return RTL_TEXTENCODING_IBM_850;
  137. case 860:
  138. return RTL_TEXTENCODING_IBM_860;
  139. case 861:
  140. return RTL_TEXTENCODING_IBM_861;
  141. case 863:
  142. return RTL_TEXTENCODING_IBM_863;
  143. case 865:
  144. return RTL_TEXTENCODING_IBM_865;
  145. case 1004:
  146. return RTL_TEXTENCODING_MS_1252;
  147. case 65400:
  148. return RTL_TEXTENCODING_SYMBOL;
  149. }
  150. return RTL_TEXTENCODING_DONTKNOW;
  151. }
  152. // -----------------------------------------------------------------------
  153. static FontFamily ImplFamilyToSal( BYTE bFamilyType )
  154. {
  155. switch ( bFamilyType )
  156. {
  157. case 4:
  158. return FAMILY_DECORATIVE;
  159. case 3:
  160. return FAMILY_SCRIPT;
  161. }
  162. return FAMILY_DONTKNOW;
  163. }
  164. // -----------------------------------------------------------------------
  165. static FontWeight ImplWeightToSal( USHORT nWeight )
  166. {
  167. // Falls sich jemand an die alte Doku gehalten hat
  168. if ( nWeight > 999 )
  169. nWeight /= 1000;
  170. switch ( nWeight )
  171. {
  172. case 1:
  173. return WEIGHT_THIN;
  174. case 2:
  175. return WEIGHT_ULTRALIGHT;
  176. case 3:
  177. return WEIGHT_LIGHT;
  178. case 4:
  179. return WEIGHT_SEMILIGHT;
  180. case 5:
  181. return WEIGHT_NORMAL;
  182. case 6:
  183. return WEIGHT_SEMIBOLD;
  184. case 7:
  185. return WEIGHT_BOLD;
  186. case 8:
  187. return WEIGHT_ULTRABOLD;
  188. case 9:
  189. return WEIGHT_BLACK;
  190. }
  191. return WEIGHT_DONTKNOW;
  192. }
  193. // -----------------------------------------------------------------------
  194. static UniString ImpStyleNameToSal( const char* pFamilyName,
  195. const char* pFaceName,
  196. USHORT nLen )
  197. {
  198. if ( !nLen )
  199. nLen = strlen(pFamilyName);
  200. // strip FamilyName from FaceName
  201. if ( strncmp( pFamilyName, pFaceName, nLen ) == 0 )
  202. {
  203. USHORT nFaceLen = (USHORT)strlen( pFaceName+nLen );
  204. // Ist Facename laenger, schneiden wir den FamilyName ab
  205. if ( nFaceLen > 1 )
  206. return UniString( pFaceName+(nLen+1), gsl_getSystemTextEncoding());
  207. else
  208. return UniString();
  209. }
  210. else
  211. return UniString( pFaceName, gsl_getSystemTextEncoding());
  212. }
  213. // -----------------------------------------------------------------------
  214. inline FontPitch ImplLogPitchToSal( BYTE fsType )
  215. {
  216. if ( fsType & FM_TYPE_FIXED )
  217. return PITCH_FIXED;
  218. else
  219. return PITCH_VARIABLE;
  220. }
  221. // -----------------------------------------------------------------------
  222. inline BYTE ImplPitchToWin( FontPitch ePitch )
  223. {
  224. if ( ePitch == PITCH_FIXED )
  225. return FM_TYPE_FIXED;
  226. //else if ( ePitch == PITCH_VARIABLE )
  227. return 0;
  228. }
  229. // -----------------------------------------------------------------------
  230. static ImplDevFontAttributes Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric)
  231. {
  232. ImplDevFontAttributes aDFA;
  233. // get font face attributes
  234. aDFA.meFamily = ImplFamilyToSal( pFontMetric->panose.bFamilyType);
  235. aDFA.meWidthType = WIDTH_DONTKNOW;
  236. aDFA.meWeight = ImplWeightToSal( pFontMetric->usWeightClass);
  237. aDFA.meItalic = (pFontMetric->fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
  238. aDFA.mePitch = ImplLogPitchToSal( pFontMetric->fsType );
  239. aDFA.mbSymbolFlag = (pFontMetric->usCodePage == SYMBOL_CHARSET);
  240. // get the font face name
  241. // the maName field stores the font name without the style, so under OS/2
  242. // we must use the family name
  243. aDFA.maName = UniString( pFontMetric->szFamilyname, gsl_getSystemTextEncoding());
  244. aDFA.maStyleName = ImpStyleNameToSal( pFontMetric->szFamilyname,
  245. pFontMetric->szFacename,
  246. strlen( pFontMetric->szFamilyname) );
  247. // get device specific font attributes
  248. aDFA.mbOrientation = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
  249. aDFA.mbDevice = (pFontMetric->fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
  250. aDFA.mbEmbeddable = false;
  251. aDFA.mbSubsettable = false;
  252. DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFamilyname);
  253. if( fontType == FT2_FONTTYPE_TRUETYPE && !aDFA.mbDevice)
  254. aDFA.mbSubsettable = true;
  255. // for now we can only embed Type1 fonts
  256. if( fontType == FT2_FONTTYPE_TYPE1 )
  257. aDFA.mbEmbeddable = true;
  258. // heuristics for font quality
  259. // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
  260. // - subsetting > embedding > none
  261. aDFA.mnQuality = 0;
  262. if( fontType == FT2_FONTTYPE_TRUETYPE )
  263. aDFA.mnQuality += 50;
  264. if( aDFA.mbSubsettable )
  265. aDFA.mnQuality += 200;
  266. else if( aDFA.mbEmbeddable )
  267. aDFA.mnQuality += 100;
  268. // #i38665# prefer Type1 versions of the standard postscript fonts
  269. if( aDFA.mbEmbeddable )
  270. {
  271. if( aDFA.maName.EqualsAscii( "AvantGarde" )
  272. || aDFA.maName.EqualsAscii( "Bookman" )
  273. || aDFA.maName.EqualsAscii( "Courier" )
  274. || aDFA.maName.EqualsAscii( "Helvetica" )
  275. || aDFA.maName.EqualsAscii( "NewCenturySchlbk" )
  276. || aDFA.maName.EqualsAscii( "Palatino" )
  277. || aDFA.maName.EqualsAscii( "Symbol" )
  278. || aDFA.maName.EqualsAscii( "Times" )
  279. || aDFA.maName.EqualsAscii( "ZapfChancery" )
  280. || aDFA.maName.EqualsAscii( "ZapfDingbats" ) )
  281. aDFA.mnQuality += 500;
  282. }
  283. aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW;
  284. aDFA.meAntiAlias = ANTIALIAS_DONTKNOW;
  285. // TODO: add alias names
  286. return aDFA;
  287. }
  288. // =======================================================================
  289. // -----------------------------------------------------------------------
  290. // =======================================================================
  291. ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric,
  292. int nHeight, BYTE nPitchAndFamily )
  293. : ImplFontData( Os2Font2DevFontAttributes(_pFontMetric), 0 ),
  294. pFontMetric( _pFontMetric ),
  295. meOs2CharSet( _pFontMetric->usCodePage),
  296. mnPitchAndFamily( nPitchAndFamily ),
  297. mpFontCharSets( NULL ),
  298. mpUnicodeMap( NULL ),
  299. mbDisableGlyphApi( false ),
  300. mbHasKoreanRange( false ),
  301. mbHasCJKSupport( false ),
  302. mbAliasSymbolsLow( false ),
  303. mbAliasSymbolsHigh( false ),
  304. mnId( 0 )
  305. {
  306. SetBitmapSize( 0, nHeight );
  307. }
  308. // -----------------------------------------------------------------------
  309. ImplOs2FontData::~ImplOs2FontData()
  310. {
  311. delete[] mpFontCharSets;
  312. if( mpUnicodeMap )
  313. mpUnicodeMap->DeReference();
  314. }
  315. // -----------------------------------------------------------------------
  316. sal_IntPtr ImplOs2FontData::GetFontId() const
  317. {
  318. return mnId;
  319. }
  320. // -----------------------------------------------------------------------
  321. void ImplOs2FontData::UpdateFromHPS( HPS hPS ) const
  322. {
  323. // short circuit if already initialized
  324. if( mpUnicodeMap != NULL )
  325. return;
  326. ReadCmapTable( hPS );
  327. ReadOs2Table( hPS );
  328. // even if the font works some fonts have problems with the glyph API
  329. // => the heuristic below tries to figure out which fonts have the problem
  330. DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFacename);
  331. if( fontType != FT2_FONTTYPE_TRUETYPE
  332. && (pFontMetric->fsDefn & FM_DEFN_GENERIC) == 0)
  333. mbDisableGlyphApi = true;
  334. }
  335. // -----------------------------------------------------------------------
  336. #ifdef GNG_VERT_HACK
  337. bool ImplOs2FontData::HasGSUBstitutions( HPS hPS ) const
  338. {
  339. if( !mbGsubRead )
  340. ReadGsubTable( hPS );
  341. return !maGsubTable.empty();
  342. }
  343. // -----------------------------------------------------------------------
  344. bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar ) const
  345. {
  346. return( maGsubTable.find( cChar ) != maGsubTable.end() );
  347. }
  348. #endif // GNG_VERT_HACK
  349. // -----------------------------------------------------------------------
  350. ImplFontCharMap* ImplOs2FontData::GetImplFontCharMap() const
  351. {
  352. mpUnicodeMap->AddReference();
  353. return mpUnicodeMap;
  354. }
  355. // -----------------------------------------------------------------------
  356. static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
  357. static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);}
  358. static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));}
  359. static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
  360. void ImplOs2FontData::ReadOs2Table( HPS hPS ) const
  361. {
  362. const DWORD Os2Tag = CalcTag( "OS/2" );
  363. DWORD nLength = Ft2GetFontData( hPS, Os2Tag, 0, NULL, 0 );
  364. if( (nLength == FT2_ERROR) || !nLength )
  365. return;
  366. std::vector<unsigned char> aOS2map( nLength );
  367. unsigned char* pOS2map = &aOS2map[0];
  368. DWORD nRC = Ft2GetFontData( hPS, Os2Tag, 0, pOS2map, nLength );
  369. sal_uInt32 nVersion = GetUShort( pOS2map );
  370. if ( nVersion >= 0x0001 && nLength >= 58 )
  371. {
  372. // We need at least version 0x0001 (TrueType rev 1.66)
  373. // to have access to the needed struct members.
  374. sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 );
  375. sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 );
  376. sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 );
  377. sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 );
  378. // Check for CJK capabilities of the current font
  379. mbHasCJKSupport = (ulUnicodeRange2 & 0x2fff0000)
  380. | (ulUnicodeRange3 & 0x00000001);
  381. mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000)
  382. | (ulUnicodeRange2 & 0x01100000);
  383. }
  384. }
  385. // -----------------------------------------------------------------------
  386. #ifdef GNG_VERT_HACK
  387. void ImplOs2FontData::ReadGsubTable( HPS hPS ) const
  388. {
  389. mbGsubRead = true;
  390. // check the existence of a GSUB table
  391. const DWORD GsubTag = CalcTag( "GSUB" );
  392. DWORD nRC = Ft2GetFontData( hPS, GsubTag, 0, NULL, 0 );
  393. if( (nRC == FT2_ERROR) || !nRC )
  394. return;
  395. // TODO: directly read the GSUB table instead of going through sft
  396. // get raw font file data
  397. DWORD nFontSize = Ft2GetFontData( hPS, 0, 0, NULL, 0 );
  398. if( nFontSize == FT2_ERROR )
  399. return;
  400. std::vector<char> aRawFont( nFontSize+1 );
  401. aRawFont[ nFontSize ] = 0;
  402. DWORD nFontSize2 = Ft2GetFontData( hPS, 0, 0, (void*)&aRawFont[0], nFontSize );
  403. if( nFontSize != nFontSize2 )
  404. return;
  405. // open font file
  406. sal_uInt32 nFaceNum = 0;
  407. if( !aRawFont[0] ) // TTC candidate
  408. nFaceNum = ~0U; // indicate "TTC font extracts only"
  409. TrueTypeFont* pTTFont = NULL;
  410. ::OpenTTFontBuffer( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
  411. if( !pTTFont )
  412. return;
  413. // add vertically substituted characters to list
  414. static const sal_Unicode aGSUBCandidates[] = {
  415. 0x0020, 0x0080, // ASCII
  416. 0x2000, 0x2600, // misc
  417. 0x3000, 0x3100, // CJK punctutation
  418. 0x3300, 0x3400, // squared words
  419. 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
  420. 0 };
  421. for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
  422. for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
  423. if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
  424. maGsubTable.insert( cChar ); // insert GSUBbed unicodes
  425. CloseTTFont( pTTFont );
  426. #if 0
  427. TrueTypeFont* pTTFont = NULL;
  428. ::OpenTTFont( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
  429. if( !pTTFont )
  430. return;
  431. // add vertically substituted characters to list
  432. static const sal_Unicode aGSUBCandidates[] = {
  433. 0x0020, 0x0080, // ASCII
  434. 0x2000, 0x2600, // misc
  435. 0x3000, 0x3100, // CJK punctutation
  436. 0x3300, 0x3400, // squared words
  437. 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
  438. 0 };
  439. for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
  440. for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
  441. if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
  442. maGsubTable.insert( cChar ); // insert GSUBbed unicodes
  443. CloseTTFont( pTTFont );
  444. #endif
  445. }
  446. #endif // GNG_VERT_HACK
  447. // -----------------------------------------------------------------------
  448. void ImplOs2FontData::ReadCmapTable( HPS hPS ) const
  449. {
  450. CmapResult aResult;
  451. aResult.mnPairCount = 0;
  452. aResult.mbSymbolic = (meOs2CharSet == SYMBOL_CHARSET);
  453. aResult.mbRecoded = true;
  454. // get the CMAP table from the font which is selected into the DC
  455. const DWORD CmapTag = CalcTag( "cmap" );
  456. DWORD nRC = Ft2GetFontData( hPS, CmapTag, 0, NULL, 0 );
  457. // read the CMAP table if available
  458. if( nRC != FT2_ERROR )
  459. {
  460. const int nLength = nRC;
  461. std::vector<unsigned char> aCmap( nLength );
  462. unsigned char* pCmap = &aCmap[0];
  463. nRC = Ft2GetFontData( hPS, CmapTag, 0, pCmap, nLength );
  464. // parse the CMAP table
  465. if( nRC == nLength )
  466. ParseCMAP( pCmap, nLength, aResult );
  467. } else {
  468. // we need to define at least a simple charmap, otherwise this font
  469. // will be mapped to default charmap, and OOo doesn't accept the
  470. // system font to match the default charmap
  471. aResult.mnPairCount = 1;
  472. // ImplFontCharMap destructor will free this memory
  473. aResult.mpPairCodes = new sal_uInt32[ 2 * aResult.mnPairCount ];
  474. aResult.mpPairCodes[0] = 0x0020;
  475. aResult.mpPairCodes[1] = 0x00FF;
  476. aResult.mpStartGlyphs = NULL;
  477. }
  478. mbDisableGlyphApi |= aResult.mbRecoded;
  479. if( aResult.mnPairCount > 0 )
  480. mpUnicodeMap = new ImplFontCharMap( aResult.mnPairCount,
  481. aResult.mpPairCodes, aResult.mpStartGlyphs );
  482. else
  483. mpUnicodeMap = ImplFontCharMap::GetDefaultMap();
  484. }
  485. // =======================================================================
  486. void Os2SalGraphics::SetTextColor( SalColor nSalColor )
  487. {
  488. CHARBUNDLE cb;
  489. cb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
  490. SALCOLOR_GREEN( nSalColor ),
  491. SALCOLOR_BLUE( nSalColor ) );
  492. // set default color attributes
  493. Ft2SetAttrs( mhPS,
  494. PRIM_CHAR,
  495. CBB_COLOR,
  496. 0,
  497. &cb );
  498. }
  499. // -----------------------------------------------------------------------
  500. USHORT Os2SalGraphics::ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int nFallbackLevel)
  501. {
  502. #if OSL_DEBUG_LEVEL>10
  503. debug_printf( "Os2SalGraphics::ImplDoSetFont\n");
  504. #endif
  505. ImplOs2FontData* pFontData = (ImplOs2FontData*)i_pFont->mpFontData;
  506. PFONTMETRICS pFontMetric = NULL;
  507. FATTRS aFAttrs;
  508. BOOL bOutline = FALSE;
  509. APIRET rc;
  510. memset( &aFAttrs, 0, sizeof( FATTRS ) );
  511. aFAttrs.usRecordLength = sizeof( FATTRS );
  512. aFAttrs.lMaxBaselineExt = i_pFont->mnHeight;
  513. aFAttrs.lAveCharWidth = i_pFont->mnWidth;
  514. // do we have a pointer to the FONTMETRICS of the selected font? -> use it!
  515. if ( pFontData )
  516. {
  517. pFontMetric = pFontData->GetFontMetrics();
  518. bOutline = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
  519. // use match&registry fields to get correct match
  520. aFAttrs.lMatch = pFontMetric->lMatch;
  521. aFAttrs.idRegistry = pFontMetric->idRegistry;
  522. aFAttrs.usCodePage = pFontMetric->usCodePage;
  523. if ( bOutline )
  524. {
  525. aFAttrs.fsFontUse |= FATTR_FONTUSE_OUTLINE;
  526. if ( i_pFont->mnOrientation )
  527. aFAttrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
  528. }
  529. else
  530. {
  531. aFAttrs.lMaxBaselineExt = pFontMetric->lMaxBaselineExt;
  532. aFAttrs.lAveCharWidth = pFontMetric->lAveCharWidth;
  533. }
  534. }
  535. // use family name for outline fonts
  536. if ( mbPrinter ) {
  537. // use font face name for printers because otherwise ft2lib will fail
  538. // to select the correct font for GPI (ticket#117)
  539. strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
  540. } else if ( !pFontMetric) {
  541. // use OOo name if fontmetrics not available!
  542. ByteString aName( i_pFont->maName.GetToken( 0 ), gsl_getSystemTextEncoding());
  543. strncpy( (char*)(aFAttrs.szFacename), aName.GetBuffer(), sizeof( aFAttrs.szFacename ) );
  544. } else if ( bOutline) {
  545. // use fontmetric family name for outline fonts
  546. strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFamilyname, sizeof( aFAttrs.szFacename ) );
  547. } else {
  548. // use real font face name for bitmaps (WarpSans only)
  549. strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
  550. }
  551. if ( i_pFont->meItalic != ITALIC_NONE )
  552. aFAttrs.fsSelection |= FATTR_SEL_ITALIC;
  553. if ( i_pFont->meWeight > WEIGHT_MEDIUM )
  554. aFAttrs.fsSelection |= FATTR_SEL_BOLD;
  555. #if OSL_DEBUG_LEVEL>1
  556. if (pFontMetric->szFacename[0] == 'A') {
  557. debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS, pFontMetric->lMatch);
  558. debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS, pFontMetric->szFacename);
  559. debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS, aFAttrs.szFacename);
  560. }
  561. #endif
  562. Ft2DeleteSetId( mhPS, nFallbackLevel + LCID_BASE);
  563. if ( (rc=Ft2CreateLogFont( mhPS, NULL, nFallbackLevel + LCID_BASE, &aFAttrs)) == GPI_ERROR ) {
  564. #if OSL_DEBUG_LEVEL>1
  565. ERRORID nLastError = WinGetLastError( GetSalData()->mhAB );
  566. debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS, nLastError );
  567. #endif
  568. return SAL_SETFONT_REMOVEANDMATCHNEW;
  569. }
  570. CHARBUNDLE aBundle;
  571. ULONG nAttrsDefault = 0;
  572. ULONG nAttrs = CBB_SET;
  573. aBundle.usSet = nFallbackLevel + LCID_BASE;
  574. if ( bOutline )
  575. {
  576. nAttrs |= CBB_BOX;
  577. aBundle.sizfxCell.cy = MAKEFIXED( i_pFont->mnHeight, 0 );
  578. if ( !i_pFont->mnWidth )
  579. {
  580. LONG nXFontRes;
  581. LONG nYFontRes;
  582. LONG nHeight;
  583. // Auf die Aufloesung achten, damit das Ergebnis auch auf
  584. // Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet
  585. // werden, da auf meinem OS2 beispielsweise als
  586. // Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck-
  587. // gegeben wird
  588. GetResolution( nXFontRes, nYFontRes );
  589. nHeight = i_pFont->mnHeight;
  590. nHeight *= nXFontRes;
  591. nHeight += nYFontRes/2;
  592. nHeight /= nYFontRes;
  593. aBundle.sizfxCell.cx = MAKEFIXED( nHeight, 0 );
  594. }
  595. else
  596. aBundle.sizfxCell.cx = MAKEFIXED( i_pFont->mnWidth, 0 );
  597. }
  598. // set orientation for outlinefonts
  599. if ( i_pFont->mnOrientation )
  600. {
  601. if ( bOutline )
  602. {
  603. nAttrs |= CBB_ANGLE;
  604. double alpha = (double)(i_pFont->mnOrientation);
  605. alpha *= 0.0017453292; // *PI / 1800
  606. mnOrientationY = (long) (1000.0 * sin( alpha ));
  607. mnOrientationX = (long) (1000.0 * cos( alpha ));
  608. aBundle.ptlAngle.x = mnOrientationX;
  609. aBundle.ptlAngle.y = mnOrientationY;
  610. }
  611. else
  612. {
  613. mnOrientationX = 1;
  614. mnOrientationY = 0;
  615. nAttrs |= CBB_ANGLE;
  616. aBundle.ptlAngle.x = 1;
  617. aBundle.ptlAngle.y = 0;
  618. }
  619. }
  620. else
  621. {
  622. mnOrientationX = 1;
  623. mnOrientationY = 0;
  624. nAttrs |= CBB_ANGLE;
  625. aBundle.ptlAngle.x = 1;
  626. aBundle.ptlAngle.y = 0;
  627. }
  628. rc = Ft2SetAttrs( mhPS, PRIM_CHAR, nAttrs, nAttrsDefault, &aBundle );
  629. #if OSL_DEBUG_LEVEL>1
  630. FONTMETRICS aOS2Metric = {0};
  631. Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
  632. #endif
  633. return 0;
  634. }
  635. USHORT Os2SalGraphics::SetFont( ImplFontSelectData* pFont, int nFallbackLevel )
  636. {
  637. // return early if there is no new font
  638. if( !pFont )
  639. {
  640. #if 0
  641. // deselect still active font
  642. if( mhDefFont )
  643. Ft2SetCharSet( mhPS, mhDefFont );
  644. // release no longer referenced font handles
  645. for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
  646. {
  647. if( mhFonts[i] )
  648. Ft2DeleteSetId( mhPS, mhFonts[i] );
  649. mhFonts[ i ] = 0;
  650. }
  651. #endif
  652. mhDefFont = 0;
  653. return 0;
  654. }
  655. #if OSL_DEBUG_LEVEL>10
  656. debug_printf( "Os2SalGraphics::SetFont\n");
  657. #endif
  658. DBG_ASSERT( pFont->mpFontData, "WinSalGraphics mpFontData==NULL");
  659. mpOs2FontEntry[ nFallbackLevel ] = reinterpret_cast<ImplOs2FontEntry*>( pFont->mpFontEntry );
  660. mpOs2FontData[ nFallbackLevel ] = static_cast<const ImplOs2FontData*>( pFont->mpFontData );
  661. ImplDoSetFont( pFont, mfFontScale, nFallbackLevel);
  662. if( !mhDefFont )
  663. {
  664. // keep default font
  665. mhDefFont = nFallbackLevel + LCID_BASE;
  666. }
  667. else
  668. {
  669. // release no longer referenced font handles
  670. for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
  671. {
  672. if( mhFonts[i] )
  673. {
  674. #if 0
  675. Ft2DeleteSetId( mhPS, mhFonts[i] );
  676. #endif
  677. mhFonts[i] = 0;
  678. }
  679. }
  680. }
  681. // store new font in correct layer
  682. mhFonts[ nFallbackLevel ] = nFallbackLevel + LCID_BASE;
  683. // now the font is live => update font face
  684. if( mpOs2FontData[ nFallbackLevel ] )
  685. mpOs2FontData[ nFallbackLevel ]->UpdateFromHPS( mhPS );
  686. if( !nFallbackLevel )
  687. {
  688. mbFontKernInit = TRUE;
  689. if ( mpFontKernPairs )
  690. {
  691. delete[] mpFontKernPairs;
  692. mpFontKernPairs = NULL;
  693. }
  694. mnFontKernPairCount = 0;
  695. }
  696. // some printers have higher internal resolution, so their
  697. // text output would be different from what we calculated
  698. // => suggest DrawTextArray to workaround this problem
  699. if ( mbPrinter )
  700. return SAL_SETFONT_USEDRAWTEXTARRAY;
  701. else
  702. return 0;
  703. }
  704. // -----------------------------------------------------------------------
  705. void Os2SalGraphics::GetFontMetric( ImplFontMetricData* pMetric )
  706. {
  707. FONTMETRICS aOS2Metric;
  708. Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
  709. #if OSL_DEBUG_LEVEL>1
  710. debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS);
  711. if (aOS2Metric.szFacename[0] == 'A') {
  712. debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS, aOS2Metric.szFacename);
  713. debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS, aOS2Metric.lMatch);
  714. }
  715. #endif
  716. pMetric->maName = UniString( aOS2Metric.szFamilyname, gsl_getSystemTextEncoding());
  717. pMetric->maStyleName = ImpStyleNameToSal( aOS2Metric.szFamilyname,
  718. aOS2Metric.szFacename,
  719. strlen( aOS2Metric.szFamilyname ) );
  720. // device independent font attributes
  721. pMetric->meFamily = ImplFamilyToSal( aOS2Metric.panose.bFamilyType);
  722. pMetric->mbSymbolFlag = (aOS2Metric.usCodePage == SYMBOL_CHARSET);
  723. pMetric->meWeight = ImplWeightToSal( aOS2Metric.usWeightClass );
  724. pMetric->mePitch = ImplLogPitchToSal( aOS2Metric.fsType );
  725. pMetric->meItalic = (aOS2Metric.fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
  726. pMetric->mnSlant = 0;
  727. // device dependend font attributes
  728. pMetric->mbDevice = (aOS2Metric.fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
  729. pMetric->mbScalableFont = (aOS2Metric.fsDefn & FM_DEFN_OUTLINE) ? true : false;
  730. if( pMetric->mbScalableFont )
  731. {
  732. // check if there are kern pairs
  733. // TODO: does this work with GPOS kerning?
  734. pMetric->mbKernableFont = (aOS2Metric.sKerningPairs > 0);
  735. }
  736. else
  737. {
  738. // bitmap fonts cannot be rotated directly
  739. pMetric->mnOrientation = 0;
  740. // bitmap fonts have no kerning
  741. pMetric->mbKernableFont = false;
  742. }
  743. // transformation dependend font metrics
  744. if ( aOS2Metric.fsDefn & FM_DEFN_OUTLINE )
  745. {
  746. pMetric->mnWidth = aOS2Metric.lEmInc;
  747. }
  748. else
  749. {
  750. pMetric->mnWidth = aOS2Metric.lAveCharWidth;
  751. pMetric->mnOrientation = 0;
  752. }
  753. pMetric->mnIntLeading = aOS2Metric.lInternalLeading;
  754. pMetric->mnExtLeading = aOS2Metric.lExternalLeading;
  755. pMetric->mnAscent = aOS2Metric.lMaxAscender;
  756. pMetric->mnDescent = aOS2Metric.lMaxDescender;
  757. // #107888# improved metric compatibility for Asian fonts...
  758. // TODO: assess workaround below for CWS >= extleading
  759. // TODO: evaluate use of aWinMetric.sTypo* members for CJK
  760. if( mpOs2FontData[0] && mpOs2FontData[0]->SupportsCJK() )
  761. {
  762. pMetric->mnIntLeading += pMetric->mnExtLeading;
  763. // #109280# The line height for Asian fonts is too small.
  764. // Therefore we add half of the external leading to the
  765. // ascent, the other half is added to the descent.
  766. const long nHalfTmpExtLeading = pMetric->mnExtLeading / 2;
  767. const long nOtherHalfTmpExtLeading = pMetric->mnExtLeading - nHalfTmpExtLeading;
  768. // #110641# external leading for Asian fonts.
  769. // The factor 0.3 has been confirmed with experiments.
  770. long nCJKExtLeading = static_cast<long>(0.30 * (pMetric->mnAscent + pMetric->mnDescent));
  771. nCJKExtLeading -= pMetric->mnExtLeading;
  772. pMetric->mnExtLeading = (nCJKExtLeading > 0) ? nCJKExtLeading : 0;
  773. pMetric->mnAscent += nHalfTmpExtLeading;
  774. pMetric->mnDescent += nOtherHalfTmpExtLeading;
  775. // #109280# HACK korean only: increase descent for wavelines and impr
  776. // YD win9x only
  777. }
  778. }
  779. // -----------------------------------------------------------------------
  780. ULONG Os2SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs )
  781. {
  782. DBG_ASSERT( sizeof( KERNINGPAIRS ) == sizeof( ImplKernPairData ),
  783. "Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" );
  784. if ( mbFontKernInit )
  785. {
  786. if( mpFontKernPairs )
  787. {
  788. delete[] mpFontKernPairs;
  789. mpFontKernPairs = NULL;
  790. }
  791. mnFontKernPairCount = 0;
  792. {
  793. KERNINGPAIRS* pPairs = NULL;
  794. FONTMETRICS aOS2Metric;
  795. Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
  796. int nCount = aOS2Metric.sKerningPairs;
  797. if( nCount )
  798. {
  799. #ifdef GCP_KERN_HACK
  800. pPairs = new KERNINGPAIRS[ nCount+1 ];
  801. mpFontKernPairs = pPairs;
  802. mnFontKernPairCount = nCount;
  803. Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
  804. #else // GCP_KERN_HACK
  805. pPairs = (KERNINGPAIRS*)pKernPairs;
  806. nCount = (nCount < nPairs) ? nCount : nPairs;
  807. Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
  808. return nCount;
  809. #endif // GCP_KERN_HACK
  810. }
  811. }
  812. mbFontKernInit = FALSE;
  813. std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData );
  814. }
  815. if( !pKernPairs )
  816. return mnFontKernPairCount;
  817. else if( mpFontKernPairs )
  818. {
  819. if ( nPairs < mnFontKernPairCount )
  820. nPairs = mnFontKernPairCount;
  821. memcpy( pKernPairs, mpFontKernPairs,
  822. nPairs*sizeof( ImplKernPairData ) );
  823. return nPairs;
  824. }
  825. return 0;
  826. }
  827. // -----------------------------------------------------------------------
  828. static ImplFontCharMap* pOs2DefaultImplFontCharMap = NULL;
  829. static const sal_uInt32 pOs2DefaultRangeCodes[] = {0x0020,0x00FF};
  830. ImplFontCharMap* Os2SalGraphics::GetImplFontCharMap() const
  831. {
  832. if( !mpOs2FontData[0] )
  833. return ImplFontCharMap::GetDefaultMap();
  834. return mpOs2FontData[0]->GetImplFontCharMap();
  835. }
  836. // -----------------------------------------------------------------------
  837. bool Os2SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
  838. const String& rFontFileURL, const String& rFontName )
  839. {
  840. #if OSL_DEBUG_LEVEL>0
  841. debug_printf("Os2SalGraphics::AddTempDevFont\n");
  842. #endif
  843. return false;
  844. }
  845. // -----------------------------------------------------------------------
  846. void Os2SalGraphics::GetDevFontList( ImplDevFontList* pList )
  847. {
  848. PFONTMETRICS pFontMetrics;
  849. ULONG nFontMetricCount;
  850. SalData* pSalData;
  851. #if OSL_DEBUG_LEVEL>0
  852. debug_printf("Os2SalGraphics::GetDevFontList\n");
  853. #endif
  854. // install OpenSymbol
  855. HMODULE hMod;
  856. ULONG ObjNum, Offset, rc;
  857. CHAR Buff[2*_MAX_PATH];
  858. char drive[_MAX_DRIVE], dir[_MAX_DIR];
  859. char fname[_MAX_FNAME], ext[_MAX_EXT];
  860. // get module handle (and name)
  861. rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff,
  862. &Offset, (ULONG)ImplSalGetUniString);
  863. DosQueryModuleName(hMod, sizeof(Buff), Buff);
  864. // replace module path with font path
  865. char* slash = strrchr( Buff, '\\');
  866. *slash = '\0';
  867. slash = strrchr( Buff, '\\');
  868. *slash = '\0';
  869. strcat( Buff, "\\SHARE\\FONTS\\TRUETYPE\\OPENS___.TTF");
  870. rc = GpiLoadPublicFonts( GetSalData()->mhAB, Buff);
  871. if ( !mbPrinter )
  872. {
  873. // Bei Bildschirm-Devices cachen wir die Liste global, da
  874. // dies im unabhaengigen Teil auch so gemacht wird und wir
  875. // ansonsten auf geloeschten Systemdaten arbeiten koennten
  876. pSalData = GetSalData();
  877. nFontMetricCount = pSalData->mnFontMetricCount;
  878. pFontMetrics = pSalData->mpFontMetrics;
  879. // Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu
  880. if ( pFontMetrics )
  881. {
  882. delete pFontMetrics;
  883. pFontMetrics = NULL;
  884. nFontMetricCount = 0;
  885. }
  886. }
  887. else
  888. {
  889. nFontMetricCount = mnFontMetricCount;
  890. pFontMetrics = mpFontMetrics;
  891. }
  892. // do we have to create the cached font list first?
  893. if ( !pFontMetrics )
  894. {
  895. // query the number of fonts available
  896. LONG nTemp = 0;
  897. nFontMetricCount = Ft2QueryFonts( mhPS,
  898. QF_PUBLIC | QF_PRIVATE,
  899. NULL, &nTemp,
  900. sizeof( FONTMETRICS ), NULL );
  901. // procede only if at least one is available!
  902. if ( nFontMetricCount )
  903. {
  904. // allocate memory for font list
  905. pFontMetrics = new FONTMETRICS[nFontMetricCount];
  906. // query font list
  907. Ft2QueryFonts( mhPS,
  908. QF_PUBLIC | QF_PRIVATE,
  909. NULL,
  910. (PLONG)&nFontMetricCount,
  911. (LONG) sizeof( FONTMETRICS ),
  912. pFontMetrics );
  913. }
  914. if ( !mbPrinter )
  915. {
  916. pSalData->mnFontMetricCount = nFontMetricCount;
  917. pSalData->mpFontMetrics = pFontMetrics;
  918. }
  919. else
  920. {
  921. mnFontMetricCount = nFontMetricCount;
  922. mpFontMetrics = pFontMetrics;
  923. }
  924. }
  925. // copy data from the font list
  926. for( ULONG i = 0; i < nFontMetricCount; i++ )
  927. {
  928. PFONTMETRICS pFontMetric = &pFontMetrics[i];
  929. // skip font starting with '@', this is an alias internally
  930. // used by truetype engine.
  931. if (pFontMetric->szFacename[0] == '@')
  932. continue;
  933. // skip bitmap fonts (but keep WarpSans)
  934. if ( (pFontMetric->fsDefn & FM_DEFN_OUTLINE) == 0
  935. && strncmp( pFontMetric->szFacename, "WarpSans", 8) )
  936. // Font nicht aufnehmen
  937. continue;
  938. // replace '-' in facename with ' ' (for ft2lib)
  939. char* dash = pFontMetric->szFacename;
  940. while( (dash=strchr( dash, '-')))
  941. *dash++ = ' ';
  942. // create new font list element
  943. ImplOs2FontData* pData = new ImplOs2FontData( pFontMetric, 0, 0 );
  944. // add font list element to font list
  945. pList->Add( pData );
  946. }
  947. }
  948. // ----------------------------------------------------------------------------
  949. void Os2SalGraphics::GetDevFontSubstList( OutputDevice* pOutDev )
  950. {
  951. }
  952. // -----------------------------------------------------------------------
  953. BOOL Os2SalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& rRect )
  954. {
  955. // use unity matrix
  956. MAT2 aMat;
  957. aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
  958. aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
  959. UINT nGGOFlags = GGO_METRICS;
  960. if( !(nIndex & GF_ISCHAR) )
  961. nGGOFlags |= GGO_GLYPH_INDEX;
  962. nIndex &= GF_IDXMASK;
  963. GLYPHMETRICS aGM;
  964. DWORD nSize = FT2_ERROR;
  965. nSize = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGM, 0, NULL, &aMat );
  966. if( nSize == FT2_ERROR )
  967. return false;
  968. rRect = Rectangle( Point( +aGM.gmptGlyphOrigin.x, -aGM.gmptGlyphOrigin.y ),
  969. Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) );
  970. rRect.Left() = static_cast<int>( mfFontScale * rRect.Left() );
  971. rRect.Right() = static_cast<int>( mfFontScale * rRect.Right() );
  972. rRect.Top() = static_cast<int>( mfFontScale * rRect.Top() );
  973. rRect.Bottom() = static_cast<int>( mfFontScale * rRect.Bottom() );
  974. return true;
  975. }
  976. // -----------------------------------------------------------------------
  977. BOOL Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB2DPolyPoly )
  978. {
  979. #if OSL_DEBUG_LEVEL>0
  980. debug_printf("Os2SalGraphics::GetGlyphOutline\n");
  981. #endif
  982. rB2DPolyPoly.clear();
  983. BOOL bRet = FALSE;
  984. // use unity matrix
  985. MAT2 aMat;
  986. aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
  987. aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
  988. UINT nGGOFlags = GGO_NATIVE;
  989. if( !(nIndex & GF_ISCHAR) )
  990. nGGOFlags |= GGO_GLYPH_INDEX;
  991. nIndex &= GF_IDXMASK;
  992. GLYPHMETRICS aGlyphMetrics;
  993. DWORD nSize1 = FT2_ERROR;
  994. nSize1 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGlyphMetrics, 0, NULL, &aMat );
  995. if( !nSize1 ) // blank glyphs are ok
  996. bRet = TRUE;
  997. else if( nSize1 != FT2_ERROR )
  998. {
  999. BYTE* pData = new BYTE[ nSize1 ];
  1000. ULONG nTotalCount = 0;
  1001. DWORD nSize2;
  1002. nSize2 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags,
  1003. &aGlyphMetrics, nSize1, pData, &aMat );
  1004. if( nSize1 == nSize2 )
  1005. {
  1006. bRet = TRUE;
  1007. int nPtSize = 512;
  1008. Point* pPoints = new Point[ nPtSize ];
  1009. BYTE* pFlags = new BYTE[ nPtSize ];
  1010. TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData;
  1011. while( (BYTE*)pHeader < pData+nSize2 )
  1012. {
  1013. // only outline data is interesting
  1014. if( pHeader->dwType != TT_POLYGON_TYPE )
  1015. break;
  1016. // get start point; next start points are end points
  1017. // of previous segment
  1018. int nPnt = 0;
  1019. long nX = IntTimes256FromFixed( pHeader->pfxStart.x );
  1020. long nY = IntTimes256FromFixed( pHeader->pfxStart.y );
  1021. pPoints[ nPnt ] = Point( nX, nY );
  1022. pFlags[ nPnt++ ] = POLY_NORMAL;
  1023. bool bHasOfflinePoints = false;
  1024. TTPOLYCURVE* pCurve = (TTPOLYCURVE*)( pHeader + 1 );
  1025. pHeader = (TTPOLYGONHEADER*)( (BYTE*)pHeader + pHeader->cb );
  1026. while( (BYTE*)pCurve < (BYTE*)pHeader )
  1027. {
  1028. int nNeededSize = nPnt + 16 + 3 * pCurve->cpfx;
  1029. if( nPtSize < nNeededSize )
  1030. {
  1031. Point* pOldPoints = pPoints;
  1032. BYTE* pOldFlags = pFlags;
  1033. nPtSize = 2 * nNeededSize;
  1034. pPoints = new Point[ nPtSize ];
  1035. pFlags = new BYTE[ nPtSize ];
  1036. for( int i = 0; i < nPnt; ++i )
  1037. {
  1038. pPoints[ i ] = pOldPoints[ i ];
  1039. pFlags[ i ] = pOldFlags[ i ];
  1040. }
  1041. delete[] pOldPoints;
  1042. delete[] pOldFlags;
  1043. }
  1044. int i = 0;
  1045. if( TT_PRIM_LINE == pCurve->wType )
  1046. {
  1047. while( i < pCurve->cpfx )
  1048. {
  1049. nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
  1050. nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
  1051. ++i;
  1052. pPoints[ nPnt ] = Point( nX, nY );
  1053. pFlags[ nPnt ] = POLY_NORMAL;
  1054. ++nPnt;
  1055. }
  1056. }
  1057. else if( TT_PRIM_QSPLINE == pCurve->wType )
  1058. {
  1059. bHasOfflinePoints = true;
  1060. while( i < pCurve->cpfx )
  1061. {
  1062. // get control point of quadratic bezier spline
  1063. nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
  1064. nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
  1065. ++i;
  1066. Point aControlP( nX, nY );
  1067. // calculate first cubic control point
  1068. // P0 = 1/3 * (PBeg + 2 * PQControl)
  1069. nX = pPoints[ nPnt-1 ].X() + 2 * aControlP.X();
  1070. nY = pPoints[ nPnt-1 ].Y() + 2 * aControlP.Y();
  1071. pPoints[ nPnt+0 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
  1072. pFlags[ nPnt+0 ] = POLY_CONTROL;
  1073. // calculate endpoint of segment
  1074. nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
  1075. nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
  1076. if ( i+1 >= pCurve->cpfx )
  1077. {
  1078. // endpoint is either last point in segment => advance
  1079. ++i;
  1080. }
  1081. else
  1082. {
  1083. // or endpoint is the middle of two control points
  1084. nX += IntTimes256FromFixed( pCurve->apfx[ i-1 ].x );
  1085. nY += IntTimes256FromFixed( pCurve->apfx[ i-1 ].y );
  1086. nX = (nX + 1) / 2;
  1087. nY = (nY + 1) / 2;
  1088. // no need to advance, because the current point
  1089. // is the control point in next bezier spline
  1090. }
  1091. pPoints[ nPnt+2 ] = Point( nX, nY );
  1092. pFlags[ nPnt+2 ] = POLY_NORMAL;
  1093. // calculate second cubic control point
  1094. // P1 = 1/3 * (PEnd + 2 * PQControl)
  1095. nX = pPoints[ nPnt+2 ].X() + 2 * aControlP.X();
  1096. nY = pPoints[ nPnt+2 ].Y() + 2 * aControlP.Y();
  1097. pPoints[ nPnt+1 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
  1098. pFlags[ nPnt+1 ] = POLY_CONTROL;
  1099. nPnt += 3;
  1100. }
  1101. }
  1102. // next curve segment
  1103. pCurve = (TTPOLYCURVE*)&pCurve->apfx[ i ];
  1104. }
  1105. // end point is start point for closed contour
  1106. // disabled, because Polygon class closes the contour itself
  1107. // pPoints[nPnt++] = pPoints[0];
  1108. // #i35928#
  1109. // Added again, but add only when not yet closed
  1110. if(pPoints[nPnt - 1] != pPoints[0])
  1111. {
  1112. if( bHasOfflinePoints )
  1113. pFlags[nPnt] = pFlags[0];
  1114. pPoints[nPnt++] = pPoints[0];
  1115. }
  1116. // convert y-coordinates W32 -> VCL
  1117. for( int i = 0; i < nPnt; ++i )
  1118. pPoints[i].Y() = -pPoints[i].Y();
  1119. // insert into polypolygon
  1120. Polygon aPoly( nPnt, pPoints, (bHasOfflinePoints ? pFlags : NULL) );
  1121. // convert to B2DPolyPolygon
  1122. // TODO: get rid of the intermediate PolyPolygon
  1123. rB2DPolyPoly.append( aPoly.getB2DPolygon() );
  1124. }
  1125. delete[] pPoints;
  1126. delete[] pFlags;
  1127. }
  1128. delete[] pData;
  1129. }
  1130. // rescaling needed for the PolyPolygon conversion
  1131. if( rB2DPolyPoly.count() )
  1132. {
  1133. const double fFactor((1.0/256) * mfFontScale);
  1134. rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor));
  1135. }
  1136. return bRet;
  1137. }
  1138. // -----------------------------------------------------------------------
  1139. // TODO: Replace this class with boost::scoped_array
  1140. class ScopedCharArray
  1141. {
  1142. public:
  1143. inline explicit ScopedCharArray(char * pArray): m_pArray(pArray) {}
  1144. inline ~ScopedCharArray() { delete[] m_pArray; }
  1145. inline char * get() const { return m_pArray; }
  1146. private:
  1147. char * m_pArray;
  1148. };
  1149. class ScopedFont
  1150. {
  1151. public:
  1152. explicit ScopedFont(Os2SalGraphics & rData);
  1153. ~ScopedFont();
  1154. private:
  1155. Os2SalGraphics & m_rData;
  1156. ULONG m_hOrigFont;
  1157. };
  1158. ScopedFont::ScopedFont(Os2SalGraphics & rData): m_rData(rData)
  1159. {
  1160. #if 0
  1161. m_hOrigFont = m_rData.mhFonts[0];
  1162. m_rData.mhFonts[0] = 0; // avoid deletion of current font
  1163. #endif
  1164. }
  1165. ScopedFont::~ScopedFont()
  1166. {
  1167. #if 0
  1168. if( m_hOrigFont )
  1169. {
  1170. // restore original font, destroy temporary font
  1171. HFONT hTempFont = m_rData.mhFonts[0];
  1172. m_rData.mhFonts[0] = m_hOrigFont;
  1173. SelectObject( m_rData.mhDC, m_hOrigFont );
  1174. DeleteObject( hTempFont );
  1175. }
  1176. #endif
  1177. }
  1178. class ScopedTrueTypeFont
  1179. {
  1180. public:
  1181. inline ScopedTrueTypeFont(): m_pFont(0) {}
  1182. ~ScopedTrueTypeFont();
  1183. int open(void * pBuffer, sal_uInt32 nLen, sal_uInt32 nFaceNum);
  1184. inline TrueTypeFont * get() const { return m_pFont; }
  1185. private:
  1186. TrueTypeFont * m_pFont;
  1187. };
  1188. ScopedTrueTypeFont::~ScopedTrueTypeFont()
  1189. {
  1190. if (m_pFont != 0)
  1191. CloseTTFont(m_pFont);
  1192. }
  1193. int ScopedTrueTypeFont::open(void * pBuffer, sal_uInt32 nLen,
  1194. sal_uInt32 nFaceNum)
  1195. {
  1196. OSL_ENSURE(m_pFont == 0, "already open");
  1197. return OpenTTFontBuffer(pBuffer, nLen, nFaceNum, &m_pFont);
  1198. }
  1199. BOOL Os2SalGraphics::CreateFontSubset( const rtl::OUString& rToFile,
  1200. const ImplFontData* pFont, long* pGlyphIDs, sal_uInt8* pEncoding,
  1201. sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo )
  1202. {
  1203. // create matching ImplFontSelectData
  1204. // we need just enough to get to the font file data
  1205. // use height=1000 for easier debugging (to match psprint's font units)
  1206. ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
  1207. // TODO: much better solution: move SetFont and restoration of old font to caller
  1208. ScopedFont aOldFont(*this);
  1209. SetFont( &aIFSD, 0 );
  1210. #if OSL_DEBUG_LEVEL > 100
  1211. // get font metrics
  1212. TEXTMETRICA aWinMetric;
  1213. if( !::GetTextMetricsA( mhDC, &aWinMetric ) )
  1214. return FALSE;
  1215. DBG_ASSERT( !(aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "cannot subset device font" );
  1216. DBG_ASSERT( aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE, "can only subset TT font" );
  1217. #endif
  1218. // get raw font file data
  1219. DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
  1220. if( nFontSize1 == FT2_ERROR )
  1221. return FALSE;
  1222. ScopedCharArray xRawFontData(new char[ nFontSize1 ]);
  1223. DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 );
  1224. if( nFontSize1 != nFontSize2 )
  1225. return FALSE;
  1226. // open font file
  1227. sal_uInt32 nFaceNum = 0;
  1228. if( !*xRawFontData.get() ) // TTC candidate
  1229. nFaceNum = ~0U; // indicate "TTC font extracts only"
  1230. ScopedTrueTypeFont aSftTTF;
  1231. int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum );
  1232. if( nRC != SF_OK )
  1233. return FALSE;
  1234. TTGlobalFontInfo aTTInfo;
  1235. ::GetTTGlobalFontInfo( aSftTTF.get(), &aTTInfo );
  1236. rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TRUETYPE;
  1237. rInfo.m_aPSName = ImplSalGetUniString( aTTInfo.psname );
  1238. rInfo.m_nAscent = +aTTInfo.winAscent;
  1239. rInfo.m_nDescent = -aTTInfo.winDescent;
  1240. rInfo.m_aFontBBox = Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ),
  1241. Point( aTTInfo.xMax, aTTInfo.yMax ) );
  1242. rInfo.m_nCapHeight = aTTInfo.yMax; // Well ...
  1243. // subset glyphs and get their properties
  1244. // take care that subset fonts require the NotDef glyph in pos 0
  1245. int nOrigCount = nGlyphCount;
  1246. USHORT aShortIDs[ 256 ];
  1247. sal_uInt8 aTempEncs[ 256 ];
  1248. int nNotDef=-1, i;
  1249. for( i = 0; i < nGlyphCount; ++i )
  1250. {
  1251. aTempEncs[i] = pEncoding[i];
  1252. sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
  1253. if( pGlyphIDs[i] & GF_ISCHAR )
  1254. {
  1255. bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0;
  1256. nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
  1257. if( nGlyphIdx == 0 && pFont->IsSymbolFont() )
  1258. {
  1259. // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX
  1260. nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
  1261. nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 );
  1262. nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
  1263. }
  1264. }
  1265. aShortIDs[i] = static_cast<USHORT>( nGlyphIdx );
  1266. if( !nGlyphIdx )
  1267. if( nNotDef < 0 )
  1268. nNotDef = i; // first NotDef glyph found
  1269. }
  1270. if( nNotDef != 0 )
  1271. {
  1272. // add fake NotDef glyph if needed
  1273. if( nNotDef < 0 )
  1274. nNotDef = nGlyphCount++;
  1275. // NotDef glyph must be in pos 0 => swap glyphids
  1276. aShortIDs[ nNotDef ] = aShortIDs[0];
  1277. aTempEncs[ nNotDef ] = aTempEncs[0];
  1278. aShortIDs[0] = 0;
  1279. aTempEncs[0] = 0;
  1280. }
  1281. DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" );
  1282. // fill pWidth array
  1283. TTSimpleGlyphMetrics* pMetrics =
  1284. ::GetTTSimpleGlyphMetrics( aSftTTF.get(), aShortIDs, nGlyphCount, aIFSD.mbVertical );
  1285. if( !pMetrics )
  1286. return FALSE;
  1287. sal_uInt16 nNotDefAdv = pMetrics[0].adv;
  1288. pMetrics[0].adv = pMetrics[nNotDef].adv;
  1289. pMetrics[nNotDef].adv = nNotDefAdv;
  1290. for( i = 0; i < nOrigCount; ++i )
  1291. pGlyphWidths[i] = pMetrics[i].adv;
  1292. free( pMetrics );
  1293. // write subset into destination file
  1294. rtl::OUString aSysPath;
  1295. if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) )
  1296. return FALSE;
  1297. rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding();
  1298. ByteString aToFile( rtl::OUStringToOString( aSysPath, aThreadEncoding ) );
  1299. nRC = ::CreateTTFromTTGlyphs( aSftTTF.get(), aToFile.GetBuffer(), aShortIDs,
  1300. aTempEncs, nGlyphCount, 0, NULL, 0 );
  1301. return nRC == SF_OK;
  1302. }
  1303. //--------------------------------------------------------------------------
  1304. const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData* pFont,
  1305. const sal_Ucs* pUnicodes, sal_Int32* pCharWidths,
  1306. FontSubsetInfo& rInfo, long* pDataLen )
  1307. {
  1308. // create matching ImplFontSelectData
  1309. // we need just enough to get to the font file data
  1310. ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
  1311. // TODO: much better solution: move SetFont and restoration of old font to caller
  1312. ScopedFont aOldFont(*this);
  1313. SetFont( &aIFSD, 0 );
  1314. // get the raw font file data
  1315. DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
  1316. if( nFontSize1 == FT2_ERROR || nFontSize1 <= 0 )
  1317. return NULL;
  1318. *pDataLen = nFontSize1;
  1319. void* pData = reinterpret_cast<void*>(new char[ nFontSize1 ]);
  1320. DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, pData, nFontSize1 );
  1321. if( nFontSize1 != nFontSize2 )
  1322. *pDataLen = 0;
  1323. // get important font properties
  1324. FONTMETRICS aOS2Metric;
  1325. if (Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ) == GPI_ERROR)
  1326. *pDataLen = 0;
  1327. rInfo.m_nFontType = SAL_FONTSUBSETINFO_TYPE_TYPE1;
  1328. rInfo.m_aPSName = ImplSalGetUniString( aOS2Metric.szFacename );
  1329. rInfo.m_nAscent = +aOS2Metric.lMaxAscender;
  1330. rInfo.m_nDescent = -aOS2Metric.lMaxDescender;
  1331. rInfo.m_aFontBBox = Rectangle( Point( 0, -aOS2Metric.lMaxDescender ),
  1332. Point( aOS2Metric.lMaxCharInc, aOS2Metric.lMaxAscender+aOS2Metric.lExternalLeading ) );
  1333. rInfo.m_nCapHeight = aOS2Metric.lMaxAscender; // Well ...
  1334. // get individual character widths
  1335. for( int i = 0; i < 256; ++i )
  1336. {
  1337. LONG nCharWidth = 0;
  1338. const sal_Ucs cChar = pUnicodes[i];
  1339. if( !Ft2QueryStringWidthW( mhPS, (LPWSTR)&cChar, 1, &nCharWidth ) )
  1340. *pDataLen = 0;
  1341. pCharWidths[

Large files files are truncated, but you can click here to view the full file