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.

2395 lines
48 KiB

  1. /***
  2. **
  3. ** Module: ttprog
  4. **
  5. ** Description:
  6. ** This is a module of the T1 to TT font converter. This is a
  7. ** sub-module of Hint module. This modules deals with the
  8. ** the font program fo the font.
  9. **
  10. ** Author: Michael Jansson
  11. **
  12. ** Created: 8/24/93
  13. **
  14. ***/
  15. /**** INCLUDES */
  16. /* General types and definitions. */
  17. #include <limits.h>
  18. /* Special types and definitions. */
  19. #include "titott.h"
  20. #include "types.h"
  21. #include "safemem.h"
  22. #include "metrics.h"
  23. #include "t1msg.h"
  24. /* Module dependent types and prototypes. */
  25. /*#include "hints.h"*/
  26. #include "ttprog.h"
  27. /***** MACROS */
  28. /*-none-*/
  29. /***** CONSTANTS */
  30. #define MAXIP 100
  31. #define CURVEPHASE 6
  32. #define MAXTHINPNTS 512
  33. #define UNDEF -1
  34. #define SMALL_LOWER 21L
  35. #define SMALL_UPPER 50L
  36. #define LARGE_LOWER 21L
  37. #define LARGE_UPPER 21L
  38. #define BUFSIZE 20
  39. #define TTFUN_SET_ZONE 1
  40. #define TTFUN_COPY_ZONE 2
  41. #define TTFUN_STEM_SNAP_WIDTH 3
  42. #define TTFUN_STEM_STD_WIDTH 4
  43. #define TTFUN_SHIFT_BLUE_ZONE 5
  44. #define TTFUN_ALIGN_BLUE_ZONE 6
  45. #define TTFUN_COPY_FAMILY 7
  46. #define TTFUN_WRITE_STEM 8
  47. #define TTFUN_VERTICAL 9
  48. #define TTFUN_HORIZONTAL 10
  49. #define TTFUN_VCENTER 11
  50. #define TTFUN_HCENTER 12
  51. #define TTFUN_RELATIVE1V 13
  52. #define TTFUN_RELATIVE2V 14
  53. #define TTFUN_RELATIVE1H 15
  54. #define TTFUN_RELATIVE2H 16
  55. #define TTFUN_SIDE1 17
  56. #define TTFUN_SIDE2 18
  57. #define TTFUN_FLEX 19
  58. #define TTFUN_SCALE3 20
  59. #define TTFUN_SHIFT1 21
  60. #define TTFUN_SHIFT2 22
  61. #define TTFUN_IP1 23
  62. #define TTFUN_IP2 24
  63. #define TTFUN_IPN 25
  64. #define TTFUN_SHP1 26
  65. #define TTFUN_SHP2 27
  66. #define TTFUN_SHPN 28
  67. #define TTFUN_RANGE 29
  68. #define TTFUN_OBLIQUE 30
  69. #define TTFUN_NUM 31 /* 1..30 */
  70. #define FDEF(name) op_pushb1, name, op_fdef,
  71. #define ENDF op_endf,
  72. #define CALL(name) op_pushb1, name, op_call
  73. #define WCVT(name) op_pushb1, name, op_swap, op_wcvtf
  74. #define PUSH1(v) op_pushb1, (v)
  75. #define PUSH2(v1, v2) op_pushb1+1, (v1), (v2)
  76. #define PUSH3(v1, v2, v3) op_pushb1+2, (v1), (v2), (v3)
  77. #define PUSH4(v1, v2, v3, v4) op_pushb1+3, (v1), (v2), (v3), (v4)
  78. #define PUSH5(v1,v2,v3,v4,v5) op_pushb1+4, (v1), (v2), (v3), (v4), (v5)
  79. static const UBYTE FontProg[] = {
  80. /******* SET ZONE FUNCTION
  81. *
  82. * Args: flat_pos
  83. *
  84. */
  85. FDEF(TTFUN_SET_ZONE)
  86. PUSH1(TMPPNT),
  87. op_swap,
  88. op_miap,
  89. PUSH1(TMPPNT),
  90. op_mdap | SUBOP_R,
  91. ENDF
  92. /******* COPY ZONE FUNCTION
  93. *
  94. * Args: from_cvt, to_cvt
  95. *
  96. */
  97. FDEF(TTFUN_COPY_ZONE)
  98. op_rcvt,
  99. op_round,
  100. op_wcvtp,
  101. ENDF
  102. /******* STEM SNAP WIDTH FUNCTION
  103. *
  104. * Args: std_ci, std_cvt, snap_ci, snap_cvt, width, storage
  105. *
  106. */
  107. FDEF(TTFUN_STEM_SNAP_WIDTH)
  108. op_mppem,
  109. op_gteq,
  110. op_if,
  111. /* Use std */
  112. op_rcvt,
  113. op_round,
  114. PUSH1(ONEPIXEL/2),
  115. op_max,
  116. op_swap, op_pop, op_swap, op_pop, op_swap, op_pop,
  117. CALL(TTFUN_WRITE_STEM),
  118. op_else,
  119. op_pop,
  120. op_mppem,
  121. op_gteq,
  122. op_if,
  123. /* Use snap */
  124. op_rcvt,
  125. op_round,
  126. PUSH1(ONEPIXEL/2),
  127. op_max,
  128. op_swap,
  129. op_pop,
  130. CALL(TTFUN_WRITE_STEM),
  131. /* Use real width. */
  132. op_else,
  133. op_pop,
  134. WCVT(TMPCVT),
  135. PUSH1(TMPCVT),
  136. op_rcvt,
  137. op_round,
  138. PUSH1(ONEPIXEL/2),
  139. op_max,
  140. CALL(TTFUN_WRITE_STEM),
  141. op_eif,
  142. op_eif,
  143. ENDF
  144. /******* STEM STD WIDTH FUNCTION
  145. *
  146. * Args: std_ci, std_cvt, width, storage
  147. *
  148. */
  149. FDEF(TTFUN_STEM_STD_WIDTH)
  150. op_mppem,
  151. op_gteq,
  152. op_if,
  153. /* Use std */
  154. op_rcvt,
  155. op_round,
  156. PUSH1(ONEPIXEL/2),
  157. op_max,
  158. op_swap,
  159. op_pop,
  160. CALL(TTFUN_WRITE_STEM),
  161. /* Use real width. */
  162. op_else,
  163. op_pop,
  164. WCVT(TMPCVT),
  165. PUSH1(TMPCVT),
  166. op_rcvt,
  167. op_round,
  168. PUSH1(ONEPIXEL/2),
  169. op_max,
  170. CALL(TTFUN_WRITE_STEM),
  171. op_eif,
  172. ENDF
  173. /******* SHIFT BLUE ZONE FUNCTION
  174. *
  175. * Args: cvt
  176. *
  177. */
  178. FDEF(TTFUN_SHIFT_BLUE_ZONE)
  179. PUSH5(TMPPNT1, TMPPNT1, TMPPNT, TMPPNT1, 5),
  180. op_cindex,
  181. op_miap,
  182. op_srp0,
  183. op_mdrp | SUBOP_mMRGR,
  184. op_gc,
  185. op_wcvtp,
  186. ENDF
  187. /******* ALIGN BLUE ZONE FUNCTION
  188. *
  189. * Args: cvt
  190. *
  191. */
  192. FDEF(TTFUN_ALIGN_BLUE_ZONE)
  193. PUSH5(TMPPNT1, TMPPNT1, TMPPNT, TMPPNT1, 5),
  194. op_cindex,
  195. op_miap,
  196. op_srp0,
  197. op_mdrp | SUBOP_ROUND,
  198. op_gc,
  199. op_wcvtp,
  200. ENDF
  201. /******* COPY FAMILY FUNCTION
  202. *
  203. * Args: base_cvt
  204. *
  205. */
  206. FDEF(TTFUN_COPY_FAMILY)
  207. op_dup,
  208. PUSH1(1),
  209. op_add,
  210. op_rcvt,
  211. op_wcvtp,
  212. ENDF
  213. /******* WRITE STEM FUNCTION
  214. *
  215. * Args: width, storage
  216. *
  217. */
  218. FDEF(TTFUN_WRITE_STEM)
  219. op_dup, /* -| width, width, storage */
  220. op_dup, /* -| width, width, width, storage */
  221. op_add, /* -| 2*width, width, storage, */
  222. op_odd, /* -| odd/even, width, storage */
  223. PUSH2(1, 4), /* -| 4, 1, odd/even, width, storage */
  224. op_cindex, /* -| storage, 1, odd/even, width, storage */
  225. op_add,
  226. op_swap, /* -| odd/even, storage+1, width, storage */
  227. op_ws,
  228. op_ws,
  229. ENDF
  230. /******* VERTICAL FUNCTION
  231. *
  232. * Args: -*none*-
  233. *
  234. */
  235. FDEF(TTFUN_VERTICAL)
  236. op_svcta | SUBOP_X,
  237. PUSH1(TWILIGHT),
  238. op_szps,
  239. ENDF
  240. /******* HORIZONTAL FUNCTION
  241. *
  242. * Args: -*none*-
  243. *
  244. */
  245. FDEF(TTFUN_HORIZONTAL)
  246. PUSH1(TWILIGHT),
  247. op_svcta,
  248. op_szps,
  249. ENDF
  250. /******* CENTER VSTEM FUNCTION
  251. *
  252. * Args: p1, p2, p3, p4, c, tz1, width
  253. *
  254. */
  255. FDEF(TTFUN_VCENTER)
  256. /* Set rounding state for the center. */
  257. PUSH2(1, 8),
  258. op_cindex,
  259. op_add,
  260. op_rs,
  261. op_if,
  262. op_rthg,
  263. op_else,
  264. op_rtg,
  265. op_eif,
  266. /* Create the stem in the twilight zone. */
  267. WCVT(TMPCVT),
  268. PUSH2(TMPCVT, 6),
  269. op_cindex,
  270. op_swap,
  271. op_miap,
  272. WCVT(TMPCVT),
  273. PUSH3(TMPCVT, 1, 6),
  274. op_cindex,
  275. op_add,
  276. op_swap,
  277. op_miap,
  278. WCVT(TMPCVT),
  279. PUSH3(TMPCVT, 2, 5),
  280. op_cindex,
  281. op_add,
  282. op_swap,
  283. op_miap,
  284. WCVT(TMPCVT),
  285. PUSH3(TMPCVT, 3, 4),
  286. op_cindex,
  287. op_add,
  288. op_swap,
  289. op_miap,
  290. /* Move/round center. */
  291. WCVT(TMPCVT), /* c */
  292. PUSH2(TMPPNT, TMPCVT),
  293. op_miap| SUBOP_R,
  294. op_rtg,
  295. /* Align all points to the center. */
  296. op_dup, op_dup, PUSH1(1), op_add,
  297. op_alignrp, op_alignrp, /* tz1, tz1+1 */
  298. /* Compute the width. */
  299. op_swap,
  300. op_rs,
  301. PUSH1(CURVEPHASE),
  302. op_sub,
  303. op_swap,
  304. /* -| tz1, width */
  305. op_dup,
  306. op_dup,
  307. op_dup,
  308. op_srp0,
  309. PUSH1(4), op_cindex,
  310. op_neg, /* -| (-width/2), tz1, tz1, tz1, width */
  311. op_shpix,
  312. PUSH1(2),
  313. op_add,
  314. op_alignrp, /* -| tz1+2, tz1, width */
  315. /* Do the other side. */
  316. /* -| tz1, width */
  317. PUSH1(1),
  318. op_add,
  319. op_dup,
  320. op_dup, /* -| tz1+1, tz1+1, tz1+1, width */
  321. op_srp0,
  322. op_roll, /* -| width, tz1+1, tz1+1 */
  323. op_shpix,
  324. PUSH1(2),
  325. op_add,
  326. op_alignrp, /* -| tz1+3 */
  327. /* Done. */
  328. ENDF
  329. /******* CENTER HSTEM FUNCTION
  330. *
  331. * Args: p1, p2, c, tz1, width
  332. *
  333. */
  334. FDEF(TTFUN_HCENTER)
  335. /* Set,rounding state for the center. */
  336. PUSH2(1, 6),
  337. op_cindex,
  338. op_add,
  339. op_rs,
  340. op_if,
  341. op_rthg,
  342. op_else,
  343. op_rtg,
  344. op_eif,
  345. /* Create the stem in the twilight zone. */
  346. WCVT(TMPCVT),
  347. PUSH2(TMPCVT, 4),
  348. op_cindex,
  349. op_swap,
  350. op_miap,
  351. WCVT(TMPCVT),
  352. PUSH3(TMPCVT, 1, 4),
  353. op_cindex,
  354. op_add,
  355. op_swap,
  356. op_miap,
  357. /* Move/round center. */
  358. WCVT(TMPCVT), /* c */
  359. PUSH2(TMPPNT, TMPCVT),
  360. op_miap| SUBOP_R,
  361. op_rtg,
  362. /* Align all points to the center. */
  363. op_dup, op_dup, PUSH1(1), op_add,
  364. op_alignrp, op_alignrp, /* tz1, tz1+1 */
  365. /* Compute the width. */
  366. op_swap,
  367. op_rs,
  368. PUSH1(CURVEPHASE),
  369. op_sub,
  370. op_swap,
  371. /* -| tz1, width */
  372. op_dup,
  373. PUSH1(3), op_cindex,
  374. op_neg, /* -| -width, tz1, tz1, width */
  375. op_shpix,
  376. /* Do the other side. */
  377. /* -| tz1, width */
  378. PUSH1(1),
  379. op_add,
  380. op_swap, /* -| width, tz1+1 */
  381. op_shpix,
  382. /* Done. */
  383. ENDF
  384. /******* RELATIVE1V STEM FUNCTION
  385. *
  386. * Args: p1, p2, p3, p4, ref, tz1, width
  387. *
  388. */
  389. FDEF(TTFUN_RELATIVE1V)
  390. /* Create the stem in the twilight zone. */
  391. WCVT(TMPCVT),
  392. PUSH2(TMPCVT, 6),
  393. op_cindex,
  394. op_swap,
  395. op_miap,
  396. WCVT(TMPCVT),
  397. PUSH3(TMPCVT, 1, 6),
  398. op_cindex,
  399. op_add,
  400. op_swap,
  401. op_miap,
  402. WCVT(TMPCVT),
  403. PUSH3(TMPCVT, 2, 5),
  404. op_cindex,
  405. op_add,
  406. op_swap,
  407. op_miap,
  408. WCVT(TMPCVT),
  409. PUSH3(TMPCVT, 3, 4),
  410. op_cindex,
  411. op_add,
  412. op_swap,
  413. op_miap,
  414. /* Move/round side. */
  415. op_srp0,
  416. op_dup,
  417. op_mdrp | SUBOP_MmRGR,
  418. /* Align points on the left side. */
  419. op_dup, PUSH1(1), op_add, op_dup, op_dup, op_dup,
  420. PUSH1(1), op_add, /* -| tz1+2, tz1+1, tz1+1, tz+1, tz, width */
  421. op_alignrp,
  422. op_alignrp,
  423. /* Align right side */
  424. op_srp0, /* -| tz1+1, tz1, width */
  425. op_roll,
  426. op_rs,
  427. op_dup,
  428. op_add, /* -| width*2, tz1+1, tz1 */
  429. op_shpix,
  430. PUSH1(3),
  431. op_add,
  432. op_alignrp, /* -| tz1+3 */
  433. ENDF
  434. /******* RELATIVE2V STEM FUNCTION
  435. *
  436. * Args: p1, p2, p3, p4, ref, tz1, width
  437. *
  438. */
  439. FDEF(TTFUN_RELATIVE2V)
  440. /* Create the stem in the twilight zone. */
  441. WCVT(TMPCVT),
  442. PUSH2(TMPCVT, 6),
  443. op_cindex,
  444. op_swap,
  445. op_miap,
  446. WCVT(TMPCVT),
  447. PUSH3(TMPCVT, 1, 6),
  448. op_cindex,
  449. op_add,
  450. op_swap,
  451. op_miap,
  452. WCVT(TMPCVT),
  453. PUSH3(TMPCVT, 2, 5),
  454. op_cindex,
  455. op_add,
  456. op_swap,
  457. op_miap,
  458. WCVT(TMPCVT),
  459. PUSH3(TMPCVT, 3, 4),
  460. op_cindex,
  461. op_add,
  462. op_swap,
  463. op_miap,
  464. /* Move/round side. */
  465. op_srp0,
  466. op_dup,
  467. PUSH1(1), op_add,
  468. op_mdrp | SUBOP_MmRGR,
  469. /* Align points on the left side. */
  470. op_dup, op_dup, op_dup, op_dup,
  471. PUSH1(3), op_add, /* -| tz1+3, tz1, tz1, tz1, tz1, width */
  472. op_alignrp,
  473. op_alignrp,
  474. /* Align left side */
  475. op_srp0, /* -| tz1, tz1, width */
  476. op_roll,
  477. op_rs,
  478. op_dup,
  479. op_add,
  480. op_neg,
  481. op_shpix, /* -| -2*width, tz1, tz1 */
  482. PUSH1(2), op_add,
  483. op_alignrp, /* -| tz1+2 */
  484. ENDF
  485. /******* RELATIVE1H STEM FUNCTION
  486. *
  487. * Args: p1, p2, ref, tz1, width
  488. *
  489. */
  490. FDEF(TTFUN_RELATIVE1H)
  491. /* Create the stem in the twilight zone. */
  492. WCVT(TMPCVT),
  493. PUSH2(TMPCVT, 4),
  494. op_cindex,
  495. op_swap,
  496. op_miap,
  497. WCVT(TMPCVT),
  498. PUSH3(TMPCVT, 1, 4),
  499. op_cindex,
  500. op_add,
  501. op_swap,
  502. op_miap,
  503. /* Move/round side. */
  504. op_srp0,
  505. op_dup,
  506. op_mdrp | SUBOP_MmRGR,
  507. /* Align all point to the lower side. */
  508. PUSH1(1), op_add, op_dup,
  509. op_alignrp,
  510. /* Align right side */
  511. op_swap,
  512. op_rs,
  513. op_dup,
  514. op_add,
  515. op_shpix,
  516. ENDF
  517. /******* RELATIVE2H STEM FUNCTION
  518. *
  519. * Args: p1, p2, ref, tz1, width
  520. *
  521. */
  522. FDEF(TTFUN_RELATIVE2H)
  523. /* Create the stem in the twilight zone. */
  524. WCVT(TMPCVT),
  525. PUSH2(TMPCVT, 4),
  526. op_cindex,
  527. op_swap,
  528. op_miap,
  529. WCVT(TMPCVT),
  530. PUSH3(TMPCVT, 1, 4),
  531. op_cindex,
  532. op_add,
  533. op_swap,
  534. op_miap,
  535. /* Move/round side. */
  536. op_srp0,
  537. op_dup,
  538. PUSH1(1), op_add,
  539. op_mdrp | SUBOP_MmRGR,
  540. /* Align all points to the center. */
  541. op_dup, op_alignrp,
  542. /* Align left side */
  543. op_swap,
  544. op_rs,
  545. op_dup,
  546. op_add,
  547. op_neg,
  548. op_shpix,
  549. ENDF
  550. /******* SIDE1 STEM FUNCTION
  551. *
  552. * Args: p1, p2, zone, tz1, width
  553. *
  554. */
  555. FDEF(TTFUN_SIDE1)
  556. /* Create the stem in the twilight zone. */
  557. WCVT(TMPCVT),
  558. PUSH2(TMPCVT, 4),
  559. op_cindex,
  560. op_swap,
  561. op_miap,
  562. WCVT(TMPCVT),
  563. PUSH3(TMPCVT, 1, 4),
  564. op_cindex,
  565. op_add,
  566. op_swap,
  567. op_miap,
  568. /* Move/round side. */
  569. PUSH2(TMPPNT, TMPPNT),
  570. op_srp0, op_swap, op_miap | SUBOP_R,
  571. /* Align all points to the side. */
  572. op_dup, PUSH1(1), op_add, op_dup, op_roll,
  573. op_alignrp, op_alignrp,
  574. /* Align first side */
  575. op_swap,
  576. op_rs,
  577. op_dup,
  578. op_add,
  579. PUSH1(CURVEPHASE),
  580. op_sub,
  581. op_shpix,
  582. ENDF
  583. /******* SIDE2 STEM FUNCTION
  584. *
  585. * Args: p1, p2, zone, tz1, width
  586. *
  587. */
  588. FDEF(TTFUN_SIDE2)
  589. /* Create the stem in the twilight zone. */
  590. WCVT(TMPCVT),
  591. PUSH2(TMPCVT, 4),
  592. op_cindex,
  593. op_swap,
  594. op_miap,
  595. WCVT(TMPCVT),
  596. PUSH3(TMPCVT, 1, 4),
  597. op_cindex,
  598. op_add,
  599. op_swap,
  600. op_miap,
  601. /* Move/round side. */
  602. PUSH2(TMPPNT, TMPPNT),
  603. op_srp0, op_swap, op_miap | SUBOP_R,
  604. /* Align all points to the side. */
  605. op_dup, op_dup, PUSH1(1), op_add,
  606. op_alignrp, op_alignrp,
  607. /* Align second side */
  608. op_swap,
  609. op_rs,
  610. op_dup,
  611. op_add,
  612. PUSH1(CURVEPHASE),
  613. op_sub,
  614. op_neg,
  615. op_shpix,
  616. ENDF
  617. /******* FLEX FUNCTION
  618. *
  619. * Args on the stack: pnt_start, pnt_mid, ref_pos, pnt_mid,
  620. * pnt_start, pnt_mid, cnt, p1, p2, ....
  621. *
  622. */
  623. FDEF(TTFUN_FLEX)
  624. op_srp0,
  625. op_alignrp,
  626. op_wcvtf,
  627. op_rcvt,
  628. op_shpix,
  629. op_srp1,
  630. op_srp2,
  631. op_sloop,
  632. op_ip,
  633. ENDF
  634. /******* SCALE3 FUNCTION
  635. *
  636. * Args: cnt, p1, p2, ...
  637. *
  638. */
  639. FDEF(TTFUN_SCALE3)
  640. PUSH4(GLYPHZONE, TMPPNT1, TMPPNT, TMPPNT1),
  641. op_pushw1, HIBYTE(-31), LOBYTE(-31),
  642. PUSH3(TMPPNT, 0, TMPPNT1),
  643. op_pushw1, HIBYTE(1000), LOBYTE(1000),
  644. op_scfs,
  645. op_scfs,
  646. op_shpix,
  647. op_srp1,
  648. op_srp2,
  649. op_szp2,
  650. op_sloop,
  651. op_ip,
  652. ENDF
  653. /******* SHIFT1 FUNCTION
  654. *
  655. * Args: cnt reduction p1 p2 ...
  656. *
  657. */
  658. FDEF(TTFUN_SHIFT1)
  659. op_sloop,
  660. op_rs,
  661. op_neg,
  662. op_shpix,
  663. ENDF
  664. /******* SHIFT2 FUNCTION
  665. *
  666. * Args: cnt reduction p1 p2 ...
  667. *
  668. */
  669. FDEF(TTFUN_SHIFT2)
  670. op_sloop,
  671. op_rs,
  672. op_shpix,
  673. ENDF
  674. /******* IP1 FUNCTION
  675. *
  676. * Args: rp1, rp2, p1
  677. *
  678. */
  679. FDEF(TTFUN_IP1)
  680. op_srp1,
  681. op_srp2,
  682. op_ip,
  683. ENDF
  684. /******* IP2 FUNCTION
  685. *
  686. * Args: rp1, rp2, p1, p2
  687. *
  688. */
  689. FDEF(TTFUN_IP2)
  690. op_srp1,
  691. op_srp2,
  692. op_ip,
  693. op_ip,
  694. ENDF
  695. /******* IPN FUNCTION
  696. *
  697. * Args: rp1, rp2, cnt, p1, p2
  698. *
  699. */
  700. FDEF(TTFUN_IPN)
  701. op_srp1,
  702. op_srp2,
  703. op_sloop,
  704. op_ip,
  705. ENDF
  706. /******* SHP1 FUNCTION
  707. *
  708. * Args: rp, p
  709. *
  710. */
  711. FDEF(TTFUN_SHP1)
  712. op_srp1,
  713. op_shp,
  714. ENDF
  715. /******* SHP2 FUNCTION
  716. *
  717. * Args: rp, p1, p2
  718. *
  719. */
  720. FDEF(TTFUN_SHP2)
  721. op_srp1,
  722. op_shp,
  723. op_shp,
  724. ENDF
  725. /******* SHPN FUNCTION
  726. *
  727. * Args: rp, cnt, p1, p2
  728. *
  729. */
  730. FDEF(TTFUN_SHPN)
  731. op_srp1,
  732. op_sloop,
  733. op_shp,
  734. ENDF
  735. /******* RANGE FUNCTION
  736. *
  737. * Args: p
  738. *
  739. */
  740. FDEF(TTFUN_RANGE)
  741. op_dup,
  742. PUSH1(1),
  743. op_add,
  744. ENDF
  745. /******* RANGE FUNCTION
  746. *
  747. * Args: pos_x, pos_y,
  748. *
  749. */
  750. FDEF(TTFUN_OBLIQUE)
  751. op_svcta | SUBOP_Y,
  752. PUSH1(TMPPNT1),
  753. op_swap,
  754. op_scfs,
  755. PUSH2(TMPPNT, 0),
  756. op_scfs,
  757. op_svcta | SUBOP_X,
  758. PUSH1(TMPPNT1),
  759. op_swap,
  760. op_scfs,
  761. PUSH2(TMPPNT, 0),
  762. op_scfs,
  763. PUSH2(TMPPNT, TMPPNT1),
  764. op_spvtl,
  765. ENDF
  766. };
  767. /***** LOCAL TYPES */
  768. /***** STATIC FUNCTIONS */
  769. /***
  770. ** Function: GetVStemWidth
  771. **
  772. ** Description:
  773. ** This function allocates a storage entry for the
  774. ** width of a vertical stem;
  775. ***/
  776. static short GetVStemWidth(WeightControl *weight, const funit width)
  777. {
  778. StemWidth *newwidths = NULL;
  779. short entry = 0;
  780. USHORT j;
  781. if (weight->cnt_vw >= weight->max_vw) {
  782. newwidths = Realloc(weight->vwidths,
  783. sizeof(StemWidth)*(weight->max_vw+BUFSIZE));
  784. if (newwidths == NULL) {
  785. entry = NOMEM;
  786. } else {
  787. weight->vwidths = newwidths;
  788. weight->max_vw += BUFSIZE;
  789. }
  790. }
  791. if (entry != NOMEM) {
  792. for (j=0; j<weight->cnt_vw; j++) {
  793. if (weight->vwidths[j].width==width) {
  794. entry = (short)weight->vwidths[j].storage;
  795. break;
  796. }
  797. }
  798. if (j==weight->cnt_vw) {
  799. weight->vwidths[weight->cnt_vw].storage = weight->storage;
  800. weight->vwidths[weight->cnt_vw].width = width;
  801. entry = (short)weight->storage;
  802. weight->storage += 2;
  803. weight->cnt_vw++;
  804. }
  805. }
  806. return entry;
  807. }
  808. /***
  809. ** Function: GetHStemWidth
  810. **
  811. ** Description:
  812. ** This function allocates a storage entry for the
  813. ** width of a vertical stem;
  814. ***/
  815. static short GetHStemWidth(WeightControl *weight, const funit width)
  816. {
  817. StemWidth *newwidths = NULL;
  818. short entry = 0;
  819. USHORT j;
  820. if (weight->cnt_hw >= weight->max_hw) {
  821. newwidths = Realloc(weight->hwidths,
  822. sizeof(StemWidth)*(weight->max_hw+BUFSIZE));
  823. if (newwidths == NULL) {
  824. entry = NOMEM;
  825. } else {
  826. weight->hwidths = newwidths;
  827. weight->max_hw += BUFSIZE;
  828. }
  829. }
  830. if (entry != NOMEM) {
  831. for (j=0; j<weight->cnt_hw; j++) {
  832. if (weight->hwidths[j].width==width) {
  833. entry = (short)weight->hwidths[j].storage;
  834. break;
  835. }
  836. }
  837. if (j==weight->cnt_hw) {
  838. weight->hwidths[weight->cnt_hw].storage = weight->storage;
  839. weight->hwidths[weight->cnt_hw].width = width;
  840. entry = (short)weight->storage;
  841. weight->storage += 2;
  842. weight->cnt_hw++;
  843. }
  844. }
  845. return entry;
  846. }
  847. /***** GLOBAL FUNCTIONS */
  848. /***
  849. ** Function: SetZone
  850. **
  851. ** Description:
  852. ** This function initiate an alignment zone
  853. ** by creating an appropriate point in the
  854. ** twilight zone.
  855. ***/
  856. USHORT SetZone(UBYTE *prep, USHORT tp, const short cvt)
  857. {
  858. /* Set up the zone. */
  859. if (cvt>255) {
  860. prep[tp++] = op_pushw1;
  861. prep[tp++] = HIBYTE(cvt);
  862. prep[tp++] = LOBYTE(cvt);
  863. prep[tp++] = op_pushb1;
  864. prep[tp++] = TTFUN_SET_ZONE;
  865. } else {
  866. prep[tp++] = op_pushb1 + 1;
  867. prep[tp++] = (UBYTE)cvt;
  868. prep[tp++] = TTFUN_SET_ZONE;
  869. }
  870. prep[tp++] = op_call;
  871. return tp;
  872. }
  873. /***
  874. ** Function: CopyZone
  875. **
  876. ** Description:
  877. ** This function copies a cvt entry, representing an
  878. ** alignment zone, to the cvt used for a particular hstem.
  879. ***/
  880. USHORT CopyZone(UBYTE *prep, short tp, short *args, const short ta)
  881. {
  882. args[0] = TTFUN_COPY_ZONE;
  883. args[1] = (short)((ta-2)/2);
  884. AssembleArgs(args, ta, prep, &tp);
  885. prep[tp++] = op_loopcall;
  886. return (USHORT)tp;
  887. }
  888. /***
  889. ** Function: CopyFamilyBlue
  890. **
  891. ** Description:
  892. ** This function copies a cvt entry, representing a
  893. ** family blue zone, to the cvt used for a particular hstem.
  894. ***/
  895. USHORT CopyFamilyBlue(UBYTE *prep, short tp, short *args, const short ta)
  896. {
  897. args[0] = TTFUN_COPY_FAMILY;
  898. args[1] = (short)(ta-2);
  899. AssembleArgs(args, ta, prep, &tp);
  900. prep[tp++] = op_loopcall;
  901. return (USHORT)tp;
  902. }
  903. /***
  904. ** Function: AlignFlat
  905. **
  906. ** Description:
  907. ** This function creates a cvt entry for
  908. ** a particular hstem.
  909. ***/
  910. USHORT AlignFlat(UBYTE *prep, short tp, short *args, const short ta)
  911. {
  912. args[0] = TTFUN_ALIGN_BLUE_ZONE;
  913. args[1] = (short)(ta-2);
  914. AssembleArgs(args, ta, prep, &tp);
  915. prep[tp++] = op_loopcall;
  916. return (USHORT)tp;
  917. }
  918. /***
  919. ** Function: AlignOvershoot
  920. **
  921. ** Description:
  922. ** This function creates a cvt entry for
  923. ** a particular hstem.
  924. ***/
  925. USHORT AlignOvershoot(UBYTE *prep, short tp, short *args, const short ta)
  926. {
  927. args[0] = TTFUN_SHIFT_BLUE_ZONE;
  928. args[1] = (short)(ta-2);
  929. AssembleArgs(args, ta, prep, &tp);
  930. prep[tp++] = op_loopcall;
  931. return (USHORT)tp;
  932. }
  933. /***
  934. ** Function: GetTopPos
  935. **
  936. ** Description:
  937. ** This function allocates a cvt entry for the
  938. ** top side of a horizontal stem;
  939. ***/
  940. short GetTopPos(const Blues *blues,
  941. AlignmentControl *align,
  942. const funit pos)
  943. {
  944. short entry = UNDEF;
  945. const funit *bluevals;
  946. short fuzz;
  947. USHORT i, j;
  948. bluevals = &(blues->bluevalues[0]);
  949. fuzz = blues->blueFuzz;
  950. /* Check if it is within a zone. */
  951. for (i=0; i<blues->blue_cnt; i+=2) {
  952. if (((bluevals[i]-fuzz)<=pos) && ((bluevals[i+1]+fuzz)>=pos))
  953. break;
  954. }
  955. /* Record the position? */
  956. if (i!=blues->blue_cnt) {
  957. i /= 2;
  958. /* Is the position already mapped to a cvt entry? */
  959. for (j=0; j<align->top[i].cnt; j++) {
  960. if (align->top[i].pos[j].y==pos) {
  961. entry = (short)align->top[i].pos[j].cvt;
  962. break;
  963. }
  964. }
  965. if (j==align->top[i].cnt) {
  966. /* Allocate the BlueZone cvt's */
  967. if (align->top[i].cnt==0) {
  968. align->top[i].blue_cvt = align->cvt;
  969. align->cvt +=2;
  970. }
  971. align->top[i].pos[align->top[i].cnt].cvt = align->cvt;
  972. align->top[i].pos[align->top[i].cnt].y = pos;
  973. entry = (short)align->cvt;
  974. align->cvt+=2;
  975. align->top[i].cnt++;
  976. }
  977. }
  978. return entry;
  979. }
  980. /***
  981. ** Function: GetBottomPos
  982. **
  983. ** Description:
  984. ** This function allocates a cvt entry for the
  985. ** top side of a horizontal stem;
  986. ***/
  987. short GetBottomPos(const Blues *blues,
  988. AlignmentControl *align,
  989. const funit pos)
  990. {
  991. short entry = UNDEF;
  992. const funit *bluevals;
  993. short fuzz;
  994. USHORT i, j;
  995. bluevals = &(blues->otherblues[0]);
  996. fuzz = blues->blueFuzz;
  997. /* Check if it is within a zone. */
  998. for (i=0; i<blues->oblue_cnt; i+=2) {
  999. if (((bluevals[i]-fuzz)<=pos) && ((bluevals[i+1]+fuzz)>=pos))
  1000. break;
  1001. }
  1002. /* Record the position? */
  1003. if (i!=blues->oblue_cnt) {
  1004. i /= 2;
  1005. /* Is the position already mapped to a cvt entry? */
  1006. for (j=0; j<align->bottom[i].cnt; j++) {
  1007. if (align->bottom[i].pos[j].y==pos) {
  1008. entry = (short)align->bottom[i].pos[j].cvt;
  1009. break;
  1010. }
  1011. }
  1012. if (j==align->bottom[i].cnt) {
  1013. /* Allocate the BlueZone and FamilyBlue cvt's */
  1014. if (align->bottom[i].cnt==0) {
  1015. align->bottom[i].blue_cvt = align->cvt++;
  1016. }
  1017. align->bottom[i].pos[align->bottom[i].cnt].cvt = align->cvt;
  1018. align->bottom[i].pos[align->bottom[i].cnt].y = pos;
  1019. entry = (short)align->cvt;
  1020. align->cvt+=2;
  1021. align->bottom[i].cnt++;
  1022. }
  1023. }
  1024. return entry;
  1025. }
  1026. /***
  1027. ** Function: CutInSize
  1028. **
  1029. ** Description:
  1030. ** This function computes the cut in size
  1031. ** of a stem, given a master width and the
  1032. ** width of the stem. This is done with the
  1033. ** StdVW==2.0 pixel treshold and the thinn
  1034. ** and wide cut in values.
  1035. ***/
  1036. USHORT CutInSize(const funit width,
  1037. const funit master,
  1038. const USHORT tresh,
  1039. const funit upem)
  1040. {
  1041. USHORT cis, ci1, ci2;
  1042. /*lint -e776 */
  1043. if (width > master) {
  1044. ci1 = (USHORT)((long)upem * SMALL_UPPER / ONEPIXEL /
  1045. (long)(width - master));
  1046. ci2 = (USHORT)((long)upem * LARGE_UPPER / ONEPIXEL /
  1047. (long)(width - master));
  1048. } else if (width < master) {
  1049. ci1 = (USHORT)((long)upem * SMALL_LOWER / ONEPIXEL /
  1050. (long)(master - width));
  1051. ci2 = (USHORT)((long)upem * LARGE_LOWER / ONEPIXEL /
  1052. (long)(master - width));
  1053. } else {
  1054. ci1 = INFINITY;
  1055. ci2 = INFINITY;
  1056. }
  1057. /*lint +e776 */
  1058. if (ci1 < tresh) {
  1059. cis = ci1;
  1060. } else if (ci2 < tresh) {
  1061. cis = tresh;
  1062. } else {
  1063. cis = ci2;
  1064. }
  1065. return cis;
  1066. }
  1067. /***
  1068. ** Function: SnapStemArgs
  1069. **
  1070. ** Description:
  1071. **
  1072. ***/
  1073. USHORT SnapStemArgs(short *args, USHORT ta,
  1074. const funit width,
  1075. const USHORT std_cvt,
  1076. const USHORT snap_cvt,
  1077. const USHORT std_ci,
  1078. const USHORT snap_ci,
  1079. const USHORT storage)
  1080. {
  1081. args[ta++] = (short)std_ci;
  1082. args[ta++] = (short)std_cvt;
  1083. args[ta++] = (short)snap_ci;
  1084. args[ta++] = (short)snap_cvt;
  1085. args[ta++] = (short)(width/2);
  1086. args[ta++] = (short)storage;
  1087. return ta;
  1088. }
  1089. /***
  1090. ** Function: StdStemArgs
  1091. **
  1092. ** Description:
  1093. **
  1094. ***/
  1095. USHORT StdStemArgs(short *args, USHORT ta,
  1096. const funit width,
  1097. const USHORT std_cvt,
  1098. const USHORT std_ci,
  1099. const USHORT storage)
  1100. {
  1101. args[ta++] = (short)std_ci;
  1102. args[ta++] = (short)std_cvt;
  1103. args[ta++] = (short)(width/2);
  1104. args[ta++] = (short)storage;
  1105. return ta;
  1106. }
  1107. /***
  1108. ** Function: CreateStdStems
  1109. **
  1110. ** Description:
  1111. **
  1112. ***/
  1113. USHORT CreateStdStems(UBYTE *prep, USHORT tp, const short cnt)
  1114. {
  1115. if (cnt>255) {
  1116. prep[tp++] = op_pushw1;
  1117. prep[tp++] = HIBYTE(cnt);
  1118. prep[tp++] = LOBYTE(cnt);
  1119. prep[tp++] = op_pushb1;
  1120. prep[tp++] = TTFUN_STEM_STD_WIDTH;
  1121. } else {
  1122. prep[tp++] = op_pushb1 + 1;
  1123. prep[tp++] = (UBYTE)cnt;
  1124. prep[tp++] = TTFUN_STEM_STD_WIDTH;
  1125. }
  1126. prep[tp++] = op_loopcall;
  1127. return tp;
  1128. }
  1129. /***
  1130. ** Function: CreateSnapStems
  1131. **
  1132. ** Description:
  1133. **
  1134. ***/
  1135. USHORT CreateSnapStems(UBYTE *prep, USHORT tp, const short cnt)
  1136. {
  1137. if (cnt>255) {
  1138. prep[tp++] = op_pushw1;
  1139. prep[tp++] = HIBYTE(cnt);
  1140. prep[tp++] = LOBYTE(cnt);
  1141. prep[tp++] = op_pushb1;
  1142. prep[tp++] = TTFUN_STEM_SNAP_WIDTH;
  1143. } else {
  1144. prep[tp++] = op_pushb1 + 1;
  1145. prep[tp++] = (UBYTE)cnt;
  1146. prep[tp++] = TTFUN_STEM_SNAP_WIDTH;
  1147. }
  1148. prep[tp++] = op_loopcall;
  1149. return tp;
  1150. }
  1151. /***
  1152. ** Function: tt_GetFontProg
  1153. **
  1154. ** Description:
  1155. ** This function returns the static font
  1156. ** font program.
  1157. ***/
  1158. const UBYTE *tt_GetFontProg(void)
  1159. {
  1160. return FontProg;
  1161. }
  1162. /***
  1163. ** Function: tt_GetFontProgSize
  1164. **
  1165. ** Description:
  1166. ** This function returns the size of the
  1167. ** static font program.
  1168. ***/
  1169. USHORT tt_GetFontProgSize(void)
  1170. {
  1171. return (USHORT)sizeof(FontProg);
  1172. }
  1173. /***
  1174. ** Function: tt_GetNumFuns
  1175. **
  1176. ** Description:
  1177. ** This function returns the number of functions
  1178. ** defined in the static font program.
  1179. ***/
  1180. USHORT tt_GetNumFuns(void)
  1181. {
  1182. return (USHORT)TTFUN_NUM;
  1183. }
  1184. /***
  1185. ** Function: EmitFlex
  1186. **
  1187. ** Description:
  1188. ** Convert a T1 flex hint into a TrueType IP[]
  1189. ** intruction sequence that will reduce a flex
  1190. ** that is flatter than a given height.
  1191. ***/
  1192. errcode EmitFlex(short *args,
  1193. short *pcd,
  1194. const funit height,
  1195. const short start,
  1196. const short mid,
  1197. const short last)
  1198. {
  1199. errcode status = SUCCESS;
  1200. int i;
  1201. /* Enough space for the instructions? */
  1202. args[(*pcd)++] = TTFUN_FLEX;
  1203. args[(*pcd)++] = start;
  1204. args[(*pcd)++] = mid;
  1205. args[(*pcd)++] = (short)height;
  1206. args[(*pcd)++] = TMPCVT;
  1207. args[(*pcd)++] = TMPCVT;
  1208. args[(*pcd)++] = mid;
  1209. args[(*pcd)++] = start;
  1210. args[(*pcd)++] = mid;
  1211. /* Push the flex points onto the stack. */
  1212. args[(*pcd)++] = (short)(last-start-2);
  1213. for (i=start+(short)1; i<last; i++)
  1214. if (i!=mid)
  1215. args[(*pcd)++] = (short)i;
  1216. return status;
  1217. }
  1218. /***
  1219. ** Function: ReduceDiagonals
  1220. **
  1221. ** Description:
  1222. ** This function generates the TT instructions
  1223. ** that will shrink the outline, in order to
  1224. ** control the width of diagonals. This implementation
  1225. ** can probably be improved.
  1226. ***/
  1227. short ReduceDiagonals(const Outline *paths,
  1228. UBYTE *pgm, short *pc,
  1229. short *args, short *pcd)
  1230. {
  1231. short cw[MAXTHINPNTS];
  1232. short ccw[MAXTHINPNTS];
  1233. short targ[MAXTHINPNTS];
  1234. const Outline *path;
  1235. Point *pts;
  1236. short i,j;
  1237. short cwi = 0, ccwi = 0;
  1238. short prev;
  1239. short n,m;
  1240. short prev_cw, prev_ccw;
  1241. short ta;
  1242. /* Collect points on left and right side that are diagonals. */
  1243. i = 0;
  1244. for (path = paths; path && ccwi<MAXTHINPNTS && cwi<MAXTHINPNTS;
  1245. path=path->next) {
  1246. pts = &path->pts[0];
  1247. prev_cw = FALSE;
  1248. prev_ccw = FALSE;
  1249. /* Are the first and last point coinciding? */
  1250. if (pts[path->count-1].x!=pts[0].x ||
  1251. pts[path->count-1].y!=pts[0].y)
  1252. prev = (short)(path->count-(short)1);
  1253. else
  1254. prev = (short)(path->count-(short)2);
  1255. /* Special case the first point. */
  1256. if (!OnCurve(path->onoff, prev) ||
  1257. (pts[0].x != pts[prev].x &&
  1258. ABS(pts[0].x - pts[prev].x) < ABS(pts[0].y - pts[prev].y)*8)) {
  1259. if (pts[0].y>pts[prev].y+20) {
  1260. if (pts[prev].y<=pts[prev-1].y)
  1261. cw[cwi++] = (short)(i+(short)path->count-1);
  1262. cw[cwi++] = i;
  1263. prev_cw = TRUE;
  1264. prev_ccw = FALSE;
  1265. } else if (pts[0].y<pts[prev].y-20) {
  1266. if (pts[prev].y>=pts[prev-1].y)
  1267. ccw[ccwi++] = (short)(i+(short)path->count-1);
  1268. ccw[ccwi++] = i;
  1269. prev_cw = FALSE;
  1270. prev_ccw = TRUE;
  1271. }
  1272. }
  1273. for (j=1; j<(short)path->count &&
  1274. ccwi<MAXTHINPNTS && cwi<MAXTHINPNTS; j++) {
  1275. i++;
  1276. if (!OnCurve(path->onoff, j-1) ||
  1277. (pts[j].x != pts[j-1].x &&
  1278. ABS(pts[j].x - pts[j-1].x) < ABS(pts[j].y - pts[j-1].y)*8)) {
  1279. if (pts[j].y>pts[j-1].y+20) {
  1280. if (!prev_cw)
  1281. cw[cwi++] = (short)(i-1);
  1282. cw[cwi++] = i;
  1283. prev_cw = TRUE;
  1284. prev_ccw = FALSE;
  1285. } else if (pts[j].y<pts[j-1].y-20) {
  1286. if (!prev_ccw)
  1287. ccw[ccwi++] = (short)(i-1);
  1288. ccw[ccwi++] = i;
  1289. prev_cw = FALSE;
  1290. prev_ccw = TRUE;
  1291. } else {
  1292. prev_cw = FALSE;
  1293. prev_ccw = FALSE;
  1294. }
  1295. } else {
  1296. prev_cw = FALSE;
  1297. prev_ccw = FALSE;
  1298. }
  1299. }
  1300. i++;
  1301. }
  1302. /* Did we get all points? */
  1303. if (ccwi>=MAXTHINPNTS || cwi>=MAXTHINPNTS) {
  1304. LogError(MSG_WARNING, MSG_DIAG, NULL);
  1305. }
  1306. /* Any points to shift? */
  1307. if (cwi || ccwi) {
  1308. args[(*pcd)++] = STORAGE_DIAG;
  1309. pgm[(*pc)++] = op_rs;
  1310. pgm[(*pc)++] = op_if;
  1311. pgm[(*pc)++] = op_svcta + SUBOP_X;
  1312. /* Switch over to GLYPHZONE */
  1313. pgm[(*pc)++] = op_szp2;
  1314. args[(*pcd)++] = 1;
  1315. ta = 3;
  1316. /* Disable "cw[m] may not have been initialized".*/ /*lint -e644 */
  1317. for (n=0; n<cwi; n=m) {
  1318. for (m=(short)(n+1); m<cwi && cw[m]==cw[m-1]+1; m++); /*lint +e644 */
  1319. if (m-n<=4) {
  1320. for (i=n; i<m; i++)
  1321. targ[ta++] = cw[i];
  1322. } else {
  1323. targ[0] = TTFUN_RANGE;
  1324. targ[1] = (short)(m-n-1);
  1325. targ[2] = cw[n];
  1326. AssembleArgs(targ, ta, pgm, pc);
  1327. pgm[(*pc)++] = op_loopcall;
  1328. ta = 3;
  1329. }
  1330. }
  1331. targ[0] = TTFUN_SHIFT1;
  1332. targ[1] = cwi;
  1333. targ[2] = STORAGE_DIAG;
  1334. AssembleArgs(targ, ta, pgm, pc);
  1335. pgm[(*pc)++] = op_call;
  1336. /************ Shift back the left side of the glyph. */
  1337. ta = 3;
  1338. /* Disable "ccw[m] may not have been initialized".*/ /*lint -e644 */
  1339. for (n=0; n<ccwi; n=m) {
  1340. for (m=(short)(n+1); m<ccwi && ccw[m]==ccw[m-1]+1; m++); /*lint +e644 */
  1341. if (m-n<=4) {
  1342. for (i=n; i<m; i++)
  1343. targ[ta++] = ccw[i];
  1344. } else {
  1345. targ[0] = TTFUN_RANGE;
  1346. targ[1] = (short)(m-n-1);
  1347. targ[2] = ccw[n];
  1348. AssembleArgs(targ, ta, pgm, pc);
  1349. pgm[(*pc)++] = op_loopcall;
  1350. ta = 3;
  1351. }
  1352. }
  1353. targ[0] = TTFUN_SHIFT2;
  1354. targ[1] = ccwi;
  1355. targ[2] = STORAGE_DIAG;
  1356. AssembleArgs(targ, ta, pgm, pc);
  1357. pgm[(*pc)++] = op_call;
  1358. #ifdef SYMETRICAL_REDUCTION
  1359. /* The amount that the outline is shrunk is computed once at
  1360. each size, in the pre-program. The outline is shrunk
  1361. symetrically by the amount: 1/16 + (12 Funits)*size/UPEm.
  1362. This approach yields more symmetrical results than shrinking
  1363. the outline horizontally alone (see separate papers on the topic). */
  1364. /* Same thing for the height... */
  1365. i = 0;
  1366. cwi = 0;
  1367. ccwi = 0;
  1368. for (path = paths; path && ccwi<MAXTHINPNTS && cwi<MAXTHINPNTS;
  1369. path=path->next) {
  1370. pts = &path->pts[0];
  1371. /* Are the first and last point coinciding? */
  1372. if (pts[path->count-1].y!=pts[0].y ||
  1373. pts[path->count-1].x!=pts[0].x)
  1374. prev = path->count-1;
  1375. else
  1376. prev = path->count-2;
  1377. if (!OnCurve(path->onoff, prev) ||
  1378. (pts[0].y != pts[prev].y &&
  1379. ABS(pts[0].y - pts[prev].y) < ABS(pts[0].x - pts[prev].x)*8)) {
  1380. if (pts[0].x>pts[prev].x+20) {
  1381. if (pts[prev].x<=pts[prev-1].x)
  1382. cw[cwi++] = i+path->count-1;
  1383. cw[cwi++] = i;
  1384. } else if (pts[0].x<pts[prev].x-20) {
  1385. if (pts[prev].x>=pts[prev-1].x)
  1386. ccw[ccwi++] = i+path->count-1;
  1387. ccw[ccwi++] = i;
  1388. }
  1389. }
  1390. for (j=1; j<path->count && ccwi<MAXTHINPNTS && cwi<MAXTHINPNTS; j++) {
  1391. i++;
  1392. if (!OnCurve(path->onoff, j-1) ||
  1393. (pts[j].y != pts[j-1].y &&
  1394. ABS(pts[j].y - pts[j-1].y) < ABS(pts[j].x - pts[j-1].x)*8)) {
  1395. if (pts[j].x>pts[j-1].x+20) {
  1396. if (!cwi || cw[cwi-1]!=i-1)
  1397. cw[cwi++] = i-1;
  1398. cw[cwi++] = i;
  1399. } else if (pts[j].x<pts[j-1].x-20) {
  1400. if (!ccwi || ccw[ccwi-1]!=i-1)
  1401. ccw[ccwi++] = i-1;
  1402. ccw[ccwi++] = i;
  1403. }
  1404. }
  1405. }
  1406. i++;
  1407. }
  1408. if (ccwi>=MAXTHINPNTS || cwi>=MAXTHINPNTS) {
  1409. LogError(MSG_WARNING, MSG_DIAG, NULL);
  1410. }
  1411. /* Any points to shift? */
  1412. if (cwi || ccwi) {
  1413. pgm[(*pc)++] = op_svcta + SUBOP_Y;
  1414. for (n=0; n<cwi; n=m) {
  1415. for (m=n+1; m<cwi && cw[m]==cw[m-1]+1; m++);
  1416. pgm[(*pc)++] = op_pushb1 + 2;
  1417. pgm[(*pc)++] = cw[n];
  1418. pgm[(*pc)++] = (UBYTE)(m-n-1);
  1419. pgm[(*pc)++] = TTFUN_RANGE;
  1420. pgm[(*pc)++] = op_loopcall;
  1421. }
  1422. pgm[(*pc)++] = op_pushb1+2;
  1423. pgm[(*pc)++] = STORAGE_DIAG;
  1424. pgm[(*pc)++] = cwi;
  1425. pgm[(*pc)++] = TTFUN_SHIFT2;
  1426. pgm[(*pc)++] = op_call;
  1427. /************ Shift back the left side of the glyph. */
  1428. for (n=0; n<ccwi; n=m) {
  1429. for (m=n+1; m<ccwi && ccw[m]==ccw[m-1]+1; m++);
  1430. pgm[(*pc)++] = op_pushb1 + 2;
  1431. pgm[(*pc)++] = (UBYTE)ccw[n];
  1432. pgm[(*pc)++] = (UBYTE)(m-n-1);
  1433. pgm[(*pc)++] = TTFUN_RANGE;
  1434. pgm[(*pc)++] = op_loopcall;
  1435. }
  1436. pgm[(*pc)++] = op_pushb1+2;
  1437. pgm[(*pc)++] = STORAGE_DIAG;
  1438. pgm[(*pc)++] = (UBYTE)ccwi;
  1439. pgm[(*pc)++] = TTFUN_SHIFT1;
  1440. pgm[(*pc)++] = op_call;
  1441. }
  1442. #endif
  1443. pgm[(*pc)++] = op_eif;
  1444. }
  1445. /* Args + num of args + function number. */
  1446. return (short)(MAX(cwi, ccwi)+2);
  1447. }
  1448. /***
  1449. ** Function: ScaleDown3
  1450. **
  1451. ** Description:
  1452. ** This function generates the TT instructions
  1453. ** that will scale down points 3%.
  1454. ***/
  1455. void ScaleDown3(const Extremas *extr, const short xcnt,
  1456. UBYTE *pgm, short *pc,
  1457. short *args, short *pcd)
  1458. {
  1459. short i,j,offset, opc, opcd;
  1460. /* Remember the state of the stacks. */
  1461. opc = (*pc);
  1462. opcd = (*pcd);
  1463. args[(*pcd)++] = TTFUN_SCALE3;
  1464. offset = (*pcd)++;
  1465. args[offset] = 0;
  1466. for (i=0; i<xcnt; i++) {
  1467. if ((extr[i].rp1==UNDEF || extr[i].rp2==UNDEF)) {
  1468. for (j=0; j<extr[i].n; j++) {
  1469. args[(*pcd)++] = extr[i].pts[j];
  1470. }
  1471. args[offset] = (short)(args[offset] + extr[i].n);
  1472. }
  1473. }
  1474. if (args[offset]>0) {
  1475. pgm[(*pc)++] = op_call;
  1476. } else {
  1477. /* Back track. */
  1478. (*pc) = opc;
  1479. (*pcd) = opcd;
  1480. }
  1481. }
  1482. /***
  1483. ** Function: EmitIP
  1484. **
  1485. ** Description:
  1486. ** This function generates the TT instructions
  1487. ** that will interpolate points that are either
  1488. ** within or between stem sides.
  1489. ***/
  1490. void EmitIP(const Extremas *extr, const short xcnt,
  1491. UBYTE *pgm, short *pc,
  1492. short *args, short *pcd,
  1493. const short scale3offset)
  1494. {
  1495. short i,j,num;
  1496. short ones[MAXIP], twoes[MAXIP], nths[MAXIP];
  1497. short cnt1, cnt2, cntn;
  1498. /*lint -e530 -e644 */
  1499. /* Shift extrems. */
  1500. cnt1 = 0; cnt2 = 0; cntn = 0; num = 0;
  1501. for (i=0; i<xcnt; i++) {
  1502. short rp;
  1503. /* Skip interpolations. */
  1504. if (extr[i].rp1!=UNDEF && extr[i].rp2!=UNDEF)
  1505. continue;
  1506. /* Set the reference points. */
  1507. if (extr[i].rp1!=UNDEF) {
  1508. rp = (short)(extr[i].rp1+scale3offset);
  1509. } else {
  1510. rp = (short)(extr[i].rp2+scale3offset);
  1511. }
  1512. if (extr[i].n==1) {
  1513. if ((cnt1+2)>=MAXIP) {
  1514. pgm[(*pc)++] = op_loopcall;
  1515. args[(*pcd)++] = TTFUN_SHP1;
  1516. args[(*pcd)++] = (short)(cnt1/2);
  1517. for (j=0; j<cnt1; j++)
  1518. args[(*pcd)++] = (short)ones[j];
  1519. cnt1 = 0;
  1520. }
  1521. ones[cnt1++] = rp;
  1522. ones[cnt1++] = extr[i].pts[0];
  1523. } else if (extr[i].n==2) {
  1524. if ((cnt2+3)>=MAXIP) {
  1525. pgm[(*pc)++] = op_loopcall;
  1526. args[(*pcd)++] = TTFUN_SHP2;
  1527. args[(*pcd)++] = (short)(cnt2/3);
  1528. for (j=0; j<cnt2; j++)
  1529. args[(*pcd)++] = (short)twoes[j];
  1530. cnt2 = 0;
  1531. }
  1532. twoes[cnt2++] = rp;
  1533. twoes[cnt2++] = extr[i].pts[0];
  1534. twoes[cnt2++] = extr[i].pts[1];
  1535. } else {
  1536. if ((cntn+2+extr[i].n)>=MAXIP) {
  1537. pgm[(*pc)++] = op_loopcall;
  1538. args[(*pcd)++] = TTFUN_SHPN;
  1539. args[(*pcd)++] = num;
  1540. for (j=0; j<cntn; j++)
  1541. args[(*pcd)++] = (short)nths[j];
  1542. cntn = 0;
  1543. num = 0;
  1544. }
  1545. nths[cntn++] = rp;
  1546. nths[cntn++] = extr[i].n;
  1547. for (j=0; j<extr[i].n; j++) {
  1548. nths[cntn++] = extr[i].pts[j];
  1549. }
  1550. num++;
  1551. }
  1552. }
  1553. if (cnt1) {
  1554. if (cnt1>2) {
  1555. pgm[(*pc)++] = op_loopcall;
  1556. args[(*pcd)++] = TTFUN_SHP1;
  1557. args[(*pcd)++] = (short)(cnt1/2);
  1558. } else {
  1559. pgm[(*pc)++] = op_call;
  1560. args[(*pcd)++] = TTFUN_SHP1;
  1561. }
  1562. for (i=0; i<cnt1; i++)
  1563. args[(*pcd)++] = ones[i];
  1564. }
  1565. if (cnt2) {
  1566. if (cnt2>3) {
  1567. pgm[(*pc)++] = op_loopcall;
  1568. args[(*pcd)++] = TTFUN_SHP2;
  1569. args[(*pcd)++] = (short)(cnt2/3);
  1570. } else {
  1571. pgm[(*pc)++] = op_call;
  1572. args[(*pcd)++] = TTFUN_SHP2;
  1573. }
  1574. for (i=0; i<cnt2; i++)
  1575. args[(*pcd)++] = twoes[i];
  1576. }
  1577. if (cntn) {
  1578. if (num>1) {
  1579. pgm[(*pc)++] = op_loopcall;
  1580. args[(*pcd)++] = TTFUN_SHPN;
  1581. args[(*pcd)++] = num;
  1582. } else {
  1583. pgm[(*pc)++] = op_call;
  1584. args[(*pcd)++] = TTFUN_SHPN;
  1585. }
  1586. for (i=0; i<cntn; i++)
  1587. args[(*pcd)++] = (short)nths[i];
  1588. }
  1589. /* Interpolate the extrems. */
  1590. cnt1 = 0; cnt2 = 0; cntn = 0; num = 0;
  1591. for (i=0; i<xcnt; i++) {
  1592. /* Skip interpolations. */
  1593. if (extr[i].rp1==UNDEF || extr[i].rp2==UNDEF)
  1594. continue;
  1595. if (extr[i].n==1) {
  1596. if ((cnt1+3)>=MAXIP) {
  1597. pgm[(*pc)++] = op_loopcall;
  1598. args[(*pcd)++] = TTFUN_IP1;
  1599. args[(*pcd)++] = (short)(cnt1/2);
  1600. for (j=0; j<cnt1; j++)
  1601. args[(*pcd)++] = (short)ones[j];
  1602. cnt1 = 0;
  1603. }
  1604. ones[cnt1++] = extr[i].rp1;
  1605. ones[cnt1++] = extr[i].rp2;
  1606. ones[cnt1++] = extr[i].pts[0];
  1607. } else if (extr[i].n==2) {
  1608. if ((cnt2+4)>=MAXIP) {
  1609. pgm[(*pc)++] = op_loopcall;
  1610. args[(*pcd)++] = TTFUN_IP2;
  1611. args[(*pcd)++] = (short)(cnt2/3);
  1612. for (j=0; j<cnt2; j++)
  1613. args[(*pcd)++] = (short)twoes[j];
  1614. cnt2 = 0;
  1615. }
  1616. twoes[cnt2++] = extr[i].rp1;
  1617. twoes[cnt2++] = extr[i].rp2;
  1618. twoes[cnt2++] = extr[i].pts[0];
  1619. twoes[cnt2++] = extr[i].pts[1];
  1620. } else {
  1621. if ((cntn+3+extr[i].n)>=MAXIP) {
  1622. pgm[(*pc)++] = op_loopcall;
  1623. args[(*pcd)++] = TTFUN_IPN;
  1624. args[(*pcd)++] = num;
  1625. for (j=0; j<cntn; j++)
  1626. args[(*pcd)++] = (short)nths[j];
  1627. cntn = 0;
  1628. num = 0;
  1629. }
  1630. nths[cntn++] = extr[i].rp1;
  1631. nths[cntn++] = extr[i].rp2;
  1632. nths[cntn++] = extr[i].n;
  1633. for (j=0; j<extr[i].n; j++) {
  1634. nths[cntn++] = extr[i].pts[j];
  1635. }
  1636. num++;
  1637. }
  1638. }
  1639. if (cnt1) {
  1640. if (cnt1>3) {
  1641. pgm[(*pc)++] = op_loopcall;
  1642. args[(*pcd)++] = TTFUN_IP1;
  1643. args[(*pcd)++] = (short)(cnt1/3);
  1644. } else {
  1645. pgm[(*pc)++] = op_call;
  1646. args[(*pcd)++] = TTFUN_IP1;
  1647. }
  1648. for (i=0; i<cnt1; i++)
  1649. args[(*pcd)++] = (short)ones[i];
  1650. }
  1651. if (cnt2) {
  1652. if (cnt2>4) {
  1653. pgm[(*pc)++] = op_loopcall;
  1654. args[(*pcd)++] = TTFUN_IP2;
  1655. args[(*pcd)++] = (short)(cnt2/4);
  1656. } else {
  1657. pgm[(*pc)++] = op_call;
  1658. args[(*pcd)++] = TTFUN_IP2;
  1659. }
  1660. for (i=0; i<cnt2; i++)
  1661. args[(*pcd)++] = (short)twoes[i];
  1662. }
  1663. if (cntn) {
  1664. if (num>1) {
  1665. pgm[(*pc)++] = op_loopcall;
  1666. args[(*pcd)++] = TTFUN_IPN;
  1667. args[(*pcd)++] = num;
  1668. } else {
  1669. pgm[(*pc)++] = op_call;
  1670. args[(*pcd)++] = TTFUN_IPN;
  1671. }
  1672. for (i=0; i<cntn; i++)
  1673. args[(*pcd)++] = (short)nths[i];
  1674. }
  1675. /*lint +e530 +e644 */
  1676. }
  1677. /***
  1678. ** Function: EmitVerticalStem
  1679. **
  1680. ** Description:
  1681. ** This function generates the code that
  1682. ** will initiate the graphics state of the
  1683. ** TrueType interpreter for the grid fitting
  1684. ** of vertical stems.
  1685. ***/
  1686. void EmitVerticalStems(UBYTE *pgm, short *pc, short *args, short *pcd)
  1687. {
  1688. pgm[(*pc)++] = op_call;
  1689. args[(*pcd)++] = TTFUN_VERTICAL;
  1690. }
  1691. /***
  1692. ** Function: EmitHorizontalStem
  1693. **
  1694. ** Description:
  1695. ** This function generates the code that
  1696. ** will initiate the graphics state of the
  1697. ** TrueType interpreter for the grid fitting
  1698. ** of vertical stems.
  1699. ***/
  1700. void EmitHorizontalStems(UBYTE *pgm, short *pc, short *args, short *pcd)
  1701. {
  1702. pgm[(*pc)++] = op_call;
  1703. args[(*pcd)++] = TTFUN_HORIZONTAL;
  1704. }
  1705. /***
  1706. ** Function: EmitVStem
  1707. **
  1708. ** Description:
  1709. ** This function generates the code that
  1710. ** will create and grid fit points in the
  1711. ** twilight zone, corresponding to a vstem.
  1712. ***/
  1713. errcode EmitVStem(UBYTE *pgm, short *pc,
  1714. short *args, short *pcd,
  1715. struct T1Metrics *t1m,
  1716. const funit width,
  1717. const funit real_side1,
  1718. const funit real_side2,
  1719. const funit side1,
  1720. const funit side2,
  1721. const short rp,
  1722. const enum aligntype align,
  1723. const short ref)
  1724. {
  1725. errcode status = SUCCESS;
  1726. short w_storage;
  1727. if ((w_storage = GetVStemWidth(GetWeight(t1m), width))==NOMEM) {
  1728. SetError(status = NOMEM);
  1729. } else {
  1730. pgm[(*pc)++] = op_call;
  1731. switch (align) {
  1732. case at_centered:
  1733. args[(*pcd)++] = TTFUN_VCENTER;
  1734. args[(*pcd)++] = (short)real_side1;
  1735. args[(*pcd)++] = (short)real_side2;
  1736. args[(*pcd)++] = (short)side1;
  1737. args[(*pcd)++] = (short)side2;
  1738. args[(*pcd)++] = (short)((side1+side2)/2);
  1739. args[(*pcd)++] = rp;
  1740. args[(*pcd)++] = w_storage;
  1741. break;
  1742. case at_relative1:
  1743. args[(*pcd)++] = TTFUN_RELATIVE1V;
  1744. args[(*pcd)++] = (short)real_side1;
  1745. args[(*pcd)++] = (short)real_side2;
  1746. args[(*pcd)++] = (short)side1;
  1747. args[(*pcd)++] = (short)side2;
  1748. args[(*pcd)++] = ref;
  1749. args[(*pcd)++] = rp;
  1750. args[(*pcd)++] = w_storage;
  1751. break;
  1752. case at_relative2:
  1753. args[(*pcd)++] = TTFUN_RELATIVE2V;
  1754. args[(*pcd)++] = (short)real_side1;
  1755. args[(*pcd)++] = (short)real_side2;
  1756. args[(*pcd)++] = (short)side1;
  1757. args[(*pcd)++] = (short)side2;
  1758. args[(*pcd)++] = ref;
  1759. args[(*pcd)++] = rp;
  1760. args[(*pcd)++] = w_storage;
  1761. break;
  1762. case at_side1:
  1763. case at_side2:
  1764. LogError(MSG_WARNING, MSG_ALIGN, NULL);
  1765. break;
  1766. }
  1767. }
  1768. return status;
  1769. }
  1770. /***
  1771. ** Function: EmitHStem
  1772. **
  1773. ** Description:
  1774. ** This function generates the code that
  1775. ** will create and grid fit points in the
  1776. ** twilight zone, corresponding to a hstem.
  1777. ***/
  1778. errcode EmitHStem(UBYTE *pgm, short *pc,
  1779. short *args, short *pcd,
  1780. struct T1Metrics *t1m,
  1781. const funit width,
  1782. const funit side1,
  1783. const funit side2,
  1784. const short rp,
  1785. const enum aligntype align,
  1786. const short ref)
  1787. {
  1788. errcode status = SUCCESS;
  1789. short w_storage;
  1790. if ((w_storage = GetHStemWidth(GetWeight(t1m), width))==NOMEM) {
  1791. SetError(status = NOMEM);
  1792. } else {
  1793. pgm[(*pc)++] = op_call;
  1794. switch (align) {
  1795. case at_side1:
  1796. args[(*pcd)++] = TTFUN_SIDE1;
  1797. args[(*pcd)++] = (short)side1;
  1798. args[(*pcd)++] = (short)side2;
  1799. args[(*pcd)++] = ref;
  1800. args[(*pcd)++] = rp;
  1801. args[(*pcd)++] = w_storage;
  1802. break;
  1803. case at_side2:
  1804. args[(*pcd)++] = TTFUN_SIDE2;
  1805. args[(*pcd)++] = (short)side1;
  1806. args[(*pcd)++] = (short)side2;
  1807. args[(*pcd)++] = ref;
  1808. args[(*pcd)++] = rp;
  1809. args[(*pcd)++] = w_storage;
  1810. break;
  1811. case at_relative1:
  1812. args[(*pcd)++] = TTFUN_RELATIVE1H;
  1813. args[(*pcd)++] = (short)side1;
  1814. args[(*pcd)++] = (short)side2;
  1815. args[(*pcd)++] = ref;
  1816. args[(*pcd)++] = rp;
  1817. args[(*pcd)++] = w_storage;
  1818. break;
  1819. case at_relative2:
  1820. args[(*pcd)++] = TTFUN_RELATIVE2H;
  1821. args[(*pcd)++] = (short)side1;
  1822. args[(*pcd)++] = (short)side2;
  1823. args[(*pcd)++] = ref;
  1824. args[(*pcd)++] = rp;
  1825. args[(*pcd)++] = w_storage;
  1826. break;
  1827. case at_centered:
  1828. default:
  1829. args[(*pcd)++] = TTFUN_HCENTER;
  1830. args[(*pcd)++] = (short)side1;
  1831. args[(*pcd)++] = (short)side2;
  1832. args[(*pcd)++] = (short)((side1+side2)/2);
  1833. args[(*pcd)++] = rp;
  1834. args[(*pcd)++] = w_storage;
  1835. break;
  1836. }
  1837. }
  1838. return status;
  1839. }
  1840. /***
  1841. ** Function: FamilyCutIn
  1842. **
  1843. ** Description:
  1844. ** This function generates a branch in the
  1845. ** pre-program.
  1846. ***/
  1847. USHORT FamilyCutIn(UBYTE *prep,
  1848. USHORT tp,
  1849. const short cis)
  1850. {
  1851. prep[tp++] = op_mppem;
  1852. if (cis<256) {
  1853. prep[tp++] = op_pushb1; prep[tp++] = (UBYTE)cis;
  1854. } else {
  1855. prep[tp++] = op_pushw1;
  1856. prep[tp++] = HIBYTE(cis);
  1857. prep[tp++] = LOBYTE(cis);
  1858. }
  1859. prep[tp++] = op_lt;
  1860. prep[tp++] = op_if;
  1861. return tp;
  1862. }
  1863. /***
  1864. ** Function: SetProjection
  1865. **
  1866. ** Description:
  1867. ** This function generates the TrueType code that
  1868. ** changes the projection vector in oblique typefaces.
  1869. ***/
  1870. void SetProjection(UBYTE *pgm, short *pc,
  1871. short *args, short *pcd,
  1872. const funit x, const funit y)
  1873. {
  1874. pgm[(*pc)++] = op_call;
  1875. args[(*pcd)++] = TTFUN_OBLIQUE;
  1876. args[(*pcd)++] = (short)y;
  1877. args[(*pcd)++] = (short)x;
  1878. }
  1879. /***
  1880. ** Function: AssembleArgs
  1881. **
  1882. ** Description:
  1883. ** This function takes a sequence of arguments and
  1884. ** assembles them into a sequence of PUSHB1[], PUSHW1[],
  1885. ** NPUSHB[] and NPUSHW[] instructions.
  1886. ***/
  1887. void AssembleArgs(short *args, const short pcd, UBYTE *is, short *cnt)
  1888. {
  1889. short bytes;
  1890. short i,j;
  1891. if ((args[pcd-1] <= UCHAR_MAX && args[pcd-1]>=0)) {
  1892. bytes = 1;
  1893. } else {
  1894. bytes = 0;
  1895. }
  1896. for (i=0, j=0; j<pcd; i++) {
  1897. /* Pack a sequence of bytes? */
  1898. if (bytes) {
  1899. if ((i-j)>=255 || i==pcd ||
  1900. (args[pcd-i-1]>UCHAR_MAX || args[pcd-i-1]<0)) {
  1901. bytes = 0;
  1902. if ((i-j)<=8) {
  1903. is[(*cnt)++] = (UBYTE)(op_pushb1 + (i-j) - 1);
  1904. } else {
  1905. is[(*cnt)++] = op_npushb;
  1906. is[(*cnt)++] = (UBYTE)(i-j);
  1907. }
  1908. while (j<i)
  1909. is[(*cnt)++] = (UBYTE)args[pcd-1-j++];
  1910. }
  1911. /* Pack a sequence of words? */
  1912. } else {
  1913. if ((i-j)>=255 || i==pcd ||
  1914. (args[pcd-i-1]<=UCHAR_MAX && args[pcd-i-1]>=0)) {
  1915. bytes = 1;
  1916. if ((i-j)<=8) {
  1917. is[(*cnt)++] = (UBYTE)(op_pushw1 + (i-j) - 1);
  1918. } else {
  1919. is[(*cnt)++] = op_npushw;
  1920. is[(*cnt)++] = (UBYTE)(i-j);
  1921. }
  1922. while (j<i) {
  1923. is[(*cnt)++] = HIBYTE(args[pcd-j-1]);
  1924. is[(*cnt)++] = LOBYTE(args[pcd-j-1]);
  1925. j++;
  1926. }
  1927. }
  1928. }
  1929. }
  1930. }