Source code of Windows XP (NT5)
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.

1374 lines
40 KiB

  1. /***
  2. **
  3. ** Module: T1Parser
  4. **
  5. ** Description:
  6. ** This is a module of the T1 to TT font converter. The module
  7. ** will extract information from a T1 font file, by parsing
  8. ** the data/commands found in PFB, PFM and AFM files.
  9. **
  10. ** Author: Michael Jansson
  11. **
  12. ** Created: 5/26/93
  13. **
  14. ***/
  15. /**** INCLUDES */
  16. /* General types and definitions. */
  17. #include <string.h>
  18. #include "types.h"
  19. /* Special types and definitions. */
  20. #include "safemem.h"
  21. #include "encoding.h"
  22. #include "metrics.h"
  23. #include "t1msg.h"
  24. /* Module dependent types and prototypes. */
  25. #include "titott.h"
  26. #include "t1parser.h"
  27. #include "charstr.h"
  28. #include "freader.h"
  29. #include "mreader.h"
  30. /***** CONSTANTS */
  31. #define ONE (USHORT)1
  32. #define BUFLEN (USHORT)512
  33. #define PS_ANGLE "/ItalicAngle"
  34. #define PS_ARRAY "array"
  35. #define PS_BEGIN "begin"
  36. #define PS_BLUEFUZZ "/BlueFuzz"
  37. #define PS_BLUESCALE "/BlueScale"
  38. #define PS_BLUESHIFT "/BlueShift"
  39. #define PS_BLUEVALUES "/BlueValues"
  40. #define PS_CHARSTRINGS "/CharStrings"
  41. #define PS_COPYRIGHT "/Copyright"
  42. #define PS_DATE "%%CreationDate:"
  43. #define PS_DUP "dup"
  44. #define PS_ENCODING "/Encoding"
  45. #define PS_END "end"
  46. #define PS_FAMILY "/FamilyName"
  47. #define PS_FAMILYBLUES "/FamilyBlues"
  48. #define PS_FAMILYOTHERBLUES "/FamilyOtherBlues"
  49. #define PS_FONTMATRIX "/FontMatrix"
  50. #define PS_FORCEBOLD "/ForceBold"
  51. #define PS_FULLNAME "/FullName"
  52. #define PS_HYBRID "hires"
  53. #define PS_ISFIXED "/isFixedPitch"
  54. #define PS_LENIV "/lenIV"
  55. #define PS_NAME "/FontName"
  56. #define PS_NOACCESS "noaccess"
  57. #define PS_NOTICE "/Notice"
  58. #define PS_OTHERBLUES "/OtherBlues"
  59. #define PS_SNAPH "/StemSnapH"
  60. #define PS_SNAPV "/StemSnapV"
  61. #define PS_STDENCODING "StandardEncoding"
  62. #define PS_STDVW "/StdVW"
  63. #define PS_STDHW "/StdHW"
  64. #define PS_SUBRS "/Subrs"
  65. #define PS_UNDERLINE "/UnderlinePosition"
  66. #define PS_UTHICK "/UnderlineThickness"
  67. #define PS_ID "/UniqueID"
  68. #define PS_VERSION "/version"
  69. #define PS_WEIGHT "/Weight"
  70. /***** LOCAL TYPES */
  71. struct T1Handle {
  72. struct FontFile *ff;
  73. struct PSState *ps;
  74. struct Subrs stdenc[256];
  75. USHORT numsubrs;
  76. struct Subrs *subrs;
  77. USHORT leniv;
  78. struct T1Metrics t1m;
  79. };
  80. /***** MACROS */
  81. /*-none-*/
  82. /***** PROTOTYPES */
  83. /*-none-*/
  84. /***** STATIC FUNCTIONS */
  85. /***
  86. ** Function: StrToFix
  87. **
  88. ** Description:
  89. ** This is a "strtod" function, that converts from
  90. ** ascii to fixpoint numbers.
  91. ***/
  92. static long StrToFix(char *str, char **out, const long base)
  93. {
  94. char *fstr;
  95. long num = 0, frac = 0, exp = 0;
  96. if (out)
  97. (*out) = str;
  98. /* Skip white space. */
  99. while (*str && (*str==' ' || *str=='\t'))
  100. str++;
  101. /* A number? */
  102. if (*str && ((*str>='0' && *str<='9') || *str=='-') || *str=='.') {
  103. num = atoi(str)*base;
  104. /* Fraction? */
  105. fstr = strchr(str, '.');
  106. if (fstr!=NULL && (strchr(str, ' ')==NULL || fstr<strchr(str, ' '))) {
  107. do {
  108. fstr++;
  109. } while (*fstr>='0' && *fstr<='9');
  110. /* Exponent? */
  111. if (*fstr=='E')
  112. exp = atoi(fstr+1);
  113. else
  114. exp = 0;
  115. fstr--;
  116. while (*fstr!='.') {
  117. frac += ((*fstr)-'0')*base;
  118. frac /= 10;
  119. fstr--;
  120. }
  121. if (num<0)
  122. num -= frac;
  123. else
  124. num += frac;
  125. /* Handle exponent. */
  126. if (exp>0) {
  127. do {
  128. num *= 10;
  129. } while (--exp);
  130. } else if (exp<0) {
  131. do {
  132. num /= 10;
  133. } while (++exp);
  134. }
  135. }
  136. /* Skip digits. */
  137. while (*str && ((*str>='0' && *str<='9') ||
  138. *str=='.' || *str=='-' || *str=='E'))
  139. str++;
  140. if (out)
  141. (*out) = str;
  142. }
  143. return num;
  144. }
  145. /***
  146. ** Function: FreeT1Composite
  147. **
  148. ** Description:
  149. ** This function frees the memory used to represent
  150. ** a composite acented T1 glyph.
  151. ***/
  152. static void FreeT1Composite(Composite *comp)
  153. {
  154. if (comp) {
  155. if (comp->cchar)
  156. Free(comp->cchar);
  157. Free(comp);
  158. }
  159. }
  160. /***
  161. ** Function: UseGlyph
  162. **
  163. ** Description:
  164. ** This function determines whether a glyph should be
  165. ** converted or not, based on the name of the glyph
  166. ** and a specification of the desired glyphs.
  167. ***/
  168. static int CDECL compare(const void *arg1, const void *arg2)
  169. {
  170. return strcmp( *((const char **)arg1), *((const char **)arg2) );
  171. }
  172. static boolean UseGlyph(const struct GlyphFilter *filter,
  173. Composite *comp,
  174. const char *name)
  175. {
  176. boolean found = FALSE;
  177. char **result;
  178. /* Check if the glyph is explicitly specified. */
  179. if (filter) {
  180. result = (char **)bsearch((char *)&name,
  181. (char *)filter->name, filter->num,
  182. sizeof(char *),
  183. compare);
  184. found = (boolean)(result!=NULL);
  185. /* Check if the glyph is specified indirectly through an accented */
  186. /* composite glyph. */
  187. if (!found) {
  188. Composite *c;
  189. for (c=comp; c &&
  190. strcmp(name, c->achar) &&
  191. strcmp(name, c->bchar); c = c->next);
  192. found = (boolean)(c!=NULL);
  193. }
  194. } else {
  195. found = TRUE;
  196. }
  197. return found;
  198. }
  199. /***
  200. ** Function: ReadFontMatrix
  201. **
  202. ** Description:
  203. ** Read the command sequence "/FontMatrix[%d %d %d %d]" and
  204. ** record the transformation matrix in the T1 handle.
  205. ***/
  206. static errcode ReadFontMatrix(struct T1Handle *t1,
  207. char *str,
  208. const USHORT len)
  209. {
  210. errcode status=SUCCESS;
  211. f16d16 fmatrix[6];
  212. USHORT i;
  213. if (GetSeq(t1->ff, str, len)) {
  214. for (i=0; i<6; i++)
  215. fmatrix[i] = StrToFix(str, &str, F16D16BASE);
  216. /* Check if we have the default matrix. */ /*lint -e771 */
  217. if (fmatrix[2]!=0 ||
  218. fmatrix[4]!=0 ||
  219. fmatrix[1]!=0 ||
  220. fmatrix[5]!=0 ||
  221. fmatrix[0]!=F16D16PPM ||
  222. fmatrix[3]!=F16D16PPM ||
  223. t1->t1m.upem!=2048) { /*lint +e771 */ /* fmatrix[] IS initialized */
  224. if ((t1->t1m.fmatrix = Malloc(sizeof(f16d16)*6))==NULL) {
  225. SetError(status = NOMEM);
  226. } else {
  227. t1->t1m.fmatrix[0] = fmatrix[0];
  228. t1->t1m.fmatrix[1] = fmatrix[1];
  229. t1->t1m.fmatrix[2] = fmatrix[2];
  230. t1->t1m.fmatrix[3] = fmatrix[3];
  231. t1->t1m.fmatrix[4] = fmatrix[4];
  232. t1->t1m.fmatrix[5] = fmatrix[5];
  233. }
  234. } else {
  235. t1->t1m.fmatrix = NULL;
  236. }
  237. } else {
  238. SetError(status = BADINPUTFILE);
  239. }
  240. return status;
  241. }
  242. /***
  243. ** Function: ReadEncodingArray
  244. **
  245. ** Description:
  246. ** Read the command sequence "/Encoding %d array ..." and
  247. ** build an encoding table, or read "/Encoding StdEncoding def"
  248. ** and used the standard encoding table.
  249. ***/
  250. static errcode ReadEncodingArray(struct T1Handle *t1,
  251. char *str,
  252. const USHORT len)
  253. {
  254. errcode status = SUCCESS;
  255. USHORT codes[ENC_MAXCODES];
  256. char *glyph_name = NULL;
  257. USHORT i, index;
  258. if (Get_Token(t1->ff, str, len)==NULL) {
  259. SetError(status = BADINPUTFILE);
  260. } else {
  261. if (strcmp(str, PS_STDENCODING) &&
  262. ((t1->t1m.encSize=(USHORT)atoi(str))!=0)) {
  263. if ((t1->t1m.encoding = AllocEncodingTable(t1->t1m.encSize))==NULL) {
  264. SetError(status = NOMEM);
  265. } else {
  266. /* Skip leading proc. */
  267. while (Get_Token(t1->ff, str, len) && strcmp(str, PS_DUP));
  268. /* Read the encoding entries: "<n> <str> put <comment>\n dup" */
  269. for (i=0; i<t1->t1m.encSize; i++) {
  270. /* Get character code. */
  271. (void)Get_Token(t1->ff, str, len);
  272. if (str[0]=='8' && str[1]=='#') { /* Octal? */
  273. index = (USHORT)atoi(&str[2]);
  274. index = (USHORT)((index/10)*8 + (index%8));
  275. } else {
  276. index = (USHORT)atoi(str);
  277. }
  278. /* Get character name. */
  279. (void)Get_Token(t1->ff, str, len);
  280. codes[ENC_MSWINDOWS] = index;
  281. codes[ENC_UNICODE] = index;
  282. if (index<256) {
  283. codes[ENC_STANDARD] = index;
  284. codes[ENC_MACCODES] = index;
  285. } else {
  286. codes[ENC_STANDARD] = NOTDEFCODE;
  287. codes[ENC_MACCODES] = NOTDEFCODE;
  288. }
  289. if ((glyph_name = Strdup(&str[1]))!=NULL)
  290. SetEncodingEntry(t1->t1m.encoding, i,
  291. glyph_name,
  292. ENC_MAXCODES,
  293. codes);
  294. else {
  295. status = NOMEM;
  296. break;
  297. }
  298. (void)Get_Token(t1->ff, str, len); /* Pop "dup" */
  299. (void)Get_Token(t1->ff, str, len); /* Pop "put" or comment. */
  300. if (str[0]=='%') {
  301. (void)GetNewLine(t1->ff, str, len);
  302. (void)Get_Token(t1->ff, str, len); /* Pop "put". */
  303. }
  304. if (strcmp(str, PS_DUP))
  305. break;
  306. }
  307. t1->t1m.encSize = (USHORT)(i+1);
  308. /* Rehash the table. */
  309. RehashEncodingTable(t1->t1m.encoding, t1->t1m.encSize);
  310. }
  311. }
  312. }
  313. return status;
  314. }
  315. /***
  316. ** Function: ReadArray
  317. **
  318. ** Description:
  319. ** Read an array.
  320. ***/
  321. static errcode ReadArray(struct T1Handle *t1,
  322. char *str,
  323. const USHORT len,
  324. funit *array,
  325. USHORT maxarr,
  326. USHORT *cnt)
  327. {
  328. errcode status;
  329. char *nxt;
  330. if (GetSeq(t1->ff, str, len)) {
  331. (*cnt)=0;
  332. do {
  333. array[(*cnt)] = (funit)(((StrToFix(str, &nxt, 4L)+8002)>>2) - 2000);
  334. if (nxt==str)
  335. break;
  336. str = nxt;
  337. } while (++(*cnt)<maxarr);
  338. status=SUCCESS;
  339. } else {
  340. SetError(status = BADINPUTFILE);
  341. }
  342. return status;
  343. }
  344. /***
  345. ** Function: ReadFontSubrs
  346. **
  347. ** Description:
  348. ** Read the command sequence "/Subrs %d array dup %d %d RD %x ND ...",
  349. ** decode and decrypt the subroutines and store them in the T1
  350. ** handle.
  351. ***/
  352. static errcode ReadFontSubrs(struct T1Handle *t1,
  353. char *str, const USHORT len)
  354. {
  355. errcode status = SUCCESS;
  356. USHORT index,i,j;
  357. USHORT count = 0;
  358. USHORT r;
  359. short b;
  360. /* Get the number of subroutines. */
  361. if (Get_Token(t1->ff, str, len)==NULL) {
  362. SetError(status = BADINPUTFILE);
  363. } else {
  364. count = (USHORT)atoi(str);
  365. /* Get the "array" keyword". */
  366. if ((Get_Token(t1->ff, str, len)==NULL) || strcmp(str, PS_ARRAY)) {
  367. SetError(status = BADINPUTFILE);
  368. } else {
  369. if ((t1->subrs = Malloc((USHORT)sizeof(struct Subrs)*count))==NULL) {
  370. SetError(status = NOMEM);
  371. } else {
  372. memset(t1->subrs, '\0', sizeof(struct Subrs)*count);
  373. t1->numsubrs = count;
  374. for (i=0; i<count; i++) {
  375. if (Get_Token(t1->ff, str, len)==NULL) { /* Get "dup" */
  376. SetError(status = BADINPUTFILE);
  377. break;
  378. }
  379. if (strcmp(str, PS_DUP)) {
  380. SetError(status = BADT1HEADER);
  381. break;
  382. }
  383. if (Get_Token(t1->ff, str, len)==NULL) { /* Get Subr index. */
  384. SetError(status=BADINPUTFILE);
  385. break;
  386. }
  387. index = (USHORT)atoi(str);
  388. if (t1->subrs[index].code) {
  389. LogError(MSG_WARNING, MSG_DBLIDX, NULL);
  390. Free(t1->subrs[index].code);
  391. }
  392. if (Get_Token(t1->ff, str, len)==NULL) { /* Get length. */
  393. SetError(status=BADINPUTFILE);
  394. break;
  395. }
  396. t1->subrs[index].len = (USHORT)(atoi(str) - t1->leniv);
  397. if ((t1->subrs[index].code
  398. = Malloc(t1->subrs[index].len))==NULL) {
  399. SetError(status = NOMEM);
  400. break;
  401. }
  402. if (Get_Token(t1->ff, str, len)==NULL) { /* Get RD + space */
  403. SetError(status=BADINPUTFILE);
  404. break;
  405. }
  406. /* Skip space. */
  407. (void)GetByte(t1->ff);
  408. /* Skip lenIV */
  409. r = 4330;
  410. for (j=0; j<t1->leniv; j++) {
  411. b=GetByte(t1->ff);
  412. (void)Decrypt(&r, (UBYTE)b);
  413. }
  414. if (status!=SUCCESS)
  415. break;
  416. /* Get code. */
  417. for (j=0; j<t1->subrs[index].len; j++) {
  418. b=GetByte(t1->ff);
  419. t1->subrs[index].code[j] = Decrypt(&r, (UBYTE)b);
  420. }
  421. if (status!=SUCCESS)
  422. break;
  423. if (Get_Token(t1->ff, str, len)==NULL) { /* Get ND */
  424. SetError(status=BADINPUTFILE);
  425. break;
  426. }
  427. /* Check for non-ATM compatible equivalent to 'ND' */
  428. if (!strcmp(str, PS_NOACCESS)) {
  429. (void)Get_Token(t1->ff, str, len);
  430. }
  431. }
  432. }
  433. }
  434. }
  435. return status;
  436. }
  437. /***** FUNCTIONS */
  438. /***
  439. ** Function: FlushWorkspace
  440. **
  441. ** Description:
  442. ** Free the resources allocated for the T1 handle.
  443. ***/
  444. void FlushWorkspace(struct T1Handle *t1)
  445. {
  446. USHORT i;
  447. /* Free /Subrs */
  448. if (t1->subrs) {
  449. for (i=0; i<t1->numsubrs; i++) {
  450. Free(t1->subrs[i].code);
  451. }
  452. Free(t1->subrs);
  453. }
  454. t1->subrs = NULL;
  455. }
  456. /***
  457. ** Function: CleanUpT1
  458. **
  459. ** Description:
  460. ** Free the resources allocated for the T1 handle.
  461. ***/
  462. errcode CleanUpT1(struct T1Handle *t1)
  463. {
  464. errcode status = SUCCESS;
  465. AlignmentControl *align;
  466. Composite *next;
  467. Blues *blues;
  468. USHORT i;
  469. if (t1) {
  470. /* Free the PSState */
  471. if (t1->ps)
  472. FreePSState(t1->ps);
  473. /* Free /Subrs */
  474. if (t1->subrs) {
  475. for (i=0; i<t1->numsubrs; i++) {
  476. Free(t1->subrs[i].code);
  477. }
  478. Free(t1->subrs);
  479. }
  480. /* Clean up font file reader. */
  481. status = FRCleanUp(t1->ff);
  482. /* Clean up font matrix. */
  483. if (t1->t1m.fmatrix)
  484. Free(t1->t1m.fmatrix);
  485. /* Clean up seac. */
  486. while (t1->t1m.used_seac) {
  487. next = t1->t1m.used_seac->next;
  488. FreeT1Composite(t1->t1m.used_seac);
  489. t1->t1m.used_seac = next;
  490. }
  491. while (t1->t1m.seac) {
  492. next = t1->t1m.seac->next;
  493. FreeT1Composite(t1->t1m.seac);
  494. t1->t1m.seac = next;
  495. }
  496. /* Clean up stdenc. */
  497. for (i=0; i<256; i++) {
  498. if (t1->stdenc[i].code) {
  499. Free(t1->stdenc[i].code);
  500. t1->stdenc[i].code = NULL;
  501. t1->stdenc[i].len = 0;
  502. }
  503. }
  504. /* Clean up encoding table. */
  505. if (t1->t1m.encoding)
  506. FreeEncoding(t1->t1m.encoding, t1->t1m.encSize);
  507. /* Free strings */
  508. if (t1->t1m.date)
  509. Free(t1->t1m.date);
  510. if (t1->t1m.copyright)
  511. Free(t1->t1m.copyright);
  512. if (t1->t1m.name)
  513. Free(t1->t1m.name);
  514. if (t1->t1m.id)
  515. Free(t1->t1m.id);
  516. if (t1->t1m.notice)
  517. Free(t1->t1m.notice);
  518. if (t1->t1m.fullname)
  519. Free(t1->t1m.fullname);
  520. if (t1->t1m.weight)
  521. Free(t1->t1m.weight);
  522. if (t1->t1m.family)
  523. Free(t1->t1m.family);
  524. if (t1->t1m.widths)
  525. Free(t1->t1m.widths);
  526. if (t1->t1m.kerns)
  527. Free(t1->t1m.kerns);
  528. if (t1->t1m.stems.vwidths)
  529. Free(t1->t1m.stems.vwidths);
  530. if (t1->t1m.stems.hwidths)
  531. Free(t1->t1m.stems.hwidths);
  532. blues = &(t1->t1m.blues);
  533. align = &(t1->t1m.blues.align);
  534. for (i=0; i<blues->blue_cnt/2; i++) {
  535. Free(align->top[i].pos);
  536. }
  537. for (i=0; i<blues->oblue_cnt/2; i++) {
  538. Free(align->bottom[i].pos);
  539. }
  540. /* Free handle. */
  541. Free(t1);
  542. }
  543. return status;
  544. }
  545. /***
  546. ** Function: InitT1Input
  547. **
  548. ** Description:
  549. ** Allocate and initiate a handle for a T1 font file, including
  550. ** extracting data from the font prolog that is needed to
  551. ** read the glyphs, such as /FontMatrix, /Subrs and /lenIV.
  552. ***/
  553. errcode InitT1Input(const struct T1Arg *arg,
  554. struct T1Handle **t1ref,
  555. struct T1Metrics **t1mref,
  556. const short (*check)(const char *,
  557. const char *,
  558. const char *))
  559. {
  560. errcode status = SUCCESS;
  561. struct T1Handle *t1;
  562. struct PSState *ps;
  563. Blues *blues;
  564. boolean hybrid = FALSE;
  565. struct T1Metrics *t1m = NULL;
  566. char str[BUFLEN];
  567. USHORT i;
  568. /* Allocate the handle. */
  569. if (((*t1ref)=Malloc((USHORT)sizeof(struct T1Handle)))==NULL ||
  570. (ps = AllocPSState())==NULL) {
  571. if ((*t1ref))
  572. Free((*t1ref));
  573. SetError(status = NOMEM);
  574. } else {
  575. /* Initiate the T1 record. */
  576. t1 = (*t1ref);
  577. t1m = &t1->t1m;
  578. (*t1mref) = t1m;
  579. blues = GetBlues(t1m);
  580. memset(t1, '\0', sizeof(*t1));
  581. t1->ps = ps;
  582. t1->leniv = 4;
  583. t1m->upem = arg->upem;
  584. t1m->defstdhw = 70;
  585. t1m->defstdvw = 80;
  586. blues->blueScale = 39; /* Should really be 39.625 */
  587. blues->blueFuzz = 1;
  588. blues->blueShift = 7 * F8D8;
  589. blues->align.cvt = 3;
  590. t1m->stems.storage = 15;
  591. /* Initiate font file reader. */
  592. if ((status=FRInit(arg->name, pfb_file, &t1->ff))==SUCCESS) {
  593. /* Read /FontMatrix and /Subrs. */
  594. while (status==SUCCESS) {
  595. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  596. SetError(status=BADINPUTFILE);
  597. /**** /ForceBold true def ****/
  598. } else if (!strcmp(str, PS_FORCEBOLD)) {
  599. if (Get_Token(t1->ff, str, BUFLEN)) {
  600. if (!strcmp(str, "true") || !strcmp(str, "True"))
  601. t1m->forcebold = TRUE;
  602. else
  603. t1m->forcebold = FALSE;
  604. status = SUCCESS;
  605. } else {
  606. status = BADINPUTFILE;
  607. }
  608. /**** /BlueFuzz 1 def ****/
  609. } else if (!strcmp(str, PS_BLUEFUZZ)) {
  610. if (Get_Token(t1->ff, str, BUFLEN)) {
  611. blues->blueFuzz = (UBYTE)atoi(str);
  612. status = SUCCESS;
  613. } else {
  614. status = BADINPUTFILE;
  615. }
  616. /**** /BlueScale 0.043625 def ****/
  617. } else if (!strcmp(str, PS_BLUESCALE)) {
  618. if (Get_Token(t1->ff, str, BUFLEN)) {
  619. str[5] = '\0';
  620. blues->blueScale = (UBYTE)atoi(&str[2]);
  621. status = SUCCESS;
  622. } else {
  623. status = BADINPUTFILE;
  624. }
  625. /**** /BlueShift 7 def ****/
  626. } else if (!strcmp(str, PS_BLUESHIFT)) {
  627. if (Get_Token(t1->ff, str, BUFLEN)) {
  628. blues->blueShift = (short)StrToFix(str, NULL, (long)F8D8);
  629. status = SUCCESS;
  630. } else {
  631. status = BADINPUTFILE;
  632. }
  633. /**** /Encoding StandardEncodind def ****/
  634. } else if (!strcmp(str, PS_ENCODING)) {
  635. status = ReadEncodingArray(t1, str, BUFLEN);
  636. /**** /StdVW [118] def ****/
  637. } else if (!strcmp(str, PS_STDVW)) {
  638. USHORT dummy;
  639. status = ReadArray(t1, str, BUFLEN,
  640. &t1m->stdvw, ONE, &dummy);
  641. /**** /StdHW [118] def ****/
  642. } else if (!strcmp(str, PS_STDHW)) {
  643. USHORT dummy;
  644. status = ReadArray(t1, str, BUFLEN,
  645. &t1m->stdhw, ONE, &dummy);
  646. /**** /StemSnapV [118 120] def ****/
  647. } else if (!strcmp(str, PS_SNAPV)) {
  648. status = ReadArray(t1, str, BUFLEN,
  649. &t1m->stemsnapv[0],
  650. MAXSNAP, &t1m->snapv_cnt);
  651. /* Add space for the snap enties in the CV table. */
  652. if (status==SUCCESS)
  653. blues->align.cvt = (USHORT)(blues->align.cvt +
  654. t1m->snapv_cnt);
  655. /**** /StemSnapH [118 120] def ****/
  656. } else if (!strcmp(str, PS_SNAPH)) {
  657. status = ReadArray(t1, str, BUFLEN,
  658. &t1m->stemsnaph[0],
  659. MAXSNAP, &t1m->snaph_cnt);
  660. /* Add space for the snap enties in the CV table. */
  661. if (status==SUCCESS)
  662. blues->align.cvt = (USHORT)(blues->align.cvt +
  663. t1m->snaph_cnt);
  664. /**** /BlueValues [-15 0] def ****/
  665. } else if (!strcmp(str, PS_BLUEVALUES)) {
  666. status = ReadArray(t1, str, BUFLEN,
  667. &(blues->bluevalues[0]),
  668. MAXBLUE, &(blues->blue_cnt));
  669. if (blues->blue_cnt%2)
  670. SetError(status = BADINPUTFILE);
  671. /**** /OtherBlues [-15 0] def ****/
  672. } else if (!strcmp(str, PS_OTHERBLUES)) {
  673. status = ReadArray(t1, str, BUFLEN,
  674. &(blues->otherblues[0]),
  675. MAXBLUE, &(blues->oblue_cnt));
  676. if (blues->oblue_cnt%2)
  677. SetError(status = BADINPUTFILE);
  678. /**** /FamilyBlues [-15 0] def ****/
  679. } else if (!strcmp(str, PS_FAMILYBLUES)) {
  680. status = ReadArray(t1, str, BUFLEN,
  681. &(blues->familyblues[0]),
  682. MAXBLUE, &(blues->fblue_cnt));
  683. /**** /FamilyOtherBlues [-15 0] def ****/
  684. } else if (!strcmp(str, PS_FAMILYOTHERBLUES)) {
  685. status = ReadArray(t1, str, BUFLEN,
  686. &(blues->familyotherblues[0]),
  687. MAXBLUE, &(blues->foblue_cnt));
  688. /**** /CharString ... */
  689. } else if (!strcmp(str, PS_CHARSTRINGS)) {
  690. break;
  691. /**** /FontMatrix [0 0.001 0 0.001 0] def ****/
  692. } else if (GetFontMatrix(t1m)==NULL &&
  693. !strcmp(str, PS_FONTMATRIX)) {
  694. status = ReadFontMatrix(t1, str, BUFLEN);
  695. } else if (!strcmp(str, PS_SUBRS)) {
  696. /* Discard prior lores /Subrs. */
  697. FlushWorkspace(t1);
  698. /* Read new subrs. */
  699. status = ReadFontSubrs(t1,str, BUFLEN);
  700. /**** /lenIV 4 def ****/
  701. } else if (!strcmp(str, PS_LENIV)) {
  702. if (Get_Token(t1->ff, str, BUFLEN)) {
  703. t1->leniv = (USHORT)atoi(str);
  704. status = SUCCESS;
  705. } else {
  706. status = BADINPUTFILE;
  707. }
  708. } else if (t1m->date==NULL && !strcmp(str, PS_DATE)) {
  709. if ((GetNewLine(t1->ff, str, BUFLEN))==NULL) {
  710. SetError(status = BADINPUTFILE);
  711. } else if ((t1m->date=Strdup(str))==NULL) {
  712. SetError(status = NOMEM);
  713. }
  714. } else if (t1m->copyright==NULL &&
  715. !strcmp(str, PS_COPYRIGHT)) {
  716. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  717. SetError(status = BADINPUTFILE);
  718. } else if ((t1m->copyright=Strdup(str))==NULL) {
  719. SetError(status = NOMEM);
  720. }
  721. } else if (t1m->name==NULL && !strcmp(str, PS_NAME)) {
  722. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  723. SetError(status = BADINPUTFILE);
  724. } else if ((t1m->name=Strdup(&str[1]))==NULL) {
  725. SetError(status = NOMEM);
  726. }
  727. } else if (t1m->id==NULL && !strcmp(str, PS_ID)) {
  728. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  729. SetError(status = BADINPUTFILE);
  730. } else if ((t1m->id=Strdup(str))==NULL) {
  731. SetError(status = NOMEM);
  732. }
  733. } else if (t1m->version.ver==0 && !strcmp(str, PS_VERSION)) {
  734. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  735. SetError(status = BADINPUTFILE);
  736. } else {
  737. t1m->version.ver = (USHORT)atoi(str);
  738. if (strchr(str, '.'))
  739. t1m->version.rev = (USHORT)atoi(strchr(str, '.')+1);
  740. else
  741. t1m->version.rev = 0;
  742. }
  743. } else if (t1m->notice==NULL && !strcmp(str, PS_NOTICE)) {
  744. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  745. SetError(status = BADINPUTFILE);
  746. } else if ((t1m->notice=Strdup(str))==NULL) {
  747. SetError(status = NOMEM);
  748. }
  749. } else if (t1m->fullname==NULL && !strcmp(str, PS_FULLNAME)) {
  750. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  751. SetError(status = BADINPUTFILE);
  752. } else if ((t1m->fullname=Strdup(str))==NULL) {
  753. SetError(status = NOMEM);
  754. }
  755. } else if (t1m->family==NULL && !strcmp(str, PS_FAMILY)) {
  756. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  757. SetError(status = BADINPUTFILE);
  758. } else if ((t1m->family=Strdup(str))==NULL) {
  759. SetError(status = NOMEM);
  760. }
  761. } else if (t1m->weight==NULL && !strcmp(str, PS_WEIGHT)) {
  762. if ((GetSeq(t1->ff, str, BUFLEN))==NULL) {
  763. SetError(status = BADINPUTFILE);
  764. } else if ((t1m->weight=Strdup(str))==NULL) {
  765. SetError(status = NOMEM);
  766. }
  767. } else if (t1m->angle==0 && !strcmp(str, PS_ANGLE)) {
  768. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  769. SetError(status = BADINPUTFILE);
  770. } else
  771. t1m->angle = StrToFix(str, NULL, F16D16BASE);
  772. } else if (t1m->underline==0 && !strcmp(str, PS_UNDERLINE)) {
  773. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  774. SetError(status = BADINPUTFILE);
  775. } else
  776. t1m->underline = (funit)StrToFix(str, NULL, 1L);
  777. } else if (t1m->uthick==0 && !strcmp(str, PS_UTHICK)) {
  778. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  779. SetError(status = BADINPUTFILE);
  780. } else
  781. t1m->uthick = (funit)StrToFix(str, NULL, 1L);
  782. } else if (!strcmp(str, PS_ISFIXED)) {
  783. if ((Get_Token(t1->ff, str, BUFLEN))==NULL) {
  784. SetError(status = BADINPUTFILE);
  785. } else
  786. if (!strcmp(str, "true") ||
  787. !strcmp(str, "True") ||
  788. !strcmp(str, "TRUE"))
  789. t1m->fixedPitch = TRUE;
  790. } else if (!strcmp(str, PS_HYBRID)) {
  791. hybrid = TRUE;
  792. }
  793. }
  794. /* Change the baseline zone into an OtherBlues[] zone. */
  795. if (blues->blue_cnt) {
  796. blues->otherblues[blues->oblue_cnt++] = blues->bluevalues[0];
  797. blues->otherblues[blues->oblue_cnt++] = blues->bluevalues[1];
  798. for (i=2; i<blues->blue_cnt; i++)
  799. blues->bluevalues[i-2] = blues->bluevalues[i];
  800. blues->blue_cnt -= 2;
  801. }
  802. if (blues->fblue_cnt) {
  803. blues->familyotherblues[blues->foblue_cnt++]
  804. = blues->familyblues[0];
  805. blues->familyotherblues[blues->foblue_cnt++]
  806. = blues->familyblues[1];
  807. for (i=2; i<blues->fblue_cnt; i++)
  808. blues->familyblues[i-2] = blues->familyblues[i];
  809. blues->fblue_cnt -= 2;
  810. }
  811. /* Allocate the space for the blue buckets. */
  812. for (i=0; i<blues->blue_cnt; i+=2) {
  813. USHORT size = (USHORT)((ABS(blues->bluevalues[i+1] -
  814. blues->bluevalues[i]) +
  815. 1 + 2*blues->blueFuzz)*
  816. (USHORT)sizeof(struct CVTPos));
  817. if ((blues->align.top[i/2].pos = Malloc(size))==NULL) {
  818. SetError(status = NOMEM);
  819. break;
  820. }
  821. /* Make sure that first value is larger than second value. */
  822. if (blues->bluevalues[i] > blues->bluevalues[i+1]) {
  823. LogError(MSG_WARNING, MSG_INVBLUES, NULL);
  824. SWAPINT(blues->bluevalues[i], blues->bluevalues[i+1]);
  825. }
  826. }
  827. for (i=0; i<blues->oblue_cnt; i+=2) {
  828. USHORT size = (USHORT)((ABS(blues->otherblues[i+1] -
  829. blues->otherblues[i]) +
  830. 1 + 2*blues->blueFuzz)*
  831. (USHORT)sizeof(struct CVTPos));
  832. if ((blues->align.bottom[i/2].pos = Malloc(size))==NULL) {
  833. SetError(status = NOMEM);
  834. break;
  835. }
  836. /* Make sure that first value is larger than second value. */
  837. if (blues->otherblues[i] > blues->otherblues[i+1]) {
  838. LogError(MSG_WARNING, MSG_INVBLUES, NULL);
  839. SWAPINT(blues->otherblues[i], blues->otherblues[i+1]);
  840. }
  841. }
  842. /* Advance to the first glyph. */
  843. if (status==SUCCESS) {
  844. while (Get_Token(t1->ff, str, BUFLEN) &&
  845. strcmp(str, PS_BEGIN));
  846. if (strcmp(str, PS_BEGIN)) {
  847. SetError(status = BADT1HEADER);
  848. }
  849. /* Skip lores chars if hybrid font. */
  850. if (status==SUCCESS && hybrid) {
  851. USHORT count;
  852. /* Skip Charstring dictionary. */
  853. do {
  854. /* Glyph name, or end. */
  855. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  856. SetError(status = BADINPUTFILE);
  857. break;
  858. }
  859. if (!strcmp(str, PS_END))
  860. break;
  861. /* Charstring length. */
  862. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  863. SetError(status = BADINPUTFILE);
  864. break;
  865. }
  866. count = (USHORT)(atoi(str)+1);
  867. /* Delimiter. */
  868. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  869. SetError(status = BADINPUTFILE);
  870. break;
  871. }
  872. /* Charstring */
  873. for (i=0; i<count; i++)
  874. (void)GetByte(t1->ff);
  875. /* Delimiter */
  876. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  877. SetError(status = BADINPUTFILE);
  878. break;
  879. }
  880. } while (status==SUCCESS);
  881. /* Skip to the beginning of next charstring. */
  882. while (Get_Token(t1->ff, str, BUFLEN) &&
  883. strcmp(str, PS_BEGIN));
  884. if (strcmp(str, PS_BEGIN)) {
  885. SetError(status = BADT1HYBRID);
  886. }
  887. }
  888. }
  889. }
  890. }
  891. if ((status==SUCCESS) && t1m && check(t1m->name,
  892. t1m->copyright,
  893. t1m->notice)!=SUCCESS)
  894. status = NOCOPYRIGHT;
  895. return status;
  896. }
  897. /***
  898. ** Function: GetT1Glyph
  899. **
  900. ** Description:
  901. ** The current file position of the T1 font file must be
  902. ** at the begining of an entry in the /CharStrings dictionary.
  903. ** The function will decode the font commands, parse them, and
  904. ** finally build a representation of the glyph.
  905. ***/
  906. errcode GetT1Glyph(struct T1Handle *t1,
  907. struct T1Glyph *glyph,
  908. const struct GlyphFilter *filter)
  909. {
  910. errcode status = SUCCESS;
  911. /* struct encoding *enc; */
  912. char str[BUFLEN];
  913. UBYTE *code;
  914. USHORT len;
  915. USHORT i;
  916. USHORT r = 4330;
  917. short b;
  918. /* Get glyph name or end. */
  919. if (Get_Token(t1->ff, str, BUFLEN)==NULL) {
  920. SetError(status = BADINPUTFILE);
  921. } else if (!strcmp(str, PS_END)) {
  922. status = DONE;
  923. } else if (str[0]!='/') {
  924. SetError(status = BADCHARSTRING);
  925. } else {
  926. if ((glyph->name = Strdup(&str[1]))==NULL) {
  927. SetError(status = NOMEM);
  928. } else {
  929. /* Get length of charstring. */
  930. (void)Get_Token(t1->ff, str, BUFLEN);
  931. len = (USHORT)atoi(str);
  932. /* Get RD + space */
  933. (void)Get_Token(t1->ff, str, BUFLEN);
  934. (void)GetByte(t1->ff);
  935. /* Get commands. */
  936. if (len<BUFLEN)
  937. code = (UBYTE *)str;
  938. else
  939. if ((code = Malloc(len*sizeof(UBYTE)))==NULL) {
  940. SetError(status = NOMEM);
  941. }
  942. if (code) {
  943. for (i=0; i<len; i++) {
  944. b = GetByte(t1->ff);
  945. code[i] = (UBYTE)Decrypt(&r, (UBYTE)b);
  946. }
  947. /* Parse commands. */
  948. if (status==SUCCESS) {
  949. if (t1->t1m.encoding!=NULL ||
  950. UseGlyph(filter, t1->t1m.seac, glyph->name)) {
  951. InitPS(t1->ps);
  952. status = ParseCharString(glyph,
  953. &t1->t1m.seac,
  954. t1->ps,
  955. t1->subrs,
  956. &code[t1->leniv],
  957. (USHORT)(len-t1->leniv));
  958. /* Skip normal conversion for the ".notdef" glyph. */
  959. if (!strcmp(glyph->name, ".notdef"))
  960. status = SKIP;
  961. } else {
  962. status = SKIP;
  963. /***
  964. Two approaches are implemented for the management of
  965. composite glyphs:
  966. 1) It is up to the client to specify a GlyphFilter such
  967. that all 'seac' characters has their dependent base and
  968. accent character in the filter as well.
  969. 2) The converter manages a list of the dependent characters,
  970. which are converted when found.
  971. Approach 2) will typically cause the converter to use more
  972. memory than what is available in the small memory model,
  973. which is why the default is to disabled it.
  974. ***/
  975. #if 0
  976. /* Record StandardEncoding glyphs, for 'seac' */
  977. if ((enc = LookupPSName(t1->t1m.encoding,
  978. t1->t1m.encSize,
  979. glyph->name)) &&
  980. (i = LookupCharCode(enc, ENC_STANDARD))!=0) {
  981. if ((t1->stdenc[i].code
  982. = Malloc(len-t1->leniv))==NULL) {
  983. SetError(status = NOMEM);
  984. } else {
  985. memcpy(t1->stdenc[i].code,
  986. &code[t1->leniv],
  987. sizeof(UBYTE) * (len - t1->leniv));
  988. t1->stdenc[i].len = len - t1->leniv;
  989. }
  990. }
  991. #endif
  992. }
  993. if (code!=(UBYTE *)str)
  994. Free(code);
  995. /* Get ND */
  996. (void)Get_Token(t1->ff, str, BUFLEN);
  997. }
  998. }
  999. }
  1000. }
  1001. return status;
  1002. }
  1003. /***
  1004. ** Function: FreeT1Glyph
  1005. **
  1006. ** Description:
  1007. ** This function frees the memory used to represent
  1008. ** a glyph that has been translated.
  1009. ***/
  1010. void FreeT1Glyph(T1Glyph *glyph)
  1011. {
  1012. Flex *flex;
  1013. Stem *stem;
  1014. Stem3 *stem3;
  1015. if (glyph->name)
  1016. Free(glyph->name);
  1017. while (glyph->hints.vstems) {
  1018. stem = glyph->hints.vstems->next;
  1019. Free(glyph->hints.vstems);
  1020. glyph->hints.vstems = stem;
  1021. }
  1022. while (glyph->hints.hstems) {
  1023. stem = glyph->hints.hstems->next;
  1024. Free(glyph->hints.hstems);
  1025. glyph->hints.hstems = stem;
  1026. }
  1027. while (glyph->hints.vstems3) {
  1028. stem3 = glyph->hints.vstems3->next;
  1029. Free(glyph->hints.vstems3);
  1030. glyph->hints.vstems3 = stem3;
  1031. }
  1032. while (glyph->hints.hstems3) {
  1033. stem3 = glyph->hints.hstems3->next;
  1034. Free(glyph->hints.hstems3);
  1035. glyph->hints.hstems3 = stem3;
  1036. }
  1037. while (glyph->hints.flex) {
  1038. flex = glyph->hints.flex->next;
  1039. Free(glyph->hints.flex);
  1040. glyph->hints.flex = flex;
  1041. }
  1042. while (glyph->paths) {
  1043. Outline *path = glyph->paths;
  1044. glyph->paths = path->next;
  1045. if (path->count) {
  1046. Free(path->onoff);
  1047. Free(path->pts);
  1048. }
  1049. Free(path);
  1050. }
  1051. memset((void *)glyph, '\0', sizeof(T1Glyph));
  1052. }
  1053. /***
  1054. ** Function: GetT1Composite
  1055. **
  1056. ** Description:
  1057. ** This function unlinks the first composite glyph
  1058. ** from the list of recorded composite glyphs, which
  1059. ** is returned to the caller.
  1060. ***/
  1061. struct Composite *GetT1Composite(struct T1Handle *t1)
  1062. {
  1063. struct Composite *comp;
  1064. comp = t1->t1m.seac;
  1065. if (comp) {
  1066. t1->t1m.seac = comp->next;
  1067. comp->next = t1->t1m.used_seac;
  1068. t1->t1m.used_seac = comp;
  1069. }
  1070. return comp;
  1071. }
  1072. /***
  1073. ** Function: GetT1BaseGlyph
  1074. **
  1075. ** Description:
  1076. ** This function parses the charstring code associated to the
  1077. ** base character of a composite character, if that glyph
  1078. ** is not already converted.
  1079. ***/
  1080. errcode GetT1BaseGlyph(struct T1Handle *t1,
  1081. const struct Composite *comp,
  1082. struct T1Glyph *glyph)
  1083. {
  1084. struct encoding *enc;
  1085. struct Subrs *subr;
  1086. errcode status = SUCCESS;
  1087. if ((enc = LookupPSName(t1->t1m.encoding,
  1088. t1->t1m.encSize,
  1089. comp->bchar))==NULL) {
  1090. LogError(MSG_WARNING, MSG_BADENC, comp->bchar);
  1091. return SKIP;
  1092. }
  1093. subr = &t1->stdenc[LookupCharCode(enc, ENC_STANDARD)];
  1094. if (subr->len==0) {
  1095. status = SKIP; /* Missing or already done. */
  1096. } else {
  1097. InitPS(t1->ps);
  1098. if ((glyph->name = Strdup((char*)comp->achar))==NULL) {
  1099. SetError(status = NOMEM);
  1100. } else {
  1101. status = ParseCharString(glyph,
  1102. &t1->t1m.seac,
  1103. t1->ps,
  1104. t1->subrs,
  1105. subr->code,
  1106. subr->len);
  1107. }
  1108. Free(subr->code);
  1109. subr->code = NULL;
  1110. subr->len = 0;
  1111. }
  1112. return status;
  1113. }
  1114. /***
  1115. ** Function: GetT1AccentGlyph
  1116. **
  1117. ** Description:
  1118. ** This function parses the charstring code associated to the
  1119. ** accent character of a composite character, if that glyph
  1120. ** is not already converted.
  1121. ***/
  1122. errcode GetT1AccentGlyph(struct T1Handle *t1,
  1123. const struct Composite *comp,
  1124. struct T1Glyph *glyph)
  1125. {
  1126. struct encoding *enc;
  1127. struct Subrs *subr;
  1128. errcode status = SUCCESS;
  1129. if ((enc = LookupPSName(t1->t1m.encoding,
  1130. t1->t1m.encSize,
  1131. comp->achar))==NULL) {
  1132. LogError(MSG_WARNING, MSG_BADENC, comp->achar);
  1133. return SKIP;
  1134. }
  1135. subr = &t1->stdenc[LookupCharCode(enc, ENC_STANDARD)];
  1136. if (subr->len==0) {
  1137. status = SKIP; /* Missing or already done. */
  1138. } else {
  1139. InitPS(t1->ps);
  1140. if ((glyph->name = Strdup((char *)comp->achar))==NULL) {
  1141. SetError(status = NOMEM);
  1142. } else {
  1143. status = ParseCharString(glyph,
  1144. &t1->t1m.seac,
  1145. t1->ps,
  1146. t1->subrs,
  1147. subr->code,
  1148. subr->len);
  1149. }
  1150. Free(subr->code);
  1151. subr->code = NULL;
  1152. subr->len = 0;
  1153. }
  1154. return status;
  1155. }
  1156. /***
  1157. ** Function: ReadOtherMetrics
  1158. **
  1159. ** Description:
  1160. ** Return font level information about the T1 font (mostly
  1161. ** metrics).
  1162. ***/
  1163. errcode ReadOtherMetrics(struct T1Metrics *t1m,
  1164. const char *metrics)
  1165. {
  1166. errcode status = SUCCESS;
  1167. if ((status = ReadFontMetrics(metrics, t1m))==NOMETRICS) {
  1168. t1m->flags = DEFAULTMETRICS;
  1169. status = SUCCESS;
  1170. } else {
  1171. t1m->flags = USEMETRICS;
  1172. }
  1173. return status;
  1174. }