write.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /*
  2. Copyright (c) 2002-2003 by Juliusz Chroboczek
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. /* $XFree86: xc/programs/fonttosfnt/write.c,v 1.4tsi Exp $ */
  20. #if defined(linux) && !defined(_GNU_SOURCE)
  21. /* for fwrite_unlocked and fread_unlocked */
  22. #define _GNU_SOURCE 1
  23. #endif
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <sys/types.h>
  27. #include <netinet/in.h>
  28. #include "X11/Xos.h"
  29. #include "fonttosfnt.h"
  30. #if !defined(I_LOVE_POSIX) && \
  31. defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
  32. #define DO_FWRITE fwrite_unlocked
  33. #define DO_FREAD fread_unlocked
  34. #else
  35. #define DO_FWRITE fwrite
  36. #define DO_FREAD fread
  37. #endif
  38. static int writeDir(FILE*, FontPtr, int, unsigned*);
  39. static int fixupDir(FILE*, FontPtr, int, int*, int*);
  40. static int fixupChecksum(FILE*, int, int);
  41. static int writeEBDT(FILE*, FontPtr);
  42. static int writeEBLC(FILE*, FontPtr);
  43. static int writeOS2(FILE*, FontPtr);
  44. static int writePCLT(FILE*, FontPtr);
  45. static int writecmap(FILE*, FontPtr);
  46. static int writeglyf(FILE*, FontPtr);
  47. static int writehead(FILE*, FontPtr);
  48. static int writehhea(FILE*, FontPtr);
  49. static int writehmtx(FILE*, FontPtr);
  50. static int writeloca(FILE*, FontPtr);
  51. static int writemaxp(FILE*, FontPtr);
  52. static int writename(FILE*, FontPtr);
  53. static int writepost(FILE*, FontPtr);
  54. int max_awidth, min_x, min_y, max_x, max_y;
  55. static CmapPtr current_cmap = NULL;
  56. static int numglyphs, nummetrics;
  57. static int write_error_occurred, read_error_occurred;
  58. /* floor(log2(x)) */
  59. static int
  60. log2_floor(int x)
  61. {
  62. int i, j;
  63. if(x <= 0)
  64. abort();
  65. i = 0;
  66. j = 1;
  67. while(2 * j < x) {
  68. i++;
  69. j *= 2;
  70. }
  71. return i;
  72. }
  73. /* 2 ** floor(log2(x)) */
  74. static int
  75. two_log2_floor(int x)
  76. {
  77. int j;
  78. if(x <= 0)
  79. abort();
  80. j = 1;
  81. while(2 * j < x) {
  82. j *= 2;
  83. }
  84. return j;
  85. }
  86. static void
  87. write_error(int rc)
  88. {
  89. /* Real Men program in C and don't use exceptions. */
  90. if(write_error_occurred)
  91. return;
  92. write_error_occurred = 1;
  93. if(rc < 0)
  94. perror("Couldn't write");
  95. else
  96. fprintf(stderr, "Short write.\n");
  97. }
  98. static void
  99. read_error(int rc)
  100. {
  101. if(read_error_occurred)
  102. return;
  103. read_error_occurred = 1;
  104. if(rc < 0)
  105. perror("Couldn't read");
  106. else
  107. fprintf(stderr, "Short read.\n");
  108. }
  109. static void
  110. writeBYTE(FILE *out, unsigned char val)
  111. {
  112. int rc;
  113. rc = DO_FWRITE(&val, 1, 1, out);
  114. if(rc != 1) write_error(rc);
  115. }
  116. static void
  117. writeBYTEs(FILE *out, unsigned char *chars, int n)
  118. {
  119. int rc;
  120. rc = DO_FWRITE(chars, 1, n, out);
  121. if(rc != n) write_error(rc);
  122. }
  123. static void
  124. writeCHAR(FILE *out, char val)
  125. {
  126. int rc;
  127. rc = DO_FWRITE(&val, 1, 1, out);
  128. if(rc != 1) write_error(rc);
  129. }
  130. static void
  131. writeCHARs(FILE *out, char *chars, int n)
  132. {
  133. int rc;
  134. rc = DO_FWRITE(chars, 1, n, out);
  135. if(rc != n) write_error(rc);
  136. }
  137. static void
  138. writeUSHORT(FILE *out, unsigned short val)
  139. {
  140. int rc;
  141. val = htons(val);
  142. rc = DO_FWRITE(&val, 2, 1, out);
  143. if(rc != 1) write_error(rc);
  144. }
  145. static void
  146. writeSHORT(FILE *out, short val)
  147. {
  148. int rc;
  149. val = htons(val);
  150. rc = DO_FWRITE(&val, 2, 1, out);
  151. if(rc != 1) write_error(rc);
  152. }
  153. static void
  154. writeULONG(FILE *out, unsigned int val)
  155. {
  156. int rc;
  157. val = htonl(val);
  158. rc = DO_FWRITE(&val, 4, 1, out);
  159. if(rc != 1) write_error(rc);
  160. }
  161. static void
  162. writeLONG(FILE *out, int val)
  163. {
  164. int rc;
  165. val = htonl(val);
  166. rc = DO_FWRITE(&val, 4, 1, out);
  167. if(rc != 1) write_error(rc);
  168. }
  169. static unsigned
  170. readULONG(FILE *out)
  171. {
  172. int rc;
  173. unsigned val;
  174. rc = DO_FREAD(&val, 4, 1, out);
  175. if(rc != 1) {
  176. read_error(rc);
  177. return 0xDEADBEEF;
  178. }
  179. return ntohl(val);
  180. }
  181. int
  182. writeFile(char *filename, FontPtr font)
  183. {
  184. int rc;
  185. FILE *out;
  186. unsigned tables[15];
  187. int head_position = 0;
  188. int full_length;
  189. int (*(table_writers[15]))(FILE*, FontPtr);
  190. int i, j;
  191. int offset[15], length[15];
  192. StrikePtr strike;
  193. fontMetrics(font, &max_awidth, &min_x, &min_y, &max_x, &max_y);
  194. out = fopen(filename, "wb+");
  195. if(out == NULL)
  196. return -1;
  197. current_cmap = makeCmap(font);
  198. if(current_cmap == NULL) {
  199. fprintf(stderr, "Couldn't build cmap.\n");
  200. return -1;
  201. }
  202. write_error_occurred = 0;
  203. read_error_occurred = 0;
  204. if(glyph_flag >= 2) {
  205. numglyphs = maxIndex(current_cmap) + 1;
  206. if(metrics_flag >= 2)
  207. nummetrics = numglyphs - 1;
  208. else if(metrics_flag >= 1)
  209. nummetrics = 1;
  210. else
  211. nummetrics = 0;
  212. } else if(glyph_flag == 1) {
  213. numglyphs = 1;
  214. nummetrics = (metrics_flag >= 1) ? 1 : 0;
  215. } else {
  216. numglyphs = 0;
  217. nummetrics = 0;
  218. }
  219. strike = font->strikes;
  220. while(strike) {
  221. strike->indexSubTables = makeIndexSubTables(strike, current_cmap);
  222. if(!strike->indexSubTables) {
  223. fprintf(stderr, "Couldn't build indexSubTable.\n");
  224. return -1;
  225. }
  226. strike = strike->next;
  227. }
  228. /* These must be sorted lexicographically */
  229. i = 0;
  230. tables[i] = makeName("EBDT"); table_writers[i] = writeEBDT; i++;
  231. tables[i] = makeName("EBLC"); table_writers[i] = writeEBLC; i++;
  232. tables[i] = makeName("OS/2"); table_writers[i] = writeOS2; i++;
  233. tables[i] = makeName("PCLT"); table_writers[i] = writePCLT; i++;
  234. tables[i] = makeName("cmap"); table_writers[i] = writecmap; i++;
  235. if(numglyphs >= 1) {
  236. tables[i] = makeName("glyf");
  237. table_writers[i] = writeglyf; i++;
  238. }
  239. tables[i] = makeName("head"); table_writers[i] = writehead; i++;
  240. tables[i] = makeName("hhea"); table_writers[i] = writehhea; i++;
  241. if(nummetrics >= 1) {
  242. tables[i] = makeName("hmtx");
  243. table_writers[i] = writehmtx; i++;
  244. }
  245. if(numglyphs >= 1) {
  246. tables[i] = makeName("loca");
  247. table_writers[i] = writeloca; i++;
  248. }
  249. tables[i] = makeName("maxp"); table_writers[i] = writemaxp; i++;
  250. tables[i] = makeName("name"); table_writers[i] = writename; i++;
  251. tables[i] = makeName("post"); table_writers[i] = writepost; i++;
  252. rc = writeDir(out, font, i, tables);
  253. if(rc < 0)
  254. goto fail;
  255. for(j = 0; j < i; j++) {
  256. offset[j] = ftell(out);
  257. if(offset[j] < 0) {
  258. perror("Couldn't compute table offset");
  259. goto fail;
  260. }
  261. if(tables[j] == makeName("head"))
  262. head_position = offset[j];
  263. rc = table_writers[j](out, font);
  264. if(rc < 0 || write_error_occurred || read_error_occurred)
  265. goto fail;
  266. length[j] = ftell(out) - offset[j];
  267. if(length[j] < 0) {
  268. perror("Couldn't compute table size");
  269. goto fail;
  270. }
  271. if(length[j] % 4 != 0) {
  272. /* Pad -- recommended by the spec, and assumed by
  273. computeChecksum. */
  274. int k;
  275. for(k = 0; k < (4 - length[j] % 4); k++) {
  276. /* This must be 0 -- see computeChecksum. */
  277. writeBYTE(out, 0);
  278. }
  279. if(write_error_occurred || read_error_occurred)
  280. goto fail;
  281. }
  282. }
  283. rc = fixupDir(out, font, i, offset, length);
  284. if(rc < 0)
  285. goto fail;
  286. full_length = ftell(out);
  287. if(full_length < 0) {
  288. perror("Couldn't compute file size");
  289. goto fail;
  290. }
  291. while(full_length % 4 != 0) {
  292. /* pad for computeChecksum */
  293. writeBYTE(out, 0);
  294. full_length++;
  295. }
  296. if(write_error_occurred || read_error_occurred)
  297. goto fail;
  298. rc = fixupChecksum(out, full_length, head_position);
  299. if(rc < 0)
  300. goto fail;
  301. fclose(out);
  302. return 0;
  303. fail:
  304. unlink(filename);
  305. return -1;
  306. }
  307. static int
  308. writeDir(FILE *out, FontPtr font, int numTables, unsigned *tables)
  309. {
  310. int i, ti;
  311. i = 0; ti = 1;
  312. while(2 * ti < numTables) {
  313. i++;
  314. ti = 2 * ti;
  315. }
  316. writeULONG(out, 0x10000); /* version */
  317. writeUSHORT(out, numTables); /* numTables */
  318. writeUSHORT(out, 16 * ti); /* searchRange */
  319. writeUSHORT(out, i); /* entrySelector */
  320. writeUSHORT(out, 16 * (numTables - ti)); /* rangeShift */
  321. /* see fixupDir */
  322. for(i = 0; i < numTables; i++) {
  323. writeULONG(out, tables[i]);
  324. writeULONG(out, 0xDEADFACE); /* checkSum */
  325. writeULONG(out, 0xDEADFACE); /* offset */
  326. writeULONG(out, 0xDEADFACE); /* length */
  327. }
  328. return 0;
  329. }
  330. static unsigned
  331. computeChecksum(FILE *out, int offset, int length)
  332. {
  333. int rc;
  334. int i;
  335. unsigned sum = 0;
  336. if(offset % 4 != 0) {
  337. fprintf(stderr, "Offset %d is not a multiple of 4\n", offset);
  338. return ~0;
  339. }
  340. rc = fseek(out, offset, SEEK_SET);
  341. if(rc < 0) {
  342. perror("Couldn't seek");
  343. return ~0;
  344. }
  345. /* This relies on the fact that we always pad tables with zeroes. */
  346. for(i = 0; i < length; i += 4) {
  347. sum += readULONG(out);
  348. }
  349. return sum;
  350. }
  351. static int
  352. fixupDir(FILE *out, FontPtr font, int numTables, int *offset, int *length)
  353. {
  354. int rc, i;
  355. unsigned sum;
  356. for(i = 0; i < numTables; i++) {
  357. sum = computeChecksum(out, offset[i], length[i]);
  358. rc = fseek(out, 12 + 16 * i + 4, SEEK_SET);
  359. if(rc != 0) {
  360. perror("Couldn't seek");
  361. return -1;
  362. }
  363. writeULONG(out, sum);
  364. writeULONG(out, offset[i]);
  365. writeULONG(out, length[i]);
  366. }
  367. return 0;
  368. }
  369. static int
  370. fixupChecksum(FILE *out, int full_length, int head_position)
  371. {
  372. int rc, checksum;
  373. checksum = computeChecksum(out, 0, full_length);
  374. rc = fseek(out, head_position + 8, SEEK_SET);
  375. if(rc != 0) {
  376. perror("Couldn't seek");
  377. return -1;
  378. }
  379. writeULONG(out, 0xB1B0AFBA - checksum); /* checkSumAdjustment */
  380. return 0;
  381. }
  382. static int
  383. writehead(FILE* out, FontPtr font)
  384. {
  385. int time_hi;
  386. unsigned time_lo;
  387. macTime(&time_hi, &time_lo);
  388. writeULONG(out, 0x00010000);
  389. writeULONG(out, 0x00010000); /* fontRevision */
  390. writeULONG(out, 0); /* checkSumAdjustment -- filled in later */
  391. writeULONG(out,0x5F0F3CF5); /* magicNumber */
  392. writeUSHORT(out, 1); /* flags */
  393. writeUSHORT(out, UNITS_PER_EM); /* unitsPerEm */
  394. writeLONG(out, time_hi); /* created */
  395. writeULONG(out, time_lo);
  396. writeLONG(out, time_hi); /* modified */
  397. writeULONG(out, time_lo);
  398. writeUSHORT(out, FONT_UNITS_FLOOR(min_x));
  399. writeUSHORT(out, FONT_UNITS_FLOOR(min_y));
  400. writeUSHORT(out, FONT_UNITS_CEIL(max_x));
  401. writeUSHORT(out, FONT_UNITS_CEIL(max_y));
  402. writeUSHORT(out, font->flags); /* macStyle */
  403. writeUSHORT(out, 1); /* lowestRecPPEM */
  404. writeSHORT(out, 0); /* fontDirectionHint */
  405. writeSHORT(out, 0); /* indexToLocFormat */
  406. writeSHORT(out, 0); /* glyphDataFormat */
  407. return 0;
  408. }
  409. static int
  410. outputRaster(FILE *out, char *raster, int width, int height, int stride,
  411. int bit_aligned)
  412. {
  413. int i, j;
  414. int len = 0;
  415. if(!bit_aligned || width % 8 == 0) {
  416. for(i = 0; i < height; i++) {
  417. writeCHARs(out, raster + i * stride, (width + 7) / 8);
  418. len += (width + 7) / 8;
  419. }
  420. } else {
  421. int bit = 0;
  422. unsigned char v = 0;
  423. for(i = 0; i < height; i++) {
  424. for(j = 0; j < width; j++) {
  425. if(BITREF(raster, stride, j, i))
  426. v |= 1 << (7 - bit);
  427. bit++;
  428. if(bit >= 8) {
  429. writeBYTE(out, v);
  430. len++;
  431. bit = 0;
  432. v = 0;
  433. }
  434. }
  435. }
  436. if(bit > 0) {
  437. writeBYTE(out, v);
  438. len++;
  439. }
  440. }
  441. return len;
  442. }
  443. static int
  444. writeEBDT(FILE* out, FontPtr font)
  445. {
  446. StrikePtr strike;
  447. BitmapPtr bitmap;
  448. IndexSubTablePtr table;
  449. int i;
  450. int offset;
  451. int ebdt_start;
  452. ebdt_start = ftell(out);
  453. writeULONG(out, 0x00020000); /* version */
  454. offset = 4;
  455. strike = font->strikes;
  456. while(strike) {
  457. table = strike->indexSubTables;
  458. while(table) {
  459. for(i = table->firstGlyphIndex; i <= table->lastGlyphIndex; i++) {
  460. bitmap = strikeBitmapIndex(strike, current_cmap, i);
  461. bitmap->location = offset;
  462. if(bit_aligned_flag && table->constantMetrics) {
  463. /* image format 5 */
  464. ;
  465. } else {
  466. /* image format 1 or 2 */
  467. writeBYTE(out, bitmap->height);
  468. writeBYTE(out, bitmap->width);
  469. writeCHAR(out, bitmap->horiBearingX);
  470. writeCHAR(out, bitmap->horiBearingY);
  471. writeBYTE(out, bitmap->advanceWidth);
  472. offset += 5;
  473. }
  474. offset += outputRaster(out,
  475. bitmap->raster,
  476. bitmap->width, bitmap->height,
  477. bitmap->stride,
  478. bit_aligned_flag);
  479. }
  480. table->lastLocation = offset;
  481. table = table->next;
  482. }
  483. strike = strike->next;
  484. }
  485. if(ftell(out) != ebdt_start + offset)
  486. abort();
  487. return 0;
  488. }
  489. static int
  490. writeSbitLineMetrics(FILE *out, StrikePtr strike, int num, int den)
  491. {
  492. int width_max, x_min, y_min, x_max, y_max;
  493. strikeMetrics(strike, &width_max, &x_min, &y_min, &x_max, &y_max);
  494. writeCHAR(out, y_max); /* ascender */
  495. writeCHAR(out, y_min); /* descender */
  496. writeBYTE(out, width_max); /* widthMax */
  497. writeCHAR(out, num); /* caretSlopeNumerator */
  498. writeCHAR(out, den); /* caretSlopeDenominator */
  499. writeCHAR(out, 0); /* caretOffset */
  500. writeCHAR(out, 0); /* minOriginSB */
  501. writeCHAR(out, 0); /* minAdvanceSB */
  502. writeCHAR(out, 0); /* maxBeforeBL */
  503. writeCHAR(out, 0); /* minAfterBL */
  504. writeCHAR(out, 0); /* pad1 */
  505. writeCHAR(out, 0); /* pad2 */
  506. return 0;
  507. }
  508. static int
  509. writeEBLC(FILE* out, FontPtr font)
  510. {
  511. int i, rc, numstrikes, eblc_start, num, den;
  512. StrikePtr strike;
  513. IndexSubTablePtr table;
  514. degreesToFraction(font->italicAngle, &num, &den);
  515. numstrikes = 0;
  516. strike = font->strikes;
  517. while(strike) {
  518. numstrikes++;
  519. strike = strike->next;
  520. }
  521. eblc_start = ftell(out);
  522. writeULONG(out, 0x00020000); /* version */
  523. writeULONG(out, numstrikes); /* numSizes */
  524. /* bitmapSizeTable */
  525. strike = font->strikes;
  526. while(strike) {
  527. strike->bitmapSizeTableLocation = ftell(out);
  528. writeULONG(out, 0xDEADFACE); /* indexSubTableArrayOffset */
  529. writeULONG(out, 0xDEADFACE); /* indexTablesSize */
  530. writeULONG(out, 0xDEADFACE); /* numberOfIndexSubTables */
  531. writeULONG(out, 0); /* colorRef */
  532. writeSbitLineMetrics(out, strike, num, den);
  533. writeSbitLineMetrics(out, strike, num, den);
  534. writeUSHORT(out, 0); /* startGlyphIndex */
  535. writeUSHORT(out, 0xFFFD); /* endGlyphIndex */
  536. writeBYTE(out, strike->sizeX); /* ppemX */
  537. writeBYTE(out, strike->sizeY); /* ppemY */
  538. writeBYTE(out, 1); /* bitDepth */
  539. writeCHAR(out, 1); /* flags */
  540. strike = strike->next;
  541. }
  542. /* indexSubTableArray, one per strike */
  543. strike = font->strikes;
  544. while(strike) {
  545. int endoffset;
  546. int numtables = 0;
  547. strike->indexSubTableLocation = ftell(out);
  548. table = strike->indexSubTables;
  549. while(table) {
  550. table->location = ftell(out);
  551. writeUSHORT(out, table->firstGlyphIndex);
  552. writeUSHORT(out, table->lastGlyphIndex);
  553. writeULONG(out, 0xDEADFACE); /* additionalOffsetToIndexSubtable */
  554. numtables++;
  555. table = table->next;
  556. }
  557. endoffset = ftell(out);
  558. rc = fseek(out, strike->bitmapSizeTableLocation, SEEK_SET);
  559. if(rc != 0) {
  560. perror("Couldn't seek");
  561. return -1;
  562. }
  563. writeULONG(out, strike->indexSubTableLocation - eblc_start);
  564. /* indexSubTableArrayOffset */
  565. writeULONG(out, endoffset - strike->indexSubTableLocation);
  566. /* indexTablesSize */
  567. writeULONG(out, numtables); /* numberOfIndexSubTables */
  568. rc = fseek(out, endoffset, SEEK_SET);
  569. if(rc != 0) {
  570. perror("Couldn't seek");
  571. return -1;
  572. }
  573. strike = strike->next;
  574. }
  575. /* actual indexSubTables */
  576. strike = font->strikes;
  577. while(strike) {
  578. int vertAdvance, y_min, y_max;
  579. strikeMetrics(strike, NULL, NULL, &y_min, NULL, &y_max);
  580. vertAdvance = y_max - y_min;
  581. table = strike->indexSubTables;
  582. while(table) {
  583. int location;
  584. int data_location;
  585. int short_offsets;
  586. int offset;
  587. location = ftell(out);
  588. rc = fseek(out, table->location + 4, SEEK_SET);
  589. if(rc != 0) {
  590. perror("Couldn't seek");
  591. return -1;
  592. }
  593. /* additionalOffsetToIndexSubtable */
  594. writeULONG(out, location - strike->indexSubTableLocation);
  595. rc = fseek(out, location, SEEK_SET);
  596. if(rc != 0) {
  597. perror("Couldn't seek");
  598. return -1;
  599. }
  600. data_location =
  601. strikeBitmapIndex(strike, current_cmap,
  602. table->firstGlyphIndex)->location;
  603. short_offsets = 1;
  604. for(i = table->firstGlyphIndex; i <= table->lastGlyphIndex; i++) {
  605. if(strikeBitmapIndex(strike, current_cmap, i)->location -
  606. data_location > 0xFFFF) {
  607. short_offsets = 0;
  608. break;
  609. }
  610. }
  611. /* indexFormat */
  612. if(table->constantMetrics)
  613. writeUSHORT(out, 2);
  614. else if(short_offsets)
  615. writeUSHORT(out, 3);
  616. else
  617. writeUSHORT(out, 1);
  618. /* imageFormat */
  619. if(bit_aligned_flag) {
  620. if(table->constantMetrics)
  621. writeUSHORT(out, 5);
  622. else
  623. writeUSHORT(out, 2);
  624. } else {
  625. writeUSHORT(out, 1);
  626. }
  627. writeULONG(out, data_location);
  628. if(table->constantMetrics) {
  629. int size;
  630. BitmapPtr bitmap =
  631. strikeBitmapIndex(strike, current_cmap,
  632. table->firstGlyphIndex);
  633. size =
  634. strikeBitmapIndex(strike, current_cmap,
  635. table->firstGlyphIndex + 1)->location -
  636. bitmap->location;
  637. writeULONG(out, size); /* imageSize */
  638. /* bigMetrics */
  639. writeBYTE(out, bitmap->height);
  640. writeBYTE(out, bitmap->width);
  641. writeCHAR(out, bitmap->horiBearingX);
  642. writeCHAR(out, bitmap->horiBearingY);
  643. writeBYTE(out, bitmap->advanceWidth);
  644. writeCHAR(out, bitmap->horiBearingX); /* vertBearingX */
  645. writeCHAR(out, bitmap->horiBearingY); /* vertBearingY */
  646. writeBYTE(out, vertAdvance); /* vertAdvance */
  647. } else {
  648. for(i = table->firstGlyphIndex;
  649. i <= table->lastGlyphIndex; i++) {
  650. offset =
  651. strikeBitmapIndex(strike, current_cmap, i)->location -
  652. data_location;
  653. if(short_offsets)
  654. writeUSHORT(out, offset);
  655. else
  656. writeULONG(out, offset);
  657. }
  658. /* Dummy glyph of size 0 to mark the end of the table */
  659. if(short_offsets) {
  660. writeUSHORT(out, table->lastLocation - data_location);
  661. writeUSHORT(out, table->lastLocation - data_location);
  662. } else {
  663. writeULONG(out, table->lastLocation - data_location);
  664. writeULONG(out, table->lastLocation - data_location);
  665. }
  666. }
  667. location = ftell(out);
  668. while(location % 4 != 0) {
  669. writeCHAR(out, 0);
  670. location--;
  671. }
  672. table = table->next;
  673. }
  674. strike = strike->next;
  675. }
  676. return 0;
  677. }
  678. static int
  679. writecmap(FILE* out, FontPtr font)
  680. {
  681. int rc, cmap_start, cmap_end;
  682. CmapPtr cmap;
  683. int segcount;
  684. segcount = 0;
  685. cmap = current_cmap;
  686. while(cmap) {
  687. segcount++;
  688. cmap = cmap->next;
  689. }
  690. segcount++; /* dummy segment to end table */
  691. cmap_start = ftell(out);
  692. writeUSHORT(out, 0); /* version */
  693. writeUSHORT(out, 1); /* number of encoding tables */
  694. writeUSHORT(out, 3); /* platform ID */
  695. writeUSHORT(out, (font->flags & FACE_SYMBOL) ? 0 : 1);
  696. /* encoding ID */
  697. writeULONG(out, 12); /* offset to beginning of subtable */
  698. /* subtable */
  699. writeUSHORT(out, 4); /* format */
  700. writeUSHORT(out, 0xDEAD); /* length */
  701. writeUSHORT(out, 0); /* language */
  702. /* How baroque can you get? */
  703. writeUSHORT(out, segcount * 2); /* segCountX2 */
  704. writeUSHORT(out, 2 * two_log2_floor(segcount)); /* searchRange */
  705. writeUSHORT(out, 1 + log2_floor(segcount)); /* entrySelector */
  706. writeUSHORT(out, 2 * (segcount - two_log2_floor(segcount)));
  707. /* rangeShift */
  708. cmap = current_cmap;
  709. while(cmap) {
  710. writeUSHORT(out, cmap->endCode);
  711. cmap = cmap->next;
  712. }
  713. writeUSHORT(out, 0xFFFF);
  714. writeUSHORT(out, 0); /* reservedPad */
  715. cmap = current_cmap;
  716. while(cmap) {
  717. writeUSHORT(out, cmap->startCode);
  718. cmap = cmap->next;
  719. }
  720. writeUSHORT(out, 0xFFFF);
  721. /* idDelta */
  722. cmap = current_cmap;
  723. while(cmap) {
  724. writeUSHORT(out, (cmap->index - cmap->startCode) & 0xFFFF);
  725. cmap = cmap->next;
  726. }
  727. writeUSHORT(out, 1);
  728. /* idRangeOffset */
  729. cmap = current_cmap;
  730. while(cmap) {
  731. writeUSHORT(out, 0);
  732. cmap = cmap->next;
  733. }
  734. writeUSHORT(out, 0);
  735. /* glyphIDArray is empty */
  736. cmap_end = ftell(out);
  737. rc = fseek(out, cmap_start + 12 + 2, SEEK_SET);
  738. if(rc != 0) {
  739. perror("Couldn't seek");
  740. return -1;
  741. }
  742. writeUSHORT(out, cmap_end - cmap_start - 12); /* length */
  743. rc = fseek(out, cmap_end, SEEK_SET);
  744. if(rc != 0) {
  745. perror("Couldn't seek");
  746. return -1;
  747. }
  748. return 0;
  749. }
  750. static int
  751. writeglyf(FILE* out, FontPtr font)
  752. {
  753. return 0;
  754. }
  755. int
  756. writehhea(FILE* out, FontPtr font)
  757. {
  758. int num, den;
  759. degreesToFraction(font->italicAngle, &num, &den);
  760. writeULONG(out, 0x00010000); /* version */
  761. writeSHORT(out, FONT_UNITS_CEIL(max_y)); /* ascender */
  762. writeSHORT(out, FONT_UNITS_FLOOR(min_y)); /* descender */
  763. writeSHORT(out, FONT_UNITS(TWO_SIXTEENTH / 20)); /* lineGap */
  764. writeUSHORT(out, FONT_UNITS(max_awidth)); /* advanceWidthMax */
  765. writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minLeftSideBearing */
  766. writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minRightSideBearing */
  767. writeSHORT(out, FONT_UNITS_CEIL(max_x)); /* xMaxExtent */
  768. writeSHORT(out, den); /* caretSlopeRise */
  769. writeSHORT(out, num); /* caretSlopeRun */
  770. writeSHORT(out, 0); /* reserved */
  771. writeSHORT(out, 0); /* reserved */
  772. writeSHORT(out, 0); /* reserved */
  773. writeSHORT(out, 0); /* reserved */
  774. writeSHORT(out, 0); /* reserved */
  775. writeSHORT(out, 0); /* metricDataFormat */
  776. writeSHORT(out, nummetrics); /* numberOfHMetrics */
  777. return 0;
  778. }
  779. static int
  780. writehmtx(FILE* out, FontPtr font)
  781. {
  782. int rc, i;
  783. for(i = 0; i <= numglyphs; i++) {
  784. int code, width, lsb;
  785. code = findCode(current_cmap, i);
  786. if(code < 0)
  787. rc = -1;
  788. else
  789. rc = glyphMetrics(font, code, &width, &lsb, NULL, NULL, NULL);
  790. if(rc < 0) {
  791. width = UNITS_PER_EM / 3;
  792. lsb = 0;
  793. }
  794. if(i < nummetrics) {
  795. writeSHORT(out, FONT_UNITS(width));
  796. writeSHORT(out, FONT_UNITS(lsb));
  797. } else {
  798. writeSHORT(out, FONT_UNITS(lsb));
  799. }
  800. }
  801. return 0;
  802. }
  803. static int
  804. writeloca(FILE* out, FontPtr font)
  805. {
  806. int i;
  807. /* All glyphs undefined -- loca table is empty, so offset 0 */
  808. for(i = 0; i < numglyphs; i++) {
  809. writeSHORT(out, 0);
  810. }
  811. writeSHORT(out, 0);
  812. return 0;
  813. }
  814. static int
  815. writemaxp(FILE* out, FontPtr font)
  816. {
  817. writeLONG(out, 0x00010000); /* version */
  818. writeUSHORT(out, numglyphs); /* numGlyphs */
  819. writeUSHORT(out, 0); /* maxPoints */
  820. writeUSHORT(out, 0); /* maxContours */
  821. writeUSHORT(out, 0); /* maxCompositePoints */
  822. writeUSHORT(out, 0); /* maxCompositeContours */
  823. writeUSHORT(out, 1); /* maxZones */
  824. writeUSHORT(out, 0); /* maxTwilightPoints */
  825. writeUSHORT(out, 0); /* maxStorage */
  826. writeUSHORT(out, 0); /* maxFunctionDefs */
  827. writeUSHORT(out, 0); /* maxInstructionDefs */
  828. writeUSHORT(out, 0); /* maxStackElements */
  829. writeUSHORT(out, 0); /* maxSizeOfInstructions */
  830. writeUSHORT(out, 0); /* maxComponentElements */
  831. writeUSHORT(out, 0); /* maxComponentDepth */
  832. return 0;
  833. }
  834. static int
  835. writename(FILE* out, FontPtr font)
  836. {
  837. int i;
  838. int offset;
  839. writeUSHORT(out, 0); /* format selector */
  840. writeUSHORT(out, font->numNames);
  841. writeUSHORT(out, 6 + font->numNames * 12); /* offset to string storage */
  842. offset = 0;
  843. for(i = 0; i < font->numNames; i++) {
  844. writeUSHORT(out, 3); /* platform id -- Microsoft */
  845. writeUSHORT(out, 1); /* encoding -- Unicode */
  846. writeUSHORT(out, 0x409); /* language id -- American English */
  847. writeUSHORT(out, font->names[i].nid); /* name id */
  848. writeUSHORT(out, font->names[i].size); /* string length */
  849. writeUSHORT(out, offset); /* string offset */
  850. offset += font->names[i].size;
  851. }
  852. for(i = 0; i < font->numNames; i++)
  853. writeCHARs(out, font->names[i].value, font->names[i].size);
  854. return 0;
  855. }
  856. static int
  857. writepost(FILE* out, FontPtr font)
  858. {
  859. int i, rc, previous_width, width, fixed_pitch;
  860. fixed_pitch = 1;
  861. previous_width = -1;
  862. for(i = 0; i < FONT_CODES; i++) {
  863. rc = glyphMetrics(font, i, &width, NULL, NULL, NULL, NULL);
  864. if(rc < 0)
  865. continue;
  866. if(previous_width >= 0) {
  867. if(width != previous_width) {
  868. fixed_pitch = 0;
  869. break;
  870. }
  871. }
  872. previous_width = width;
  873. }
  874. writeULONG(out, 0x00030000); /* FormatType */
  875. writeULONG(out, font->italicAngle); /* italicAngle */
  876. writeSHORT(out, FONT_UNITS(font->underlinePosition));
  877. writeSHORT(out, FONT_UNITS(font->underlineThickness));
  878. writeULONG(out, fixed_pitch); /* isFixedPitch */
  879. writeULONG(out, 0); /* minMemType42 */
  880. writeULONG(out, 0); /* maxMemType42 */
  881. writeULONG(out, 0); /* minMemType1 */
  882. writeULONG(out, 0); /* maxMemType1 */
  883. return 0;
  884. }
  885. static int
  886. writeOS2(FILE* out, FontPtr font)
  887. {
  888. int i;
  889. writeUSHORT(out, 0x0001);
  890. writeSHORT(out, FONT_UNITS(max_awidth / 2)); /* xAvgCharWidth; */
  891. writeUSHORT(out, font->weight); /* usWeightClass; */
  892. writeUSHORT(out, font->width); /* usWidthClass; */
  893. writeSHORT(out, 0); /* fsType; */
  894. writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptXSize; */
  895. writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptYSize; */
  896. writeSHORT(out, 0); /* ySubscriptXOffset; */
  897. writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptYOffset; */
  898. writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptXSize; */
  899. writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYSize; */
  900. writeSHORT(out, 0); /* ySuperscriptXOffset; */
  901. writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYOffset; */
  902. writeSHORT(out, FONT_UNITS(font->underlineThickness));
  903. /* yStrikeoutSize; */
  904. writeSHORT(out, UNITS_PER_EM / 4); /* yStrikeoutPosition; */
  905. writeSHORT(out, 0); /* sFamilyClass; */
  906. for(i = 0; i < 10; i++)
  907. writeBYTE(out, 0); /* panose; */
  908. writeULONG(out, 0xFFFF); /* ulUnicodeRange1; */
  909. writeULONG(out, 0xFFFF); /* ulUnicodeRange2; */
  910. writeULONG(out, 0x03FF); /* ulUnicodeRange3; */
  911. writeULONG(out, 0U); /* ulUnicodeRange4; */
  912. writeULONG(out, font->foundry); /* achVendID[4]; */
  913. writeUSHORT(out, 0x0040); /* fsSelection; */
  914. writeUSHORT(out, 0x20); /* usFirstCharIndex; */
  915. writeUSHORT(out, 0xFFFD); /* usLastCharIndex; */
  916. writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* sTypoAscender; */
  917. writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* sTypoDescender; */
  918. writeUSHORT(out, FONT_UNITS(max_y - min_y));
  919. /* sTypoLineGap; */
  920. writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* usWinAscent; */
  921. writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* usWinDescent; */
  922. writeULONG(out, 3); /* ulCodePageRange1; */
  923. writeULONG(out, 0); /* ulCodePageRange2; */
  924. return 0;
  925. }
  926. static int
  927. writePCLT(FILE* out, FontPtr font)
  928. {
  929. char name[16] = "X11 font ";
  930. char filename[6] = "X11R00";
  931. unsigned char charComplement[8] =
  932. {0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0xFE};
  933. int style, w, strokeWeight, widthType;
  934. style = 0;
  935. if(font->flags & FACE_ITALIC)
  936. style = 1;
  937. w = (font->weight + 50) / 100;
  938. if(w < 5)
  939. strokeWeight = w - 6;
  940. else if(w == 5)
  941. strokeWeight = 0;
  942. else
  943. strokeWeight = w - 4;
  944. if(font->width <= 2)
  945. widthType = -3;
  946. else if(font->width <= 4)
  947. widthType = -2;
  948. else if(font->width <= 6)
  949. widthType = 0;
  950. else if(font->width <= 7)
  951. widthType = 2;
  952. else
  953. widthType = 3;
  954. writeULONG(out, 0x00010000); /* version */
  955. writeULONG(out, 0); /* FontNumber */
  956. writeUSHORT(out, FONT_UNITS(max_awidth)); /* pitch */
  957. writeUSHORT(out, FONT_UNITS(max_y)); /* xHeight */
  958. writeUSHORT(out, style); /* style */
  959. writeUSHORT(out, 6 << 12); /* TypeFamily */
  960. writeUSHORT(out, FONT_UNITS(max_y)); /* CapHeight */
  961. writeUSHORT(out, 0); /* SymbolSet */
  962. writeCHARs(out, name, 16); /* TypeFace */
  963. writeBYTEs(out, charComplement, 8); /* CharacterComplement */
  964. writeCHARs(out, filename, 6); /* FileName */
  965. writeCHAR(out, strokeWeight); /* StrokeWeight */
  966. writeCHAR(out, widthType); /* WidthType */
  967. writeCHAR(out, 1 << 6); /* SerifStyle */
  968. writeCHAR(out, 0); /* Reserved */
  969. return 0;
  970. }