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.

4768 lines
156 KiB

  1. /*
  2. * Adobe Universal Font Library
  3. *
  4. * Copyright (c) 1996 Adobe Systems Inc.
  5. * All Rights Reserved
  6. *
  7. * UFOT42.c
  8. *
  9. *
  10. * $Header:
  11. */
  12. /*===============================================================================*
  13. * Include files used by this interface *
  14. *===============================================================================*/
  15. #include "UFLPriv.h"
  16. #include "UFOT42.h"
  17. #include "UFLMem.h"
  18. #include "UFLMath.h"
  19. #include "UFLStd.h"
  20. #include "UFLErr.h"
  21. #include "UFLPS.h"
  22. #include "ParseTT.h"
  23. #include "UFLVm.h"
  24. #include "ttformat.h"
  25. /*
  26. * Private function prototypes
  27. */
  28. UFLErrCode
  29. T42VMNeeded(
  30. UFOStruct *pUFObj,
  31. const UFLGlyphsInfo *pGlyphs,
  32. unsigned long *pVMNeeded,
  33. unsigned long *pFCNeeded
  34. );
  35. UFLErrCode
  36. T42FontDownloadIncr(
  37. UFOStruct *pUFObj,
  38. const UFLGlyphsInfo *pGlyphs,
  39. unsigned long *pVMUsage,
  40. unsigned long *pFCUsage
  41. );
  42. UFLErrCode
  43. T42UndefineFont(
  44. UFOStruct *pUFObj
  45. );
  46. UFLErrCode
  47. DefaultGetRotatedGIDs(
  48. UFOStruct *pUFObj,
  49. T42FontStruct *pFont,
  50. UFLFontProcs *pFontProcs
  51. );
  52. static unsigned long
  53. GetLenByScanLoca(
  54. void PTR_PREFIX *locationTable,
  55. unsigned short wGlyfIndex,
  56. unsigned long cNumGlyphs,
  57. int iLongFormat
  58. );
  59. /*=============================================================================
  60. TrueType Table Description
  61. cmap - This table defines the mapping of character codes to the glyph index
  62. values used in the font. It may contain more than one subtable, in
  63. order to support more than one character encoding scheme. Character
  64. codes that do not correspond to any glyph in the font should be
  65. mapped to glyph index 0. The glyph at this location must be a
  66. special glyph representing a missing character.
  67. cvt - This table contains a list of values that can be referenced by
  68. instructions. They can be used, among other things, to control
  69. characteristics for different glyphs.
  70. fpgm - This table is similar to the CVT Program, except that it is only run
  71. once, when the font is first used. It is used only for FDEFs and
  72. IDEFs. Thus the CVT Program need not contain function definitions.
  73. However, the CVT Program may redefine existing FDEFs or IDEFs.
  74. FDEFS - Functional defs. IDEFs - Intruction defs.
  75. glyf - This table contains information that describes the glyphs in the font.
  76. head - This table gives global information about the font.
  77. Table version number 0x00010000 for version 1.0.
  78. FIXED fontRevision Set by font manufacturer.
  79. ULONG checkSumAdjustment To compute: set it to 0, sum
  80. the entire font as ULONG, then
  81. store 0xB1B0AFBA - sum.
  82. ULONG magicNumber Set to 0x5F0F3CF5.
  83. USHORT flags Bit 0 - baseline for font at y=0
  84. Bit 1 - left sidebearing at x=0
  85. Bit 2 - instructions may depend
  86. on point size
  87. Bit 3 - force ppem to integer
  88. values for all internal
  89. scaler math; may use
  90. fractional ppem sizes
  91. if this bit is clear
  92. USHORT unitsPerEm Valid range is from 16 to 16384
  93. longDateTime created International date (8-byte field).
  94. longDateTime modified International date (8-byte field).
  95. FWORD xMin For all glyph bounding boxes.
  96. FWORD yMin For all glyph bounding boxes.
  97. FWORD xMax For all glyph bounding boxes.
  98. FWORD yMax For all glyph bounding boxes.
  99. USHORT macStyle Bit 0 bold (if set to 1)
  100. Bit 1 italic (if set to 1)
  101. Bits 2-15 reserved (set to 0).
  102. USHORT lowestRecPPEM Smallest readable size in pixels.
  103. SHORT fontDirectionHint 0 Fully mixed directional glyphs
  104. 1 Only strongly left to right
  105. 2 Like 1 but also contains neutrals1
  106. -1 Only strongly right to left
  107. -2 Like -1 but also contains neutrals.
  108. SHORT indexToLocFormat 0 for short offsets, 1 for long.
  109. SHORT glyphDataFormat 0 for current format.
  110. hhea - This table contains information for horizontal layout.
  111. Type Name Description
  112. FIXED Table version number 0x00010000 for version 1.0.
  113. FWORD Ascender Typographic ascent.
  114. FWORD Descender Typographic descent.
  115. FWORD LineGap Typographic line gap. Negative
  116. LineGap values are treated as zero
  117. in Windows 3.1, System 6, and System 7.
  118. UFWORD advanceWidthMax Maximum advance width value in hmtx table.
  119. FWORD minLeftSideBearing Minimum left sidebearing value in hmtx table.
  120. FWORD minRightSideBearing Minimum right sidebearing value.
  121. Calculated as Min(aw - lsb - (xMax - xMin)).
  122. FWORD xMaxExtent Max(lsb + (xMax - xMin)).
  123. SHORT caretSlopeRise Used to calculate the slope of the
  124. cursor (rise/run); 1 for vertical.
  125. SHORT caretSlopeRun 0 for vertical.
  126. SHORT (reserved) set to 0
  127. SHORT (reserved) set to 0
  128. SHORT (reserved) set to 0
  129. SHORT (reserved) set to 0
  130. SHORT (reserved) set to 0
  131. SHORT metricDataFormat 0 for current format.
  132. USHORT numberOfHMetrics Number of hMetric entries in hmtx
  133. table; may be smaller than the total
  134. number of glyphs in the font.
  135. hmtx - Horizontal metrics
  136. loca - The indexToLoc table stores the offsets to the locations of the
  137. glyphs in the font, relative to the beginning of the glyphData
  138. table. In order to compute the length of the last glyph element,
  139. there is an extra entry after the last valid index. By definition,
  140. index zero points to the missing character, which is the character
  141. that appears if a character is not found in the font. The missing
  142. character is commonly represented by a blank box or a space. If the
  143. font does not contain an outline for the missing character, then the
  144. first and second offsets should have the same value. This also
  145. applies to any other character without an outline, such as the space
  146. character. Most routines will look at the 'maxp' table to determine
  147. the number of glyphs in the font, but the value in the loca table
  148. should agree. There are two versions of this table, the short and
  149. the long. The version is specified in the indexToLocFormat entry in
  150. the head' table.
  151. maxp - This table establishes the memory requirements for this font.
  152. Type Name Description
  153. Fixed Table version number 0x00010000 for version 1.0.
  154. USHORT numGlyphs The number of glyphs in the font.
  155. USHORT maxPoints Maximum points in a non-composite glyph.
  156. USHORT maxContours Maximum contours in a non-composite glyph.
  157. USHORT maxCompositePoints Maximum points in a composite glyph.
  158. USHORT maxCompositeContours Maximum contours in a composite glyph.
  159. USHORT maxZones 1 if instructions do not use the twilight zone (Z0)
  160. 2 if instructions do use Z0
  161. This should be set to 2 in most cases.
  162. USHORT maxTwilightPoints Maximum points used in Z0.
  163. USHORT maxStorage Number of Storage Area locations.
  164. USHORT maxFunctionDefs Number of FDEFs.
  165. USHORT maxInstructionDefs Number of IDEFs.
  166. USHORT maxStackElements Maximum stack depth2.
  167. USHORT maxSizeOfInstructions Maximum byte count for glyph instructions.
  168. USHORT maxComponentElements Maximum number of components
  169. referenced at "top level" for any
  170. composite glyph.
  171. USHORT maxComponentDepth Maximum levels of recursion; 1 for
  172. simple components.
  173. prep - The Control Value Program consists of a set of TrueType instructions
  174. that will be executed whenever the font or point size or
  175. transformation matrix change and before each glyph is interpreted.
  176. Any instruction is legal in the CVT Program but since no glyph is
  177. associated with it, instructions intended to move points within a
  178. particular glyph outline cannot be used in the CVT Program. The name
  179. 'prep' is anachronistic.
  180. ===============================================================================*/
  181. static char *RequiredTables_default[MINIMALNUMBERTABLES] = {
  182. "cvt ",
  183. "fpgm", /* This table is missing from many fonts. */
  184. "glyf",
  185. "head",
  186. "hhea",
  187. "hmtx",
  188. "loca",
  189. "maxp",
  190. "prep"
  191. };
  192. static char *RequiredTables_2015[MINIMALNUMBERTABLES] = {
  193. "cvt ",
  194. "fpgm", /* This table is missing from many fonts. */
  195. "glyf",
  196. "head",
  197. "hhea",
  198. "hmtx",
  199. // "loca", /* This huge table is Not needed on 2015 Pritners. */
  200. "maxp",
  201. "prep",
  202. /* This must be the last (dummy) entry. Don't add anything after this. */
  203. "zzzz"
  204. };
  205. char *gcidSuffix[NUM_CIDSUFFIX] = {
  206. "CID",
  207. "CIDR",
  208. "CID32K",
  209. "CID32KR"
  210. };
  211. static char* RDString = " RDS "; /* Fix bug Adobe #233904 */
  212. typedef struct {
  213. long startU;
  214. long endU;
  215. long startL;
  216. long endL;
  217. } CODERANGE;
  218. typedef struct {
  219. short sMaxCount; // Maximum number of glyphs
  220. short sCount; // Number of glyps we're holding
  221. unsigned short *pGlyphs; // Pointer to array of glyph indices.
  222. } COMPOSITEGLYPHS;
  223. #if 1
  224. static CODERANGE gHalfWidthChars[] = {
  225. {0x0020, 0x007E, 0x20, 0x7E}, /* CJK ASCII chars */
  226. {0xFF60, 0xFF9F, 0x20, 0x5F}, /* 0x20 to 0x5F is made up to make the localcode range the size. */
  227. {0xFFA0, 0xFFDF, 0xA0, 0xDF}, /* HalfWidth J-Katakana and K-Hangul (see Unicode Book P.383) */
  228. {0, 0, 0, 0} /* terminator */
  229. };
  230. #else
  231. /*
  232. * This could be more accurite than the one above. But we don't use this until
  233. * it becomes really necessary.
  234. */
  235. static CODERANGE gHalfWidthChars[] = {
  236. {0x0020, 0x007E, 0x20, 0x7E}, /* ASCII (0x20-0x7E) */
  237. {0xFF61, 0xFF9F, 0xA1, 0xDF}, /* Half-width Katakana (0xA1-0xDF) */
  238. {0xFFA0, 0xFFDC, 0x40, 0x7C}, /* HalfWidth jamo (0x40-0x7C) */
  239. {0, 0, 0, 0} /* terminator */
  240. };
  241. #endif
  242. #define NUM_HALFWIDTHCHARS \
  243. ((short) (gHalfWidthChars[0].endL - gHalfWidthChars[0].startL + 1) + \
  244. (gHalfWidthChars[1].endL - gHalfWidthChars[1].startL + 1) + \
  245. (gHalfWidthChars[2].endL - gHalfWidthChars[2].startL + 1) + \
  246. (gHalfWidthChars[3].endL - gHalfWidthChars[3].startL + 1) + 1 )
  247. /*
  248. * CIDSysInfo "(Adobe) (WinCharSetFFFF) 0" is registered for Win95 driver. Re-use it here.
  249. */
  250. static UFLCMapInfo CMapInfo_FF_H = {"WinCharSetFFFF-H", 1, 0, "Adobe", "WinCharSetFFFF", 0};
  251. static UFLCMapInfo CMapInfo_FF_V = {"WinCharSetFFFF-V", 1, 1, "Adobe", "WinCharSetFFFF", 0};
  252. static UFLCMapInfo CMapInfo_FF_H2 = {"WinCharSetFFFF-H2", 1, 0, "Adobe", "WinCharSetFFFF", 0};
  253. static UFLCMapInfo CMapInfo_FF_V2 = {"WinCharSetFFFF-V2", 1, 1, "Adobe", "WinCharSetFFFF", 0};
  254. #define CIDSUFFIX 0
  255. #define CIDSUFFIX_R 1
  256. #define CIDSUFFIX_32K 2
  257. #define CIDSUFFIX_32KR 3
  258. /* Magic Baseline Numbers: */
  259. #define TT_BASELINE_X "0.15"
  260. #define TT_BASELINE_Y "0.85"
  261. /*
  262. * Function implementations
  263. */
  264. void
  265. T42FontCleanUp(
  266. UFOStruct *pUFObj
  267. )
  268. {
  269. T42FontStruct *pFont;
  270. if (pUFObj->pAFont == nil)
  271. return;
  272. pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  273. if (pFont == nil)
  274. return;
  275. if (pFont->pHeader != nil)
  276. {
  277. UFLDeletePtr(pUFObj->pMem, pFont->pHeader);
  278. pFont->pHeader = nil;
  279. }
  280. if (pFont->pMinSfnt != nil)
  281. {
  282. UFLDeletePtr(pUFObj->pMem, pFont->pMinSfnt);
  283. pFont->pMinSfnt = nil;
  284. }
  285. if (pFont->pStringLength != nil)
  286. {
  287. UFLDeletePtr(pUFObj->pMem, pFont->pStringLength);
  288. pFont->pStringLength = nil;
  289. }
  290. if (pFont->pLocaTable != nil)
  291. {
  292. UFLDeletePtr(pUFObj->pMem, pFont->pLocaTable);
  293. pFont->pLocaTable = nil;
  294. }
  295. if (pFont->pRotatedGlyphIDs != nil)
  296. {
  297. UFLDeletePtr(pUFObj->pMem, pFont->pRotatedGlyphIDs);
  298. pFont->pRotatedGlyphIDs = nil;
  299. }
  300. }
  301. unsigned long
  302. GetFontTable(
  303. UFOStruct *pUFObj,
  304. unsigned long tableName,
  305. unsigned char *pTable,
  306. unsigned long bufferSize // Fixed bug 516514
  307. )
  308. {
  309. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  310. unsigned long tableSize;
  311. /* Get the size of the table. */
  312. tableSize = GETTTFONTDATA(pUFObj,
  313. tableName, 0L,
  314. nil, 0L,
  315. pFont->info.fData.fontIndex);
  316. /* Read the table in. */
  317. if (pTable && tableSize)
  318. {
  319. // Fixed bug 516514. make sure the buffer is big enough
  320. if (tableSize > bufferSize)
  321. tableSize = bufferSize;
  322. tableSize = GETTTFONTDATA(pUFObj,
  323. tableName, 0L,
  324. pTable, tableSize,
  325. pFont->info.fData.fontIndex);
  326. /*
  327. * Special hack to fix #185003 and #308981
  328. * Avoid useless maxSizeOfInstructions check in TrueType rasterizer by
  329. * setting the highest value. maxSizeOfInstructions field in 'maxp'
  330. * table is at byte offset 26 and 27.
  331. */
  332. if (tableName == MAXP_TABLE)
  333. pTable[26] = pTable[27] = 0xff;
  334. }
  335. return tableSize;
  336. }
  337. void *
  338. GetSfntTable(
  339. unsigned char *sfnt,
  340. unsigned long tableName
  341. )
  342. {
  343. TableDirectoryStruct *pTableDirectory = (TableDirectoryStruct *)sfnt;
  344. TableEntryStruct *pTableEntry = (TableEntryStruct *)((char *)pTableDirectory
  345. + sizeof (TableDirectoryStruct));
  346. unsigned short i = 0;
  347. while (i < MOTOROLAINT(pTableDirectory->numTables))
  348. {
  349. if (pTableEntry->tag == tableName)
  350. {
  351. break;
  352. }
  353. else
  354. {
  355. pTableEntry = (TableEntryStruct *)((char *)pTableEntry + sizeof (TableEntryStruct));
  356. i++;
  357. }
  358. }
  359. if (i < MOTOROLAINT(pTableDirectory->numTables))
  360. {
  361. if (pTableEntry->offset)
  362. return (void *)(sfnt + MOTOROLALONG(pTableEntry->offset));
  363. }
  364. return nil;
  365. }
  366. unsigned long
  367. GetTableSize(
  368. UFOStruct *pUFObj,
  369. unsigned char *pHeader,
  370. unsigned long tableName
  371. )
  372. /*++
  373. Routine Description:
  374. This function returns the size of a table within this In-Memory-Version
  375. pHeader if it is present - If Not present, read-in from the orginal font
  376. header - we need this because 'loca' won't be in pHeader for CID/42, but
  377. we need its size!.
  378. --*/
  379. {
  380. TableDirectoryStruct *pTableDirectory = (TableDirectoryStruct *)pHeader;
  381. TableEntryStruct *pTableEntry = (TableEntryStruct *)((char *)pTableDirectory
  382. + sizeof (TableDirectoryStruct));
  383. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  384. unsigned short i;
  385. for (i = 0; i < MOTOROLAINT(pTableDirectory->numTables); i++)
  386. {
  387. if (pTableEntry->tag == tableName)
  388. break;
  389. else
  390. pTableEntry = (TableEntryStruct *)((char *)pTableEntry + sizeof (TableEntryStruct));
  391. }
  392. //
  393. // 'loca' table can be 0 length in 'sfnts': just get it from the font.
  394. // Bug 229911 ang 9/12/97
  395. //
  396. if ((i < MOTOROLAINT(pTableDirectory->numTables))
  397. && ((unsigned long)MOTOROLALONG(pTableEntry->length) > 0))
  398. {
  399. return ((unsigned long)MOTOROLALONG(pTableEntry->length));
  400. }
  401. else
  402. {
  403. //
  404. // We don't have this table in pHeader. So find out the size from
  405. // orignal font file.
  406. //
  407. return GETTTFONTDATA(pUFObj,
  408. tableName, 0L,
  409. nil, 0L,
  410. pFont->info.fData.fontIndex);
  411. }
  412. }
  413. unsigned long
  414. GetGlyphTableSize(
  415. UFOStruct *pUFObj
  416. )
  417. {
  418. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  419. return GetTableSize(pUFObj, pFont->pHeader, GLYF_TABLE);
  420. }
  421. unsigned long
  422. GetTableDirectory(
  423. UFOStruct *pUFObj,
  424. TableDirectoryStruct *pTableDir
  425. )
  426. {
  427. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  428. unsigned long size = sizeof (TableDirectoryStruct);
  429. if (pTableDir == 0)
  430. return size; /* Return the size only. */
  431. /*
  432. * TTCHeader or TableDirectoryStruct starts from the beginning of the font
  433. * file.
  434. */
  435. size = GETTTFONTDATA(pUFObj,
  436. nil, 0L,
  437. pTableDir, sizeof (TableDirectoryStruct),
  438. 0);
  439. /*
  440. * Check if this is a TTC file - only uses first 4 bytes of pTableDIR.
  441. */
  442. if (BIsTTCFont(*((unsigned long *)((char *)pTableDir))))
  443. {
  444. /* Parse TTCHeader to get correct offsetToTableDir from fontIndex. */
  445. size = pFont->info.fData.offsetToTableDir
  446. = GetOffsetToTableDirInTTC(pUFObj, pFont->info.fData.fontIndex);
  447. if (size > 0)
  448. {
  449. /* Now get the correct TableDirectory from the TTC file. */
  450. size = GETTTFONTDATA(pUFObj,
  451. nil, pFont->info.fData.offsetToTableDir,
  452. pTableDir, sizeof (TableDirectoryStruct),
  453. pFont->info.fData.fontIndex);
  454. }
  455. }
  456. /*
  457. * Do some basic check - better fail than crash. NumTables must be
  458. * reasonable.
  459. */
  460. if ((MOTOROLAINT(pTableDir->numTables) < 3)
  461. || (MOTOROLAINT(pTableDir->numTables) > 50))
  462. {
  463. return 0;
  464. }
  465. return size;
  466. }
  467. unsigned long
  468. GetTableEntry(
  469. UFOStruct *pUFObj,
  470. TableEntryStruct *pTableEntry,
  471. TableDirectoryStruct *pTableDir
  472. )
  473. {
  474. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  475. unsigned long size;
  476. if (pTableDir == 0)
  477. return 0; /* We need the TableDirectoryStruct to get the entry. */
  478. size = MOTOROLAINT(pTableDir->numTables) * sizeof (TableEntryStruct);
  479. if (pTableEntry == 0)
  480. return size; /* Return the size only. */
  481. /* TableEntryStruct starts right after the TableDirectory. */
  482. size = GETTTFONTDATA(pUFObj,
  483. nil, pFont->info.fData.offsetToTableDir + sizeof (TableDirectoryStruct),
  484. pTableEntry, size,
  485. pFont->info.fData.fontIndex);
  486. return size;
  487. }
  488. unsigned long
  489. GetFontHeaderSize(
  490. UFOStruct *pUFObj
  491. )
  492. {
  493. TableDirectoryStruct tableDir;
  494. unsigned long size;
  495. /* Need to fill in tableDir for GetTableEntry(). */
  496. size = GetTableDirectory(pUFObj, &tableDir);
  497. if (size != 0)
  498. size += GetTableEntry(pUFObj, 0, &tableDir); /* Get size only. */
  499. return size;
  500. }
  501. UFLErrCode
  502. GetFontHeader(
  503. UFOStruct *pUFObj,
  504. unsigned char *pHeader
  505. )
  506. {
  507. unsigned char* tempHeader = pHeader;
  508. TableDirectoryStruct* pTableDir = (TableDirectoryStruct *)tempHeader;
  509. unsigned long size = GetTableDirectory(pUFObj, pTableDir);
  510. tempHeader += size; /* Move past table directory. */
  511. size = GetTableEntry(pUFObj, (TableEntryStruct *)tempHeader, pTableDir);
  512. return kNoErr;
  513. }
  514. unsigned long
  515. GetNumGlyphsInGlyphTable(
  516. UFOStruct *pUFO
  517. )
  518. {
  519. unsigned long dwSize;
  520. Type42HeaderStruct headTable;
  521. short indexToLocFormat;
  522. unsigned long numGlyphs, realNumGlyphs;
  523. unsigned long locaSize;
  524. unsigned long PTR_PREFIX *pLoca;
  525. unsigned long i;
  526. /* Get numGlyphs - 4th and 5th byte in 'maxp' table. See MaxPTableStruct. */
  527. numGlyphs = GetNumGlyphs(pUFO);
  528. if (numGlyphs == 0)
  529. return 0; /* We don't understand this format. */
  530. /*
  531. * Get indexToLocFormat.
  532. * Because of unknown reason the compiler claims that the size of
  533. * Type42HeaderStruct (or its object) is 56 rather than 54 so that we
  534. * cannot get the contents of 'head' table by single GETTTFONTDATA call.
  535. * Instead, we call the function twice, once to get the size of 'head'
  536. * table and then to get its contents.
  537. */
  538. dwSize = GETTTFONTDATA(pUFO,
  539. HEAD_TABLE, 0L,
  540. nil, 0L,
  541. pUFO->pFData->fontIndex);
  542. if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
  543. return 0; /* No 'head' table. This should never happen. */
  544. // Fixed bug 516508. case 2
  545. if (dwSize > sizeof(Type42HeaderStruct))
  546. dwSize = sizeof(Type42HeaderStruct);
  547. dwSize = GETTTFONTDATA(pUFO,
  548. HEAD_TABLE, 0L,
  549. &headTable, dwSize,
  550. pUFO->pFData->fontIndex);
  551. if ((dwSize == 0) || (dwSize == 0xFFFFFFFFL))
  552. return 0; /* Still something is wrong. */
  553. indexToLocFormat = MOTOROLAINT(headTable.indexToLocFormat);
  554. /*
  555. * Allocate a buffer to hold 'loca' table and read it into memory.
  556. */
  557. locaSize = (numGlyphs + 1) * (indexToLocFormat ? 4 : 2);
  558. pLoca = UFLNewPtr(pUFO->pMem, locaSize);
  559. if (pLoca)
  560. {
  561. dwSize = GETTTFONTDATA(pUFO,
  562. LOCA_TABLE, 0L,
  563. pLoca, locaSize,
  564. pUFO->pFData->fontIndex);
  565. }
  566. else
  567. dwSize = 0;
  568. /*
  569. * Get real number of glyphs.
  570. */
  571. realNumGlyphs = 0;
  572. if (pLoca && (dwSize != 0) && (dwSize != 0xFFFFFFFFL))
  573. {
  574. /* Assume good until find otherwise. */
  575. if (indexToLocFormat)
  576. {
  577. unsigned long dwLoca, dwLocaNext;
  578. unsigned long PTR_PREFIX *pLongLoca;
  579. pLongLoca = (unsigned long PTR_PREFIX *)pLoca;
  580. for (i = 0; i < numGlyphs; i++)
  581. {
  582. dwLoca = MOTOROLALONG(pLongLoca[i]);
  583. dwLocaNext = MOTOROLALONG(pLongLoca[i + 1]);
  584. /* Check for 0 and duplicate. */
  585. if ((dwLoca != 0) && (dwLoca != dwLocaNext))
  586. {
  587. realNumGlyphs++;
  588. }
  589. }
  590. }
  591. else
  592. {
  593. unsigned short wLoca, wLocaNext;
  594. unsigned short PTR_PREFIX *pShortLoca;
  595. pShortLoca = (unsigned short PTR_PREFIX *)pLoca;
  596. for (i = 0; i < numGlyphs; i++)
  597. {
  598. wLoca = MOTOROLAINT(pShortLoca[i]);
  599. wLocaNext = MOTOROLAINT(pShortLoca[i + 1]);
  600. /* Check for 0 and duplicate. */
  601. if ((wLoca != 0) && (wLoca != wLocaNext))
  602. {
  603. realNumGlyphs++;
  604. }
  605. }
  606. }
  607. }
  608. if (pLoca)
  609. UFLDeletePtr(pUFO->pMem, pLoca);
  610. return realNumGlyphs;
  611. }
  612. void
  613. GetAverageGlyphSize(
  614. UFOStruct *pUFObj
  615. )
  616. {
  617. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  618. unsigned long glyfTableSize = GetGlyphTableSize(pUFObj);
  619. unsigned long cGlyphs;
  620. if (UFO_NUM_GLYPHS(pUFObj) == 0)
  621. pFont->info.fData.cNumGlyphs = GetNumGlyphs(pUFObj);
  622. cGlyphs = GetNumGlyphsInGlyphTable(pUFObj);
  623. if ((UFO_NUM_GLYPHS(pUFObj) != 0) && (cGlyphs != 0))
  624. pFont->averageGlyphSize = glyfTableSize / cGlyphs;
  625. else
  626. pFont->averageGlyphSize = 0;
  627. }
  628. #pragma optimize("", off)
  629. //
  630. // fix Whistler bug 251303: prevent overrun of the tablesPresent array
  631. //
  632. #define PRESENT_TABLE_ENTRIES MINIMALNUMBERTABLES+2
  633. unsigned long
  634. GenerateMinimalSfnt(
  635. UFOStruct* pUFObj,
  636. char** requiredTables,
  637. UFLBool bFullFont
  638. )
  639. {
  640. unsigned long tablesPresent[PRESENT_TABLE_ENTRIES];
  641. UFLBool hasloca;
  642. T42FontStruct *pFont;
  643. TableDirectoryStruct *pTableDir;
  644. TableEntryStruct *pTableEntry;
  645. unsigned char huge *pCurrentMinSfnt;
  646. unsigned short currentTable, numberOfTables, numberOfRealTables;
  647. unsigned long size;
  648. TableEntryStruct *pGlyphTableEntry;
  649. unsigned char *glyfData;
  650. TableEntryStruct tableEntry;
  651. unsigned long tableSize;
  652. unsigned short i;
  653. //
  654. // Bug fix 229911: ang 9/12/97
  655. // Check if RequiredTables has 'loca'. If not, remember to add 0-length one
  656. // as the last entry.
  657. //
  658. hasloca = 0;
  659. for (i = 0; i < MINIMALNUMBERTABLES; i++)
  660. {
  661. if (UFLstrcmp(requiredTables[i], "loca") == 0)
  662. hasloca = 1;
  663. tablesPresent[i] = (unsigned long)0xFFFFFFFF;
  664. }
  665. //
  666. // Initialize the additional entries
  667. //
  668. for (i = MINIMALNUMBERTABLES ; i < PRESENT_TABLE_ENTRIES ; i++)
  669. {
  670. tablesPresent[i] = (unsigned long)0xFFFFFFFF;
  671. }
  672. //
  673. // Set up the primary pointers.
  674. //
  675. pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  676. pTableDir = (TableDirectoryStruct *)pFont->pHeader;
  677. pTableEntry = (TableEntryStruct *)((char *)(pFont->pHeader) + sizeof (TableDirectoryStruct));
  678. pCurrentMinSfnt = (unsigned char huge *)pFont->pMinSfnt;
  679. //
  680. // Determine how many tables are actually present in pHeader (not in the
  681. // original TTF!).
  682. //
  683. numberOfTables = 0;
  684. for (i = 0; i < MINIMALNUMBERTABLES; i++)
  685. {
  686. if (GetTableSize(pUFObj, pFont->pHeader, *(unsigned long *)(requiredTables[i])))
  687. {
  688. tablesPresent[numberOfTables] = *(unsigned long *)requiredTables[i];
  689. ++numberOfTables;
  690. }
  691. }
  692. //
  693. // Add extra entry if necessary.
  694. //
  695. if (!bFullFont)
  696. numberOfTables += 1; // for 'gdir' table entry as the T42 indication
  697. if (!hasloca)
  698. numberOfTables += 1; // for 0-length 'loca' table entry
  699. //
  700. // size will have the required size for the minimum 'sfnts' at the end.
  701. //
  702. size = sizeof (TableDirectoryStruct) + sizeof (TableEntryStruct) * numberOfTables;
  703. //
  704. // Initialize the table directory.
  705. //
  706. if (pFont->pMinSfnt)
  707. {
  708. TableDirectoryStruct tableDir;
  709. unsigned long dwVersion = 1;
  710. tableDir.version = MOTOROLAINT(dwVersion);
  711. tableDir.numTables =
  712. tableDir.searchRange =
  713. tableDir.entrySelector =
  714. tableDir.rangeshift =
  715. tableDir.numTables = MOTOROLAINT(numberOfTables);
  716. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  717. pCurrentMinSfnt,
  718. &tableDir,
  719. sizeof (TableDirectoryStruct));
  720. pCurrentMinSfnt += sizeof (TableDirectoryStruct);
  721. }
  722. //
  723. // Initialize the table entries. Initialization of 'glyf' table entry will
  724. // be done later in order to make sure to put it at the end of the minimum
  725. // 'sfnts'.
  726. //
  727. // Note that we do linear search to find a table directory entry. This is
  728. // becasue some TT fonts don't have sorted table directory so that we can't
  729. // do binary search. (This is a fix for #310998.)
  730. //
  731. pGlyphTableEntry = nil;
  732. glyfData = nil;
  733. numberOfRealTables = MOTOROLAINT(pTableDir->numTables);
  734. for (currentTable = 0; currentTable < numberOfTables; currentTable++)
  735. {
  736. TableEntryStruct *pEntry = pTableEntry;
  737. for (i = 0; i < numberOfRealTables; i++)
  738. {
  739. if (tablesPresent[currentTable] == pEntry->tag)
  740. {
  741. if (pFont->pMinSfnt)
  742. {
  743. if (pEntry->tag == GLYF_TABLE)
  744. {
  745. glyfData = pCurrentMinSfnt;
  746. }
  747. else
  748. {
  749. tableEntry.tag = pEntry->tag;
  750. tableEntry.checkSum = pEntry->checkSum;
  751. tableEntry.offset = MOTOROLALONG(size);
  752. tableEntry.length = pEntry->length;
  753. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  754. pCurrentMinSfnt,
  755. &tableEntry,
  756. sizeof (TableEntryStruct));
  757. }
  758. pCurrentMinSfnt += sizeof (TableEntryStruct);
  759. }
  760. if (pEntry->tag == GLYF_TABLE)
  761. {
  762. pGlyphTableEntry = pEntry;
  763. }
  764. else
  765. {
  766. tableSize = MOTOROLALONG(pEntry->length);
  767. size += BUMP4BYTE(tableSize);
  768. }
  769. break;
  770. }
  771. pEntry = (TableEntryStruct *)((char *)pEntry + sizeof (TableEntryStruct));
  772. }
  773. }
  774. //
  775. // Update 'glyf' table entry lastly.
  776. //
  777. if (glyfData && pGlyphTableEntry && pFont->pMinSfnt)
  778. {
  779. tableEntry.tag = pGlyphTableEntry->tag;
  780. tableEntry.checkSum = pGlyphTableEntry->checkSum;
  781. tableEntry.offset = MOTOROLALONG(size);
  782. tableEntry.length = pGlyphTableEntry->length;
  783. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  784. glyfData,
  785. &tableEntry,
  786. sizeof (TableEntryStruct));
  787. }
  788. if (pGlyphTableEntry && bFullFont)
  789. {
  790. tableSize = MOTOROLALONG(pGlyphTableEntry->length);
  791. size += BUMP4BYTE(tableSize);
  792. }
  793. //
  794. // Special 'gdir' and 'loca' table entry handling.
  795. //
  796. if (!bFullFont && pFont->pMinSfnt)
  797. {
  798. tableEntry.tag = *(unsigned long *)"gdir";
  799. tableEntry.checkSum = 0;
  800. tableEntry.offset = 0;
  801. tableEntry.length = 0;
  802. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  803. pCurrentMinSfnt,
  804. &tableEntry,
  805. (long)sizeof (TableEntryStruct));
  806. pCurrentMinSfnt += sizeof (TableEntryStruct);
  807. }
  808. if (!hasloca && pFont->pMinSfnt)
  809. {
  810. tableEntry.tag = LOCA_TABLE;
  811. tableEntry.checkSum = 0;
  812. tableEntry.offset = 0;
  813. tableEntry.length = 0;
  814. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  815. pCurrentMinSfnt,
  816. &tableEntry,
  817. (long)sizeof (TableEntryStruct));
  818. pCurrentMinSfnt += sizeof (TableEntryStruct);
  819. }
  820. //
  821. // Copy the required tables after the entries.
  822. //
  823. if (pFont->pMinSfnt)
  824. {
  825. unsigned long bytesRemaining;
  826. pTableEntry = (TableEntryStruct *)((char *)pFont->pMinSfnt + sizeof (TableDirectoryStruct));
  827. if (!bFullFont)
  828. --numberOfTables; // Because there is no 'gdir' table.
  829. if (!hasloca)
  830. --numberOfTables; // Because we treat 'loca' table as 0-length.
  831. for (i = 0; i < (unsigned short)numberOfTables; i++)
  832. {
  833. if (tablesPresent[i] != GLYF_TABLE)
  834. {
  835. bytesRemaining = MOTOROLALONG(pTableEntry->length);
  836. bytesRemaining = BUMP4BYTE(bytesRemaining);
  837. // Fixed bug 516514
  838. GetFontTable(pUFObj, tablesPresent[i], pCurrentMinSfnt, bytesRemaining);
  839. pCurrentMinSfnt += bytesRemaining;
  840. }
  841. pTableEntry = (TableEntryStruct *)((char *)pTableEntry + sizeof (TableEntryStruct));
  842. }
  843. //
  844. // Copy 'glyf' table lastly.
  845. //
  846. if (bFullFont)
  847. {
  848. bytesRemaining = MOTOROLALONG(pGlyphTableEntry->length);
  849. bytesRemaining = BUMP4BYTE(bytesRemaining);
  850. // Fixed bug 516514
  851. GetFontTable(pUFObj, GLYF_TABLE, pCurrentMinSfnt, bytesRemaining);
  852. }
  853. }
  854. return size;
  855. }
  856. #pragma optimize("", on)
  857. UFLErrCode
  858. GetMinSfnt(
  859. UFOStruct *pUFObj,
  860. UFLBool bFullFont
  861. )
  862. {
  863. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  864. char **requiredTables = RequiredTables_default;
  865. UFLErrCode retVal = kNoErr;
  866. //
  867. // IF CID Type 42, then we are sure we can omit the huge 'loca' table
  868. // because Send-TT-as-CID/Type42 is only supported on 2015 or above
  869. // printers.
  870. //
  871. if (IS_TYPE42CID(pUFObj->lDownloadFormat))
  872. {
  873. requiredTables = RequiredTables_2015;
  874. }
  875. if (pFont->pMinSfnt == 0)
  876. {
  877. unsigned long headerSize, sfntSize;
  878. /* Get the size of the portion of the Type font we need. */
  879. headerSize = GetFontHeaderSize(pUFObj);
  880. if (headerSize == 0)
  881. return kErrOutOfMemory; /* Some thing wrong when getting header. */
  882. if ((pFont->pHeader = (unsigned char *)UFLNewPtr(pUFObj->pMem, headerSize)) == nil)
  883. return kErrOutOfMemory;
  884. GetFontHeader(pUFObj, pFont->pHeader);
  885. /* Calculate minimal /sfnts size for Incr or full download. */
  886. sfntSize = GenerateMinimalSfnt(pUFObj, requiredTables, bFullFont);
  887. if ((pFont->pMinSfnt = (unsigned char *)UFLNewPtr(pUFObj->pMem, sfntSize)) == nil)
  888. {
  889. UFLDeletePtr(pUFObj->pMem, pFont->pHeader);
  890. pFont->pHeader = nil;
  891. return kErrOutOfMemory;
  892. }
  893. /* Creates our sfnt - minSfnt. We then work on this minSfnt. */
  894. GenerateMinimalSfnt(pUFObj, requiredTables, bFullFont);
  895. if (retVal == kNoErr)
  896. pFont->minSfntSize = sfntSize;
  897. }
  898. return retVal;
  899. }
  900. unsigned long
  901. GetNextLowestOffset(
  902. TableEntryStruct *pTableEntry,
  903. TableEntryStruct **ppCurrentTable,
  904. short numTables,
  905. unsigned long leastOffset
  906. )
  907. {
  908. unsigned long lowestFound = 0xFFFFFFFFL;
  909. short i;
  910. for (i = 0; i < numTables; ++i)
  911. {
  912. if (((unsigned long)MOTOROLALONG(pTableEntry->offset) > leastOffset)
  913. && ((unsigned long)MOTOROLALONG(pTableEntry->offset) < lowestFound))
  914. {
  915. lowestFound = (unsigned long)MOTOROLALONG(pTableEntry->offset);
  916. *ppCurrentTable = pTableEntry;
  917. }
  918. pTableEntry = (TableEntryStruct *)((char *)pTableEntry + sizeof (TableEntryStruct));
  919. }
  920. return lowestFound;
  921. }
  922. unsigned long
  923. GetBestGlyfBreak(
  924. UFOStruct *pUFObj,
  925. unsigned char *sfnt,
  926. unsigned long upperLimit,
  927. UFLBool longGlyfs
  928. )
  929. {
  930. unsigned long retVal = 0xFFFFFFFFL;
  931. unsigned long dwGlyphStart = 0xFFFFFFFFL;
  932. unsigned long dwTableSize;
  933. unsigned short numGlyphs;
  934. unsigned short i;
  935. /* Get the size of loca table. */
  936. dwTableSize = GetTableSize(pUFObj, sfnt, LOCA_TABLE);
  937. if (0 == dwTableSize)
  938. return retVal;
  939. if (longGlyfs)
  940. {
  941. unsigned long PTR_PREFIX *locationTable =
  942. (unsigned long PTR_PREFIX *)GetSfntTable(sfnt, LOCA_TABLE);
  943. if (locationTable)
  944. {
  945. numGlyphs = (unsigned short)(dwTableSize / sizeof (unsigned long));
  946. for (i = 0; i < numGlyphs; i++)
  947. {
  948. if (MOTOROLALONG(*locationTable) > upperLimit)
  949. {
  950. retVal = dwGlyphStart ;
  951. break;
  952. }
  953. else
  954. {
  955. if ((MOTOROLALONG(*locationTable) & 0x03L) == 0)
  956. {
  957. /* Remember "good" guy. */
  958. dwGlyphStart = MOTOROLALONG(*locationTable);
  959. }
  960. locationTable++;
  961. }
  962. }
  963. }
  964. }
  965. else
  966. {
  967. short PTR_PREFIX* locationTable =
  968. (short PTR_PREFIX*)GetSfntTable(sfnt, LOCA_TABLE);
  969. if (locationTable)
  970. {
  971. numGlyphs = (unsigned short)(dwTableSize / sizeof (unsigned short));
  972. upperLimit /= 2;
  973. for (i = 0; i < numGlyphs; i++)
  974. {
  975. if ((unsigned long)(MOTOROLAINT(*locationTable)) >= upperLimit)
  976. {
  977. retVal = dwGlyphStart;
  978. break;
  979. }
  980. else
  981. {
  982. if ((MOTOROLAINT(*locationTable) & 0x01) == 0)
  983. {
  984. /* Remember "good" guy. */
  985. dwGlyphStart =
  986. (unsigned long)(2L * (unsigned short)MOTOROLAINT(*locationTable));
  987. }
  988. locationTable++;
  989. }
  990. }
  991. }
  992. }
  993. return retVal;
  994. }
  995. UFLErrCode
  996. CalculateStringLength(
  997. UFOStruct *pUFObj,
  998. T42FontStruct *pFont,
  999. unsigned long tableSize
  1000. )
  1001. {
  1002. unsigned long *stringLength = pFont->pStringLength;
  1003. unsigned long *maxStringLength = stringLength + tableSize;
  1004. if (pFont->minSfntSize >= THIRTYTWOK)
  1005. {
  1006. unsigned long glyphTableStart = 0L;
  1007. unsigned long nextOffset = 0L; /* Offset for the current point */
  1008. unsigned long prevOffset = 0L; /* Offset for the previous breakpoint */
  1009. TableEntryStruct *pTableEntry = (TableEntryStruct *)(pFont->pMinSfnt + sizeof (TableDirectoryStruct));
  1010. TableDirectoryStruct *pTableDir = (TableDirectoryStruct *)pFont->pMinSfnt;
  1011. TableEntryStruct *pCurrentTable;
  1012. do
  1013. {
  1014. nextOffset = GetNextLowestOffset(pTableEntry,
  1015. &pCurrentTable,
  1016. (short)MOTOROLAINT(pTableDir->numTables),
  1017. nextOffset);
  1018. if (nextOffset == (unsigned long)0xFFFFFFFF)
  1019. {
  1020. /* No more data. */
  1021. break ;
  1022. }
  1023. if ((nextOffset + MOTOROLALONG(pCurrentTable->length) - prevOffset) > THIRTYTWOK)
  1024. {
  1025. /*
  1026. * Total size is more that 64K.
  1027. */
  1028. unsigned long dwNewPoint; /* Offset from the beginning of glyph table */
  1029. if (pCurrentTable->tag == GLYF_TABLE)
  1030. {
  1031. // DCR -- to improve perfomance, don't need this for Incr downloading.
  1032. /*
  1033. * If we stopped just on 'glyf' table, get the break points
  1034. * to be inside the table but between two glyphs.
  1035. */
  1036. glyphTableStart = nextOffset; /* Next segment starts here. */
  1037. dwNewPoint = 0L;
  1038. while (1)
  1039. {
  1040. dwNewPoint = GetBestGlyfBreak(pUFObj, pFont->pMinSfnt,
  1041. prevOffset + THIRTYTWOK - glyphTableStart,
  1042. (UFLBool)(pFont->headTable.indexToLocFormat ? 1 : 0));
  1043. if (dwNewPoint == 0xFFFFFFFF)
  1044. {
  1045. /* No next point. */
  1046. break;
  1047. }
  1048. else
  1049. {
  1050. nextOffset = glyphTableStart + dwNewPoint;
  1051. prevOffset = nextOffset; /* New segment starts here. */
  1052. *stringLength = nextOffset; /* Save this breakpoint. */
  1053. stringLength++; /* Next breakpoint goes there. */
  1054. if (stringLength >= maxStringLength)
  1055. return kErrOutOfBoundary;
  1056. }
  1057. }
  1058. }
  1059. else
  1060. {
  1061. /* Save the break point at Table Boundry. */
  1062. prevOffset = nextOffset; /* New segment starts here. */
  1063. *stringLength = nextOffset; /* Save this breakpoint. */
  1064. stringLength++; /* Next breakpoint goes there. */
  1065. if (stringLength >= maxStringLength)
  1066. return kErrOutOfBoundary;
  1067. /*
  1068. * Break the single table at 64K boundry -- regardless
  1069. * what TT Spec says.
  1070. */
  1071. /* Tried on a 2016.102 printer. It works. 10-11-1995 */
  1072. glyphTableStart = nextOffset; /* Next segment starts here */
  1073. dwNewPoint = 0L;
  1074. while (1)
  1075. {
  1076. /*
  1077. * We use 64K here becasue we only break a table when
  1078. * ABSOLUTELY necessary >64K.
  1079. */
  1080. dwNewPoint += SIXTYFOURK;
  1081. if (dwNewPoint > MOTOROLALONG(pCurrentTable->length))
  1082. {
  1083. /* No next point. */
  1084. break;
  1085. }
  1086. else
  1087. {
  1088. nextOffset = glyphTableStart + dwNewPoint;
  1089. prevOffset = nextOffset; /* New segment starts here. */
  1090. *stringLength = nextOffset;
  1091. stringLength++; /* Next breakpoint goes there. */
  1092. if (stringLength >= maxStringLength)
  1093. return kErrOutOfBoundary;
  1094. }
  1095. }
  1096. }
  1097. }
  1098. } while (1);
  1099. }
  1100. *stringLength = pFont->minSfntSize + 1; /* Always close the breakpoints list. */
  1101. stringLength++;
  1102. if (stringLength >= maxStringLength)
  1103. return kErrOutOfBoundary;
  1104. *stringLength = 0; /* Always close the breakpoints list with 0!!! */
  1105. return kNoErr;
  1106. }
  1107. UFLErrCode
  1108. FillInHeadTable(
  1109. UFOStruct *pUFObj
  1110. )
  1111. {
  1112. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  1113. // Fixed bug 516514
  1114. if (GetFontTable(pUFObj, HEAD_TABLE, (unsigned char *)&pFont->headTable,
  1115. sizeof(Type42HeaderStruct)) == 0)
  1116. return kErrBadTable;
  1117. // else
  1118. // return kNoErr;
  1119. // WCC 5/14/98 convert all motorola bytes.
  1120. pFont->headTable.tableVersionNumber = MOTOROLALONG(pFont->headTable.tableVersionNumber);
  1121. pFont->headTable.fontRevision = MOTOROLALONG(pFont->headTable.fontRevision);
  1122. pFont->headTable.checkSumAdjustment = MOTOROLALONG(pFont->headTable.checkSumAdjustment);
  1123. pFont->headTable.magicNumber = MOTOROLALONG(pFont->headTable.magicNumber);
  1124. pFont->headTable.flags = MOTOROLAINT(pFont->headTable.flags);
  1125. pFont->headTable.unitsPerEm = MOTOROLAINT(pFont->headTable.unitsPerEm);
  1126. // Need to convert timeCreated and timeModified.
  1127. pFont->headTable.xMin = MOTOROLAINT(pFont->headTable.xMin);
  1128. pFont->headTable.yMin = MOTOROLAINT(pFont->headTable.yMin);
  1129. pFont->headTable.xMax = MOTOROLAINT(pFont->headTable.xMax);
  1130. pFont->headTable.yMax = MOTOROLAINT(pFont->headTable.yMax);
  1131. pFont->headTable.macStyle = MOTOROLAINT(pFont->headTable.macStyle);
  1132. pFont->headTable.lowestRecPPEM = MOTOROLAINT(pFont->headTable.lowestRecPPEM);
  1133. pFont->headTable.fontDirectionHint = MOTOROLAINT(pFont->headTable.fontDirectionHint);
  1134. pFont->headTable.indexToLocFormat = MOTOROLAINT(pFont->headTable.indexToLocFormat);
  1135. pFont->headTable.glyfDataFormat = MOTOROLAINT(pFont->headTable.glyfDataFormat);
  1136. return kNoErr;
  1137. }
  1138. short
  1139. PSSendSfntsBinary(
  1140. UFOStruct *pUFObj
  1141. )
  1142. {
  1143. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  1144. char huge *glyphs = (char huge *)pFont->pMinSfnt;
  1145. unsigned long minSfntSize = pFont->minSfntSize;
  1146. unsigned long *breakHere = pFont->pStringLength;
  1147. unsigned long dwLen = *breakHere;
  1148. UFLHANDLE stream = pUFObj->pUFL->hOut;
  1149. short nSubStr = 1;
  1150. short i = 0;
  1151. if (dwLen > minSfntSize)
  1152. {
  1153. /* There's only 1 string. */
  1154. dwLen--;
  1155. StrmPutInt(stream, dwLen + 1);
  1156. StrmPutString(stream, RDString);
  1157. StrmPutBytes(stream, glyphs, (UFLsize_t)dwLen, 0);
  1158. StrmPutString(stream, "0");
  1159. return nSubStr; /* It is 1 -- only one string. */
  1160. }
  1161. StrmPutInt(stream, dwLen + 1);
  1162. StrmPutString(stream, RDString);
  1163. StrmPutBytes(stream, glyphs, (UFLsize_t)dwLen, 0);
  1164. StrmPutString(stream, "0");
  1165. glyphs = glyphs + dwLen;
  1166. while (breakHere[i] <= minSfntSize)
  1167. {
  1168. dwLen = breakHere[i + 1] - breakHere[i];
  1169. if (breakHere[i + 1] > minSfntSize)
  1170. dwLen--;
  1171. StrmPutInt(stream, dwLen + 1);
  1172. StrmPutString(stream, RDString);
  1173. StrmPutBytes(stream, glyphs, (UFLsize_t)dwLen, 0);
  1174. StrmPutStringEOL(stream, "0");
  1175. glyphs = glyphs+dwLen;
  1176. i++;
  1177. nSubStr++;
  1178. }
  1179. return nSubStr;
  1180. }
  1181. short
  1182. PSSendSfntsAsciiHex(
  1183. UFOStruct *pUFObj
  1184. )
  1185. {
  1186. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  1187. char huge *glyphs = (char huge *)pFont->pMinSfnt;
  1188. unsigned long minSfntSize = pFont->minSfntSize;
  1189. unsigned long *breakHere = pFont->pStringLength;
  1190. unsigned long dwBreak = *breakHere - 1;
  1191. UFLHANDLE stream = pUFObj->pUFL->hOut;
  1192. short bytesSent = 1;
  1193. short nSubStr = 1;
  1194. unsigned long i;
  1195. StrmPutString(stream, "<");
  1196. for (i = 0; i < minSfntSize; i++)
  1197. {
  1198. StrmPutAsciiHex(stream, glyphs, 1);
  1199. ++glyphs;
  1200. ++bytesSent;
  1201. if (i == dwBreak)
  1202. {
  1203. if (dwBreak != minSfntSize)
  1204. {
  1205. StrmPutStringEOL(stream, "00>");
  1206. bytesSent = 1;
  1207. StrmPutString(stream, "<");
  1208. }
  1209. dwBreak = *(++breakHere) - 1 ;
  1210. nSubStr++;
  1211. }
  1212. /*
  1213. * We already have a control (stream->Out->AddEOL) when to add a EOL.
  1214. *
  1215. * if (!(bytesSent % 40))
  1216. * {
  1217. * StrmPutStringEOL(stream, nilStr);
  1218. * bytesSent = 1;
  1219. * }
  1220. */
  1221. }
  1222. StrmPutString(stream, "00>");
  1223. return nSubStr;
  1224. }
  1225. UFLErrCode
  1226. CalcBestGlyfTableBreaks(
  1227. UFOStruct *pUFObj,
  1228. unsigned long upperLimit,
  1229. unsigned long tableSize
  1230. )
  1231. {
  1232. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  1233. unsigned long *stringLength = pFont->pStringLength;
  1234. unsigned long *maxStringLength = stringLength + tableSize;
  1235. unsigned long prevOffset = 0L; /* Offset for the previous breakpoint */
  1236. unsigned long nextOffset = 0xFFFFFFFFL; /* Offset for the current point */
  1237. unsigned long glyfTableSize = GetTableSize(pUFObj, pFont->pHeader, GLYF_TABLE);
  1238. unsigned long locaTableSize = GetTableSize(pUFObj, pFont->pHeader, LOCA_TABLE);
  1239. *stringLength = 0L; /* Start with offset 0. */
  1240. stringLength++;
  1241. if (glyfTableSize > upperLimit)
  1242. {
  1243. unsigned short numGlyphs;
  1244. unsigned short i; /* 'loca' table entries counter */
  1245. if (pFont->headTable.indexToLocFormat)
  1246. {
  1247. /* long offsets */
  1248. unsigned long PTR_PREFIX *locationTable = (unsigned long PTR_PREFIX *)pFont->pLocaTable;
  1249. numGlyphs = (unsigned short)(locaTableSize / sizeof (unsigned long));
  1250. for (i = 0; i < numGlyphs; i++)
  1251. {
  1252. unsigned long dwTmp = MOTOROLALONG(*locationTable);
  1253. if ((dwTmp > (prevOffset + upperLimit))
  1254. && (nextOffset != prevOffset))
  1255. {
  1256. *stringLength = nextOffset;
  1257. stringLength++;
  1258. if (stringLength >= maxStringLength)
  1259. return kErrOutOfBoundary;
  1260. prevOffset = nextOffset;
  1261. }
  1262. else
  1263. {
  1264. if ((dwTmp & 0x03L) == 0)
  1265. nextOffset = dwTmp;
  1266. locationTable++;
  1267. }
  1268. }
  1269. }
  1270. else
  1271. {
  1272. unsigned short PTR_PREFIX *locationTable = (unsigned short PTR_PREFIX *)pFont->pLocaTable;
  1273. numGlyphs = (unsigned short)(locaTableSize / sizeof (unsigned short));
  1274. for (i = 0; i < numGlyphs; i++)
  1275. {
  1276. unsigned short iTmp = MOTOROLAINT(*locationTable);
  1277. if (((2L * (unsigned long)iTmp) > (prevOffset + upperLimit))
  1278. && (nextOffset != prevOffset))
  1279. {
  1280. *stringLength = nextOffset;
  1281. stringLength++;
  1282. if (stringLength >= maxStringLength)
  1283. return kErrOutOfBoundary;
  1284. prevOffset = nextOffset;
  1285. }
  1286. else
  1287. {
  1288. if ((iTmp & 0x01) == 0)
  1289. nextOffset = 2L * (unsigned long)iTmp;
  1290. locationTable++;
  1291. }
  1292. }
  1293. }
  1294. }
  1295. *stringLength = glyfTableSize; /* Close the breakpoints list. */
  1296. stringLength++;
  1297. if (stringLength >= maxStringLength)
  1298. return kErrOutOfBoundary;
  1299. *stringLength = 0; /* Always close the breakpoints list with 0!!! */
  1300. return kNoErr;
  1301. }
  1302. UFLErrCode
  1303. GenerateGlyphStorageExt(
  1304. UFOStruct *pUFObj,
  1305. unsigned long tableSize
  1306. )
  1307. {
  1308. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  1309. unsigned long *stringLength = pFont->pStringLength;
  1310. unsigned long upperLimit = SFNT_STRINGSIZE; /* 0x3FFE */
  1311. UFLHANDLE stream = pUFObj->pUFL->hOut;
  1312. UFLErrCode retVal;
  1313. short i;
  1314. retVal = CalcBestGlyfTableBreaks(pUFObj, upperLimit, tableSize);
  1315. if (retVal != kNoErr)
  1316. return retVal;
  1317. /*
  1318. * Send down the array of Glyph strings.
  1319. */
  1320. retVal = StrmPutStringEOL(stream, nilStr);
  1321. if (kNoErr == retVal)
  1322. retVal = StrmPutString(stream, "[");
  1323. for (i = 1; (retVal == kNoErr) && (stringLength[i] != 0); i++)
  1324. {
  1325. unsigned long stringSize;
  1326. #if 0
  1327. //
  1328. // For Chinese Font SongTi, the very last stringLength is incorrect:
  1329. // glyfSize = 7068416, but the last glyf breaks at 6890292.
  1330. // That means the very last glyf is 178124 - this is impossible.
  1331. // Either GDI is not returning correct number or our function
  1332. // GetTableSize() is wrong. Untill we fix our problem or get a better
  1333. // build of Win95, this is a temp fix. ?????. 10-12-95
  1334. //
  1335. if (stringLength[i] > stringLength[i-1] + 0xFFFF)
  1336. stringSize = (unsigned long)0x3FFF; // 16K. This is a bogus entry anyway.
  1337. else
  1338. #endif
  1339. stringSize = stringLength[i] - stringLength[i-1];
  1340. if (kNoErr == retVal)
  1341. retVal = StrmPutInt(stream, stringSize + 1);
  1342. if (retVal == kNoErr)
  1343. {
  1344. if (i % 13 == 0)
  1345. retVal = StrmPutStringEOL(stream, nilStr);
  1346. else
  1347. retVal = StrmPutString(stream, " ");
  1348. }
  1349. }
  1350. if (kNoErr == retVal)
  1351. retVal = StrmPutStringEOL(stream, "] AllocGlyphStorage");
  1352. return retVal;
  1353. }
  1354. unsigned short
  1355. GetTableDirectoryOffset(
  1356. T42FontStruct *pFont,
  1357. unsigned long tableName
  1358. )
  1359. {
  1360. TableDirectoryStruct* tableDirectory = (TableDirectoryStruct *)pFont->pMinSfnt;
  1361. TableEntryStruct* tableEntry = (TableEntryStruct *)((char *)tableDirectory
  1362. + sizeof (TableDirectoryStruct));
  1363. unsigned short offset = sizeof (TableDirectoryStruct);
  1364. unsigned short i = 0;
  1365. while (i < MOTOROLAINT(tableDirectory->numTables))
  1366. {
  1367. if (tableEntry->tag == tableName)
  1368. break;
  1369. else
  1370. {
  1371. tableEntry = (TableEntryStruct *)((char *)tableEntry + sizeof (TableEntryStruct));
  1372. offset += sizeof (TableEntryStruct);
  1373. i++;
  1374. }
  1375. }
  1376. return offset;
  1377. }
  1378. /* Sorting and Searching functions for an array of longs */
  1379. // Function to compare longs
  1380. static short
  1381. CompareLong(
  1382. const long x,
  1383. const long y
  1384. )
  1385. {
  1386. if (x == y)
  1387. return 0;
  1388. else if (x < y)
  1389. return -1;
  1390. else
  1391. return 1;
  1392. }
  1393. // Function to swap pointers to longs
  1394. static void
  1395. SwapLong(
  1396. long *a,
  1397. long *b
  1398. )
  1399. {
  1400. if (a != b)
  1401. {
  1402. long tmp = *a;
  1403. *a = *b;
  1404. *b = tmp;
  1405. }
  1406. }
  1407. /* This is a tailored version of shortsort. Works only for array of longs. */
  1408. static void
  1409. ShortsortLong(
  1410. char *lo,
  1411. char *hi,
  1412. unsigned short width,
  1413. short (*comp)(const long, const long)
  1414. )
  1415. {
  1416. while (hi > lo)
  1417. {
  1418. char *max = lo;
  1419. char *p;
  1420. for (p = lo + width; p <= hi; p += width)
  1421. {
  1422. if (comp(*(long *)p, *(long *)max) > 0)
  1423. max = p;
  1424. }
  1425. SwapLong((long *)max, (long *)hi);
  1426. hi -= width;
  1427. }
  1428. }
  1429. /* Function to Sort the array between lo and hi (inclusive) */
  1430. void
  1431. QsortLong(
  1432. char* base,
  1433. unsigned short num,
  1434. unsigned short width,
  1435. short (*comp)(const long, const long)
  1436. )
  1437. {
  1438. char *lo, *hi; /* ends of sub-array currently sorting */
  1439. char *mid; /* points to middle of subarray */
  1440. char *loguy, *higuy; /* traveling pointers for partition step */
  1441. unsigned short size; /* size of the sub-array */
  1442. short stkptr; /* stack for saving sub-array to be processed */
  1443. char *lostk[16], *histk[16];
  1444. /* Testing shows that this is a good value. */
  1445. const unsigned short CUTOFF0 = 8;
  1446. /*
  1447. * Note: the number of stack entries required is no more than
  1448. * 1 + log2(size), so 16 is sufficient for any array with <=64K elems.
  1449. */
  1450. if ((num < 2) || (width == 0))
  1451. return; /* Nothing to do. */
  1452. stkptr = 0; /* Initialize stack. */
  1453. lo = (char *)base;
  1454. hi = (char *)base + width * (num - 1); /* Initialize limits. */
  1455. /*
  1456. * This entry point is for pseudo-recursion calling: setting lo and hi and
  1457. * jumping to here is like recursion, but stkptr is prserved, locals aren't,
  1458. * so we preserve stuff on the stack.
  1459. */
  1460. sort_recurse:
  1461. size = (unsigned short)((hi - lo) / width + 1); /* Number of el's to sort */
  1462. if (size <= CUTOFF0)
  1463. {
  1464. ShortsortLong(lo, hi, width, comp);
  1465. }
  1466. else
  1467. {
  1468. mid = lo + (size / 2) * width; /* Find middle element. */
  1469. SwapLong((long *)mid, (long *)lo); /* Wwap it to beginning of array. */
  1470. loguy = lo;
  1471. higuy = hi + width;
  1472. /*
  1473. * Note that higuy decreases and loguy increases on every iteration,
  1474. * so loop must terminate.
  1475. */
  1476. while(1)
  1477. {
  1478. do
  1479. {
  1480. loguy += width;
  1481. } while (loguy <= hi && comp(*(long *)loguy, *(long *)lo) <= 0);
  1482. do
  1483. {
  1484. higuy -= width;
  1485. } while (higuy > lo && comp(*(long *)higuy, *(long *)lo) >= 0);
  1486. if (higuy < loguy)
  1487. break;
  1488. SwapLong((long *)loguy, (long *)higuy);
  1489. }
  1490. SwapLong((long *)lo, (long *)higuy); /* Put partition element in place. */
  1491. if ((higuy - 1 - lo) >= (hi - loguy))
  1492. {
  1493. if ((lo + width) < higuy)
  1494. {
  1495. lostk[stkptr] = lo;
  1496. histk[stkptr] = higuy - width;
  1497. ++stkptr; /* Save big recursion for later. */
  1498. }
  1499. if (loguy < hi)
  1500. {
  1501. lo = loguy;
  1502. goto sort_recurse; /* Do small recursion. */
  1503. }
  1504. }
  1505. else
  1506. {
  1507. if (loguy < hi)
  1508. {
  1509. lostk[stkptr] = loguy;
  1510. histk[stkptr] = hi;
  1511. ++stkptr; /* Save big recursion for later. */
  1512. }
  1513. if ((lo + width) < higuy)
  1514. {
  1515. hi = higuy - width;
  1516. goto sort_recurse; /* Do small recursion. */
  1517. }
  1518. }
  1519. }
  1520. /*
  1521. * We have sorted the array, except for any pending sorts on the stack.
  1522. * Check if there are any, and do them.
  1523. */
  1524. --stkptr;
  1525. if (stkptr >= 0)
  1526. {
  1527. lo = lostk[stkptr];
  1528. hi = histk[stkptr];
  1529. goto sort_recurse; /* Pop subarray from stack. */
  1530. }
  1531. else
  1532. return; /* All subarrays done. */
  1533. }
  1534. /* This is a tailored version of the CRT bsearch(). */
  1535. void *
  1536. BsearchLong (
  1537. const long key,
  1538. const char *base,
  1539. unsigned short num,
  1540. unsigned short width,
  1541. short (*compare)(const long, const long)
  1542. )
  1543. {
  1544. char *lo = (char *)base;
  1545. char *hi = (char *)base + (num - 1) * width;
  1546. while (lo <= hi)
  1547. {
  1548. unsigned short half;
  1549. if (half = (num / 2))
  1550. {
  1551. short result;
  1552. char *mid = lo + (num & 1 ? half : (half - 1)) * width;
  1553. if (!(result = (*compare)(key, *(long *)mid)))
  1554. return mid;
  1555. else if (result < 0)
  1556. {
  1557. hi = mid - width;
  1558. num = num & 1 ? half : half - 1;
  1559. }
  1560. else
  1561. {
  1562. lo = mid + width;
  1563. num = half;
  1564. }
  1565. }
  1566. else if (num)
  1567. return ((*compare)((long)key, *(long *)lo) ? nil : lo);
  1568. else
  1569. break;
  1570. }
  1571. return nil;
  1572. }
  1573. UFLErrCode
  1574. DefaultGetRotatedGIDs(
  1575. UFOStruct *pUFObj,
  1576. T42FontStruct *pFont,
  1577. UFLFontProcs *pFontProcs
  1578. )
  1579. {
  1580. UFLErrCode retVal = kNoErr;
  1581. unsigned short num = 0; // Remember the number of GIDs.
  1582. long *pFoundGID;
  1583. short subTable;
  1584. unsigned long offset;
  1585. short i;
  1586. /*
  1587. * Don't forget to double the size. We expect extra GIDs coming from 'GSUB'
  1588. * or 'mort' table.
  1589. */
  1590. pFont->pRotatedGlyphIDs = (long *)UFLNewPtr(pUFObj->pMem, (NUM_HALFWIDTHCHARS + 1) * sizeof (long) * 2);
  1591. if (!pFont->pRotatedGlyphIDs)
  1592. return kErrOutOfMemory;
  1593. /*
  1594. * To scan through TTF's 'cmap' table to fingure out the glyph ids for all
  1595. * characters in the range for romans and single byte chars.
  1596. */
  1597. if (!pFontProcs->pfGetGlyphID)
  1598. GetGlyphIDEx(pUFObj, 0, 0, &subTable, &offset, GGIEX_HINT_INIT);
  1599. pFoundGID = pFont->pRotatedGlyphIDs;
  1600. for (i = 0;
  1601. (gHalfWidthChars[i].startU != gHalfWidthChars[i].endU)
  1602. && (gHalfWidthChars[i].startU != 0);
  1603. i++)
  1604. {
  1605. long unicode, localcode;
  1606. for (unicode = gHalfWidthChars[i].startU, localcode = gHalfWidthChars[i].startL;
  1607. unicode <= gHalfWidthChars[i].endU;
  1608. unicode++, localcode++)
  1609. {
  1610. unsigned long gi;
  1611. if (pFontProcs->pfGetGlyphID)
  1612. gi = pFontProcs->pfGetGlyphID(pUFObj->hClientData,
  1613. (unsigned short)unicode,
  1614. (unsigned short)localcode);
  1615. else
  1616. gi = GetGlyphIDEx(pUFObj, unicode, localcode,
  1617. &subTable, &offset, GGIEX_HINT_GET);
  1618. if (gi > (unsigned long)UFO_NUM_GLYPHS(pUFObj))
  1619. gi = 0;
  1620. if (gi != 0)
  1621. {
  1622. *pFoundGID = (long)gi;
  1623. pFoundGID++;
  1624. num++;
  1625. }
  1626. else
  1627. {
  1628. //
  1629. // We will have to treat all Half-width single characters as
  1630. // "space" because we don't want to place a Double-Byte
  1631. // /.notdef as rotated.
  1632. //
  1633. }
  1634. }
  1635. }
  1636. if (pFontProcs->pfGetRotatedGSUBs) // Fix #316070
  1637. {
  1638. // OK to trancate long to unsigned short.
  1639. num += (unsigned short)pFontProcs->pfGetRotatedGSUBs(
  1640. pUFObj->hClientData,
  1641. pFont->pRotatedGlyphIDs,
  1642. num);
  1643. }
  1644. pFont->numRotatedGlyphIDs = num;
  1645. //
  1646. // Now, sort the array so that we can search quicker later.
  1647. //
  1648. QsortLong((char *)(pFont->pRotatedGlyphIDs),
  1649. pFont->numRotatedGlyphIDs,
  1650. 4,
  1651. CompareLong);
  1652. return retVal;
  1653. }
  1654. UFLErrCode
  1655. T42GetRotatedGIDs(
  1656. UFOStruct *pUFObj,
  1657. T42FontStruct *pFont
  1658. )
  1659. {
  1660. UFLFontProcs *pFontProcs = (UFLFontProcs *)&(pUFObj->pUFL->fontProcs);
  1661. /* Assume this first in order to fall back to the default logic. */
  1662. UFLErrCode retVal = kErrOSFunctionFailed;
  1663. pFont->numRotatedGlyphIDs = 0;
  1664. if (pFontProcs->pfGetRotatedGIDs)
  1665. {
  1666. long nGlyphs = pFontProcs->pfGetRotatedGIDs(pUFObj->hClientData, nil, 0, nil);
  1667. if (nGlyphs > 0)
  1668. {
  1669. pFont->pRotatedGlyphIDs = (long *)UFLNewPtr(pUFObj->pMem, (nGlyphs + 1) * sizeof (long));
  1670. if (pFont->pRotatedGlyphIDs)
  1671. {
  1672. pFontProcs->pfGetRotatedGIDs(pUFObj->hClientData, pFont->pRotatedGlyphIDs, nGlyphs, nil);
  1673. pFont->numRotatedGlyphIDs = (unsigned short)nGlyphs;
  1674. retVal = kNoErr;
  1675. }
  1676. else
  1677. retVal = kErrOutOfMemory;
  1678. }
  1679. else
  1680. retVal = (nGlyphs == 0) ? kNoErr: kErrOSFunctionFailed;
  1681. }
  1682. if (retVal == kErrOSFunctionFailed)
  1683. {
  1684. /*
  1685. * Default logic: scan TTF's cmap to get GIDs for CJK half-width chars.
  1686. */
  1687. retVal = DefaultGetRotatedGIDs(pUFObj, pFont, pFontProcs);
  1688. }
  1689. return retVal;
  1690. }
  1691. UFLBool
  1692. IsDoubleByteGI(
  1693. unsigned short gi,
  1694. long *pGlyphIDs,
  1695. short length
  1696. )
  1697. {
  1698. void *index;
  1699. // Return True if gi is NOT in the pGlyphIDs - index==nil.
  1700. index = BsearchLong((long)gi, (char *)pGlyphIDs, length, 4, CompareLong);
  1701. return ((index == nil) ? 1 : 0);
  1702. }
  1703. /*============================================================================*
  1704. * Begin Code to support more than 32K glyphs *
  1705. *============================================================================*/
  1706. /******************************************************************************
  1707. *
  1708. * T42SendCMapWinCharSetFFFF_V
  1709. *
  1710. * Make a vertical CMap based on known Rotated Glyph-indices (1 Byte chars).
  1711. * Create a CMapType 1 CMap. Since this CMap is different for different font,
  1712. * the CMapName is passed in by caller as lpNewCmap. The resulting CMap uses
  1713. * 2 or 4(lGlyphs>32K) CMaps: e.g.
  1714. *
  1715. * [/TT31c1db0t0cid /TT31c1db0t0cidR]
  1716. * or
  1717. * [/TT31c1db0t0cid /TT31c1db0t0cidR /TT31c1db0t0cid32K /MSTT31c1db0t0cid32KR]
  1718. *
  1719. ******************************************************************************/
  1720. UFLErrCode
  1721. T42SendCMapWinCharSetFFFF_V(
  1722. UFOStruct *pUFObj,
  1723. long *pRotatedGID,
  1724. short wLength,
  1725. UFLCMapInfo *pCMap,
  1726. char *pNewCmap,
  1727. unsigned long lGlyphs,
  1728. UFLHANDLE stream,
  1729. char *strmbuf,
  1730. size_t cchstrmbuf
  1731. )
  1732. {
  1733. short nCount, nCount32K, nLen, i, j;
  1734. unsigned short wPrev, wCurr;
  1735. UFLErrCode retVal;
  1736. UFLBool bCMapV2 = (pCMap == &CMapInfo_FF_V2) ? 1 : 0;
  1737. UFLsprintf(strmbuf, cchstrmbuf,
  1738. "/CIDInit /ProcSet findresource begin "
  1739. "12 dict begin begincmap /%s usecmap",
  1740. pCMap->CMapName);
  1741. retVal = StrmPutStringEOL(stream, strmbuf);
  1742. /*
  1743. * Create CIDSystemInfo unique for this font. Since this CMap will refer to
  1744. * more than one font, the CIDSystmInfo is going to be an array.
  1745. */
  1746. if (retVal == kNoErr)
  1747. retVal = StrmPutStringEOL(stream, "/CIDSystemInfo [3 dict dup begin");
  1748. UFLsprintf(strmbuf, cchstrmbuf, "/Registry (%s) def", pCMap->Registry);
  1749. if (retVal == kNoErr)
  1750. retVal = StrmPutStringEOL(stream, strmbuf);
  1751. UFLsprintf(strmbuf, cchstrmbuf, "/Ordering (%s) def", pNewCmap);
  1752. if (retVal == kNoErr)
  1753. retVal = StrmPutStringEOL(stream, strmbuf);
  1754. if (retVal == kNoErr)
  1755. retVal = StrmPutStringEOL(stream, "/Supplement 0 def");
  1756. if (lGlyphs <= NUM_32K_1)
  1757. UFLsprintf(strmbuf, cchstrmbuf, "end dup] def");
  1758. else
  1759. UFLsprintf(strmbuf, cchstrmbuf, "end dup dup dup] def");
  1760. if (retVal == kNoErr)
  1761. retVal = StrmPutStringEOL(stream, strmbuf);
  1762. UFLsprintf(strmbuf, cchstrmbuf, "/CMapName /%s def", pNewCmap);
  1763. if (retVal == kNoErr)
  1764. retVal = StrmPutStringEOL(stream, strmbuf);
  1765. /* Fix /CIDInit /ProcSet bug: need "/WMode 1 def" explicitly. */
  1766. if (retVal == kNoErr)
  1767. retVal = StrmPutStringEOL(stream, "/WMode 1 def");
  1768. if (retVal == kNoErr)
  1769. retVal = StrmPutStringEOL(stream, "0 beginusematrix [0 1 -1 0 0 0] endusematrix");
  1770. if ((retVal == kNoErr) && bCMapV2)
  1771. retVal = StrmPutStringEOL(stream, "2 beginusematrix [0 1 -1 0 0 0] endusematrix");
  1772. /* Skip to emit begin~endcidrange if there is no rotated GIDs. */
  1773. if (wLength == 0)
  1774. goto SENDCMAPFFFF_V_ENDCMAP;
  1775. /*
  1776. * Count how many different Glyph-indices are there in pRotatedGID.
  1777. * It must be sorted and there may be duplicates so that we count only
  1778. * unique GIDs.
  1779. */
  1780. wPrev = (unsigned short)*pRotatedGID;
  1781. nCount = nCount32K = 0;
  1782. if (wPrev > NUM_32K_1)
  1783. nCount32K++;
  1784. else
  1785. nCount++;
  1786. for (i = 0; i < wLength; i++)
  1787. {
  1788. wCurr = (unsigned short)*(pRotatedGID + i);
  1789. if (wPrev == wCurr)
  1790. continue;
  1791. else
  1792. {
  1793. wPrev = wCurr;
  1794. if (wPrev > NUM_32K_1)
  1795. nCount32K++;
  1796. else
  1797. nCount++;
  1798. }
  1799. }
  1800. /*
  1801. * Emit 0 to 32K rotated GIDs to font number 1.
  1802. */
  1803. if (retVal == kNoErr)
  1804. retVal = StrmPutStringEOL(stream, "1 usefont");
  1805. if (100 < nCount)
  1806. UFLsprintf(strmbuf, cchstrmbuf, "100 begincidrange");
  1807. else
  1808. UFLsprintf(strmbuf, cchstrmbuf, "%d begincidrange", nCount);
  1809. wPrev = (unsigned short)*(pRotatedGID);
  1810. if (retVal == kNoErr)
  1811. {
  1812. if (kNoErr == retVal)
  1813. retVal = StrmPutStringEOL(stream, strmbuf);
  1814. if (kNoErr == retVal)
  1815. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1816. if (kNoErr == retVal)
  1817. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1818. UFLsprintf(strmbuf, cchstrmbuf, "%u", wPrev);
  1819. if (kNoErr == retVal)
  1820. retVal = StrmPutStringEOL(stream, strmbuf);
  1821. }
  1822. nLen = 1;
  1823. for (i = 1; i < wLength; i++)
  1824. {
  1825. wCurr = (unsigned short)*(pRotatedGID + i);
  1826. /*
  1827. * This potion is for 0 to 32K glyphs - the pRotatedGID are sorted,
  1828. * so we can just break out of the loop here.
  1829. */
  1830. if (wCurr > NUM_32K_1)
  1831. break;
  1832. if (wPrev == wCurr)
  1833. continue;
  1834. else
  1835. {
  1836. wPrev = wCurr;
  1837. nLen++;
  1838. }
  1839. if (retVal == kNoErr)
  1840. {
  1841. if (kNoErr == retVal)
  1842. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1843. if (kNoErr == retVal)
  1844. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1845. UFLsprintf(strmbuf, cchstrmbuf, "%u", wPrev);
  1846. if (kNoErr == retVal)
  1847. retVal = StrmPutStringEOL(stream, strmbuf);
  1848. }
  1849. if (nLen % 100 == 0)
  1850. {
  1851. if (nCount - nLen > 100)
  1852. UFLsprintf(strmbuf, cchstrmbuf, "endcidrange\n100 begincidrange");
  1853. else if (nCount - nLen > 0)
  1854. UFLsprintf(strmbuf, cchstrmbuf, "endcidrange\n%d begincidrange", nCount - nLen);
  1855. else
  1856. UFLsprintf(strmbuf, cchstrmbuf, " ");
  1857. }
  1858. else
  1859. continue; /* Do next record. */
  1860. if (retVal == kNoErr)
  1861. retVal = StrmPutStringEOL(stream, strmbuf);
  1862. }
  1863. if (retVal == kNoErr)
  1864. retVal = StrmPutStringEOL(stream, "endcidrange");
  1865. /*
  1866. * Emit 32K+ GIDs.
  1867. */
  1868. if (NUM_32K_1 < lGlyphs)
  1869. {
  1870. /*
  1871. * Build two more re-mappings using CMAP-WinCharSetFFFF-V2, which is
  1872. * created from CMAP-WinCharSetFFFF-H2 specifying 32K+ glyphs as
  1873. * font number 1. (See the definition of CMAP-WinCharSetFFFF-H2 in
  1874. * CMap_FF.ps.) Since font number 1 is already used for 0 to 32K
  1875. * rotated GIDs above, we need to redefine the range for 32K+
  1876. * unrotated GIDs as font number 2, *then* define the range for 32K+
  1877. * rotated GIDs as font number 3. (Here is the font array we are
  1878. * assuming: [000, 000R, 00032K, 00032KR])
  1879. *
  1880. * Note also that when this is a %hostfont% font (bCMapV2 is 0), we
  1881. * don't need to use CMAP-WinCharSetFFFF-V2 but CMAP-WinCharSetFFFF-V
  1882. * instead. But we still need to emit 32K+ glyph cidrange here.
  1883. * In this case, we don't send '3 usefont' so that the cidrange lines
  1884. * are emitted as continuation for font number 1.
  1885. */
  1886. if (bCMapV2)
  1887. {
  1888. /*
  1889. * Emit font number 2 range.
  1890. */
  1891. if (retVal == kNoErr)
  1892. retVal = StrmPutStringEOL(stream, "2 usefont");
  1893. nCount = (int)((long)lGlyphs - (long)NUM_32K_1 + 0xFE) / 0xFF;
  1894. UFLsprintf(strmbuf, cchstrmbuf, "%d begincidrange", nCount);
  1895. if (retVal == kNoErr)
  1896. retVal = StrmPutStringEOL(stream, strmbuf);
  1897. /*
  1898. * We assume NUM_32K_1 ends at 00 (such as 0xFF00, or 0xFE00...).
  1899. */
  1900. for (i = 0; i < nCount; i++)
  1901. {
  1902. wPrev = (unsigned short) (i * 0x100 + (long)NUM_32K_1);
  1903. if (kNoErr == retVal)
  1904. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1905. if (kNoErr == retVal)
  1906. retVal = StrmPutWordAsciiHex(stream, (unsigned short)(wPrev + 0xFF));
  1907. UFLsprintf(strmbuf, cchstrmbuf, "%u", (unsigned short)(i * 0x100));
  1908. if (retVal == kNoErr)
  1909. retVal = StrmPutStringEOL(stream, strmbuf);
  1910. }
  1911. if (retVal == kNoErr)
  1912. retVal = StrmPutStringEOL(stream, "endcidrange");
  1913. }
  1914. if (0 < nCount32K)
  1915. {
  1916. /*
  1917. * Emit rotated GIDs of font number 3 or 1 if not using
  1918. * '2' version of VCMap (which means this is a %hostfont%
  1919. * font that has 32K+ glyphs.)
  1920. */
  1921. if ((retVal == kNoErr) && bCMapV2)
  1922. retVal = StrmPutStringEOL(stream, "3 usefont");
  1923. wPrev = (unsigned short)*pRotatedGID;
  1924. for (j = 0; j < wLength; j++)
  1925. {
  1926. wCurr = (unsigned short)*(pRotatedGID + j);
  1927. wPrev = wCurr;
  1928. if (wPrev > NUM_32K_1)
  1929. break; /* Found the start point. */
  1930. }
  1931. if (100 < nCount32K)
  1932. UFLsprintf(strmbuf, cchstrmbuf, "100 begincidrange");
  1933. else
  1934. UFLsprintf(strmbuf, cchstrmbuf, "%d begincidrange", nCount32K);
  1935. if (retVal == kNoErr)
  1936. {
  1937. if (kNoErr == retVal)
  1938. retVal = StrmPutStringEOL(stream, strmbuf);
  1939. if (kNoErr == retVal)
  1940. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1941. if (kNoErr == retVal)
  1942. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1943. UFLsprintf(strmbuf, cchstrmbuf, "%u", bCMapV2 ? wPrev - NUM_32K_1 : wPrev);
  1944. if (kNoErr == retVal)
  1945. retVal = StrmPutStringEOL(stream, strmbuf);
  1946. }
  1947. nLen = 1;
  1948. for (i = j; i < wLength; i++)
  1949. {
  1950. wCurr = (unsigned short)*(pRotatedGID + i);
  1951. if (wPrev == wCurr)
  1952. continue;
  1953. else
  1954. {
  1955. wPrev = wCurr;
  1956. nLen++;
  1957. }
  1958. if (retVal == kNoErr)
  1959. {
  1960. if (kNoErr == retVal)
  1961. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1962. if (kNoErr == retVal)
  1963. retVal = StrmPutWordAsciiHex(stream, wPrev);
  1964. UFLsprintf(strmbuf, cchstrmbuf, "%u", bCMapV2 ? wPrev - NUM_32K_1 : wPrev);
  1965. if (kNoErr == retVal)
  1966. retVal = StrmPutStringEOL(stream, strmbuf);
  1967. }
  1968. if (nLen % 100 == 0)
  1969. {
  1970. if (100 < nCount - nLen)
  1971. UFLsprintf(strmbuf, cchstrmbuf, "endcidrange 100 begincidrange");
  1972. else if (0 < nCount - nLen)
  1973. UFLsprintf(strmbuf, cchstrmbuf, "endcidrange %d begincidrange", nCount-nLen);
  1974. else
  1975. UFLsprintf(strmbuf, cchstrmbuf, " ");
  1976. }
  1977. else
  1978. continue; /* Do next record. */
  1979. if (retVal == kNoErr)
  1980. retVal = StrmPutStringEOL(stream, strmbuf);
  1981. }
  1982. if (retVal == kNoErr)
  1983. retVal = StrmPutStringEOL(stream, "endcidrange");
  1984. /* End of additional 32K+ CMap code. */
  1985. }
  1986. }
  1987. SENDCMAPFFFF_V_ENDCMAP:
  1988. if (retVal == kNoErr)
  1989. retVal = StrmPutStringEOL(stream, "endcmap CMapName currentdict "
  1990. "/CMap defineresource pop end end");
  1991. return retVal;
  1992. }
  1993. /*============================================================================*
  1994. * End Code To Support More Than 32K Glyphs *
  1995. *============================================================================*/
  1996. long
  1997. AdjBBox(
  1998. long value,
  1999. UFLBool lowerleft
  2000. )
  2001. {
  2002. if (lowerleft)
  2003. {
  2004. if (value > 0)
  2005. return (value - 1);
  2006. else if (value < 0)
  2007. return (value + 1);
  2008. else
  2009. return (value);
  2010. }
  2011. else
  2012. {
  2013. if (value > 0)
  2014. return (value + 1);
  2015. if (value < 0)
  2016. return (value - 1);
  2017. else
  2018. return (value);
  2019. }
  2020. }
  2021. UFLErrCode
  2022. T42CreateBaseFont(
  2023. UFOStruct *pUFObj,
  2024. const UFLGlyphsInfo *pGlyphs,
  2025. unsigned long *pVMUsage,
  2026. UFLBool bFullFont,
  2027. char *pHostFontName
  2028. )
  2029. {
  2030. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  2031. UFLFontProcs *pFontProcs = (UFLFontProcs *)&(pUFObj->pUFL->fontProcs);
  2032. UFLHANDLE stream = pUFObj->pUFL->hOut;
  2033. UFLErrCode retVal = kNoErr;
  2034. unsigned long cidCount, tableSize, tableSize1, sizeUsed;
  2035. UFLCMapInfo *pCMap;
  2036. char strmbuf[256];
  2037. /* Sanity check */
  2038. if (pFont == nil)
  2039. return kErrInvalidHandle;
  2040. /*
  2041. * Download procsets.
  2042. */
  2043. if (pUFObj->pUFL->outDev.pstream->pfDownloadProcset == 0)
  2044. return kErrDownloadProcset;
  2045. if (!pUFObj->pUFL->outDev.pstream->pfDownloadProcset(pUFObj->pUFL->outDev.pstream, kT42Header))
  2046. return kErrDownloadProcset;
  2047. if (IS_TYPE42CID_KEYEDFONT(pUFObj->lDownloadFormat))
  2048. {
  2049. if (!pUFObj->pUFL->outDev.pstream->pfDownloadProcset(pUFObj->pUFL->outDev.pstream, kCMap_FF))
  2050. return kErrDownloadProcset;
  2051. }
  2052. /*
  2053. * There is a bumpy road ahead when kFontInit2 state.
  2054. */
  2055. if (UFO_FONT_INIT2(pUFObj))
  2056. goto T42CreateBaseFont_FontInit2_1;
  2057. /*
  2058. * Generate the minimal sfnt.
  2059. */
  2060. retVal = GetMinSfnt(pUFObj, bFullFont);
  2061. if (kNoErr == retVal)
  2062. retVal = FillInHeadTable(pUFObj);
  2063. if (kNoErr == retVal)
  2064. pFont->info.fData.cNumGlyphs = GetNumGlyphs(pUFObj);
  2065. if (kNoErr == retVal)
  2066. {
  2067. tableSize = GetTableSize(pUFObj, pFont->pMinSfnt, LOCA_TABLE);
  2068. if (tableSize)
  2069. {
  2070. /*
  2071. * The following code includes fix for #317027 and #316096: load
  2072. * 'loca' table and set the extra glyph offset entry if it's
  2073. * missing and the delta from the last glyph offset is less than
  2074. * 4K for safety.
  2075. */
  2076. unsigned long expectedTableSize = pFont->info.fData.cNumGlyphs + 1;
  2077. expectedTableSize *= pFont->headTable.indexToLocFormat ? 4 : 2;
  2078. // Fixed bug 516514
  2079. if (expectedTableSize > tableSize)
  2080. {
  2081. sizeUsed = expectedTableSize;
  2082. pFont->pLocaTable = UFLNewPtr(pUFObj->pMem, expectedTableSize);
  2083. }
  2084. else
  2085. {
  2086. sizeUsed = tableSize;
  2087. pFont->pLocaTable = UFLNewPtr(pUFObj->pMem, tableSize);
  2088. }
  2089. if (pFont->pLocaTable)
  2090. {
  2091. if (GetFontTable(pUFObj, LOCA_TABLE, (unsigned char *)pFont->pLocaTable, sizeUsed) == 0)
  2092. {
  2093. retVal = kErrGetFontData;
  2094. }
  2095. else if (expectedTableSize > tableSize)
  2096. {
  2097. unsigned long glyfTableSize = GetTableSize(pUFObj, pFont->pMinSfnt, GLYF_TABLE);
  2098. unsigned char *pTable, *pExtraEntry;
  2099. unsigned long lastValidOffset;
  2100. pTable = (unsigned char *)pFont->pLocaTable;
  2101. if (pFont->headTable.indexToLocFormat)
  2102. {
  2103. unsigned long *pLastEntry =
  2104. (unsigned long *)(pTable + (pFont->info.fData.cNumGlyphs - 1) * 4);
  2105. lastValidOffset = MOTOROLALONG(*pLastEntry);
  2106. if (glyfTableSize - lastValidOffset < 4097)
  2107. {
  2108. pExtraEntry = (unsigned char *)(pLastEntry + 1);
  2109. *pExtraEntry++ = (unsigned char)((glyfTableSize & 0xFF000000) >> 24);
  2110. *pExtraEntry++ = (unsigned char)((glyfTableSize & 0x00FF0000) >> 16);
  2111. *pExtraEntry++ = (unsigned char)((glyfTableSize & 0x0000FF00) >> 8);
  2112. *pExtraEntry = (unsigned char)((glyfTableSize & 0x000000FF));
  2113. }
  2114. }
  2115. else
  2116. {
  2117. unsigned short *pLastEntry =
  2118. (unsigned short *)(pTable + (pFont->info.fData.cNumGlyphs - 1) * 2);
  2119. lastValidOffset = MOTOROLAINT(*pLastEntry);
  2120. if (glyfTableSize - lastValidOffset < 4097)
  2121. {
  2122. pExtraEntry = (unsigned char *)(pLastEntry + 1);
  2123. *pExtraEntry++ = (unsigned char)((glyfTableSize & 0x0000FF00) >> 8);
  2124. *pExtraEntry = (unsigned char)((glyfTableSize & 0x000000FF));
  2125. }
  2126. }
  2127. }
  2128. }
  2129. else
  2130. retVal = kErrOutOfMemory;
  2131. }
  2132. else
  2133. retVal = kErrGetFontData;
  2134. }
  2135. if (kNoErr == retVal)
  2136. {
  2137. /* Fix blue screen bug 278017. */
  2138. tableSize = pFont->minSfntSize; /* instead of GetGlyphTableSize(pUFObj) */
  2139. if (!bFullFont)
  2140. tableSize += GetGlyphTableSize(pUFObj);
  2141. if (((tableSize / SFNT_STRINGSIZE) * 5 / 4) > NUM_16KSTR)
  2142. tableSize = (tableSize / SFNT_STRINGSIZE) * 5 / 4;
  2143. else
  2144. tableSize = NUM_16KSTR;
  2145. tableSize1 = tableSize + 1;
  2146. pFont->pStringLength =
  2147. (unsigned long *)UFLNewPtr(pUFObj->pMem, tableSize1 * sizeof(unsigned long));
  2148. if (pFont->pStringLength)
  2149. retVal = CalculateStringLength(pUFObj, pFont, tableSize1);
  2150. else
  2151. retVal = kErrOutOfMemory;
  2152. }
  2153. //////////////////////////////////////////////////////////////////////////
  2154. //
  2155. // /sfnts initialization is done. Actual downloading begins here.
  2156. //
  2157. //////////////////////////////////////////////////////////////////////////
  2158. /*
  2159. * Send out left upper right lower values.
  2160. */
  2161. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2162. {
  2163. // Fixed bug #516915
  2164. if (0 == pFont->headTable.unitsPerEm)
  2165. retVal = kErrGetFontData;
  2166. else
  2167. {
  2168. /*
  2169. * The first four values are the font bounding box. We convert all
  2170. * floats into 24.8 fixed values. Make sure the bounding box doesn't
  2171. * get truncated down to a smaller area.
  2172. */
  2173. UFLsprintfEx(strmbuf, CCHOF(strmbuf), "%f %f %f %f",
  2174. (AdjBBox((long)pFont->headTable.xMin, 1) << 8) / (long)pFont->headTable.unitsPerEm,
  2175. (AdjBBox((long)pFont->headTable.yMin, 1) << 8) / (long)pFont->headTable.unitsPerEm,
  2176. (AdjBBox((long)pFont->headTable.xMax, 0) << 8) / (long)pFont->headTable.unitsPerEm,
  2177. (AdjBBox((long)pFont->headTable.yMax, 0) << 8) / (long)pFont->headTable.unitsPerEm);
  2178. retVal = StrmPutStringEOL(pUFObj->pUFL->hOut, strmbuf);
  2179. }
  2180. }
  2181. /*
  2182. * Send out encoding name.
  2183. */
  2184. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2185. {
  2186. /*
  2187. * Always emit Encoding array filled with /.notdef (due to bug fix
  2188. * #273021).
  2189. */
  2190. retVal = StrmPutString(stream, gnotdefArray);
  2191. }
  2192. /*
  2193. * Send out font name.
  2194. */
  2195. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2196. {
  2197. /*
  2198. * If CID-keyed font, then append "CID" to the CIDFont name so that
  2199. * CID_Resource is also consisted of the original fontName.
  2200. */
  2201. if (IS_TYPE42CID_KEYEDFONT(pUFObj->lDownloadFormat))
  2202. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s", pFont->info.CIDFontName, gcidSuffix[0]);
  2203. else
  2204. UFLsprintf(strmbuf, CCHOF(strmbuf), " /%s", pUFObj->pszFontName);
  2205. retVal = StrmPutStringEOL(stream, strmbuf);
  2206. }
  2207. /*
  2208. * First landing place when kFontInit2 state.
  2209. */
  2210. T42CreateBaseFont_FontInit2_1:
  2211. /*
  2212. * Setup for CID-keyed-font or CIDFont-Resource downloading.
  2213. */
  2214. if ((kNoErr == retVal) && IS_TYPE42CID(pUFObj->lDownloadFormat))
  2215. {
  2216. //
  2217. // hasvmtx is used to determine whether to call the AddT42vmtxEntry
  2218. // function later.
  2219. //
  2220. unsigned long tblSize = GETTTFONTDATA(pUFObj,
  2221. VMTX_TABLE, 0L,
  2222. nil, 0L,
  2223. pFont->info.fData.fontIndex);
  2224. pUFObj->pAFont->hasvmtx = tblSize ? 1 : 0;
  2225. if (pFont->info.bUseIdentityCMap)
  2226. {
  2227. UFLBool bUseCMap2 = 0;
  2228. cidCount = UFO_NUM_GLYPHS(pUFObj);
  2229. /*
  2230. * Use '2' version of CMap if the number of glyphs are greater
  2231. * than 32K *and* this is not a %hostfont% font.
  2232. */
  2233. if((NUM_32K_1 < cidCount) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2234. bUseCMap2 = 1;
  2235. if (IS_TYPE42CID_H(pUFObj->lDownloadFormat))
  2236. pCMap = bUseCMap2 ? &CMapInfo_FF_H2 : &CMapInfo_FF_H;
  2237. else
  2238. pCMap = bUseCMap2 ? &CMapInfo_FF_V2 : &CMapInfo_FF_V;
  2239. }
  2240. else
  2241. {
  2242. cidCount = pFont->info.CIDCount;
  2243. /* If CMap is provided, use it. */
  2244. pCMap = &(pFont->info.CMap);
  2245. }
  2246. }
  2247. /*
  2248. * Need one more warp when kFontInit2 state.
  2249. */
  2250. if (UFO_FONT_INIT2(pUFObj))
  2251. goto T42CreateBaseFont_FontInit2_2;
  2252. /*
  2253. * Begin font dictionary download.
  2254. */
  2255. if ((kNoErr == retVal)
  2256. && IS_TYPE42CID(pUFObj->lDownloadFormat)
  2257. && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2258. {
  2259. /*
  2260. * If downloading CID Type 42, add CIDSysInfo, CIDCount, CIDMap, and
  2261. * CDevProc.
  2262. */
  2263. /* Registry, Ordering, and Suppliment */
  2264. UFLsprintf(strmbuf, CCHOF(strmbuf),
  2265. "(%s) (%s) %d",
  2266. pCMap->Registry, pCMap->Ordering, pCMap->Supplement);
  2267. if (kNoErr == retVal)
  2268. retVal = StrmPutStringEOL(stream, strmbuf);
  2269. /* CIDCount */
  2270. UFLsprintf(strmbuf, CCHOF(strmbuf), "%lu", min(cidCount, (long)NUM_32K_1));
  2271. if (kNoErr == retVal)
  2272. retVal = StrmPutStringEOL(stream, strmbuf);
  2273. /* CIDMap */
  2274. if (pFontProcs->pfGetCIDMap
  2275. && (tableSize = pFontProcs->pfGetCIDMap(pUFObj->hClientData, nil, 0)))
  2276. {
  2277. char* pCIDMap = UFLNewPtr(pUFObj->pMem, tableSize);
  2278. if (pCIDMap)
  2279. {
  2280. tableSize = pFontProcs->pfGetCIDMap(pUFObj->hClientData, pCIDMap, tableSize);
  2281. /* The pCIDMap is already ASCII, so just send it using PutBytes(). */
  2282. if (kNoErr == retVal)
  2283. StrmPutBytes(stream, pCIDMap, (UFLsize_t) tableSize, 1);
  2284. UFLDeletePtr(pUFObj->pMem, pCIDMap);
  2285. }
  2286. }
  2287. else
  2288. {
  2289. /*
  2290. * IDStr creates an Identity string.
  2291. * WCC - IDStrNull creates a strings which maps all CIDs to GID 0.
  2292. * Bug #260864. Use IDStrNull for Character Code mode.
  2293. */
  2294. if (pFont->info.bUpdateCIDMap)
  2295. UFLsprintf(strmbuf, CCHOF(strmbuf), "%lu IDStrNull", min(cidCount - 1, (long)NUM_32K_1));
  2296. else
  2297. UFLsprintf(strmbuf, CCHOF(strmbuf), "%lu IDStr", min(cidCount - 1, (long)NUM_32K_1));
  2298. if (kNoErr == retVal)
  2299. retVal = StrmPutStringEOL(stream, strmbuf);
  2300. }
  2301. /*
  2302. * CDevProc
  2303. *
  2304. * Further investigation due to #351487 led us to download Metrics2
  2305. * array with TopSideBearing/EM as vy for EVERY glyph and generate
  2306. * the following metrics in CDevProc:
  2307. *
  2308. * W1x = 0
  2309. * W1y = -AdvancedHeight / EM
  2310. * vx = descender / EM
  2311. * vy = ury + TopSideBearing / EM
  2312. *
  2313. * According to this, the CDevProc became very simple like this:
  2314. *
  2315. * {pop 4 index add}
  2316. *
  2317. * On the other hand, if the TrueType font doesn't have 'vmtx' table,
  2318. * then the driver never download Metrics2 for any glyph at all and
  2319. * the following CDevProc is use instead:
  2320. *
  2321. * {5 {pop} repeat 0 -1 descender/em ascender/em}
  2322. *
  2323. * This is an agreement between the driver and %hostfont% teams to
  2324. * make the inks from %hostfont% RIP and non %hostfont% RIP match.
  2325. * (...but this is not actually the same CDevProc %hostfont% RIP
  2326. * uses. Ascender and descender values %hostfont% RIP uses are the
  2327. * ones from 'vhea' or 'hhea'. Whereas, ascender and descender values
  2328. * the driver uses to generate this CDevProc are from 'OS/2' or 'hhea'.
  2329. * A font, almost always, has 'OS/2' and 'hhea', hence the CDevProc
  2330. * downloaded by the driver and the one generated by %hostfont% RIP
  2331. * aren't same normally.)
  2332. *
  2333. * Other bug numbers related with this problem are 277035, 277063,
  2334. * 303540, and 309104.
  2335. */
  2336. {
  2337. if (pUFObj->pAFont->hasvmtx)
  2338. {
  2339. UFLsprintf(strmbuf, CCHOF(strmbuf), "{pop 4 index add}bind");
  2340. }
  2341. else
  2342. {
  2343. long em, w1y, vx, vy, tsb, vasc;
  2344. UFLBool bUseDef;
  2345. GetMetrics2FromTTF(pUFObj, 0, &em, &w1y, &vx, &vy, &tsb, &bUseDef, 1, &vasc);
  2346. UFLsprintf(strmbuf, CCHOF(strmbuf),
  2347. "{5{pop}repeat 0 -1 %ld %ld div %ld %ld div}bind",
  2348. vx, em, vy, em);
  2349. }
  2350. if (kNoErr == retVal)
  2351. retVal = StrmPutStringEOL(stream, strmbuf);
  2352. }
  2353. UFLsprintf(strmbuf, CCHOF(strmbuf), "CIDT42Begin");
  2354. if (kNoErr == retVal)
  2355. retVal = StrmPutStringEOL(stream, strmbuf);
  2356. }
  2357. else if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  2358. {
  2359. /* Plain Type 42 format */
  2360. if (kNoErr == retVal)
  2361. retVal = StrmPutStringEOL(stream, "Type42DictBegin");
  2362. }
  2363. //////////////////////////////////////////////////////////////////////////
  2364. //
  2365. // Either Type42DictBegin or CIDT42Begin has just emitted.
  2366. // Begin downloading /sfnts array
  2367. //
  2368. //////////////////////////////////////////////////////////////////////////
  2369. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  2370. {
  2371. if (kNoErr == retVal)
  2372. retVal = StrmPutString(stream, "[");
  2373. if (kNoErr == retVal)
  2374. {
  2375. /* Remember Number of strings of all otherTables sent. */
  2376. if (StrmCanOutputBinary(stream))
  2377. pFont->cOtherTables = PSSendSfntsBinary(pUFObj);
  2378. else
  2379. pFont->cOtherTables = PSSendSfntsAsciiHex(pUFObj);
  2380. }
  2381. if ((kNoErr == retVal) && !bFullFont)
  2382. retVal = GenerateGlyphStorageExt(pUFObj, tableSize1);
  2383. if (kNoErr == retVal)
  2384. retVal = StrmPutStringEOL(stream, "]def ");
  2385. }
  2386. //////////////////////////////////////////////////////////////////////////
  2387. //
  2388. // /sfnts array downloading completed. Then emit extra info, such as
  2389. // FontInfo, FSType, and XUID.
  2390. //
  2391. //////////////////////////////////////////////////////////////////////////
  2392. if ((kNoErr == retVal) && !bFullFont && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2393. {
  2394. /* Invoke procedure to prepare for 2015 incremental downloading. */
  2395. retVal = StrmPutInt(stream, GetTableDirectoryOffset(pFont, LOCA_TABLE));
  2396. if (kNoErr == retVal)
  2397. retVal = StrmPutString(stream, " ");
  2398. if (kNoErr == retVal)
  2399. retVal = StrmPutInt(stream, GetTableDirectoryOffset(pFont, GLYF_TABLE));
  2400. if (kNoErr == retVal)
  2401. retVal = StrmPutStringEOL(stream, " ");
  2402. if (kNoErr == retVal)
  2403. retVal = StrmPutStringEOL(stream, "PrepFor2015");
  2404. }
  2405. /*
  2406. * Add FontInfo dict if 'post' table is not good as of today. We only need
  2407. * this info in FontInfo dict.
  2408. */
  2409. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2410. {
  2411. retVal = StrmPutStringEOL(stream, "AddFontInfoBegin");
  2412. pUFObj->dwFlags |= UFO_HasFontInfo;
  2413. }
  2414. /*
  2415. * GoodName
  2416. * Ignore to test whether this font has good 'post' table and always emit
  2417. * AddFontInfo to include glyph name to Unicode mapping.
  2418. */
  2419. // if (!BHasGoodPostTable(pUFObj))
  2420. // {
  2421. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2422. {
  2423. UFLsprintf(strmbuf, CCHOF(strmbuf), "AddFontInfo");
  2424. if (kNoErr == retVal)
  2425. {
  2426. retVal = StrmPutStringEOL(stream, strmbuf);
  2427. pUFObj->dwFlags |= UFO_HasG2UDict;
  2428. }
  2429. }
  2430. // }
  2431. /*
  2432. * Add more font properties to FontInfo of the current dict.
  2433. */
  2434. if ((kNoErr == retVal)
  2435. && pFontProcs->pfAddFontInfo
  2436. && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2437. {
  2438. char *pBuffer;
  2439. int bufLen = 1000;
  2440. pBuffer = UFLNewPtr(pUFObj->pMem, bufLen);
  2441. if (pBuffer)
  2442. {
  2443. pFontProcs->pfAddFontInfo(pUFObj->hClientData, pBuffer, bufLen);
  2444. retVal = StrmPutStringEOL(stream, pBuffer);
  2445. UFLDeletePtr(pUFObj->pMem, pBuffer);
  2446. }
  2447. pBuffer = nil;
  2448. }
  2449. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2450. {
  2451. /* Fixing bug 284250. Add /FSType to FontInfoDict. */
  2452. long fsType;
  2453. if ((fsType = GetOS2FSType(pUFObj)) == -1)
  2454. fsType = 4;
  2455. UFLsprintf(strmbuf, CCHOF(strmbuf), "/FSType %ld def", fsType);
  2456. retVal = StrmPutStringEOL(stream, strmbuf);
  2457. }
  2458. /*
  2459. * End FontInfo.
  2460. */
  2461. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2462. retVal = StrmPutStringEOL(stream, "AddFontInfoEnd");
  2463. /*
  2464. * Optionally add XUID.
  2465. */
  2466. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2467. {
  2468. unsigned long sSize = pUFObj->pAFont->Xuid.sSize;
  2469. if (sSize)
  2470. {
  2471. unsigned long *pXUID = pUFObj->pAFont->Xuid.pXUID;
  2472. retVal = StrmPutString(stream, "[");
  2473. while (sSize)
  2474. {
  2475. UFLsprintf(strmbuf, CCHOF(strmbuf), "16#%x ", *pXUID);
  2476. if (kNoErr == retVal)
  2477. retVal = StrmPutString(stream, strmbuf);
  2478. pXUID++;
  2479. sSize--;
  2480. }
  2481. UFLsprintf(strmbuf, CCHOF(strmbuf), "] AddXUID");
  2482. if (kNoErr == retVal)
  2483. retVal = StrmPutStringEOL(stream, strmbuf);
  2484. }
  2485. }
  2486. /*
  2487. * End font dictionary download.
  2488. */
  2489. if (IS_TYPE42CID(pUFObj->lDownloadFormat) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  2490. {
  2491. /* End CID Type 42 CIDFont resource creation. */
  2492. if (kNoErr == retVal)
  2493. {
  2494. UFLsprintf(strmbuf, CCHOF(strmbuf), "CIDT42End");
  2495. if (kNoErr == retVal)
  2496. retVal = StrmPutStringEOL(stream, strmbuf);
  2497. }
  2498. }
  2499. else if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  2500. {
  2501. /* End plain Type 42 font creation. */
  2502. if (kNoErr == retVal)
  2503. retVal = StrmPutStringEOL(stream, "Type42DictEnd");
  2504. }
  2505. //////////////////////////////////////////////////////////////////////////
  2506. //
  2507. // End downloading with Type42DictEnd or CIDT42End.
  2508. //
  2509. // When the font is a Roman TrueType font, a ready-to-use, Type 42 font
  2510. // has been defined.
  2511. //
  2512. // When the font is a CJK TrueType font, a CIDFont resource has been
  2513. // defined. But it's just a CIDFont and we still need to perform extra
  2514. // work in order to define a CID-Keyed font, which is:
  2515. //
  2516. // 1. Define a CMap with rotated GlyphIDs if this is a vertical font.
  2517. // 2. Do composefont with the CIDFont and the CMap(s).
  2518. //
  2519. //////////////////////////////////////////////////////////////////////////
  2520. /*
  2521. * Final landing place when kFontInit2 state.
  2522. */
  2523. T42CreateBaseFont_FontInit2_2:
  2524. /*
  2525. * At this point, a CIDFont resource is created. If the request is to
  2526. * do kTTType42CID_Resource, we are done.
  2527. */
  2528. if ((kNoErr == retVal) && IS_TYPE42CID_KEYEDFONT(pUFObj->lDownloadFormat))
  2529. {
  2530. /*
  2531. * Instantiate the CMap resource if do composefont - notice a convention
  2532. * used here: CMAP-cmapname is used to instantiate cmapname.
  2533. * See CMap_FF.ps as an example.
  2534. */
  2535. if (kNoErr == retVal)
  2536. {
  2537. UFLsprintf(strmbuf, CCHOF(strmbuf), "CMAP-%s", pCMap->CMapName);
  2538. if (kNoErr == retVal)
  2539. retVal = StrmPutStringEOL(stream, strmbuf);
  2540. }
  2541. /*
  2542. * Now we can construct CID-keyed font from the CIDFont reosurce and CMap.
  2543. *
  2544. * e.g. /TT3782053888t0 /WinCharSetFFFF-H [/TT3782053888t0cid] composefont pop
  2545. *
  2546. * !!!BUT!!!, if there are more than 32K glyphs (like some Korean TT Fonts),
  2547. * we need to make copies of the CIDFont Resource and make use of more than
  2548. * one CMap - it's ugly, but it's the only way to do it. PPeng, 11-12-1996
  2549. */
  2550. if (pUFObj->lDownloadFormat == kTTType42CID_H)
  2551. {
  2552. /*
  2553. * Horizontal
  2554. * We need 1 or 2 CIDFonts when downloading it by ourselves.
  2555. * But, when this font is available as %hostfont%, we can simple
  2556. * composefont it without any trick.
  2557. */
  2558. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  2559. {
  2560. if (cidCount <= NUM_32K_1)
  2561. {
  2562. /*
  2563. * We create a CID-keyed font using only one CIDFont.
  2564. */
  2565. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s%s] composefont pop",
  2566. pUFObj->pszFontName,
  2567. pCMap->CMapName,
  2568. pFont->info.CIDFontName, gcidSuffix[0]);
  2569. if (kNoErr == retVal)
  2570. retVal = StrmPutStringEOL(stream, strmbuf);
  2571. }
  2572. else
  2573. {
  2574. /*
  2575. * We create a CID-keyed font using two CIDFonts.
  2576. * Make a copy of the CIDFont so we can access 32K+ glyphs.
  2577. *
  2578. * But, when this is a %hostfont% font, we don't need to
  2579. * create a copy. Simply do composefont.
  2580. */
  2581. UFLsprintf(strmbuf, CCHOF(strmbuf), "%lu dup 1 sub %lu IDStr2 /%s%s /%s%s T42CIDCP32K",
  2582. cidCount - (long)NUM_32K_1, (long)NUM_32K_1,
  2583. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K],
  2584. pFont->info.CIDFontName, gcidSuffix[0]);
  2585. if (kNoErr == retVal)
  2586. retVal = StrmPutString(stream, strmbuf);
  2587. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s%s ",
  2588. pUFObj->pszFontName, pCMap->CMapName,
  2589. pFont->info.CIDFontName, gcidSuffix[0]);
  2590. if (kNoErr == retVal)
  2591. retVal = StrmPutString(stream, strmbuf);
  2592. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s] composefont pop",
  2593. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K]);
  2594. if (kNoErr == retVal)
  2595. retVal = StrmPutStringEOL(stream, strmbuf);
  2596. }
  2597. }
  2598. else
  2599. {
  2600. /*
  2601. * %hostfont% support
  2602. * Simply composefont this %hostfont% font with
  2603. * %%IncludeResource DSC comment.
  2604. */
  2605. UFLsprintf(strmbuf, CCHOF(strmbuf), "%%%%IncludeResource: CIDFont %s",
  2606. pHostFontName);
  2607. if (kNoErr == retVal)
  2608. retVal = StrmPutStringEOL(stream, strmbuf);
  2609. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s] composefont pop",
  2610. pUFObj->pszFontName,
  2611. pCMap->CMapName,
  2612. pHostFontName);
  2613. if (kNoErr == retVal)
  2614. retVal = StrmPutStringEOL(stream, strmbuf);
  2615. }
  2616. }
  2617. else
  2618. {
  2619. /*
  2620. * Vertical
  2621. * We need 2 or 4 CIDFonts when downloading it by ourselves.
  2622. * But, when this font is available as %hostfont%, we can simple
  2623. * composefont it without any trick.
  2624. */
  2625. /*
  2626. * Prior to composefont, instanciate a veritcal CMap and rearrange
  2627. * it with rotated glyph IDs.
  2628. */
  2629. char *newCMapName;
  2630. DWORD cbCMapNameSize;
  2631. cbCMapNameSize = UFLstrlen(pCMap->CMapName)
  2632. + UFLstrlen(pFont->info.CIDFontName)
  2633. + 1;
  2634. newCMapName = (char*)UFLNewPtr(pUFObj->pMem, cbCMapNameSize);
  2635. if (newCMapName)
  2636. UFLsprintf(newCMapName, cbCMapNameSize / sizeof(char),
  2637. "%s%s",
  2638. pCMap->CMapName, pFont->info.CIDFontName);
  2639. else
  2640. retVal = kErrOutOfMemory;
  2641. /* Get rotated glyph IDs. */
  2642. if (kNoErr == retVal)
  2643. retVal = T42GetRotatedGIDs(pUFObj, pFont);
  2644. if (kNoErr == retVal)
  2645. retVal = T42SendCMapWinCharSetFFFF_V(pUFObj, pFont->pRotatedGlyphIDs,
  2646. (short)(pFont->numRotatedGlyphIDs),
  2647. pCMap, newCMapName, cidCount,
  2648. stream, strmbuf, CCHOF(strmbuf));
  2649. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  2650. {
  2651. if (cidCount <= NUM_32K_1)
  2652. {
  2653. /*
  2654. * We need 2 CIDFonts.
  2655. * Make a copy of the CIDFont so we can access rotated
  2656. * glyphs.
  2657. */
  2658. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /%s%s T42CIDCPR",
  2659. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_R],
  2660. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX]);
  2661. if (kNoErr == retVal)
  2662. retVal = StrmPutStringEOL(stream, strmbuf);
  2663. /* Now create a CID-Keyed Font using the two CIDFonts. */
  2664. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s%s /%s%s] composefont pop",
  2665. pUFObj->pszFontName,
  2666. newCMapName,
  2667. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX],
  2668. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_R]);
  2669. if (kNoErr == retVal)
  2670. retVal = StrmPutStringEOL(stream, strmbuf);
  2671. }
  2672. else
  2673. {
  2674. /*
  2675. * We need 4 CIDFonts.
  2676. * Make copies of the CIDFont so we can access 32K+ glyphs.
  2677. */
  2678. UFLsprintf(strmbuf, CCHOF(strmbuf), "%lu dup 1 sub %lu IDStr2 /%s%s /%s%s T42CIDCP32K",
  2679. cidCount - (long)NUM_32K_1, (long)NUM_32K_1,
  2680. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K],
  2681. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX]);
  2682. if (kNoErr == retVal)
  2683. retVal = StrmPutStringEOL(stream, strmbuf);
  2684. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /%s%s T42CIDCPR",
  2685. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_R],
  2686. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX]);
  2687. if (kNoErr == retVal)
  2688. retVal = StrmPutStringEOL(stream, strmbuf);
  2689. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /%s%s T42CIDCPR",
  2690. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32KR],
  2691. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K]);
  2692. if (kNoErr == retVal)
  2693. retVal = StrmPutStringEOL(stream, strmbuf);
  2694. /*
  2695. * Now create a CID-Keyed Font using the four CIDFonts.
  2696. */
  2697. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s%s ",
  2698. pUFObj->pszFontName, newCMapName,
  2699. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX]);
  2700. if (kNoErr == retVal)
  2701. retVal = StrmPutStringEOL(stream, strmbuf);
  2702. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /%s%s /%s%s] composefont pop",
  2703. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_R],
  2704. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K],
  2705. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32KR] );
  2706. if (kNoErr == retVal)
  2707. retVal = StrmPutStringEOL(stream, strmbuf);
  2708. }
  2709. }
  2710. else
  2711. {
  2712. /*
  2713. * %hostfont% support
  2714. * CIDMap bug has to be fixed on HostFont capable RIP. No need
  2715. * to split glyphs in multiple CIDFonts even if the numbers of
  2716. * the glyphs are greater than 32K.
  2717. */
  2718. UFLsprintf(strmbuf, CCHOF(strmbuf), "%%%%IncludeResource: CIDFont %s", pHostFontName);
  2719. if (kNoErr == retVal)
  2720. retVal = StrmPutStringEOL(stream, strmbuf);
  2721. /*
  2722. * Fix 384736: GDI and %hostfont%-RIP get ascender and
  2723. * descender values from different tables; GDI gets them from
  2724. * 'OS/2' or 'hhea' vs. %hostfont%-RIP gets them from 'vhea' or
  2725. * 'hhea'. This causes the output on the screen and ink from
  2726. * %hostfont%-RIP different. To adjust 'the policy difference'
  2727. * with three types of real-world CJK TrueType fonts -
  2728. * 1) the good, which has 'vhea' and 'vmtx', and ascender and
  2729. * descender values are consistent throughout 'OS/2',
  2730. * 'vhea', and 'hhea' tables.
  2731. * 2) the bad, which doesn't have 'vhea' and/or 'vmtx' tables.
  2732. * 3) the ugry, which has 'vhea' and/or 'vmtx' tables but
  2733. * their ascender and descender values are inconsistent
  2734. * throughout 'OS/2', 'vhea', and 'hhea' tables.
  2735. * - the driver needs to change glyph metrics by installing
  2736. * either special CDevProc for 3 or adjusted FontMatrix for 2.
  2737. */
  2738. {
  2739. long em, w1y, vx, vy, tsb, vasc;
  2740. UFLBool bUseDef;
  2741. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s ", pHostFontName, gcidSuffix[CIDSUFFIX]);
  2742. if (kNoErr == retVal)
  2743. retVal = StrmPutString(stream, strmbuf);
  2744. GetMetrics2FromTTF(pUFObj, 0, &em, &w1y, &vx, &vy, &tsb, &bUseDef, 1, &vasc);
  2745. if (pUFObj->pAFont->hasvmtx && (vy != vasc))
  2746. {
  2747. UFLsprintf(strmbuf, CCHOF(strmbuf), "%ld %ld sub %ld div", vy, vasc, em);
  2748. }
  2749. else if (!pUFObj->pAFont->hasvmtx)
  2750. {
  2751. UFLsprintf(strmbuf, CCHOF(strmbuf), "{5{pop}repeat 0 -1 %ld %ld div %ld %ld div}bind", vx, em, vy, em);
  2752. }
  2753. else
  2754. {
  2755. UFLsprintf(strmbuf, CCHOF(strmbuf), "true");
  2756. }
  2757. if (kNoErr == retVal)
  2758. retVal = StrmPutString(stream, strmbuf);
  2759. UFLsprintf(strmbuf, CCHOF(strmbuf), " /%s hfDef42CID", pHostFontName);
  2760. }
  2761. if (kNoErr == retVal)
  2762. retVal = StrmPutStringEOL(stream, strmbuf);
  2763. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /%s hfDefRT42CID",
  2764. pUFObj->pszFontName, gcidSuffix[CIDSUFFIX_R],
  2765. pHostFontName);
  2766. if (kNoErr == retVal)
  2767. retVal = StrmPutStringEOL(stream, strmbuf);
  2768. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /%s [/%s%s /%s%s] composefont pop",
  2769. pUFObj->pszFontName,
  2770. newCMapName,
  2771. pHostFontName, gcidSuffix[CIDSUFFIX],
  2772. pUFObj->pszFontName, gcidSuffix[CIDSUFFIX_R]);
  2773. if (kNoErr == retVal)
  2774. retVal = StrmPutStringEOL(stream, strmbuf);
  2775. }
  2776. if (newCMapName)
  2777. UFLDeletePtr(pUFObj->pMem, newCMapName);
  2778. }
  2779. }
  2780. else if (HOSTFONT_IS_VALID_UFO(pUFObj))
  2781. {
  2782. /*
  2783. * %hostfont% support
  2784. * Redefine the font using the already existing TrueType host font with
  2785. * a unque name so that we can reencode its encoding vector freely. We
  2786. * want empty CharStrings so that we give true to hfRedefFont.
  2787. */
  2788. UFLsprintf(strmbuf, CCHOF(strmbuf), "\n%%%%IncludeResource: font %s", pHostFontName);
  2789. if (kNoErr == retVal)
  2790. retVal = StrmPutStringEOL(stream, strmbuf);
  2791. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s true /%s hfRedefFont", pUFObj->pszFontName, pHostFontName);
  2792. if (kNoErr == retVal)
  2793. retVal = StrmPutStringEOL(stream, strmbuf);
  2794. }
  2795. //////////////////////////////////////////////////////////////////////////
  2796. //
  2797. // The TrueType font has been Downloaded and defined. Cleanup mess.
  2798. //
  2799. //////////////////////////////////////////////////////////////////////////
  2800. if ((kNoErr == retVal) && bFullFont)
  2801. {
  2802. UFLDeletePtr(pUFObj->pMem, pFont->pStringLength);
  2803. pFont->pStringLength = nil;
  2804. }
  2805. if (pFont->pMinSfnt)
  2806. {
  2807. UFLDeletePtr(pUFObj->pMem, pFont->pMinSfnt);
  2808. pFont->pMinSfnt = nil;
  2809. }
  2810. /*
  2811. * Free buffers allocated when error occurred. (bug #293130)
  2812. */
  2813. if (kNoErr != retVal)
  2814. {
  2815. if (pFont->pHeader != nil)
  2816. UFLDeletePtr(pUFObj->pMem, pFont->pHeader);
  2817. pFont->pHeader = nil;
  2818. if (pFont->pStringLength != nil)
  2819. UFLDeletePtr(pUFObj->pMem, pFont->pStringLength);
  2820. pFont->pStringLength = nil;
  2821. if (pFont->pLocaTable != nil)
  2822. UFLDeletePtr(pUFObj->pMem, pFont->pLocaTable);
  2823. pFont->pLocaTable = nil;
  2824. if (pFont->pRotatedGlyphIDs != nil)
  2825. UFLDeletePtr(pUFObj->pMem, pFont->pRotatedGlyphIDs);
  2826. pFont->pRotatedGlyphIDs = nil;
  2827. }
  2828. /*
  2829. * Change the font state.
  2830. */
  2831. if (kNoErr == retVal)
  2832. {
  2833. if (pUFObj->flState == kFontInit2)
  2834. {
  2835. /* This is a duplicate so that it should have char(s). */
  2836. pUFObj->flState = kFontHasChars;
  2837. }
  2838. else
  2839. pUFObj->flState = kFontHeaderDownloaded;
  2840. }
  2841. return retVal;
  2842. }
  2843. /*=============================================================================*
  2844. * PutT42Char and its sub functions *
  2845. *=============================================================================*/
  2846. UFLErrCode
  2847. T42UpdateCIDMap(
  2848. UFOStruct *pUFObj,
  2849. unsigned short wGlyfIndex,
  2850. unsigned short cid,
  2851. char *cidFontName,
  2852. UFLHANDLE stream,
  2853. char *strmbuf,
  2854. size_t cchstrmbuf
  2855. )
  2856. {
  2857. UFLErrCode retVal = kNoErr;
  2858. /* (2 * cid) is the BYTE-index in CIDMap. */
  2859. UFLsprintf(strmbuf, cchstrmbuf, "%ld ", (long)(2 * cid));
  2860. retVal = StrmPutString(stream, strmbuf);
  2861. if (retVal == kNoErr)
  2862. retVal = StrmPutWordAsciiHex(stream, wGlyfIndex);
  2863. UFLsprintf(strmbuf, cchstrmbuf, " /%s UpdateCIDMap", cidFontName);
  2864. if (retVal == kNoErr)
  2865. retVal = StrmPutStringEOL(stream, strmbuf);
  2866. return retVal;
  2867. }
  2868. UFLErrCode
  2869. AddT42vmtxEntry(
  2870. UFOStruct *pUFObj,
  2871. unsigned short wGlyfIndex,
  2872. unsigned short cid,
  2873. char *cidFontName,
  2874. UFLHANDLE stream,
  2875. char *strmbuf,
  2876. size_t cchstrmbuf
  2877. )
  2878. {
  2879. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  2880. UFLErrCode retVal = kNoErr;
  2881. long em, w1y, vx, vy, tsb, vasc;
  2882. UFLBool bUseDef;
  2883. /*
  2884. * Add vertical metrics array Metrics2 for every glyph regardless of
  2885. * writing mode (Fix #351487) if its 'vmtx' exists.
  2886. *
  2887. * The elements of Metrics2 array should basically look like this:
  2888. *
  2889. * [0 -AdvanceHeight/EM Descender/EM Ascender/EM]
  2890. *
  2891. * But, to support both fixed and proportional fonts universally we set
  2892. * TopSideBearing/EM as vy instead and add ury to it in CDevProc. So the
  2893. * array now looks like this:
  2894. *
  2895. * [0 -AdvanceHeight/EM Descender/EM TopSideBearing/EM]
  2896. *
  2897. * In CDevProc TopSideBearing/EM and ury are added to get real vy value
  2898. * for the glyph. See the code emitting /CDevProc in the T42CreateBaseFont
  2899. * function above for the details.
  2900. */
  2901. if (pUFObj->pAFont->hasvmtx)
  2902. {
  2903. GetMetrics2FromTTF(pUFObj, wGlyfIndex, &em, &w1y, &vx, &vy, &tsb, &bUseDef, 0, &vasc);
  2904. UFLsprintf(strmbuf, cchstrmbuf,
  2905. "%ld [0 %ld %ld div %ld %ld div %ld %ld div] /%s T0AddT42Mtx2",
  2906. (long)cid, -w1y, em, vx, em, tsb, em, cidFontName);
  2907. retVal = StrmPutStringEOL(stream, strmbuf);
  2908. }
  2909. return retVal;
  2910. }
  2911. unsigned short
  2912. GetCIDAndCIDFontName(
  2913. UFOStruct *pUFObj,
  2914. unsigned short wGid,
  2915. char *cidFontName,
  2916. size_t cchFontName
  2917. )
  2918. /*++
  2919. Routine Description:
  2920. Retunrs cid - a number and the cidFontName.
  2921. --*/
  2922. {
  2923. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  2924. unsigned short cid = 0;
  2925. if (IS_TYPE42CID_KEYEDFONT(pUFObj->lDownloadFormat))
  2926. {
  2927. /*
  2928. * For CID-Keyed font, we control the CIDFont name.
  2929. */
  2930. if (pFont->info.bUseIdentityCMap && (wGid > NUM_32K_1))
  2931. {
  2932. /*
  2933. * 32K+ glyphs are re-mapped to the 32K CIDFont.
  2934. */
  2935. UFLsprintf(cidFontName, cchFontName, "%s%s",
  2936. pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX_32K]);
  2937. cid = (unsigned short)((long)wGid-(long)NUM_32K_1);
  2938. }
  2939. else
  2940. {
  2941. UFLsprintf(cidFontName, cchFontName, "%s%s", pFont->info.CIDFontName, gcidSuffix[CIDSUFFIX]);
  2942. cid = wGid;
  2943. }
  2944. }
  2945. else
  2946. {
  2947. UFLsprintf(cidFontName, cchFontName, "%s", pUFObj->pszFontName);
  2948. /*
  2949. * Don't know how to assign a CID. Return zero.
  2950. */
  2951. }
  2952. return cid;
  2953. }
  2954. UFLErrCode
  2955. PutT42Char(
  2956. UFOStruct *pUFObj,
  2957. unsigned short wGlyfIndex,
  2958. unsigned short wCid,
  2959. COMPOSITEGLYPHS *pCompGlyphs,
  2960. char *strmbuf,
  2961. size_t cchstrmbuf
  2962. )
  2963. {
  2964. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  2965. unsigned long *glyphRanges = pFont->pStringLength;
  2966. UFLHANDLE stream = pUFObj->pUFL->hOut;
  2967. UFLErrCode retVal = kNoErr;
  2968. UFLBool bMoreComp = 0;
  2969. unsigned short cid, i, wIndex, wCompFlags;
  2970. unsigned long glyphOffset, glyphLength;
  2971. char *pGlyph;
  2972. char *pCompTmp;
  2973. char cidFontName[64];
  2974. if (wGlyfIndex > UFO_NUM_GLYPHS(pUFObj))
  2975. {
  2976. /*
  2977. * If the requested glyph is out of range, pretend it is downloaded
  2978. * without error.
  2979. */
  2980. return kNoErr;
  2981. }
  2982. /* indexToLocFormat contains 0 for short offsets and 1 for long. */
  2983. if (pFont->headTable.indexToLocFormat)
  2984. {
  2985. unsigned long PTR_PREFIX *locationTable = (unsigned long PTR_PREFIX *)pFont->pLocaTable;
  2986. /*
  2987. * Bad font protection: some fonts have bad 'loca' data for a few
  2988. * glyphs. These bad glyphs will be treated as /.notdef.
  2989. */
  2990. // if (MOTOROLALONG(locationTable[wGlyfIndex + 1]) < MOTOROLALONG(locationTable[wGlyfIndex]))
  2991. // return kNoErr;
  2992. /* Get the offset to the glyph from the beginning of the glyf table. */
  2993. glyphOffset = MOTOROLALONG(locationTable[wGlyfIndex]);
  2994. if ((MOTOROLALONG(locationTable[wGlyfIndex + 1]) < MOTOROLALONG(locationTable[wGlyfIndex]))
  2995. || ((MOTOROLALONG(locationTable[wGlyfIndex + 1]) - MOTOROLALONG(locationTable[wGlyfIndex])) > 16384L))
  2996. {
  2997. glyphLength = GetLenByScanLoca(locationTable,
  2998. wGlyfIndex,
  2999. UFO_NUM_GLYPHS(pUFObj),
  3000. pFont->headTable.indexToLocFormat);
  3001. }
  3002. else
  3003. {
  3004. glyphLength = (unsigned long)MOTOROLALONG(locationTable[wGlyfIndex + 1]) - glyphOffset;
  3005. }
  3006. }
  3007. else
  3008. {
  3009. unsigned short PTR_PREFIX *locationTable = (unsigned short PTR_PREFIX*)pFont->pLocaTable;
  3010. /*
  3011. * Bad font protection: some fonts have bad 'loca' data for a few
  3012. * glyphs. These bad glyphs will be treated as /.notdef.
  3013. * /
  3014. // if (MOTOROLAINT(locationTable[wGlyfIndex + 1]) < MOTOROLAINT(locationTable[wGlyfIndex]))
  3015. // return kNoErr;
  3016. /* Get the offset to the glyph from the beginning of the glyf table. */
  3017. glyphOffset = (unsigned long)MOTOROLAINT(locationTable[wGlyfIndex]) * 2;
  3018. if ((MOTOROLAINT(locationTable[wGlyfIndex + 1]) < MOTOROLAINT(locationTable[wGlyfIndex]))
  3019. || ((MOTOROLAINT(locationTable[wGlyfIndex + 1]) - MOTOROLAINT(locationTable[wGlyfIndex])) > 16384))
  3020. {
  3021. glyphLength = GetLenByScanLoca(locationTable,
  3022. wGlyfIndex,
  3023. UFO_NUM_GLYPHS(pUFObj),
  3024. pFont->headTable.indexToLocFormat);
  3025. }
  3026. else
  3027. {
  3028. glyphLength = (unsigned long)MOTOROLAINT(locationTable[wGlyfIndex + 1]) * 2 - glyphOffset;
  3029. }
  3030. }
  3031. /*
  3032. * GlyphIndices that have no glyph description point to the same offset.
  3033. * So, GlyphLength becomes 0. Handle these as special cases for 2015 and
  3034. * pre-2015.
  3035. */
  3036. if (!glyphLength)
  3037. {
  3038. /* Send parameters for /AddT42Char procedure. */
  3039. retVal = StrmPutStringEOL(stream, nilStr);
  3040. /*
  3041. * Locate /sfnts string number in which the glyph occurs and offset of
  3042. * the glyph in "that" string.
  3043. */
  3044. for (i = 1; glyphRanges[i] != 0; i++)
  3045. {
  3046. if (glyphOffset < glyphRanges[i])
  3047. {
  3048. i--; /* Gives the "actual" string index (as opposed to string number). */
  3049. break;
  3050. }
  3051. }
  3052. /*
  3053. * Send index of /sfnts string in which this glyph belongs. Check if a
  3054. * valid index i was found.
  3055. */
  3056. if (glyphRanges[i] == 0)
  3057. {
  3058. /*
  3059. * Oops, this should not have happened. But it will with Monotype
  3060. * Sorts or any font whose last few glyphs are not defined.
  3061. * Roll back i to point to glyph index 0, the bullet character.
  3062. * Anyway, it does not matter where this glyph (with no description)
  3063. * points to, really. Only 2015 needs a real entry in /GlyphDirectory,
  3064. * even for glyphs with no description, ie, the entry:
  3065. * /GlyphIndex < > def in the dict /GlyphDirectory.
  3066. */
  3067. i = 0;
  3068. glyphOffset = 0;
  3069. }
  3070. retVal = StrmPutInt(stream, pFont->cOtherTables + i);
  3071. if (kNoErr == retVal)
  3072. retVal = StrmPutString(stream, " ");
  3073. /* Send offset of the glyph in the particular /sfnts string. */
  3074. if (kNoErr == retVal)
  3075. retVal = StrmPutInt(stream, glyphOffset - glyphRanges[i]);
  3076. if (kNoErr == retVal)
  3077. retVal = StrmPutString(stream, " ");
  3078. /* Send the glyph index. */
  3079. if (kNoErr == retVal)
  3080. retVal = StrmPutInt(stream, wGlyfIndex);
  3081. if (kNoErr == retVal)
  3082. retVal = StrmPutString(stream, " <> ");
  3083. if (IS_TYPE42CID(pUFObj->lDownloadFormat))
  3084. {
  3085. cid = GetCIDAndCIDFontName(pUFObj, wGlyfIndex, cidFontName, CCHOF(cidFontName));
  3086. UFLsprintf(strmbuf, cchstrmbuf, "/%s T0AddT42Char ", cidFontName);
  3087. if (kNoErr == retVal)
  3088. retVal = StrmPutStringEOL(stream, strmbuf);
  3089. if (!pFont->info.bUseIdentityCMap)
  3090. cid = wCid;
  3091. AddT42vmtxEntry(pUFObj, wGlyfIndex, wCid, cidFontName, stream, strmbuf, cchstrmbuf);
  3092. if (pFont->info.bUpdateCIDMap)
  3093. T42UpdateCIDMap(pUFObj, wGlyfIndex, wCid, cidFontName, stream, strmbuf, cchstrmbuf);
  3094. }
  3095. else
  3096. {
  3097. UFLsprintf(strmbuf, cchstrmbuf, "/%s AddT42Char ", pUFObj->pszFontName);
  3098. if (kNoErr == retVal)
  3099. retVal = StrmPutStringEOL(stream, strmbuf);
  3100. }
  3101. return retVal;
  3102. } /* if ( !glyphLength ) */
  3103. /*
  3104. * Get the physical glyph data to lpGlyph.
  3105. */
  3106. pGlyph = (char *)UFLNewPtr(pUFObj->pMem, glyphLength);
  3107. if (pGlyph == nil)
  3108. retVal = kErrOutOfMemory;
  3109. if (0 == GETTTFONTDATA(pUFObj,
  3110. GLYF_TABLE, glyphOffset,
  3111. pGlyph, glyphLength,
  3112. pFont->info.fData.fontIndex))
  3113. {
  3114. retVal = kErrGetFontData;
  3115. }
  3116. /*
  3117. * Handle Composite Characters.
  3118. */
  3119. if ((kNoErr == retVal) && (*((short *)pGlyph) == MINUS_ONE))
  3120. {
  3121. pCompTmp = pGlyph;
  3122. pCompTmp += 10; /* Move to beginning of glyph description. */
  3123. do
  3124. {
  3125. wCompFlags = MOTOROLAINT(*((unsigned short *)pCompTmp));
  3126. wIndex = MOTOROLAINT(((unsigned short *)pCompTmp)[1]);
  3127. /*
  3128. * Download the first "component" glyph of this composite
  3129. * character.
  3130. */
  3131. if ((wIndex < UFO_NUM_GLYPHS(pUFObj))
  3132. && !IS_GLYPH_SENT( pUFObj->pAFont->pDownloadedGlyphs, wIndex))
  3133. {
  3134. if (pFont->info.bUseIdentityCMap)
  3135. {
  3136. if (wIndex > NUM_32K_1)
  3137. {
  3138. /* 32K+ glyphs are re-mapped to the 32K CIDFont. */
  3139. cid = (unsigned short)((long)wIndex - (long)NUM_32K_1);
  3140. }
  3141. else
  3142. {
  3143. cid = wIndex;
  3144. }
  3145. }
  3146. else
  3147. cid = 0; /* Don't know the wCid. */
  3148. retVal = PutT42Char(pUFObj, wIndex, cid, pCompGlyphs, strmbuf, cchstrmbuf);
  3149. if (retVal == kNoErr)
  3150. {
  3151. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pDownloadedGlyphs, wIndex);
  3152. /*
  3153. * If we ran out of space to keep track of the composite
  3154. * componets then allocate more space.
  3155. */
  3156. if ((pCompGlyphs->sCount >= pCompGlyphs->sMaxCount)
  3157. && (pCompGlyphs->pGlyphs != nil))
  3158. {
  3159. short sEnlargeSize = pCompGlyphs->sMaxCount + 50;
  3160. if (UFLEnlargePtr(pUFObj->pMem,
  3161. (void **)&pCompGlyphs->pGlyphs,
  3162. (sEnlargeSize * sizeof (unsigned short)), 1))
  3163. {
  3164. pCompGlyphs->sMaxCount = sEnlargeSize;
  3165. }
  3166. else
  3167. {
  3168. /*
  3169. * For some reason we can't get more space.
  3170. * Then just don't do this at all.
  3171. */
  3172. UFLDeletePtr(pUFObj->pMem, pCompGlyphs->pGlyphs);
  3173. pCompGlyphs->pGlyphs = nil;
  3174. pCompGlyphs->sCount = pCompGlyphs->sMaxCount = 0;
  3175. }
  3176. }
  3177. /*
  3178. * Remember which composite glyph componet we downloaded.
  3179. */
  3180. if (pCompGlyphs->pGlyphs)
  3181. {
  3182. *(pCompGlyphs->pGlyphs + pCompGlyphs->sCount) = wIndex;
  3183. pCompGlyphs->sCount++;
  3184. }
  3185. }
  3186. }
  3187. /*
  3188. * Check for other components in this composite character.
  3189. */
  3190. if ((kNoErr == retVal) && (wCompFlags & MORE_COMPONENTS))
  3191. {
  3192. bMoreComp = 1;
  3193. /*
  3194. * Find out how far we need to advance lpCompTmp to get to next
  3195. * component of the composite character.
  3196. */
  3197. if (wCompFlags & ARG_1_AND_2_ARE_WORDS)
  3198. pCompTmp += 8;
  3199. else
  3200. pCompTmp += 6;
  3201. /*
  3202. * Check what kind of scaling is done on the glyph component.
  3203. */
  3204. if (wCompFlags & WE_HAVE_A_SCALE)
  3205. {
  3206. pCompTmp += 2;
  3207. }
  3208. else
  3209. {
  3210. if (wCompFlags & WE_HAVE_AN_X_AND_Y_SCALE)
  3211. {
  3212. pCompTmp += 4;
  3213. }
  3214. else
  3215. {
  3216. if (wCompFlags & WE_HAVE_A_TWO_BY_TWO)
  3217. pCompTmp += 8;
  3218. }
  3219. }
  3220. }
  3221. else
  3222. {
  3223. bMoreComp = 0;
  3224. }
  3225. } while (bMoreComp && (kNoErr == retVal)); /* do~while loop */
  3226. } /* If composite character */
  3227. /*
  3228. * Locate /sfnts string number in which the glyph occurs and offset of
  3229. * the glyph in "that" string.
  3230. */
  3231. if (kNoErr == retVal)
  3232. {
  3233. i = 1;
  3234. while (glyphRanges[i] != 0)
  3235. {
  3236. if (glyphOffset < glyphRanges[i])
  3237. {
  3238. i--; /* Gives the "actual" string index (as opposed to string number). */
  3239. break;
  3240. }
  3241. i++; /* Go to the next string and check if Glyph belongs there. */
  3242. }
  3243. }
  3244. /* Send index of /sfnts string in which this glyph belongs. */
  3245. if (kNoErr == retVal)
  3246. retVal = StrmPutInt(stream, pFont->cOtherTables + i);
  3247. if (kNoErr == retVal)
  3248. retVal = StrmPutString(stream, " ");
  3249. /* Send offset of the glyph in the particular /sfnts string. */
  3250. if (kNoErr == retVal)
  3251. retVal = StrmPutInt(stream, glyphOffset-glyphRanges[i]);
  3252. if (kNoErr == retVal)
  3253. retVal = StrmPutString(stream, " ");
  3254. /* Send the glyph index. */
  3255. if (kNoErr == retVal)
  3256. retVal = StrmPutInt(stream, wGlyfIndex);
  3257. if (kNoErr == retVal)
  3258. retVal = StrmPutString(stream, " ");
  3259. /* Download the glyph in binary (or) AsciiHex format. */
  3260. if (kNoErr == retVal)
  3261. {
  3262. if (StrmCanOutputBinary(stream))
  3263. {
  3264. retVal = StrmPutInt(stream, glyphLength);
  3265. if (kNoErr == retVal)
  3266. retVal = StrmPutString(stream, RDString);
  3267. if (kNoErr == retVal)
  3268. retVal = StrmPutBytes(stream, pGlyph, (UFLsize_t)glyphLength, 0);
  3269. }
  3270. else
  3271. {
  3272. retVal = StrmPutString(stream, "<");
  3273. if (kNoErr == retVal)
  3274. retVal = StrmPutAsciiHex(stream, pGlyph, glyphLength);
  3275. if (kNoErr == retVal)
  3276. retVal = StrmPutString(stream, ">");
  3277. }
  3278. }
  3279. if (IS_TYPE42CID(pUFObj->lDownloadFormat))
  3280. {
  3281. cid = GetCIDAndCIDFontName(pUFObj, wGlyfIndex, cidFontName, CCHOF(cidFontName));
  3282. UFLsprintf(strmbuf, cchstrmbuf, "/%s T0AddT42Char ", cidFontName);
  3283. if (kNoErr == retVal)
  3284. retVal = StrmPutStringEOL(stream, strmbuf);
  3285. if (!pFont->info.bUseIdentityCMap)
  3286. cid = wCid;
  3287. AddT42vmtxEntry(pUFObj, wGlyfIndex, cid, cidFontName, stream, strmbuf, cchstrmbuf);
  3288. if (pFont->info.bUpdateCIDMap)
  3289. T42UpdateCIDMap(pUFObj, wGlyfIndex, wCid, cidFontName, stream, strmbuf, cchstrmbuf);
  3290. }
  3291. else
  3292. {
  3293. UFLsprintf(strmbuf, cchstrmbuf, "/%s AddT42Char ", pUFObj->pszFontName);
  3294. if (kNoErr == retVal)
  3295. retVal = StrmPutStringEOL(stream, strmbuf);
  3296. }
  3297. if (pGlyph)
  3298. {
  3299. UFLDeletePtr(pUFObj->pMem, pGlyph);
  3300. pGlyph = nil;
  3301. }
  3302. return retVal;
  3303. }
  3304. UFLErrCode
  3305. T42AddChars(
  3306. UFOStruct *pUFObj,
  3307. const UFLGlyphsInfo *pGlyphs
  3308. )
  3309. {
  3310. UFLHANDLE stream = pUFObj->pUFL->hOut;
  3311. UFLErrCode retVal = kNoErr;
  3312. unsigned short cid = 0;
  3313. short totalGlyphs = 0;
  3314. unsigned short wIndex;
  3315. UFLGlyphID *glyphs;
  3316. COMPOSITEGLYPHS compGlyphs;
  3317. char strmbuf[128];
  3318. short i;
  3319. /*
  3320. * Save a copy of Downloaded glpyh list. This is used to update CharStrings
  3321. * later.
  3322. */
  3323. UFLmemcpy((const UFLMemObj*)pUFObj->pMem,
  3324. pUFObj->pAFont->pVMGlyphs,
  3325. pUFObj->pAFont->pDownloadedGlyphs,
  3326. (UFLsize_t)(GLYPH_SENT_BUFSIZE(UFO_NUM_GLYPHS(pUFObj))));
  3327. /*
  3328. * Keep track of composite glyphs that might of been downloaded.
  3329. */
  3330. compGlyphs.sMaxCount = pGlyphs->sCount * 2;
  3331. compGlyphs.sCount = 0;
  3332. /*
  3333. * Update the charstring uses GoodNames only if the Encoding vector is nil.
  3334. */
  3335. if(pUFObj->pszEncodeName == nil)
  3336. compGlyphs.pGlyphs = nil;
  3337. else
  3338. compGlyphs.pGlyphs = (unsigned short *)UFLNewPtr(pUFObj->pMem,
  3339. compGlyphs.sMaxCount * sizeof (unsigned short));
  3340. if (compGlyphs.pGlyphs == nil)
  3341. compGlyphs.sMaxCount = 0;
  3342. /*
  3343. * The main loop for downloading the glyphs of the given string.
  3344. */
  3345. glyphs = pGlyphs->pGlyphIndices;
  3346. for (i = 0; kNoErr == retVal && i < pGlyphs->sCount; i++)
  3347. {
  3348. /* LOWord is the real GID. */
  3349. wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF);
  3350. if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
  3351. continue;
  3352. if (!IS_GLYPH_SENT(pUFObj->pAFont->pDownloadedGlyphs, wIndex))
  3353. {
  3354. if (pGlyphs->pCharIndex)
  3355. cid = pGlyphs->pCharIndex[i];
  3356. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  3357. retVal = PutT42Char(pUFObj, wIndex, cid, &compGlyphs, strmbuf, CCHOF(strmbuf));
  3358. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pDownloadedGlyphs, wIndex);
  3359. totalGlyphs++;
  3360. }
  3361. }
  3362. /*
  3363. * Make sure that .notdef is sent.
  3364. */
  3365. if ((kNoErr == retVal) && (pUFObj->flState >= kFontInit))
  3366. {
  3367. if (!IS_GLYPH_SENT(pUFObj->pAFont->pDownloadedGlyphs, 0))
  3368. {
  3369. cid = 0; /* Don't know its CID. */
  3370. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  3371. retVal = PutT42Char(pUFObj, 0x0000, cid, &compGlyphs, strmbuf, CCHOF(strmbuf));
  3372. if (kNoErr == retVal)
  3373. {
  3374. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pDownloadedGlyphs, 0);
  3375. totalGlyphs++;
  3376. }
  3377. }
  3378. }
  3379. /*
  3380. * Update the charstring uses GoodNames if the Encoding vector is nil.
  3381. */
  3382. if ((kNoErr == retVal) && (pUFObj->pszEncodeName == nil) && (totalGlyphs > 0))
  3383. {
  3384. /*
  3385. * Begin CharStirng re-encoding.
  3386. */
  3387. UFLBool bAddCompGlyphAlternate = 0;
  3388. UFLBool bGoodName;
  3389. char *pGoodName;
  3390. retVal = StrmPutString(stream, "/");
  3391. if (kNoErr == retVal)
  3392. retVal = StrmPutString(stream, pUFObj->pszFontName);
  3393. if (kNoErr == retVal)
  3394. retVal = StrmPutStringEOL(stream, " findfont /CharStrings get begin");
  3395. /*
  3396. * If we ran out of space in keeping with Composite Glyph Component,
  3397. * then add composite component to Encoding the long way.
  3398. */
  3399. if (!compGlyphs.pGlyphs)
  3400. {
  3401. bAddCompGlyphAlternate = 1;
  3402. compGlyphs.sCount = compGlyphs.sMaxCount =0;
  3403. }
  3404. /*
  3405. * Update the CharStrings with all of the newly added Glyphs.
  3406. * First go through the Main Glyph Index arrays.
  3407. */
  3408. for (i = 0; (kNoErr == retVal) && (i < (pGlyphs->sCount + compGlyphs.sCount)); i++)
  3409. {
  3410. /*
  3411. * Get glyph index from either the regular glyphs list or the
  3412. * composite list. LOWord is the read GID in either case.
  3413. */
  3414. if (i < pGlyphs->sCount)
  3415. wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF);
  3416. else
  3417. wIndex = (unsigned short)(compGlyphs.pGlyphs[i - pGlyphs->sCount] & 0x0000FFFF);
  3418. if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
  3419. continue;
  3420. if ((0 == pUFObj->pUFL->bDLGlyphTracking)
  3421. || (pGlyphs->pCharIndex == nil) // DownloadFace
  3422. || (pUFObj->pEncodeNameList) // DownloadFace
  3423. || !IS_GLYPH_SENT(pUFObj->pAFont->pVMGlyphs, wIndex))
  3424. {
  3425. bGoodName = FindGlyphName(pUFObj, pGlyphs, i, wIndex, &pGoodName);
  3426. /* Fix bug 274008: check Glyph Name only for DownloadFace. */
  3427. if (pUFObj->pEncodeNameList)
  3428. {
  3429. if ((UFLstrcmp(pGoodName, Hyphen) == 0) && (i == 45))
  3430. {
  3431. /* Add /minus to CharString. */
  3432. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s %d def", Minus, wIndex);
  3433. if (kNoErr == retVal)
  3434. retVal = StrmPutStringEOL(stream, strmbuf);
  3435. }
  3436. if ((UFLstrcmp(pGoodName, Hyphen) == 0) && (i == 173))
  3437. {
  3438. /* Add /sfthyphen to CharString. */
  3439. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s %d def", SftHyphen, wIndex);
  3440. if (kNoErr == retVal)
  3441. retVal = StrmPutStringEOL(stream, strmbuf);
  3442. }
  3443. if (!ValidGlyphName(pGlyphs, i, wIndex, pGoodName))
  3444. continue;
  3445. /* Send only one ".notdef". */
  3446. if ((UFLstrcmp(pGoodName, Notdef) == 0)
  3447. && (wIndex == (unsigned short)(glyphs[0] & 0x0000FFFF))
  3448. && IS_GLYPH_SENT(pUFObj->pAFont->pVMGlyphs, wIndex))
  3449. continue;
  3450. }
  3451. if (kNoErr == retVal)
  3452. retVal = StrmPutString(stream, "/");
  3453. if (kNoErr == retVal)
  3454. retVal = StrmPutString(stream, pGoodName);
  3455. UFLsprintf(strmbuf, CCHOF(strmbuf), " %d def", wIndex);
  3456. if (kNoErr == retVal)
  3457. retVal = StrmPutStringEOL(stream, strmbuf);
  3458. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pVMGlyphs, wIndex);
  3459. if (bGoodName)
  3460. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pCodeGlyphs, wIndex);
  3461. }
  3462. }
  3463. /*
  3464. * Do composite font this way only if we ran out of space.
  3465. */
  3466. if (bAddCompGlyphAlternate)
  3467. {
  3468. /*
  3469. * Now go through all VMGlyphs to see if there is any glyph are
  3470. * downloaded as part of Composite glyph above. - fix bug 217228.
  3471. * PPeng, 6-12-1997
  3472. */
  3473. for (wIndex = 0;
  3474. (kNoErr == retVal) && (wIndex < UFO_NUM_GLYPHS(pUFObj));
  3475. wIndex++)
  3476. {
  3477. if ((0 == pUFObj->pUFL->bDLGlyphTracking)
  3478. /* || (pGlyphs->pCharIndex == nil) */
  3479. || (IS_GLYPH_SENT(pUFObj->pAFont->pDownloadedGlyphs, wIndex)
  3480. && !IS_GLYPH_SENT(pUFObj->pAFont->pVMGlyphs, wIndex)))
  3481. {
  3482. /*
  3483. * For composite glyphs, always try to use its good name.
  3484. */
  3485. pGoodName = GetGlyphName(pUFObj,
  3486. (unsigned long)wIndex,
  3487. nil,
  3488. &bGoodName);
  3489. retVal = StrmPutString(stream, "/");
  3490. if (kNoErr == retVal)
  3491. retVal = StrmPutString(stream, pGoodName);
  3492. UFLsprintf(strmbuf, CCHOF(strmbuf), " %d def", wIndex);
  3493. if (kNoErr == retVal)
  3494. retVal = StrmPutStringEOL(stream, strmbuf);
  3495. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pVMGlyphs, wIndex);
  3496. }
  3497. }
  3498. }
  3499. /*
  3500. * End CharStirng re-encoding.
  3501. */
  3502. if (kNoErr == retVal)
  3503. retVal = StrmPutStringEOL(stream, "end");
  3504. }
  3505. /*
  3506. * Update the Encoding vector if we use GoodNames.
  3507. */
  3508. if ((kNoErr == retVal) && (pUFObj->pszEncodeName == nil) && (pGlyphs->sCount > 0))
  3509. {
  3510. /*
  3511. * Check pUFObj->pUpdatedEncoding to see if we really need to update it.
  3512. */
  3513. for (i = 0; i < pGlyphs->sCount; i++)
  3514. {
  3515. if ((0 == pUFObj->pUFL->bDLGlyphTracking)
  3516. || (pGlyphs->pCharIndex == nil) // DownloadFace
  3517. || (pUFObj->pEncodeNameList) // DownloadFace
  3518. || !IS_GLYPH_SENT(pUFObj->pUpdatedEncoding, pGlyphs->pCharIndex[i]))
  3519. {
  3520. /* Found at least one not updated, do it (once) for all. */
  3521. retVal = UpdateEncodingVector(pUFObj, pGlyphs, 0, pGlyphs->sCount);
  3522. break;
  3523. }
  3524. }
  3525. }
  3526. /*
  3527. * Update the FontInfo with Unicode information.
  3528. */
  3529. if ((kNoErr == retVal)
  3530. && (pGlyphs->sCount > 0)
  3531. && (pUFObj->dwFlags & UFO_HasG2UDict)
  3532. && !HOSTFONT_IS_VALID_UFO(pUFObj))
  3533. {
  3534. /*
  3535. * Check pUFObj->pAFont->pCodeGlyphs to see if we really need to update
  3536. * it.
  3537. */
  3538. for (i = 0; i < pGlyphs->sCount; i++)
  3539. {
  3540. /* LOWord is the real GID. */
  3541. wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF);
  3542. if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
  3543. continue;
  3544. if (!IS_GLYPH_SENT(pUFObj->pAFont->pCodeGlyphs, wIndex))
  3545. {
  3546. /* Found at least one not updated, do it (once) for all. */
  3547. retVal = UpdateCodeInfo(pUFObj, pGlyphs, 0);
  3548. break;
  3549. }
  3550. }
  3551. }
  3552. if (compGlyphs.pGlyphs)
  3553. {
  3554. UFLDeletePtr(pUFObj->pMem, compGlyphs.pGlyphs);
  3555. compGlyphs.pGlyphs = nil;
  3556. }
  3557. /*
  3558. * Downloading glyph(s) is done. Change the font state.
  3559. */
  3560. if (kNoErr ==retVal)
  3561. pUFObj->flState = kFontHasChars;
  3562. return retVal;
  3563. }
  3564. UFLErrCode
  3565. T42VMNeeded(
  3566. UFOStruct *pUFObj,
  3567. const UFLGlyphsInfo *pGlyphs,
  3568. unsigned long *pVMNeeded,
  3569. unsigned long *pFCNeeded
  3570. )
  3571. {
  3572. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  3573. UFLErrCode retVal = kNoErr;
  3574. unsigned long vmUsed = 0;
  3575. UFLBool bFullFont;
  3576. UFLGlyphID *glyphs;
  3577. if (pUFObj->flState < kFontInit)
  3578. return kErrInvalidState;
  3579. if ((pGlyphs == nil) || (pGlyphs->pGlyphIndices == nil) || (pVMNeeded == nil))
  3580. return kErrInvalidParam;
  3581. *pVMNeeded = 0;
  3582. if (pFCNeeded)
  3583. *pFCNeeded = 0;
  3584. glyphs = pGlyphs->pGlyphIndices;
  3585. bFullFont = (pGlyphs->sCount == -1) ? 1 : 0;
  3586. if ((0 == pFont->minSfntSize) || (pFont->pHeader == nil))
  3587. retVal = GetMinSfnt(pUFObj, bFullFont);
  3588. if (kNoErr == retVal)
  3589. {
  3590. unsigned long totalGlyphs = 0;
  3591. /*
  3592. * Scan the list, check what characters that we have downloaded.
  3593. */
  3594. if (!bFullFont)
  3595. {
  3596. short i;
  3597. UFLmemcpy((const UFLMemObj *)pUFObj->pMem,
  3598. pUFObj->pAFont->pVMGlyphs,
  3599. pUFObj->pAFont->pDownloadedGlyphs,
  3600. (UFLsize_t)(GLYPH_SENT_BUFSIZE(UFO_NUM_GLYPHS(pUFObj))));
  3601. for (i = 0; i < pGlyphs->sCount; i++)
  3602. {
  3603. /* LOWord is the real GID. */
  3604. unsigned short wIndex = (unsigned short)(glyphs[i] & 0x0000FFFF);
  3605. if (wIndex >= UFO_NUM_GLYPHS(pUFObj))
  3606. continue;
  3607. if (!IS_GLYPH_SENT( pUFObj->pAFont->pVMGlyphs, wIndex))
  3608. {
  3609. SET_GLYPH_SENT_STATUS(pUFObj->pAFont->pVMGlyphs, wIndex);
  3610. totalGlyphs++;
  3611. }
  3612. }
  3613. }
  3614. else
  3615. {
  3616. totalGlyphs = UFO_NUM_GLYPHS(pUFObj);
  3617. }
  3618. /*
  3619. * Start with the size of the minimal sfnt if the header has not been
  3620. * sent yet.
  3621. */
  3622. if (pUFObj->flState < kFontHeaderDownloaded)
  3623. {
  3624. vmUsed = pFont->minSfntSize;
  3625. }
  3626. /*
  3627. * If incremental downloading and there are glyphs to check, add these
  3628. * to total VMUsage of each glyph is the average size of each glyph in
  3629. * the glyf table.
  3630. */
  3631. if (bFullFont == 0)
  3632. {
  3633. if (GETPSVERSION(pUFObj) < 2015)
  3634. {
  3635. /*
  3636. * For pre2015 printers, we need to pre-allocate VM for all
  3637. * Glyphs. The VM for whole font is allocated when the Header
  3638. * is Sent.
  3639. */
  3640. if (pUFObj->flState < kFontHeaderDownloaded)
  3641. {
  3642. vmUsed += GetGlyphTableSize(pUFObj);
  3643. }
  3644. else
  3645. {
  3646. /*
  3647. * After header is sent on pre-2015 printer, no more VM
  3648. * allocation for adding chars, so set to 0 -- VM for both
  3649. * Header and Glyph table are allocate already!
  3650. */
  3651. vmUsed = 0;
  3652. }
  3653. }
  3654. else
  3655. {
  3656. if (glyphs != nil)
  3657. {
  3658. /* Check if this has been calculated yet. */
  3659. if (pFont->averageGlyphSize == 0)
  3660. GetAverageGlyphSize(pUFObj);
  3661. /* If this is still zero, there's a problem with the sfnt. */
  3662. if (pFont->averageGlyphSize == 0)
  3663. retVal = kErrBadTable;
  3664. else
  3665. vmUsed += totalGlyphs * pFont->averageGlyphSize;
  3666. /*
  3667. * Fix bug 256940: make it compatible with 95 driver.
  3668. * jjia 7/2/98
  3669. */
  3670. if ((IS_TYPE42CID(pUFObj->lDownloadFormat))
  3671. && (pUFObj->flState < kFontHeaderDownloaded))
  3672. {
  3673. vmUsed += (UFO_NUM_GLYPHS(pUFObj)) * 2;
  3674. }
  3675. }
  3676. }
  3677. }
  3678. if ((kNoErr == retVal) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  3679. *pVMNeeded = VMT42RESERVED(vmUsed);
  3680. }
  3681. return retVal;
  3682. }
  3683. #if 0
  3684. /*
  3685. * Currently this function is not called from any place.
  3686. */
  3687. UFLErrCode
  3688. DownloadFullFont(
  3689. UFOStruct *pUFObj
  3690. )
  3691. {
  3692. UFLErrCode retVal = kNoErr;
  3693. /*
  3694. * Can only download full font if no header has been downloaded before.
  3695. * The only possible state that meets this requirement is kFontInit.
  3696. */
  3697. if (pUFObj->flState != kFontInit)
  3698. return kErrInvalidState;
  3699. /* Create and download the full font. */
  3700. retVal = T42CreateBaseFont(pUFObj, nil, nil, 1);
  3701. if (retVal == kNoErr)
  3702. pUFObj->flState = kFontFullDownloaded;
  3703. return retVal;
  3704. }
  3705. #endif
  3706. /******************************************************************************
  3707. *
  3708. * T42FontDownloadIncr
  3709. *
  3710. * Function: Adds all of the characters from pGlyphs that aren't already
  3711. * downloaded for the TrueType font.
  3712. *
  3713. ******************************************************************************/
  3714. UFLErrCode
  3715. T42FontDownloadIncr(
  3716. UFOStruct *pUFObj,
  3717. const UFLGlyphsInfo *pGlyphs,
  3718. unsigned long *pVMUsage,
  3719. unsigned long *pFCUsage
  3720. )
  3721. {
  3722. UFLErrCode retVal = kNoErr;
  3723. char *pHostFontName = nil;
  3724. if (pFCUsage)
  3725. *pFCUsage = 0;
  3726. /*
  3727. * Sanity checks.
  3728. */
  3729. if (pUFObj->flState < kFontInit)
  3730. return kErrInvalidState;
  3731. if ((pGlyphs == nil) || (pGlyphs->pGlyphIndices == nil) || (pGlyphs->sCount == 0))
  3732. return kErrInvalidParam;
  3733. /*
  3734. * No need to download if the full font has already been downloaded.
  3735. */
  3736. if (pUFObj->flState == kFontFullDownloaded)
  3737. return kNoErr;
  3738. /*
  3739. * Check %hostfont% status prior to download anything.
  3740. */
  3741. HostFontValidateUFO(pUFObj, &pHostFontName);
  3742. /*
  3743. * Check the VM usage - before sending the Header. On Pre-2015 printers,
  3744. * VMUsage is 0 after the header is downloaded (pre-allocate).
  3745. */
  3746. if (!HOSTFONT_IS_VALID_UFO(pUFObj))
  3747. retVal = T42VMNeeded(pUFObj, pGlyphs, pVMUsage, nil); /* nil for pFCUsage */
  3748. /*
  3749. * Create a base font if it has not been done yet.
  3750. */
  3751. if (pUFObj->flState == kFontInit)
  3752. retVal = T42CreateBaseFont(pUFObj, pGlyphs, pVMUsage, 0, pHostFontName);
  3753. /*
  3754. * Download the glyphs.
  3755. */
  3756. if (kNoErr == retVal)
  3757. retVal = T42AddChars(pUFObj, pGlyphs);
  3758. return retVal;
  3759. }
  3760. UFLErrCode
  3761. T42UndefineFont(
  3762. UFOStruct *pUFObj
  3763. )
  3764. /*++
  3765. Routine Description:
  3766. Send PS code to undefine fonts: /UDF and /UDR should be defined properly
  3767. by client to something like:
  3768. /UDF
  3769. {
  3770. IsLevel2
  3771. {undefinefont}
  3772. { pop }ifelse
  3773. } bind def
  3774. /UDR
  3775. {
  3776. IsLevel2
  3777. {undefineresource}
  3778. { pop pop }ifelse
  3779. } bind def
  3780. --*/
  3781. {
  3782. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  3783. UFLErrCode retVal = kNoErr;
  3784. UFLHANDLE stream = pUFObj->pUFL->hOut;
  3785. char strmbuf[256];
  3786. short int i;
  3787. if (pUFObj->flState < kFontHeaderDownloaded)
  3788. return retVal;
  3789. /*
  3790. * If the font is a Type 42 CID-keyed font, then undefine its CIDFont
  3791. * resources first. (We don't care to leave its CMaps in VM.)
  3792. * But if the font is created on a HostFont system, no need to undefine the
  3793. * resources since we didn't donwload them.
  3794. */
  3795. if (IS_TYPE42CID_KEYEDFONT(pUFObj->lDownloadFormat) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  3796. {
  3797. /*
  3798. * Undefine CIDFont resources: there are 4 possible CIDFonts.
  3799. *
  3800. * e.g. /TT37820t0CID, /TT37820t0CIDR, /TT37820t0CID32K, /TT37820t0CID32KR
  3801. *
  3802. * We can send "udefineresource" for all of them; the command is very
  3803. * forgiving.
  3804. */
  3805. for (i = 0; i < NUM_CIDSUFFIX; i++)
  3806. {
  3807. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s%s /CIDFont UDR", pUFObj->pszFontName, gcidSuffix[i]);
  3808. if (kNoErr == retVal)
  3809. retVal = StrmPutStringEOL(stream, strmbuf);
  3810. }
  3811. }
  3812. /*
  3813. * Undefine the font.
  3814. */
  3815. if (IS_TYPE42CIDFONT_RESOURCE(pUFObj->lDownloadFormat) && !HOSTFONT_IS_VALID_UFO(pUFObj))
  3816. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s /CIDFont UDR", pUFObj->pszFontName);
  3817. else
  3818. UFLsprintf(strmbuf, CCHOF(strmbuf), "/%s UDF", pUFObj->pszFontName);
  3819. if (kNoErr == retVal)
  3820. retVal = StrmPutStringEOL(stream, strmbuf);
  3821. return retVal;
  3822. }
  3823. UFOStruct *
  3824. T42FontInit(
  3825. const UFLMemObj *pMem,
  3826. const UFLStruct *pUFL,
  3827. const UFLRequest *pRequest
  3828. )
  3829. {
  3830. UFOStruct *pUFObj = (UFOStruct *)UFLNewPtr(pMem, sizeof (UFOStruct));
  3831. UFLTTFontInfo *pInfo;
  3832. long maxGlyphs;
  3833. if (pUFObj == nil)
  3834. return nil;
  3835. /* Initialize data. */
  3836. UFOInitData(pUFObj, UFO_TYPE42, pMem, pUFL, pRequest,
  3837. (pfnUFODownloadIncr) T42FontDownloadIncr,
  3838. (pfnUFOVMNeeded) T42VMNeeded,
  3839. (pfnUFOUndefineFont) T42UndefineFont,
  3840. (pfnUFOCleanUp) T42FontCleanUp,
  3841. (pfnUFOCopy) CopyFont);
  3842. /*
  3843. * pszFontName should be allocated and initialized. If not, cannot continue.
  3844. */
  3845. if ((pUFObj->pszFontName == nil) || (pUFObj->pszFontName[0] == '\0'))
  3846. {
  3847. UFLDeletePtr(pMem, pUFObj);
  3848. return nil;
  3849. }
  3850. pInfo = (UFLTTFontInfo*)pRequest->hFontInfo;
  3851. maxGlyphs = pInfo->fData.cNumGlyphs;
  3852. /*
  3853. * A convenience pointer used in GetNumGlyph() - must be set now.
  3854. */
  3855. pUFObj->pFData = &(pInfo->fData); /* !!! Temporary assignment !!! */
  3856. if (maxGlyphs == 0)
  3857. maxGlyphs = GetNumGlyphs(pUFObj);
  3858. if (NewFont(pUFObj, sizeof (T42FontStruct), maxGlyphs) == kNoErr)
  3859. {
  3860. unsigned long sSize;
  3861. unsigned long *pXUID;
  3862. T42FontStruct *pFont = (T42FontStruct *)pUFObj->pAFont->hFont;
  3863. pFont->info = *pInfo;
  3864. /*
  3865. * A convenience pointer - set to the permanent one.
  3866. */
  3867. pUFObj->pFData = &(pFont->info.fData); /* !!! Real assignment !!! */
  3868. /*
  3869. * Get ready to find out correct glyphNames from 'post' table -
  3870. * set correct pFont->info.fData.fontIndex and offsetToTableDir.
  3871. */
  3872. if (pFont->info.fData.fontIndex == FONTINDEX_UNKNOWN)
  3873. pFont->info.fData.fontIndex = GetFontIndexInTTC(pUFObj);
  3874. /*
  3875. * Get num of Glyphs in this TT file if not set yet.
  3876. */
  3877. if (pFont->info.fData.cNumGlyphs == 0)
  3878. pFont->info.fData.cNumGlyphs = maxGlyphs;
  3879. /*
  3880. * Copy or Set XUID array to our UFLXUID structure.
  3881. */
  3882. sSize = pInfo->fData.xuid.sSize;
  3883. if (sSize == 0)
  3884. {
  3885. /*
  3886. * 'sSize == 0' means that UFL needs to figure out the XUID.
  3887. */
  3888. // Fixed bug 387970. We have to initialize offsetToTableDir to make
  3889. // CreateXUIDArray work for ttc font.
  3890. pFont->info.fData.offsetToTableDir =
  3891. GetOffsetToTableDirInTTC(pUFObj, pFont->info.fData.fontIndex);
  3892. sSize = CreateXUIDArray(pUFObj, nil);
  3893. pXUID = (unsigned long *)UFLNewPtr(pUFObj->pMem,
  3894. sSize * sizeof (unsigned long));
  3895. if (pXUID)
  3896. sSize = CreateXUIDArray(pUFObj, pXUID);
  3897. }
  3898. else
  3899. {
  3900. /*
  3901. * The XUID is passed in by client - just copy it.
  3902. */
  3903. pXUID = (unsigned long *)UFLNewPtr(pUFObj->pMem,
  3904. sSize * sizeof (unsigned long));
  3905. if (pXUID)
  3906. {
  3907. UFLmemcpy(pUFObj->pMem,
  3908. pXUID, pInfo->fData.xuid.pXUID,
  3909. sSize * sizeof (unsigned long));
  3910. }
  3911. }
  3912. if (sSize && pXUID)
  3913. {
  3914. pUFObj->pAFont->Xuid.sSize = sSize;
  3915. pUFObj->pAFont->Xuid.pXUID = pXUID;
  3916. }
  3917. else if (pXUID)
  3918. UFLDeletePtr(pUFObj->pMem, pXUID);
  3919. /*
  3920. * More initializations
  3921. */
  3922. pFont->cOtherTables = 0;
  3923. pFont->pHeader = nil;
  3924. pFont->pMinSfnt = nil;
  3925. pFont->pStringLength = nil;
  3926. pFont->pLocaTable = nil;
  3927. pFont->minSfntSize = 0;
  3928. pFont->averageGlyphSize = 0;
  3929. pFont->pRotatedGlyphIDs = nil;
  3930. pUFObj->pUpdatedEncoding = (unsigned char *)UFLNewPtr(pMem, GLYPH_SENT_BUFSIZE(256));
  3931. if (pUFObj->pUpdatedEncoding != 0)
  3932. {
  3933. /*
  3934. * Completed initialization. Change the state.
  3935. */
  3936. pUFObj->flState = kFontInit;
  3937. }
  3938. }
  3939. return pUFObj;
  3940. }
  3941. static unsigned long
  3942. GetLenByScanLoca(
  3943. void PTR_PREFIX *locationTable,
  3944. unsigned short wGlyfIndex,
  3945. unsigned long cNumGlyphs,
  3946. int iLongFormat
  3947. )
  3948. {
  3949. unsigned long GlyphLen = 0;
  3950. unsigned long nextGlyphOffset = 0xFFFFFFFF;
  3951. unsigned long i;
  3952. if (iLongFormat)
  3953. {
  3954. unsigned long PTR_PREFIX* locaTableL = locationTable;
  3955. for (i = 0; i < cNumGlyphs; i++)
  3956. {
  3957. if ((MOTOROLALONG(locaTableL[i]) > MOTOROLALONG(locaTableL[wGlyfIndex]))
  3958. && (MOTOROLALONG(locaTableL[i]) < nextGlyphOffset))
  3959. {
  3960. nextGlyphOffset = MOTOROLALONG(locaTableL[i]);
  3961. }
  3962. }
  3963. if (nextGlyphOffset != 0xFFFFFFFF)
  3964. GlyphLen = nextGlyphOffset - MOTOROLALONG(locaTableL[wGlyfIndex]);
  3965. }
  3966. else
  3967. {
  3968. unsigned short PTR_PREFIX* locaTableS = locationTable;
  3969. for (i = 0; i < cNumGlyphs; i++)
  3970. {
  3971. if ((MOTOROLAINT(locaTableS[i]) > MOTOROLAINT(locaTableS[wGlyfIndex]))
  3972. && (MOTOROLAINT(locaTableS[i]) < nextGlyphOffset))
  3973. {
  3974. nextGlyphOffset = MOTOROLAINT(locaTableS[i]);
  3975. }
  3976. }
  3977. if (nextGlyphOffset != 0xFFFFFFFF)
  3978. GlyphLen = (nextGlyphOffset - MOTOROLAINT(locaTableS[wGlyfIndex])) * 2;
  3979. }
  3980. return GlyphLen;
  3981. }