summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-05-11 13:47:43 (GMT)
committer John Mark Bell <jmb@netsurf-browser.org>2009-05-11 13:47:43 (GMT)
commit2038c15dc3b8c22155d88a6964c89a5eb0a277d9 (patch)
treeb1000dd265907d1805a951c1dfacb391a31c42f3
parentd68c4c5f75a164f4dc93154b7d05e99e87ba599c (diff)
downloadttf2f-2038c15dc3b8c22155d88a6964c89a5eb0a277d9.tar.gz
ttf2f-2038c15dc3b8c22155d88a6964c89a5eb0a277d9.tar.bz2
Make outlines output write latin1 glyphs first
svn path=/trunk/tools/ttf2f/; revision=7466
-rw-r--r--src/outlines.c339
-rw-r--r--src/outlines.h1
2 files changed, 192 insertions, 148 deletions
diff --git a/src/outlines.c b/src/outlines.c
index 77b8266..dab386d 100644
--- a/src/outlines.c
+++ b/src/outlines.c
@@ -12,8 +12,11 @@
#include "outlines.h"
#include "utils.h"
-ttf2f_result write_chunk(FILE* file, int chunk_no, ttf2f_ctx *ctx,
+static ttf2f_result write_chunk(FILE* file, unsigned int chunk_no,
+ ttf2f_ctx *ctx, size_t *cur_glyph,
unsigned int *out_chunk_size);
+static ttf2f_result append_glyph(struct glyph *g, size_t idx, ttf2f_ctx *ctx,
+ struct chunk **chunk, unsigned int *chunk_size);
/**
* Write the font outlines to file
@@ -30,9 +33,14 @@ ttf2f_result outlines_write(const char *savein, const char *name,
int table_end_len, i;
unsigned int current_chunk_offset;
unsigned int chunk_table_entry;
+ size_t cur_glyph = 0;
+ unsigned int slots;
FILE *output;
char out[1024];
+ /* Number of slots in chunk tables */
+ slots = ctx->nglyphs + N_ELEMENTS(ctx->latin1tab) - ctx->nlatin1;
+
/* length of name + \0 + "Outlines" + \0 */
table_end_len = strlen(name) + 10;
@@ -47,7 +55,7 @@ ttf2f_result outlines_write(const char *savein, const char *name,
header.Y = ctx->metrics->bbox[3] - ctx->metrics->bbox[1];
header.chunk_data.chunk_table_offset =
sizeof(struct outlines_header) + ((table_end_len + 6) & ~3);
- header.chunk_data.nchunks = (ctx->nglyphs / 32) + 2;
+ header.chunk_data.nchunks = ((slots + 31) & ~31) / 32;
header.chunk_data.num_scaffold = 1; /* no scaffold lines */
header.chunk_data.scaffold_flags = OUTLINES_SCAFFOLD_16BIT |
OUTLINES_SCAFFOLD_NON_ZERO_WINDING;
@@ -58,11 +66,11 @@ ttf2f_result outlines_write(const char *savein, const char *name,
header.chunk_data.reserved[4] = 0;
snprintf(out, 1024, "%s" DIR_SEP "Outlines", savein);
- if ((output = fopen(out, "wb+") ) == NULL)
+ if ((output = fopen(out, "wb") ) == NULL)
return TTF2F_RESULT_OPEN;
/* write file header */
- if (fwrite((void*)&header, sizeof(struct outlines_header), 1, output)
+ if (fwrite(&header, sizeof(struct outlines_header), 1, output)
!= 1) goto error_write;
/* write scaffold table */
@@ -78,8 +86,10 @@ ttf2f_result outlines_write(const char *savein, const char *name,
/* word align */
i = table_end_len + 3 + sizeof(struct outlines_header);
- while (i++ < header.chunk_data.chunk_table_offset)
- if (fputc(0x0, output) == EOF) goto error_write;
+ while (i++ < header.chunk_data.chunk_table_offset) {
+ if (fputc(0x0, output) == EOF)
+ goto error_write;
+ }
/* write chunk table */
chunk_table_entry = 1;
@@ -88,8 +98,8 @@ ttf2f_result outlines_write(const char *savein, const char *name,
/* initialise chunk table */
for (i = 0; i <= header.chunk_data.nchunks; i++) {
- if (fwrite((void*)&current_chunk_offset, sizeof(int),
- 1, output) != 1) goto error_write;
+ if (fwrite(&current_chunk_offset, sizeof(int), 1, output) != 1)
+ goto error_write;
}
/* write copyright information to file */
@@ -102,24 +112,21 @@ ttf2f_result outlines_write(const char *savein, const char *name,
current_chunk_offset += 42 + strlen(ctx->metrics->name_full) +
strlen(ctx->metrics->name_copyright);
- while(current_chunk_offset % 4) {
+ while (current_chunk_offset % 4) {
if (fputc(0x0, output) == EOF) goto error_write;
current_chunk_offset++;
}
- /* fill in offsets 0 and 1 */
+ /* Write first chunk offset */
fseek(output, header.chunk_data.chunk_table_offset, SEEK_SET);
- if (fwrite((void*)&current_chunk_offset, sizeof(int), 1, output) != 1)
- goto error_write;
-
- if (fwrite((void*)&current_chunk_offset, sizeof(int), 1, output) != 1)
+ if (fwrite(&current_chunk_offset, sizeof(int), 1, output) != 1)
goto error_write;
for (; header.chunk_data.nchunks > 1; header.chunk_data.nchunks--) {
unsigned int chunk_size;
ttf2f_result err;
- callback((chunk_table_entry * 100) / ((ctx->nglyphs / 32) + 2));
+ callback((chunk_table_entry * 100) / ((slots + 31) + ~31) / 32);
ttf2f_poll(1);
/* seek to start of current chunk */
@@ -127,7 +134,7 @@ ttf2f_result outlines_write(const char *savein, const char *name,
/* write chunk */
err = write_chunk(output, chunk_table_entry - 1, ctx,
- &chunk_size);
+ &cur_glyph, &chunk_size);
if (err != TTF2F_RESULT_OK) {
fclose(output);
@@ -145,7 +152,7 @@ ttf2f_result outlines_write(const char *savein, const char *name,
/* fill in next chunk table entry */
fseek(output, header.chunk_data.chunk_table_offset +
(chunk_table_entry+1) * 4, SEEK_SET);
- if (fwrite((void*)&current_chunk_offset, sizeof(int), 1,
+ if (fwrite(&current_chunk_offset, sizeof(int), 1,
output) != 1) goto error_write;
chunk_table_entry++;
@@ -170,17 +177,16 @@ error_write:
* \param file Stream handle
* \param chunk_no The current chunk number (0..nchunks-1)
* \param ctx Conversion context
+ * \param cur_glyph Current glyph index
* \return Size of this chunk, or 0 on failure
*/
-ttf2f_result write_chunk(FILE* file, int chunk_no, ttf2f_ctx *ctx,
- unsigned int *out_chunk_size)
+ttf2f_result write_chunk(FILE* file, unsigned int chunk_no, ttf2f_ctx *ctx,
+ size_t *cur_glyph, unsigned int *out_chunk_size)
{
- const struct glyph *g;
+ ttf2f_result err;
+ struct glyph *g;
struct chunk *chunk;
unsigned int chunk_size;
- struct outline *o, *next;
- struct char_data *character;
- size_t i;
*out_chunk_size = 0;
@@ -193,144 +199,56 @@ ttf2f_result write_chunk(FILE* file, int chunk_no, ttf2f_ctx *ctx,
chunk_size = sizeof(struct chunk);
- /* 32 chars in each chunk */
- for (i = 0; i != 32; i++) {
-
- ttf2f_poll(1);
+ if (chunk_no < N_ELEMENTS(ctx->latin1tab) / 32) {
+ size_t i;
- if ((chunk_no * 32) + i >= ctx->nglyphs)
- /* exit if we've reached the end of the input */
- break;
+ /* Latin 1 table */
+ for (i = 0; i != 32; i++) {
+ g = ctx->latin1tab[(chunk_no * 32) + i];
+ /* Skip undefined glyphs */
+ if (g == NULL)
+ continue;
- /* get glyph */
- g = &ctx->glyphs[(chunk_no * 32) + i];
+ err = append_glyph(g, i, ctx, &chunk, &chunk_size);
+ if (err != TTF2F_RESULT_OK) {
+ free(chunk);
+ return err;
+ }
- /* no path => skip character */
- if (g->ttf_pathlen == 0) {
- chunk->offset[i] = 0;
- continue;
+ g->done_outlines = 1;
}
+ } else {
+ size_t nchars = 0;
+ size_t idx = *cur_glyph;
+
+ /* Everything else */
+ while (nchars < 32) {
+ /* Done if there are no more glyphs */
+ if (idx == ctx->nglyphs)
+ break;
- /* offset from index start */
- chunk->offset[i] = chunk_size - 4;
-
- chunk = realloc((char*)chunk,
- chunk_size+sizeof(struct char_data));
- if (chunk == NULL)
- return TTF2F_RESULT_NOMEM;
-
- character = (struct char_data*)(void*)((char*)chunk + chunk_size);
-
- chunk_size += sizeof(struct char_data);
-
- character->flags = CHAR_12BIT_COORDS | CHAR_OUTLINE;
- /* character x0, y0 */
- character->x0y0[0] = g->xMin & 0xFF;
- character->x0y0[1] = ((g->yMin << 4) & 0xF0) |
- ((g->xMin >> 8) & 0xF);
- character->x0y0[2] = (g->yMin >> 4) & 0xFF;
- /* character width, height */
- character->xsys[0] = (g->xMax - g->xMin) & 0xFF;
- character->xsys[1] = (((g->yMax - g->yMin) << 4) & 0xF) |
- (((g->xMax - g->xMin) >> 8) & 0xF);
- character->xsys[2] = ((g->yMax - g->yMin) >> 4) & 0xFF;
-
- /* decompose glyph path */
- glpath(ctx, (chunk_no * 32) + i);
+ g = &ctx->glyphs[idx++];
- for (o = g->outline; o; o = next) {
- if (!o)
- break;
+ /* Skip glyphs already written */
+ if (g->done_outlines)
+ continue;
- /* movement type */
- switch (o->type) {
- case TERMINATE:
- /* end of outline */
- chunk = realloc((char*)chunk, chunk_size + 1);
- if (chunk == NULL)
- return TTF2F_RESULT_NOMEM;
- *((char*)chunk+chunk_size-1) = 0;
- chunk_size += 1;
- break;
- case MOVE_TO:
- /* move to point */
- chunk = realloc((char*)chunk, chunk_size + 4);
- if (chunk == NULL)
- return TTF2F_RESULT_NOMEM;
- /* id, no scaffold */
- *((char*)chunk+chunk_size-1) = 1;
- /* x, y */
- *((char*)chunk+chunk_size) =
- o->data.move_to.x & 0xFF;
- *((char*)chunk+chunk_size+1) =
- (((o->data.move_to.y << 4) & 0xF0) |
- ((o->data.move_to.x >> 8) & 0xF));
- *((char*)chunk+chunk_size+2) =
- (o->data.move_to.y >> 4) & 0xFF;
- chunk_size += 4;
- break;
- case LINE_TO:
- /* draw line to point */
- chunk = realloc((char*)chunk, chunk_size + 4);
- if (chunk == NULL)
- return TTF2F_RESULT_NOMEM;
- /* id, no scaffold */
- *((char*)chunk+chunk_size-1) = 2;
- /* x, y */
- *((char*)chunk+chunk_size) =
- o->data.line_to.x & 0xFF;
- *((char*)chunk+chunk_size+1) =
- (((o->data.line_to.y << 4) & 0xF0) |
- ((o->data.line_to.x >> 8) & 0xF));
- *((char*)chunk+chunk_size+2) =
- (o->data.line_to.y >> 4) & 0xFF;
- chunk_size += 4;
- break;
- case CURVE:
- /* draw bezier curve to point */
- chunk = realloc((char*)chunk, chunk_size + 10);
- if (chunk == NULL)
- return TTF2F_RESULT_NOMEM;
- /* id, no scaffold */
- *((char*)chunk+chunk_size-1) = 3;
- /* x1, y1 */
- *((char*)chunk+chunk_size) =
- o->data.curve.x1 & 0xFF;
- *((char*)chunk+chunk_size+1) =
- (((o->data.curve.y1 << 4) & 0xF0) |
- ((o->data.curve.x1 >> 8) & 0xF));
- *((char*)chunk+chunk_size+2) =
- (o->data.curve.y1 >> 4) & 0xFF;
- /* x2, y2 */
- *((char*)chunk+chunk_size+3) =
- o->data.curve.x2 & 0xFF;
- *((char*)chunk+chunk_size+4) =
- (((o->data.curve.y2 << 4) & 0xF0) |
- ((o->data.curve.x2 >> 8) & 0xF));
- *((char*)chunk+chunk_size+5) =
- (o->data.curve.y2 >> 4) & 0xFF;
- /* x3, y3 */
- *((char*)chunk+chunk_size+6) =
- o->data.curve.x3 & 0xFF;
- *((char*)chunk+chunk_size+7) =
- (((o->data.curve.y3 << 4) & 0xF0) |
- ((o->data.curve.x3 >> 8) & 0xF));
- *((char*)chunk+chunk_size+8) =
- (o->data.curve.y3 >> 4) & 0xFF;
- chunk_size += 10;
- break;
+ err = append_glyph(g, nchars, ctx, &chunk, &chunk_size);
+ if (err != TTF2F_RESULT_OK) {
+ free(chunk);
+ return err;
}
- next = o->next;
- free(o);
+ g->done_outlines = 1;
+
+ nchars++;
}
- /* shift chunk end pointer to end of character */
- chunk_size -= 1;
+ *cur_glyph = idx;
}
/* write chunk to file */
- if (fwrite((void*)chunk, chunk_size, 1, file) != 1) {
+ if (fwrite(chunk, chunk_size, 1, file) != 1) {
free(chunk);
return TTF2F_RESULT_WRITE;
}
@@ -342,3 +260,130 @@ ttf2f_result write_chunk(FILE* file, int chunk_no, ttf2f_ctx *ctx,
return TTF2F_RESULT_OK;
}
+ttf2f_result append_glyph(struct glyph *g, size_t idx, ttf2f_ctx *ctx,
+ struct chunk **chunk, unsigned int *chunk_size)
+{
+ struct chunk *temp;
+ struct outline *o, *next;
+ struct char_data *character;
+ size_t outline_size = 0;
+ char *outline;
+
+ ttf2f_poll(1);
+
+ /* no path => skip character */
+ if (g->ttf_pathlen == 0) {
+ (*chunk)->offset[idx] = 0;
+ return TTF2F_RESULT_OK;
+ }
+
+ /* offset from index start */
+ (*chunk)->offset[idx] = (*chunk_size) - 4;
+
+ temp = realloc((*chunk), (*chunk_size) + sizeof(struct char_data));
+ if (temp == NULL)
+ return TTF2F_RESULT_NOMEM;
+ (*chunk) = temp;
+
+ character = (void *)((char *) (*chunk) + (*chunk_size));
+
+ (*chunk_size) += sizeof(struct char_data);
+
+ character->flags = CHAR_12BIT_COORDS | CHAR_OUTLINE;
+ /* character x0, y0 */
+ character->x0y0[0] = g->xMin & 0xFF;
+ character->x0y0[1] = ((g->yMin << 4) & 0xF0) | ((g->xMin >> 8) & 0xF);
+ character->x0y0[2] = (g->yMin >> 4) & 0xFF;
+ /* character width, height */
+ character->xsys[0] = (g->xMax - g->xMin) & 0xFF;
+ character->xsys[1] = (((g->yMax - g->yMin) << 4) & 0xF) |
+ (((g->xMax - g->xMin) >> 8) & 0xF);
+ character->xsys[2] = ((g->yMax - g->yMin) >> 4) & 0xFF;
+
+ /* decompose glyph path */
+ glpath(ctx, g - ctx->glyphs);
+
+ /* Step 1: count size of outline data */
+ for (o = g->outline; o != NULL; o = o->next) {
+ /* movement type */
+ switch (o->type) {
+ case TERMINATE:
+ /* end of outline */
+ outline_size += 1;
+ break;
+ case MOVE_TO:
+ outline_size += 4;
+ break;
+ case LINE_TO:
+ outline_size += 4;
+ break;
+ case CURVE:
+ outline_size += 10;
+ break;
+ }
+ }
+
+ temp = realloc((*chunk), (*chunk_size) + outline_size);
+ if (temp == NULL)
+ return TTF2F_RESULT_NOMEM;
+ (*chunk) = temp;
+
+ outline = (char *) (*chunk) + (*chunk_size);
+
+ (*chunk_size) += outline_size;
+
+ /* Step 2: populate outline data */
+ for (o = g->outline; o != NULL; o = next) {
+ switch (o->type) {
+ case TERMINATE:
+ *(outline++) = 0;
+ break;
+ case MOVE_TO:
+ /* move to point */
+ /* id, no scaffold */
+ *(outline++) = 1;
+ /* x, y */
+ *(outline++) = o->data.move_to.x & 0xFF;
+ *(outline++) = (((o->data.move_to.y << 4) & 0xF0) |
+ ((o->data.move_to.x >> 8) & 0xF));
+ *(outline++) = (o->data.move_to.y >> 4) & 0xFF;
+ break;
+ case LINE_TO:
+ /* draw line to point */
+ /* id, no scaffold */
+ *(outline++) = 2;
+ /* x, y */
+ *(outline++) = o->data.line_to.x & 0xFF;
+ *(outline++) = (((o->data.line_to.y << 4) & 0xF0) |
+ ((o->data.line_to.x >> 8) & 0xF));
+ *(outline++) = (o->data.line_to.y >> 4) & 0xFF;
+ break;
+ case CURVE:
+ /* draw bezier curve to point */
+ /* id, no scaffold */
+ *(outline++) = 3;
+ /* x1, y1 */
+ *(outline++) = o->data.curve.x1 & 0xFF;
+ *(outline++) = (((o->data.curve.y1 << 4) & 0xF0) |
+ ((o->data.curve.x1 >> 8) & 0xF));
+ *(outline++) = (o->data.curve.y1 >> 4) & 0xFF;
+ /* x2, y2 */
+ *(outline++) = o->data.curve.x2 & 0xFF;
+ *(outline++) = (((o->data.curve.y2 << 4) & 0xF0) |
+ ((o->data.curve.x2 >> 8) & 0xF));
+ *(outline++) = (o->data.curve.y2 >> 4) & 0xFF;
+ /* x3, y3 */
+ *(outline++) = o->data.curve.x3 & 0xFF;
+ *(outline++) = (((o->data.curve.y3 << 4) & 0xF0) |
+ ((o->data.curve.x3 >> 8) & 0xF));
+ *(outline++) = (o->data.curve.y3 >> 4) & 0xFF;
+ break;
+ }
+
+ next = o->next;
+ free(o);
+ }
+
+ return TTF2F_RESULT_OK;
+}
+
diff --git a/src/outlines.h b/src/outlines.h
index 9f2bf91..4b67ea4 100644
--- a/src/outlines.h
+++ b/src/outlines.h
@@ -32,7 +32,6 @@ struct outlines_header {
struct chunk {
unsigned int flags;
unsigned int offset[32];
- unsigned char depend[4];
};
struct char_data {