#if defined(linux) && !defined(_GNU_SOURCE)
#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;
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;
}
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)
{
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;
}
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) {
int k;
for(k = 0; k < (4 - length[j] % 4); k++) {
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) {
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);
writeUSHORT(out, numTables);
writeUSHORT(out, 16 * ti);
writeUSHORT(out, i - 1);
writeUSHORT(out, 16 * (numTables - ti));
for(i = 0; i < numTables; i++) {
writeULONG(out, tables[i]);
writeULONG(out, 0xDEADFACE);
writeULONG(out, 0xDEADFACE);
writeULONG(out, 0xDEADFACE);
}
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;
}
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);
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);
writeULONG(out, 0);
writeULONG(out,0x5F0F3CF5);
writeUSHORT(out, 1);
writeUSHORT(out, UNITS_PER_EM);
writeLONG(out, time_hi);
writeULONG(out, time_lo);
writeLONG(out, time_hi);
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);
writeUSHORT(out, 1);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, 0);
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);
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) {
;
} else {
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);
writeCHAR(out, y_min);
writeBYTE(out, width_max);
writeCHAR(out, num);
writeCHAR(out, den);
writeCHAR(out, 0);
writeCHAR(out, 0);
writeCHAR(out, 0);
writeCHAR(out, 0);
writeCHAR(out, 0);
writeCHAR(out, 0);
writeCHAR(out, 0);
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);
writeULONG(out, numstrikes);
strike = font->strikes;
while(strike) {
strike->bitmapSizeTableLocation = ftell(out);
writeULONG(out, 0xDEADFACE);
writeULONG(out, 0xDEADFACE);
writeULONG(out, 0xDEADFACE);
writeULONG(out, 0);
writeSbitLineMetrics(out, strike, num, den);
writeSbitLineMetrics(out, strike, num, den);
writeUSHORT(out, 0);
writeUSHORT(out, 0xFFFD);
writeBYTE(out, strike->sizeX);
writeBYTE(out, strike->sizeY);
writeBYTE(out, 1);
writeCHAR(out, 1);
strike = strike->next;
}
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);
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);
writeULONG(out, endoffset - strike->indexSubTableLocation);
writeULONG(out, numtables);
rc = fseek(out, endoffset, SEEK_SET);
if(rc != 0) {
perror("Couldn't seek");
return -1;
}
strike = strike->next;
}
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;
}
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;
}
}
if(table->constantMetrics)
writeUSHORT(out, 2);
else if(short_offsets)
writeUSHORT(out, 3);
else
writeUSHORT(out, 1);
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);
writeBYTE(out, bitmap->height);
writeBYTE(out, bitmap->width);
writeCHAR(out, bitmap->horiBearingX);
writeCHAR(out, bitmap->horiBearingY);
writeBYTE(out, bitmap->advanceWidth);
writeCHAR(out, bitmap->horiBearingX);
writeCHAR(out, bitmap->horiBearingY);
writeBYTE(out, 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);
}
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++;
cmap_start = ftell(out);
writeUSHORT(out, 0);
writeUSHORT(out, 1);
writeUSHORT(out, 3);
writeUSHORT(out, (font->flags & FACE_SYMBOL) ? 0 : 1);
writeULONG(out, 12);
writeUSHORT(out, 4);
writeUSHORT(out, 0xDEAD);
writeUSHORT(out, 0);
writeUSHORT(out, segcount * 2);
writeUSHORT(out, 2 * two_log2_floor(segcount));
writeUSHORT(out, 1 + log2_floor(segcount));
writeUSHORT(out, 2 * (segcount - two_log2_floor(segcount)));
cmap = current_cmap;
while(cmap) {
writeUSHORT(out, cmap->endCode);
cmap = cmap->next;
}
writeUSHORT(out, 0xFFFF);
writeUSHORT(out, 0);
cmap = current_cmap;
while(cmap) {
writeUSHORT(out, cmap->startCode);
cmap = cmap->next;
}
writeUSHORT(out, 0xFFFF);
cmap = current_cmap;
while(cmap) {
writeUSHORT(out, (cmap->index - cmap->startCode) & 0xFFFF);
cmap = cmap->next;
}
writeUSHORT(out, 1);
cmap = current_cmap;
while(cmap) {
writeUSHORT(out, 0);
cmap = cmap->next;
}
writeUSHORT(out, 0);
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);
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);
writeSHORT(out, FONT_UNITS_CEIL(max_y));
writeSHORT(out, FONT_UNITS_FLOOR(min_y));
writeSHORT(out, FONT_UNITS(TWO_SIXTEENTH / 20));
writeUSHORT(out, FONT_UNITS(max_awidth));
writeSHORT(out, FONT_UNITS_FLOOR(min_x));
writeSHORT(out, FONT_UNITS_FLOOR(min_x));
writeSHORT(out, FONT_UNITS_CEIL(max_x));
writeSHORT(out, den);
writeSHORT(out, num);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, 0);
writeSHORT(out, nummetrics);
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;
for(i = 0; i < numglyphs; i++) {
writeSHORT(out, 0);
}
writeSHORT(out, 0);
return 0;
}
static int
writemaxp(FILE* out, FontPtr font)
{
writeLONG(out, 0x00010000);
writeUSHORT(out, numglyphs);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 1);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
writeUSHORT(out, 0);
return 0;
}
static int
writename(FILE* out, FontPtr font)
{
int i;
int offset;
writeUSHORT(out, 0);
writeUSHORT(out, font->numNames);
writeUSHORT(out, 6 + font->numNames * 12);
offset = 0;
for(i = 0; i < font->numNames; i++) {
writeUSHORT(out, 3);
writeUSHORT(out, 1);
writeUSHORT(out, 0x409);
writeUSHORT(out, font->names[i].nid);
writeUSHORT(out, font->names[i].size);
writeUSHORT(out, 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);
writeULONG(out, font->italicAngle);
writeSHORT(out, FONT_UNITS(font->underlinePosition));
writeSHORT(out, FONT_UNITS(font->underlineThickness));
writeULONG(out, fixed_pitch);
writeULONG(out, 0);
writeULONG(out, 0);
writeULONG(out, 0);
writeULONG(out, 0);
return 0;
}
static int
writeOS2(FILE* out, FontPtr font)
{
int i;
writeUSHORT(out, 0x0001);
writeSHORT(out, FONT_UNITS(max_awidth / 2));
writeUSHORT(out, font->weight);
writeUSHORT(out, font->width);
writeSHORT(out, 0);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, 0);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, 0);
writeSHORT(out, UNITS_PER_EM / 5);
writeSHORT(out, FONT_UNITS(font->underlineThickness));
writeSHORT(out, UNITS_PER_EM / 4);
writeSHORT(out, 0);
for(i = 0; i < 10; i++)
writeBYTE(out, 0);
writeULONG(out, 0xFFFF);
writeULONG(out, 0xFFFF);
writeULONG(out, 0x03FF);
writeULONG(out, 0U);
writeULONG(out, font->foundry);
writeUSHORT(out, 0x0040);
writeUSHORT(out, 0x20);
writeUSHORT(out, 0xFFFD);
writeUSHORT(out, FONT_UNITS_CEIL(max_y));
writeUSHORT(out, -FONT_UNITS_FLOOR(min_y));
writeUSHORT(out, FONT_UNITS(max_y - min_y));
writeUSHORT(out, FONT_UNITS_CEIL(max_y));
writeUSHORT(out, -FONT_UNITS_FLOOR(min_y));
writeULONG(out, 3);
writeULONG(out, 0);
return 0;
}
static int
writePCLT(FILE* out, FontPtr font)
{
char name[16] = XVENDORNAME" 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);
writeULONG(out, 0);
writeUSHORT(out, FONT_UNITS(max_awidth));
writeUSHORT(out, FONT_UNITS(max_y));
writeUSHORT(out, style);
writeUSHORT(out, 6 << 12);
writeUSHORT(out, FONT_UNITS(max_y));
writeUSHORT(out, 0);
writeCHARs(out, name, 16);
writeBYTEs(out, charComplement, 8);
writeCHARs(out, filename, 6);
writeCHAR(out, strokeWeight);
writeCHAR(out, widthType);
writeCHAR(out, 1 << 6);
writeCHAR(out, 0);
return 0;
}