From 2038c15dc3b8c22155d88a6964c89a5eb0a277d9 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Mon, 11 May 2009 13:47:43 +0000 Subject: Make outlines output write latin1 glyphs first svn path=/trunk/tools/ttf2f/; revision=7466 --- src/outlines.c | 339 ++++++++++++++++++++++++++++++++------------------------- src/outlines.h | 1 - 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*)¤t_chunk_offset, sizeof(int), - 1, output) != 1) goto error_write; + if (fwrite(¤t_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*)¤t_chunk_offset, sizeof(int), 1, output) != 1) - goto error_write; - - if (fwrite((void*)¤t_chunk_offset, sizeof(int), 1, output) != 1) + if (fwrite(¤t_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*)¤t_chunk_offset, sizeof(int), 1, + if (fwrite(¤t_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 { -- cgit v1.2.3