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.

1119 lines
35 KiB

  1. /***
  2. **
  3. ** Module: Trans
  4. **
  5. ** Description:
  6. ** This is a module of the T1 to TT font converter. The module
  7. ** contains functions that will convert T1 specific data into
  8. ** corresponding TT data, such as hints and font metrics.
  9. **
  10. ** Author: Michael Jansson
  11. **
  12. ** Created: 5/28/93
  13. **
  14. ***/
  15. /**** INCLUDES */
  16. /* General types and definitions. */
  17. #include <string.h>
  18. /* Special types and definitions. */
  19. #include "titott.h"
  20. #include "types.h"
  21. #include "safemem.h"
  22. #include "trig.h"
  23. #include "metrics.h"
  24. #include "encoding.h"
  25. #include "builder.h"
  26. #include "t1msg.h"
  27. /* Module dependent types and prototypes. */
  28. #include "trans.h"
  29. #include "hints.h"
  30. /***** CONSTANTS */
  31. /* PitchAndFamily pitch values (low 4 bits) */
  32. #define DEFAULT_PITCH 0x00
  33. #define FIXED_PITCH 0x01
  34. #define VARIABLE_PITCH 0x02
  35. /* PitchAndFamily family values (high 4 bits) */
  36. #define FF_DONTCARE 0x00
  37. #define FF_ROMAN 0x10
  38. #define FF_SWISS 0x20
  39. #define FF_MODERN 0x30
  40. #define FF_SCRIPT 0x40
  41. #define FF_DECORATIVE 0x50
  42. #define SWISS_LEADING 0x21
  43. #define ROMAN_LEADING 0x11
  44. #define NOCARE_PANOSE 0
  45. #define NO_PANOSE 1
  46. #define COVE_PANOSE 2
  47. #define TEXT_PANOSE 2
  48. #define DECORATIVE_PANOSE 4
  49. #define SCRIPT_PANOSE 3
  50. #define SANS_PANOSE 11
  51. #define FIXED_PANOSE 9
  52. #define BUFMARG 64
  53. #define CLIMIT 8
  54. #define CLIMIT2 4
  55. #define SUBDIVIDE 0
  56. #define CONVERT 1
  57. #define FW_THIN 100
  58. #define FW_EXTRALIGHT 200
  59. #define FW_LIGHT 300
  60. #define FW_NORMAL 400
  61. #define FW_MEDIUM 500
  62. #define FW_SEMIBOLD 600
  63. #define FW_BOLD 700
  64. #define FW_BLACK 900
  65. #define FWIDTH_ULTRA_CONDENSED 1
  66. #define FWIDTH_EXTRA_CONDENSED 2
  67. #define FWIDTH_CONDENSED 3
  68. #define FWIDTH_SEMI_CONDENSED 4
  69. #define FWIDTH_NORMAL 5
  70. #define FWIDTH_SEMI_EXPANDED 6
  71. #define FWIDTH_EXPANDED 7
  72. #define FWIDTH_EXTRA_EXPANDED 8
  73. #define FWIDTH_ULTRA_EXPANDED 9
  74. #define MAC_ITALIC 0x01
  75. #define MAC_BOLD 0x02
  76. #define FS_ITALIC 0x01
  77. #define FS_BOLD 0x20
  78. #define FS_NORMAL 0x40
  79. #define CVTSIZE 5
  80. /***** LOCAL TYPES */
  81. /* None */
  82. /***** MACROS */
  83. #define ATMSCALE(v) (((v)*31)/32)
  84. #define IP(v,x1,x2,x1p,x2p) /*lint -e776 */(short)((long)(v-x1)*(long)(x2p-x1p)/(long)(x2-x1)+(long)x1p)/*lint +e776*/
  85. #define ADDCVT(val) ttm->cvt[ttm->cvt_cnt++] = (short)(val)
  86. #define SGN(v) ((v)>0 ? 1 : -1)
  87. #define DIR(v,w) (char)((ABS((v)-(w))<16) ? 0 : SGN((w) - (v)))
  88. /***** PROTOTYPES */
  89. static USHORT SplitSpline(Point *pts, ULONG *onoff,
  90. int i, USHORT length,
  91. const funit x0, const funit y0,
  92. const funit x1, const funit y1,
  93. const funit x2, const funit y2,
  94. const funit x3, const funit y3,
  95. const int delta);
  96. /***** STATIC FUNCTIONS */
  97. /***
  98. ** Function: LookupComposite
  99. **
  100. ** Description:
  101. **
  102. ***/
  103. static struct encoding *LookupComposite(struct Composite *comp, char *name)
  104. {
  105. while (comp) {
  106. if (comp->oenc && !strcmp(LookupCharName(comp->oenc), name))
  107. return comp->oenc;
  108. comp=comp->next;
  109. }
  110. return NULL;
  111. }
  112. /***
  113. ** Function: norm
  114. **
  115. ** Description:
  116. ** Normalize an angle so that it falls within the
  117. ** range ~[-pi, pi]
  118. ***/
  119. static int norm(int a)
  120. {
  121. if (a>PI)
  122. a -= 2*PI;
  123. if (a<-PI)
  124. a += 2*PI;
  125. return ABS(a)/16;
  126. }
  127. /***
  128. ** Function: CompareCurves
  129. **
  130. ** Description:
  131. ** Make a estimate of the error between a cubic
  132. ** and a quadric curve, given four control points,
  133. ** and suggest an action (sub-division or convertion).
  134. ***/
  135. static boolean FASTCALL CompareCurves(const funit x0, const funit y0,
  136. const funit x1, const funit y1,
  137. const funit x2, const funit y2,
  138. const funit x3, const funit y3,
  139. const funit nx, const funit ny,
  140. const int delta)
  141. {
  142. int a, b;
  143. if ((ABS(ny-y0)>CLIMIT || ABS(nx-x0)>CLIMIT) &&
  144. (ABS(ny-y3)>CLIMIT || ABS(nx-x3)>CLIMIT)) {
  145. if (y0!=y1 || x0!=x1)
  146. a = norm(Atan2(ny-y0, nx-x0) - Atan2(y1-y0, x1-x0))
  147. * (ABS(ny-y0) + ABS(nx-x0));
  148. else if (y0!=y2 || x2!=x0)
  149. a = norm(Atan2(ny-y0, nx-x0) - Atan2(y2-y0, x2-x0))
  150. * (ABS(ny-y0) + ABS(nx-x0));
  151. else
  152. a = 0;
  153. if (a>=delta)
  154. return SUBDIVIDE;
  155. if (y2!=y3 || x2!=x3)
  156. b = norm(Atan2(y3-ny, x3-nx) - Atan2(y3-y2, x3-x2))
  157. * (ABS(ny-y0) + ABS(nx-x0));
  158. else if (y1!=y3 || x1!=x3)
  159. b = norm(Atan2(y3-ny, x3-nx) - Atan2(y3-y1, x3-x1))
  160. * (ABS(ny-y0) + ABS(nx-x0));
  161. else
  162. b = 0;
  163. if (b>=delta) /* angle too big. */
  164. return SUBDIVIDE;
  165. }
  166. return CONVERT;
  167. }
  168. /***
  169. ** Function: ConvertSpline
  170. **
  171. ** Description:
  172. ** This function adds a spline to the current contour, by first
  173. ** converting it from a cubic to a quadric spline.
  174. ***/
  175. static USHORT ConvertSpline(Point *pts, ULONG *onoff,
  176. USHORT length, int i,
  177. const funit x0, const funit y0,
  178. const funit x1, const funit y1,
  179. const funit x2, const funit y2,
  180. const funit x3, const funit y3,
  181. const int delta)
  182. {
  183. funit nx, ny;
  184. int oi = i;
  185. USHORT n = 0;
  186. ny = (funit)(((-y0+y1+y2+((y1+y2)<<1)-y3 + 4002)/4) - (short)1000);
  187. nx = (funit)(((-x0+x1+x2+((x1+x2)<<1)-x3 + 4002)/4) - (short)1000);
  188. if (CompareCurves(x0, y0,
  189. x1, y1,
  190. x2, y2,
  191. x3, y3,
  192. nx, ny, delta)==SUBDIVIDE) {
  193. n = SplitSpline(pts, onoff, i, length,
  194. x0, y0, x1, y1, x2, y2, x3, y3, delta);
  195. } else /* CONVERT */ {
  196. if (i>1 && !OnCurve(onoff, i-2) &&
  197. (short)(pts[i-1].x >= pts[i-2].x) != (short)(pts[i-1].x >= nx) &&
  198. (short)(pts[i-1].y >= pts[i-2].y) != (short)(pts[i-1].y >= ny) &&
  199. (short)(pts[i-1].x > pts[i-2].x) != (short)(pts[i-1].x > nx) &&
  200. (short)(pts[i-1].y > pts[i-2].y) != (short)(pts[i-1].y > ny) &&
  201. ABS(pts[i-1].x - (nx+pts[i-2].x)/2)<CLIMIT2 &&
  202. ABS(pts[i-1].y - (ny+pts[i-2].y)/2)<CLIMIT2) {
  203. }
  204. SetOffPoint(onoff, i);
  205. pts[i].y = ny;
  206. pts[i].x = nx;
  207. i++;
  208. SetOnPoint(onoff, i);
  209. pts[i].y = y3;
  210. pts[i].x = x3;
  211. i++;
  212. n = (USHORT)(i-oi);
  213. }
  214. return n;
  215. }
  216. /***
  217. ** Function: SplitSpline
  218. **
  219. ** Description:
  220. ** This function converts a cubic spline by first
  221. ** creating two new cubic splines, using de Casteljau's
  222. ** algorithm, and then adding the two new splines to the
  223. ** current path.
  224. ***/
  225. static USHORT SplitSpline(Point *pts, ULONG *onoff,
  226. int i, USHORT length,
  227. const funit x0, const funit y0,
  228. const funit x1, const funit y1,
  229. const funit x2, const funit y2,
  230. const funit x3, const funit y3,
  231. const int delta)
  232. {
  233. funit xt, yt;
  234. funit nx1, ny1;
  235. funit nx2, ny2;
  236. funit nx3, ny3;
  237. funit nx4, ny4;
  238. funit nx5, ny5;
  239. USHORT cnt;
  240. xt = (funit)(((x1+x2+8001)/2)-4000);
  241. yt = (funit)(((y1+y2+8001)/2)-4000);
  242. nx1 = (funit)(((x0+x1+8001)/2)-4000);
  243. ny1 = (funit)(((y0+y1+8001)/2)-4000);
  244. nx2 = (funit)(((nx1+xt+8001)/2)-4000);
  245. ny2 = (funit)(((ny1+yt+8001)/2)-4000);
  246. nx5 = (funit)(((x2+x3+8001)/2)-4000);
  247. ny5 = (funit)(((y2+y3+8001)/2)-4000);
  248. nx4 = (funit)(((nx5+xt+8001)/2)-4000);
  249. ny4 = (funit)(((ny5+yt+8001)/2)-4000);
  250. nx3 = (funit)(((nx2+nx4+8001)/2)-4000);
  251. ny3 = (funit)(((ny2+ny4+8001)/2)-4000);
  252. cnt = ConvertSpline(pts, onoff, length, i,
  253. x0, y0,
  254. (funit)nx1, (funit)ny1,
  255. (funit)nx2, (funit)ny2,
  256. (funit)nx3, (funit)ny3,
  257. delta);
  258. cnt = (USHORT)(cnt + ConvertSpline(pts, onoff, length, i+cnt,
  259. (funit)nx3, (funit)ny3,
  260. (funit)nx4, (funit)ny4,
  261. (funit)nx5, (funit)ny5,
  262. x3, y3,
  263. delta));
  264. return cnt;
  265. }
  266. /***
  267. ** Function: FreeOutline
  268. **
  269. ** Description:
  270. ** This function frees the memory allocated for one
  271. ** contour.
  272. **
  273. ***/
  274. static void FreeOutline(Outline *path)
  275. {
  276. Outline *tmp;
  277. while (path) {
  278. tmp = path;
  279. path=path->next;
  280. Free(tmp->pts);
  281. Free(tmp->onoff);
  282. Free(tmp);
  283. }
  284. }
  285. /***
  286. ** Function: ConvertOutline
  287. **
  288. ** Description:
  289. ** This function converts an outline by replacing the
  290. ** cubic splines with quadric splines, and by scaling the
  291. ** coordinates to the desired em-height.
  292. **
  293. ***/
  294. static errcode ConvertOutline(const struct T1Metrics *t1m,
  295. Outline *src, Outline **dst,
  296. const int delta,
  297. short *sideboard)
  298. {
  299. errcode status = SUCCESS;
  300. f16d16 *fmatrix;
  301. Outline *path;
  302. ULONG *onoff = NULL;
  303. Point *pts = NULL;
  304. USHORT count;
  305. USHORT i,j,n;
  306. USHORT tot = 0;
  307. USHORT t1tot = 0;
  308. /* Get the T1 font transformation matrix. */
  309. fmatrix = GetFontMatrix(t1m);
  310. while (src) {
  311. /* Skip paths with less than three points. */
  312. if (src->count<3) {
  313. t1tot = (USHORT)(t1tot + src->count);
  314. src = src->next;
  315. continue;
  316. }
  317. /* Allocate the needed resources */
  318. count = (USHORT)((src->count+BUFMARG)&~0x0f);
  319. path = Malloc(sizeof(Outline));
  320. pts = Malloc(count*sizeof(Point));
  321. onoff = Malloc(ONOFFSIZE(count));
  322. if (path==NULL || pts==NULL || onoff==NULL) {
  323. if (path)
  324. Free(path);
  325. if (pts)
  326. Free(pts);
  327. if (onoff)
  328. Free(onoff);
  329. FreeOutline((*dst));
  330. (*dst) = NULL;
  331. SetError(status = NOMEM);
  332. break;
  333. }
  334. memset(onoff, '\0', ONOFFSIZE(count));
  335. /* Convert the splines. */ /*lint -e771 */
  336. i=0;
  337. j=0;
  338. while (i<src->count) {
  339. char prev = DIR(src->pts[(i-2+src->count)%src->count].y,
  340. src->pts[(i-1+src->count)%src->count].y);
  341. char this = DIR(src->pts[(i-1+src->count)%src->count].y,
  342. src->pts[i].y);
  343. /* Double the local extremas so that diag-cntrl will work. */
  344. if (prev && this && prev!=this)
  345. pts[j++] = src->pts[(i-1+src->count)%src->count];
  346. if (OnCurve(src->onoff, i)) {
  347. pts[j++] = src->pts[i++];
  348. } else {
  349. /* pts[j] = pts[j-1]; j++; */
  350. n = ConvertSpline(pts, onoff, count, (int)j,
  351. src->pts[i-1].x, src->pts[i-1].y,
  352. src->pts[i-0].x, src->pts[i-0].y,
  353. src->pts[i+1].x, src->pts[i+1].y,
  354. src->pts[i+2].x, src->pts[i+2].y,
  355. delta);
  356. /* Enforce horizontal and vertical tangents. */
  357. if (OnCurve(onoff, j-1)) {
  358. if (src->pts[i-1].x==src->pts[i-0].x)
  359. pts[j].x = (funit)((pts[j].x + pts[j-1].x)/2);
  360. if (src->pts[i-1].y==src->pts[i-0].y)
  361. pts[j].y = (funit)((pts[j].y + pts[j-1].y)/2);
  362. }
  363. if (src->pts[i+1].x==src->pts[i+2].x)
  364. pts[j+n-2].x = (funit)((pts[j+n-1].x + pts[j+n-2].x)/2);
  365. if (src->pts[i+1].y==src->pts[i+2].y)
  366. pts[j+n-2].y = (funit)((pts[j+n-2].y + pts[j+n-1].y)/2);
  367. j = (USHORT)(j + n);
  368. i += 3;
  369. }
  370. /* Both a line and a curve end with an on-curve point. */
  371. sideboard[t1tot+i-1] = (short)(j-1+tot);
  372. /* Extend the pts/onoff arrays. */
  373. if (j+BUFMARG/2>=count) {
  374. Point *newpts = NULL;
  375. ULONG *newonoff = NULL;
  376. count += BUFMARG;
  377. newpts = Realloc(pts, count*sizeof(Point));
  378. newonoff = Realloc(onoff, ONOFFSIZE(count));
  379. if (newpts==NULL || newonoff==NULL) {
  380. if (newonoff)
  381. Free(newonoff);
  382. if (newpts)
  383. Free(newpts);
  384. /*lint -e644 */
  385. if (onoff)
  386. Free(onoff);
  387. if (pts)
  388. Free(pts);
  389. /*lint +e644 */
  390. FreeOutline((*dst));
  391. (*dst) = NULL;
  392. SetError(status=NOMEM);
  393. break;
  394. }
  395. pts = newpts;
  396. onoff = newonoff;
  397. }
  398. }
  399. if (status!=SUCCESS)
  400. break;
  401. /* Scale the points. */
  402. TransAllPoints(t1m, pts, j, fmatrix);
  403. t1tot = (USHORT)(t1tot + src->count);
  404. src = src->next;
  405. (*dst) = path;
  406. path->next = NULL;
  407. path->pts = pts;
  408. path->onoff = onoff;
  409. path->count = (USHORT)j; /*lint +e771 */
  410. dst = &(path->next);
  411. tot = (USHORT)(tot + j);
  412. }
  413. return status;
  414. }
  415. #ifdef MSDOS
  416. #pragma auto_inline(off)
  417. #endif
  418. static long Mul2(long a, long b, long c, long d)
  419. {
  420. return a*b+c*d;
  421. }
  422. #ifdef MSDOS
  423. #pragma auto_inline(on)
  424. #endif
  425. /***** FUNCTIONS */
  426. /***
  427. ** Function: TransAllPoints
  428. **
  429. ** Description:
  430. ** Translate a coordinate according to a transformation matrix.
  431. ***/
  432. void FASTCALL TransAllPoints(const struct T1Metrics *t1m,
  433. Point *pts,
  434. const USHORT cnt,
  435. const f16d16 *fmatrix)
  436. {
  437. if (fmatrix==NULL) {
  438. register Point *p;
  439. register int i;
  440. i = cnt;
  441. p = pts;
  442. while (i--) {
  443. p->x = (funit)((p->x<<1)+(((p->x<<1)+
  444. p->x+(p->x/16)+
  445. 8224)/64) - 128);
  446. p++;
  447. }
  448. i = cnt;
  449. p = pts;
  450. while (i--) {
  451. p->y = (funit)((p->y<<1)+(((p->y<<1)+
  452. p->y+
  453. (p->y/16)+
  454. 8224)/64) - 128);
  455. p++;
  456. }
  457. } else {
  458. Point *p;
  459. int i;
  460. long u,v;
  461. i = cnt;
  462. p = pts;
  463. while (i--) {
  464. v = (GetUPEM(t1m) * (Mul2(fmatrix[0], (long)p->x,
  465. fmatrix[2], (long)p->y) +
  466. fmatrix[4]) + F16D16HALF) / 524288L;
  467. u = (GetUPEM(t1m) * (Mul2(fmatrix[1], (long)p->x,
  468. fmatrix[3], (long)p->y) +
  469. fmatrix[5]) + F16D16HALF) / 524288L;
  470. p->x = (funit)v;
  471. p->y = (funit)u;
  472. p++;
  473. }
  474. }
  475. }
  476. /***
  477. ** Function: TransX
  478. **
  479. ** Description:
  480. ** Translate a horizontal coordinate according to a transformation matrix.
  481. ***/
  482. funit FASTCALL TransX(const struct T1Metrics *t1m, const funit x)
  483. {
  484. f16d16 *fmatrix = GetFontMatrix(t1m);
  485. funit pos;
  486. if (fmatrix) {
  487. pos = (funit)((GetUPEM(t1m)* ATMSCALE(fmatrix[0] * x) +
  488. F16D16HALF) / F16D16BASE);
  489. } else {
  490. pos = (funit)(((int)x<<1)-((((int)x+((int)x/64)+8224)/64) - 128));
  491. }
  492. return pos;
  493. }
  494. /***
  495. ** Function: TransY
  496. **
  497. ** Description:
  498. ** Translate a vertical coordinate according to a transformation matrix.
  499. ***/
  500. funit FASTCALL TransY(const struct T1Metrics *t1m, const funit y)
  501. {
  502. f16d16 *fmatrix = GetFontMatrix(t1m);
  503. funit pos;
  504. if (fmatrix) {
  505. pos = (funit)((GetUPEM(t1m)*fmatrix[3] * y +
  506. F16D16HALF) / F16D16BASE);
  507. } else {
  508. pos = (funit)(((int)y<<1)+((((int)y<<1)+
  509. (int)y+
  510. ((int)y/16)+
  511. 8224)/64) - 128);
  512. }
  513. return pos;
  514. }
  515. /***
  516. ** Function: ConvertGlyph
  517. **
  518. ** Description:
  519. ** This function convertes the data associated to a T1 font glyph
  520. ** into the corresponding data used in a TT font glyph.
  521. ***/
  522. errcode FASTCALL ConvertGlyph(struct T1Metrics *t1m,
  523. const struct T1Glyph *t1glyph,
  524. struct TTGlyph **ttglyph,
  525. const int delta)
  526. {
  527. errcode status = SUCCESS;
  528. struct encoding *code;
  529. if ((code = LookupPSName(CurrentEncoding(t1m),
  530. EncodingSize(t1m),
  531. t1glyph->name))==NULL &&
  532. (code = LookupComposite(Composites(t1m), t1glyph->name))==NULL &&
  533. strcmp(t1glyph->name, ".notdef")) {
  534. LogError(MSG_INFO, MSG_BADENC, t1glyph->name);
  535. status = SUCCESS;
  536. } else {
  537. if (((*ttglyph) = Malloc(sizeof(struct TTGlyph)))==NULL) {
  538. SetError(status = NOMEM);
  539. } else {
  540. short *sideboard = NULL;
  541. Outline *path;
  542. USHORT tot;
  543. memset((*ttglyph), '\0', sizeof(struct TTGlyph));
  544. if (t1glyph->width.y!=0) {
  545. LogError(MSG_WARNING, MSG_BADAW, NULL);
  546. }
  547. (*ttglyph)->aw = TransY(t1m, t1glyph->width.x);
  548. (*ttglyph)->lsb = TransY(t1m, t1glyph->lsb.x);
  549. (*ttglyph)->code = code;
  550. (*ttglyph)->num = 0;
  551. (*ttglyph)->twilights = 0;
  552. /* Initiate the side board. */
  553. for (path=t1glyph->paths, tot=0; path; path=path->next)
  554. tot = (USHORT)(tot + path->count);
  555. if (tot && (sideboard = Malloc((unsigned)tot*sizeof(short)))==NULL) {
  556. SetError(status=NOMEM);
  557. } else if ((status = ConvertOutline(t1m, t1glyph->paths,
  558. &((*ttglyph)->paths),
  559. delta,
  560. sideboard))==SUCCESS)
  561. status = ConvertHints(t1m,
  562. &t1glyph->hints,
  563. t1glyph->paths,
  564. (*ttglyph)->paths,
  565. sideboard,
  566. &(*ttglyph)->hints,
  567. &(*ttglyph)->num,
  568. &(*ttglyph)->stack,
  569. &(*ttglyph)->twilights);
  570. if (sideboard)
  571. Free(sideboard);
  572. /* Pick default std widths. */
  573. if (t1glyph->name[0]=='l' && t1glyph->name[1]=='\0') {
  574. if (GetStdVW(t1m)==0 && t1glyph->hints.vstems)
  575. SetDefStdVW(t1m, t1glyph->hints.vstems->width);
  576. }
  577. if (t1glyph->name[0]=='z' && t1glyph->name[1]=='\0') {
  578. if (GetStdHW(t1m)==0) {
  579. if (t1glyph->hints.hstems && t1glyph->hints.hstems->width)
  580. SetDefStdHW(t1m, t1glyph->hints.hstems->width);
  581. else if (t1glyph->hints.vstems && t1glyph->hints.vstems->width)
  582. SetDefStdHW(t1m, t1glyph->hints.vstems->width);
  583. }
  584. }
  585. }
  586. }
  587. return status;
  588. }
  589. /***
  590. ** Function: ConvertComposite
  591. **
  592. ** Description:
  593. ** This function convertes the data associated to a T1 font seac glyph
  594. ** into the corresponding data used in a TT font composite glyph.
  595. **
  596. ***/
  597. errcode FASTCALL ConvertComposite(struct T1Metrics *t1m,
  598. const struct Composite *comp,
  599. struct TTComposite *ttcomp)
  600. {
  601. Point pt;
  602. pt.x = comp->adx;
  603. pt.y = comp->ady;
  604. TransAllPoints(t1m, &pt, 1, GetFontMatrix(t1m));
  605. ttcomp->dx = pt.x + (pt.x - TransX(t1m, comp->adx));
  606. ttcomp->dy = pt.y;
  607. ttcomp->aw = TransY(t1m, comp->aw);
  608. ttcomp->lsb = TransY(t1m, comp->asbx);
  609. ttcomp->aenc = LookupPSName(CurrentEncoding(t1m),
  610. EncodingSize(t1m), comp->achar);
  611. ttcomp->benc = LookupPSName(CurrentEncoding(t1m),
  612. EncodingSize(t1m), comp->bchar);
  613. if ((ttcomp->cenc = LookupPSName(CurrentEncoding(t1m),
  614. EncodingSize(t1m), comp->cchar))==NULL) {
  615. LogError(MSG_INFO, MSG_BADENC, comp->cchar);
  616. }
  617. ttcomp->oenc = comp->oenc;
  618. if (ttcomp->aenc && ttcomp->benc)
  619. return SUCCESS;
  620. return SKIP;
  621. }
  622. /***
  623. ** Function: ConvertMetrics
  624. **
  625. ** Description:
  626. **
  627. ***/
  628. errcode FASTCALL ConvertMetrics(const struct TTHandle *tt,
  629. struct T1Metrics *t1m,
  630. struct TTMetrics *ttm,
  631. const char *tag)
  632. {
  633. const AlignmentControl *align;
  634. const Blues *blues;
  635. USHORT prep_size;
  636. UBYTE *prep = NULL;
  637. errcode status = SUCCESS;
  638. Point bbox[2];
  639. funit em;
  640. funit PostAsc;
  641. USHORT i, j;
  642. ttm->Encoding = CurrentEncoding(t1m);
  643. ttm->encSize = EncodingSize(t1m);
  644. ttm->version.ver = t1m->version.ver;
  645. ttm->version.rev = t1m->version.rev;
  646. if ((ttm->verstr = Malloc(strlen(tag)+4+1+4+1))==NULL) {
  647. SetError(status = NOMEM);
  648. } else {
  649. strcpy(ttm->verstr, tag);
  650. (void)_itoa((int)ttm->version.ver, &ttm->verstr[strlen(ttm->verstr)], 4);
  651. strcat(ttm->verstr, ".");
  652. (void)_itoa((int)ttm->version.rev, &ttm->verstr[strlen(ttm->verstr)], 4);
  653. ttm->created.a = 0;
  654. ttm->created.b = 0;
  655. ttm->family = t1m->family;
  656. ttm->copyright = t1m->copyright;
  657. ttm->name = t1m->name;
  658. ttm->id = t1m->id;
  659. ttm->notice = t1m->notice;
  660. ttm->fullname = t1m->fullname;
  661. ttm->weight = t1m->weight;
  662. ttm->angle = t1m->angle;
  663. ttm->underline = TransY(t1m, t1m->underline);
  664. ttm->uthick = TransY(t1m, t1m->uthick);
  665. ttm->usWidthClass = (USHORT)(strstr(t1m->fullname, "Ultra-condensed")
  666. ? FWIDTH_ULTRA_CONDENSED :
  667. ((strstr(t1m->fullname, "Extra-condensed") ? FWIDTH_EXTRA_CONDENSED :
  668. ((strstr(t1m->fullname, "Condensed") ? FWIDTH_CONDENSED :
  669. ((strstr(t1m->fullname, "Semi-condensed") ? FWIDTH_SEMI_CONDENSED :
  670. ((strstr(t1m->fullname, "Semi-expanded")
  671. ? FWIDTH_SEMI_EXPANDED :
  672. ((strstr(t1m->fullname, "Expanded")
  673. ? FWIDTH_EXPANDED :
  674. ((strstr(t1m->fullname, "Extra-expanded")
  675. ? FWIDTH_EXTRA_EXPANDED :
  676. ((strstr(t1m->fullname, "Ultra-expanded")
  677. ? FWIDTH_ULTRA_EXPANDED :
  678. FWIDTH_NORMAL)))))))))))))));
  679. /* Window based metrics. */
  680. // ps driver does not compute asc and desc based on the
  681. // windows charset. So, we will not do it either. We will
  682. // also use the all glyhs supported in the font.
  683. // Ps driver acutally trusts the values found in .pfm file.
  684. // These values, according to afm->pfm converter code, are computed
  685. // over all glyphs. However, some vendors ship buggy pfm's with
  686. // zero ascenders or negative descenders. If we took these values
  687. // literally, as ps driver does, the true type driver would
  688. // shave off portions of glyphs and the conversion would appear broken.
  689. // Pcl printing and screen output would be totally broken.
  690. // Turns out that for these buggy fonts ATM on win31 also
  691. // corrects the value from .pfm files for screen and pcl printer.
  692. // [bodind]
  693. // total bbox: [bodind], replaced WindowsBBox function:
  694. GlobalBBox(tt, bbox);
  695. ttm->winAscender = ABS(bbox[1].y);
  696. ttm->winDescender = ABS(bbox[0].y);
  697. ttm->panose[0] = NOCARE_PANOSE;
  698. ttm->panose[1] = NOCARE_PANOSE;
  699. ttm->panose[2] = NOCARE_PANOSE;
  700. ttm->panose[3] = NOCARE_PANOSE;
  701. ttm->panose[4] = NOCARE_PANOSE;
  702. ttm->panose[5] = NOCARE_PANOSE;
  703. ttm->panose[6] = NOCARE_PANOSE;
  704. ttm->panose[6] = NOCARE_PANOSE;
  705. ttm->panose[7] = NOCARE_PANOSE;
  706. ttm->panose[8] = NOCARE_PANOSE;
  707. ttm->panose[9] = NOCARE_PANOSE;
  708. /* Fixed pitch fonts are not given a panose by ATM. */
  709. if (!(t1m->fixedPitch)) {
  710. switch (t1m->pitchfam & 0xf0) {
  711. case FF_DECORATIVE:
  712. ttm->panose[0] = (UBYTE)DECORATIVE_PANOSE;
  713. ttm->panose[1] = (UBYTE)NO_PANOSE;
  714. break;
  715. case FF_ROMAN:
  716. ttm->panose[0] = (UBYTE)TEXT_PANOSE;
  717. ttm->panose[1] = (UBYTE)COVE_PANOSE;
  718. break;
  719. case FF_SWISS:
  720. ttm->panose[0] = (UBYTE)TEXT_PANOSE;
  721. ttm->panose[1] = (UBYTE)SANS_PANOSE;
  722. break;
  723. case FF_SCRIPT:
  724. ttm->panose[0] = (UBYTE)SCRIPT_PANOSE;
  725. ttm->panose[1] = (UBYTE)SANS_PANOSE;
  726. break;
  727. case FF_MODERN:
  728. ttm->panose[0] = (UBYTE)TEXT_PANOSE;
  729. ttm->panose[1] = (UBYTE)SANS_PANOSE;
  730. break;
  731. }
  732. }
  733. ttm->isFixPitched = t1m->fixedPitch;
  734. ttm->panose[2] = (UBYTE)((t1m->tmweight - 500) * 12 / 900 + 6);
  735. /* Mac based metrics. */
  736. MacBBox(tt, bbox);
  737. ttm->macLinegap = TransY(t1m, (funit)(t1m->extLeading +
  738. (ttm->winAscender +
  739. ttm->winDescender) -
  740. (bbox[1].y-bbox[0].y)));
  741. /* Typographical metrics. */
  742. ttm->emheight = GetUPEM(t1m);
  743. if (t1m->flags==DEFAULTMETRICS) {
  744. ttm->usWeightClass = (USHORT)(strstr(t1m->fullname, "Thin") ? FW_THIN :
  745. ((strstr(t1m->fullname, "light") ? FW_EXTRALIGHT :
  746. ((strstr(t1m->fullname, "Light") ? FW_LIGHT :
  747. ((strstr(t1m->fullname, "Medium") ? FW_MEDIUM :
  748. ((strstr(t1m->fullname, "emi-bold") ? FW_SEMIBOLD :
  749. ((strstr(t1m->fullname, "Bold") ? FW_BOLD :
  750. ((strstr(t1m->fullname, "Black") ? FW_BLACK :
  751. FW_NORMAL)))))))))))));
  752. ttm->macStyle = (USHORT)(((ttm->usWeightClass>FW_MEDIUM)?MAC_BOLD : 0) |
  753. ((ttm->angle != 0) ? MAC_ITALIC : 0));
  754. ttm->fsSelection = (USHORT)(((ttm->angle != 0) ? FS_ITALIC : 0) |
  755. ((ttm->usWeightClass > FW_MEDIUM) ? FS_BOLD : 0) |
  756. ((ttm->usWeightClass==FW_NORMAL)
  757. ? FS_NORMAL : 0));
  758. ttm->typAscender = TypographicalAscender(tt);
  759. ttm->typDescender = TypographicalDescender(tt);
  760. em = ttm->typAscender - ttm->typDescender;
  761. ttm->superoff.y = (funit)(em / 2);
  762. ttm->superoff.x = 0;
  763. ttm->supersize.y = (funit)(em * 2 / 3);
  764. ttm->supersize.x = (funit)(em * 3 / 4);
  765. ttm->suboff.y = (funit)(em / 5);
  766. ttm->suboff.x = 0;
  767. ttm->subsize.y = (funit)(em * 2 / 3);
  768. ttm->subsize.x = (funit)(em * 3 / 4);
  769. ttm->strikeoff = (funit)(ttm->typAscender / 2);
  770. ttm->strikesize = (funit)(ttm->typAscender / 10);
  771. } else {
  772. ttm->usWeightClass = t1m->tmweight;
  773. ttm->macStyle = (USHORT)(((t1m->tmweight>FW_MEDIUM)?MAC_BOLD : 0) |
  774. ((ttm->angle != 0) ? MAC_ITALIC : 0));
  775. ttm->fsSelection = (USHORT)(((ttm->angle != 0) ? FS_ITALIC : 0) |
  776. ((ttm->usWeightClass > FW_MEDIUM) ? FS_BOLD : 0) |
  777. ((ttm->usWeightClass==FW_NORMAL)
  778. ? FS_NORMAL : 0));
  779. ttm->typAscender = TransY(t1m, (funit)(t1m->ascent -
  780. t1m->intLeading));
  781. ttm->typDescender = (funit)(-TransY(t1m, t1m->descent)-1);
  782. ttm->typLinegap = TransY(t1m, (funit)(t1m->intLeading +
  783. t1m->extLeading));
  784. ttm->superoff.y = ABS(TransY(t1m, t1m->superoff));
  785. ttm->superoff.x = 0;
  786. ttm->supersize.y = TransY(t1m, t1m->supersize);
  787. ttm->supersize.x = (funit)(TransY(t1m, t1m->supersize) * 3 / 4);
  788. ttm->suboff.y = ABS(TransY(t1m, t1m->suboff));
  789. ttm->suboff.x = 0;
  790. ttm->subsize.y = TransY(t1m, t1m->subsize);
  791. ttm->subsize.x = (funit)(TransY(t1m, t1m->subsize) * 3 / 4);
  792. ttm->strikeoff = ABS(TransY(t1m, t1m->strikeoff));
  793. ttm->strikesize = TransY(t1m, t1m->strikesize);
  794. // Adjust usWinAscent so that internal leading matches up.
  795. // For fonts that do not have buggy pfm files, this adjustment
  796. // will do nothing, for those for which intLeading is
  797. // incorrectly set to zero, taking max means that the tops will not
  798. // be chopped off in the converted font. ttfd shaves off anything
  799. // that extends beyond ascender or descender. For fonts with buggy
  800. // pfm's, tt conversions may have bogus internal leadings, but this
  801. // is better than having glyph bottoms or tops shaved off. [bodind]
  802. PostAsc = ttm->emheight + TransY(t1m, t1m->intLeading) - ttm->winDescender;
  803. if (PostAsc > ttm->winAscender)
  804. ttm->winAscender = PostAsc;
  805. }
  806. /* Gray-scale threshold. */
  807. if (GetStdVW(t1m)!=0 || GetDefStdVW(t1m)!=0) {
  808. ttm->onepix = (USHORT)(1 + GetUPEM(t1m)*3/2 /
  809. TransY(t1m, ((GetStdVW(t1m) ?
  810. GetStdVW(t1m) :
  811. GetDefStdVW(t1m)))));
  812. }
  813. // needed in producing the correct ifimetrics for tt conversion
  814. ttm->DefaultChar = t1m->DefaultChar;
  815. ttm->BreakChar = t1m->BreakChar;
  816. ttm->CharSet = t1m->CharSet; // essential for correct font mapping
  817. /* Character widths. */
  818. if (t1m->flags!=DEFAULTMETRICS) {
  819. ttm->FirstChar = t1m->firstChar;
  820. ttm->LastChar = t1m->lastChar;
  821. if ((ttm->widths = Malloc(sizeof(funit)*
  822. (t1m->lastChar-t1m->firstChar+1)))==NULL) {
  823. SetError(status = NOMEM);
  824. } else {
  825. for (i=0; i<=(unsigned)(t1m->lastChar-t1m->firstChar); i++) {
  826. ttm->widths[i] = TransY(t1m, t1m->widths[i]);
  827. }
  828. }
  829. }
  830. /* Pair kerning. */
  831. if (t1m->flags!=DEFAULTMETRICS &&
  832. t1m->kerns!=NULL) {
  833. if ((ttm->kerns = Malloc(sizeof(struct kerning)*
  834. t1m->kernsize))==NULL) {
  835. SetError(status = NOMEM);
  836. } else {
  837. for (i=0; i<t1m->kernsize; i++) {
  838. ttm->kerns[i].left = t1m->kerns[i].left;
  839. ttm->kerns[i].right = t1m->kerns[i].right;
  840. ttm->kerns[i].delta = TransY(t1m, t1m->kerns[i].delta);
  841. }
  842. ttm->kernsize = t1m->kernsize;
  843. }
  844. }
  845. /* Pre program. */
  846. if ((prep = GetPrep(PREPSIZE))!=NULL &&
  847. (prep_size = BuildPreProgram(t1m,
  848. GetWeight(t1m),
  849. GetBlues(t1m),
  850. GetAlignment(t1m),
  851. &prep, PREPSIZE,
  852. &(ttm->maxprepstack)))>0) {
  853. /* Store the pre-program. */
  854. UsePrep(ttm, prep, prep_size);
  855. }
  856. /* CVT entries. */
  857. blues = GetBlues(t1m);
  858. if (status!=NOMEM &&
  859. (ttm->cvt = Malloc(blues->align.cvt * CVTSIZE)) == NULL) {
  860. SetError(status = NOMEM);
  861. } else {
  862. ADDCVT(0); /* TMPCVT */
  863. ADDCVT((GetStdVW(t1m)==0) ?
  864. TransX(t1m, GetDefStdVW(t1m))/2 :
  865. TransX(t1m, GetStdVW(t1m))/2);
  866. ADDCVT((GetStdHW(t1m)==0) ?
  867. TransY(t1m, GetDefStdHW(t1m))/2 :
  868. TransY(t1m, GetStdHW(t1m))/2);
  869. for (i=0; i<t1m->snapv_cnt; i++)
  870. ADDCVT(TransY(t1m, t1m->stemsnapv[i])/2);
  871. for (i=0; i<t1m->snaph_cnt; i++)
  872. ADDCVT(TransY(t1m, t1m->stemsnaph[i])/2);
  873. /* Align the top zones. */
  874. align = GetAlignment(t1m);
  875. for (i=0; i<blues->blue_cnt/2; i++) {
  876. /* Skip empty zones. */
  877. if (align->top[i].cnt==0)
  878. continue;
  879. ttm->cvt[align->top[i].blue_cvt]
  880. = (short)TransY(t1m, blues->bluevalues[i*2]);
  881. ttm->cvt[align->top[i].blue_cvt+1]
  882. = (short)TransY(t1m, blues->bluevalues[i*2+1]);
  883. for (j=0; j<align->top[i].cnt; j++) {
  884. funit pos;
  885. int k;
  886. /* Get the closest family. */
  887. k = MatchingFamily(blues->bluevalues[i*2],
  888. blues->familyblues,
  889. blues->fblue_cnt);
  890. /* Compute the position in the zone w.r.t. the family blues. */
  891. if (blues->bluevalues[i*2] != blues->bluevalues[i*2+1])
  892. pos = IP(align->top[i].pos[j].y,
  893. blues->bluevalues[i*2],
  894. blues->bluevalues[i*2+1],
  895. blues->familyblues[k],
  896. blues->familyblues[k+1]);
  897. else
  898. pos = blues->familyblues[k];
  899. ttm->cvt[align->top[i].pos[j].cvt]
  900. = (short)TransY(t1m, align->top[i].pos[j].y);
  901. ttm->cvt[align->top[i].pos[j].cvt+1]
  902. = (short)TransY(t1m, pos);
  903. }
  904. }
  905. /* Align the bottom zones. */
  906. for (i=0; i<blues->oblue_cnt/2; i++) {
  907. /* Skip empty zones. */
  908. if (align->bottom[i].cnt==0)
  909. continue;
  910. ttm->cvt[align->bottom[i].blue_cvt]
  911. = (short)TransY(t1m, blues->otherblues[i*2+1]);
  912. for (j=0; j<align->bottom[i].cnt; j++) {
  913. funit pos;
  914. int k;
  915. /* Get the closest family. */
  916. k = MatchingFamily(blues->otherblues[i*2],
  917. blues->familyotherblues,
  918. blues->foblue_cnt);
  919. /* Compute the position in the zone w.r.t. the family blues. */
  920. if (blues->otherblues[i*2] != blues->otherblues[i*2+1])
  921. pos = IP(align->bottom[i].pos[j].y,
  922. blues->otherblues[i*2],
  923. blues->otherblues[i*2+1],
  924. blues->familyotherblues[k],
  925. blues->familyotherblues[k+1]);
  926. else
  927. pos = blues->familyotherblues[k];
  928. ttm->cvt[align->bottom[i].pos[j].cvt]
  929. = (short)TransY(t1m, align->bottom[i].pos[j].y);
  930. ttm->cvt[align->bottom[i].pos[j].cvt+1]
  931. = (short)TransY(t1m, pos);
  932. }
  933. }
  934. /* Add the family zones. */
  935. for (i=0; i<blues->fblue_cnt/2; i++) {
  936. if (blues->family_cvt[i]!=UNDEF_CVT) {
  937. ttm->cvt[blues->family_cvt[i]]
  938. = (short)TransY(t1m, blues->familyblues[i*2]);
  939. ttm->cvt[blues->family_cvt[i]+1]
  940. = (short)TransY(t1m, blues->familyblues[i*2+1]);
  941. }
  942. }
  943. /* Add the family other zones. */
  944. for (i=0; i<blues->foblue_cnt/2; i++) {
  945. if (blues->familyother_cvt[i]!=UNDEF_CVT) {
  946. ttm->cvt[blues->familyother_cvt[i]]
  947. = (short)TransY(t1m, blues->familyotherblues[i*2+1]);
  948. }
  949. }
  950. ttm->cvt_cnt = blues->align.cvt;
  951. ttm->maxstorage = t1m->stems.storage;
  952. /* Store the font-program. */
  953. SetFPGM(ttm, GetFontProg(), GetFontProgSize(), GetNumFuns());
  954. }
  955. }
  956. return status;
  957. }