From 85a5d6298ed17b0576051bd9ddb72c923e51d606 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sun, 3 Apr 2011 12:46:42 +0200 Subject: [PATCH] More files from FreeType's `autofit' and `base' modules. --- src/Makefile.am | 4 + src/tagloadr.c | 386 ++++++++++++++++++++++++++++++++++++++++ src/tagloadr.h | 116 ++++++++++++ src/taglobal.c | 8 +- src/talatin.c | 8 +- src/taloader.c | 536 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/taloader.h | 51 ++++++ src/tatypes.h | 5 + 8 files changed, 1106 insertions(+), 8 deletions(-) create mode 100644 src/tagloadr.c create mode 100644 src/tagloadr.h create mode 100644 src/taloader.c create mode 100644 src/taloader.h diff --git a/src/Makefile.am b/src/Makefile.am index fda318d..e4161af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,12 +7,16 @@ noinst_LIBRARIES = libttfautohint.a libttfautohint_a_SOURCES = ta.h \ tadummy.c \ tadummy.h \ + tagloadr.c \ + tagloadr.h \ taglobal.c \ taglobal.h \ tahints.c \ tahints.h \ talatin.c \ talatin.h \ + taloader.c \ + taloader.h \ tasort.c \ tasort.h \ tatypes.h \ diff --git a/src/tagloadr.c b/src/tagloadr.c new file mode 100644 index 0000000..554d7e2 --- /dev/null +++ b/src/tagloadr.c @@ -0,0 +1,386 @@ +/* tagloadr.c */ + +/* originally file `ftgloadr.c' (2011-Mar-28) from FreeType */ + +/* heavily modified 2011 by Werner Lemberg */ + +#include +#include + +#include "tatypes.h" +#include "tagloadr.h" + + + /*************************************************************************/ + /* */ + /* The glyph loader is a simple object which is used to load a set of */ + /* glyphs easily. It is critical for the correct loading of composites. */ + /* */ + /* Ideally, one can see it as a stack of abstract `glyph' objects. */ + /* */ + /* loader.base Is really the bottom of the stack. It describes a */ + /* single glyph image made of the juxtaposition of */ + /* several glyphs (those `in the stack'). */ + /* */ + /* loader.current Describes the top of the stack, on which a new */ + /* glyph can be loaded. */ + /* */ + /* Rewind Clears the stack. */ + /* Prepare Set up `loader.current' for addition of a new glyph */ + /* image. */ + /* Add Add the `current' glyph image to the `base' one, */ + /* and prepare for another one. */ + /* */ + /*************************************************************************/ + + +/* create a new glyph loader */ +FT_Error +TA_GlyphLoader_New(TA_GlyphLoader *aloader) +{ + TA_GlyphLoader loader; + + + loader = (TA_GlyphLoader)calloc(1, sizeof (TA_GlyphLoaderRec)); + + if (!loader) + return FT_Err_Out_Of_Memory; + + *aloader = loader; + return FT_Err_Ok; +} + + +/* rewind the glyph loader - reset counters to 0 */ +void +TA_GlyphLoader_Rewind(TA_GlyphLoader loader) +{ + TA_GlyphLoad base = &loader->base; + TA_GlyphLoad current = &loader->current; + + + base->outline.n_points = 0; + base->outline.n_contours = 0; + base->num_subglyphs = 0; + + *current = *base; +} + + +/* reset the glyph loader, frees all allocated tables */ +/* and starts from zero */ +void +TA_GlyphLoader_Reset(TA_GlyphLoader loader) +{ + free(loader->base.outline.points); + free(loader->base.outline.tags); + free(loader->base.outline.contours); + free(loader->base.extra_points); + free(loader->base.subglyphs); + + loader->base.outline.points = NULL; + loader->base.outline.tags = NULL; + loader->base.outline.contours = NULL; + loader->base.extra_points = NULL; + loader->base.subglyphs = NULL; + + loader->base.extra_points2 = NULL; + + loader->max_points = 0; + loader->max_contours = 0; + loader->max_subglyphs = 0; + + TA_GlyphLoader_Rewind(loader); +} + + +/* delete a glyph loader */ +void +TA_GlyphLoader_Done(TA_GlyphLoader loader) +{ + if (loader) + { + TA_GlyphLoader_Reset(loader); + free(loader); + } +} + + +/* re-adjust the `current' outline fields */ +static void +TA_GlyphLoader_Adjust_Points(TA_GlyphLoader loader) +{ + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + + + current->points = base->points + base->n_points; + current->tags = base->tags + base->n_points; + current->contours = base->contours + base->n_contours; + + /* handle extra points table - if any */ + if (loader->use_extra) + { + loader->current.extra_points = loader->base.extra_points + + base->n_points; + + loader->current.extra_points2 = loader->base.extra_points2 + + base->n_points; + } +} + + +FT_Error +TA_GlyphLoader_CreateExtra(TA_GlyphLoader loader) +{ + loader->base.extra_points = + (FT_Vector*)calloc(1, 2 * loader->max_points * sizeof (FT_Vector)); + if (!loader->base.extra_points) + return FT_Err_Out_Of_Memory; + + loader->use_extra = 1; + loader->base.extra_points2 = loader->base.extra_points + + loader->max_points; + + TA_GlyphLoader_Adjust_Points(loader); + + return FT_Err_Ok; +} + + +/* re-adjust the `current' subglyphs field */ +static void +TA_GlyphLoader_Adjust_Subglyphs(TA_GlyphLoader loader) +{ + TA_GlyphLoad base = &loader->base; + TA_GlyphLoad current = &loader->current; + + + current->subglyphs = base->subglyphs + base->num_subglyphs; +} + + +/* ensure that we can add `n_points' and `n_contours' to our glyph -- */ +/* this function reallocates its outline tables if necessary, */ +/* but it DOESN'T change the number of points within the loader */ +FT_Error +TA_GlyphLoader_CheckPoints(TA_GlyphLoader loader, + FT_UInt n_points, + FT_UInt n_contours) +{ + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + FT_Bool adjust = 0; + + FT_UInt new_max, old_max; + + + /* check points & tags */ + new_max = base->n_points + current->n_points + n_points; + old_max = loader->max_points; + + if (new_max > old_max) + { + FT_Vector* points_new; + char* tags_new; + + + new_max = TA_PAD_CEIL(new_max, 8); + + if (new_max > FT_OUTLINE_POINTS_MAX) + return FT_Err_Array_Too_Large; + + points_new = (FT_Vector*)realloc(base->points, + new_max * sizeof (FT_Vector)); + if (!points_new) + return FT_Err_Out_Of_Memory; + base->points = points_new; + + tags_new = (char*)realloc(base->tags, + new_max * sizeof (char)); + if (!tags_new) + return FT_Err_Out_Of_Memory; + base->tags = tags_new; + + if (loader->use_extra) + { + FT_Vector* extra_points_new; + + + extra_points_new = + (FT_Vector*)realloc(loader->base.extra_points, + new_max * 2 * sizeof (FT_Vector)); + if (!extra_points_new) + return FT_Err_Out_Of_Memory; + loader->base.extra_points = extra_points_new; + + memmove(loader->base.extra_points + new_max, + loader->base.extra_points + old_max, + old_max * sizeof (FT_Vector)); + + loader->base.extra_points2 = loader->base.extra_points + new_max; + } + + adjust = 1; + loader->max_points = new_max; + } + + /* check contours */ + old_max = loader->max_contours; + new_max = base->n_contours + current->n_contours + n_contours; + if (new_max > old_max) + { + short* contours_new; + + + new_max = TA_PAD_CEIL(new_max, 4); + + if (new_max > FT_OUTLINE_CONTOURS_MAX) + return FT_Err_Array_Too_Large; + + contours_new = (short*)realloc(base->contours, + new_max * sizeof (short)); + if (!contours_new) + return FT_Err_Out_Of_Memory; + base->contours = contours_new; + + adjust = 1; + loader->max_contours = new_max; + } + + if (adjust) + TA_GlyphLoader_Adjust_Points(loader); + + return FT_Err_Ok; +} + + +/* ensure that we can add `n_subglyphs' to our glyph -- */ +/* this function reallocates its subglyphs table if necessary, */ +/* but it DOES NOT change the number of subglyphs within the loader */ +FT_Error +TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader, + FT_UInt n_subs) +{ + FT_UInt new_max, old_max; + + TA_GlyphLoad base = &loader->base; + TA_GlyphLoad current = &loader->current; + + + new_max = base->num_subglyphs + current->num_subglyphs + n_subs; + old_max = loader->max_subglyphs; + if (new_max > old_max) + { + TA_SubGlyph subglyphs_new; + + + new_max = TA_PAD_CEIL(new_max, 2); + subglyphs_new = (TA_SubGlyph)realloc(base->subglyphs, + new_max * sizeof (TA_SubGlyphRec)); + if (!subglyphs_new) + return FT_Err_Out_Of_Memory; + base->subglyphs = subglyphs_new; + + loader->max_subglyphs = new_max; + + TA_GlyphLoader_Adjust_Subglyphs(loader); + } + + return FT_Err_Ok; +} + + +/* prepare loader for the addition of a new glyph on top of the base one */ +void +TA_GlyphLoader_Prepare(TA_GlyphLoader loader) +{ + TA_GlyphLoad current = &loader->current; + + + current->outline.n_points = 0; + current->outline.n_contours = 0; + current->num_subglyphs = 0; + + TA_GlyphLoader_Adjust_Points (loader); + TA_GlyphLoader_Adjust_Subglyphs(loader); +} + + +/* add current glyph to the base image -- and prepare for another */ +void +TA_GlyphLoader_Add(TA_GlyphLoader loader) +{ + TA_GlyphLoad base; + TA_GlyphLoad current; + + FT_UInt n_curr_contours; + FT_UInt n_base_points; + FT_UInt n; + + + if (!loader) + return; + + base = &loader->base; + current = &loader->current; + + n_curr_contours = current->outline.n_contours; + n_base_points = base->outline.n_points; + + base->outline.n_points = + (short)(base->outline.n_points + current->outline.n_points); + base->outline.n_contours = + (short)(base->outline.n_contours + current->outline.n_contours); + + base->num_subglyphs += current->num_subglyphs; + + /* adjust contours count in newest outline */ + for (n = 0; n < n_curr_contours; n++) + current->outline.contours[n] = + (short)(current->outline.contours[n] + n_base_points); + + /* prepare for another new glyph image */ + TA_GlyphLoader_Prepare(loader); +} + + +FT_Error +TA_GlyphLoader_CopyPoints(TA_GlyphLoader target, + TA_GlyphLoader source) +{ + FT_Error error; + FT_UInt num_points = source->base.outline.n_points; + FT_UInt num_contours = source->base.outline.n_contours; + + + error = TA_GlyphLoader_CheckPoints(target, num_points, num_contours); + if (!error) + { + FT_Outline* out = &target->base.outline; + FT_Outline* in = &source->base.outline; + + + memcpy(out->points, in->points, num_points * sizeof (FT_Vector)); + memcpy(out->contours, in->contours, num_contours * sizeof (short)); + memcpy(out->tags, in->tags, num_points * sizeof (char)); + + /* do we need to copy the extra points? */ + if (target->use_extra && source->use_extra) + { + memcpy(target->base.extra_points, source->base.extra_points, + num_points * sizeof (FT_Vector)); + memcpy(target->base.extra_points2, source->base.extra_points2, + num_points * sizeof (FT_Vector)); + } + + out->n_points = (short)num_points; + out->n_contours = (short)num_contours; + + TA_GlyphLoader_Adjust_Points(target); + } + + return error; +} + +/* end of tagloadr.c */ diff --git a/src/tagloadr.h b/src/tagloadr.h new file mode 100644 index 0000000..a8f9f90 --- /dev/null +++ b/src/tagloadr.h @@ -0,0 +1,116 @@ +/* tagloadr.h */ + +/* originally file `ftgloadr.h' (2011-Mar-28) from FreeType */ + +/* heavily modified 2011 by Werner Lemberg */ + +#ifndef __TAGLOADR_H__ +#define __TAGLOADR_H__ + +#include +#include FT_FREETYPE_H + + +typedef struct TA_SubGlyphRec_ +{ + FT_Int index; + FT_UShort flags; + + FT_Int arg1; + FT_Int arg2; + + FT_Matrix transform; +} TA_SubGlyphRec, *TA_SubGlyph; + + +typedef struct TA_GlyphLoadRec_ +{ + FT_Outline outline; /* outline */ + + FT_Vector* extra_points; /* extra points table */ + FT_Vector* extra_points2; /* second extra points table */ + + FT_UInt num_subglyphs; /* number of subglyphs */ + TA_SubGlyph subglyphs; /* subglyphs */ +} TA_GlyphLoadRec, *TA_GlyphLoad; + + +typedef struct TA_GlyphLoaderRec_ +{ + FT_UInt max_points; + FT_UInt max_contours; + FT_UInt max_subglyphs; + FT_Bool use_extra; + + TA_GlyphLoadRec base; + TA_GlyphLoadRec current; +} TA_GlyphLoaderRec, *TA_GlyphLoader; + + +/* create new empty glyph loader */ +FT_Error +TA_GlyphLoader_New(TA_GlyphLoader *aloader); + +/* add an extra points table to a glyph loader */ +FT_Error +TA_GlyphLoader_CreateExtra(TA_GlyphLoader loader); + +/* destroy a glyph loader */ +void +TA_GlyphLoader_Done(TA_GlyphLoader loader); + +/* reset a glyph loader (frees everything int it) */ +void +TA_GlyphLoader_Reset(TA_GlyphLoader loader); + +/* rewind a glyph loader */ +void +TA_GlyphLoader_Rewind(TA_GlyphLoader loader); + +/* check that there is enough space to add */ +/* `n_points' and `n_contours' to the glyph loader */ +FT_Error +TA_GlyphLoader_CheckPoints(TA_GlyphLoader loader, + FT_UInt n_points, + FT_UInt n_contours); + + +#define TA_GLYPHLOADER_CHECK_P(_loader, _count) \ + ((_count) == 0 || ((_loader)->base.outline.n_points \ + + (_loader)->current.outline.n_points \ + + (unsigned long)(_count)) <= (_loader)->max_points) + +#define TA_GLYPHLOADER_CHECK_C(_loader, _count) \ + ((_count) == 0 || ((_loader)->base.outline.n_contours \ + + (_loader)->current.outline.n_contours \ + + (unsigned long)(_count)) <= (_loader)->max_contours) + +#define TA_GLYPHLOADER_CHECK_POINTS(_loader, _points, _contours) \ + ((TA_GLYPHLOADER_CHECK_P(_loader, _points) \ + && TA_GLYPHLOADER_CHECK_C(_loader, _contours)) \ + ? 0 \ + : TA_GlyphLoader_CheckPoints((_loader), (_points), (_contours))) + + +/* check that there is enough space to add */ +/* `n_subs' sub-glyphs to a glyph loader */ +FT_Error +TA_GlyphLoader_CheckSubGlyphs(TA_GlyphLoader loader, + FT_UInt n_subs); + +/* prepare a glyph loader, i.e. empty the current glyph */ +void +TA_GlyphLoader_Prepare(TA_GlyphLoader loader); + +/* add the current glyph to the base glyph */ +void +TA_GlyphLoader_Add(TA_GlyphLoader loader); + +/* copy points from one glyph loader to another */ +FT_Error +TA_GlyphLoader_CopyPoints(TA_GlyphLoader target, + TA_GlyphLoader source); + +#endif /* __TAGLOADR_H__ */ + +/* end of tagloadr.h */ diff --git a/src/taglobal.c b/src/taglobal.c index c1c9e66..7103ea6 100644 --- a/src/taglobal.c +++ b/src/taglobal.c @@ -49,7 +49,7 @@ static TA_ScriptClass const ta_script_classes[] = typedef struct TA_FaceGlobalsRec_ { FT_Face face; - FT_Long glyph_count; /* same as face->num_glyphs */ + FT_Long glyph_count; /* same as face->num_glyphs */ FT_Byte* glyph_scripts; TA_ScriptMetrics metrics[TA_SCRIPT_MAX]; @@ -158,10 +158,10 @@ ta_face_globals_new(FT_Face face, TA_FaceGlobals *aglobals) { FT_Error error; - TA_FaceGlobals globals = NULL; + TA_FaceGlobals globals; - globals = (TA_FaceGlobals)calloc(1, sizeof (*globals) + + globals = (TA_FaceGlobals)calloc(1, sizeof (TA_FaceGlobalsRec) + face->num_glyphs * sizeof (FT_Byte)); if (!globals) { @@ -206,7 +206,7 @@ ta_face_globals_free(TA_FaceGlobals globals) #endif if (clazz->script_metrics_done) - clazz->script_metrics_done( globals->metrics[nn]); + clazz->script_metrics_done(globals->metrics[nn]); free(globals->metrics[nn]); globals->metrics[nn] = NULL; diff --git a/src/talatin.c b/src/talatin.c index f4a8a59..f50f66d 100644 --- a/src/talatin.c +++ b/src/talatin.c @@ -105,7 +105,7 @@ ta_latin_metrics_init_widths(TA_LatinMetrics metrics, dist = -dist; if (num_widths < TA_LATIN_MAX_WIDTHS) - axis->widths[ num_widths++ ].org = dist; + axis->widths[num_widths++].org = dist; } } @@ -156,7 +156,7 @@ static void ta_latin_metrics_init_blues(TA_LatinMetrics metrics, FT_Face face) { - FT_Pos flats [TA_LATIN_MAX_TEST_CHARACTERS]; + FT_Pos flats[TA_LATIN_MAX_TEST_CHARACTERS]; FT_Pos rounds[TA_LATIN_MAX_TEST_CHARACTERS]; FT_Int num_flats; FT_Int num_rounds; @@ -621,7 +621,7 @@ ta_latin_metrics_scale_dim(TA_LatinMetrics metrics, /* scale global values in both directions */ -FT_LOCAL_DEF(void) +void ta_latin_metrics_scale(TA_LatinMetrics metrics, TA_Scaler scaler) { @@ -1492,7 +1492,7 @@ ta_latin_compute_stem_width(TA_GlyphHints hints, if (!TA_LATIN_HINTS_DO_STEM_ADJUST(hints) - || axis->extra_light ) + || axis->extra_light) return width; if (dist < 0) diff --git a/src/taloader.c b/src/taloader.c new file mode 100644 index 0000000..31c7386 --- /dev/null +++ b/src/taloader.c @@ -0,0 +1,536 @@ +/* taloader.c */ + +/* originally file `afloader.c' (2011-Mar-28) from FreeType */ + +/* heavily modified 2011 by Werner Lemberg */ + +#include + +#include +#include FT_GLYPH_H + +#include "taloader.h" +#include "tahints.h" +#include "taglobal.h" + + +/* from file `ftobjs.h' (2011-Mar-28) from FreeType */ +typedef struct FT_Slot_InternalRec_ +{ + TA_GlyphLoader loader; + FT_UInt flags; + FT_Bool glyph_transformed; + FT_Matrix glyph_matrix; + FT_Vector glyph_delta; + void* glyph_hints; +} FT_GlyphSlot_InternalRec; + + +/* initialize glyph loader */ + +FT_Error +ta_loader_init(TA_Loader loader) +{ + memset(loader, 0, sizeof (TA_LoaderRec)); + + ta_glyph_hints_init(&loader->hints); +#ifdef TA_DEBUG + _ta_debug_hints = &loader->hints; +#endif + return TA_GlyphLoader_New(&loader->gloader); +} + + +/* reset glyph loader and compute globals if necessary */ + +FT_Error +ta_loader_reset(TA_Loader loader, + FT_Face face) +{ + FT_Error error = FT_Err_Ok; + + + loader->face = face; + loader->globals = (TA_FaceGlobals)face->autohint.data; + + TA_GlyphLoader_Rewind(loader->gloader); + + if (loader->globals == NULL) + { + error = ta_face_globals_new(face, &loader->globals); + if (!error) + { + face->autohint.data = (FT_Pointer)loader->globals; + face->autohint.finalizer = (FT_Generic_Finalizer)ta_face_globals_free; + } + } + + return error; +} + + +/* finalize glyph loader */ + +void +ta_loader_done(TA_Loader loader) +{ + ta_glyph_hints_done(&loader->hints); + + loader->face = NULL; + loader->globals = NULL; + +#ifdef TA_DEBUG + _ta_debug_hints = NULL; +#endif + TA_GlyphLoader_Done(loader->gloader); + loader->gloader = NULL; +} + + +/* load a single glyph component; this routine calls itself recursively, */ +/* if necessary, and does the main work of `ta_loader_load_glyph' */ + +static FT_Error +ta_loader_load_g(TA_Loader loader, + TA_Scaler scaler, + FT_UInt glyph_index, + FT_Int32 load_flags, + FT_UInt depth) +{ + FT_Error error; + FT_Face face = loader->face; + TA_GlyphLoader gloader = loader->gloader; + TA_ScriptMetrics metrics = loader->metrics; + TA_GlyphHints hints = &loader->hints; + FT_GlyphSlot slot = face->glyph; + FT_Slot_Internal internal = slot->internal; + + + error = FT_Load_Glyph(face, glyph_index, load_flags); + if (error) + goto Exit; + + loader->transformed = internal->glyph_transformed; + if (loader->transformed) + { + FT_Matrix inverse; + + + loader->trans_matrix = internal->glyph_matrix; + loader->trans_delta = internal->glyph_delta; + + inverse = loader->trans_matrix; + FT_Matrix_Invert(&inverse); + FT_Vector_Transform(&loader->trans_delta, &inverse); + } + + /* set linear metrics */ + slot->linearHoriAdvance = slot->metrics.horiAdvance; + slot->linearVertAdvance = slot->metrics.vertAdvance; + + switch (slot->format) + { + case FT_GLYPH_FORMAT_OUTLINE: + /* translate the loaded glyph when an internal transform is needed */ + if (loader->transformed) + FT_Outline_Translate(&slot->outline, + loader->trans_delta.x, + loader->trans_delta.y); + + /* copy the outline points in the loader's current extra points */ + /* which are used to keep original glyph coordinates */ + error = TA_GLYPHLOADER_CHECK_POINTS(gloader, + slot->outline.n_points + 4, + slot->outline.n_contours); + if (error) + goto Exit; + + memcpy(gloader->current.outline.points, + slot->outline.points, + slot->outline.n_points * sizeof (FT_Vector)); + memcpy(gloader->current.outline.contours, + slot->outline.contours, + slot->outline.n_contours * sizeof (short)); + memcpy(gloader->current.outline.tags, + slot->outline.tags, + slot->outline.n_points * sizeof (char)); + + gloader->current.outline.n_points = slot->outline.n_points; + gloader->current.outline.n_contours = slot->outline.n_contours; + + /* compute original horizontal phantom points */ + /* (and ignore vertical ones) */ + loader->pp1.x = hints->x_delta; + loader->pp1.y = hints->y_delta; + loader->pp2.x = FT_MulFix(slot->metrics.horiAdvance, + hints->x_scale) + hints->x_delta; + loader->pp2.y = hints->y_delta; + + /* be sure to check for spacing glyphs */ + if (slot->outline.n_points == 0) + goto Hint_Metrics; + + /* now load the slot image into the auto-outline */ + /* and run the automatic hinting process */ + if (metrics->clazz->script_hints_apply) + metrics->clazz->script_hints_apply(hints, + &gloader->current.outline, + metrics); + + /* we now need to adjust the metrics according to the change in */ + /* width/positioning that occurred during the hinting process */ + if (scaler->render_mode != FT_RENDER_MODE_LIGHT) + { + FT_Pos old_rsb, old_lsb, new_lsb; + FT_Pos pp1x_uh, pp2x_uh; + TA_AxisHints axis = &hints->axis[TA_DIMENSION_HORZ]; + + TA_Edge edge1 = axis->edges; /* leftmost edge */ + TA_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */ + + + if (axis->num_edges > 1 && TA_HINTS_DO_ADVANCE(hints)) + { + old_rsb = loader->pp2.x - edge2->opos; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + /* remember unhinted values to later account */ + /* for rounding errors */ + pp1x_uh = new_lsb - old_lsb; + pp2x_uh = edge2->pos + old_rsb; + + /* prefer too much space over too little space */ + /* for very small sizes */ + if (old_lsb < 24) + pp1x_uh -= 8; + if (old_rsb < 24) + pp2x_uh += 8; + + loader->pp1.x = TA_PIX_ROUND(pp1x_uh); + loader->pp2.x = TA_PIX_ROUND(pp2x_uh); + + if (loader->pp1.x >= new_lsb + && old_lsb > 0) + loader->pp1.x -= 64; + if (loader->pp2.x <= edge2->pos + && old_rsb > 0) + loader->pp2.x += 64; + + slot->lsb_delta = loader->pp1.x - pp1x_uh; + slot->rsb_delta = loader->pp2.x - pp2x_uh; + } + else + { + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; + + + loader->pp1.x = TA_PIX_ROUND(pp1x); + loader->pp2.x = TA_PIX_ROUND(pp2x); + + slot->lsb_delta = loader->pp1.x - pp1x; + slot->rsb_delta = loader->pp2.x - pp2x; + } + } + else + { + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; + + + loader->pp1.x = TA_PIX_ROUND(pp1x + hints->xmin_delta); + loader->pp2.x = TA_PIX_ROUND(pp2x + hints->xmax_delta); + + slot->lsb_delta = loader->pp1.x - pp1x; + slot->rsb_delta = loader->pp2.x - pp2x; + } + + /* good, we simply add the glyph to our loader's base */ + TA_GlyphLoader_Add(gloader); + break; + + case FT_GLYPH_FORMAT_COMPOSITE: + { + FT_UInt nn, num_subglyphs = slot->num_subglyphs; + FT_UInt num_base_subgs, start_point; + TA_SubGlyph subglyph; + + + start_point = gloader->base.outline.n_points; + + /* first of all, copy the subglyph descriptors in the glyph loader */ + error = TA_GlyphLoader_CheckSubGlyphs(gloader, num_subglyphs); + if (error) + goto Exit; + + memcpy(gloader->current.subglyphs, + slot->subglyphs, + num_subglyphs * sizeof (TA_SubGlyphRec)); + + gloader->current.num_subglyphs = num_subglyphs; + num_base_subgs = gloader->base.num_subglyphs; + + /* now read each subglyph independently */ + for (nn = 0; nn < num_subglyphs; nn++) + { + FT_Vector pp1, pp2; + FT_Pos x, y; + FT_UInt num_points, num_new_points, num_base_points; + + + /* gloader.current.subglyphs can change during glyph loading due */ + /* to re-allocation -- we must recompute the current subglyph on */ + /* each iteration */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + pp1 = loader->pp1; + pp2 = loader->pp2; + + num_base_points = gloader->base.outline.n_points; + + error = ta_loader_load_g(loader, scaler, subglyph->index, + load_flags, depth + 1); + if (error) + goto Exit; + + /* recompute subglyph pointer */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + if (subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS) + { + pp1 = loader->pp1; + pp2 = loader->pp2; + } + else + { + loader->pp1 = pp1; + loader->pp2 = pp2; + } + + num_points = gloader->base.outline.n_points; + num_new_points = num_points - num_base_points; + + /* now perform the transformation required for this subglyph */ + if (subglyph->flags & (FT_SUBGLYPH_FLAG_SCALE + | FT_SUBGLYPH_FLAG_XY_SCALE + | FT_SUBGLYPH_FLAG_2X2)) + { + FT_Vector* cur = gloader->base.outline.points + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for (; cur < limit; cur++) + FT_Vector_Transform(cur, &subglyph->transform); + } + + /* apply offset */ + if (!(subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES)) + { + FT_Int k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + if (start_point + k >= num_base_points + || l >= (FT_UInt)num_new_points) + { + error = FT_Err_Invalid_Composite; + goto Exit; + } + + l += num_base_points; + + /* for now, only use the current point coordinates; */ + /* we eventually may consider another approach */ + p1 = gloader->base.outline.points + start_point + k; + p2 = gloader->base.outline.points + start_point + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = FT_MulFix(subglyph->arg1, hints->x_scale) + hints->x_delta; + y = FT_MulFix(subglyph->arg2, hints->y_scale) + hints->y_delta; + + x = TA_PIX_ROUND(x); + y = TA_PIX_ROUND(y); + } + + { + FT_Outline dummy = gloader->base.outline; + + + dummy.points += num_base_points; + dummy.n_points = (short)num_new_points; + + FT_Outline_Translate(&dummy, x, y); + } + } + } + break; + + default: + /* we don't support other formats (yet?) */ + error = FT_Err_Unimplemented_Feature; + } + +Hint_Metrics: + if (depth == 0) + { + FT_BBox bbox; + FT_Vector vvector; + + + vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX; + vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY; + vvector.x = FT_MulFix(vvector.x, metrics->scaler.x_scale); + vvector.y = FT_MulFix(vvector.y, metrics->scaler.y_scale); + + /* transform the hinted outline if needed */ + if (loader->transformed) + { + FT_Outline_Transform(&gloader->base.outline, &loader->trans_matrix); + FT_Vector_Transform(&vvector, &loader->trans_matrix); + } +#if 1 + /* we must translate our final outline by -pp1.x */ + /* and compute the new metrics */ + if (loader->pp1.x) + FT_Outline_Translate(&gloader->base.outline, -loader->pp1.x, 0); +#endif + FT_Outline_Get_CBox(&gloader->base.outline, &bbox); + + bbox.xMin = TA_PIX_FLOOR(bbox.xMin); + bbox.yMin = TA_PIX_FLOOR(bbox.yMin); + bbox.xMax = TA_PIX_CEIL(bbox.xMax); + bbox.yMax = TA_PIX_CEIL(bbox.yMax); + + slot->metrics.width = bbox.xMax - bbox.xMin; + slot->metrics.height = bbox.yMax - bbox.yMin; + slot->metrics.horiBearingX = bbox.xMin; + slot->metrics.horiBearingY = bbox.yMax; + + slot->metrics.vertBearingX = TA_PIX_FLOOR(bbox.xMin + vvector.x); + slot->metrics.vertBearingY = TA_PIX_FLOOR(bbox.yMax + vvector.y); + + /* for mono-width fonts (like Andale, Courier, etc.) we need */ + /* to keep the original rounded advance width; ditto for */ + /* digits if all have the same advance width */ + if (FT_IS_FIXED_WIDTH(slot->face) + || (ta_face_globals_is_digit(loader->globals, glyph_index) + && metrics->digits_have_same_width)) + { + slot->metrics.horiAdvance = FT_MulFix(slot->metrics.horiAdvance, + metrics->scaler.x_scale); + + /* set delta values to 0, otherwise code that uses them */ + /* is going to ruin the fixed advance width */ + slot->lsb_delta = 0; + slot->rsb_delta = 0; + } + else + { + /* non-spacing glyphs must stay as-is */ + if (slot->metrics.horiAdvance) + slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; + } + + slot->metrics.vertAdvance = FT_MulFix(slot->metrics.vertAdvance, + metrics->scaler.y_scale); + + slot->metrics.horiAdvance = TA_PIX_ROUND(slot->metrics.horiAdvance); + slot->metrics.vertAdvance = TA_PIX_ROUND(slot->metrics.vertAdvance); + + /* now copy outline into glyph slot */ + TA_GlyphLoader_Rewind(internal->loader); + error = TA_GlyphLoader_CopyPoints(internal->loader, gloader); + if (error) + goto Exit; + + slot->outline = internal->loader->base.outline; + slot->format = FT_GLYPH_FORMAT_OUTLINE; + } + +#ifdef DEBUG_HINTER + ta_debug_hinter = hinter; +#endif + +Exit: + return error; +} + + +/* load a glyph */ + +FT_Error +ta_loader_load_glyph(TA_Loader loader, + FT_Face face, + FT_UInt gindex, + FT_UInt32 load_flags) +{ + FT_Error error; + FT_Size size = face->size; + TA_ScalerRec scaler; + + + if (!size) + return FT_Err_Invalid_Argument; + + memset(&scaler, 0, sizeof (TA_ScalerRec)); + + scaler.face = face; + scaler.x_scale = size->metrics.x_scale; + scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ + scaler.y_scale = size->metrics.y_scale; + scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ + + scaler.render_mode = FT_LOAD_TARGET_MODE(load_flags); + scaler.flags = 0; /* XXX: fix this */ + + error = ta_loader_reset(loader, face); + if (!error) + { + TA_ScriptMetrics metrics; + FT_UInt options = 0; + + +#ifdef FT_OPTION_AUTOFIT2 + /* XXX: undocumented hook to activate the latin2 hinter */ + if (load_flags & (1UL << 20)) + options = 2; +#endif + + error = ta_face_globals_get_metrics(loader->globals, gindex, + options, &metrics); + if (!error) + { + loader->metrics = metrics; + + if (metrics->clazz->script_metrics_scale) + metrics->clazz->script_metrics_scale(metrics, &scaler); + else + metrics->scaler = scaler; + + load_flags |= FT_LOAD_NO_SCALE + | FT_LOAD_IGNORE_TRANSFORM; + load_flags &= ~FT_LOAD_RENDER; + + if (metrics->clazz->script_hints_init) + { + error = metrics->clazz->script_hints_init(&loader->hints, + metrics); + if (error) + goto Exit; + } + + error = ta_loader_load_g(loader, &scaler, gindex, load_flags, 0); + } + } +Exit: + return error; +} + +/* end of taloader.c */ diff --git a/src/taloader.h b/src/taloader.h new file mode 100644 index 0000000..e8ecb56 --- /dev/null +++ b/src/taloader.h @@ -0,0 +1,51 @@ +/* taloader.h */ + +/* originally file `afloader.h' (2011-Mar-28) from FreeType */ + +/* heavily modified 2011 by Werner Lemberg */ + +#ifndef __TALOADER_H__ +#define __TALOADER_H__ + +#include "tahints.h" +#include "taglobal.h" +#include "tagloadr.h" + + +typedef struct TA_LoaderRec_ +{ + FT_Face face; /* current face */ + TA_FaceGlobals globals; /* current face globals */ + TA_GlyphLoader gloader; /* glyph loader */ + TA_GlyphHintsRec hints; + TA_ScriptMetrics metrics; + FT_Bool transformed; + FT_Matrix trans_matrix; + FT_Vector trans_delta; + FT_Vector pp1; + FT_Vector pp2; + /* we don't handle vertical phantom points */ +} TA_LoaderRec, *TA_Loader; + + +FT_Error +ta_loader_init(TA_Loader loader); + + +FT_Error +ta_loader_reset(TA_Loader loader, + FT_Face face); + +void +ta_loader_done(TA_Loader loader); + + +FT_Error +ta_loader_load_glyph(TA_Loader loader, + FT_Face face, + FT_UInt gindex, + FT_UInt32 load_flags); + +#endif /* __TALOADER_H__ */ + +/* end of taloader.h */ diff --git a/src/tatypes.h b/src/tatypes.h index 9246c51..2febc98 100644 --- a/src/tatypes.h +++ b/src/tatypes.h @@ -41,6 +41,11 @@ extern void* _ta_debug_hints; #define TA_ABS(a) ((a) < 0 ? -(a) : (a)) +/* from file `ftobjs.h' from FreeType */ +#define TA_PAD_FLOOR(x, n) ((x) & ~((n) - 1)) +#define TA_PAD_ROUND(x, n) TA_PAD_FLOOR((x) + ((n) / 2), n) +#define TA_PAD_CEIL(x, n) TA_PAD_FLOOR((x) + ((n) - 1), n) + #define TA_PIX_FLOOR(x) ((x) & ~63) #define TA_PIX_ROUND(x) TA_PIX_FLOOR((x) + 32) #define TA_PIX_CEIL(x) TA_PIX_FLOOR((x) + 63) -- 2.11.4.GIT