12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079 |
- /*
- Copyright (c) 2002-2003 by Juliusz Chroboczek
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- /* $XFree86: xc/programs/fonttosfnt/write.c,v 1.4tsi Exp $ */
- #if defined(linux) && !defined(_GNU_SOURCE)
- /* for fwrite_unlocked and fread_unlocked */
- #define _GNU_SOURCE 1
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include "X11/Xos.h"
- #include "fonttosfnt.h"
- #if !defined(I_LOVE_POSIX) && \
- defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
- #define DO_FWRITE fwrite_unlocked
- #define DO_FREAD fread_unlocked
- #else
- #define DO_FWRITE fwrite
- #define DO_FREAD fread
- #endif
- static int writeDir(FILE*, FontPtr, int, unsigned*);
- static int fixupDir(FILE*, FontPtr, int, int*, int*);
- static int fixupChecksum(FILE*, int, int);
- static int writeEBDT(FILE*, FontPtr);
- static int writeEBLC(FILE*, FontPtr);
- static int writeOS2(FILE*, FontPtr);
- static int writePCLT(FILE*, FontPtr);
- static int writecmap(FILE*, FontPtr);
- static int writeglyf(FILE*, FontPtr);
- static int writehead(FILE*, FontPtr);
- static int writehhea(FILE*, FontPtr);
- static int writehmtx(FILE*, FontPtr);
- static int writeloca(FILE*, FontPtr);
- static int writemaxp(FILE*, FontPtr);
- static int writename(FILE*, FontPtr);
- static int writepost(FILE*, FontPtr);
- int max_awidth, min_x, min_y, max_x, max_y;
- static CmapPtr current_cmap = NULL;
- static int numglyphs, nummetrics;
- static int write_error_occurred, read_error_occurred;
- /* floor(log2(x)) */
- static int
- log2_floor(int x)
- {
- int i, j;
- if(x <= 0)
- abort();
- i = 0;
- j = 1;
- while(2 * j < x) {
- i++;
- j *= 2;
- }
- return i;
- }
- /* 2 ** floor(log2(x)) */
- static int
- two_log2_floor(int x)
- {
- int j;
-
- if(x <= 0)
- abort();
- j = 1;
- while(2 * j < x) {
- j *= 2;
- }
- return j;
- }
- static void
- write_error(int rc)
- {
- /* Real Men program in C and don't use exceptions. */
- if(write_error_occurred)
- return;
- write_error_occurred = 1;
- if(rc < 0)
- perror("Couldn't write");
- else
- fprintf(stderr, "Short write.\n");
- }
- static void
- read_error(int rc)
- {
- if(read_error_occurred)
- return;
- read_error_occurred = 1;
- if(rc < 0)
- perror("Couldn't read");
- else
- fprintf(stderr, "Short read.\n");
- }
- static void
- writeBYTE(FILE *out, unsigned char val)
- {
- int rc;
- rc = DO_FWRITE(&val, 1, 1, out);
- if(rc != 1) write_error(rc);
- }
- static void
- writeBYTEs(FILE *out, unsigned char *chars, int n)
- {
- int rc;
- rc = DO_FWRITE(chars, 1, n, out);
- if(rc != n) write_error(rc);
- }
- static void
- writeCHAR(FILE *out, char val)
- {
- int rc;
- rc = DO_FWRITE(&val, 1, 1, out);
- if(rc != 1) write_error(rc);
- }
- static void
- writeCHARs(FILE *out, char *chars, int n)
- {
- int rc;
- rc = DO_FWRITE(chars, 1, n, out);
- if(rc != n) write_error(rc);
- }
- static void
- writeUSHORT(FILE *out, unsigned short val)
- {
- int rc;
- val = htons(val);
- rc = DO_FWRITE(&val, 2, 1, out);
- if(rc != 1) write_error(rc);
- }
- static void
- writeSHORT(FILE *out, short val)
- {
- int rc;
- val = htons(val);
- rc = DO_FWRITE(&val, 2, 1, out);
- if(rc != 1) write_error(rc);
- }
- static void
- writeULONG(FILE *out, unsigned int val)
- {
- int rc;
- val = htonl(val);
- rc = DO_FWRITE(&val, 4, 1, out);
- if(rc != 1) write_error(rc);
- }
- static void
- writeLONG(FILE *out, int val)
- {
- int rc;
- val = htonl(val);
- rc = DO_FWRITE(&val, 4, 1, out);
- if(rc != 1) write_error(rc);
- }
- static unsigned
- readULONG(FILE *out)
- {
- int rc;
- unsigned val;
- rc = DO_FREAD(&val, 4, 1, out);
- if(rc != 1) {
- read_error(rc);
- return 0xDEADBEEF;
- }
- return ntohl(val);
- }
- int
- writeFile(char *filename, FontPtr font)
- {
- int rc;
- FILE *out;
- unsigned tables[15];
- int head_position = 0;
- int full_length;
- int (*(table_writers[15]))(FILE*, FontPtr);
- int i, j;
- int offset[15], length[15];
- StrikePtr strike;
- fontMetrics(font, &max_awidth, &min_x, &min_y, &max_x, &max_y);
- out = fopen(filename, "wb+");
- if(out == NULL)
- return -1;
- current_cmap = makeCmap(font);
- if(current_cmap == NULL) {
- fprintf(stderr, "Couldn't build cmap.\n");
- return -1;
- }
- write_error_occurred = 0;
- read_error_occurred = 0;
- if(glyph_flag >= 2) {
- numglyphs = maxIndex(current_cmap) + 1;
- if(metrics_flag >= 2)
- nummetrics = numglyphs - 1;
- else if(metrics_flag >= 1)
- nummetrics = 1;
- else
- nummetrics = 0;
- } else if(glyph_flag == 1) {
- numglyphs = 1;
- nummetrics = (metrics_flag >= 1) ? 1 : 0;
- } else {
- numglyphs = 0;
- nummetrics = 0;
- }
- strike = font->strikes;
- while(strike) {
- strike->indexSubTables = makeIndexSubTables(strike, current_cmap);
- if(!strike->indexSubTables) {
- fprintf(stderr, "Couldn't build indexSubTable.\n");
- return -1;
- }
- strike = strike->next;
- }
- /* These must be sorted lexicographically */
- i = 0;
- tables[i] = makeName("EBDT"); table_writers[i] = writeEBDT; i++;
- tables[i] = makeName("EBLC"); table_writers[i] = writeEBLC; i++;
- tables[i] = makeName("OS/2"); table_writers[i] = writeOS2; i++;
- tables[i] = makeName("PCLT"); table_writers[i] = writePCLT; i++;
- tables[i] = makeName("cmap"); table_writers[i] = writecmap; i++;
- if(numglyphs >= 1) {
- tables[i] = makeName("glyf");
- table_writers[i] = writeglyf; i++;
- }
- tables[i] = makeName("head"); table_writers[i] = writehead; i++;
- tables[i] = makeName("hhea"); table_writers[i] = writehhea; i++;
- if(nummetrics >= 1) {
- tables[i] = makeName("hmtx");
- table_writers[i] = writehmtx; i++;
- }
- if(numglyphs >= 1) {
- tables[i] = makeName("loca");
- table_writers[i] = writeloca; i++;
- }
- tables[i] = makeName("maxp"); table_writers[i] = writemaxp; i++;
- tables[i] = makeName("name"); table_writers[i] = writename; i++;
- tables[i] = makeName("post"); table_writers[i] = writepost; i++;
- rc = writeDir(out, font, i, tables);
- if(rc < 0)
- goto fail;
- for(j = 0; j < i; j++) {
- offset[j] = ftell(out);
- if(offset[j] < 0) {
- perror("Couldn't compute table offset");
- goto fail;
- }
- if(tables[j] == makeName("head"))
- head_position = offset[j];
- rc = table_writers[j](out, font);
- if(rc < 0 || write_error_occurred || read_error_occurred)
- goto fail;
- length[j] = ftell(out) - offset[j];
- if(length[j] < 0) {
- perror("Couldn't compute table size");
- goto fail;
- }
- if(length[j] % 4 != 0) {
- /* Pad -- recommended by the spec, and assumed by
- computeChecksum. */
- int k;
- for(k = 0; k < (4 - length[j] % 4); k++) {
- /* This must be 0 -- see computeChecksum. */
- writeBYTE(out, 0);
- }
- if(write_error_occurred || read_error_occurred)
- goto fail;
- }
- }
- rc = fixupDir(out, font, i, offset, length);
- if(rc < 0)
- goto fail;
- full_length = ftell(out);
- if(full_length < 0) {
- perror("Couldn't compute file size");
- goto fail;
- }
- while(full_length % 4 != 0) {
- /* pad for computeChecksum */
- writeBYTE(out, 0);
- full_length++;
- }
- if(write_error_occurred || read_error_occurred)
- goto fail;
- rc = fixupChecksum(out, full_length, head_position);
- if(rc < 0)
- goto fail;
- fclose(out);
- return 0;
- fail:
- unlink(filename);
- return -1;
- }
- static int
- writeDir(FILE *out, FontPtr font, int numTables, unsigned *tables)
- {
- int i, ti;
- i = 0; ti = 1;
- while(2 * ti < numTables) {
- i++;
- ti = 2 * ti;
- }
- writeULONG(out, 0x10000); /* version */
- writeUSHORT(out, numTables); /* numTables */
- writeUSHORT(out, 16 * ti); /* searchRange */
- writeUSHORT(out, i); /* entrySelector */
- writeUSHORT(out, 16 * (numTables - ti)); /* rangeShift */
- /* see fixupDir */
- for(i = 0; i < numTables; i++) {
- writeULONG(out, tables[i]);
- writeULONG(out, 0xDEADFACE); /* checkSum */
- writeULONG(out, 0xDEADFACE); /* offset */
- writeULONG(out, 0xDEADFACE); /* length */
- }
- return 0;
- }
- static unsigned
- computeChecksum(FILE *out, int offset, int length)
- {
- int rc;
- int i;
- unsigned sum = 0;
- if(offset % 4 != 0) {
- fprintf(stderr, "Offset %d is not a multiple of 4\n", offset);
- return ~0;
- }
- rc = fseek(out, offset, SEEK_SET);
- if(rc < 0) {
- perror("Couldn't seek");
- return ~0;
- }
- /* This relies on the fact that we always pad tables with zeroes. */
- for(i = 0; i < length; i += 4) {
- sum += readULONG(out);
- }
- return sum;
- }
- static int
- fixupDir(FILE *out, FontPtr font, int numTables, int *offset, int *length)
- {
- int rc, i;
- unsigned sum;
- for(i = 0; i < numTables; i++) {
- sum = computeChecksum(out, offset[i], length[i]);
- rc = fseek(out, 12 + 16 * i + 4, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- writeULONG(out, sum);
- writeULONG(out, offset[i]);
- writeULONG(out, length[i]);
- }
- return 0;
- }
- static int
- fixupChecksum(FILE *out, int full_length, int head_position)
- {
- int rc, checksum;
- checksum = computeChecksum(out, 0, full_length);
- rc = fseek(out, head_position + 8, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- writeULONG(out, 0xB1B0AFBA - checksum); /* checkSumAdjustment */
- return 0;
- }
-
- static int
- writehead(FILE* out, FontPtr font)
- {
- int time_hi;
- unsigned time_lo;
- macTime(&time_hi, &time_lo);
- writeULONG(out, 0x00010000);
- writeULONG(out, 0x00010000); /* fontRevision */
- writeULONG(out, 0); /* checkSumAdjustment -- filled in later */
- writeULONG(out,0x5F0F3CF5); /* magicNumber */
- writeUSHORT(out, 1); /* flags */
- writeUSHORT(out, UNITS_PER_EM); /* unitsPerEm */
- writeLONG(out, time_hi); /* created */
- writeULONG(out, time_lo);
- writeLONG(out, time_hi); /* modified */
- writeULONG(out, time_lo);
- writeUSHORT(out, FONT_UNITS_FLOOR(min_x));
- writeUSHORT(out, FONT_UNITS_FLOOR(min_y));
- writeUSHORT(out, FONT_UNITS_CEIL(max_x));
- writeUSHORT(out, FONT_UNITS_CEIL(max_y));
- writeUSHORT(out, font->flags); /* macStyle */
- writeUSHORT(out, 1); /* lowestRecPPEM */
- writeSHORT(out, 0); /* fontDirectionHint */
- writeSHORT(out, 0); /* indexToLocFormat */
- writeSHORT(out, 0); /* glyphDataFormat */
- return 0;
- }
- static int
- outputRaster(FILE *out, char *raster, int width, int height, int stride,
- int bit_aligned)
- {
- int i, j;
- int len = 0;
- if(!bit_aligned || width % 8 == 0) {
- for(i = 0; i < height; i++) {
- writeCHARs(out, raster + i * stride, (width + 7) / 8);
- len += (width + 7) / 8;
- }
- } else {
- int bit = 0;
- unsigned char v = 0;
- for(i = 0; i < height; i++) {
- for(j = 0; j < width; j++) {
- if(BITREF(raster, stride, j, i))
- v |= 1 << (7 - bit);
- bit++;
- if(bit >= 8) {
- writeBYTE(out, v);
- len++;
- bit = 0;
- v = 0;
- }
- }
- }
- if(bit > 0) {
- writeBYTE(out, v);
- len++;
- }
- }
- return len;
- }
- static int
- writeEBDT(FILE* out, FontPtr font)
- {
- StrikePtr strike;
- BitmapPtr bitmap;
- IndexSubTablePtr table;
- int i;
- int offset;
- int ebdt_start;
- ebdt_start = ftell(out);
- writeULONG(out, 0x00020000); /* version */
- offset = 4;
- strike = font->strikes;
- while(strike) {
- table = strike->indexSubTables;
- while(table) {
- for(i = table->firstGlyphIndex; i <= table->lastGlyphIndex; i++) {
- bitmap = strikeBitmapIndex(strike, current_cmap, i);
- bitmap->location = offset;
- if(bit_aligned_flag && table->constantMetrics) {
- /* image format 5 */
- ;
- } else {
- /* image format 1 or 2 */
- writeBYTE(out, bitmap->height);
- writeBYTE(out, bitmap->width);
- writeCHAR(out, bitmap->horiBearingX);
- writeCHAR(out, bitmap->horiBearingY);
- writeBYTE(out, bitmap->advanceWidth);
- offset += 5;
- }
- offset += outputRaster(out,
- bitmap->raster,
- bitmap->width, bitmap->height,
- bitmap->stride,
- bit_aligned_flag);
- }
- table->lastLocation = offset;
- table = table->next;
- }
- strike = strike->next;
- }
- if(ftell(out) != ebdt_start + offset)
- abort();
- return 0;
- }
- static int
- writeSbitLineMetrics(FILE *out, StrikePtr strike, int num, int den)
- {
- int width_max, x_min, y_min, x_max, y_max;
- strikeMetrics(strike, &width_max, &x_min, &y_min, &x_max, &y_max);
- writeCHAR(out, y_max); /* ascender */
- writeCHAR(out, y_min); /* descender */
- writeBYTE(out, width_max); /* widthMax */
- writeCHAR(out, num); /* caretSlopeNumerator */
- writeCHAR(out, den); /* caretSlopeDenominator */
- writeCHAR(out, 0); /* caretOffset */
- writeCHAR(out, 0); /* minOriginSB */
- writeCHAR(out, 0); /* minAdvanceSB */
- writeCHAR(out, 0); /* maxBeforeBL */
- writeCHAR(out, 0); /* minAfterBL */
- writeCHAR(out, 0); /* pad1 */
- writeCHAR(out, 0); /* pad2 */
- return 0;
- }
- static int
- writeEBLC(FILE* out, FontPtr font)
- {
- int i, rc, numstrikes, eblc_start, num, den;
- StrikePtr strike;
- IndexSubTablePtr table;
- degreesToFraction(font->italicAngle, &num, &den);
- numstrikes = 0;
- strike = font->strikes;
- while(strike) {
- numstrikes++;
- strike = strike->next;
- }
- eblc_start = ftell(out);
-
- writeULONG(out, 0x00020000); /* version */
- writeULONG(out, numstrikes); /* numSizes */
- /* bitmapSizeTable */
- strike = font->strikes;
- while(strike) {
- strike->bitmapSizeTableLocation = ftell(out);
- writeULONG(out, 0xDEADFACE); /* indexSubTableArrayOffset */
- writeULONG(out, 0xDEADFACE); /* indexTablesSize */
- writeULONG(out, 0xDEADFACE); /* numberOfIndexSubTables */
- writeULONG(out, 0); /* colorRef */
- writeSbitLineMetrics(out, strike, num, den);
- writeSbitLineMetrics(out, strike, num, den);
- writeUSHORT(out, 0); /* startGlyphIndex */
- writeUSHORT(out, 0xFFFD); /* endGlyphIndex */
- writeBYTE(out, strike->sizeX); /* ppemX */
- writeBYTE(out, strike->sizeY); /* ppemY */
- writeBYTE(out, 1); /* bitDepth */
- writeCHAR(out, 1); /* flags */
- strike = strike->next;
- }
- /* indexSubTableArray, one per strike */
- strike = font->strikes;
- while(strike) {
- int endoffset;
- int numtables = 0;
- strike->indexSubTableLocation = ftell(out);
- table = strike->indexSubTables;
- while(table) {
- table->location = ftell(out);
- writeUSHORT(out, table->firstGlyphIndex);
- writeUSHORT(out, table->lastGlyphIndex);
- writeULONG(out, 0xDEADFACE); /* additionalOffsetToIndexSubtable */
- numtables++;
- table = table->next;
- }
- endoffset = ftell(out);
- rc = fseek(out, strike->bitmapSizeTableLocation, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- writeULONG(out, strike->indexSubTableLocation - eblc_start);
- /* indexSubTableArrayOffset */
- writeULONG(out, endoffset - strike->indexSubTableLocation);
- /* indexTablesSize */
- writeULONG(out, numtables); /* numberOfIndexSubTables */
- rc = fseek(out, endoffset, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- strike = strike->next;
- }
- /* actual indexSubTables */
- strike = font->strikes;
- while(strike) {
- int vertAdvance, y_min, y_max;
- strikeMetrics(strike, NULL, NULL, &y_min, NULL, &y_max);
- vertAdvance = y_max - y_min;
- table = strike->indexSubTables;
- while(table) {
- int location;
- int data_location;
- int short_offsets;
- int offset;
- location = ftell(out);
- rc = fseek(out, table->location + 4, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- /* additionalOffsetToIndexSubtable */
- writeULONG(out, location - strike->indexSubTableLocation);
- rc = fseek(out, location, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- data_location =
- strikeBitmapIndex(strike, current_cmap,
- table->firstGlyphIndex)->location;
- short_offsets = 1;
- for(i = table->firstGlyphIndex; i <= table->lastGlyphIndex; i++) {
- if(strikeBitmapIndex(strike, current_cmap, i)->location -
- data_location > 0xFFFF) {
- short_offsets = 0;
- break;
- }
- }
- /* indexFormat */
- if(table->constantMetrics)
- writeUSHORT(out, 2);
- else if(short_offsets)
- writeUSHORT(out, 3);
- else
- writeUSHORT(out, 1);
- /* imageFormat */
- if(bit_aligned_flag) {
- if(table->constantMetrics)
- writeUSHORT(out, 5);
- else
- writeUSHORT(out, 2);
- } else {
- writeUSHORT(out, 1);
- }
- writeULONG(out, data_location);
- if(table->constantMetrics) {
- int size;
- BitmapPtr bitmap =
- strikeBitmapIndex(strike, current_cmap,
- table->firstGlyphIndex);
- size =
- strikeBitmapIndex(strike, current_cmap,
- table->firstGlyphIndex + 1)->location -
- bitmap->location;
- writeULONG(out, size); /* imageSize */
- /* bigMetrics */
- writeBYTE(out, bitmap->height);
- writeBYTE(out, bitmap->width);
- writeCHAR(out, bitmap->horiBearingX);
- writeCHAR(out, bitmap->horiBearingY);
- writeBYTE(out, bitmap->advanceWidth);
- writeCHAR(out, bitmap->horiBearingX); /* vertBearingX */
- writeCHAR(out, bitmap->horiBearingY); /* vertBearingY */
- writeBYTE(out, vertAdvance); /* vertAdvance */
- } else {
- for(i = table->firstGlyphIndex;
- i <= table->lastGlyphIndex; i++) {
- offset =
- strikeBitmapIndex(strike, current_cmap, i)->location -
- data_location;
- if(short_offsets)
- writeUSHORT(out, offset);
- else
- writeULONG(out, offset);
- }
- /* Dummy glyph of size 0 to mark the end of the table */
- if(short_offsets) {
- writeUSHORT(out, table->lastLocation - data_location);
- writeUSHORT(out, table->lastLocation - data_location);
- } else {
- writeULONG(out, table->lastLocation - data_location);
- writeULONG(out, table->lastLocation - data_location);
- }
- }
- location = ftell(out);
- while(location % 4 != 0) {
- writeCHAR(out, 0);
- location--;
- }
- table = table->next;
- }
- strike = strike->next;
- }
- return 0;
- }
- static int
- writecmap(FILE* out, FontPtr font)
- {
- int rc, cmap_start, cmap_end;
- CmapPtr cmap;
- int segcount;
- segcount = 0;
- cmap = current_cmap;
- while(cmap) {
- segcount++;
- cmap = cmap->next;
- }
- segcount++; /* dummy segment to end table */
- cmap_start = ftell(out);
- writeUSHORT(out, 0); /* version */
- writeUSHORT(out, 1); /* number of encoding tables */
- writeUSHORT(out, 3); /* platform ID */
- writeUSHORT(out, (font->flags & FACE_SYMBOL) ? 0 : 1);
- /* encoding ID */
- writeULONG(out, 12); /* offset to beginning of subtable */
- /* subtable */
- writeUSHORT(out, 4); /* format */
- writeUSHORT(out, 0xDEAD); /* length */
- writeUSHORT(out, 0); /* language */
- /* How baroque can you get? */
- writeUSHORT(out, segcount * 2); /* segCountX2 */
- writeUSHORT(out, 2 * two_log2_floor(segcount)); /* searchRange */
- writeUSHORT(out, 1 + log2_floor(segcount)); /* entrySelector */
- writeUSHORT(out, 2 * (segcount - two_log2_floor(segcount)));
- /* rangeShift */
- cmap = current_cmap;
- while(cmap) {
- writeUSHORT(out, cmap->endCode);
- cmap = cmap->next;
- }
- writeUSHORT(out, 0xFFFF);
- writeUSHORT(out, 0); /* reservedPad */
- cmap = current_cmap;
- while(cmap) {
- writeUSHORT(out, cmap->startCode);
- cmap = cmap->next;
- }
- writeUSHORT(out, 0xFFFF);
- /* idDelta */
- cmap = current_cmap;
- while(cmap) {
- writeUSHORT(out, (cmap->index - cmap->startCode) & 0xFFFF);
- cmap = cmap->next;
- }
- writeUSHORT(out, 1);
- /* idRangeOffset */
- cmap = current_cmap;
- while(cmap) {
- writeUSHORT(out, 0);
- cmap = cmap->next;
- }
- writeUSHORT(out, 0);
- /* glyphIDArray is empty */
- cmap_end = ftell(out);
- rc = fseek(out, cmap_start + 12 + 2, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- writeUSHORT(out, cmap_end - cmap_start - 12); /* length */
- rc = fseek(out, cmap_end, SEEK_SET);
- if(rc != 0) {
- perror("Couldn't seek");
- return -1;
- }
- return 0;
- }
- static int
- writeglyf(FILE* out, FontPtr font)
- {
- return 0;
- }
- int
- writehhea(FILE* out, FontPtr font)
- {
- int num, den;
- degreesToFraction(font->italicAngle, &num, &den);
- writeULONG(out, 0x00010000); /* version */
- writeSHORT(out, FONT_UNITS_CEIL(max_y)); /* ascender */
- writeSHORT(out, FONT_UNITS_FLOOR(min_y)); /* descender */
- writeSHORT(out, FONT_UNITS(TWO_SIXTEENTH / 20)); /* lineGap */
- writeUSHORT(out, FONT_UNITS(max_awidth)); /* advanceWidthMax */
- writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minLeftSideBearing */
- writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minRightSideBearing */
- writeSHORT(out, FONT_UNITS_CEIL(max_x)); /* xMaxExtent */
- writeSHORT(out, den); /* caretSlopeRise */
- writeSHORT(out, num); /* caretSlopeRun */
- writeSHORT(out, 0); /* reserved */
- writeSHORT(out, 0); /* reserved */
- writeSHORT(out, 0); /* reserved */
- writeSHORT(out, 0); /* reserved */
- writeSHORT(out, 0); /* reserved */
- writeSHORT(out, 0); /* metricDataFormat */
- writeSHORT(out, nummetrics); /* numberOfHMetrics */
- return 0;
- }
- static int
- writehmtx(FILE* out, FontPtr font)
- {
- int rc, i;
- for(i = 0; i <= numglyphs; i++) {
- int code, width, lsb;
- code = findCode(current_cmap, i);
- if(code < 0)
- rc = -1;
- else
- rc = glyphMetrics(font, code, &width, &lsb, NULL, NULL, NULL);
- if(rc < 0) {
- width = UNITS_PER_EM / 3;
- lsb = 0;
- }
- if(i < nummetrics) {
- writeSHORT(out, FONT_UNITS(width));
- writeSHORT(out, FONT_UNITS(lsb));
- } else {
- writeSHORT(out, FONT_UNITS(lsb));
- }
- }
- return 0;
- }
- static int
- writeloca(FILE* out, FontPtr font)
- {
- int i;
- /* All glyphs undefined -- loca table is empty, so offset 0 */
- for(i = 0; i < numglyphs; i++) {
- writeSHORT(out, 0);
- }
- writeSHORT(out, 0);
- return 0;
- }
- static int
- writemaxp(FILE* out, FontPtr font)
- {
- writeLONG(out, 0x00010000); /* version */
- writeUSHORT(out, numglyphs); /* numGlyphs */
- writeUSHORT(out, 0); /* maxPoints */
- writeUSHORT(out, 0); /* maxContours */
- writeUSHORT(out, 0); /* maxCompositePoints */
- writeUSHORT(out, 0); /* maxCompositeContours */
- writeUSHORT(out, 1); /* maxZones */
- writeUSHORT(out, 0); /* maxTwilightPoints */
- writeUSHORT(out, 0); /* maxStorage */
- writeUSHORT(out, 0); /* maxFunctionDefs */
- writeUSHORT(out, 0); /* maxInstructionDefs */
- writeUSHORT(out, 0); /* maxStackElements */
- writeUSHORT(out, 0); /* maxSizeOfInstructions */
- writeUSHORT(out, 0); /* maxComponentElements */
- writeUSHORT(out, 0); /* maxComponentDepth */
- return 0;
- }
- static int
- writename(FILE* out, FontPtr font)
- {
- int i;
- int offset;
- writeUSHORT(out, 0); /* format selector */
- writeUSHORT(out, font->numNames);
- writeUSHORT(out, 6 + font->numNames * 12); /* offset to string storage */
- offset = 0;
- for(i = 0; i < font->numNames; i++) {
- writeUSHORT(out, 3); /* platform id -- Microsoft */
- writeUSHORT(out, 1); /* encoding -- Unicode */
- writeUSHORT(out, 0x409); /* language id -- American English */
- writeUSHORT(out, font->names[i].nid); /* name id */
- writeUSHORT(out, font->names[i].size); /* string length */
- writeUSHORT(out, offset); /* string offset */
- offset += font->names[i].size;
- }
- for(i = 0; i < font->numNames; i++)
- writeCHARs(out, font->names[i].value, font->names[i].size);
- return 0;
- }
- static int
- writepost(FILE* out, FontPtr font)
- {
- int i, rc, previous_width, width, fixed_pitch;
- fixed_pitch = 1;
- previous_width = -1;
- for(i = 0; i < FONT_CODES; i++) {
- rc = glyphMetrics(font, i, &width, NULL, NULL, NULL, NULL);
- if(rc < 0)
- continue;
- if(previous_width >= 0) {
- if(width != previous_width) {
- fixed_pitch = 0;
- break;
- }
- }
- previous_width = width;
- }
-
- writeULONG(out, 0x00030000); /* FormatType */
- writeULONG(out, font->italicAngle); /* italicAngle */
- writeSHORT(out, FONT_UNITS(font->underlinePosition));
- writeSHORT(out, FONT_UNITS(font->underlineThickness));
- writeULONG(out, fixed_pitch); /* isFixedPitch */
- writeULONG(out, 0); /* minMemType42 */
- writeULONG(out, 0); /* maxMemType42 */
- writeULONG(out, 0); /* minMemType1 */
- writeULONG(out, 0); /* maxMemType1 */
- return 0;
- }
- static int
- writeOS2(FILE* out, FontPtr font)
- {
- int i;
- writeUSHORT(out, 0x0001);
- writeSHORT(out, FONT_UNITS(max_awidth / 2)); /* xAvgCharWidth; */
- writeUSHORT(out, font->weight); /* usWeightClass; */
- writeUSHORT(out, font->width); /* usWidthClass; */
- writeSHORT(out, 0); /* fsType; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptXSize; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptYSize; */
- writeSHORT(out, 0); /* ySubscriptXOffset; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySubscriptYOffset; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptXSize; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYSize; */
- writeSHORT(out, 0); /* ySuperscriptXOffset; */
- writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYOffset; */
- writeSHORT(out, FONT_UNITS(font->underlineThickness));
- /* yStrikeoutSize; */
- writeSHORT(out, UNITS_PER_EM / 4); /* yStrikeoutPosition; */
- writeSHORT(out, 0); /* sFamilyClass; */
- for(i = 0; i < 10; i++)
- writeBYTE(out, 0); /* panose; */
- writeULONG(out, 0xFFFF); /* ulUnicodeRange1; */
- writeULONG(out, 0xFFFF); /* ulUnicodeRange2; */
- writeULONG(out, 0x03FF); /* ulUnicodeRange3; */
- writeULONG(out, 0U); /* ulUnicodeRange4; */
- writeULONG(out, font->foundry); /* achVendID[4]; */
- writeUSHORT(out, 0x0040); /* fsSelection; */
- writeUSHORT(out, 0x20); /* usFirstCharIndex; */
- writeUSHORT(out, 0xFFFD); /* usLastCharIndex; */
- writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* sTypoAscender; */
- writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* sTypoDescender; */
- writeUSHORT(out, FONT_UNITS(max_y - min_y));
- /* sTypoLineGap; */
- writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* usWinAscent; */
- writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* usWinDescent; */
- writeULONG(out, 3); /* ulCodePageRange1; */
- writeULONG(out, 0); /* ulCodePageRange2; */
- return 0;
- }
- static int
- writePCLT(FILE* out, FontPtr font)
- {
- char name[16] = "X11 font ";
- char filename[6] = "X11R00";
- unsigned char charComplement[8] =
- {0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0xFE};
- int style, w, strokeWeight, widthType;
- style = 0;
- if(font->flags & FACE_ITALIC)
- style = 1;
- w = (font->weight + 50) / 100;
- if(w < 5)
- strokeWeight = w - 6;
- else if(w == 5)
- strokeWeight = 0;
- else
- strokeWeight = w - 4;
- if(font->width <= 2)
- widthType = -3;
- else if(font->width <= 4)
- widthType = -2;
- else if(font->width <= 6)
- widthType = 0;
- else if(font->width <= 7)
- widthType = 2;
- else
- widthType = 3;
- writeULONG(out, 0x00010000); /* version */
- writeULONG(out, 0); /* FontNumber */
- writeUSHORT(out, FONT_UNITS(max_awidth)); /* pitch */
- writeUSHORT(out, FONT_UNITS(max_y)); /* xHeight */
- writeUSHORT(out, style); /* style */
- writeUSHORT(out, 6 << 12); /* TypeFamily */
- writeUSHORT(out, FONT_UNITS(max_y)); /* CapHeight */
- writeUSHORT(out, 0); /* SymbolSet */
- writeCHARs(out, name, 16); /* TypeFace */
- writeBYTEs(out, charComplement, 8); /* CharacterComplement */
- writeCHARs(out, filename, 6); /* FileName */
- writeCHAR(out, strokeWeight); /* StrokeWeight */
- writeCHAR(out, widthType); /* WidthType */
- writeCHAR(out, 1 << 6); /* SerifStyle */
- writeCHAR(out, 0); /* Reserved */
- return 0;
- }
|