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.

839 lines
25 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. /* Decode integer. */
  396. if (v>=32) {
  397. if (v<=246)
  398. PushStack(v-139);
  399. else if (v<=250) {
  400. w = *code++; len--;
  401. PushStack((v-247)*256+w+108);
  402. } else if (v<=254) {
  403. w = *code++; len--;
  404. PushStack(-(v-251)*256-w-108);
  405. } else {
  406. v1 = *code++; len--;
  407. v2 = *code++; len--;
  408. v3 = *code++; len--;
  409. v4 = *code++; len--;
  410. PushStack(((v1*256+v2)*256+v3)*256+v4);
  411. }
  412. /* Decode command. */
  413. } else {
  414. switch (v) {
  415. case PSOP_HSTEM:
  416. width = (funit)PopStack();
  417. offset = (funit)PopStack();
  418. if ((stem = NewStem(offset, width, ps->hr))==NULL)
  419. return NOMEM;
  420. stem->next = glyph->hints.hstems;
  421. glyph->hints.hstems = stem;
  422. break;
  423. case PSOP_VSTEM:
  424. width = (funit)PopStack();
  425. offset = (funit)PopStack()+glyph->lsb.x;
  426. if ((stem = NewStem(offset, width, (ps->hr)))==NULL)
  427. return NOMEM;
  428. stem->next = glyph->hints.vstems;
  429. glyph->hints.vstems = stem;
  430. break;
  431. case PSOP_VMOVETO:
  432. CurrYPoint(ps) += (funit)PopStack();
  433. break;
  434. case PSOP_RLINETO:
  435. y1 = CurrYPoint(ps) + (funit)PopStack();
  436. x1 = CurrXPoint(ps) + (funit)PopStack();
  437. SetOnPoint(ps->onoff, ps->numpts);
  438. AddPoint(ps, x1, y1);
  439. break;
  440. case PSOP_HLINETO:
  441. x1 = CurrXPoint(ps) + (funit)PopStack();
  442. y1 = CurrYPoint(ps);
  443. SetOnPoint(ps->onoff, ps->numpts);
  444. AddPoint(ps, x1, y1);
  445. break;
  446. case PSOP_VLINETO:
  447. x1 = CurrXPoint(ps);
  448. y1 = CurrYPoint(ps) + (funit)PopStack();
  449. SetOnPoint(ps->onoff, ps->numpts);
  450. AddPoint(ps, x1, y1);
  451. break;
  452. case PSOP_RRCURVETO:
  453. dy3 = (funit)PopStack();
  454. dx3 = (funit)PopStack();
  455. dy2 = (funit)PopStack();
  456. dx2 = (funit)PopStack();
  457. dy1 = (funit)PopStack();
  458. dx1 = (funit)PopStack();
  459. x0 = CurrXPoint(ps);
  460. y0 = CurrYPoint(ps);
  461. x1 = x0 + dx1;
  462. y1 = y0 + dy1;
  463. x2 = x1 + dx2;
  464. y2 = y1 + dy2;
  465. x3 = x2 + dx3;
  466. y3 = y2 + dy3;
  467. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  468. break;
  469. case PSOP_CLOSEPATH:
  470. /* Add the path to the glyph. */
  471. if ((status = NewPath(glyph, ps->pts,
  472. ps->onoff, ps->numpts))!=SUCCESS)
  473. return status;
  474. /* Current point = last point. */
  475. SetOnPoint(ps->onoff, 0);
  476. ps->pts[0] = ps->pts[ps->numpts-1];
  477. ps->totpts = (USHORT)(ps->totpts + ps->numpts);
  478. ps->numpts = 1;
  479. break;
  480. case PSOP_CALLSUBR:
  481. v = PopStack();
  482. if ((status = ParseCharString(glyph, comp, ps,
  483. subrs, subrs[v].code,
  484. subrs[v].len))!=SUCCESS)
  485. return status;
  486. break;
  487. case PSOP_RETURN:
  488. ps->calls--;
  489. return SUCCESS;
  490. case PSOP_ESCAPE:
  491. v = *code++; len--;
  492. switch (v) {
  493. case PSOP_DOTSECTION:
  494. /* End of dot section? */
  495. if (ps->numpts>1) {
  496. ps->hr = (short)(ps->totpts+ps->numpts-1);
  497. HintReplacement(glyph, (short)(ps->hr-1));
  498. }
  499. break;
  500. case PSOP_VSTEM3:
  501. w1 = (funit)PopStack();
  502. o1 = (funit)PopStack()+glyph->lsb.x;
  503. w2 = (funit)PopStack();
  504. o2 = (funit)PopStack()+glyph->lsb.x;
  505. w3 = (funit)PopStack();
  506. o3 = (funit)PopStack()+glyph->lsb.x;
  507. if (o1>o2) {
  508. SWAPINT(o1, o2);
  509. SWAPINT(w1, w2);
  510. }
  511. if (o1>o3) {
  512. SWAPINT(o1, o3);
  513. SWAPINT(w1, w3);
  514. }
  515. if (o3<o2) {
  516. SWAPINT(o2, o3);
  517. SWAPINT(w2, w3);
  518. }
  519. if ((stem3 = NewStem3(o1, w1,
  520. o2, w2,
  521. o3, w3,
  522. ps->hr))==NULL)
  523. return NOMEM;
  524. stem3->next = glyph->hints.vstems3;
  525. glyph->hints.vstems3 = stem3;
  526. break;
  527. case PSOP_HSTEM3:
  528. w1 = (funit)PopStack(); o1 = (funit)PopStack();
  529. w2 = (funit)PopStack(); o2 = (funit)PopStack();
  530. w3 = (funit)PopStack(); o3 = (funit)PopStack();
  531. if ((stem3 = NewStem3(o1, w1,
  532. o2, w2,
  533. o3, w3,
  534. ps->hr))==NULL)
  535. return NOMEM;
  536. stem3->next = glyph->hints.hstems3;
  537. glyph->hints.hstems3 = stem3;
  538. break;
  539. case PSOP_SEAC:
  540. if ((c=Malloc(sizeof(Composite)))==NULL) {
  541. return NOMEM;
  542. }
  543. c->aw = glyph->width.x;
  544. c->achar = LookupCharName(DecodeChar(NULL, (USHORT)0,
  545. ENC_STANDARD,
  546. (USHORT)PopStack()));
  547. c->bchar = LookupCharName(DecodeChar(NULL, (USHORT)0,
  548. ENC_STANDARD,
  549. (USHORT)PopStack()));
  550. if ((c->cchar = Strdup(glyph->name))==NULL)
  551. return NOMEM;
  552. c->oenc = NULL;
  553. c->ady = (funit)PopStack();
  554. c->adx = (funit)PopStack();
  555. c->asbx = (funit)PopStack();
  556. c->next = *comp;
  557. *comp = c;
  558. if (glyph->paths==NULL)
  559. return SKIP;
  560. if ((glyph->name = Malloc(strlen(c->achar)+
  561. strlen(c->bchar)+2))==NULL ||
  562. (c->oenc = AllocEncodingTable((USHORT)1))==NULL) {
  563. if (glyph->name)
  564. Free(glyph->name);
  565. if (c->oenc)
  566. Free(c->oenc);
  567. return NOMEM;
  568. }
  569. strcpy(glyph->name, c->bchar);
  570. strcat(glyph->name, c->achar);
  571. memset(zero, '\0', sizeof(zero[0])*ENC_MAXCODES);
  572. if ((glyph_name = Strdup(glyph->name))!=NULL)
  573. SetEncodingEntry(c->oenc, (USHORT)0, glyph_name,
  574. ENC_MAXCODES, zero);
  575. else
  576. return NOMEM;
  577. break;
  578. case PSOP_SBW:
  579. glyph->width.y = (funit)PopStack();
  580. glyph->width.x = (funit)PopStack();
  581. glyph->lsb.y = (funit)PopStack();
  582. glyph->lsb.x = (funit)PopStack();
  583. ps->pts[0].x = glyph->lsb.x;
  584. ps->pts[0].y = glyph->lsb.y;
  585. ps->numpts = 1;
  586. SetOnPoint(ps->onoff, 0);
  587. break;
  588. case PSOP_DIV:
  589. /* LogError("Floating point precision lost.\n"); */
  590. y1 = (funit)PopStack();
  591. x1 = (funit)PopStack();
  592. PushStack(((long)x1+(long)(y1>>1))/(long)y1);
  593. break;
  594. case PSOP_CALLOTHERSUBR:
  595. subr = PopStack();
  596. args = PopStack();
  597. /* Remember the arguments for future pop's. */
  598. for (i=0; i<args; i++) {
  599. ps->otherargs[i] = ps->stack[args-i-1];
  600. }
  601. ps->otherptr = 0;
  602. switch (subr) {
  603. case HINT_END_FLEX:
  604. y0 = (funit)PopStack();
  605. x0 = (funit)PopStack();
  606. flexciv = (funit)PopStack();
  607. ps->numpts--;
  608. SetOffPoint(ps->onoff, ps->numpts-2);
  609. SetOffPoint(ps->onoff, ps->numpts-3);
  610. SetOffPoint(ps->onoff, ps->numpts-5);
  611. SetOffPoint(ps->onoff, ps->numpts-6);
  612. if ((flex = NewFlex(ps->flexref,
  613. PrevPoint(ps, 3),
  614. PrevPoint(ps, 6),
  615. (USHORT)(ps->totpts+
  616. ps->numpts-7),
  617. (USHORT)(ps->totpts+
  618. ps->numpts-4),
  619. (USHORT)(ps->totpts+
  620. ps->numpts-1),
  621. flexciv))==NULL)
  622. return NOMEM;
  623. flex->next = glyph->hints.flex;
  624. glyph->hints.flex = flex;
  625. break;
  626. case HINT_START_FLEX:
  627. ps->flex = 1;
  628. x0 = CurrXPoint(ps);
  629. y0 = CurrYPoint(ps);
  630. SetOnPoint(ps->onoff, ps->numpts);
  631. AddPoint(ps, x0, y0);
  632. break;
  633. case HINT_MID_FLEX:
  634. y0 = CurrYPoint(ps);
  635. x0 = CurrXPoint(ps);
  636. if (ps->flex==1) {
  637. ps->flexref.x = x0;
  638. ps->flexref.y = y0;
  639. ps->flex=0;
  640. } else {
  641. SetOnPoint(ps->onoff, ps->numpts);
  642. AddPoint(ps, x0, y0);
  643. }
  644. break;
  645. case HINT_REPLACEMENT:
  646. ps->hr = (short)(ps->totpts+ps->numpts-1);
  647. HintReplacement(glyph, (short)(ps->hr-1));
  648. (void)PopStack();
  649. break;
  650. default:
  651. ps->ptr = (USHORT)(ps->ptr - args);
  652. break;
  653. }
  654. break;
  655. case PSOP_POP:
  656. PushStack(ps->otherargs[ps->otherptr++]);
  657. break;
  658. case PSOP_SETCURRENTPOINT:
  659. (ps->ptr) -= 2;
  660. break;
  661. case 15:
  662. ps->ptr-=2;
  663. break;
  664. default:
  665. LogError(MSG_ERROR, MSG_BADESC, NULL);
  666. SetError(status = BADCHARSTRING);
  667. return status;
  668. }
  669. break;
  670. case PSOP_HSBW:
  671. glyph->width.x = (funit)PopStack();
  672. glyph->width.y = 0;
  673. glyph->lsb.x = (funit)PopStack();
  674. glyph->lsb.y = 0;
  675. ps->pts[0].x = glyph->lsb.x;
  676. ps->pts[0].y = 0;
  677. ps->numpts = 1;
  678. SetOnPoint(ps->onoff, 0);
  679. break;
  680. case PSOP_ENDCHAR:
  681. if (ps->numpts>1) {
  682. if ((status = NewPath(glyph, ps->pts,
  683. ps->onoff, ps->numpts))!=SUCCESS)
  684. return status;
  685. }
  686. return SUCCESS;
  687. case PSOP_RMOVETO:
  688. CurrYPoint(ps) += (funit)PopStack();
  689. CurrXPoint(ps) += (funit)PopStack();
  690. break;
  691. case PSOP_HMOVETO:
  692. CurrXPoint(ps) += (funit)PopStack();
  693. break;
  694. case PSOP_VHCURVETO:
  695. dy3 = 0;
  696. dx3 = (funit)PopStack();
  697. dy2 = (funit)PopStack();
  698. dx2 = (funit)PopStack();
  699. dy1 = (funit)PopStack();
  700. dx1 = 0;
  701. x0 = CurrXPoint(ps);
  702. y0 = CurrYPoint(ps);
  703. x1 = x0 + dx1;
  704. y1 = y0 + dy1;
  705. x2 = x1 + dx2;
  706. y2 = y1 + dy2;
  707. x3 = x2 + dx3;
  708. y3 = y2 + dy3;
  709. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  710. break;
  711. case PSOP_HVCURVETO:
  712. dy3 = (funit)PopStack();
  713. dx3 = 0;
  714. dy2 = (funit)PopStack();
  715. dx2 = (funit)PopStack();
  716. dy1 = 0;
  717. dx1 = (funit)PopStack();
  718. x0 = CurrXPoint(ps);
  719. y0 = CurrYPoint(ps);
  720. x1 = x0 + dx1;
  721. y1 = y0 + dy1;
  722. x2 = x1 + dx2;
  723. y2 = y1 + dy2;
  724. x3 = x2 + dx3;
  725. y3 = y2 + dy3;
  726. AddCSpline(ps, x1, y1, x2, y2, x3, y3);
  727. break;
  728. case 15:
  729. ps->ptr -=2;
  730. break;
  731. default:
  732. strcpy(msg, "'00' (00)");
  733. msg[1] = (char)('0' + (v/10));
  734. msg[2] = (char)('0' + (v%10));
  735. msg[6] = (char)('0' + (ps->ptr/10));
  736. msg[7] = (char)('0' + (ps->ptr%10));
  737. LogError(MSG_ERROR, MSG_BADOP, msg);
  738. SetError(status = BADCHARSTRING);
  739. return status;
  740. }
  741. }
  742. /* Check number of elements on the stack. */
  743. if (ps->ptr>MAXSTACK)
  744. return BADCHARSTRING;
  745. }
  746. return SUCCESS;
  747. }