From c3dd151b0f5401a603e66c13ec5a11655754b385 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Wed, 26 Jul 2000 14:11:15 +0000 Subject: [PATCH] autohint: Formatting. Replacing many enums with #defines since we do arithmetics (especially ORing which would produce undefined enum values). The ideal thing instead of #defines is `const int' as provided in C++... Adding header files to rules.mk --- src/autohint/ahglobal.c | 4 +- src/autohint/ahglyph.c | 84 +-- src/autohint/ahhint.c | 1137 +++++++++++++++++++++------------------ src/autohint/ahhint.h | 65 ++- src/autohint/ahloader.h | 99 ++-- src/autohint/ahmodule.c | 60 ++- src/autohint/ahmodule.h | 15 +- src/autohint/ahoptim.c | 441 ++++++++------- src/autohint/ahoptim.h | 113 ++-- src/autohint/ahtypes.h | 646 ++++++++++++---------- src/autohint/autohint.c | 11 +- src/autohint/mather.py | 74 ++- src/autohint/rules.mk | 33 +- src/type1/rules.mk | 1 + 14 files changed, 1546 insertions(+), 1237 deletions(-) diff --git a/src/autohint/ahglobal.c b/src/autohint/ahglobal.c index 999fc1621..892ca8617 100644 --- a/src/autohint/ahglobal.c +++ b/src/autohint/ahglobal.c @@ -102,14 +102,14 @@ AH_LOG(( "blue zones computation\n" )); AH_LOG(( "------------------------------------------------\n" )); - for ( blue = (AH_Blue)0; blue < ah_blue_max; blue++ ) + for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ ) { const char* p = blue_chars[blue]; const char* limit = p + MAX_TEST_CHARACTERS; FT_Pos *blue_ref, *blue_shoot; - AH_LOG(( "blue %3d: ", (int)blue )); + AH_LOG(( "blue %3d: ", blue )); num_flats = 0; num_rounds = 0; diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 1dcf3fbd8..348ee8e32 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -11,7 +11,7 @@ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ @@ -547,7 +547,7 @@ /* a segment is round if either its first or last point */ /* is a control point */ if ( ( segment->first->flags | point->flags ) & - ah_flah_control ) + ah_flah_control ) segment->flags |= ah_edge_round; /* compute segment size */ @@ -1150,7 +1150,7 @@ if ( best_dist > 64 / 4 ) best_dist = 64 / 4; - for ( blue = (AH_Blue)0; blue < ah_blue_max; blue++ ) + for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ ) { /* if it is a top zone, check for right edges -- if it is a bottom */ /* zone, check for left edges */ @@ -1213,79 +1213,87 @@ } - /************************************************************************ - * - * - * ah_outline_scale_blue_edges - * - * - * This functions must be called before hinting in order to re-adjust - * the content of the detected edges (basically change the "blue edge" - * pointer from 'design units' to 'scaled ones' - * - ************************************************************************/ - + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_scale_blue_edges */ + /* */ + /* */ + /* This functions must be called before hinting in order to re-adjust */ + /* the contents of the detected edges (basically change the `blue */ + /* edge' pointer from `design units' to `scaled ones'). */ + /* */ LOCAL_FUNC void ah_outline_scale_blue_edges( AH_Outline* outline, AH_Face_Globals* globals ) { - AH_Edge* edge = outline->horz_edges; - AH_Edge* limit = edge + outline->num_hedges; - FT_Int delta; + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + FT_Int delta; + delta = globals->scaled.blue_refs - globals->design.blue_refs; + for ( ; edge < limit; edge++ ) { - if (edge->blue_edge) + if ( edge->blue_edge ) edge->blue_edge += delta; } } - - - #ifdef AH_DEBUG_GLYPH - extern - void ah_dump_edges( AH_Outline* outline ) + + void ah_dump_edges( AH_Outline* outline ) { AH_Edge* edges; AH_Edge* limit; AH_Segment* segments; FT_Int dimension; + edges = outline->horz_edges; limit = edges + outline->num_hedges; segments = outline->horz_segments; + for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Edge* edge; - printf ( "Table of %s edges:\n", !dimension ? "vertical" : "horizontal" ); - printf ( " [ index | pos | dir | link | serif | blue | opos | pos ]\n" ); + + printf ( "Table of %s edges:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos ]\n" ); for ( edge = edges; edge < limit; edge++ ) { printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", edge - edges, (int)edge->fpos, - edge->dir == ah_dir_up ? "up" : - (edge->dir == ah_dir_down ? "down" : - (edge->dir == ah_dir_left ? "left" : - (edge->dir == ah_dir_right ? "right" : "none") - ) - ), - edge->link ? (edge->link-edges) : -1, - edge->serif ? (edge->serif-edges) : -1, + edge->dir == ah_dir_up + ? "up" + : ( edge->dir == ah_dir_down + ? "down" + : ( edge->dir == ah_dir_left + ? "left" + : ( edge->dir == ah_dir_right + ? "right" + : "none" ) ) ), + edge->link ? ( edge->link - edges ) : -1, + edge->serif ? ( edge->serif - edges ) : -1, edge->blue_edge ? 'y' : 'n', - edge->opos/64.0, - edge->pos/64.0 ); + edge->opos / 64.0, + edge->pos / 64.0 ); } - edges = outline->vert_edges; limit = edges + outline->num_vedges; segments = outline->vert_segments; } } -#endif + +#endif /* AH_DEBUG_GLYPH */ + + +/* END */ diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c index 1bc4faafe..f50f8839d 100644 --- a/src/autohint/ahhint.c +++ b/src/autohint/ahhint.c @@ -2,70 +2,81 @@ /* */ /* ahhint.c */ /* */ -/* Glyph hinter */ +/* Glyph hinter (body). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ + #ifdef FT_FLAT_COMPILE + #include "ahhint.h" #include "ahglyph.h" #include "ahangles.h" + #else + #include #include #include + #endif #include -#define FACE_GLOBALS(face) ((AH_Face_Globals*)(face)->autohint.data) + +#define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data) #define AH_USE_IUP - /*******************************************************************/ - /*******************************************************************/ - /**** ****/ - /**** Hinting routines ****/ - /**** ****/ - /*******************************************************************/ - /*******************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Hinting routines ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + static int disable_horz_edges = 0; static int disable_vert_edges = 0; + /* snap a given width in scaled coordinates to one of the */ - /* current standard widths.. */ + /* current standard widths */ static - FT_Pos ah_snap_width( FT_Pos* widths, - FT_Int count, - FT_Pos width ) + FT_Pos ah_snap_width( FT_Pos* widths, + FT_Int count, + FT_Pos width ) { int n; - FT_Pos best = 64+32+2; + FT_Pos best = 64 + 32 + 2; FT_Pos reference = width; + for ( n = 0; n < count; n++ ) { FT_Pos w; FT_Pos dist; + w = widths[n]; dist = width - w; - if (dist < 0) dist = -dist; - if (dist < best) + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) { best = dist; reference = w; @@ -89,8 +100,7 @@ } - - /* Align one stem edge relative to the previous stem edge */ + /* align one stem edge relative to the previous stem edge */ static void ah_align_linked_edge( AH_Hinter* hinter, AH_Edge* base_edge, @@ -101,20 +111,21 @@ AH_Globals* globals = &hinter->globals->scaled; FT_Pos sign = 1; - if (dist < 0) + + if ( dist < 0 ) { dist = -dist; sign = -1; } - if (vertical) + if ( vertical ) { dist = ah_snap_width( globals->heights, globals->num_heights, dist ); /* in the case of vertical hinting, always round */ - /* the stem heights to integer pixels.. */ - if (dist >= 64) - dist = (dist+16) & -64; + /* the stem heights to integer pixels */ + if ( dist >= 64 ) + dist = ( dist + 16 ) & -64; else dist = 64; } @@ -122,31 +133,30 @@ { dist = ah_snap_width( globals->widths, globals->num_widths, dist ); - if (hinter->flags & ah_hinter_monochrome) + if ( hinter->flags & ah_hinter_monochrome ) { /* monochrome horizontal hinting: snap widths to integer pixels */ - /* with a different threshold.. */ - if (dist < 64) + /* with a different threshold */ + if ( dist < 64 ) dist = 64; else - dist = (dist+32) & -64; + dist = ( dist + 32 ) & -64; } else { /* for horizontal anti-aliased hinting, we adopt a more subtle */ - /* approach, we strengthen small stems, round stems whose size */ + /* approach: we strengthen small stems, round stems whose size */ /* is between 1 and 2 pixels to an integer, otherwise nothing */ - if (dist < 48) - dist = (dist+64) >> 1; - - else if (dist < 128) - dist = (dist+42) & -64; + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + else if ( dist < 128 ) + dist = ( dist + 42 ) & -64; } } - stem_edge->pos = base_edge->pos + sign*dist; - } + stem_edge->pos = base_edge->pos + sign * dist; + } static @@ -157,46 +167,50 @@ FT_Pos dist; FT_Pos sign = 1; - UNUSED(hinter); + UNUSED( hinter ); + + dist = serif->opos - base->opos; - if (dist < 0) + if ( dist < 0 ) { dist = -dist; sign = -1; } - if (base->flags & ah_edge_done) /* do not strengthen serifs */ + if ( base->flags & ah_edge_done ) { - if (dist > 64) - dist = (dist+16) & -64; + if ( dist > 64 ) + dist = ( dist + 16 ) & -64; - else if (dist <= 32) - dist = (dist+33) >> 1; + else if ( dist <= 32 ) + dist = ( dist + 33 ) >> 1; } - serif->pos = base->pos + sign*dist; + + serif->pos = base->pos + sign * dist; } - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ - /**** ****/ - /**** E D G E H I N T I N G ****/ - /**** ****/ - /**** ****/ - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** E D G E H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /* Another alternative edge hinting algorithm */ static void ah_hint_edges_3( AH_Hinter* hinter ) { - AH_Edge* edges; - AH_Edge* edge_limit; - AH_Outline* outline = hinter->glyph; - FT_Int dimension; + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Outline* outline = hinter->glyph; + FT_Int dimension; + edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; @@ -209,29 +223,31 @@ AH_Edge* anchor = 0; int has_serifs = 0; - if (disable_vert_edges && !dimension) + + if ( disable_vert_edges && !dimension ) goto Next_Dimension; - if (disable_horz_edges && dimension) + if ( disable_horz_edges && dimension ) goto Next_Dimension; /* we begin by aligning all stems relative to the blue zone */ - /* if needed.. that's only for horizontal edges.. */ - if (dimension) + /* if needed -- that's only for horizontal edges */ + if ( dimension ) { for ( edge = edges; edge < edge_limit; edge++ ) { FT_Pos* blue; - AH_Edge *edge1, *edge2; + AH_Edge *edge1, *edge2; - if (edge->flags & ah_edge_done) + + if ( edge->flags & ah_edge_done ) continue; blue = edge->blue_edge; edge1 = 0; edge2 = edge->link; - if (blue) + if ( blue ) { edge1 = edge; } @@ -242,19 +258,19 @@ edge2 = edge; } - if (!edge1) + if ( !edge1 ) continue; edge1->pos = blue[0]; edge1->flags |= ah_edge_done; - if (edge2 && !edge2->blue_edge) + if ( edge2 && !edge2->blue_edge ) { ah_align_linked_edge( hinter, edge1, edge2, dimension ); edge2->flags |= ah_edge_done; } - if (!anchor) + if ( !anchor ) anchor = edge; } } @@ -267,12 +283,13 @@ { AH_Edge *edge2; - if (edge->flags & ah_edge_done) + + if ( edge->flags & ah_edge_done ) continue; /* skip all non-stem edges */ edge2 = edge->link; - if (!edge2) + if ( !edge2 ) { has_serifs++; continue; @@ -281,12 +298,14 @@ /* now, align the stem */ /* this should not happen, but it's better to be safe.. */ - if (edge2->blue_edge || edge2 < edge) + if ( edge2->blue_edge || edge2 < edge ) { + #if 0 printf( "strange blue alignement, edge %d to %d\n", - edge - edges, edge2 - edges ); + edge - edges, edge2 - edges ); #endif + ah_align_linked_edge( hinter, edge2, edge, dimension ); edge->flags |= ah_edge_done; continue; @@ -296,67 +315,70 @@ FT_Bool min = 0; FT_Pos delta; - if (!anchor) + if ( !anchor ) { - edge->pos = (edge->opos+32) & -64; + edge->pos = ( edge->opos + 32 ) & -64; anchor = edge; } else - edge->pos = anchor->pos + ((edge->opos - anchor->opos + 32) & -64); + edge->pos = anchor->pos + + ( ( edge->opos - anchor->opos + 32 ) & -64 ); edge->flags |= ah_edge_done; - if (edge > edges && edge->pos < edge[-1].pos) + if ( edge > edges && edge->pos < edge[-1].pos ) { edge->pos = edge[-1].pos; - min = 1; + min = 1; } ah_align_linked_edge( hinter, edge, edge2, dimension ); delta = 0; - if ( edge2+1 < edge_limit && + if ( edge2 + 1 < edge_limit && edge2[1].flags & ah_edge_done ) delta = edge2[1].pos - edge2->pos; - if (delta < 0) + if ( delta < 0 ) { edge2->pos += delta; - if (!min) + if ( !min ) edge->pos += delta; } edge2->flags |= ah_edge_done; } } - if (!has_serifs) + if ( !has_serifs ) goto Next_Dimension; /* now, hint the remaining edges (serifs and single) in order */ - /* to complete our processing.. */ + /* to complete our processing */ for ( edge = edges; edge < edge_limit; edge++ ) { - if (edge->flags & ah_edge_done) + if ( edge->flags & ah_edge_done ) continue; - if (edge->serif) + if ( edge->serif ) { ah_align_serif_edge( hinter, edge->serif, edge ); } - else if (!anchor) + else if ( !anchor ) { - edge->pos = (edge->opos+32) & -64; + edge->pos = ( edge->opos + 32 ) & -64; anchor = edge; } else - edge->pos = anchor->pos + ((edge->opos-anchor->opos+32) & -64); + edge->pos = anchor->pos + + ( ( edge->opos-anchor->opos + 32 ) & -64 ); edge->flags |= ah_edge_done; - if (edge > edges && edge->pos < edge[-1].pos) + if ( edge > edges && edge->pos < edge[-1].pos ) edge->pos = edge[-1].pos; - if ( edge+1 < edge_limit && edge[1].flags & ah_edge_done && - edge->pos > edge[1].pos) + if ( edge + 1 < edge_limit && + edge[1].flags & ah_edge_done && + edge->pos > edge[1].pos ) edge->pos = edge[1].pos; } @@ -364,15 +386,9 @@ edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; } - } - - - - - LOCAL_FUNC void ah_hinter_hint_edges( AH_Hinter* hinter, int no_horz_edges, @@ -381,40 +397,40 @@ disable_horz_edges = no_horz_edges; disable_vert_edges = no_vert_edges; - /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */ - /* reduce the problem of the disappearing eye in the "e" of Times */ - /* also, creates some artifacts near the blue zones ?? */ + /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */ + /* reduce the problem of the disappearing eye in the `e' of Times... */ + /* also, creates some artifacts near the blue zones? */ { ah_hint_edges_3( hinter ); - /* outline optimiser removed temporarily */ #if 0 - if (hinter->flags & ah_hinter_optimize) + /* outline optimizer removed temporarily */ + if ( hinter->flags & ah_hinter_optimize ) { AH_Optimizer opt; - if (!AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory )) + + if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) ) { AH_Optimizer_Compute( &opt ); AH_Optimizer_Done( &opt ); } } #endif + } } - - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ - /**** ****/ - /**** P O I N T H I N T I N G ****/ - /**** ****/ - /**** ****/ - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P O I N T H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ static void ah_hinter_align_edge_points( AH_Hinter* hinter ) @@ -424,8 +440,9 @@ AH_Edge* edge_limit; FT_Int dimension; - edges = outline->horz_edges; - edge_limit = edges + outline->num_hedges; + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; for ( dimension = 1; dimension >= 0; dimension-- ) { @@ -433,20 +450,26 @@ AH_Edge* before; AH_Edge* after; + before = 0; after = 0; edge = edges; for ( ; edge < edge_limit; edge++ ) { - /* move the points of each segment in each edge to the edge's position */ + /* move the points of each segment */ + /* in each edge to the edge's position */ AH_Segment* seg = edge->first; + + do { AH_Point* point = seg->first; + + for (;;) { - if (dimension) + if ( dimension ) { point->y = edge->pos; point->flags |= ah_flah_touch_y; @@ -456,23 +479,25 @@ point->x = edge->pos; point->flags |= ah_flah_touch_x; } - if (point == seg->last) + + if ( point == seg->last ) break; point = point->next; } seg = seg->edge_next; - } - while (seg != edge->first); + + } while ( seg != edge->first ); } + edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; } } - /* hint the strong points - this is equivalent to the TrueType "IP" */ + /* hint the strong points -- this is equivalent to the TrueType `IP' */ static void ah_hinter_align_strong_points( AH_Hinter* hinter ) { @@ -484,6 +509,7 @@ AH_Point* point_limit; AH_Flags touch_flag; + points = outline->points; point_limit = points + outline->num_points; @@ -498,6 +524,7 @@ AH_Edge* before; AH_Edge* after; + before = 0; after = 0; @@ -507,36 +534,45 @@ FT_Pos u, ou, fu; /* point position */ FT_Pos delta; + if ( point->flags & touch_flag ) continue; #ifndef AH_OPTION_NO_WEAK_INTERPOLATION - /* if this point is candidate to weak interpolation, we'll */ + /* if this point is candidate to weak interpolation, we will */ /* interpolate it after all strong points have been processed */ if ( point->flags & ah_flah_weak_interpolation ) continue; #endif - if (dimension) { u = point->fy; ou = point->oy; } - else { u = point->fx; ou = point->ox; } + if ( dimension ) + { + u = point->fy; + ou = point->oy; + } + else + { + u = point->fx; + ou = point->ox; + } fu = u; - /* is the point before the first edge ? */ + /* is the point before the first edge? */ edge = edges; delta = edge->fpos - u; - if (delta >= 0) + if ( delta >= 0 ) { - u = edge->pos - (edge->opos - ou); + u = edge->pos - ( edge->opos - ou ); goto Store_Point; } /* is the point after the last edge ? */ - edge = edge_limit-1; + edge = edge_limit - 1; delta = u - edge->fpos; if ( delta >= 0 ) { - u = edge->pos + (ou - edge->opos); + u = edge->pos + ( ou - edge->opos ); goto Store_Point; } @@ -545,6 +581,7 @@ AH_Edge* before = 0; AH_Edge* after = 0; + for ( edge = edges; edge < edge_limit; edge++ ) { if ( u == edge->fpos ) @@ -557,7 +594,7 @@ before = edge; } - for ( edge = edge_limit-1; edge >= edges; edge-- ) + for ( edge = edge_limit - 1; edge >= edges; edge-- ) { if ( u == edge->fpos ) { @@ -574,11 +611,14 @@ after->pos - before->pos, after->fpos - before->fpos ); } + Store_Point: /* save the point position */ - if (dimension) point->y = u; - else point->x = u; + if ( dimension ) + point->y = u; + else + point->x = u; point->flags |= touch_flag; } @@ -591,6 +631,7 @@ #ifndef AH_OPTION_NO_WEAK_INTERPOLATION + static void ah_iup_shift( AH_Point* p1, AH_Point* p2, @@ -599,10 +640,11 @@ AH_Point* p; FT_Pos delta = ref->u - ref->v; + for ( p = p1; p < ref; p++ ) p->u = p->v + delta; - for ( p = ref+1; p <= p2; p++ ) + for ( p = ref + 1; p <= p2; p++ ) p->u = p->v + delta; } @@ -620,16 +662,22 @@ FT_Pos d1 = ref1->u - v1; FT_Pos d2 = ref2->u - v2; - if (p1 > p2) return; - if (v1 == v2) + if ( p1 > p2 ) + return; + + if ( v1 == v2 ) { for ( p = p1; p <= p2; p++ ) { FT_Pos u = p->v; - if (u <= v1) u += d1; - else u += d2; + + if ( u <= v1 ) + u += d1; + else + u += d2; + p->u = u; } return; @@ -641,9 +689,12 @@ { u = p->v; - if (u <= v1) u += d1; - else if (u >= v2) u += d2; - else u = ref1->u+FT_MulDiv( u-v1, ref2->u-ref1->u, v2-v1 ); + if ( u <= v1 ) + u += d1; + else if ( u >= v2 ) + u += d2; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); p->u = u; } @@ -653,16 +704,21 @@ for ( p = p1; p <= p2; p++ ) { u = p->v; - if (u <= v2) u += d2; - else if (u >= v1) u += d1; - else u = ref1->u+FT_MulDiv( u-v1, ref2->u-ref1->u, v2-v1 ); + + if ( u <= v2 ) + u += d2; + else if ( u >= v1 ) + u += d1; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); p->u = u; } } } - /* interpolate weak points - this is equivalent to the TrueType "IUP" */ + + /* interpolate weak points -- this is equivalent to the TrueType `IUP' */ static void ah_hinter_align_weak_points( AH_Hinter* hinter ) { @@ -675,10 +731,11 @@ AH_Point** contour_limit; AH_Flags touch_flag; + points = outline->points; point_limit = points + outline->num_points; - /* PASS 1 : Move segment points to edge positions */ + /* PASS 1: Move segment points to edge positions */ edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; @@ -690,10 +747,11 @@ for ( dimension = 1; dimension >= 0; dimension-- ) { - AH_Point* point; - AH_Point* end_point; - AH_Point* first_point; - AH_Point** contour; + AH_Point* point; + AH_Point* end_point; + AH_Point* first_point; + AH_Point** contour; + point = points; contour = outline->contours; @@ -704,52 +762,53 @@ end_point = point->prev; first_point = point; - while (point <= end_point && !(point->flags & touch_flag)) + while ( point <= end_point && !( point->flags & touch_flag ) ) point++; - if (point <= end_point) + if ( point <= end_point ) { AH_Point* first_touched = point; AH_Point* cur_touched = point; + point++; while ( point <= end_point ) { - if (point->flags & touch_flag) + if ( point->flags & touch_flag ) { - /* we found two succesive touched points, we interpolate */ - /* all contour points between them.. */ - ah_iup_interp( cur_touched+1, point-1, + /* we found two successive touched points; we interpolate */ + /* all contour points between them */ + ah_iup_interp( cur_touched + 1, point - 1, cur_touched, point ); cur_touched = point; } point++; } - if (cur_touched == first_touched) + if ( cur_touched == first_touched ) { /* this is a special case: only one point was touched in the */ - /* contour.. we thus simply shift the whole contour.. */ + /* contour; we thus simply shift the whole contour */ ah_iup_shift( first_point, end_point, cur_touched ); } else { /* now interpolate after the last touched point to the end */ - /* of the contour.. */ - ah_iup_interp( cur_touched+1, end_point, + /* of the contour */ + ah_iup_interp( cur_touched + 1, end_point, cur_touched, first_touched ); - /* if the first contour point isn't touched, interpolate */ - /* from the contour start to the first touched point */ - if (first_touched > points) - ah_iup_interp( first_point, first_touched-1, + /* if the first contour point isn't touched, interpolate */ + /* from the contour start to the first touched point */ + if ( first_touched > points ) + ah_iup_interp( first_point, first_touched - 1, cur_touched, first_touched ); } } } /* now save the interpolated values back to x/y */ - if (dimension) + if ( dimension ) { for ( point = points; point < point_limit; point++ ) point->y = point->u; @@ -766,7 +825,9 @@ } } } -#endif + +#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */ + LOCAL_FUNC void ah_hinter_align_points( AH_Hinter* hinter ) @@ -783,16 +844,16 @@ } - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ - /**** ****/ - /**** H I N T E R O B J E C T M E T H O D S ****/ - /**** ****/ - /**** ****/ - /**************************************************************************/ - /**************************************************************************/ - /**************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** H I N T E R O B J E C T M E T H O D S ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /* scale and fit the global metrics */ static @@ -805,6 +866,7 @@ AH_Globals* design = &globals->design; AH_Globals* scaled = &globals->scaled; + /* copy content */ *scaled = *design; @@ -820,22 +882,28 @@ { FT_Pos delta, delta2; + delta = design->blue_shoots[n] - design->blue_refs[n]; - delta2 = delta; if (delta < 0) delta2 = -delta2; + delta2 = delta; + if ( delta < 0 ) + delta2 = -delta2; delta2 = FT_MulFix( delta2, y_scale ); - if (delta2 < 32) + if ( delta2 < 32 ) delta2 = 0; - else if (delta2 < 64) - delta2 = 32 + (((delta2-32)+16) & -32); + else if ( delta2 < 64 ) + delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 ); else - delta2 = (delta2+32) & -64; + delta2 = ( delta2 + 32 ) & -64; - if (delta < 0) delta2 = -delta2; + if ( delta < 0 ) + delta2 = -delta2; - scaled->blue_refs [n] = (FT_MulFix(design->blue_refs[n],y_scale)+32) & -64; + scaled->blue_refs[n] = + ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64; scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2; } + globals->x_scale = x_scale; globals->y_scale = y_scale; } @@ -849,38 +917,42 @@ } - /* finalise a hinter object */ + /* finalize a hinter object */ void ah_hinter_done( AH_Hinter* hinter ) { - if (hinter) + if ( hinter ) { FT_Memory memory = hinter->memory; + ah_loader_done( hinter->loader ); ah_outline_done( hinter->glyph ); - /* note: the globals pointer is _not_ owned by the hinter */ - /* but by the current face object, we don't need to */ - /* release it.. */ + /* note: the `globals' pointer is _not_ owned by the hinter */ + /* but by the current face object, we don't need to */ + /* release it */ hinter->globals = 0; hinter->face = 0; - FREE(hinter); + FREE( hinter ); } } - /* create a new empty hinter object */ - FT_Error ah_hinter_new( FT_Library library, AH_Hinter* *ahinter ) + /* create a new empty hinter object */ + FT_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ) { AH_Hinter* hinter = 0; FT_Memory memory = library->memory; FT_Error error; + *ahinter = 0; /* allocate object */ - if (ALLOC( hinter, sizeof(*hinter) )) goto Exit; + if ( ALLOC( hinter, sizeof ( *hinter ) ) ) + goto Exit; hinter->memory = memory; hinter->flags = 0; @@ -889,39 +961,43 @@ error = ah_outline_new( memory, &hinter->glyph ) || ah_loader_new ( memory, &hinter->loader ) || ah_loader_create_extra( hinter->loader ); - if (error) goto Exit; + if ( error ) + goto Exit; *ahinter = hinter; Exit: - if (error) + if ( error ) ah_hinter_done( hinter ); return error; } - /* create a face's autohint globals */ - FT_Error ah_hinter_new_face_globals( AH_Hinter* hinter, - FT_Face face, - AH_Globals* globals ) + /* create a face's autohint globals */ + FT_Error ah_hinter_new_face_globals( AH_Hinter* hinter, + FT_Face face, + AH_Globals* globals ) { FT_Error error; FT_Memory memory = hinter->memory; AH_Face_Globals* face_globals; - if ( ALLOC( face_globals, sizeof(*face_globals) ) ) + + if ( ALLOC( face_globals, sizeof ( *face_globals ) ) ) goto Exit; hinter->face = face; hinter->globals = face_globals; - if (globals) + + if ( globals ) face_globals->design = *globals; else ah_hinter_compute_globals( hinter ); face->autohint.data = face_globals; - face->autohint.finalizer = (FT_Generic_Finalizer)ah_hinter_done_face_globals; + face->autohint.finalizer = (FT_Generic_Finalizer) + ah_hinter_done_face_globals; face_globals->face = face; Exit: @@ -929,357 +1005,381 @@ } - - /* discard a face's autohint globals */ + /* discard a face's autohint globals */ void ah_hinter_done_face_globals( AH_Face_Globals* globals ) { - FT_Face face = globals->face; - FT_Memory memory = face->memory; + FT_Face face = globals->face; + FT_Memory memory = face->memory; + FREE( globals ); } - - static - FT_Error ah_hinter_load( AH_Hinter* hinter, - FT_UInt glyph_index, - FT_UInt load_flags, - FT_UInt depth ) - { - FT_Face face = hinter->face; - FT_GlyphSlot slot = face->glyph; - FT_Fixed x_scale = face->size->metrics.x_scale; - FT_Fixed y_scale = face->size->metrics.y_scale; - FT_Glyph_Metrics metrics; /* temporary metrics */ - FT_Error error; - AH_Outline* outline = hinter->glyph; - AH_Loader* gloader = hinter->loader; - FT_Bool no_horz_hints = (load_flags & AH_HINT_NO_HORZ_EDGES) != 0; - FT_Bool no_vert_hints = (load_flags & AH_HINT_NO_VERT_EDGES) != 0; - - /* load the glyph */ - error = FT_Load_Glyph( face, glyph_index, load_flags ); - if (error) goto Exit; - - /* save current glyph metrics */ - metrics = slot->metrics; - - switch (slot->format) - { - case ft_glyph_format_outline: - { - /* first of all, copy the outline points in the loader's current */ - /* extra points, which is used to keep original glyph coordinates */ - error = ah_loader_check_points( gloader, slot->outline.n_points+2, - slot->outline.n_contours ); - if (error) goto Exit; - - MEM_Copy( gloader->current.extra_points, slot->outline.points, - slot->outline.n_points * sizeof(FT_Vector) ); - - MEM_Copy( gloader->current.outline.contours, slot->outline.contours, - slot->outline.n_contours*sizeof(short) ); - - MEM_Copy( 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 phantom points */ - hinter->pp1.x = 0; - hinter->pp1.y = 0; - hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); - hinter->pp2.y = 0; - - /* 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.. */ - error = ah_outline_load( outline, face ); /* XXXX: change to slot */ - if (error) goto Exit; - - /* perform feature detection */ - ah_outline_detect_features( outline ); - - if ( !no_horz_hints ) - { - ah_outline_compute_blue_edges( outline, hinter->globals ); - ah_outline_scale_blue_edges( outline, hinter->globals ); - } - - /* perform alignment control */ - ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints ); - ah_hinter_align( hinter ); - - /* now save the current outline into the loader's current table */ - ah_outline_save( outline, gloader ); - - /* we now need to hint the metrics according to the change in */ - /* width/positioning that occured during the hinting process */ - { - FT_Pos old_width, new_width; - FT_Pos old_advance, new_advance; - FT_Pos old_lsb, new_lsb; - AH_Edge* edge1 = outline->vert_edges; /* left-most edge */ - AH_Edge* edge2 = edge1 + outline->num_vedges-1; /* right-mode edge */ - - old_width = edge2->opos - edge1->opos; - new_width = edge2->pos - edge1->pos; - - old_advance = hinter->pp2.x; - old_lsb = edge1->opos; - new_lsb = edge1->pos; - - new_advance = old_advance + (new_width+new_lsb-old_width-old_lsb); - - hinter->pp1.x = ((new_lsb - old_lsb)+32) & -64; - hinter->pp2.x = ((edge2->pos + (old_advance - edge2->opos))+32) & -64; - } - - /* good, we simply add the glyph to our loader's base */ - ah_loader_add( gloader ); - } - break; - - case ft_glyph_format_composite: - { - FT_UInt nn, num_subglyphs = slot->num_subglyphs; - FT_UInt num_base_subgs, start_point, start_contour; - FT_SubGlyph* subglyph; - - start_point = gloader->base.outline.n_points; - start_contour = gloader->base.outline.n_contours; - - /* first of all, copy the subglyph descriptors in the glyph loader */ - error = ah_loader_check_subglyphs( gloader, num_subglyphs ); - if (error) goto Exit; - - MEM_Copy( gloader->current.subglyphs, slot->subglyphs, - num_subglyphs*sizeof(FT_SubGlyph) ); - - 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 = hinter->pp1; - pp2 = hinter->pp2; - - num_base_points = gloader->base.outline.n_points; - - error = ah_hinter_load( hinter, 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 = hinter->pp1; - pp2 = hinter->pp2; - } - else - { - hinter->pp1 = pp1; - hinter->pp2 = pp2; - } - - num_points = gloader->base.outline.n_points; - num_new_points = num_points - num_base_points; - - /* now perform the transform 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* org = gloader->base.extra_points + num_base_points; - FT_Vector* limit = cur + num_new_points; - - for ( ; cur < limit; cur++, org++ ) - { - FT_Vector_Transform( cur, &subglyph->transform ); - FT_Vector_Transform( org, &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 may consider another approach in the near future */ - 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, x_scale ); - y = FT_MulFix( subglyph->arg2, y_scale ); - - x = ( x + 32 ) & -64; - y = ( y + 32 ) & -64; - } - - { - FT_Outline dummy = gloader->base.outline; - dummy.points += num_base_points; - dummy.n_points = 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; - - /* we must translate our final outline by -pp1.x, and compute */ - /* the new metrics.. */ - if (hinter->pp1.x) - FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 ); - - FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); - bbox.xMin &= -64; - bbox.yMin &= -64; - bbox.xMax = (bbox.xMax+63) & -64; - bbox.yMax = (bbox.yMax+63) & -64; - - 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.horiAdvance = hinter->pp2.x - hinter->pp1.x; - /* XXXX: TO DO - slot->linearHoriAdvance */ - - /* now copy outline into glyph slot */ - ah_loader_rewind( slot->loader ); - error = ah_loader_copy_points( slot->loader, gloader ); - if (error) goto Exit; - - slot->outline = slot->loader->base.outline; - slot->format = ft_glyph_format_outline; - } - - Exit: - return error; - } + static + FT_Error ah_hinter_load( AH_Hinter* hinter, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_UInt depth ) + { + FT_Face face = hinter->face; + FT_GlyphSlot slot = face->glyph; + FT_Fixed x_scale = face->size->metrics.x_scale; + FT_Fixed y_scale = face->size->metrics.y_scale; + FT_Glyph_Metrics metrics; /* temporary metrics */ + FT_Error error; + AH_Outline* outline = hinter->glyph; + AH_Loader* gloader = hinter->loader; + FT_Bool no_horz_hints = + ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0; + FT_Bool no_vert_hints = + ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0; - /* load and hint a given glyph */ - FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, - FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_Int load_flags ) - { - FT_Face face = slot->face; - FT_Error error; - FT_Fixed x_scale = size->metrics.x_scale; - FT_Fixed y_scale = size->metrics.y_scale; - AH_Face_Globals* face_globals = FACE_GLOBALS(face); + /* load the glyph */ + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + goto Exit; - /* first of all, we need to check that we're using the correct face and */ - /* global hints to load the glyph */ - if ( hinter->face != face || hinter->globals != face_globals ) - { - hinter->face = face; - if (!face_globals) - { - error = ah_hinter_new_face_globals( hinter, face, 0 ); - if (error) goto Exit; - } - hinter->globals = FACE_GLOBALS(face); - face_globals = FACE_GLOBALS(face); - } + /* save current glyph metrics */ + metrics = slot->metrics; - /* now, we must check the current character pixel size to see if we need */ - /* to rescale the global metrics.. */ - if ( face_globals->x_scale != x_scale || - face_globals->y_scale != y_scale ) - { - ah_hinter_scale_globals( hinter, x_scale, y_scale ); - } + switch ( slot->format ) + { + case ft_glyph_format_outline: + /* first of all, copy the outline points in the loader's current */ + /* extra points, which is used to keep original glyph coordinates */ + error = ah_loader_check_points( gloader, slot->outline.n_points + 2, + slot->outline.n_contours ); + if ( error ) + goto Exit; - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; + MEM_Copy( gloader->current.extra_points, slot->outline.points, + slot->outline.n_points * sizeof ( FT_Vector ) ); - ah_loader_rewind( hinter->loader ); + MEM_Copy( gloader->current.outline.contours, slot->outline.contours, + slot->outline.n_contours * sizeof ( short ) ); - error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + MEM_Copy( gloader->current.outline.tags, slot->outline.tags, + slot->outline.n_points * sizeof ( char ) ); - Exit: - return error; - } + gloader->current.outline.n_points = slot->outline.n_points; + gloader->current.outline.n_contours = slot->outline.n_contours; + + /* compute original phantom points */ + hinter->pp1.x = 0; + hinter->pp1.y = 0; + hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); + hinter->pp2.y = 0; + + /* 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 */ + error = ah_outline_load( outline, face ); /* XXX: change to slot */ + if ( error ) + goto Exit; + + /* perform feature detection */ + ah_outline_detect_features( outline ); + + if ( !no_horz_hints ) + { + ah_outline_compute_blue_edges( outline, hinter->globals ); + ah_outline_scale_blue_edges( outline, hinter->globals ); + } + + /* perform alignment control */ + ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints ); + ah_hinter_align( hinter ); + + /* now save the current outline into the loader's current table */ + ah_outline_save( outline, gloader ); + + /* we now need to hint the metrics according to the change in */ + /* width/positioning that occured during the hinting process */ + { + FT_Pos old_width, new_width; + FT_Pos old_advance, new_advance; + FT_Pos old_lsb, new_lsb; + AH_Edge* edge1 = outline->vert_edges; /* leftmost edge */ + AH_Edge* edge2 = edge1 + + outline->num_vedges - 1; /* rightmost edge */ - /* retrieve a face's autohint globals for client applications */ + old_width = edge2->opos - edge1->opos; + new_width = edge2->pos - edge1->pos; + + old_advance = hinter->pp2.x; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + new_advance = old_advance + + ( new_width + new_lsb - old_width - old_lsb ); + + hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64; + hinter->pp2.x = ( ( edge2->pos + + ( old_advance - edge2->opos ) ) + 32 ) & -64; + } + + /* good, we simply add the glyph to our loader's base */ + ah_loader_add( gloader ); + break; + + case ft_glyph_format_composite: + { + FT_UInt nn, num_subglyphs = slot->num_subglyphs; + FT_UInt num_base_subgs, start_point, start_contour; + FT_SubGlyph* subglyph; + + + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + + /* first of all, copy the subglyph descriptors in the glyph loader */ + error = ah_loader_check_subglyphs( gloader, num_subglyphs ); + if ( error ) + goto Exit; + + MEM_Copy( gloader->current.subglyphs, slot->subglyphs, + num_subglyphs * sizeof ( FT_SubGlyph ) ); + + 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 = hinter->pp1; + pp2 = hinter->pp2; + + num_base_points = gloader->base.outline.n_points; + + error = ah_hinter_load( hinter, 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 = hinter->pp1; + pp2 = hinter->pp2; + } + else + { + hinter->pp1 = pp1; + hinter->pp2 = pp2; + } + + num_points = gloader->base.outline.n_points; + num_new_points = num_points - num_base_points; + + /* now perform the transform 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* org = gloader->base.extra_points + + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for ( ; cur < limit; cur++, org++ ) + { + FT_Vector_Transform( cur, &subglyph->transform ); + FT_Vector_Transform( org, &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 may consider another approach in the near future */ + 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, x_scale ); + y = FT_MulFix( subglyph->arg2, y_scale ); + + x = ( x + 32 ) & -64; + y = ( y + 32 ) & -64; + } + + { + FT_Outline dummy = gloader->base.outline; + + + dummy.points += num_base_points; + dummy.n_points = 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; + + + /* we must translate our final outline by -pp1.x, and compute */ + /* the new metrics */ + if ( hinter->pp1.x ) + FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 ); + + FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); + bbox.xMin &= -64; + bbox.yMin &= -64; + bbox.xMax = ( bbox.xMax + 63 ) & -64; + bbox.yMax = ( bbox.yMax + 63 ) & -64; + + 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.horiAdvance = hinter->pp2.x - hinter->pp1.x; + /* XXX: TO DO - slot->linearHoriAdvance */ + + /* now copy outline into glyph slot */ + ah_loader_rewind( slot->loader ); + error = ah_loader_copy_points( slot->loader, gloader ); + if ( error ) + goto Exit; + + slot->outline = slot->loader->base.outline; + slot->format = ft_glyph_format_outline; + } + + Exit: + return error; + } + + + /* load and hint a given glyph */ + FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ) + { + FT_Face face = slot->face; + FT_Error error; + FT_Fixed x_scale = size->metrics.x_scale; + FT_Fixed y_scale = size->metrics.y_scale; + AH_Face_Globals* face_globals = FACE_GLOBALS( face ); + + + /* first of all, we need to check that we're using the correct face and */ + /* global hints to load the glyph */ + if ( hinter->face != face || hinter->globals != face_globals ) + { + hinter->face = face; + if ( !face_globals ) + { + error = ah_hinter_new_face_globals( hinter, face, 0 ); + if ( error ) + goto Exit; + } + hinter->globals = FACE_GLOBALS( face ); + face_globals = FACE_GLOBALS( face ); + } + + /* now, we must check the current character pixel size to see if we */ + /* need to rescale the global metrics */ + if ( face_globals->x_scale != x_scale || + face_globals->y_scale != y_scale ) + ah_hinter_scale_globals( hinter, x_scale, y_scale ); + + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; + + ah_loader_rewind( hinter->loader ); + + error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + + Exit: + return error; + } + + + /* retrieve a face's autohint globals for client applications */ void ah_hinter_get_global_hints( AH_Hinter* hinter, FT_Face face, - void* *global_hints, - long *global_len ) + void** global_hints, + long* global_len ) { AH_Globals* globals = 0; FT_Memory memory = hinter->memory; FT_Error error; + /* allocate new master globals */ - if (ALLOC( globals, sizeof(*globals))) + if ( ALLOC( globals, sizeof ( *globals ) ) ) goto Fail; /* compute face globals if needed */ - if (!FACE_GLOBALS(face)) + if ( !FACE_GLOBALS( face ) ) { error = ah_hinter_new_face_globals( hinter, face, 0 ); - if (error) goto Fail; + if ( error ) + goto Fail; } - *globals = FACE_GLOBALS(face)->design; + *globals = FACE_GLOBALS( face )->design; *global_hints = globals; - *global_len = sizeof(*globals); + *global_len = sizeof( *globals ); + return; Fail: FREE( globals ); + *global_hints = 0; *global_len = 0; } @@ -1288,8 +1388,11 @@ void ah_hinter_done_global_hints( AH_Hinter* hinter, void* global_hints ) { - FT_Memory memory = hinter->memory; + FT_Memory memory = hinter->memory; + + FREE( global_hints ); } +/* END */ diff --git a/src/autohint/ahhint.h b/src/autohint/ahhint.h index 212743392..bb297fb80 100644 --- a/src/autohint/ahhint.h +++ b/src/autohint/ahhint.h @@ -2,64 +2,71 @@ /* */ /* ahhint.h */ /* */ -/* Glyph hinter declarations */ +/* Glyph hinter (declaration). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ -#ifndef AGHINT_H -#define AGHINT_H + + +#ifndef AHHINT_H +#define AHHINT_H + #ifdef FT_FLAT_COMPILE + #include "ahglobal.h" + #else + #include + #endif -#define AH_HINT_DEFAULT 0 -#define AH_HINT_NO_ALIGNMENT 1 -#define AH_HINT_NO_HORZ_EDGES 0x20000 -#define AH_HINT_NO_VERT_EDGES 0x40000 + +#define AH_HINT_DEFAULT 0 +#define AH_HINT_NO_ALIGNMENT 1 +#define AH_HINT_NO_HORZ_EDGES 0x20000L +#define AH_HINT_NO_VERT_EDGES 0x40000L + /* create a new empty hinter object */ + FT_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ); - /* create a new empty hinter object */ - extern - FT_Error ah_hinter_new( FT_Library library, AH_Hinter* *ahinter ); - - /* Load a hinted glyph in the hinter */ - extern + /* Load a hinted glyph in the hinter */ FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, FT_GlyphSlot slot, FT_Size size, FT_UInt glyph_index, FT_Int load_flags ); - /* finalise a hinter object */ - extern - void ah_hinter_done( AH_Hinter* hinter ); + /* finalize a hinter object */ + void ah_hinter_done( AH_Hinter* hinter ); LOCAL_DEF - void ah_hinter_done_face_globals( AH_Face_Globals* globals ); + void ah_hinter_done_face_globals( AH_Face_Globals* globals ); - extern - void ah_hinter_get_global_hints( AH_Hinter* hinter, - FT_Face face, - void* *global_hints, - long *global_len ); + void ah_hinter_get_global_hints( AH_Hinter* hinter, + FT_Face face, + void** global_hints, + long* global_len ); - extern - void ah_hinter_done_global_hints( AH_Hinter* hinter, - void* global_hints ); + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ); -#endif /* AGHINT_H */ + +#endif /* AHHINT_H */ + + +/* END */ diff --git a/src/autohint/ahloader.h b/src/autohint/ahloader.h index 68f3e22b2..4a8563c0a 100644 --- a/src/autohint/ahloader.h +++ b/src/autohint/ahloader.h @@ -2,44 +2,53 @@ /* */ /* ahloader.h */ /* */ -/* Glyph loader implementation for the auto-hinting module */ -/* This defines the AG_GlyphLoader type in two different ways: */ +/* Glyph loader for the auto-hinting module (declaration only). */ /* */ -/* - when the module is compiled within FreeType 2, the type */ -/* is simply a typedef to FT_GlyphLoader */ -/* */ -/* - when the module is compiled as a standalone object, */ -/* AG_GlyphLoader has its own implementation.. */ -/* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ -#ifndef AGLOADER_H -#define AGLOADER_H + + + /*************************************************************************/ + /* */ + /* This defines the AH_GlyphLoader type in two different ways: */ + /* */ + /* - If the module is compiled within FreeType 2, the type is simply a */ + /* typedef to FT_GlyphLoader. */ + /* */ + /* - If the module is compiled as a standalone object, AH_GlyphLoader */ + /* has its own implementation. */ + /* */ + /*************************************************************************/ + + +#ifndef AHLOADER_H +#define AHLOADER_H + #ifdef _STANDALONE_ - typedef struct AH_GlyphLoad_ + typedef struct AH_GlyphLoad_ { - FT_Outline outline; /* outline */ - FT_UInt num_subglyphs; /* number of subglyphs */ - FT_SubGlyph* subglyphs; /* subglyphs */ - FT_Vector* extra_points; /* extra points table.. */ + FT_Outline outline; /* outline */ + FT_UInt num_subglyphs; /* number of subglyphs */ + FT_SubGlyph* subglyphs; /* subglyphs */ + FT_Vector* extra_points; /* extra points table */ } AH_GlyphLoad; - struct AH_GlyphLoader_ + struct AH_GlyphLoader_ { FT_Memory memory; FT_UInt max_points; @@ -50,38 +59,47 @@ AH_GlyphLoad base; AH_GlyphLoad current; - void* other; /* for possible future extension ? */ - + void* other; /* for possible future extensions */ }; - LOCAL_DEF FT_Error AH_GlyphLoader_New( FT_Memory memory, - AH_GlyphLoader* *aloader ); + LOCAL_DEF + FT_Error AH_GlyphLoader_New( FT_Memory memory, + AH_GlyphLoader** aloader ); - LOCAL_DEF FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); + LOCAL_DEF + FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); - LOCAL_DEF void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); + LOCAL_DEF + void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); - LOCAL_DEF void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); + LOCAL_DEF + void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); - LOCAL_DEF void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); + LOCAL_DEF + void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); - LOCAL_DEF FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, - FT_UInt n_points, - FT_UInt n_contours ); + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); - LOCAL_DEF FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, - FT_UInt n_subs ); + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, + FT_UInt n_subs ); - LOCAL_DEF void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); + LOCAL_DEF + void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); + LOCAL_DEF + void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); - LOCAL_DEF void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); + LOCAL_DEF + FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, + FT_GlyphLoader* source ); - LOCAL_DEF FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, - FT_GlyphLoader* source ); +#else /* _STANDALONE */ -#else #include #define AH_Load FT_GlyphLoad @@ -98,6 +116,9 @@ #define ah_loader_add FT_GlyphLoader_Add #define ah_loader_copy_points FT_GlyphLoader_Copy_Points -#endif +#endif /* _STANDALONE_ */ -#endif /* AGLOADER_H */ +#endif /* AHLOADER_H */ + + +/* END */ diff --git a/src/autohint/ahmodule.c b/src/autohint/ahmodule.c index 887d03d08..85755681e 100644 --- a/src/autohint/ahmodule.c +++ b/src/autohint/ahmodule.c @@ -2,34 +2,41 @@ /* */ /* ahmodule.c */ /* */ -/* Auto-hinting module implementation */ +/* Auto-hinting module implementation (declaration). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ + + #include + #ifdef FT_FLAT_COMPILE + #include "ahhint.h" + #else + #include + #endif - typedef struct FT_AutoHinterRec_ + typedef struct FT_AutoHinterRec_ { - FT_ModuleRec root; - AH_Hinter* hinter; + FT_ModuleRec root; + AH_Hinter* hinter; } FT_AutoHinterRec; @@ -40,37 +47,42 @@ return ah_hinter_new( module->root.library, &module->hinter ); } + static - void ft_autohinter_done( FT_AutoHinter module ) + void ft_autohinter_done( FT_AutoHinter module ) { ah_hinter_done( module->hinter ); } + static FT_Error ft_autohinter_load( FT_AutoHinter module, FT_GlyphSlot slot, - FT_Size size, - FT_UInt glyph_index, - FT_ULong load_flags ) + FT_Size size, + FT_UInt glyph_index, + FT_ULong load_flags ) { return ah_hinter_load_glyph( module->hinter, slot, size, glyph_index, load_flags ); } + static void ft_autohinter_reset( FT_AutoHinter module, FT_Face face ) { - UNUSED(module); - if (face->autohint.data) - ah_hinter_done_face_globals( face->autohint.data ); + UNUSED( module ); + + if ( face->autohint.data ) + ah_hinter_done_face_globals( (AH_Face_Globals*)(face->autohint.data) ); } + static void ft_autohinter_get_globals( FT_AutoHinter module, FT_Face face, - void* *global_hints, - long *global_len ) + void** global_hints, + long* global_len ) { ah_hinter_get_global_hints( module->hinter, face, global_hints, global_len ); @@ -94,18 +106,22 @@ ft_autohinter_done_globals }; + const FT_Module_Class autohint_module_class = { ft_module_hinter, - sizeof( FT_AutoHinterRec ), + sizeof ( FT_AutoHinterRec ), "autohinter", - 0x10000, /* version 1.0 of the autohinter */ - 0x20000, /* requires FreeType 2.0 or above */ + 0x10000L, /* version 1.0 of the autohinter */ + 0x20000L, /* requires FreeType 2.0 or above */ (const void*)&autohinter_interface, - (FT_Module_Constructor) ft_autohinter_init, - (FT_Module_Destructor) ft_autohinter_done, - (FT_Module_Requester) 0 + (FT_Module_Constructor)ft_autohinter_init, + (FT_Module_Destructor) ft_autohinter_done, + (FT_Module_Requester) 0 }; + + +/* END */ diff --git a/src/autohint/ahmodule.h b/src/autohint/ahmodule.h index 7a5789619..28b07538b 100644 --- a/src/autohint/ahmodule.h +++ b/src/autohint/ahmodule.h @@ -2,26 +2,31 @@ /* */ /* ahmodule.h */ /* */ -/* Auto-hinting module declaration */ +/* Auto-hinting module (declaration). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ + + #ifndef AHMODULE_H #define AHMODULE_H #include - FT_EXPORT_VAR(const FT_Module_Class) autohint_module_class; + FT_EXPORT_VAR( const FT_Module_Class ) autohint_module_class; #endif /* AHMODULE_H */ + + +/* END */ diff --git a/src/autohint/ahoptim.c b/src/autohint/ahoptim.c index daf49f6a9..d301dd7ee 100644 --- a/src/autohint/ahoptim.c +++ b/src/autohint/ahoptim.c @@ -1,106 +1,131 @@ /***************************************************************************/ /* */ -/* FreeType Auto-Gridder Outline Optimisation */ +/* ahoptim.c */ /* */ -/* This module is in charge of optimising the outlines produced by the */ -/* auto-hinter in direct mode. This is required at small pixel sizes in */ -/* order to ensure coherent spacing, among other things.. */ +/* FreeType auto hinting outline optimization (body). */ /* */ -/* The technique used in this module is a simplified simulated annealing. */ -/* */ -/* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ -#include /* for ALLOC_ARRAY and FREE */ + + /*************************************************************************/ + /* */ + /* This module is in charge of optimising the outlines produced by the */ + /* auto-hinter in direct mode. This is required at small pixel sizes in */ + /* order to ensure coherent spacing, among other things.. */ + /* */ + /* The technique used in this module is a simplified simulated */ + /* annealing. */ + /* */ + /*************************************************************************/ + + +#include /* for ALLOC_ARRAY() and FREE() */ + #ifdef FT_FLAT_COMPILE + #include "ahoptim.h" + #else + #include + #endif -/* define this macro to use brute force optimisation, this is slow, but */ -/* a good way to perfect the distortion function "by hand" through */ -/* tweaking.. */ -#define BRUTE_FORCE -#define xxxDEBUG_OPTIM + /* define this macro to use brute force optimisation -- this is slow, */ + /* but a good way to perfect the distortion function `by hand' through */ + /* tweaking */ +#define AH_BRUTE_FORCE + + +#define xxxAH_DEBUG_OPTIM + #undef LOG -#ifdef DEBUG_OPTIM -#define LOG(x) optim_log##x -#else -#define LOG(x) -#endif +#ifdef AH_DEBUG_OPTIM + +#define LOG( x ) optim_log##x + +#else + +#define LOG( x ) + +#endif /* AH_DEBUG_OPTIM */ + + +#ifdef AH_DEBUG_OPTIM -#ifdef DEBUG_OPTIM #include #include #include -#define FLOAT(x) ((float)((x)/64.0)) +#define FLOAT( x ) ( (float)( (x) / 64.0 ) ) -static -void optim_log( const char* fmt, ... ) -{ - va_list ap; + static + void optim_log( const char* fmt, ... ) + { + va_list ap; - va_start( ap, fmt ); - vprintf( fmt, ap ); - va_end( ap ); -} -#endif + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + } -#ifdef DEBUG_OPTIM static void AH_Dump_Stems( AH_Optimizer* optimizer ) { int n; AH_Stem* stem; + stem = optimizer->stems; for ( n = 0; n < optimizer->num_stems; n++, stem++ ) { - LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}=<%1.f..%1.f> force=%.1f speed=%.1f\n", + LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}=" + "<%1.f..%1.f> force=%.1f speed=%.1f\n", optimizer->vertical ? 'V' : 'H', n, - FLOAT(stem->edge1->opos), FLOAT(stem->edge2->opos), - FLOAT(stem->edge1->pos), FLOAT(stem->edge2->pos), - FLOAT(stem->min_pos), FLOAT(stem->max_pos), - FLOAT(stem->force), FLOAT(stem->velocity) )); + FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ), + FLOAT( stem->edge1->pos ), FLOAT( stem->edge2->pos ), + FLOAT( stem->min_pos ), FLOAT( stem->max_pos ), + FLOAT( stem->force ), FLOAT( stem->velocity ) )); } } + static void AH_Dump_Stems2( AH_Optimizer* optimizer ) { int n; AH_Stem* stem; + stem = optimizer->stems; for ( n = 0; n < optimizer->num_stems; n++, stem++ ) { LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n", optimizer->vertical ? 'V' : 'H', n, - FLOAT(stem->pos), - FLOAT(stem->min_pos), FLOAT(stem->max_pos), - FLOAT(stem->force), FLOAT(stem->velocity) )); + FLOAT( stem->pos ), + FLOAT( stem->min_pos ), FLOAT( stem->max_pos ), + FLOAT( stem->force ), FLOAT( stem->velocity ) )); } } + static void AH_Dump_Springs( AH_Optimizer* optimizer ) { @@ -108,20 +133,25 @@ void optim_log( const char* fmt, ... ) AH_Spring* spring; AH_Stem* stems; + spring = optimizer->springs; stems = optimizer->stems; LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' )); + for ( n = 0; n < optimizer->num_springs; n++, spring++ ) { - LOG(( " [%d-%d:%.1f:%1.f:%.1f]", spring->stem1 - stems, spring->stem2 - stems, - FLOAT(spring->owidth), - FLOAT(spring->stem2->pos-(spring->stem1->pos+spring->stem1->width)), - FLOAT(spring->tension) )); + LOG(( " [%d-%d:%.1f:%1.f:%.1f]", + spring->stem1 - stems, spring->stem2 - stems, + FLOAT( spring->owidth ), + FLOAT( spring->stem2->pos - + ( spring->stem1->pos + spring->stem1->width ) ), + FLOAT( spring->tension ) )); } LOG(( "\n" )); } -#endif + +#endif /* AH_DEBUG_OPTIM */ /*************************************************************************/ @@ -130,23 +160,27 @@ void optim_log( const char* fmt, ... ) /**** ****/ /**** COMPUTE STEMS AND SPRINGS IN AN OUTLINE ****/ /**** ****/ - /**** ****/ - /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ + static - int valid_stem_segments( AH_Segment* seg1, AH_Segment* seg2 ) + int valid_stem_segments( AH_Segment* seg1, + AH_Segment* seg2 ) { - return seg1->serif == 0 && seg2 && seg2->link == seg1 && seg1->pos < seg2->pos && + return seg1->serif == 0 && + seg2 && + seg2->link == seg1 && + seg1->pos < seg2->pos && seg1->min_coord <= seg2->max_coord && seg2->min_coord <= seg1->max_coord; } + /* compute all stems in an outline */ static - int optim_compute_stems( AH_Optimizer* optimizer ) + int optim_compute_stems( AH_Optimizer* optimizer ) { AH_Outline* outline = optimizer->outline; FT_Fixed scale; @@ -158,6 +192,7 @@ void optim_log( const char* fmt, ... ) AH_Stem** p_stems; FT_Int* p_num_stems; + edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; scale = outline->y_scale; @@ -171,25 +206,29 @@ void optim_log( const char* fmt, ... ) FT_Int num_stems = 0; AH_Edge* edge; + /* first of all, count the number of stems in this direction */ for ( edge = edges; edge < edge_limit; edge++ ) { AH_Segment* seg = edge->first; + + do { - if (valid_stem_segments( seg, seg->link )) + if (valid_stem_segments( seg, seg->link ) ) num_stems++; seg = seg->edge_next; - } while (seg != edge->first); + } while ( seg != edge->first ); } /* now allocate the stems and build their table */ - if (num_stems > 0) + if ( num_stems > 0 ) { AH_Stem* stem; + if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) ) goto Exit; @@ -198,14 +237,17 @@ void optim_log( const char* fmt, ... ) { AH_Segment* seg = edge->first; AH_Segment* seg2; + + do { seg2 = seg->link; - if (valid_stem_segments(seg,seg2)) + if ( valid_stem_segments( seg, seg2 ) ) { AH_Edge* edge1 = seg->edge; AH_Edge* edge2 = seg2->edge; + stem->edge1 = edge1; stem->edge2 = edge2; stem->opos = edge1->opos; @@ -218,49 +260,51 @@ void optim_log( const char* fmt, ... ) FT_Pos min_coord = seg->min_coord; FT_Pos max_coord = seg->max_coord; - if (seg2->min_coord > min_coord) + + if ( seg2->min_coord > min_coord ) min_coord = seg2->min_coord; - if (seg2->max_coord < max_coord) + if ( seg2->max_coord < max_coord ) max_coord = seg2->max_coord; stem->min_coord = min_coord; stem->max_coord = max_coord; } - /* compute minimum and maximum positions for stem */ + /* compute minimum and maximum positions for stem -- */ /* note that the left-most/bottom-most stem has always */ - /* a fixed position.. */ - if (stem == stems || edge1->blue_edge || edge2->blue_edge) + /* a fixed position */ + if ( stem == stems || edge1->blue_edge || edge2->blue_edge ) { - /* this stem cannot move, it is snapped to a blue edge */ + /* this stem cannot move; it is snapped to a blue edge */ stem->min_pos = stem->pos; stem->max_pos = stem->pos; } else { - /* this edge can move, compute its min and max positions */ + /* this edge can move; compute its min and max positions */ FT_Pos pos1 = stem->opos; FT_Pos pos2 = pos1 + stem->owidth - stem->width; - FT_Pos min1 = (pos1 & -64); - FT_Pos min2 = (pos2 & -64); + FT_Pos min1 = pos1 & -64; + FT_Pos min2 = pos2 & -64; + stem->min_pos = min1; - stem->max_pos = min1+64; - if (min2 < min1) + stem->max_pos = min1 + 64; + if ( min2 < min1 ) stem->min_pos = min2; else - stem->max_pos = min2+64; + stem->max_pos = min2 + 64; - /* XXX : just to see what it does */ + /* XXX: just to see what it does */ stem->max_pos += 64; - /* just for the case where direct hinting did some incredible */ - /* things (e.g. blue edge shifts..) */ - if (stem->min_pos > stem->pos) + /* just for the case where direct hinting did some */ + /* incredible things (e.g. blue edge shifts) */ + if ( stem->min_pos > stem->pos ) stem->min_pos = stem->pos; - if (stem->max_pos < stem->pos) + if ( stem->max_pos < stem->pos ) stem->max_pos = stem->pos; } @@ -270,8 +314,8 @@ void optim_log( const char* fmt, ... ) stem++; } seg = seg->edge_next; - } - while (seg != edge->first); + + } while ( seg != edge->first ); } } @@ -285,17 +329,21 @@ void optim_log( const char* fmt, ... ) p_stems = &optimizer->vert_stems; p_num_stems = &optimizer->num_vstems; } + Exit: - #ifdef DEBUG_OPTIM - AH_Dump_Stems(optimizer); - #endif + +#ifdef AH_DEBUG_OPTIM + AH_Dump_Stems( optimizer ); +#endif + return error; } /* returns the spring area between two stems, 0 if none */ static - FT_Pos stem_spring_area( AH_Stem* stem1, AH_Stem* stem2 ) + FT_Pos stem_spring_area( AH_Stem* stem1, + AH_Stem* stem2 ) { FT_Pos area1 = stem1->max_coord - stem1->min_coord; FT_Pos area2 = stem2->max_coord - stem2->min_coord; @@ -303,18 +351,19 @@ void optim_log( const char* fmt, ... ) FT_Pos max = stem1->max_coord; FT_Pos area; + /* order stems */ - if (stem2->opos <= stem1->opos + stem1->owidth) + if ( stem2->opos <= stem1->opos + stem1->owidth ) return 0; - if (min < stem2->min_coord) + if ( min < stem2->min_coord ) min = stem2->min_coord; - if (max < stem2->max_coord) + if ( max < stem2->max_coord ) max = stem2->max_coord; - area = (max-min); - if ( 2*area < area1 && 2*area < area2 ) + area = ( max-min ); + if ( 2 * area < area1 && 2 * area < area2 ) area = 0; return area; @@ -326,7 +375,7 @@ void optim_log( const char* fmt, ... ) int optim_compute_springs( AH_Optimizer* optimizer ) { /* basically, a spring exists between two stems if most of their */ - /* surface is aligned.. */ + /* surface is aligned */ FT_Memory memory = optimizer->memory; AH_Stem* stems; @@ -338,6 +387,7 @@ void optim_log( const char* fmt, ... ) FT_Int* p_num_springs; AH_Spring** p_springs; + stems = optimizer->horz_stems; stem_limit = stems + optimizer->num_hstems; @@ -349,20 +399,24 @@ void optim_log( const char* fmt, ... ) FT_Int num_springs = 0; AH_Spring* springs = 0; + /* first of all, count stem springs */ - for ( stem = stems; stem+1 < stem_limit; stem++ ) + for ( stem = stems; stem + 1 < stem_limit; stem++ ) { AH_Stem* stem2; + + for ( stem2 = stem+1; stem2 < stem_limit; stem2++ ) - if (stem_spring_area(stem,stem2)) + if ( stem_spring_area( stem, stem2 ) ) num_springs++; } /* then allocate and build the springs table */ - if (num_springs > 0) + if ( num_springs > 0 ) { AH_Spring* spring; + /* allocate table of springs */ if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) ) goto Exit; @@ -374,15 +428,16 @@ void optim_log( const char* fmt, ... ) AH_Stem* stem2; FT_Pos area; - for ( stem2 = stem+1; stem2 < stem_limit; stem2++ ) + + for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ ) { - area = stem_spring_area(stem,stem2); - if (area) + area = stem_spring_area( stem, stem2 ); + if ( area ) { /* add a new spring here */ spring->stem1 = stem; spring->stem2 = stem2; - spring->owidth = stem2->opos - (stem->opos + stem->owidth); + spring->owidth = stem2->opos - ( stem->opos + stem->owidth ); spring->tension = 0; spring++; @@ -401,31 +456,35 @@ void optim_log( const char* fmt, ... ) } Exit: - #ifdef DEBUG_OPTIM - AH_Dump_Springs(optimizer); - #endif + +#ifdef AH_DEBUG_OPTIM + AH_Dump_Springs( optimizer ); +#endif + return error; } + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /**** ****/ - /**** OPTIMISE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/ - /**** ****/ - /**** ****/ + /**** OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ -#ifndef BRUTE_FORCE +#ifndef AH_BRUTE_FORCE + /* compute all spring tensions */ static void optim_compute_tensions( AH_Optimizer* optimizer ) { AH_Spring* spring = optimizer->springs; AH_Spring* limit = spring + optimizer->num_springs; + + for ( ; spring < limit; spring++ ) { AH_Stem* stem1 = spring->stem1; @@ -436,111 +495,115 @@ void optim_log( const char* fmt, ... ) FT_Pos tension; FT_Pos sign; - /* compute the tension, it simply is -K*(new_width-old_width) */ - width = stem2->pos - (stem1->pos + stem1->width); - tension = width - spring->owidth; + + /* compute the tension; it simply is -K*(new_width-old_width) */ + width = stem2->pos - ( stem1->pos + stem1->width ); + tension = width - spring->owidth; sign = 1; - if (tension < 0) + if ( tension < 0 ) { sign = -1; tension = -tension; } - if (width <= 0) + if ( width <= 0 ) tension = 32000; else - tension = (tension << 10)/width; + tension = ( tension << 10 ) / width; - tension = -sign*FT_MulFix( tension, optimizer->tension_scale ); + tension = -sign * FT_MulFix( tension, optimizer->tension_scale ); spring->tension = tension; /* now, distribute tension among the englobing stems, if they */ - /* are able to move.. */ + /* are able to move */ status = 0; - if (stem1->pos <= stem1->min_pos) + if ( stem1->pos <= stem1->min_pos ) status |= 1; - if (stem2->pos >= stem2->max_pos) + if ( stem2->pos >= stem2->max_pos ) status |= 2; - if (!status) + if ( !status ) tension /= 2; - if ((status & 1)== 0) + if ( ( status & 1 ) == 0 ) stem1->force -= tension; - if ((status & 2)== 0) + if ( ( status & 2 ) == 0 ) stem2->force += tension; } } - - /* compute all stem movements - returns 0 if nothing moved */ + /* compute all stem movements -- returns 0 if nothing moved */ static - int optim_compute_stem_movements( AH_Optimizer* optimizer ) + int optim_compute_stem_movements( AH_Optimizer* optimizer ) { AH_Stem* stems = optimizer->stems; AH_Stem* limit = stems + optimizer->num_stems; AH_Stem* stem = stems; int moved = 0; + /* set initial forces to velocity */ for ( stem = stems; stem < limit; stem++ ) { stem->force = stem->velocity; - stem->velocity /= 2; /* XXXX: Heuristics */ + stem->velocity /= 2; /* XXX: Heuristics */ } /* compute the sum of forces applied on each stem */ optim_compute_tensions( optimizer ); - #ifdef DEBUG_OPTIM + +#ifdef AH_DEBUG_OPTIM AH_Dump_Springs( optimizer ); AH_Dump_Stems2( optimizer ); - #endif +#endif - /* now, see if something can move ? */ + /* now, see whether something can move */ for ( stem = stems; stem < limit; stem++ ) { - if (stem->force > optimizer->tension_threshold) + if ( stem->force > optimizer->tension_threshold ) { /* there is enough tension to move the stem to the right */ - if (stem->pos < stem->max_pos) + if ( stem->pos < stem->max_pos ) { - stem->pos += 64; - stem->velocity = stem->force/2; - moved = 1; + stem->pos += 64; + stem->velocity = stem->force / 2; + moved = 1; } else stem->velocity = 0; } - else if (stem->force < optimizer->tension_threshold) + else if ( stem->force < optimizer->tension_threshold ) { /* there is enough tension to move the stem to the left */ - if (stem->pos > stem->min_pos) + if ( stem->pos > stem->min_pos ) { - stem->pos -= 64; - stem->velocity = stem->force/2; - moved = 1; + stem->pos -= 64; + stem->velocity = stem->force / 2; + moved = 1; } else stem->velocity = 0; } } + /* return 0 if nothing moved */ return moved; } -#endif /* BRUTE_FORCE */ +#endif /* AH_BRUTE_FORCE */ /* compute current global distortion from springs */ static - FT_Pos optim_compute_distorsion( AH_Optimizer* optimizer ) + FT_Pos optim_compute_distortion( AH_Optimizer* optimizer ) { AH_Spring* spring = optimizer->springs; AH_Spring* limit = spring + optimizer->num_springs; - FT_Pos distorsion = 0; + FT_Pos distortion = 0; + for ( ; spring < limit; spring++ ) { @@ -548,32 +611,34 @@ void optim_log( const char* fmt, ... ) AH_Stem* stem2 = spring->stem2; FT_Pos width; - width = stem2->pos - (stem1->pos + stem1->width); - width -= spring->owidth; - if (width < 0) + width = stem2->pos - ( stem1->pos + stem1->width ); + width -= spring->owidth; + if ( width < 0 ) width = -width; - distorsion += width; + distortion += width; } - return distorsion; + + return distortion; } - /* record stems configuration in "best of" history */ + /* record stems configuration in `best of' history */ static void optim_record_configuration( AH_Optimizer* optimizer ) { - FT_Pos distorsion; + FT_Pos distortion; AH_Configuration* configs = optimizer->configs; AH_Configuration* limit = configs + optimizer->num_configs; AH_Configuration* config; - distorsion = optim_compute_distorsion( optimizer ); - LOG(( "config distorsion = %.1f ", FLOAT(distorsion*64) )); + + distortion = optim_compute_distortion( optimizer ); + LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) )); /* check that we really need to add this configuration to our */ - /* sorted history.. */ - if ( limit > configs && limit[-1].distorsion < distorsion ) + /* sorted history */ + if ( limit > configs && limit[-1].distortion < distortion ) { LOG(( "ejected\n" )); return; @@ -583,46 +648,50 @@ void optim_log( const char* fmt, ... ) { int n; + config = limit; - if (optimizer->num_configs < AH_MAX_CONFIGS) + if ( optimizer->num_configs < AH_MAX_CONFIGS ) optimizer->num_configs++; else config--; - config->distorsion = distorsion; + config->distortion = distortion; for ( n = 0; n < optimizer->num_stems; n++ ) config->positions[n] = optimizer->stems[n].pos; } /* move the current configuration towards the front of the list */ - /* when necessary, yes this is slow bubble sort ;-) */ - while ( config > configs && config[0].distorsion < config[-1].distorsion ) + /* when necessary -- yes this is slow bubble sort ;-) */ + while ( config > configs && config[0].distortion < config[-1].distortion ) { AH_Configuration temp; + + config--; temp = config[0]; config[0] = config[1]; config[1] = temp; } - LOG(( "recorded !!\n" )); + LOG(( "recorded!\n" )); } -#ifdef BRUTE_FORCE +#ifdef AH_BRUTE_FORCE + /* optimize outline in a single direction */ static void optim_compute( AH_Optimizer* optimizer ) { - int n; - FT_Bool moved; - + int n; + FT_Bool moved; AH_Stem* stem = optimizer->stems; AH_Stem* limit = stem + optimizer->num_stems; + /* empty, exit */ - if (stem >= limit) + if ( stem >= limit ) return; optimizer->num_configs = 0; @@ -634,13 +703,13 @@ void optim_log( const char* fmt, ... ) do { /* record current configuration */ - optim_record_configuration(optimizer); + optim_record_configuration( optimizer ); /* now change configuration */ moved = 0; for ( stem = optimizer->stems; stem < limit; stem++ ) { - if (stem->pos < stem->max_pos) + if ( stem->pos < stem->max_pos ) { stem->pos += 64; moved = 1; @@ -649,8 +718,7 @@ void optim_log( const char* fmt, ... ) stem->pos = stem->min_pos; } - } - while (moved); + } while ( moved ); /* now, set the best stem positions */ for ( n = 0; n < optimizer->num_stems; n++ ) @@ -658,6 +726,7 @@ void optim_log( const char* fmt, ... ) AH_Stem* stem = optimizer->stems + n; FT_Pos pos = optimizer->configs[0].positions[n]; + stem->edge1->pos = pos; stem->edge2->pos = pos + stem->width; @@ -665,31 +734,36 @@ void optim_log( const char* fmt, ... ) stem->edge2->flags |= ah_edge_done; } } -#else + +#else /* AH_BRUTE_FORCE */ + /* optimize outline in a single direction */ static void optim_compute( AH_Optimizer* optimizer ) { int n, counter, counter2; + optimizer->num_configs = 0; optimizer->tension_scale = 0x80000L; optimizer->tension_threshold = 64; /* record initial configuration threshold */ - optim_record_configuration(optimizer); + optim_record_configuration( optimizer ); + counter = 0; for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- ) { - if (counter == 0) - counter = 2*optimizer->num_stems; + if ( counter == 0 ) + counter = 2 * optimizer->num_stems; - if (!optim_compute_stem_movements( optimizer )) + if ( !optim_compute_stem_movements( optimizer ) ) break; - optim_record_configuration(optimizer); + optim_record_configuration( optimizer ); + counter--; - if (counter == 0) + if ( counter == 0 ) optimizer->tension_scale /= 2; } @@ -699,6 +773,7 @@ void optim_log( const char* fmt, ... ) AH_Stem* stem = optimizer->stems + n; FT_Pos pos = optimizer->configs[0].positions[n]; + stem->edge1->pos = pos; stem->edge2->pos = pos + stem->width; @@ -706,7 +781,9 @@ void optim_log( const char* fmt, ... ) stem->edge2->flags |= ah_edge_done; } } -#endif + +#endif /* AH_BRUTE_FORCE */ + /*************************************************************************/ /*************************************************************************/ @@ -714,19 +791,19 @@ void optim_log( const char* fmt, ... ) /**** ****/ /**** HIGH-LEVEL OPTIMIZER API ****/ /**** ****/ - /**** ****/ - /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ - /* releases the optimisation data */ + /* releases the optimization data */ void AH_Optimizer_Done( AH_Optimizer* optimizer ) { - if (optimizer) + if ( optimizer ) { FT_Memory memory = optimizer->memory; + + FREE( optimizer->horz_stems ); FREE( optimizer->vert_stems ); FREE( optimizer->horz_springs ); @@ -735,6 +812,7 @@ void optim_log( const char* fmt, ... ) } } + /* loads the outline into the optimizer */ int AH_Optimizer_Init( AH_Optimizer* optimizer, AH_Outline* outline, @@ -742,7 +820,8 @@ void optim_log( const char* fmt, ... ) { FT_Error error; - MEM_Set( optimizer, 0, sizeof(*optimizer)); + + MEM_Set( optimizer, 0, sizeof ( *optimizer ) ); optimizer->outline = outline; optimizer->memory = memory; @@ -750,22 +829,26 @@ void optim_log( const char* fmt, ... ) /* compute stems and springs */ error = optim_compute_stems ( optimizer ) || optim_compute_springs( optimizer ); - if (error) goto Fail; + if ( error ) + goto Fail; /* allocate stem positions history and configurations */ { int n, max_stems; + max_stems = optimizer->num_hstems; - if (max_stems < optimizer->num_vstems) + if ( max_stems < optimizer->num_vstems ) max_stems = optimizer->num_vstems; - if ( ALLOC_ARRAY( optimizer->positions, max_stems*AH_MAX_CONFIGS, FT_Pos ) ) + if ( ALLOC_ARRAY( optimizer->positions, + max_stems * AH_MAX_CONFIGS, FT_Pos ) ) goto Fail; optimizer->num_configs = 0; for ( n = 0; n < AH_MAX_CONFIGS; n++ ) - optimizer->configs[n].positions = optimizer->positions + n*max_stems; + optimizer->configs[n].positions = optimizer->positions + + n * max_stems; } return error; @@ -784,9 +867,9 @@ void optim_log( const char* fmt, ... ) optimizer->num_springs = optimizer->num_hsprings; optimizer->springs = optimizer->horz_springs; - if (optimizer->num_springs > 0) + if ( optimizer->num_springs > 0 ) { - LOG(( "horizontal optimisation ------------------------\n" )); + LOG(( "horizontal optimization ------------------------\n" )); optim_compute( optimizer ); } @@ -795,14 +878,12 @@ void optim_log( const char* fmt, ... ) optimizer->num_springs = optimizer->num_vsprings; optimizer->springs = optimizer->vert_springs; - if (optimizer->num_springs) + if ( optimizer->num_springs ) { - LOG(( "vertical optimisation --------------------------\n" )); + LOG(( "vertical optimization --------------------------\n" )); optim_compute( optimizer ); } } - - - +/* END */ diff --git a/src/autohint/ahoptim.h b/src/autohint/ahoptim.h index 3ff82337a..a1f52bf68 100644 --- a/src/autohint/ahoptim.h +++ b/src/autohint/ahoptim.h @@ -1,64 +1,68 @@ /***************************************************************************/ /* */ -/* FreeType Auto-Gridder Outline Optimisation */ +/* ahoptim.h */ /* */ -/* This module is in charge of optimising the outlines produced by the */ -/* auto-hinter in direct mode. This is required at small pixel sizes in */ -/* order to ensure coherent spacing, among other things.. */ +/* FreeType auto hinting outline optimization (declaration). */ /* */ -/* The technique used in this module is a simplified simulated annealing. */ -/* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ -#ifndef AGOPTIM_H -#define AGOPTIM_H + +#ifndef AHOPTIM_H +#define AHOPTIM_H + #ifdef FT_FLAT_COMPILE + #include "ahtypes.h" + #else + #include + #endif -/* the maximal number of stem configurations to record during optimisation */ + + /* the maximal number of stem configurations to record */ + /* during optimization */ #define AH_MAX_CONFIGS 8 - typedef struct AH_Stem_ + typedef struct AH_Stem_ { - FT_Pos pos; /* current position */ - FT_Pos velocity; /* current velocity */ - FT_Pos force; /* sum of current forces */ - FT_Pos width; /* normalized width */ + FT_Pos pos; /* current position */ + FT_Pos velocity; /* current velocity */ + FT_Pos force; /* sum of current forces */ + FT_Pos width; /* normalized width */ - FT_Pos min_pos; /* minimum grid position */ - FT_Pos max_pos; /* maximum grid position */ + FT_Pos min_pos; /* minimum grid position */ + FT_Pos max_pos; /* maximum grid position */ - AH_Edge* edge1; /* left/bottom edge */ - AH_Edge* edge2; /* right/top edge */ + AH_Edge* edge1; /* left/bottom edge */ + AH_Edge* edge2; /* right/top edge */ - FT_Pos opos; /* original position */ - FT_Pos owidth; /* original width */ + FT_Pos opos; /* original position */ + FT_Pos owidth; /* original width */ - FT_Pos min_coord; /* minimum coordinate */ - FT_Pos max_coord; /* maximum coordinate */ + FT_Pos min_coord; /* minimum coordinate */ + FT_Pos max_coord; /* maximum coordinate */ } AH_Stem; /* A spring between two stems */ - typedef struct AH_Spring_ + typedef struct AH_Spring_ { AH_Stem* stem1; AH_Stem* stem2; @@ -69,69 +73,64 @@ /* A configuration records the position of each stem at a given time */ - /* as well as the associated distortion.. */ + /* as well as the associated distortion */ typedef struct AH_Configuration_ { FT_Pos* positions; - FT_Long distorsion; + FT_Long distortion; } AH_Configuration; - - - typedef struct AH_Optimizer_ + typedef struct AH_Optimizer_ { - FT_Memory memory; - AH_Outline* outline; + FT_Memory memory; + AH_Outline* outline; - FT_Int num_hstems; - AH_Stem* horz_stems; + FT_Int num_hstems; + AH_Stem* horz_stems; - FT_Int num_vstems; - AH_Stem* vert_stems; + FT_Int num_vstems; + AH_Stem* vert_stems; - FT_Int num_hsprings; - FT_Int num_vsprings; - AH_Spring* horz_springs; - AH_Spring* vert_springs; + FT_Int num_hsprings; + FT_Int num_vsprings; + AH_Spring* horz_springs; + AH_Spring* vert_springs; FT_Int num_configs; - AH_Configuration configs[ AH_MAX_CONFIGS ]; + AH_Configuration configs[AH_MAX_CONFIGS]; FT_Pos* positions; /* during each pass, use these instead */ - FT_Int num_stems; - AH_Stem* stems; + FT_Int num_stems; + AH_Stem* stems; - FT_Int num_springs; - AH_Spring* springs; - FT_Bool vertical; + FT_Int num_springs; + AH_Spring* springs; + FT_Bool vertical; - FT_Fixed tension_scale; - FT_Pos tension_threshold; + FT_Fixed tension_scale; + FT_Pos tension_threshold; } AH_Optimizer; /* loads the outline into the optimizer */ - extern int AH_Optimizer_Init( AH_Optimizer* optimizer, AH_Outline* outline, FT_Memory memory ); - /* compute optimal outline */ - extern void AH_Optimizer_Compute( AH_Optimizer* optimizer ); - - - /* releases the optimisation data */ - extern + /* release the optimization data */ void AH_Optimizer_Done( AH_Optimizer* optimizer ); -#endif /* AGOPTIM_H */ +#endif /* AHOPTIM_H */ + + +/* END */ diff --git a/src/autohint/ahtypes.h b/src/autohint/ahtypes.h index e73b55cb9..3372ea9af 100644 --- a/src/autohint/ahtypes.h +++ b/src/autohint/ahtypes.h @@ -2,181 +2,216 @@ /* */ /* ahtypes.h */ /* */ -/* General types and definitions for the auto-hint module */ +/* General types and definitions for the auto-hint module */ +/* (specification only). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ -#ifndef AGTYPES_H -#define AGTYPES_H -#include /* for freetype.h + LOCAL_DEF etc.. */ +#ifndef AHTYPES_H +#define AHTYPES_H + + +#include /* for freetype.h + LOCAL_DEF etc. */ + #ifdef FT_FLAT_COMPILE -#include "ahloader.h" /* glyph loader types & declarations */ + +#include "ahloader.h" + #else -#include /* glyph loader types & declarations */ + +#include + #endif -#define xxDEBUG_AG -#ifdef DEBUG_AG +#define xxAH_DEBUG + + +#ifdef AH_DEBUG + #include -#define AH_LOG(x) printf##x + +#define AH_LOG( x ) printf##x + #else -#define AH_LOG(x) /* nothing */ + +#define AH_LOG( x ) do ; while ( 0 ) /* nothing */ + #endif -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/**** ****/ -/**** COMPILE-TIME BUILD OPTIONS ****/ -/**** ****/ -/**** Toggle these configuration macros to experiment with ****/ -/**** "features" of the auto-hinter.. ****/ -/**** ****/ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** COMPILE-TIME BUILD OPTIONS ****/ + /**** ****/ + /**** Toggle these configuration macros to experiment with `features' ****/ + /**** of the auto-hinter. ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ -/* if this option is defined, only strong interpolation will be used to */ -/* place the points between edges. Otherwise, "smooth" points are detected */ -/* and later hinted through weak interpolation to correct some unpleasant */ -/* artefacts.. */ -/* */ -#undef AH_OPTION_NO_WEAK_INTERPOLATION -#undef AH_OPTION_NO_STRONG_INTERPOLATION -/* undefine this macro if you don't want to hint the metrics */ -/* there is no reason to do this, except for experimentation */ + /*************************************************************************/ + /* */ + /* If this option is defined, only strong interpolation will be used to */ + /* place the points between edges. Otherwise, `smooth' points are */ + /* detected and later hinted through weak interpolation to correct some */ + /* unpleasant artefacts. */ + /* */ +#undef AH_OPTION_NO_WEAK_INTERPOLATION + + + /*************************************************************************/ + /* */ + /* If this option is defined, only weak interpolation will be used to */ + /* place the points between edges. Otherwise, `strong' points are */ + /* detected and later hinted through strong interpolation to correct */ + /* some unpleasant artefacts. */ + /* */ +#undef AH_OPTION_NO_STRONG_INTERPOLATION + + + /*************************************************************************/ + /* */ + /* Undefine this macro if you don't want to hint the metrics. There is */ + /* no reason to do this (at least for non-CJK scripts), except for */ + /* experimentation. */ + /* */ #define AH_HINT_METRICS -/* define this macro if you do not want to insert extra edges at a glyph's */ -/* x and y extrema (when there isn't one already available). This help */ -/* reduce a number of artefacts and allow hinting of metrics.. */ -/* */ -#undef AH_OPTION_NO_EXTREMUM_EDGES -/* don't touch for now.. */ + /*************************************************************************/ + /* */ + /* Define this macro if you do not want to insert extra edges at a */ + /* glyph's x and y extremum (if there isn't one already available). */ + /* This helps to reduce a number of artefacts and allows hinting of */ + /* metrics. */ + /* */ +#undef AH_OPTION_NO_EXTREMUM_EDGES + + + /* don't touch for now */ #define AH_MAX_WIDTHS 12 #define AH_MAX_HEIGHTS 12 -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/**** ****/ -/**** TYPES DEFINITIONS ****/ -/**** ****/ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ - /* see agangles.h */ - typedef FT_Int AH_Angle; + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** TYPE DEFINITIONS ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ - /* hint flags */ - typedef enum AH_Flags_ - { - ah_flah_none = 0, - - /* bezier control points flags */ - ah_flah_conic = 1, - ah_flah_cubic = 2, - ah_flah_control = ah_flah_conic | ah_flah_cubic, - - /* extrema flags */ - ah_flah_extrema_x = 4, - ah_flah_extrema_y = 8, - - /* roundness */ - ah_flah_round_x = 16, - ah_flah_round_y = 32, - - /* touched */ - ah_flah_touch_x = 64, - ah_flah_touch_y = 128, - - /* weak interpolation */ - ah_flah_weak_interpolation = 256, - - /* never remove this one !! */ - ah_flah_max - - } AH_Flags; + /* see agangles.h */ + typedef FT_Int AH_Angle; - /* edge hint flags */ - typedef enum AH_Edge_Flags_ - { - ah_edge_normal = 0, - ah_edge_round = 1, - ah_edge_serif = 2, - ah_edge_done = 4 + /* hint flags */ +#define ah_flah_none 0 - } AH_Edge_Flags; + /* bezier control points flags */ +#define ah_flah_conic 1 +#define ah_flah_cubic 2 +#define ah_flah_control ( ah_flah_conic | ah_flah_cubic ) + + /* extrema flags */ +#define ah_flah_extrema_x 4 +#define ah_flah_extrema_y 8 + + /* roundness */ +#define ah_flah_round_x 16 +#define ah_flah_round_y 32 + + /* touched */ +#define ah_flah_touch_x 64 +#define ah_flah_touch_y 128 + + /* weak interpolation */ +#define ah_flah_weak_interpolation 256 + + typedef FT_Int AH_Flags; - /* hint directions - the values are computed so that two vectors are */ - /* in opposite directions iff "dir1+dir2 == 0" */ - typedef enum AH_Direction_ - { - ah_dir_none = 4, - ah_dir_right = 1, - ah_dir_left = -1, - ah_dir_up_and_down = 0, - ah_dir_left_and_right = 0, - ah_dir_up = 2, - ah_dir_down = -2 + /* edge hint flags */ +#define ah_edge_normal 0 +#define ah_edge_round 1 +#define ah_edge_serif 2 +#define ah_edge_done 4 - } AH_Direction; + typedef FT_Int AH_Edge_Flags; + + + /* hint directions -- the values are computed so that two vectors are */ + /* in opposite directions iff `dir1+dir2 == 0' */ +#define ah_dir_none 4 +#define ah_dir_right 1 +#define ah_dir_left -1 +#define ah_dir_up 2 +#define ah_dir_down -2 + + typedef FT_Int AH_Direction; typedef struct AH_Point AH_Point; typedef struct AH_Segment AH_Segment; typedef struct AH_Edge AH_Edge; - /*************************************************************************** - * - * - * AH_Point - * - * - * A structure used to model an outline point to the AH_Outline type - * - * - * flags :: current point hint flags - * ox, oy :: current original scaled coordinates - * fx, fy :: current coordinates in font units - * x, y :: current hinter coordinates - * u, v :: point coordinates - meaning varies with context - * - * in_dir :: direction of inwards vector (prev->point) - * out_dir :: direction of outwards vector (point->next) - * - * in_angle :: angle of inwards vector - * out_angle :: angle of outwards vector - * - * next :: next point in same contour - * prev :: previous point in same contour - * - */ + + /*************************************************************************/ + /* */ + /* */ + /* AH_Point */ + /* */ + /* */ + /* A structure used to model an outline point to the AH_Outline type. */ + /* */ + /* */ + /* flags :: The current point hint flags. */ + /* */ + /* ox, oy :: The current original scaled coordinates. */ + /* */ + /* fx, fy :: The current coordinates in font units. */ + /* */ + /* x, y :: The current hinter coordinates. */ + /* */ + /* u, v :: Point coordinates -- meaning varies with context. */ + /* */ + /* in_dir :: The direction of the inwards vector (prev->point). */ + /* */ + /* out_dir :: The direction of the outwards vector (point->next). */ + /* */ + /* in_angle :: The angle of the inwards vector. */ + /* */ + /* out_angle :: The angle of the outwards vector. */ + /* */ + /* next :: The next point in same contour. */ + /* */ + /* prev :: The previous point in same contour. */ + /* */ struct AH_Point { - AH_Flags flags; /* point flags used by hinter */ + AH_Flags flags; /* point flags used by hinter */ FT_Pos ox, oy; FT_Pos fx, fy; FT_Pos x, y; @@ -188,226 +223,239 @@ AH_Angle in_angle; AH_Angle out_angle; - AH_Point* next; /* next point in contour */ - AH_Point* prev; /* previous point in contour */ + AH_Point* next; /* next point in contour */ + AH_Point* prev; /* previous point in contour */ }; - /*************************************************************************** - * - * - * AH_Segment - * - * - * a structure used to describe an edge segment to the auto-hinter. A - * segment is simply a sequence of successive points located on the same - * horizontal or vertical "position", in a given direction. - * - * - * flags :: segment edge flags ( straight, rounded.. ) - * dir :: segment direction - * - * first :: first point in segment - * last :: last point in segment - * contour :: ptr to first point of segment's contour - * - * pos :: segment position in font units - * size :: segment size - * - * edge :: edge of current segment - * edge_next :: next segment on same edge - * - * link :: the pairing segment for this edge - * serif :: the primary segment for serifs - * num_linked :: the number of other segments that link to this one - * - * score :: used to score the segment when selecting them.. - * - */ + /*************************************************************************/ + /* */ + /* */ + /* AH_Segment */ + /* */ + /* */ + /* A structure used to describe an edge segment to the auto-hinter. */ + /* A segment is simply a sequence of successive points located on the */ + /* same horizontal or vertical `position', in a given direction. */ + /* */ + /* */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The segment direction. */ + /* */ + /* first :: The first point in the segment. */ + /* */ + /* last :: The last point in the segment. */ + /* */ + /* contour :: A pointer to the first point of the segment's */ + /* contour. */ + /* */ + /* pos :: The segment position in font units. */ + /* */ + /* size :: The segment size. */ + /* */ + /* edge :: The edge of the current segment. */ + /* */ + /* edge_next :: The next segment on the same edge. */ + /* */ + /* link :: The pairing segment for this edge. */ + /* */ + /* serif :: The primary segment for serifs. */ + /* */ + /* num_linked :: The number of other segments that link to this one. */ + /* */ + /* score :: Used to score the segment when selecting them. */ + /* */ struct AH_Segment { AH_Edge_Flags flags; AH_Direction dir; - AH_Point* first; /* first point in edge segment */ - AH_Point* last; /* last point in edge segment */ - AH_Point** contour; /* ptr to first point of segment's contour */ + AH_Point* first; /* first point in edge segment */ + AH_Point* last; /* last point in edge segment */ + AH_Point** contour; /* ptr to first point of segment's contour */ - FT_Pos pos; /* position of segment */ - FT_Pos min_coord; /* minimum coordinate of segment */ - FT_Pos max_coord; /* maximum coordinate of segment */ + FT_Pos pos; /* position of segment */ + FT_Pos min_coord; /* minimum coordinate of segment */ + FT_Pos max_coord; /* maximum coordinate of segment */ AH_Edge* edge; AH_Segment* edge_next; - AH_Segment* link; /* link segment */ - AH_Segment* serif; /* primary segment for serifs */ - FT_Pos num_linked; /* number of linked segments */ + AH_Segment* link; /* link segment */ + AH_Segment* serif; /* primary segment for serifs */ + FT_Pos num_linked; /* number of linked segments */ FT_Int score; }; - /*************************************************************************** - * - * - * AH_Edge - * - * - * a structure used to describe an edge, which really is a horizontal - * or vertical coordinate which will be hinted depending on the segments - * located on it.. - * - * - * flags :: segment edge flags ( straight, rounded.. ) - * dir :: main segment direction on this edge - * - * first :: first edge segment - * last :: last edge segment - * - * fpos :: original edge position in font units - * opos :: original scaled edge position - * pos :: hinted edge position - * - * link :: the linked edge - * serif :: the serif edge - * num_paired :: the number of other edges that pair to this one - * - * score :: used to score the edge when selecting them.. - * - * blue_edge :: indicate the blue zone edge this edge is related to - * only set for some of the horizontal edges in a Latin - * font.. - * - ***************************************************************************/ + /*************************************************************************/ + /* */ + /* */ + /* AH_Edge */ + /* */ + /* */ + /* A structure used to describe an edge, which really is a horizontal */ + /* or vertical coordinate to be hinted depending on the segments */ + /* located on it. */ + /* */ + /* */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The main segment direction on this edge. */ + /* */ + /* first :: The first edge segment. */ + /* */ + /* last :: The last edge segment. */ + /* */ + /* fpos :: The original edge position in font units. */ + /* */ + /* opos :: The original scaled edge position. */ + /* */ + /* pos :: The hinted edge position. */ + /* */ + /* link :: The linked edge. */ + /* */ + /* serif :: The serif edge. */ + /* */ + /* num_paired :: The number of other edges that pair to this one. */ + /* */ + /* score :: Used to score the edge when selecting them. */ + /* */ + /* blue_edge :: Indicate the blue zone edge this edge is related to. */ + /* Only set for some of the horizontal edges in a Latin */ + /* font. */ + /* */ struct AH_Edge { - AH_Edge_Flags flags; - AH_Direction dir; + AH_Edge_Flags flags; + AH_Direction dir; - AH_Segment* first; - AH_Segment* last; + AH_Segment* first; + AH_Segment* last; - FT_Pos fpos; - FT_Pos opos; - FT_Pos pos; + FT_Pos fpos; + FT_Pos opos; + FT_Pos pos; - AH_Edge* link; - AH_Edge* serif; - FT_Int num_linked; + AH_Edge* link; + AH_Edge* serif; + FT_Int num_linked; - FT_Int score; - FT_Pos* blue_edge; + FT_Int score; + FT_Pos* blue_edge; }; - /* an outline as seen by the hinter */ - typedef struct AH_Outline_ + /* an outline as seen by the hinter */ + typedef struct AH_Outline_ { - FT_Memory memory; + FT_Memory memory; - AH_Direction vert_major_dir; /* vertical major direction */ - AH_Direction horz_major_dir; /* horizontal major direction */ + AH_Direction vert_major_dir; /* vertical major direction */ + AH_Direction horz_major_dir; /* horizontal major direction */ - FT_Fixed x_scale; - FT_Fixed y_scale; - FT_Pos edge_distance_threshold; + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Pos edge_distance_threshold; - FT_Int max_points; - FT_Int num_points; - AH_Point* points; + FT_Int max_points; + FT_Int num_points; + AH_Point* points; - FT_Int max_contours; - FT_Int num_contours; - AH_Point** contours; + FT_Int max_contours; + FT_Int num_contours; + AH_Point** contours; - FT_Int num_hedges; - AH_Edge* horz_edges; + FT_Int num_hedges; + AH_Edge* horz_edges; - FT_Int num_vedges; - AH_Edge* vert_edges; + FT_Int num_vedges; + AH_Edge* vert_edges; - FT_Int num_hsegments; - AH_Segment* horz_segments; + FT_Int num_hsegments; + AH_Segment* horz_segments; - FT_Int num_vsegments; - AH_Segment* vert_segments; + FT_Int num_vsegments; + AH_Segment* vert_segments; } AH_Outline; +#define ah_blue_capital_top 0 /* THEZOCQS */ +#define ah_blue_capital_bottom ( ah_blue_capital_top + 1 ) /* HEZLOCUS */ +#define ah_blue_small_top ( ah_blue_capital_bottom + 1 ) /* xzroesc */ +#define ah_blue_small_bottom ( ah_blue_small_top + 1 ) /* xzroesc */ +#define ah_blue_small_minor ( ah_blue_small_bottom + 1 ) /* pqgjy */ +#define ah_blue_max ( ah_blue_small_minor + 1 ) - typedef enum AH_Blue_ - { - ah_blue_capital_top, /* THEZOCQS */ - ah_blue_capital_bottom, /* HEZLOCUS */ - ah_blue_small_top, /* xzroesc */ - ah_blue_small_bottom, /* xzroesc */ - ah_blue_small_minor, /* pqgjy */ - - ah_blue_max - - } AH_Blue; - - typedef enum - { - ah_hinter_monochrome = 1, - ah_hinter_optimize = 2 - - } AH_Hinter_Flags; + typedef FT_Int AH_Blue; - /************************************************************************ - * - * - * AH_Globals - * - * - * Holds the global metrics for a given font face (be it in design - * units, or scaled pixel values).. - * - * - * num_widths :: number of widths - * num_heights :: number of heights - * widths :: snap widths, including standard one - * heights :: snap height, including standard one - * blue_refs :: reference position of blue zones - * blue_shoots :: overshoot position of blue zones - * - ************************************************************************/ +#define ah_hinter_monochrome 1 +#define ah_hinter_optimize 2 + typedef FT_Int AH_Hinter_Flags; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Globals */ + /* */ + /* */ + /* Holds the global metrics for a given font face (be it in design */ + /* units or scaled pixel values). */ + /* */ + /* */ + /* num_widths :: The number of widths. */ + /* */ + /* num_heights :: The number of heights. */ + /* */ + /* widths :: Snap widths, including standard one. */ + /* */ + /* heights :: Snap height, including standard one. */ + /* */ + /* blue_refs :: The reference positions of blue zones. */ + /* */ + /* blue_shoots :: The overshoot positions of blue zones. */ + /* */ typedef struct AH_Globals_ { FT_Int num_widths; FT_Int num_heights; - FT_Pos widths [ AH_MAX_WIDTHS ]; - FT_Pos heights[ AH_MAX_HEIGHTS ]; + FT_Pos widths [AH_MAX_WIDTHS]; + FT_Pos heights[AH_MAX_HEIGHTS]; - FT_Pos blue_refs [ ah_blue_max ]; - FT_Pos blue_shoots[ ah_blue_max ]; + FT_Pos blue_refs [ah_blue_max]; + FT_Pos blue_shoots[ah_blue_max]; } AH_Globals; - /************************************************************************ - * - * - * AH_Face_Globals - * - * - * Holds the complete global metrics for a given font face (i.e. the - * design units version + a scaled version + the current scales used) - * - * - * face :: handle to source face object - * design :: globals in font design units - * scaled :: scaled globals in sub-pixel values - * x_scale :: current horizontal scale - * y_scale :: current vertical scale - * - ************************************************************************/ - - typedef struct AH_Face_Globals_ + /*************************************************************************/ + /* */ + /* */ + /* AH_Face_Globals */ + /* */ + /* */ + /* Holds the complete global metrics for a given font face (i.e., the */ + /* design units version + a scaled version + the current scales */ + /* used). */ + /* */ + /* */ + /* face :: A handle to the source face object */ + /* */ + /* design :: The globals in font design units. */ + /* */ + /* scaled :: Scaled globals in sub-pixel values. */ + /* */ + /* x_scale :: The current horizontal scale. */ + /* */ + /* y_scale :: The current vertical scale. */ + /* */ + typedef struct AH_Face_Globals_ { FT_Face face; AH_Globals design; @@ -419,12 +467,10 @@ } AH_Face_Globals; - - - typedef struct AH_Hinter + typedef struct AH_Hinter { FT_Memory memory; - FT_Long flags; + AH_Hinter_Flags flags; FT_Int algorithm; FT_Face face; @@ -439,4 +485,8 @@ } AH_Hinter; -#endif /* AGTYPES_H */ + +#endif /* AHTYPES_H */ + + +/* END */ diff --git a/src/autohint/autohint.c b/src/autohint/autohint.c index fb5ee1db3..5916b6330 100644 --- a/src/autohint/autohint.c +++ b/src/autohint/autohint.c @@ -2,22 +2,23 @@ /* */ /* autohint.c */ /* */ -/* Automatic Hinting wrapper. */ +/* Automatic Hinting wrapper (body only). */ /* */ -/* Copyright 2000: Catharon Productions Inc. */ +/* Copyright 2000 Catharon Productions Inc. */ /* Author: David Turner */ /* */ /* This file is part of the Catharon Typography Project and shall only */ /* be used, modified, and distributed under the terms of the Catharon */ /* Open Source License that should come with this file under the name */ -/* "CatharonLicense.txt". By continuing to use, modify, or distribute */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ -/* Note that this license is compatible with the FreeType license */ +/* Note that this license is compatible with the FreeType license. */ /* */ /***************************************************************************/ + #define FT_MAKE_OPTION_SINGLE_OBJECT #ifdef FT_FLAT_COMPILE @@ -38,3 +39,5 @@ #endif + +/* END */ diff --git a/src/autohint/mather.py b/src/autohint/mather.py index 9f0b34439..b416fdfcb 100644 --- a/src/autohint/mather.py +++ b/src/autohint/mather.py @@ -1,3 +1,21 @@ +#!/usr/bin/env python +# + +# +# autohint math table builder +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + import math ag_pi = 256 @@ -5,50 +23,56 @@ ag_pi = 256 def print_arctan( atan_bits ): atan_base = 1 << atan_bits - print "static AH_Angle ag_arctan[ 1L << AG_ATAN_BITS ] =" - print "{" + print " static AH_Angle ag_arctan[1L << AG_ATAN_BITS] =" + print " {" count = 0 - line = "" + line = " " - for n in range(atan_base): + for n in range( atan_base ): comma = "," - if (n == atan_base-1): + if ( n == atan_base - 1 ): comma = "" - angle = math.atan(n*1.0/atan_base)/math.pi*ag_pi - line = line + " " + repr(int(angle+0.5)) + comma - count = count+1; - if (count == 8): + angle = math.atan( n * 1.0 / atan_base ) / math.pi * ag_pi + line = line + " " + repr( int( angle + 0.5 ) ) + comma + count = count + 1; + if ( count == 8 ): count = 0 print line - line = "" + line = " " - if (count >0): + if ( count > 0 ): print line - print "};" + print " };" +# This routine is not used currently. +# def print_sines(): - print "static FT_Fixed ah_sines[ AG_HALF_PI+1 ] =" - print "{" + print " static FT_Fixed ah_sines[AG_HALF_PI + 1] =" + print " {" + count = 0 - line = "" + line = " " - for n in range(ag_pi/2): - sinus = math.sin(n*math.pi/ag_pi) - line = line + " " + repr(int(65536.0*sinus)) + "," - count = count+1 - if (count == 8): + for n in range( ag_pi / 2 ): + sinus = math.sin( n * math.pi / ag_pi ) + line = line + " " + repr( int( 65536.0 * sinus ) ) + "," + count = count + 1 + if ( count == 8 ): count = 0 print line - line = "" + line = " " - if (count > 0): + if ( count > 0 ): print line - print " 65536" - print "};" + print " 65536" + print " };" -print_arctan(8) + +print_arctan( 8 ) print + +# END diff --git a/src/autohint/rules.mk b/src/autohint/rules.mk index 94cb023b3..87f7849ad 100644 --- a/src/autohint/rules.mk +++ b/src/autohint/rules.mk @@ -3,28 +3,17 @@ # +# Copyright 2000 Catharon Productions Inc. +# Author: David Turner # -# Copyright 2000: Catharon Productions Inc. -# Author: David Turner +# This file is part of the Catharon Typography Project and shall only +# be used, modified, and distributed under the terms of the Catharon +# Open Source License that should come with this file under the name +# `CatharonLicense.txt'. By continuing to use, modify, or distribute +# this file you indicate that you have read the license and +# understand and accept it fully. # -# This file is part of the Catharon Typography Project and shall only -# be used, modified, and distributed under the terms of the Catharon -# Open Source License that should come with this file under the name -# "CatharonLicense.txt". By continuing to use, modify, or distribute -# this file you indicate that you have read the license and -# understand and accept it fully. -# -# Note that this license is compatible with the FreeType license -# -# -# Copyright 1996-2000 by -# David Turner, Robert Wilhelm, and Werner Lemberg. -# -# This file is part of the FreeType project, and may only be used, modified, -# and distributed under the terms of the FreeType project license, -# LICENSE.TXT. By continuing to use, modify, or distribute this file you -# indicate that you have read the license and understand and accept it -# fully. +# Note that this license is compatible with the FreeType license. # AUTO driver directory @@ -48,7 +37,9 @@ AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \ # AUTO driver headers # -AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) +AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \ + $(AUTO_DIR_)ahloader.h \ + $(AUTO_DIR_)ahtypes.h # AUTO driver object(s) diff --git a/src/type1/rules.mk b/src/type1/rules.mk index b5872ac6b..b544446ae 100644 --- a/src/type1/rules.mk +++ b/src/type1/rules.mk @@ -70,4 +70,5 @@ $(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H) DRV_OBJS_S += $(T1_DRV_OBJ_S) DRV_OBJS_M += $(T1_DRV_OBJ_M) + # EOF