Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1468 lines
42 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * font.cpp
  8. *
  9. * Revision History:
  10. *
  11. * Aug/12/1999 Xudong Wu [tessiew]
  12. * Created it.
  13. *
  14. \**************************************************************************/
  15. #include "precomp.hpp"
  16. const DOUBLE PI = 3.1415926535897932384626433832795;
  17. #if DBG
  18. #include <mmsystem.h>
  19. #endif
  20. //
  21. // Masks for supported code pages in the font
  22. //
  23. #define Latine1CodePageMask 0x0000000000000001
  24. #define Latine2CodePageMask 0x0000000000000002
  25. #define CyrillicCodePageMask 0x0000000000000004
  26. #define GreekCodePageMask 0x0000000000000008
  27. #define TurkishCodePageMask 0x0000000000000010
  28. #define HebrewCodePageMask 0x0000000000000020
  29. #define ArabicCodePageMask 0x0000000000000040
  30. #define BalticCodePageMask 0x0000000000000080
  31. #define Reserved1CodePageMask 0x000000000000FF00
  32. #define ThaiCodePageMask 0x0000000000010000
  33. #define JapanCodePageMask 0x0000000000020000
  34. #define ChineseCodePageMask 0x0000000000040000
  35. #define KoreanCodePageMask 0x0000000000080000
  36. #define TraditionalChineseCodePageMask 0x0000000000100000
  37. #define KoreanJohabCodePageMask 0x0000000000200000
  38. #define Reserved2CodePageMask 0x000000001FC00000
  39. #define MacintoshPageMask 0x0000000020000000
  40. #define OEMCodePageMask 0x0000000040000000
  41. #define SymbolCodePageMask 0x0000000080000000
  42. #define Reserved3CodePageMask 0x0000FFFF00000000
  43. #define IBMGreekCodePageMask 0x0001000000000000
  44. #define RussianMsDosCodePageMask 0x0002000000000000
  45. #define NordicCodePageMask 0x0004000000000000
  46. #define ArabicMsDosCodePageMask 0x0008000000000000
  47. #define CanandianMsDosCodePageMask 0x0010000000000000
  48. #define HebrewMsDosCodePageMask 0x0020000000000000
  49. #define IcelandicMsDosCodePageMask 0x0040000000000000
  50. #define PortugueseMsDosCodePageMask 0x0080000000000000
  51. #define IBMTurkishCodePageMask 0x0100000000000000
  52. #define IBMCyrillicCodePageMask 0x0200000000000000
  53. #define Latin2MsDosCodePageMask 0x0400000000000000
  54. #define BalticMsDosCodePageMask 0x0800000000000000
  55. #define Greek437CodePageMask 0x1000000000000000
  56. #define ArabicAsmoCodePageMask 0x2000000000000000
  57. #define WeLatinCodePageMask 0x4000000000000000
  58. #define USCodePageMask 0x8000000000000000
  59. ///// Create fonts from DC and optional ANSI or Unicode logfont
  60. //
  61. //
  62. GpFont::GpFont(
  63. REAL size,
  64. const GpFontFamily *family,
  65. INT style,
  66. Unit unit
  67. ) :
  68. Family (family),
  69. EmSize (size),
  70. Style (style),
  71. SizeUnit (unit)
  72. {
  73. SetValid(TRUE); // default is valid
  74. if (!(Family && Family->IsFileLoaded()))
  75. Family = NULL;
  76. }
  77. GpFont::GpFont(
  78. HDC hdc
  79. )
  80. {
  81. SetValid(TRUE); // default is valid
  82. // intialize it as invalid
  83. Family = NULL;
  84. InitializeFromDc(hdc);
  85. }
  86. GpFont::GpFont(
  87. HDC hdc,
  88. LOGFONTW *logfont
  89. )
  90. {
  91. SetValid(TRUE); // default is valid
  92. HFONT hOldFont = NULL;
  93. // intialize it as invalid
  94. Family = NULL;
  95. if (!hdc)
  96. return;
  97. HFONT hFont = CreateFontIndirectW(logfont);
  98. if (!hFont) return;
  99. hOldFont = (HFONT) SelectObject(hdc, hFont);
  100. InitializeFromDc(hdc);
  101. if (!hOldFont)
  102. return;
  103. DeleteObject(SelectObject(hdc, hOldFont));
  104. }
  105. GpFont::GpFont(
  106. HDC hdc,
  107. LOGFONTA *logfont
  108. )
  109. {
  110. SetValid(TRUE); // default is valid
  111. HFONT hOldFont = NULL;
  112. // intialize it as invalid
  113. Family = NULL;
  114. if (!hdc)
  115. return;
  116. HFONT hFont = CreateFontIndirectA(logfont);
  117. if (!hFont)
  118. return;
  119. hOldFont = (HFONT) SelectObject(hdc, hFont);
  120. InitializeFromDc(hdc);
  121. if (!hOldFont)
  122. return;
  123. DeleteObject(SelectObject(hdc, hOldFont));
  124. }
  125. VOID GpFont::InitializeFromDc(
  126. HDC hdc
  127. )
  128. {
  129. WCHAR faceName[LF_FACESIZE];
  130. GpFontTable *fontTable;
  131. fontTable = (GpInstalledFontCollection::GetGpInstalledFontCollection())->GetFontTable();
  132. if (!fontTable->IsValid())
  133. return;
  134. if (!fontTable->IsPrivate() && !fontTable->IsFontLoaded())
  135. fontTable->LoadAllFonts();
  136. if (Globals::IsNt) {
  137. TEXTMETRICW tmw;
  138. if (!GetTextMetricsW(hdc, &tmw)) {
  139. return;
  140. }
  141. GetTextFaceW(hdc, LF_FACESIZE, faceName);
  142. EmSize = REAL(tmw.tmHeight-tmw.tmInternalLeading);
  143. Style = FontStyleRegular;
  144. if (tmw.tmWeight > 400) {Style |= FontStyleBold;}
  145. if (tmw.tmItalic) {Style |= FontStyleItalic;}
  146. if (tmw.tmUnderlined) {Style |= FontStyleUnderline;}
  147. if (tmw.tmStruckOut) {Style |= FontStyleStrikeout;}
  148. }
  149. else
  150. {
  151. TEXTMETRICA tma;
  152. if (!GetTextMetricsA(hdc, &tma)) {
  153. return;
  154. }
  155. char faceNameA[LF_FACESIZE];
  156. GetTextFaceA(hdc, LF_FACESIZE, faceNameA);
  157. AnsiToUnicodeStr(faceNameA, faceName, LF_FACESIZE);
  158. EmSize = REAL(tma.tmHeight-tma.tmInternalLeading);
  159. Style = FontStyleRegular;
  160. if (tma.tmWeight > 400) {Style |= FontStyleBold;}
  161. if (tma.tmItalic) {Style |= FontStyleItalic;}
  162. if (tma.tmUnderlined) {Style |= FontStyleUnderline;}
  163. if (tma.tmStruckOut) {Style |= FontStyleStrikeout;}
  164. }
  165. if (faceName[0] == L'@')
  166. UnicodeStringCopy(&faceName[0], &faceName[1]);
  167. Family = fontTable->GetFontFamily(faceName);
  168. if (Family == NULL)
  169. {
  170. GetFamilySubstitution(faceName, (GpFontFamily **) &Family);
  171. }
  172. if (!(Family && Family->IsFileLoaded()))
  173. Family = NULL;
  174. SizeUnit = UnitWorld;
  175. }
  176. GpStatus GpFont::GetLogFontA(
  177. GpGraphics * g,
  178. LOGFONTA * lfa
  179. )
  180. {
  181. PointF scale;
  182. REAL rotateRadians;
  183. REAL shear;
  184. PointF translate;
  185. GpMatrix worldToDevice;
  186. g->GetWorldToDeviceTransform(&worldToDevice);
  187. SplitTransform(
  188. worldToDevice,
  189. scale,
  190. rotateRadians,
  191. shear,
  192. translate);
  193. INT rotateDeciDegrees = 3600 - (INT) (rotateRadians * 1800 / PI);
  194. if (rotateDeciDegrees == 3600)
  195. rotateDeciDegrees = 0;
  196. REAL emHeight = EmSize * scale.Y * g->GetScaleForAlternatePageUnit(SizeUnit);
  197. lfa->lfHeight = -GpRound(emHeight);
  198. lfa->lfWidth = 0;
  199. lfa->lfEscapement = rotateDeciDegrees;
  200. lfa->lfOrientation = rotateDeciDegrees;
  201. lfa->lfWeight = Style & FontStyleBold ? 700 : 400;
  202. lfa->lfItalic = Style & FontStyleItalic ? 1 : 0;
  203. lfa->lfUnderline = Style & FontStyleUnderline ? 1 : 0;
  204. lfa->lfStrikeOut = Style & FontStyleStrikeout ? 1 : 0;
  205. lfa->lfCharSet = (((GpFontFamily *)Family)->GetFace(Style))->GetCharset(g->GetHdc());
  206. lfa->lfOutPrecision = 0;
  207. lfa->lfClipPrecision = 0;
  208. lfa->lfQuality = 0;
  209. lfa->lfPitchAndFamily = 0;
  210. UnicodeToAnsiStr((WCHAR*)( (BYTE*)(((GpFontFamily *)Family)->GetFace(Style))->pifi +
  211. (((GpFontFamily *)Family)->GetFace(Style))->pifi->dpwszFamilyName),
  212. lfa->lfFaceName, LF_FACESIZE);
  213. // Do we need to have a scale value for width????
  214. // We still need to think about it.
  215. return Ok;
  216. }
  217. GpStatus GpFont::GetLogFontW(
  218. GpGraphics * g,
  219. LOGFONTW * lfw)
  220. {
  221. PointF scale;
  222. REAL rotateRadians;
  223. REAL shear;
  224. PointF translate;
  225. GpMatrix worldToDevice;
  226. g->GetWorldToDeviceTransform(&worldToDevice);
  227. SplitTransform(
  228. worldToDevice,
  229. scale,
  230. rotateRadians,
  231. shear,
  232. translate);
  233. INT rotateDeciDegrees = 3600 - (INT) (rotateRadians * 1800 / PI);
  234. if (rotateDeciDegrees == 3600)
  235. rotateDeciDegrees = 0;
  236. REAL emHeight = EmSize * scale.Y * g->GetScaleForAlternatePageUnit(SizeUnit);
  237. lfw->lfHeight = -GpRound(emHeight);
  238. lfw->lfWidth = 0;
  239. lfw->lfEscapement = rotateDeciDegrees;
  240. lfw->lfOrientation = rotateDeciDegrees;
  241. lfw->lfWeight = Style & FontStyleBold ? 700 : 400;
  242. lfw->lfItalic = Style & FontStyleItalic ? 1 : 0;
  243. lfw->lfUnderline = Style & FontStyleUnderline ? 1 : 0;
  244. lfw->lfStrikeOut = Style & FontStyleStrikeout ? 1 : 0;
  245. ASSERT(((GpFontFamily *)Family)->GetFace(Style));
  246. lfw->lfCharSet = (((GpFontFamily *)Family)->GetFace(Style))->GetCharset(g->GetHdc());
  247. lfw->lfOutPrecision = 0;
  248. lfw->lfClipPrecision = 0;
  249. lfw->lfQuality = 0;
  250. lfw->lfPitchAndFamily = 0;
  251. memcpy(lfw->lfFaceName, (WCHAR*)( (BYTE*)(((GpFontFamily *)Family)->GetFace(Style))->pifi +
  252. (((GpFontFamily *)Family)->GetFace(Style))->pifi->dpwszFamilyName),
  253. sizeof(lfw->lfFaceName));
  254. return Ok;
  255. }
  256. /**************************************************************************\
  257. *
  258. *
  259. * Revision History:
  260. *
  261. * 02/11/1999 YungT
  262. * Created it.
  263. *
  264. \**************************************************************************/
  265. int CALLBACK GpFontFace::EnumFontFamExProcW(
  266. const ENUMLOGFONTEXW *lpelfe, // pointer to logical-font data
  267. const NEWTEXTMETRICEXW *lpntme, // pointer to physical-font data
  268. int FontType, // type of font
  269. LPARAM lParam // application-defined data
  270. )
  271. {
  272. if (FontType == TRUETYPE_FONTTYPE)
  273. {
  274. (*(BYTE *) lParam) = lpelfe->elfLogFont.lfCharSet;
  275. return 0;
  276. }
  277. else
  278. {
  279. return 1; // Don't stop!
  280. }
  281. }
  282. /**************************************************************************\
  283. *
  284. *
  285. * Revision History:
  286. *
  287. * 02/11/1999 YungT
  288. * Created it.
  289. *
  290. \**************************************************************************/
  291. int CALLBACK GpFontFace::EnumFontFamExProcA(
  292. const ENUMLOGFONTEXA *lpelfe, // pointer to logical-font data
  293. const NEWTEXTMETRICEXA *lpntme, // pointer to physical-font data
  294. int FontType, // type of font
  295. LPARAM lParam // application-defined data
  296. )
  297. {
  298. if (FontType == TRUETYPE_FONTTYPE)
  299. {
  300. (*(BYTE *) lParam) = lpelfe->elfLogFont.lfCharSet;
  301. return 0;
  302. }
  303. else
  304. {
  305. return 1; // Don't stop!
  306. }
  307. }
  308. /**************************************************************************\
  309. *
  310. * Function Description:
  311. *
  312. * Get the charset from GDI
  313. *
  314. * Arguments:
  315. *
  316. * We need it for we need to select a logfont into DC. Or
  317. * Convert a GpFont to LOGFONT
  318. *
  319. * Returns:
  320. *
  321. * BYTE value of charset
  322. *
  323. * History:
  324. *
  325. * 02/11/2000 YungT
  326. * Created it.
  327. *
  328. \**************************************************************************/
  329. BYTE GpFontFace::GetCharset(HDC hDc) const
  330. {
  331. if (lfCharset == DEFAULT_CHARSET)
  332. {
  333. if (Globals::IsNt) {
  334. LOGFONTW lfw = {
  335. 0,
  336. 0,
  337. 0,
  338. 0,
  339. 0,
  340. 0,
  341. 0,
  342. 0,
  343. DEFAULT_CHARSET, // charset
  344. 0,
  345. 0,
  346. 0,
  347. 0,
  348. L""
  349. };
  350. memcpy(lfw.lfFaceName, (WCHAR*)( (BYTE*)pifi + pifi->dpwszFamilyName),
  351. sizeof(lfw.lfFaceName));
  352. EnumFontFamiliesExW(hDc, &lfw, (FONTENUMPROCW) EnumFontFamExProcW, (LPARAM) &lfCharset, 0);
  353. }
  354. else
  355. {
  356. // ANSI version for Win9X
  357. LOGFONTA lfa = {
  358. 0,
  359. 0,
  360. 0,
  361. 0,
  362. 0,
  363. 0,
  364. 0,
  365. 0,
  366. DEFAULT_CHARSET, // charset
  367. 0,
  368. 0,
  369. 0,
  370. 0,
  371. ""
  372. };
  373. UnicodeToAnsiStr((WCHAR*)( (BYTE*)pifi + pifi->dpwszFamilyName),
  374. lfa.lfFaceName, LF_FACESIZE);
  375. EnumFontFamiliesExA(hDc, &lfa, (FONTENUMPROCA) EnumFontFamExProcA, (LPARAM) &lfCharset, 0);
  376. }
  377. }
  378. return lfCharset;
  379. }
  380. ///// InitializeImagerTables
  381. //
  382. // Load character to glyph map and design advance widths
  383. static inline
  384. UINT16 byteSwapUINT16(UINT16 u)
  385. {
  386. return ((u & 0x00FF) << 8)
  387. | ((u & 0xFF00) >> 8);
  388. }
  389. #pragma pack(push, 1)
  390. struct HheaTable {
  391. // NOTE: all fields are stored in Big Endian (Motorola) ordering
  392. UINT32 version; // Table version number 0x00010000 for version 1.0.
  393. INT16 Ascender; // Typographic ascent.
  394. INT16 Descender; // Typographic descent.
  395. INT16 LineGap; // Typographic line gap. Negative LineGap values are
  396. // treated as zero in Windows 3.1, System 6, and System 7.
  397. UINT16 advanceWidthMax; // Maximum advance width value in 'hmtx' table.
  398. INT16 minLeftSideBearing; // Minimum left sidebearing value in 'hmtx' table.
  399. INT16 minRightSideBearing; // Minimum right sidebearing value; calculated as Min(aw - lsb - (xMax - xMin)).
  400. INT16 xMaxExtent; // Max(lsb + (xMax - xMin)).
  401. INT16 caretSlopeRise; // Used to calculate the slope of the cursor (rise/run); 1 for vertical.
  402. INT16 caretSlopeRun; // 0 for vertical.
  403. INT16 reserved1; // set to 0
  404. INT16 reserved2; // set to 0
  405. INT16 reserved3; // set to 0
  406. INT16 reserved4; // set to 0
  407. INT16 reserved5; // set to 0
  408. INT16 metricDataFormat; // 0 for current format.
  409. UINT16 numberOfHMetrics; // Number of hMetric entries in 'hmtx' table; must be equal to the CharStrings INDEX count in the 'CFF ' table.
  410. };
  411. struct VheaTable {
  412. // NOTE: all fields are stored in Big Endian (Motorola) ordering
  413. UINT32 version; // Version number of the vertical header table (0x00010000 for the initial version).
  414. INT16 ascent; // Distance in FUnits from the centerline to the previous line's descent.
  415. INT16 descent; // Distance in FUnits from the centerline to the next line's ascent.
  416. INT16 lineGap; // Reserved; set to 0
  417. INT16 advanceHeightMax; // The maximum advance height measurement -in FUnits found in the font.
  418. // This value must be consistent with the entries in the vertical metrics table.
  419. INT16 minTop; // SideBearing The minimum top sidebearing measurement found in the font, in FUnits.
  420. // This value must be consistent with the entries in the vertical metrics table.
  421. INT16 minBottom; // SideBearing The minimum bottom sidebearing measurement found in the font, in FUnits.
  422. // This value must be consistent with the entries in the vertical metrics table.
  423. INT16 yMaxExtent; // Defined as yMaxExtent=minTopSideBearing+(yMax-yMin)
  424. INT16 caretSlopeRise; // The value of the caretSlopeRise field divided by the value of the caretSlopeRun Field
  425. // determines the slope of the caret. A value of 0 for the rise and a value of 1 for the
  426. // run specifies a horizontal caret. A value of 1 for the rise and a value of 0 for the
  427. // run specifies a vertical caret. Intermediate values are desirable for fonts whose
  428. // glyphs are oblique or italic. For a vertical font, a horizontal caret is best.
  429. INT16 caretSlopeRun; // See the caretSlopeRise field. Value=1 for nonslanted vertical fonts.
  430. INT16 caretOffset; // The amount by which the highlight on a slanted glyph needs to be shifted away from
  431. // the glyph in order to produce the best appearance. Set value equal to 0 for nonslanted fonts.
  432. INT16 reserved1; // Set to 0.
  433. INT16 reserved2; // Set to 0.
  434. INT16 reserved3; // Set to 0.
  435. INT16 reserved4; // Set to 0.
  436. INT16 metricDataFormat; // Set to 0.
  437. UINT16 numOfLongVerMetrics; // Number of advance heights in the vertical metrics table; must be equal to the
  438. // CharStrings INDEX count field in the 'CFF ' table.
  439. };
  440. #pragma pack(pop)
  441. GpStatus GpFontFace::GetFontData(UINT32 tag, INT* tableSize, BYTE** pjTable) const
  442. {
  443. GpStatus status = Ok;
  444. ULONG cjTable;
  445. if (ttfdSemGetTrueTypeTable (pff->hff, iFont, tag, pjTable, &cjTable) == FD_ERROR)
  446. {
  447. return GenericError;
  448. }
  449. *tableSize = cjTable;
  450. return status;
  451. }
  452. void GpFontFace::ReleaseFontData() const
  453. {
  454. ttfdSemReleaseTrueTypeTable (pff->hff);
  455. }
  456. ///// GetGlyphDesignAdvances
  457. //
  458. // Returns advance widths along or perpendicular to baseline in
  459. // font design units.
  460. void GpFontFace::GetGlyphDesignAdvances(
  461. const UINT16 *glyphs, // In
  462. INT glyphCount, // In
  463. INT style, // In - causes adjustment for algorithmic style emulation
  464. BOOL vertical, // In - Use vmtx, not hmtx
  465. REAL tracking, // In - expansion factor
  466. UINT16 *advances // Out
  467. ) const
  468. {
  469. if (vertical)
  470. {
  471. if (DesignVerticalAdvance)
  472. {
  473. DesignVerticalAdvance->Lookup(glyphs, glyphCount, advances);
  474. }
  475. else
  476. {
  477. // There's no vmtx - fallback appropriately
  478. // Win 9x uses the typographic height (typo ascender - typo descender),
  479. // but NT uses the cell height (cell ascender + cell descender).
  480. // Which shall we use? The problem with the cell height is that in a
  481. // multilingual font it may be much taller than the Far East glyphs,
  482. // causing the common case (Far East vertical text) to appear too
  483. // widely spaced. The problem with the typographic height is that it
  484. // includes little or no extra space for diacritic marks.
  485. // Choice: use the Typographic height: It is best for FE, and the font
  486. // can fix non FE diacritic cases if it wishes by providing a vmtx.
  487. for (INT i=0; i<glyphCount; i++)
  488. {
  489. advances[i] = pifi->fwdTypoAscender - pifi->fwdTypoDescender;
  490. }
  491. }
  492. }
  493. else
  494. {
  495. DesignAdvance->Lookup(glyphs, glyphCount, advances);
  496. if ( (style & FontStyleBold)
  497. && !(GetFaceStyle() & FontStyleBold))
  498. {
  499. // Algorithmic emboldening increases glyph width
  500. UINT16 extraAdvance = ((pifi->fwdUnitsPerEm * 2 - 1) / 100);
  501. for (INT i=0; i<glyphCount; i++)
  502. {
  503. if (advances[i] != 0)
  504. {
  505. advances[i] += extraAdvance;
  506. }
  507. }
  508. }
  509. if (tracking != 1.0)
  510. {
  511. for (INT i=0; i<glyphCount; i++)
  512. {
  513. advances[i] = static_cast<UINT16>(GpRound(advances[i] * tracking));
  514. }
  515. }
  516. }
  517. }
  518. ///// GetGlyphDesignAdvancesIdeal
  519. //
  520. // Returns advance widths along or perpendicular to baseline scaled to
  521. // ideal units.
  522. void GpFontFace::GetGlyphDesignAdvancesIdeal(
  523. const UINT16 *glyphs, // In
  524. INT glyphCount, // In
  525. INT style, // In - Causes adjustment for algorithmic style emulation
  526. BOOL vertical, // In - Use vtmx, not htmx
  527. REAL designToIdeal, // In - Scale factor for each advance width
  528. REAL tracking, // In - Expansion factor
  529. INT *advances // Out
  530. ) const
  531. {
  532. if (vertical)
  533. {
  534. if (DesignVerticalAdvance)
  535. {
  536. for (INT i=0; i<glyphCount; i++)
  537. {
  538. advances[i] = GpRound(TOREAL(DesignVerticalAdvance->Lookup(glyphs[i]) * designToIdeal));
  539. }
  540. }
  541. else
  542. {
  543. INT commonVerticalAdvance = GpRound(TOREAL(
  544. //(pifi->fwdMacAscender - pifi->fwdMacDescender)
  545. pifi->fwdUnitsPerEm
  546. * designToIdeal
  547. ));
  548. for (INT i=0; i<glyphCount; i++)
  549. {
  550. advances[i] = commonVerticalAdvance;
  551. }
  552. }
  553. }
  554. else
  555. {
  556. // Horizontal advance width
  557. for (INT i=0; i<glyphCount; i++)
  558. {
  559. advances[i] = GpRound(TOREAL(DesignAdvance->Lookup(glyphs[i]) * designToIdeal * tracking));
  560. }
  561. if ( (style & FontStyleBold)
  562. && !(GetFaceStyle() & FontStyleBold))
  563. {
  564. // Algorithmic emboldening increases glyph width
  565. UINT16 extraAdvance = ((pifi->fwdUnitsPerEm * 2 - 1) / 100);
  566. for (INT i=0; i<glyphCount; i++)
  567. {
  568. if (advances[i] != 0)
  569. {
  570. advances[i] += extraAdvance;
  571. }
  572. }
  573. }
  574. }
  575. }
  576. BOOL GpFontFace::IsCodePageSupported(UINT codePage)
  577. {
  578. switch (codePage)
  579. {
  580. case 1252:
  581. return SupportedCodePages & Latine1CodePageMask ? TRUE : FALSE;
  582. break;
  583. case 1250:
  584. return SupportedCodePages & Latine2CodePageMask ? TRUE : FALSE;
  585. break;
  586. case 1251:
  587. return SupportedCodePages & CyrillicCodePageMask ? TRUE : FALSE;
  588. break;
  589. case 1253:
  590. return SupportedCodePages & GreekCodePageMask ? TRUE : FALSE;
  591. break;
  592. case 1254:
  593. return SupportedCodePages & TurkishCodePageMask ? TRUE : FALSE;
  594. break;
  595. case 1255:
  596. return SupportedCodePages & HebrewCodePageMask ? TRUE : FALSE;
  597. break;
  598. case 1256:
  599. return SupportedCodePages & ArabicCodePageMask ? TRUE : FALSE;
  600. break;
  601. case 1257:
  602. return SupportedCodePages & BalticCodePageMask ? TRUE : FALSE;
  603. break;
  604. case 874:
  605. return SupportedCodePages & ThaiCodePageMask ? TRUE : FALSE;
  606. break;
  607. case 932:
  608. return SupportedCodePages & JapanCodePageMask ? TRUE : FALSE;
  609. break;
  610. case 936:
  611. return SupportedCodePages & ChineseCodePageMask ? TRUE : FALSE;
  612. break;
  613. case 949:
  614. return SupportedCodePages & KoreanCodePageMask ? TRUE : FALSE;
  615. break;
  616. case 950:
  617. return SupportedCodePages & TraditionalChineseCodePageMask ? TRUE : FALSE;
  618. break;
  619. case 1361:
  620. return SupportedCodePages & KoreanJohabCodePageMask? TRUE : FALSE;
  621. break;
  622. case 869:
  623. return SupportedCodePages & IBMGreekCodePageMask ? TRUE : FALSE;
  624. break;
  625. case 866:
  626. return SupportedCodePages & RussianMsDosCodePageMask ? TRUE : FALSE;
  627. break;
  628. case 865:
  629. return SupportedCodePages & NordicCodePageMask ? TRUE : FALSE;
  630. break;
  631. case 864:
  632. return SupportedCodePages & ArabicMsDosCodePageMask ? TRUE : FALSE;
  633. break;
  634. case 863:
  635. return SupportedCodePages & CanandianMsDosCodePageMask ? TRUE : FALSE;
  636. break;
  637. case 862:
  638. return SupportedCodePages & HebrewMsDosCodePageMask ? TRUE : FALSE;
  639. break;
  640. case 861:
  641. return SupportedCodePages & IcelandicMsDosCodePageMask ? TRUE : FALSE;
  642. break;
  643. case 860:
  644. return SupportedCodePages & PortugueseMsDosCodePageMask ? TRUE : FALSE;
  645. break;
  646. case 857:
  647. return SupportedCodePages & IBMTurkishCodePageMask ? TRUE : FALSE;
  648. break;
  649. case 855:
  650. return SupportedCodePages & IBMCyrillicCodePageMask ? TRUE : FALSE;
  651. break;
  652. case 852:
  653. return SupportedCodePages & Latin2MsDosCodePageMask ? TRUE : FALSE;
  654. break;
  655. case 775:
  656. return SupportedCodePages & BalticMsDosCodePageMask ? TRUE : FALSE;
  657. break;
  658. case 737:
  659. return SupportedCodePages & Greek437CodePageMask ? TRUE : FALSE;
  660. break;
  661. case 708:
  662. return SupportedCodePages & ArabicAsmoCodePageMask ? TRUE : FALSE;
  663. break;
  664. case 850:
  665. return SupportedCodePages & WeLatinCodePageMask ? TRUE : FALSE;
  666. break;
  667. case 437:
  668. return SupportedCodePages & USCodePageMask ? TRUE : FALSE;
  669. break;
  670. }
  671. return FALSE;
  672. }
  673. static inline UINT16 MapGetUINT16(UINT16 *p, Status* pStatus)
  674. {
  675. UINT16 r;
  676. __try
  677. {
  678. r = *p;
  679. }
  680. __except (EXCEPTION_EXECUTE_HANDLER)
  681. {
  682. *pStatus = GenericError;
  683. }
  684. return r;
  685. }
  686. BOOL GpFontFace::InitializeImagerTables()
  687. {
  688. // MissingGlyph Should be initialized before calling Shaping.Create()
  689. // because it depends on it.
  690. MissingGlyph = 0; // !!! Not true for all FE fonts
  691. // We goining to initialize it correctly in shaping.cpp
  692. SupportedCodePages = 0;
  693. // Initialise tables to default values
  694. Cmap = 0;
  695. DesignAdvance = 0;
  696. DesignVerticalAdvance = NULL;
  697. DesignTopSidebearing = NULL;
  698. MissingGlyph = 0; // !!! Not true for all FE fonts
  699. BlankGlyph = 0;
  700. RequiresFullText = FALSE;
  701. Shaping.Cache = NULL;
  702. Gsub = NULL;
  703. Mort = NULL;
  704. Gpos = NULL;
  705. Gdef = NULL;
  706. VerticalSubstitutionCount = 0;
  707. VerticalSubstitutionOriginals = NULL;
  708. VerticalSubstitutionSubstitutions = NULL;
  709. BYTE * hheaTable = 0;
  710. INT hheaLength = 0;
  711. if (GetFontData('aehh', &hheaLength, &hheaTable) != Ok)
  712. {
  713. return FALSE;
  714. }
  715. // from now on we can't return early, because we need to release font data in the end of the function
  716. GpStatus status = Ok;
  717. Cmap = new IntMap<UINT16>;
  718. if (!Cmap)
  719. status = OutOfMemory;
  720. else
  721. status = Cmap->GetStatus();
  722. if (status == Ok)
  723. {
  724. DesignAdvance = new IntMap<UINT16>;
  725. if (!DesignAdvance)
  726. status = OutOfMemory;
  727. else
  728. status = DesignAdvance->GetStatus();
  729. }
  730. /// Load CMAP
  731. //
  732. //
  733. if (status == Ok)
  734. {
  735. INT cmapLength = 0;
  736. BYTE *cmapTable = 0;
  737. if (Cmap &&
  738. GetFontData('pamc', &cmapLength, &cmapTable) == Ok)
  739. {
  740. AutoArray<BYTE> cmapCopy(new BYTE [cmapLength]); // copy of cmap table
  741. if (!cmapCopy)
  742. status = OutOfMemory;
  743. else
  744. MapCopy (cmapCopy.Get(), cmapTable, cmapLength, &status);
  745. ReleaseFontData(); // deref cmap
  746. if (status == Ok)
  747. {
  748. bSymbol = FALSE;
  749. status = ReadCmap(cmapCopy.Get(), cmapLength, Cmap, &bSymbol);
  750. // !!! Fix up CMAP for special font types here
  751. // We fallback to Microsoft Sans serif for Arabic scripts which does not have
  752. // a glyph for Arabic percent sign (before Whistler)
  753. // We replace its glyph with the Latin precent sign.
  754. if (status == Ok &&
  755. !UnicodeStringCompareCI((PWSTR)((BYTE*)pifi + pifi->dpwszFamilyName),L"Microsoft Sans Serif") &&
  756. Cmap->Lookup(0x066A) == 0)
  757. {
  758. status = Cmap->Insert(0x066A, Cmap->Lookup(0x0025));
  759. }
  760. }
  761. }
  762. }
  763. /// Load horizontal metrics
  764. //
  765. //
  766. if (status == Ok)
  767. {
  768. INT hmtxLength = 0;
  769. BYTE *hmtxTable = 0;
  770. if (DesignAdvance &&
  771. GetFontData('xtmh', &hmtxLength, &hmtxTable) == Ok)
  772. {
  773. AutoArray<BYTE> hmtxCopy(new BYTE [hmtxLength]); // copy of hmtx table
  774. // Copy the hmtx so we can party on it (byte swap for example)
  775. if (!hmtxCopy)
  776. status = OutOfMemory;
  777. else
  778. MapCopy (hmtxCopy.Get(), hmtxTable, hmtxLength, &status);
  779. ReleaseFontData(); // deref hmtx
  780. if (status == Ok)
  781. {
  782. UINT16 numberOfHMetrics = MapGetUINT16(
  783. &((HheaTable *)hheaTable)->numberOfHMetrics,
  784. &status);
  785. if (status == Ok)
  786. status = ReadMtx(
  787. hmtxCopy.Get(),
  788. hmtxLength,
  789. NumGlyphs,
  790. byteSwapUINT16(numberOfHMetrics),
  791. DesignAdvance
  792. );
  793. }
  794. }
  795. }
  796. /// Load vertical metrics, if any
  797. //
  798. //
  799. if (status == Ok)
  800. {
  801. BYTE *vheaTable = 0;
  802. INT vheaLength = 0;
  803. if (GetFontData('aehv', &vheaLength, &vheaTable) == Ok)
  804. {
  805. INT vmtxLength = 0;
  806. BYTE *vmtxTable = 0;
  807. if (GetFontData('xtmv', &vmtxLength, &vmtxTable) == Ok)
  808. {
  809. AutoArray<BYTE> vmtxCopy(new BYTE [vmtxLength]); // copy of vmtx table
  810. if (!vmtxCopy)
  811. status = OutOfMemory;
  812. else
  813. MapCopy (vmtxCopy.Get(), vmtxTable, vmtxLength, &status);
  814. ReleaseFontData(); // deref vmtx
  815. if (status == Ok)
  816. {
  817. UINT16 numOfLongVerMetrics = MapGetUINT16(
  818. &((VheaTable *)vheaTable)->numOfLongVerMetrics,
  819. &status);
  820. if (status == Ok)
  821. {
  822. numOfLongVerMetrics = byteSwapUINT16(numOfLongVerMetrics);
  823. DesignVerticalAdvance = new IntMap<UINT16>;
  824. if (!DesignVerticalAdvance)
  825. status = OutOfMemory;
  826. else
  827. {
  828. status = ReadMtx(
  829. vmtxCopy.Get(),
  830. vmtxLength,
  831. NumGlyphs,
  832. numOfLongVerMetrics,
  833. DesignVerticalAdvance
  834. );
  835. }
  836. if (status == Ok)
  837. {
  838. DesignTopSidebearing = new IntMap<UINT16>;
  839. if (!DesignTopSidebearing)
  840. status = OutOfMemory;
  841. else
  842. {
  843. status = ReadMtxSidebearing(
  844. vmtxCopy.Get(),
  845. vmtxLength,
  846. NumGlyphs,
  847. numOfLongVerMetrics,
  848. DesignTopSidebearing
  849. );
  850. }
  851. }
  852. }
  853. }
  854. }
  855. ReleaseFontData(); // deref vhea
  856. }
  857. }
  858. /// Load OTL tables
  859. //
  860. //
  861. if (status == Ok)
  862. {
  863. INT tableSize = 0;
  864. BYTE *tableAddress = 0;
  865. if (GetFontData('BUSG', &tableSize, &tableAddress) == Ok) // GSUB
  866. {
  867. Gsub = new BYTE[tableSize];
  868. if (!Gsub)
  869. status = OutOfMemory;
  870. else
  871. {
  872. MapCopy(Gsub, tableAddress, tableSize, &status);
  873. // Override the table first fix32 version field to our own use,
  874. // it now contains the size of each table in byte.
  875. ((UINT32 *)Gsub)[0] = tableSize;
  876. }
  877. ReleaseFontData();
  878. }
  879. else
  880. {
  881. if (GetFontData('trom', &tableSize, &tableAddress) == Ok) // mort
  882. {
  883. Mort = new BYTE[tableSize];
  884. if (!Mort)
  885. status = OutOfMemory;
  886. else
  887. {
  888. MapCopy(Mort, tableAddress, tableSize, &status);
  889. // Override the table first fix32 version field to our own use,
  890. // it now contains the size of each table in byte.
  891. ((UINT32 *)Mort)[0] = tableSize;
  892. }
  893. ReleaseFontData();
  894. }
  895. }
  896. if (status == Ok && GetFontData('SOPG', &tableSize, &tableAddress) == Ok) // GPOS
  897. {
  898. Gpos = new BYTE[tableSize];
  899. if (!Gpos)
  900. status = OutOfMemory;
  901. else
  902. {
  903. MapCopy(Gpos, tableAddress, tableSize, &status);
  904. ((UINT32 *)Gpos)[0] = tableSize;
  905. }
  906. ReleaseFontData();
  907. }
  908. if (status == Ok && GetFontData('FEDG', &tableSize, &tableAddress) == Ok) // GDEF
  909. {
  910. Gdef = new BYTE[tableSize];
  911. if (!Gdef)
  912. status = OutOfMemory;
  913. else
  914. {
  915. MapCopy(Gdef, tableAddress, tableSize, &status);
  916. ((UINT32 *)Gdef)[0] = tableSize;
  917. }
  918. ReleaseFontData();
  919. }
  920. if (status == Ok)
  921. {
  922. if (Gsub)
  923. {
  924. // Get address of vertical substitution info, if any
  925. LoadVerticalSubstitution(
  926. Gsub,
  927. &VerticalSubstitutionCount,
  928. &VerticalSubstitutionOriginals,
  929. &VerticalSubstitutionSubstitutions
  930. );
  931. }
  932. else if (Mort)
  933. {
  934. LoadMortVerticalSubstitution(
  935. Mort,
  936. &VerticalSubstitutionCount,
  937. &VerticalSubstitutionOriginals,
  938. &VerticalSubstitutionSubstitutions
  939. );
  940. }
  941. }
  942. }
  943. /// Build shaping cache
  944. //
  945. //
  946. if (status == Ok)
  947. status = Shaping.Create(this);
  948. if (status == Ok)
  949. BlankGlyph = Cmap->Lookup(' ');
  950. // All done
  951. ReleaseFontData(); // deref hhea
  952. if (status != Ok)
  953. {
  954. FreeImagerTables();
  955. return FALSE;
  956. }
  957. return TRUE;
  958. }
  959. void GpFontFace::FreeImagerTables()
  960. {
  961. delete Cmap, Cmap = NULL;
  962. delete DesignAdvance, DesignAdvance = NULL;
  963. Shaping.Destroy();
  964. delete DesignVerticalAdvance, DesignVerticalAdvance = NULL;
  965. delete DesignTopSidebearing, DesignTopSidebearing = NULL;
  966. delete [] Gsub, Gsub = NULL;
  967. delete [] Mort, Mort = NULL;
  968. delete [] Gpos, Gpos = NULL;
  969. delete [] Gdef, Gdef = NULL;
  970. } // GpFontFace::FreeImagerTables
  971. GpStatus
  972. GpGlyphPath::CopyPath(GpPath *path)
  973. {
  974. ASSERT(path->IsValid());
  975. INT count;
  976. curveCount = path->GetSubpathCount();
  977. hasBezier = path->HasCurve();
  978. pointCount = count = path->GetPointCount();
  979. if (count)
  980. {
  981. points = (GpPointF*) ((BYTE*)this + sizeof(GpGlyphPath));
  982. types = (BYTE*) ((BYTE*)points + sizeof(GpPointF) * count);
  983. const GpPointF *pathPoints = path->GetPathPoints();
  984. const BYTE *pathTypes = path->GetPathTypes();
  985. GpMemcpy(points, pathPoints, count * sizeof(GpPointF));
  986. GpMemcpy(types, pathTypes, count * sizeof(BYTE));
  987. }
  988. else // 'blank' glyph
  989. {
  990. points = NULL;
  991. types = NULL;
  992. }
  993. return Ok;
  994. }
  995. ///// GetHeight
  996. //
  997. // Returns height in world units for a given graphics. If graphics passed
  998. // as NULL works as if passed a graphics derived from GetDC(NULL).
  999. GpStatus
  1000. GpFont::GetHeightAtWorldEmSize(REAL worldEmSize, REAL *height) const
  1001. {
  1002. const GpFontFace *face = Family->GetFace(Style);
  1003. if (!face)
  1004. {
  1005. return InvalidParameter;
  1006. }
  1007. *height = TOREAL(worldEmSize * face->GetDesignLineSpacing()
  1008. / face->GetDesignEmHeight());
  1009. return Ok;
  1010. }
  1011. GpStatus
  1012. GpFont::GetHeight(REAL dpi, REAL *height) const
  1013. {
  1014. REAL worldEmSize = EmSize;
  1015. switch (SizeUnit)
  1016. {
  1017. case UnitPoint: worldEmSize = EmSize * dpi / 72.0f; break;
  1018. case UnitInch: worldEmSize = EmSize * dpi; break;
  1019. case UnitDocument: worldEmSize = EmSize * dpi / 300.0f; break;
  1020. case UnitMillimeter: worldEmSize = EmSize * dpi / 25.4f; break;
  1021. }
  1022. return GetHeightAtWorldEmSize(worldEmSize, height);
  1023. }
  1024. GpStatus
  1025. GpFont::GetHeight(const GpGraphics *graphics, REAL *height) const
  1026. {
  1027. REAL worldEmSize = EmSize
  1028. * graphics->GetScaleForAlternatePageUnit(SizeUnit);
  1029. return GetHeightAtWorldEmSize(worldEmSize, height);
  1030. }
  1031. class FontRecordData : public ObjectData
  1032. {
  1033. public:
  1034. REAL EmSize;
  1035. Unit SizeUnit;
  1036. INT Style;
  1037. UINT Flag;
  1038. UINT Length;
  1039. };
  1040. /**************************************************************************\
  1041. *
  1042. * Function Description:
  1043. *
  1044. * Get the font data.
  1045. *
  1046. * Arguments:
  1047. *
  1048. * [IN] dataBuffer - fill this buffer with the data
  1049. * [IN/OUT] size - IN - size of buffer; OUT - number bytes written
  1050. *
  1051. * Return Value:
  1052. *
  1053. * GpStatus - Ok or error code
  1054. *
  1055. * Created:
  1056. *
  1057. * 9/13/1999 DCurtis
  1058. *
  1059. \**************************************************************************/
  1060. GpStatus
  1061. GpFont::GetData(
  1062. IStream * stream
  1063. ) const
  1064. {
  1065. ASSERT (stream != NULL);
  1066. WCHAR * familyName = const_cast<WCHAR *>((const_cast<GpFontFamily *>(Family))->GetCaptializedName());
  1067. UINT length = 0;
  1068. if (familyName)
  1069. {
  1070. length = UnicodeStringLength(familyName);
  1071. }
  1072. FontRecordData fontData;
  1073. fontData.EmSize = EmSize;
  1074. fontData.SizeUnit = SizeUnit;
  1075. fontData.Style = Style;
  1076. // !!! For now, we assume the next block of bytes is the
  1077. // family name (flag == 0). In the future, we need to handle
  1078. // memory images (flag == 1).
  1079. fontData.Flag = 0;
  1080. fontData.Length = length;
  1081. stream->Write(&fontData, sizeof(fontData), NULL);
  1082. stream->Write(familyName, length * sizeof(WCHAR), NULL);
  1083. // align
  1084. if ((length & 0x01) != 0)
  1085. {
  1086. length = 0;
  1087. stream->Write(&length, sizeof(WCHAR), NULL);
  1088. }
  1089. return Ok;
  1090. }
  1091. UINT
  1092. GpFont::GetDataSize() const
  1093. {
  1094. UINT dataSize = sizeof(FontRecordData);
  1095. WCHAR * familyName = const_cast<WCHAR *>((const_cast<GpFontFamily *>(Family))->GetCaptializedName());
  1096. if (familyName)
  1097. {
  1098. dataSize += (UnicodeStringLength(familyName) * sizeof(WCHAR));
  1099. }
  1100. return ((dataSize + 3) & (~3)); // align
  1101. }
  1102. /**************************************************************************\
  1103. *
  1104. * Function Description:
  1105. *
  1106. * Read the font object from memory.
  1107. *
  1108. * Arguments:
  1109. *
  1110. * [IN] dataBuffer - the data that was read from the stream
  1111. * [IN] size - the size of the data
  1112. *
  1113. * Return Value:
  1114. *
  1115. * GpStatus - Ok or failure status
  1116. *
  1117. * Created:
  1118. *
  1119. * 4/26/1999 DCurtis
  1120. *
  1121. \**************************************************************************/
  1122. GpStatus
  1123. GpFont::SetData(
  1124. const BYTE * dataBuffer,
  1125. UINT size
  1126. )
  1127. {
  1128. if ((dataBuffer == NULL) || (size < sizeof(FontRecordData)))
  1129. {
  1130. WARNING(("dataBuffer is NULL or size is too small"));
  1131. return InvalidParameter;
  1132. }
  1133. UINT flag;
  1134. UINT length;
  1135. WCHAR familyName[FamilyNameMax];
  1136. const FontRecordData * fontData = (const FontRecordData *)dataBuffer;
  1137. if (!fontData->MajorVersionMatches())
  1138. {
  1139. WARNING(("Version number mismatch"));
  1140. return InvalidParameter;
  1141. }
  1142. EmSize = fontData->EmSize;
  1143. SizeUnit = fontData->SizeUnit;
  1144. Style = fontData->Style;
  1145. length = fontData->Length;
  1146. dataBuffer += sizeof(FontRecordData);
  1147. if (size < (sizeof(FontRecordData) + (length * sizeof(WCHAR))))
  1148. {
  1149. WARNING(("size is too small"));
  1150. return InvalidParameter;
  1151. }
  1152. // !!! For now, we assume the next block of bytes is the
  1153. // family name (flag == 0). In the future, we need to handle
  1154. // memory images (flag == 1).
  1155. if (length > FamilyNameMax)
  1156. {
  1157. length = FamilyNameMax;
  1158. }
  1159. // read in the familyName/data
  1160. UnicodeStringCopyCount (familyName,
  1161. (WCHAR *)dataBuffer,
  1162. length);
  1163. familyName[length] = 0;
  1164. // !!! For now, we assume that the font family comes from
  1165. // the installed font collection
  1166. //
  1167. // also make sure the font table is loaded the application may play
  1168. // the meta file before loading the font table.
  1169. GpFontTable *fontTable = Globals::FontCollection->GetFontTable();
  1170. if (!fontTable->IsValid())
  1171. return OutOfMemory;
  1172. if (!fontTable->IsPrivate() && !fontTable->IsFontLoaded())
  1173. fontTable->LoadAllFonts();
  1174. Family = fontTable->GetFontFamily(familyName);
  1175. if (Family == NULL)
  1176. {
  1177. GpStatus status = GpFontFamily::GetGenericFontFamilySansSerif((GpFontFamily **) &Family);
  1178. if (status != Ok)
  1179. {
  1180. Family = NULL;
  1181. return status;
  1182. }
  1183. }
  1184. if (!(Family && Family->IsFileLoaded()))
  1185. {
  1186. Family = NULL;
  1187. }
  1188. if (Family == NULL)
  1189. {
  1190. return GenericError;
  1191. }
  1192. UpdateUid();
  1193. return Ok;
  1194. }