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.

847 lines
26 KiB

  1. /***
  2. **
  3. ** Module: CharStr
  4. **
  5. ** Description:
  6. ** This is a module of the T1 to TT font converter. The module
  7. ** contain one function that interprets the commands in a T1
  8. ** CharString and builds a representation of the glyph for the
  9. ** it.
  10. **
  11. ** Author: Michael Jansson
  12. **
  13. ** Created: 5/26/93
  14. **
  15. ***/
  16. /**** INCLUDES */
  17. /* General types and definitions. */
  18. #include <string.h>
  19. /* Special types and definitions. */
  20. #include "titott.h"
  21. #include "types.h"
  22. #include "metrics.h"
  23. #include "encoding.h"
  24. #include "safemem.h"
  25. #include "t1msg.h"
  26. /* Module dependent types and prototypes. */
  27. #include "charstr.h"
  28. /***** CONSTANTS */
  29. #define MAXSTACK 24
  30. #define BUFMARGIN 256
  31. /* Known OtherSubr entries. */
  32. #define HINT_END_FLEX 0
  33. #define HINT_START_FLEX 1
  34. #define HINT_MID_FLEX 2
  35. #define HINT_REPLACEMENT 3
  36. #define PSOP_HSTEM 1
  37. #define PSOP_VSTEM 3
  38. #define PSOP_VMOVETO 4
  39. #define PSOP_RLINETO 5
  40. #define PSOP_HLINETO 6
  41. #define PSOP_VLINETO 7
  42. #define PSOP_RRCURVETO 8
  43. #define PSOP_CLOSEPATH 9
  44. #define PSOP_CALLSUBR 10
  45. #define PSOP_RETURN 11
  46. #define PSOP_ESCAPE 12
  47. # define PSOP_DOTSECTION 0
  48. # define PSOP_VSTEM3 1
  49. # define PSOP_HSTEM3 2
  50. # define PSOP_SEAC 6
  51. # define PSOP_SBW 7
  52. # define PSOP_DIV 12
  53. # define PSOP_CALLOTHERSUBR 16
  54. # define PSOP_POP 17
  55. # define PSOP_SETCURRENTPOINT 33
  56. #define PSOP_HSBW 13
  57. #define PSOP_ENDCHAR 14
  58. #define PSOP_RMOVETO 21
  59. #define PSOP_HMOVETO 22
  60. #define PSOP_VHCURVETO 30
  61. #define PSOP_HVCURVETO 31
  62. /***** LOCAL TYPES */
  63. /* Referenced types. */
  64. typedef struct PSState {
  65. long stack[MAXSTACK+2];
  66. Point *pts;
  67. ULONG *onoff;
  68. USHORT totpts;
  69. USHORT numpts;
  70. USHORT ptr;
  71. short hr;
  72. USHORT maxpts;
  73. USHORT flex;
  74. Point flexref;
  75. int calls;
  76. long otherargs[16];
  77. USHORT otherptr;
  78. } PSState;
  79. /***** MACROS */
  80. #define AddPoint(ps, px, py) {ps->pts[ps->numpts].x = px;\
  81. ps->pts[ps->numpts].y = py;\
  82. ps->numpts++;}
  83. #define CurrXPoint(ps) ps->pts[ps->numpts-1].x
  84. #define CurrYPoint(ps) ps->pts[ps->numpts-1].y
  85. #define PrevPoint(ps, index) ps->pts[ps->numpts-1-index]
  86. #define PushStack(v) ps->stack[(ps->ptr)++] = (v)
  87. #define PopStack() ps->stack[--(ps->ptr)]
  88. /***** STATIC FUNCTIONS */
  89. /***
  90. ** Function: AddCSpline
  91. **
  92. ** Description:
  93. ** Record a cubic spline.
  94. **
  95. ***/
  96. static void AddCSpline(PSState *ps,
  97. const funit x1, const funit y1,
  98. const funit x2, const funit y2,
  99. const funit x3, const funit y3)
  100. {
  101. SetOffPoint(ps->onoff, ps->numpts);
  102. AddPoint(ps, x1, y1);
  103. SetOffPoint(ps->onoff, ps->numpts);
  104. AddPoint(ps, x2, y2);
  105. SetOnPoint(ps->onoff, ps->numpts);
  106. AddPoint(ps, x3, y3);
  107. }
  108. /***
  109. ** Function: HintReplacement
  110. **
  111. ** Description:
  112. ** This function limits the range of points which are
  113. ** affected by stem hints. It may be invoked by the
  114. ** "dotsection" and the more general hint replacement
  115. ** mechanism found in T1 fonts.
  116. ***/
  117. static void HintReplacement(T1Glyph *glyph, const short hr)
  118. {
  119. Stem *stem;
  120. Stem3 *stem3;
  121. /* Dead stem hints?, e.g. replaced before ever used? */
  122. if (hr==ENDOFPATH) {
  123. for (stem=glyph->hints.hstems; stem; stem=stem->next)
  124. if (stem->i2==ENDOFPATH)
  125. stem->i2 = NORANGE;
  126. for (stem=glyph->hints.vstems; stem; stem=stem->next)
  127. if (stem->i2==ENDOFPATH)
  128. stem->i2 = NORANGE;
  129. for (stem3=glyph->hints.hstems3; stem3; stem3=stem3->next) {
  130. if (stem3->stem1.i2==ENDOFPATH) {
  131. stem3->stem1.i2 = NORANGE;
  132. stem3->stem2.i2 = NORANGE;
  133. stem3->stem3.i2 = NORANGE;
  134. }
  135. }
  136. for (stem3=glyph->hints.vstems3; stem3; stem3=stem3->next) {
  137. if (stem3->stem1.i2==ENDOFPATH) {
  138. stem3->stem1.i2 = NORANGE;
  139. stem3->stem2.i2 = NORANGE;
  140. stem3->stem3.i2 = NORANGE;
  141. }
  142. }
  143. /* Set the end-point for the stem hints that are replaced. */
  144. } else {
  145. for (stem=glyph->hints.hstems; stem; stem=stem->next)
  146. if (stem->i2==ENDOFPATH)
  147. stem->i2 = hr;
  148. for (stem=glyph->hints.vstems; stem; stem=stem->next)
  149. if (stem->i2==ENDOFPATH)
  150. stem->i2 = hr;
  151. for (stem3=glyph->hints.hstems3; stem3; stem3=stem3->next) {
  152. if (stem3->stem1.i2==ENDOFPATH) {
  153. stem3->stem1.i2 = hr;
  154. stem3->stem2.i2 = hr;
  155. stem3->stem3.i2 = hr;
  156. }
  157. }
  158. for (stem3=glyph->hints.vstems3; stem3; stem3=stem3->next) {
  159. if (stem3->stem1.i2==ENDOFPATH) {
  160. stem3->stem1.i2 = hr;
  161. stem3->stem2.i2 = hr;
  162. stem3->stem3.i2 = hr;
  163. }
  164. }
  165. }
  166. }
  167. /***
  168. ** Function: NewFlex
  169. **
  170. ** Description:
  171. ** This function records a new flex hint for
  172. ** the current glyph.
  173. ***/
  174. static Flex *NewFlex(const Point ref,
  175. const Point midpos,
  176. const Point startpos,
  177. const USHORT start,
  178. const USHORT mid,
  179. const USHORT end,
  180. const funit civ)
  181. {
  182. Flex *flex = NULL;
  183. if ((flex = Malloc(sizeof(Flex)))!=NULL) {
  184. flex->civ = civ;
  185. flex->pos = ref;
  186. flex->midpos = midpos;
  187. flex->startpos = startpos;
  188. flex->start = start;
  189. flex->mid = mid;
  190. flex->end = end;
  191. }
  192. return flex;
  193. }
  194. /***
  195. ** Function: NewStem
  196. **
  197. ** Description:
  198. ** This function records a new stem hint for
  199. ** the current glyph.
  200. ***/
  201. static Stem *NewStem(const funit offset,
  202. const funit width,
  203. const short hr)
  204. {
  205. Stem *stem = NULL;
  206. if ((stem = Malloc(sizeof(Stem)))!=NULL) {
  207. if (width>0) {
  208. stem->offset = offset;
  209. stem->width = width;
  210. } else {
  211. stem->offset = offset+width;
  212. stem->width = -width;
  213. }
  214. stem->i1 = hr;
  215. stem->i2 = ENDOFPATH;
  216. }
  217. return stem;
  218. }
  219. /***
  220. ** Function: NewStem3
  221. **
  222. ** Description:
  223. ** This function records a new stem3 hint for the current glyph.
  224. ***/
  225. static Stem3 *NewStem3(const funit o1, const funit w1,
  226. const funit o2, const funit w2,
  227. const funit o3, const funit w3,
  228. const short hr)
  229. {
  230. Stem3 *stem3 = NULL;
  231. if ((stem3 = Malloc(sizeof(Stem3)))!=NULL) {
  232. stem3->stem1.offset = o1;
  233. stem3->stem1.width = w1;
  234. stem3->stem1.i1 = hr;
  235. stem3->stem1.i2 = ENDOFPATH;
  236. stem3->stem2.offset = o2;
  237. stem3->stem2.width = w2;
  238. stem3->stem2.i1 = hr;
  239. stem3->stem2.i2 = ENDOFPATH;
  240. stem3->stem3.offset = o3;
  241. stem3->stem3.width = w3;
  242. stem3->stem3.i1 = hr;
  243. stem3->stem3.i2 = ENDOFPATH;
  244. }
  245. return stem3;
  246. }
  247. /***
  248. ** Function: NewPath
  249. **
  250. ** Description:
  251. ** This function adds a new contour to the current glyph.
  252. ***/
  253. static errcode NewPath(T1Glyph *glyph,
  254. const Point *pts,
  255. ULONG *onoff,
  256. const USHORT numpts)
  257. {
  258. errcode status = SUCCESS;
  259. Outline *path;
  260. Outline *prev;
  261. /* Skip 1,2 point paths. */
  262. if (numpts>2) {
  263. if ((path=Malloc(sizeof(Outline)))==NULL) {
  264. SetError(status = NOMEM);
  265. } else {
  266. path->pts=Malloc(sizeof(Point)*numpts);
  267. path->onoff=Malloc(ONOFFSIZE(numpts));
  268. if (path->pts==NULL || path->onoff==NULL) {
  269. if (path->pts)
  270. Free(path->pts);
  271. if (path->onoff)
  272. Free(path->onoff);
  273. Free(path);
  274. return NOMEM;
  275. }
  276. /* Initiate the new sub-path. */
  277. memcpy(path->pts, pts, sizeof(Point)*numpts);
  278. memcpy(path->onoff, onoff, ONOFFSIZE(numpts));
  279. path->count = numpts;
  280. /* Link it in. */
  281. path->next = NULL;
  282. if (glyph->paths==NULL) {
  283. glyph->paths = path;
  284. } else {
  285. for (prev = glyph->paths; prev->next; prev=prev->next);
  286. prev->next = path;
  287. }
  288. }
  289. }
  290. return status;
  291. }
  292. /***** FUNCTIONS */
  293. /***
  294. ** Function: AllocPSState
  295. **
  296. ** Description:
  297. ** This function allocates the workspace
  298. ** used by the t1 parser.
  299. ***/
  300. struct PSState *AllocPSState(void)
  301. {
  302. struct PSState *ps;
  303. if ((ps = Malloc(sizeof(struct PSState)))!=NULL) {
  304. memset(ps, '\0', sizeof(struct PSState));
  305. }
  306. return ps;
  307. }
  308. /***
  309. ** Function: FreePSState
  310. **
  311. ** Description:
  312. ** This function frees the workspace
  313. ** used by the t1 parser.
  314. ***/
  315. void FreePSState(struct PSState *ps)
  316. {
  317. if (ps) {
  318. if (ps->onoff)
  319. Free(ps->onoff);
  320. if (ps->pts)
  321. Free(ps->pts);
  322. }
  323. Free(ps);
  324. }
  325. /***
  326. ** Function: InitPS
  327. **
  328. ** Description:
  329. ** This function initiate the workspace
  330. ** used by the t1 parser.
  331. ***/
  332. void InitPS(struct PSState *ps)
  333. {
  334. ps->hr = 0;
  335. ps->totpts = 0;
  336. ps->ptr = 0;
  337. ps->calls = 0;
  338. }
  339. /***
  340. ** Function: ParseCharString
  341. **
  342. ** Description:
  343. ** This function parses a CharString and builds a
  344. ** of the charstring glyph.
  345. ***/
  346. errcode ParseCharString(T1Glyph *glyph,
  347. struct Composite **comp,
  348. PSState *ps,
  349. const struct Subrs *subrs,
  350. UBYTE *code,
  351. USHORT len)
  352. {
  353. Composite *c;
  354. Stem3 *stem3;
  355. Stem *stem;
  356. Flex *flex;
  357. long v, w;
  358. funit dx1, dy1, dx2, dy2, dx3, dy3;
  359. funit x0, y0, x1, y1, x2, y2, x3, y3;
  360. funit width, offset;
  361. funit o1, o2, o3, w1, w2, w3;
  362. long v1, v2, v3, v4;
  363. errcode status = SUCCESS;
  364. long subr, args;
  365. funit flexciv;
  366. char *glyph_name = NULL;
  367. USHORT zero[ENC_MAXCODES];
  368. char msg[64];
  369. int i;
  370. /* Keep track on the number of recursive calls. */
  371. ps->calls++;
  372. if (ps->calls>100) {
  373. LogError(MSG_ERROR, MSG_RECURSION, NULL);
  374. SetError(status = BADCHARSTRING);
  375. return status;
  376. }
  377. while (len) {
  378. v = *code++; len--;
  379. /* Check for space for the paths. */
  380. if (ps->numpts+4>=ps->maxpts) {
  381. Point *newpts;
  382. ULONG *newonoff;
  383. if ((newpts=Realloc(ps->pts,
  384. sizeof(Point)*(ps->maxpts+BUFMARGIN)))==NULL)
  385. return NOMEM;
  386. else
  387. ps->pts = newpts;
  388. if ((newonoff=Realloc(ps->onoff,
  389. ONOFFSIZE(ps->maxpts+BUFMARGIN)))==NULL)
  390. return NOMEM;
  391. else
  392. ps->onoff = newonoff;
  393. ps->maxpts += BUFMARGIN;
  394. }
  395. /* Check the operator stack size. */
  396. if ((ps->ptr+1)>=MAXSTACK) {
  397. SetError(status = BADCHARSTRING);
  398. return status;
  399. }
  400. /* Decode integer. */
  401. if (v>=32) {
  402. if (v<=246)
  403. PushStack(v-139);
  404. else if (v<=250) {
  405. w = *code++; len--;
  406. PushStack((v-247)*256+w+108);
  407. } else if (v<=254) {
  408. w = *code++; len--;
  409. PushStack(-(v-251)*256-w-108);
  410. } else {
  411. v1 = *code++; len--;
  412. v2 = *code++; len--;
  413. v3 = *code++; len--;
  414. v4 = *code++; len--;
  415. PushStack(((v1*256+v2)*256+v3)*256+v4);
  416. }
  417. /* Decode command. */
  418. } else {
  419. switch (v) {
  420. case PSOP_HSTEM:
  421. width = (funit)PopStack();
  422. offset = (funit)PopStack();
  423. if ((stem = NewStem(offset, width, ps->hr))==NULL)
  424. return NOMEM;
  425. stem->next = glyph->hints.hstems;
  426. glyph->hints.hstems = stem;
  427. break;
  428. case PSOP_VSTEM:
  429. width = (funit)PopStack();
  430. offset = (funit)PopStack()+glyph->lsb.x;
  431. if ((stem = NewStem(offset, width, (ps->hr)))==NULL)
  432. return NOMEM;
  433. stem->next = glyph->hints.vstems;
  434. glyph->hints.vstems = stem;
  435. break;
  436. case PSOP_VMOVETO:
  437. CurrYPoint(ps) += (funit)PopStack();
  438. break;
  439. case PSOP_RLINETO:
  440. y1 = CurrYPoint(ps) + (funit)PopStack();
  441. x1 = CurrXPoint(ps) + (funit)PopStack();
  442. SetOnPoint(ps->onoff, ps->numpts);
  443. AddPoint(ps, x1, y1);
  444. break;
  445. case PSOP_HLINETO:
  446. x1 = CurrXPoint(ps) + (funit)PopStack();
  447. y1 = CurrYPoint(ps);
  448. SetOnPoint(ps->onoff, ps->numpts);
  449. AddPoint(ps, x1, y1);
  450. break;
  451. case PSOP_VLINETO:
  452. x1 = CurrXPoint(ps);
  453. y1 = CurrYPoint(ps) + (funit)PopStack();
  454. SetOnPoint(ps->onoff, ps->numpts);
  455. AddPoint(ps, x1, y1);
  456. break;
  457. case PSOP_RRCURVETO:
  458. dy3 = (funit)PopStack();
  459. dx3 = (funit)PopStack();
  460. dy2 = (funit)PopStack();
  461. dx2 = (funit)PopStack();
  462. dy1 = (funit)PopStack();
  463. dx1 = (funit)PopStack();
  464. x0 = CurrXPoint(ps);
  465. y0 = CurrYPoint(ps);
  466. x1 = x0 + dx1;
  467. y1 = y0 + dy1;
  468. x2 = x1 + dx2;
  469. y2 = y1 + dy2;
  470. x3 = x2 + dx3;
  471. y3 = y2 + dy3;
  472. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  473. break;
  474. case PSOP_CLOSEPATH:
  475. /* Add the path to the glyph. */
  476. if ((status = NewPath(glyph, ps->pts,
  477. ps->onoff, ps->numpts))!=SUCCESS)
  478. return status;
  479. /* Current point = last point. */
  480. SetOnPoint(ps->onoff, 0);
  481. ps->pts[0] = ps->pts[ps->numpts-1];
  482. ps->totpts = (USHORT)(ps->totpts + ps->numpts);
  483. ps->numpts = 1;
  484. break;
  485. case PSOP_CALLSUBR:
  486. v = PopStack();
  487. if ((status = ParseCharString(glyph, comp, ps,
  488. subrs, subrs[v].code,
  489. subrs[v].len))!=SUCCESS)
  490. return status;
  491. break;
  492. case PSOP_RETURN:
  493. ps->calls--;
  494. return SUCCESS;
  495. case PSOP_ESCAPE:
  496. v = *code++; len--;
  497. switch (v) {
  498. case PSOP_DOTSECTION:
  499. /* End of dot section? */
  500. if (ps->numpts>1) {
  501. ps->hr = (short)(ps->totpts+ps->numpts-1);
  502. HintReplacement(glyph, (short)(ps->hr-1));
  503. }
  504. break;
  505. case PSOP_VSTEM3:
  506. w1 = (funit)PopStack();
  507. o1 = (funit)PopStack()+glyph->lsb.x;
  508. w2 = (funit)PopStack();
  509. o2 = (funit)PopStack()+glyph->lsb.x;
  510. w3 = (funit)PopStack();
  511. o3 = (funit)PopStack()+glyph->lsb.x;
  512. if (o1>o2) {
  513. SWAPINT(o1, o2);
  514. SWAPINT(w1, w2);
  515. }
  516. if (o1>o3) {
  517. SWAPINT(o1, o3);
  518. SWAPINT(w1, w3);
  519. }
  520. if (o3<o2) {
  521. SWAPINT(o2, o3);
  522. SWAPINT(w2, w3);
  523. }
  524. if ((stem3 = NewStem3(o1, w1,
  525. o2, w2,
  526. o3, w3,
  527. ps->hr))==NULL)
  528. return NOMEM;
  529. stem3->next = glyph->hints.vstems3;
  530. glyph->hints.vstems3 = stem3;
  531. break;
  532. case PSOP_HSTEM3:
  533. w1 = (funit)PopStack(); o1 = (funit)PopStack();
  534. w2 = (funit)PopStack(); o2 = (funit)PopStack();
  535. w3 = (funit)PopStack(); o3 = (funit)PopStack();
  536. if ((stem3 = NewStem3(o1, w1,
  537. o2, w2,
  538. o3, w3,
  539. ps->hr))==NULL)
  540. return NOMEM;
  541. stem3->next = glyph->hints.hstems3;
  542. glyph->hints.hstems3 = stem3;
  543. break;
  544. case PSOP_SEAC:
  545. if ((c=Malloc(sizeof(Composite)))==NULL) {
  546. return NOMEM;
  547. }
  548. c->aw = glyph->width.x;
  549. c->achar = LookupCharName(DecodeChar(NULL, (USHORT)0,
  550. ENC_STANDARD,
  551. (USHORT)PopStack()));
  552. c->bchar = LookupCharName(DecodeChar(NULL, (USHORT)0,
  553. ENC_STANDARD,
  554. (USHORT)PopStack()));
  555. if ((c->cchar = Strdup(glyph->name))==NULL)
  556. return NOMEM;
  557. c->oenc = NULL;
  558. c->ady = (funit)PopStack();
  559. c->adx = (funit)PopStack();
  560. c->asbx = (funit)PopStack();
  561. c->next = *comp;
  562. *comp = c;
  563. if (glyph->paths==NULL)
  564. return SKIP;
  565. if ((glyph->name = Malloc(strlen(c->achar)+
  566. strlen(c->bchar)+2))==NULL ||
  567. (c->oenc = AllocEncodingTable((USHORT)1))==NULL) {
  568. if (glyph->name)
  569. Free(glyph->name);
  570. if (c->oenc)
  571. Free(c->oenc);
  572. return NOMEM;
  573. }
  574. strcpy(glyph->name, c->bchar);
  575. strcat(glyph->name, c->achar);
  576. memset(zero, '\0', sizeof(zero[0])*ENC_MAXCODES);
  577. if ((glyph_name = Strdup(glyph->name))!=NULL)
  578. SetEncodingEntry(c->oenc, (USHORT)0, glyph_name,
  579. ENC_MAXCODES, zero);
  580. else
  581. return NOMEM;
  582. break;
  583. case PSOP_SBW:
  584. glyph->width.y = (funit)PopStack();
  585. glyph->width.x = (funit)PopStack();
  586. glyph->lsb.y = (funit)PopStack();
  587. glyph->lsb.x = (funit)PopStack();
  588. ps->pts[0].x = glyph->lsb.x;
  589. ps->pts[0].y = glyph->lsb.y;
  590. ps->numpts = 1;
  591. SetOnPoint(ps->onoff, 0);
  592. break;
  593. case PSOP_DIV:
  594. /* LogError("Floating point precision lost.\n"); */
  595. y1 = (funit)PopStack();
  596. x1 = (funit)PopStack();
  597. if ((ps->ptr+1)>=MAXSTACK)
  598. return BADCHARSTRING;
  599. PushStack(((long)x1+(long)(y1>>1))/(long)y1);
  600. break;
  601. case PSOP_CALLOTHERSUBR:
  602. subr = PopStack();
  603. args = PopStack();
  604. /* Remember the arguments for future pop's. */
  605. for (i=0; i<args; i++) {
  606. ps->otherargs[i] = ps->stack[args-i-1];
  607. }
  608. ps->otherptr = 0;
  609. switch (subr) {
  610. case HINT_END_FLEX:
  611. y0 = (funit)PopStack();
  612. x0 = (funit)PopStack();
  613. flexciv = (funit)PopStack();
  614. ps->numpts--;
  615. SetOffPoint(ps->onoff, ps->numpts-2);
  616. SetOffPoint(ps->onoff, ps->numpts-3);
  617. SetOffPoint(ps->onoff, ps->numpts-5);
  618. SetOffPoint(ps->onoff, ps->numpts-6);
  619. if ((flex = NewFlex(ps->flexref,
  620. PrevPoint(ps, 3),
  621. PrevPoint(ps, 6),
  622. (USHORT)(ps->totpts+
  623. ps->numpts-7),
  624. (USHORT)(ps->totpts+
  625. ps->numpts-4),
  626. (USHORT)(ps->totpts+
  627. ps->numpts-1),
  628. flexciv))==NULL)
  629. return NOMEM;
  630. flex->next = glyph->hints.flex;
  631. glyph->hints.flex = flex;
  632. break;
  633. case HINT_START_FLEX:
  634. ps->flex = 1;
  635. x0 = CurrXPoint(ps);
  636. y0 = CurrYPoint(ps);
  637. SetOnPoint(ps->onoff, ps->numpts);
  638. AddPoint(ps, x0, y0);
  639. break;
  640. case HINT_MID_FLEX:
  641. y0 = CurrYPoint(ps);
  642. x0 = CurrXPoint(ps);
  643. if (ps->flex==1) {
  644. ps->flexref.x = x0;
  645. ps->flexref.y = y0;
  646. ps->flex=0;
  647. } else {
  648. SetOnPoint(ps->onoff, ps->numpts);
  649. AddPoint(ps, x0, y0);
  650. }
  651. break;
  652. case HINT_REPLACEMENT:
  653. ps->hr = (short)(ps->totpts+ps->numpts-1);
  654. HintReplacement(glyph, (short)(ps->hr-1));
  655. (void)PopStack();
  656. break;
  657. default:
  658. ps->ptr = (USHORT)(ps->ptr - args);
  659. break;
  660. }
  661. break;
  662. case PSOP_POP:
  663. if ((ps->ptr+1)>=MAXSTACK)
  664. return BADCHARSTRING;
  665. PushStack(ps->otherargs[ps->otherptr++]);
  666. break;
  667. case PSOP_SETCURRENTPOINT:
  668. (ps->ptr) -= 2;
  669. break;
  670. case 15:
  671. ps->ptr-=2;
  672. break;
  673. default:
  674. LogError(MSG_ERROR, MSG_BADESC, NULL);
  675. SetError(status = BADCHARSTRING);
  676. return status;
  677. }
  678. break;
  679. case PSOP_HSBW:
  680. glyph->width.x = (funit)PopStack();
  681. glyph->width.y = 0;
  682. glyph->lsb.x = (funit)PopStack();
  683. glyph->lsb.y = 0;
  684. ps->pts[0].x = glyph->lsb.x;
  685. ps->pts[0].y = 0;
  686. ps->numpts = 1;
  687. SetOnPoint(ps->onoff, 0);
  688. break;
  689. case PSOP_ENDCHAR:
  690. if (ps->numpts>1) {
  691. if ((status = NewPath(glyph, ps->pts,
  692. ps->onoff, ps->numpts))!=SUCCESS)
  693. return status;
  694. }
  695. return SUCCESS;
  696. case PSOP_RMOVETO:
  697. CurrYPoint(ps) += (funit)PopStack();
  698. CurrXPoint(ps) += (funit)PopStack();
  699. break;
  700. case PSOP_HMOVETO:
  701. CurrXPoint(ps) += (funit)PopStack();
  702. break;
  703. case PSOP_VHCURVETO:
  704. dy3 = 0;
  705. dx3 = (funit)PopStack();
  706. dy2 = (funit)PopStack();
  707. dx2 = (funit)PopStack();
  708. dy1 = (funit)PopStack();
  709. dx1 = 0;
  710. x0 = CurrXPoint(ps);
  711. y0 = CurrYPoint(ps);
  712. x1 = x0 + dx1;
  713. y1 = y0 + dy1;
  714. x2 = x1 + dx2;
  715. y2 = y1 + dy2;
  716. x3 = x2 + dx3;
  717. y3 = y2 + dy3;
  718. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  719. break;
  720. case PSOP_HVCURVETO:
  721. dy3 = (funit)PopStack();
  722. dx3 = 0;
  723. dy2 = (funit)PopStack();
  724. dx2 = (funit)PopStack();
  725. dy1 = 0;
  726. dx1 = (funit)PopStack();
  727. x0 = CurrXPoint(ps);
  728. y0 = CurrYPoint(ps);
  729. x1 = x0 + dx1;
  730. y1 = y0 + dy1;
  731. x2 = x1 + dx2;
  732. y2 = y1 + dy2;
  733. x3 = x2 + dx3;
  734. y3 = y2 + dy3;
  735. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  736. break;
  737. case 15:
  738. ps->ptr -=2;
  739. break;
  740. default:
  741. strcpy(msg, "'00' (00)");
  742. msg[1] = (char)('0' + (v/10));
  743. msg[2] = (char)('0' + (v%10));
  744. msg[6] = (char)('0' + (ps->ptr/10));
  745. msg[7] = (char)('0' + (ps->ptr%10));
  746. LogError(MSG_ERROR, MSG_BADOP, msg);
  747. SetError(status = BADCHARSTRING);
  748. return status;
  749. }
  750. }
  751. /* Check number of elements on the stack. */
  752. if (ps->ptr>MAXSTACK)
  753. return BADCHARSTRING;
  754. }
  755. return SUCCESS;
  756. }