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.

1140 lines
38 KiB

  1. /*
  2. * Adobe Universal Font Library
  3. *
  4. * Copyright (c) 1996 Adobe Systems Inc.
  5. * All Rights Reserved
  6. *
  7. * GOODNAME.C
  8. *
  9. *
  10. * $Header:
  11. */
  12. /*===============================================================================*
  13. * Include files used by this interface *
  14. *===============================================================================*/
  15. #include "UFLPriv.h"
  16. #include "UFLMem.h"
  17. #include "UFLMath.h"
  18. #include "UFLStd.h"
  19. #include "UFLErr.h"
  20. #include "UFLPS.h"
  21. #include "ParseTT.h"
  22. #include "UFLVm.h"
  23. #include "ufot42.h"
  24. #include "goodname.h"
  25. #include "ttformat.h"
  26. /* ------------------------------------------------------------- */
  27. static void GetTTcmap2Stuff(
  28. void *pTTcmap,
  29. TTcmap2Stuff *p2
  30. )
  31. {
  32. if (pTTcmap == NULL)
  33. return;
  34. p2->pByte = (unsigned char *) pTTcmap;
  35. /* subHeaderKeys[256] starts at fourth WORD */
  36. p2->subHeaderKeys = (unsigned short *) (p2->pByte + 6);
  37. p2->subHeaders = (PTTcmap2SH)(p2->pByte + 6 + 2 * 256);
  38. }
  39. static void GetTTcmap4Stuff(
  40. void *pTTcmap,
  41. TTcmap4Stuff *p4
  42. )
  43. {
  44. unsigned short *pWord; /* a pointer in WORD format */
  45. if (pTTcmap == NULL)
  46. return;
  47. /* a convenient pointer */
  48. pWord = (unsigned short *)pTTcmap;
  49. /* fourth WORD is segCount X 2 */
  50. p4->segCount = (MOTOROLAINT(pWord[3]))/2;
  51. p4->endCode = pWord + 7;
  52. p4->startCode = pWord + 7 + p4->segCount * 1 + 1;
  53. p4->idDelta = pWord + 7 + p4->segCount * 2 + 1;
  54. p4->idRangeOffset = pWord + 7 + p4->segCount * 3 + 1;
  55. p4->glyphIdArray = pWord + 7 + p4->segCount * 4 + 1;
  56. }
  57. static void GetTTmortStuff(
  58. void *pTTmort, /* mort table data */
  59. TTmortStuff *p
  60. )
  61. {
  62. unsigned short *pWord; /* a pointer in WORD format */
  63. if (pTTmort == NULL)
  64. return;
  65. /* a convenient pointer */
  66. pWord = (unsigned short *)pTTmort;
  67. /* 34th Word is the second Unit16 in the BinSrchHeader */
  68. p->nEntries = MOTOROLAINT(pWord[34]);
  69. /* LookupSingle starts at 77th byte - 38th Word */
  70. p->pGlyphSet = pWord + 38 ;
  71. }
  72. /* ------------------------------------------------------------- */
  73. static void GetTTGSUBStuff(
  74. void *pTTGSUB, /* GSUB table data */
  75. TTGSUBStuff *p
  76. )
  77. {
  78. unsigned short *pWord; /* a pointer in WORD format */
  79. unsigned short offSet;
  80. if (pTTGSUB == NULL)
  81. return;
  82. /* a convenient pointer */
  83. pWord = (unsigned short *)pTTGSUB;
  84. /* fourth WORD is offset to LooupList */
  85. offSet = MOTOROLAINT(pWord[4]);
  86. p->pLookupList = (unsigned short *)((unsigned char *)pTTGSUB + offSet);
  87. p->lookupCount = MOTOROLAINT(p->pLookupList[0] );
  88. }
  89. /* ------------------------------------------------------------- */
  90. /* This function is responsible for cmap, mort and GSUB */
  91. unsigned short GetTablesFromTTFont(
  92. UFOStruct *pUFObj
  93. )
  94. {
  95. unsigned short retVal = 0;
  96. unsigned long dwSize, dwOffset, dwcmapSize;
  97. unsigned short wData[4];
  98. unsigned short numSubTables, index;
  99. PSubTableEntry pTableEntry = NULL;
  100. unsigned long cmapOffset;
  101. UFLBool foundUnicodeCmap = 0;
  102. unsigned short platformID, encodingID, format;
  103. AFontStruct *pAFont;
  104. unsigned long length;
  105. if (pUFObj == NULL)
  106. return 0;
  107. pAFont = pUFObj->pAFont;
  108. if (pAFont == NULL)
  109. return 0;
  110. /* Check if the cmap/mort/GSUB data is already in pTTFData */
  111. if (pAFont->gotTables)
  112. return 1;
  113. /* setup booleans - so we don't have to look into data for correctness */
  114. pAFont->hascmap = 0;
  115. pAFont->hasmort = 0;
  116. pAFont->hasGSUB = 0;
  117. pAFont->gsubTBSize = 0;
  118. pAFont->cmapTBSize = 0;
  119. pAFont->mortTBSize = 0;
  120. pAFont->gotTables = 1;
  121. /* Get cmap table */
  122. dwSize= GETTTFONTDATA(pUFObj,
  123. CMAP_TABLE,
  124. 0,
  125. (void *) wData,
  126. 4,
  127. pUFObj->pFData->fontIndex);
  128. if (dwSize==0 || dwSize==0xFFFFFFFFL)
  129. {
  130. goto exit0; // no SubHeader !!!
  131. }
  132. /* usually 2 or 3 subTables */
  133. numSubTables = MOTOROLAINT(wData[1]);
  134. pTableEntry = UFLNewPtr(pUFObj->pMem, numSubTables * sizeof(SubTableEntry));
  135. if (pTableEntry == NULL)
  136. goto exit0;
  137. /**********************/
  138. /* Get cmap subtables */
  139. /**********************/
  140. dwSize= GETTTFONTDATA(pUFObj,
  141. CMAP_TABLE,
  142. 4, // skip header
  143. (void *) pTableEntry,
  144. numSubTables * sizeof(SubTableEntry),
  145. pUFObj->pFData->fontIndex);
  146. if (dwSize==0 || dwSize==0xFFFFFFFFL)
  147. {
  148. goto exit0; // no SubHeader !!!
  149. }
  150. /* We Prefer Unicode Encoding: PlatForm=3, Encoding = 1
  151. * Since the subtable entries are sorted by PlatformID and then EncodingID,
  152. * our searching is reallyg this order:
  153. * Mac:J->CT->K->CS, Win:Uni->J->CS->CT->K and we will stop if found Win:Uni
  154. * or the last one found (in the list) will be used.
  155. */
  156. foundUnicodeCmap = 0;
  157. cmapOffset = 0;
  158. for (index = 0; index < numSubTables && !foundUnicodeCmap; index++)
  159. {
  160. platformID = MOTOROLAINT((pTableEntry + index)->platformID);
  161. encodingID = MOTOROLAINT((pTableEntry + index)->encodingID);
  162. dwOffset = MOTOROLALONG((pTableEntry + index)->offset);
  163. if (platformID != 3)
  164. continue;
  165. /* Get cmap subtable's format - first USHORT at Table->offset */
  166. dwSize= GETTTFONTDATA(pUFObj,
  167. CMAP_TABLE,
  168. dwOffset,
  169. (void *) &(wData[0]),
  170. 4,
  171. pUFObj->pFData->fontIndex);
  172. if (dwSize == 0 || dwSize == 0xFFFFFFFF)
  173. continue;
  174. format = MOTOROLAINT(wData[0]);
  175. length = MOTOROLAINT(wData[1]);
  176. /* we only parse format 2 or 4 for now */
  177. if (format != 2 && format !=4)
  178. continue;
  179. switch(encodingID)
  180. {
  181. case 1:
  182. if (format == 2)
  183. pAFont->cmapFormat = DTT_Win_UNICODE_cmap2;
  184. else /* must be 4 */
  185. pAFont->cmapFormat = DTT_Win_UNICODE_cmap4;
  186. cmapOffset = dwOffset;
  187. dwcmapSize = length;
  188. foundUnicodeCmap = 1;
  189. break;
  190. case 2:
  191. if (format == 2)
  192. pAFont->cmapFormat = DTT_Win_J_cmap2;
  193. else /* must be 4 */
  194. pAFont->cmapFormat = DTT_Win_J_cmap4;
  195. cmapOffset = dwOffset;
  196. dwcmapSize = length;
  197. break;
  198. case 3:
  199. /* PRC- TTF docs says Big5, but Win95CT's minglu.ttc is Big5, has encodingdID=4 */
  200. if (format == 2)
  201. pAFont->cmapFormat = DTT_Win_CS_cmap2;
  202. else /* must be 4 */
  203. pAFont->cmapFormat = DTT_Win_CS_cmap4;
  204. cmapOffset = dwOffset;
  205. dwcmapSize = length;
  206. break;
  207. case 4:
  208. /* MingLi.ttc on Win95CT has EncodiingID 4 even though TTF Doc says should be 3 */
  209. if (format == 2)
  210. pAFont->cmapFormat = DTT_Win_CT_cmap2;
  211. else /* must be 4 */
  212. pAFont->cmapFormat = DTT_Win_CT_cmap4;
  213. cmapOffset = dwOffset;
  214. dwcmapSize = length;
  215. break;
  216. case 5:
  217. if (format == 2)
  218. pAFont->cmapFormat = DTT_Win_K_cmap2;
  219. else /* must be 4 */
  220. pAFont->cmapFormat = DTT_Win_K_cmap4;
  221. cmapOffset = dwOffset;
  222. dwcmapSize = length;
  223. break;
  224. default:
  225. break;
  226. }
  227. }
  228. if (cmapOffset == 0)
  229. goto exit0;
  230. /* Some TTFs have bad dwcmapSize (wData[1]), so far only Dfgihi7.ttc
  231. * (see bug 289106) has 4 bytes more than dwcmapSize.
  232. * Since we don't want to inspect the tables' relationships to get
  233. * the real length at this late stage (1-14-99), we just read
  234. * in 8 bytes more.
  235. * If these 8 bytes are not used, it doesn't hurt any one.
  236. * If they are use as in dfgihi.ttc, we fix 289106 */
  237. dwcmapSize += 8;
  238. /* next buffer is global cache - not freed per job */
  239. pAFont->pTTcmap = UFLNewPtr(pUFObj->pMem, dwcmapSize );
  240. if (pAFont->pTTcmap == NULL)
  241. goto exit0;
  242. /* Get this cmap subtable data */
  243. dwSize= GETTTFONTDATA(pUFObj,
  244. CMAP_TABLE,
  245. cmapOffset,
  246. (void *) pAFont->pTTcmap,
  247. dwcmapSize,
  248. pUFObj->pFData->fontIndex);
  249. if (dwSize > 0 && dwSize < 0xFFFFFFFF)
  250. {
  251. pAFont->hascmap = 1;
  252. pAFont->cmapTBSize = dwcmapSize;
  253. /* Set the convenient pointers */
  254. if (TTcmap_IS_FORMAT2(pAFont->cmapFormat))
  255. GetTTcmap2Stuff(pAFont->pTTcmap, &(pAFont->cmap2) );
  256. else /* must be 4 */
  257. GetTTcmap4Stuff(pAFont->pTTcmap, &(pAFont->cmap4) );
  258. retVal = 1; /* finally success */
  259. }
  260. else
  261. {
  262. goto exit0;
  263. }
  264. /* Continue to get GSUB and mort only if we have Unicode/CJK cmap */
  265. if (retVal == 0)
  266. goto exit0;
  267. /**********************/
  268. /* get mort table */
  269. /**********************/
  270. dwSize= GETTTFONTDATA(pUFObj,
  271. MORT_TABLE,
  272. 0,
  273. NULL, /* use NULL to ask for size first */
  274. 0,
  275. pUFObj->pFData->fontIndex);
  276. if (dwSize > mort_HEADERSIZE && dwSize < 0xFFFFFFFF)
  277. {
  278. /* Has "mort" in this font - it is Optional */
  279. /* next buffer is global cache - not freed per job */
  280. pAFont->pTTmort = UFLNewPtr(pUFObj->pMem, dwSize );
  281. if (pAFont->pTTmort != NULL)
  282. {
  283. /* Get the mort table data */
  284. dwSize= GETTTFONTDATA(pUFObj,
  285. MORT_TABLE,
  286. 0,
  287. (void *) pAFont->pTTmort,
  288. dwSize,
  289. pUFObj->pFData->fontIndex);
  290. if (dwSize > mort_HEADERSIZE && dwSize < 0xFFFFFFFF)
  291. {
  292. pAFont->hasmort = 1;
  293. pAFont->mortTBSize = dwSize;
  294. /* Set the convenient pointers */
  295. GetTTmortStuff(pAFont->pTTmort, &(pAFont->mortStuff) );
  296. }
  297. }
  298. }
  299. /**********************/
  300. /* get GSUB table */
  301. /**********************/
  302. dwSize= GETTTFONTDATA(pUFObj,
  303. GSUB_TABLE,
  304. 0,
  305. NULL, /* use NULL to ask for size first */
  306. 0,
  307. pUFObj->pFData->fontIndex);
  308. if (dwSize > GSUB_HEADERSIZE && dwSize < 0xFFFFFFFF)
  309. {
  310. /* Has "GSUB" in this font - it is Optional */
  311. /* next buffer is global cache - not freed per job */
  312. pAFont->pTTGSUB = UFLNewPtr(pUFObj->pMem, dwSize );
  313. if (pAFont->pTTGSUB != NULL)
  314. {
  315. /* Get the GSUB table data */
  316. dwSize= GETTTFONTDATA(pUFObj,
  317. GSUB_TABLE,
  318. 0,
  319. (void *) pAFont->pTTGSUB,
  320. dwSize,
  321. pUFObj->pFData->fontIndex);
  322. if (dwSize > GSUB_HEADERSIZE && dwSize < 0xFFFFFFFF)
  323. {
  324. pAFont->hasGSUB = 1;
  325. pAFont->gsubTBSize = dwSize;
  326. /* Set the convenient pointers */
  327. GetTTGSUBStuff(pAFont->pTTGSUB, &(pAFont->GSUBStuff) );
  328. }
  329. }
  330. }
  331. exit0:
  332. if (pTableEntry)
  333. UFLDeletePtr(pUFObj->pMem, pTableEntry);
  334. return retVal;
  335. }
  336. static unsigned short ParseTTcmap2(
  337. TTcmap2Stuff *p2 , /* all convenient pointers are here */
  338. unsigned char *pTTCMAPEnd,
  339. unsigned short gid
  340. )
  341. {
  342. unsigned short codeVal;
  343. unsigned short index;
  344. unsigned short subHdrKey;
  345. PTTcmap2SH pSubHeader;
  346. unsigned short highByte, first, count, byteOffset, id;
  347. short delta;
  348. unsigned short *pTemp;
  349. /* This function parses cmap Format 2: High-byte mapping through table
  350. Win 3-(1/2/3/4/5)-2
  351. */
  352. codeVal = 0;
  353. if (((unsigned char *)(p2->subHeaderKeys) < (unsigned char *)(p2->pByte)) ||
  354. ((unsigned char *)(p2->subHeaderKeys + 256) > pTTCMAPEnd))
  355. return codeVal;
  356. /* Search subHeaders one by one:
  357. subHeader 0 is special: it is used for single-byte character codes,
  358. Other highByte mapped to subHeader 0 should be ignored
  359. */
  360. for (highByte = 0; highByte<256; highByte++)
  361. {
  362. subHdrKey = MOTOROLAINT(p2->subHeaderKeys[highByte]);
  363. if (highByte != 0 && subHdrKey == 0 )
  364. continue;
  365. pSubHeader = p2->subHeaders + (subHdrKey / 8);
  366. if (((unsigned char *)(pSubHeader) < (unsigned char *)(p2->pByte)) ||
  367. ((unsigned char *)(pSubHeader + 1) > pTTCMAPEnd))
  368. continue;
  369. first = MOTOROLAINT(pSubHeader->firstCode);
  370. count = MOTOROLAINT(pSubHeader->entryCount);
  371. delta = MOTOROLAINT(pSubHeader->idDelta);
  372. byteOffset = MOTOROLAINT(pSubHeader->idRangeOffset);
  373. /* How to use idRangeOffset? The document says:
  374. "The value of the idRangeOffset is the number of bytes
  375. past the actual location of the idRangeOffset word where
  376. the glyphIndexArray element corresponding to firstCode appears"
  377. *
  378. Parsing cmap == parsing these words carefully (trial-and-error)!
  379. Offset to idRangeOffset is 524 + subHdrKey - now we know why subHdrKey is i*8 */
  380. byteOffset += 524 + subHdrKey ;
  381. for (index = 0; index < count; index++)
  382. {
  383. pTemp = (unsigned short *) (p2->pByte + byteOffset + 2 * index);
  384. if (((unsigned char *)pTemp < (unsigned char *)(p2->pByte)) ||
  385. ((unsigned char *)pTemp > pTTCMAPEnd))
  386. continue;
  387. id = *(pTemp);
  388. id = MOTOROLAINT(id);
  389. if (id == 0)
  390. continue;
  391. id += delta ;
  392. if (id == gid)
  393. {
  394. codeVal = (highByte << 8) + index + first ;
  395. return codeVal;
  396. }
  397. }
  398. }
  399. return codeVal;
  400. }
  401. static unsigned short ParseTTcmap4(
  402. TTcmap4Stuff *p4 , /* all convenient pointers are here */
  403. unsigned char *pTTCMAP,
  404. unsigned char *pTTCMAPEnd,
  405. unsigned short gid
  406. )
  407. {
  408. unsigned short codeVal;
  409. long index, j, k, rangeNum;
  410. unsigned short gidStart, gidEnd;
  411. unsigned short n1, n2;
  412. /* This function parses cmap Format 4: Segment mapping to delta values
  413. Win 3-(1/2/3/4/5)-4
  414. */
  415. codeVal = 0;
  416. if (((unsigned char *)(p4->idRangeOffset) < pTTCMAP) ||
  417. ((unsigned char *)(p4->idRangeOffset + p4->segCount) > pTTCMAPEnd))
  418. return codeVal;
  419. if (((unsigned char *)(p4->startCode) < pTTCMAP) ||
  420. ((unsigned char *)(p4->startCode + p4->segCount) > pTTCMAPEnd))
  421. return codeVal;
  422. if (((unsigned char *)(p4->idDelta) < pTTCMAP) ||
  423. ((unsigned char *)(p4->idDelta + p4->segCount) > pTTCMAPEnd))
  424. return codeVal;
  425. if (((unsigned char *)(p4->endCode) < pTTCMAP) ||
  426. ((unsigned char *)(p4->endCode + p4->segCount) > pTTCMAPEnd))
  427. return codeVal;
  428. /* Search for segments with idRangeOffset[i] =0 */
  429. for (index = 0; index <= (long)p4->segCount; index++)
  430. {
  431. if (p4->idRangeOffset[index] != 0)
  432. continue;
  433. gidStart = MOTOROLAINT(p4->idDelta[index]) + MOTOROLAINT(p4->startCode[index]);
  434. gidEnd = MOTOROLAINT(p4->idDelta[index]) + MOTOROLAINT(p4->endCode[index]);
  435. if (gidStart <= gid &&
  436. gidEnd >= gid)
  437. {
  438. codeVal = gid - MOTOROLAINT(p4->idDelta[index]);
  439. return codeVal;
  440. }
  441. }
  442. /* Still not found, Search for segments with idRangeOffset[i] !=0 */
  443. for (index = 0; index <= (long)p4->segCount; index++)
  444. {
  445. if (p4->idRangeOffset[index] == 0)
  446. continue;
  447. n1 = MOTOROLAINT(p4->startCode[index]);
  448. n2 = MOTOROLAINT(p4->endCode[index]);
  449. rangeNum = n2 - n1;
  450. /* check for End of cmap - fix bug 261628 */
  451. if (n1 == 0xFFFF)
  452. break;
  453. /* check for Bad cmap */
  454. if (n1 > n2)
  455. break;
  456. /* have to check one-by-one */
  457. for (j = 0; j <= rangeNum; j++)
  458. {
  459. /* Word index to glyphIDArray */
  460. k = j + MOTOROLAINT(p4->idRangeOffset[index]) / 2 - p4->segCount + index ;
  461. gidStart = MOTOROLAINT(p4->glyphIdArray[k]);
  462. if (gidStart != 0)
  463. {
  464. gidStart += MOTOROLAINT(p4->idDelta[index]);
  465. if (gidStart == gid)
  466. {
  467. codeVal = MOTOROLAINT(p4->startCode[index]) + (unsigned short)j;
  468. return codeVal;
  469. }
  470. }
  471. }
  472. }
  473. return codeVal;
  474. }
  475. static unsigned short ParseTTcmapForUnicode(
  476. AFontStruct *pAFont,
  477. unsigned short gid,
  478. unsigned short *pUV,
  479. unsigned short wSize
  480. )
  481. {
  482. unsigned short codeVal;
  483. unsigned char *pTTCMAPEnd;
  484. pTTCMAPEnd = ((unsigned char *)pAFont->pTTcmap) + pAFont->cmapTBSize;
  485. /* Find code point for the glyph id by reversing cmap */
  486. if (TTcmap_IS_FORMAT2(pAFont->cmapFormat))
  487. codeVal = ParseTTcmap2(&(pAFont->cmap2), pTTCMAPEnd, gid);
  488. else /* must be 4 */
  489. codeVal = ParseTTcmap4(&(pAFont->cmap4), pAFont->pTTcmap, pTTCMAPEnd, gid);
  490. if (codeVal == 0)
  491. return 0;
  492. /* found corresponding code - convert to Unicode if code is not Unicode*/
  493. *pUV = codeVal;
  494. return 1;
  495. }
  496. /* ------------------------------------------------------------------ */
  497. /* Coverage Table:
  498. CoverageFormat1 table: Individual glyph indices
  499. Type Name Description
  500. uint16 CoverageFormat Format identifier format = 1
  501. uint16 GlyphCount Number of glyphs in the GlyphArray
  502. GlyphID GlyphArray[GlyphCount] Array of GlyphIDs in numerical order
  503. CoverageFormat2 table: Range of glyphs
  504. Type Name Description
  505. uint16 CoverageFormat Format identifier format = 2
  506. uint16 RangeCount Number of RangeRecords
  507. struct RangeRecord[RangeCount] Array of glyph ranges ordered by Start GlyphID
  508. RangeRecord
  509. Type Name Description
  510. GlyphID Start First GlyphID in the range
  511. GlyphID End Last GlyphID in the range
  512. uint16 StartCoverageIndex Coverage Index of first GlyphID in range
  513. */
  514. /* A lcoal function to enumerate/parse Coverage table used in GSUB:
  515. * gid0 - starting point for next covered Gid;
  516. * it is also used as state variable, 0 at beginning.
  517. * gidInput - one gid Covered >= gid; 0xFFFF when there is no such gid
  518. * coverageIndex - Coverage Index for gidIn
  519. * return: true if there are more glyphs covered
  520. */
  521. static UFLBool EnumTTCoverage(
  522. void *pCoverage, /* Coverage table */
  523. unsigned char *pTTGSUBEnd,
  524. unsigned short gid0, /* start */
  525. unsigned short *gidInput, /* gid covered */
  526. unsigned short *coverageIndex /* corresponding Index */
  527. )
  528. {
  529. unsigned short *pWord;
  530. unsigned short cFormat, gCount, gid;
  531. unsigned short *pGid;
  532. long index;
  533. if (pCoverage == NULL || gid0 == 0xFFFF)
  534. return 0;
  535. // pCoverage is a good pointer, it has been checked begore calling this function
  536. pWord = (unsigned short *) pCoverage;
  537. cFormat = MOTOROLAINT(pWord[0]);
  538. gCount = MOTOROLAINT(pWord[1]); /* count of Glyph or ranGes */
  539. pGid = (unsigned short *)((unsigned char *)pCoverage + 4);
  540. /* find next gid >= gid0 -- Coverage is ordered! */
  541. if (cFormat == 1)
  542. {
  543. // Fixed bug #516519
  544. if ((unsigned char *)(pGid + gCount) > pTTGSUBEnd)
  545. goto Done;
  546. /* List format, pGid points to GlyphArray and coverageIndex starts from 0 */
  547. for (index = 0; index < (long)gCount; index++ )
  548. {
  549. gid = MOTOROLAINT(pGid[index]);
  550. if (gid >= gid0)
  551. {
  552. *gidInput = gid;
  553. *coverageIndex = (unsigned short)index;
  554. return 1;
  555. }
  556. }
  557. }
  558. else if (cFormat == 2)
  559. {
  560. /* Range format, pGid points to first RangeRecord */
  561. unsigned short gidStart, gidEnd, startCoverageIndex;
  562. // Fixed bug #516519
  563. if ((unsigned char *)(pGid + gCount*3) > pTTGSUBEnd)
  564. goto Done;
  565. for (index = 0; index < (long)gCount; index++ )
  566. {
  567. gidStart = MOTOROLAINT(pGid[0]);
  568. gidEnd = MOTOROLAINT(pGid[1]);
  569. startCoverageIndex = MOTOROLAINT(pGid[2]);
  570. /* first if gid0==0 */
  571. if (gid0 == 0)
  572. {
  573. if ( index == 0 )
  574. {
  575. *gidInput = gidStart;
  576. *coverageIndex = startCoverageIndex;
  577. return 1;
  578. }
  579. }
  580. /* find the first range that covers gid0 */
  581. else if (gid0 >= gidStart && gid0 <= gidEnd )
  582. {
  583. *gidInput = gid0;
  584. *coverageIndex = startCoverageIndex + gid0 - gidStart;
  585. return 1;
  586. }
  587. pGid += 3; /* Each RangeRecord is 3 ASUns16 */
  588. }
  589. }
  590. /* else don't know or new format */
  591. Done:
  592. *gidInput = 0xFFFF;
  593. *coverageIndex = 0xFFFF;
  594. return 0;
  595. }
  596. /* ------------------------------------------------------------------ */
  597. /* SingleSubstitution Table
  598. SingleSubstFormat1 subtable: Calculated output glyph indices
  599. Type Name Description
  600. uint16 SubstFormat Format identifier-format = 1
  601. Offset Coverage Offset to Coverage table-from beginning of substitution table
  602. int16 DeltaGlyphID Add to original GlyphID to get substitute GlyphID
  603. SingleSubstFormat2 subtable: Specified output glyph indices
  604. Type Name Description
  605. uint16 SubstFormat Format identifier-format = 2
  606. Offset Coverage Offset to Coverage table-from beginning of Substitution table
  607. uint16 GlyphCount Number of GlyphIDs in the Substitute array
  608. GlyphID Substitute[GlyphCount] Array of substitute GlyphIDs
  609. -ordered by Coverage Index
  610. */
  611. /* A local function to parse Substitution Table Format 1
  612. * have to linear search - we are doing reverse mapping from
  613. * the substitutedGID to original gid
  614. */
  615. static unsigned short ParseTTSubstTable_1(
  616. void *pSubstTable, /* Subst table data */
  617. unsigned char *pTTGSUBEnd,
  618. unsigned short gid, /* Given GID */
  619. unsigned short *pRSubGid /* Reverse Substitution */
  620. )
  621. {
  622. unsigned short *pTable;
  623. void *pCoverage;
  624. unsigned short substFormat;
  625. unsigned short offSet;
  626. unsigned short gidIn, coverageIndex;
  627. // pTable is a good pointer, it has been checked begore calling this function
  628. pTable = (unsigned short *)(pSubstTable);
  629. /* pTable points to either SingleSubstFormat1 or SingleSubstFormat2 */
  630. substFormat = MOTOROLAINT(pTable[0]);
  631. offSet = MOTOROLAINT(pTable[1]);
  632. pCoverage = (void *) ((unsigned char *)pSubstTable + offSet );
  633. // Fixed bug #516519.
  634. // Check to make sure pConverage is good. It is used in function EnumTTCoverage
  635. if (((unsigned char *)pCoverage < (unsigned char *)pSubstTable) ||
  636. ((unsigned char *)pCoverage + 3*sizeof(unsigned short)) > pTTGSUBEnd)
  637. {
  638. return 0;
  639. }
  640. if (substFormat == 1 )
  641. {
  642. unsigned short delta = MOTOROLAINT(pTable[2]);
  643. gidIn = 0;
  644. coverageIndex = 0;
  645. while (EnumTTCoverage(pCoverage, pTTGSUBEnd, gidIn, &gidIn, &coverageIndex) )
  646. {
  647. if (gid == gidIn + delta)
  648. {
  649. /* gidIn may be substituted by gid in the PS file, return the reverseSubstituiton */
  650. *pRSubGid = gidIn;
  651. return 1;
  652. }
  653. gidIn++; /* For EnumTTCoverage() */
  654. }
  655. return 0;
  656. }
  657. else if (substFormat == 2 )
  658. {
  659. unsigned short count, gidSub;
  660. count = MOTOROLAINT(pTable[2]);
  661. gidIn = 0;
  662. coverageIndex = 0;
  663. while (EnumTTCoverage(pCoverage, pTTGSUBEnd, gidIn, &gidIn, &coverageIndex) )
  664. {
  665. if (coverageIndex < count)
  666. {
  667. gidSub = MOTOROLAINT(pTable[ 3 + coverageIndex]);
  668. if (gid == gidSub)
  669. {
  670. /* gidIn may be substituted by gid in the PS file, return the reverseSubstituiton */
  671. *pRSubGid = gidIn;
  672. return 1;
  673. }
  674. }
  675. gidIn++; /* For EnumTTCoverage() */
  676. }
  677. return 0;
  678. }
  679. /* else unknow or not found */
  680. return 0;
  681. }
  682. /* ------------------------------------------------------------------ */
  683. /*
  684. AlternateSubstFormat1 subtable: Alternative output glyphs
  685. Type Name Description
  686. uint16 SubstFormat Format identifier-format = 1
  687. Offset Coverage Offset to Coverage table-from beginning of Substitution table
  688. uint16 AlternateSetCount Number of AlternateSet tables
  689. Offset AlternateSet[AlternateSetCount] Array of offsets to AlternateSet tables
  690. -from beginning of Substitution table-ordered by Coverage Index
  691. AlternateSet table
  692. Type Name Description
  693. uint16 GlyphCount Number of GlyphIDs in the Alternate array
  694. GlyphID Alternate[GlyphCount] Array of alternate GlyphIDs-in arbitrary order
  695. */
  696. /* A local function to parse Substitution Table Format 1
  697. * have to linear search - we are doing reverse mapping from
  698. * the substitutedGID to original gid
  699. */
  700. static unsigned short ParseTTSubstTable_3(
  701. void *pSubstTable, /* Subst table data */
  702. unsigned char *pTTGSUBEnd,
  703. unsigned short gid, /* Given GID */
  704. unsigned short *pRSubGid /* Reverse Substitution */
  705. )
  706. {
  707. unsigned short *pTable;
  708. void *pCoverage;
  709. unsigned short substFormat;
  710. unsigned short offSet, altCount;
  711. unsigned short gidIn, coverageIndex;
  712. unsigned short *pAlt;
  713. // pTable is a good pointer, it has been checked begore calling this function
  714. pTable = (unsigned short *)(pSubstTable);
  715. /* pTable points to AlternateSubstFormat1 */
  716. substFormat = MOTOROLAINT(pTable[0]);
  717. offSet = MOTOROLAINT(pTable[1]);
  718. pCoverage = (void *) ((unsigned char *)pSubstTable + offSet );
  719. // Fixed bug #516519
  720. // Check to make sure pConverage is good. It is used in function EnumTTCoverage
  721. if (((unsigned char *)pCoverage < (unsigned char *)pSubstTable) ||
  722. ((unsigned char *)pCoverage + 3*sizeof(unsigned short)) > pTTGSUBEnd)
  723. {
  724. return 0;
  725. }
  726. altCount = MOTOROLAINT(pTable[2]);
  727. if (substFormat == 1 )
  728. {
  729. unsigned short index, gCount, gidAlt;
  730. gidIn = 0;
  731. coverageIndex = 0;
  732. while (EnumTTCoverage(pCoverage, pTTGSUBEnd, gidIn, &gidIn, &coverageIndex) )
  733. {
  734. if (coverageIndex < altCount)
  735. {
  736. /* For each gidIn, we have an array of alternates */
  737. offSet = MOTOROLAINT(pTable[3 + coverageIndex] );
  738. pAlt = (unsigned short *) ((unsigned char *)pSubstTable + offSet );
  739. gCount = MOTOROLAINT(pAlt[0]);
  740. for (index = 0; index < gCount; index++)
  741. {
  742. gidAlt = MOTOROLAINT(pAlt[1 + index]);
  743. if (gidAlt == gid)
  744. {
  745. /* gidIn may be substituted by gid in the PS file, return the reverseSubstituiton */
  746. *pRSubGid = gidIn;
  747. return 1;
  748. }
  749. }
  750. }
  751. gidIn++; /* For EnumTTCoverage() */
  752. }
  753. return 0;
  754. }
  755. /* else unknow or not found */
  756. return 0;
  757. }
  758. /* ------------------------------------------------------------------ */
  759. /* Function to parse GSUB table. Since we only want the substituted glyph index
  760. * to parse cmap for Unicode information, we don't have to look at
  761. * ScriptList/FeatureList. For LookUpTypes, we only check 1-1 substitution:
  762. * -Single- replace one glyph with another ,and
  763. * -Alternate- replace one glyph with one of many glyphs
  764. * Ignore Multple/Ligature/Context - are they for a text layout only???
  765. *
  766. GSUB Header (Offset = uint16)
  767. Type Name Description
  768. fixed32 Version Version of the GSUB table
  769. initially set to 0x00010000
  770. Offset ScriptList Offset to ScriptList table
  771. from beginning of GSUB table
  772. Offset FeatureList Offset to FeatureList table
  773. from beginning of GSUB table
  774. Offset LookupList Offset to LookupList table
  775. from beginning of GSUB table
  776. Lookup List:
  777. Type Name Description
  778. uint16 LookupCount Number of lookups in this table
  779. Offset Lookup[LookupCount] Array of offsets to Lookup tables
  780. from beginning of LookupList (first lookup is Lookup index = 0)
  781. Lookup Table
  782. Type Name Description
  783. uint16 LookupType Different enumerations for GSUB
  784. uint16 LookupFlag Lookup qualifiers
  785. uint16 SubTableCount Number of SubTables for this lookup
  786. Offset SubTable[SubTableCount] Array of offsets to SubTables
  787. from beginning of Lookup table
  788. */
  789. static unsigned short ParseTTGSUBForSubGid(
  790. void *pTTGSUB, /* GSUB table data */
  791. unsigned long gsubTBSize,
  792. TTGSUBStuff *p,
  793. unsigned short gid, /* Given GID */
  794. unsigned short *pRSubGid /* Reverse Substitution */
  795. )
  796. {
  797. unsigned short lookupType;
  798. unsigned short subTableCount;
  799. long i, j;
  800. unsigned short offSet;
  801. unsigned short *pTable;
  802. void *pSubstTable;
  803. unsigned char *pTTGSUBEnd;
  804. if (pTTGSUB == NULL || gid == 0 || p == NULL )
  805. return 0;
  806. // Fixed bug #516519.
  807. // Check to see if pointer p and lookup array are whthin GSUB table
  808. pTTGSUBEnd = (unsigned char *)pTTGSUB + gsubTBSize;
  809. if (((unsigned char *)p < (unsigned char *)pTTGSUB) ||
  810. ((unsigned char *)p + sizeof(unsigned short) * p->lookupCount) > pTTGSUBEnd)
  811. {
  812. return 0;
  813. }
  814. /* GSUB must be good - should check for pTTFData->hasGSUB first */
  815. /* now look through the lookup tables one by one */
  816. for (i = 0; i < (long)p->lookupCount; i++)
  817. {
  818. offSet = MOTOROLAINT(p->pLookupList[1 + i]); /* skip lookupCount */
  819. pTable = (unsigned short *)((unsigned char *)p->pLookupList + offSet);
  820. // Fixed bug #516519.
  821. // check to see if the offset is within the gsub table.
  822. // Add 3 to make sure we can get pTable[0],pTable[1],pTable[2] (see code right below)
  823. if (((unsigned char *)pTable < (unsigned char *)pTTGSUB) ||
  824. ((unsigned char *)(pTable + 3) > pTTGSUBEnd))
  825. {
  826. continue;
  827. }
  828. lookupType = MOTOROLAINT(pTable[0]);
  829. subTableCount = MOTOROLAINT(pTable[2]);
  830. // Fixed bug #516519
  831. if ((unsigned char *)(pTable + subTableCount + 3) > pTTGSUBEnd)
  832. {
  833. continue;
  834. }
  835. /* Only parse Type Single(1) and Alternate(3) tables */
  836. if (lookupType == 1 )
  837. {
  838. for (j = 0; j < (long)subTableCount; j++)
  839. {
  840. offSet = MOTOROLAINT(pTable[3 + j]);
  841. pSubstTable = (void *) ((unsigned char *)pTable + offSet );
  842. // Fixed bug #516519.
  843. // add 6 bytes (3*sizeof(ushort)) to make sure we can get Table[0..2]
  844. // Please see ParseTTSubstTable_1
  845. if (((unsigned char *)pSubstTable < (unsigned char*)pTTGSUB) ||
  846. (((unsigned char *)pSubstTable + 3*sizeof(unsigned short)) > pTTGSUBEnd))
  847. {
  848. continue;
  849. }
  850. if (ParseTTSubstTable_1(pSubstTable, pTTGSUBEnd, gid, pRSubGid) )
  851. return 1;
  852. }
  853. }
  854. else if (lookupType == 3)
  855. {
  856. for (j = 0; j < (long) subTableCount; j++)
  857. {
  858. offSet = MOTOROLAINT(pTable[3 + j]);
  859. pSubstTable = (void *) ((unsigned char *)pTable + offSet );
  860. // Fixed bug #516519
  861. if (((unsigned char *)pSubstTable < (unsigned char *) pTTGSUB) ||
  862. (((unsigned char *)pSubstTable + 3*sizeof(unsigned short)) > pTTGSUBEnd))
  863. {
  864. continue;
  865. }
  866. if (ParseTTSubstTable_3(pSubstTable, pTTGSUBEnd, gid, pRSubGid) )
  867. return 1;
  868. }
  869. }
  870. /* else - ignore other Substitutions */
  871. }
  872. /* not found */
  873. return 0;
  874. }
  875. /* ------------------------------------------------------------------ */
  876. /* Function to parse mort table. We recognize only a very specific
  877. implementation of 'mort' as used/understood by GDI:
  878. Name Contents
  879. (constants) 0x000100000000000100000001
  880. Uint32 length1 Length of the whole table - 8
  881. (constants) 0x000300010003000000000001FFFFFFFF
  882. (constants) 0x0003000100000000FFFFFFFE00080000
  883. (constants) 0x0000000000000000
  884. Uint16 length2 Length of the whole table - 0x38
  885. (constants) 0x8004000000010006
  886. BinSrchHeader binSrchHeader Binary Search Header
  887. LookupSingle entries[n] Actual lookup entries, sorted by glyph index
  888. BinSrchHeader
  889. Type Name Contents
  890. Uint16 entrySize Size in bytes of a lookup entry (set to 4)
  891. Uint16 nEntries Number of lookup entries to be searched
  892. Uint16 searchRange entrySize * (largest power of 2 less than or equal to nEntries)
  893. Uint16 entrySelector log2 of (largest power of 2 less than or equal to nEntries)
  894. Uint16 rangeShift entrySize * (nEntries - largest power of 2 less than or equal to nEntries)
  895. LookupSingle
  896. Type Name Contents
  897. GlyphID glyphid1 The glyph index for the horizontal shape
  898. GlyphID glyphid2 The glyph index for the vertical shape
  899. The last lookup entry must be a sentinel with glyphid1=glyphid2=0xFFFF.
  900. */
  901. static unsigned short ParseTTmortForSubGid(
  902. void *pTTmort, /* mort table data */
  903. unsigned long mortTBSize,
  904. TTmortStuff *p, /* all convenient pointers are here */
  905. unsigned short gid, /* Given GID */
  906. unsigned short *pRSubGid /* Reverse Substitution */
  907. )
  908. {
  909. unsigned short gid1, gid2;
  910. long i;
  911. if (pTTmort == NULL || gid == 0 || p == NULL)
  912. return 0;
  913. // Fixed bug #516519.
  914. // Check to see if pointer p and lookup array are whthin MORT table
  915. if (((unsigned char *)p < (unsigned char *)pTTmort) ||
  916. ((unsigned char *)p + sizeof(unsigned short) * 2 * p->nEntries) > ((unsigned char *)pTTmort + mortTBSize))
  917. {
  918. return 0;
  919. }
  920. /* mort must be good - should check for pTTFData->hasmort first */
  921. /* Search for gid - we do linear search because 'mort'
  922. table is usually for vertical substitution and we want the
  923. original Horizontal gid for a given Vertical gid
  924. */
  925. for (i = 0; i <= (long) p->nEntries; i++)
  926. {
  927. gid1 = MOTOROLAINT(p->pGlyphSet[i * 2]);
  928. gid2 = MOTOROLAINT(p->pGlyphSet[i * 2 + 1]);
  929. if (gid1 == 0xFFFF && gid2 == 0xFFFF)
  930. break;
  931. if (gid2 == gid)
  932. {
  933. *pRSubGid = gid1;
  934. return 1;
  935. }
  936. }
  937. /* not found */
  938. return 0;
  939. }
  940. /* ------------------------------------------------------------------ */
  941. unsigned short ParseTTTablesForUnicode(
  942. UFOStruct *pUFObj,
  943. unsigned short gid,
  944. unsigned short *pUV,
  945. unsigned short wSize,
  946. TTparseFlag ParseFlag
  947. )
  948. {
  949. AFontStruct *pAFont;
  950. unsigned short retVal = 0;
  951. unsigned short gidSave;
  952. unsigned short i;
  953. *pUV = 0;
  954. if (pUFObj == NULL)
  955. return 0;
  956. pAFont = pUFObj->pAFont;
  957. if (pAFont == NULL)
  958. return 0;
  959. /* This function only get at most 1 UV for a glyph ID */
  960. if (pUV == NULL)
  961. return 1;
  962. if (!GetTablesFromTTFont(pUFObj))
  963. return 0;
  964. /* This function depends on good cmap format:
  965. Platform=3, Encoding=1/2/3/4/5, Format=4 */
  966. if (pAFont->pTTcmap == NULL ||
  967. pAFont->hascmap == 0 ||
  968. gid == 0 )
  969. return 0;
  970. /* if DTT_parseCmapOnly flag is set, means that
  971. /* we need unicode only. do not need char code */
  972. if ((ParseFlag == DTT_parseCmapOnly) &&
  973. (!TTcmap_IS_UNICODE(pAFont->cmapFormat)))
  974. return 0;
  975. if ((ParseFlag == DTT_parseCmapOnly) ||
  976. (ParseFlag == DTT_parseAllTables))
  977. {
  978. retVal = ParseTTcmapForUnicode(pAFont, gid, pUV, wSize);
  979. }
  980. if ((retVal == 0) && (pAFont->hasmort || pAFont->hasGSUB) &&
  981. ((ParseFlag == DTT_parseMoreGSUBOnly) ||
  982. (ParseFlag == DTT_parseAllTables)))
  983. {
  984. unsigned short revSubGid;
  985. unsigned short hasSub;
  986. /* Still not found, try GSUB table */
  987. if (retVal == 0 && pAFont->hasGSUB )
  988. {
  989. gidSave = gid;
  990. for (i = 0; i < 10; i++) // Loop Max 10 times.
  991. {
  992. hasSub = ParseTTGSUBForSubGid(pAFont->pTTGSUB, pAFont->gsubTBSize, &(pAFont->GSUBStuff), gid, &revSubGid);
  993. if (hasSub)
  994. {
  995. retVal = ParseTTcmapForUnicode(pAFont, revSubGid, pUV, wSize);
  996. if (retVal != 0)
  997. break;
  998. else
  999. gid = revSubGid;
  1000. }
  1001. else
  1002. break;
  1003. }
  1004. gid = gidSave;
  1005. }
  1006. /* try mort table for substitution (reverse searching) */
  1007. if (retVal == 0 && pAFont->hasmort)
  1008. {
  1009. hasSub = ParseTTmortForSubGid(pAFont->pTTmort, pAFont->mortTBSize, &(pAFont->mortStuff), gid, &revSubGid);
  1010. if (hasSub)
  1011. {
  1012. retVal = ParseTTcmapForUnicode(pAFont, revSubGid, pUV, wSize);
  1013. }
  1014. }
  1015. }
  1016. return retVal;
  1017. }