From d16a4b8111c42699e352cf2e758454c9a1189bab Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 15 Feb 2000 12:56:44 +0000 Subject: [PATCH] removed obsolete hinter source code --- src/type1z/t1hinter.c | 1269 ----------------------------------------- src/type1z/t1hinter.h | 380 ------------ 2 files changed, 1649 deletions(-) delete mode 100644 src/type1z/t1hinter.c delete mode 100644 src/type1z/t1hinter.h diff --git a/src/type1z/t1hinter.c b/src/type1z/t1hinter.c deleted file mode 100644 index dc59441bd..000000000 --- a/src/type1z/t1hinter.c +++ /dev/null @@ -1,1269 +0,0 @@ -/******************************************************************* - * - * t1hinter.c 1.2 - * - * Type1 hinter. - * - * Copyright 1996-1999 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. - * - * - * The Hinter is in charge of fitting th scaled outline to the - * pixel grid in order to considerably improve the quality of - * the Type 1 font driver's output.. - * - ******************************************************************/ - -#include -#include -#include - -#undef FT_COMPONENT -#define FT_COMPONENT trace_t1hint /* for debugging/tracing */ - - -#undef ONE_PIXEL -#define ONE_PIXEL 64 - -#undef ROUND -#define ROUND(x) (( x + ONE_PIXEL/2 ) & -ONE_PIXEL) - -#undef SCALE -#define SCALE(val) FT_MulFix( val, scale ) - -/* various constants used to describe the alignment of a horizontal */ -/* stem with regards to the blue zones */ -#define T1_ALIGN_NONE 0 -#define T1_ALIGN_BOTTOM 1 -#define T1_ALIGN_TOP 2 -#define T1_ALIGN_BOTH 3 - - -/************************************************************************ - * - * - * t1_set_blue_zones - * - * - * Set a size object's blue zones during reset. This will compute - * the "snap" zone corresponding to each blue zone. - * - * - * size :: handle to target size object - * - * - * Error code. 0 means success - * - * - * This functions does the following : - * - * 1. It extracts the bottom and top blue zones from the - * face object. - * - * 2. Each zone is then grown by BlueFuzz, overlapping - * is eliminated by adjusting the zone edges appropriately - * - * 3. For each zone, we keep its original font units position, its - * original scaled position, as well as its grown/adjusted - * edges. - * - ************************************************************************/ - - /* ultra simple bubble sort (not a lot of elements, mostly */ - /* pre-sorted, no need for quicksort) */ - static - void t1_sort_blues( T1_Int* blues, - T1_Int count ) - { - T1_Int i, swap; - T1_Int* cur; - - for ( i = 2; i < count; i += 2 ) - { - cur = blues + i; - do - { - if ( cur[-1] < cur[0] ) - break; - - swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap; - swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap; - cur -= 2; - } - while ( cur > blues ); - } - } - - - static - T1_Error t1_set_blue_zones( T1_Size size ) - { - T1_Face face = (T1_Face)size->root.face; - T1_Font* priv = &face->type1; - T1_Int n; - T1_Int blues[24]; - T1_Int num_bottom; - T1_Int num_top; - T1_Int num_blues; - T1_Size_Hints* hints = size->hints; - T1_Snap_Zone* zone; - T1_Pos pix, orus; - T1_Pos min, max, threshold; - T1_Fixed scale; - T1_Bool is_bottom; - - /**********************************************************************/ - /* */ - /* COPY BOTTOM AND TOP BLUE ZONES IN LOCAL ARRAYS */ - /* */ - /* */ - - /* First of all, check the sizes of the /BlueValues and /OtherBlues */ - /* tables. They all must contain an even number of arguments */ - if ( priv->num_other_blues & 1 || - priv->num_blues & 1 ) - { - FT_ERROR(( "T1.Copy_Blues : odd number of blue values\n" )); - return T1_Err_Syntax_Error; - } - - /* copy the bottom blue zones from /OtherBlues */ - num_top = 0; - num_bottom = priv->num_other_blues; - - for ( n = 0; n < num_bottom; n ++ ) - blues[n] = priv->other_blues[n]; - - /* Add the first blue zone in /BlueValues to the table */ - num_top = priv->num_blues - 2; - if ( num_top >= 0 ) - { - blues[ num_bottom ] = priv->blue_values[0]; - blues[num_bottom+1] = priv->blue_values[1]; - - num_bottom += 2; - } - - /* sort the bottom blue zones */ - t1_sort_blues( blues, num_bottom ); - - hints->num_bottom_zones = num_bottom >> 1; - - /* now copy the /BlueValues to the top of the blues array */ - if ( num_top > 0 ) - { - for ( n = 0; n < num_top; n++ ) - blues[ num_bottom+n ] = priv->blue_values[n+2]; - - /* sort the top blue zones */ - t1_sort_blues( blues + num_bottom, num_top ); - } - else - num_top = 0; - - num_blues = num_top + num_bottom; - hints->num_blue_zones = ( num_blues ) >> 1; - - /**********************************************************************/ - /* */ - /* BUILD BLUE SNAP ZONES FROM THE LOCAL BLUES ARRAYS */ - /* */ - /* */ - - scale = size->root.metrics.y_scale; - zone = hints->blue_zones; - threshold = ONE_PIXEL/4; /* 0.25 pixels */ - - for ( n = 0; n < num_blues; n += 2, zone ++ ) - { - is_bottom = ( n < num_bottom ? 1 : 0 ); - - orus = blues[n+is_bottom]; /* get alignement coordinate */ - pix = SCALE( orus ); /* scale it */ - - min = SCALE( blues[ n ] - priv->blue_fuzz ); - max = SCALE( blues[n+1] + priv->blue_fuzz ); - - if ( min > pix - threshold ) min = pix - threshold; - if ( max < pix + threshold ) max = pix + threshold; - - zone->orus = orus; - zone->pix = pix; - zone->min = min; - zone->max = max; - } - - /* adjust edges in case of overlap */ - zone = hints->blue_zones; - for ( n = 0; n < num_blues-2; n += 2, zone ++ ) - { - if ( n != num_bottom-2 && - zone[0].max > zone[1].min ) - { - zone[0].max = zone[1].min = (zone[0].pix+zone[1].pix)/2; - } - } - - - /* Compare the current pixel size with the BlueScale value */ - /* to know wether to supress overshoots.. */ - - hints->supress_overshoots = - ( size->root.metrics.y_ppem < FT_MulFix(1000,priv->blue_scale) ); - - /* Now print the new blue values in tracing mode */ -#ifdef FT_DEBUG_LEVEL_TRACE - - FT_TRACE2(( "Blue Zones for size object at $%08lx :\n", (long)size )); - FT_TRACE2(( " orus pix min max\n" )); - FT_TRACE2(( "-------------------------------\n" )); - - zone = hints->blue_zones; - for ( n = 0; n < hints->num_blue_zones; n++ ) - { - FT_TRACE2(( " %3d %.2f %.2f %.2f\n", - zone->orus, - zone->pix/64.0, - zone->min/64.0, - zone->max/64.0 )); - zone++; - } - FT_TRACE2(( "\nOver shoots are %s\n\n", - hints->supress_overshoots ? "supressed" : "active" )); - -#endif /* DEBUG_LEVEL_TRACE */ - - return T1_Err_Ok; - } - - - -/************************************************************************ - * - * - * t1_set_snap_zones - * - * - * This function set a size object's stem snap zones. - * - * - * size :: handle to target size object - * - * - * Error code. 0 means success - * - * - * This function performs the following : - * - * 1. It reads and scales the stem snap widths from the parent face - * - * 2. A "snap zone" is computed for each snap width, by "growing" - * it with a threshold of a 1/2 pixel. Overlapping is avoided - * through proper edge adjustment. - * - * 3. Each width whose zone contain the scaled standard set width - * is removed from the table - * - * 4. Finally, the standard set width is scaled, and its correponding - * "snap zone" is inserted into the sorted snap zones table - * - ************************************************************************/ - - static - T1_Error t1_set_snap_zones( T1_Size size ) - { - T1_Int n, direction, n_zones, num_zones; - T1_Snap_Zone* zone; - T1_Snap_Zone* base_zone; - T1_Short* orgs; - T1_Pos standard_width; - T1_Fixed scale; - - T1_Face face = (T1_Face)size->root.face; - T1_Font* priv = &face->type1; - T1_Size_Hints* hints = size->hints; - - /* start with horizontal snap zones */ - direction = 0; - standard_width = priv->standard_width; - n_zones = priv->num_snap_widths; - base_zone = hints->snap_widths; - orgs = priv->stem_snap_widths; - scale = size->root.metrics.x_scale; - - while (direction < 2) - { - /*****************************************************************/ - /* */ - /* Read and scale stem snap widths table from the physical */ - /* font record. */ - /* */ - T1_Pos prev, orus, pix, min, max, threshold; - - threshold = ONE_PIXEL/4; - zone = base_zone; - - if ( n_zones > 0 ) - { - orus = *orgs++; - pix = SCALE( orus ); - min = pix-threshold; - max = pix+threshold; - - zone->orus = orus; - zone->pix = pix; - zone->min = min; - prev = pix; - - for ( n = 1; n < n_zones; n++ ) - { - orus = *orgs++; - pix = SCALE( orus ); - - if ( pix-prev < 2*threshold ) - { - min = max = (pix+prev)/2; - } - else - min = pix-threshold; - - zone->max = max; - zone++; - zone->orus = orus; - zone->pix = pix; - zone->min = min; - - max = pix+threshold; - prev = pix; - } - zone->max = max; - } - - /* print the scaled stem snap values in tracing modes */ -#ifdef FT_DEBUG_LEVEL_TRACE - - FT_TRACE2(( "Set_Snap_Zones : first %s pass\n", - direction ? "vertical" : "horizontal" )); - - FT_TRACE2(( "Scaled original stem snap zones :\n" )); - FT_TRACE2(( " orus pix min max\n" )); - FT_TRACE2(( "-----------------------------\n" )); - - zone = base_zone; - for ( n = 0; n < n_zones; n++, zone++ ) - FT_TRACE2(( " %3d %.2f %.2f %.2f\n", - zone->orus, - zone->pix/64.0, - zone->min/64.0, - zone->max/64.0 )); - FT_TRACE2(( "\n" )); - - FT_TRACE2(( "Standard width = %d\n", standard_width )); -#endif - - /*****************************************************************/ - /* */ - /* Now, each snap width which is in the range of the standard */ - /* set width will be removed from the list.. */ - /* */ - - if ( standard_width > 0 ) - { - T1_Snap_Zone* parent; - T1_Pos std_pix, std_min, std_max; - - std_pix = SCALE( standard_width ); - - std_min = std_pix-threshold; - std_max = std_pix+threshold; - - num_zones = 0; - zone = base_zone; - parent = base_zone; - - for ( n = 0; n < n_zones; n++ ) - { - if ( zone->pix >= std_min && zone->pix <= std_max ) - { - /* this zone must be removed from the list */ - if ( std_min > zone->min ) std_min = zone->min; - if ( std_max < zone->max ) std_max = zone->max; - } - else - { - *parent++ = *zone; - num_zones++; - } - zone++; - } - - /**********************************************/ - /* Now, insert the standard width zone */ - - zone = base_zone+num_zones; - while ( zone > base_zone && zone[-1].pix > std_max ) - { - zone[0] = zone[-1]; - zone --; - } - - /* check border zones */ - if ( zone > base_zone && zone[-1].max > std_min ) - zone[-1].max = std_min; - - if ( zone < base_zone+num_zones && zone[1].min < std_max ) - zone[1].min = std_max; - - zone->orus = standard_width; - zone->pix = std_pix; - zone->min = std_min; - zone->max = std_max; - - num_zones++; - } - else - num_zones = n_zones; - - /* save total number of stem snaps now */ - if (direction) hints->num_snap_heights = num_zones; - else hints->num_snap_widths = num_zones; - - /* print the scaled stem snap values in tracing modes */ -#ifdef FT_DEBUG_LEVEL_TRACE - - FT_TRACE2(( "Set_Snap_Zones : second %s pass\n", - direction ? "vertical" : "horizontal" )); - - FT_TRACE2(( "Scaled clipped stem snap zones :\n" )); - FT_TRACE2(( " orus pix min max\n" )); - FT_TRACE2(( "-----------------------------\n" )); - - zone = base_zone; - for ( n = 0; n < num_zones; n++, zone++ ) - FT_TRACE2(( " %3d %.2f %.2f %.2f\n", - zone->orus, - zone->pix/64.0, - zone->min/64.0, - zone->max/64.0 )); - FT_TRACE2(( "\n" )); - - FT_TRACE2(( "Standard width = %d\n", standard_width )); -#endif - - /* continue with vertical snap zone */ - direction++; - standard_width = priv->standard_height; - n_zones = priv->num_snap_heights; - base_zone = hints->snap_heights; - orgs = priv->stem_snap_heights; - scale = size->root.metrics.y_scale; - } - - return T1_Err_Ok; - } - - -/************************************************************************ - * - * - * T1_New_Size_Hinter - * - * - * Allocates a new hinter structure for a given size object - * - * - * size :: handle to target size object - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_FUNC - T1_Error T1_New_Size_Hinter( T1_Size size ) - { - FT_Memory memory = size->root.face->memory; - - return MEM_Alloc( size->hints, sizeof(*size->hints) ); - } - - -/************************************************************************ - * - * - * T1_Done_Size_Hinter - * - * - * Releases a given size object's hinter structure - * - * - * size :: handle to target size object - * - ************************************************************************/ - - LOCAL_FUNC - void T1_Done_Size_Hinter( T1_Size size ) - { - FT_Memory memory = size->root.face->memory; - - FREE( size->hints ); - } - - - -/************************************************************************ - * - * - * T1_Reset_Size_Hinter - * - * - * Recomputes hinting information when a given size object has - * changed its resolutions/char sizes/pixel sizes - * - * - * size :: handle to size object - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_FUNC - T1_Error T1_Reset_Size_Hinter( T1_Size size ) - { - return t1_set_blue_zones(size) || t1_set_snap_zones(size); - } - - - -/************************************************************************ - * - * - * T1_New_Glyph_Hinter - * - * - * Allocates a new hinter structure for a given glyph slot - * - * - * glyph :: handle to target glyph slot - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_FUNC - T1_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ) - { - FT_Memory memory = glyph->root.face->memory; - - return MEM_Alloc( glyph->hints, sizeof(*glyph->hints) ); - } - - -/************************************************************************ - * - * - * T1_Done_Glyph_Hinter - * - * - * Releases a given glyph slot's hinter structure - * - * - * glyph :: handle to glyph slot - * - ************************************************************************/ - - LOCAL_FUNC - void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ) - { - FT_Memory memory = glyph->root.face->memory; - - FREE( glyph->hints ); - } - - - - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - /********** *********/ - /********** *********/ - /********** HINTED GLYPH LOADER *********/ - /********** *********/ - /********** The following code is in charge of the first *********/ - /********** and second pass when loading a single outline *********/ - /********** *********/ - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - - static - T1_Error t1_hinter_ignore( void ) - { - /* do nothing, used for "dotsection" which is unsupported for now */ - return 0; - } - - static - T1_Error t1_hinter_stem( T1_Builder* builder, - T1_Pos pos, - T1_Int width, - T1_Bool vertical ) - { - T1_Stem_Table* stem_table; - T1_Stem_Hint* stems; - T1_Stem_Hint* cur_stem; - T1_Int min, max, n, num_stems; - T1_Bool new_stem; - T1_Glyph_Hints* hinter = builder->glyph->hints; - - /* select the appropriate stem array */ - stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems; - stems = stem_table->stems; - num_stems = stem_table->num_stems; - - /* Compute minimum and maximum orus for the stem */ - min = pos + ( vertical - ? builder->left_bearing.x - : builder->left_bearing.y ); - - if ( width >= 0 ) - max = min + width; - else - { - /* a negative width indicates a ghost stem */ - if ( width == -21 ) - min += width; - - max = min; - } - - /* now scan the array. If we find a stem with the same borders */ - /* simply activate it.. */ - cur_stem = stems; - new_stem = 1; - - for ( n = 0; n < num_stems; n++, cur_stem++ ) - { - if ( cur_stem->min_edge.orus == min && - cur_stem->max_edge.orus == max ) - { - /* This stem is already in the table, simply activate it */ - if ( (cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE) == 0) - { - cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE; - stem_table->num_active ++; - } - new_stem = 0; - break; - } - } - - /* add a new stem to the array when necessary */ - if (new_stem) - { - if (cur_stem >= stems + T1_HINTER_MAX_EDGES) - { - FT_ERROR(( "T1.Hinter : too many stems in glyph charstring\n" )); - return T1_Err_Syntax_Error; - } - - /* on the first pass, we record the stem, otherwise, this is */ - /* a bug in the glyph loader !! */ - if ( builder->pass == 0 ) - { - cur_stem->min_edge.orus = min; - cur_stem->max_edge.orus = max; - cur_stem->hint_flags = T1_HINT_FLAG_ACTIVE; - - stem_table->num_stems++; - stem_table->num_active++; - } - else - { - FT_ERROR(( "T1.Hinter : fatal glyph loader bug - pass2-stem\n" )); - return T1_Err_Syntax_Error; - } - } - - return T1_Err_Ok; - } - - - static - T1_Error t1_hinter_stem3( T1_Builder* builder, - T1_Pos pos0, - T1_Int width0, - T1_Pos pos1, - T1_Int width1, - T1_Pos pos2, - T1_Int width2, - T1_Bool vertical ) - { - /* For now, don't be elitist and simply call "stem" 3 times */ - return t1_hinter_stem( builder, pos0, width0, vertical ) || - t1_hinter_stem( builder, pos1, width1, vertical ) || - t1_hinter_stem( builder, pos2, width2, vertical ); - } - - - static - T1_Error t1_hinter_changehints( T1_Builder* builder ) - { - T1_Int dimension; - T1_Stem_Table* stem_table; - T1_Glyph_Hints* hinter = builder->glyph->hints; - - /* if we're in the second pass of glyph hinting, we must */ - /* call the function T1_Hint_Points on the builder in order */ - /* to force the fit the latest points to the pixel grid */ - if ( builder->pass == 1 ) - T1_Hint_Points( builder ); - - /* Simply de-activate all hints in all arrays */ - stem_table = &hinter->hori_stems; - - for ( dimension = 2; dimension > 0; dimension-- ) - { - T1_Stem_Hint* cur = stem_table->stems; - T1_Stem_Hint* limit = cur + stem_table->num_stems; - - for ( ; cur < limit; cur++ ) - cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE; - - stem_table->num_active = 0; - stem_table = &hinter->vert_stems; - } - - return T1_Err_Ok; - } - - - LOCAL_FUNC - const T1_Hinter_Funcs t1_hinter_funcs = - { - (T1_Hinter_ChangeHints) t1_hinter_changehints, - (T1_Hinter_DotSection) t1_hinter_ignore, - (T1_Hinter_Stem) t1_hinter_stem, - (T1_Hinter_Stem3) t1_hinter_stem3 - }; - - - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - /********** *********/ - /********** *********/ - /********** STEM HINTS MANAGEMENT *********/ - /********** *********/ - /********** The following code is in charge of computing *********/ - /********** the placement of each scaled stem hint.. *********/ - /********** *********/ - /**********************************************************************/ - /**********************************************************************/ - /**********************************************************************/ - -/************************************************************************ - * - * - * t1_sort_hints - * - * - * Sort the list of active stems in increasing order, through - * the "sort" indexing table - * - * - * table :: a stem hints table - * - ************************************************************************/ - - static - void t1_sort_hints( T1_Stem_Table* table ) - { - T1_Int num_stems = table->num_stems; - T1_Int num_active = 0; - T1_Int* sort = table->sort; - T1_Stem_Hint* stems = table->stems; - T1_Int n; - - /* record active stems in sort table */ - for ( n = 0; n < num_stems; n++ ) - { - if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE ) - sort[num_active++] = n; - } - - /* now sort the indices. There are usually very few stems, */ - /* and they are pre-sorted in 90% cases, so we choose a */ - /* simple bubble sort (quicksort would be slower).. */ - for ( n = 1; n < num_active; n++ ) - { - T1_Int p = n-1; - T1_Stem_Hint* cur = stems + sort[n]; - - do - { - T1_Int swap; - T1_Stem_Hint* prev = stems + sort[p]; - - /* note that by definition, the active stems cannot overlap */ - /* so we simply compare their "min" to sort them.. */ - /* (we could compare their max, this wouldn't change anything) */ - if ( prev->min_edge.orus <= cur->min_edge.orus ) - break; - - /* swap elements */ - swap = sort[ p ]; - sort[ p ] = sort[p+1]; - sort[p+1] = swap; - p--; - } - while ( p >= 0 ); - } - - table->num_active = num_active; - } - - -/************************************************************************ - * - * - * t1_hint_horizontal_stems - * - * - * Compute the location of each scaled horizontal stem hint. - * This takes care of the blue zones and the horizontal stem - * snap table - * - * - * table :: the horizontal stem hints table - * hints :: the current size's hint structure - * blueShift :: the value of the /BlueShift as taken from the - * face object. - * scale :: the 16.16 scale used to convert outline - * units to 26.6 pixels - * - * - * For now, all stems are hinted independently from each other. - * It might be necessary, for better performance, to introduce - * the notion of "controlled" hints describing things like - * counter-stems, stem3 as well as overlapping stems control. - * - ************************************************************************/ - - static - void t1_hint_horizontal_stems( T1_Stem_Table* table, - T1_Size_Hints* hints, - T1_Pos blueShift, - T1_Fixed scale ) - { - T1_Stem_Hint* stem = table->stems; - T1_Stem_Hint* limit = stem + table->num_stems; - - /* first of all, scale the blueShift */ - blueShift = SCALE(blueShift); - - /* then scan the horizontal stem table */ - for ( ; stem < limit; stem++ ) - { - T1_Pos bottom_orus = stem->min_edge.orus; - T1_Pos top_orus = stem->max_edge.orus; - - T1_Pos top_pix = SCALE( top_orus ); - T1_Pos bottom_pix = SCALE( bottom_orus ); - T1_Pos width_pix = top_pix - bottom_pix; - - T1_Pos bottom = bottom_pix; - T1_Pos top = top_pix; - T1_Int align = T1_ALIGN_NONE; - - /******************************************************************/ - /* Snap pixel width if in stem snap range */ - { - T1_Snap_Zone* zone = hints->snap_heights; - T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; - - for ( ; zone < zone_limit; zone++ ) - { - if ( width_pix < zone->min ) - break; - - if ( width_pix <= zone->max ) - { - width_pix = zone->pix; - break; - } - } - } - - /******************************************************************/ - /* round width - minimum 1 pixel if this isn't a ghost stem */ - if ( width_pix > 0 ) - width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND(width_pix) ); - - - /******************************************************************/ - /* Now check for bottom blue zones alignement */ - { - T1_Int num_blues = hints->num_bottom_zones; - T1_Snap_Zone* blue = hints->blue_zones; - T1_Snap_Zone* blue_limit = blue + num_blues; - - for ( ; blue < blue_limit; blue++ ) - { - if ( bottom_pix < blue->min ) - break; - - if ( bottom_pix <= blue->max ) - { - align = T1_ALIGN_BOTTOM; - bottom = ROUND( blue->pix ); - - /* implements blue shift */ - if (!hints->supress_overshoots) - { - T1_Pos delta = blue->pix - bottom_pix; - - delta = ( delta < blueShift ? 0 : ROUND( delta ) ); - bottom -= delta; - } - } - } - } - - - /******************************************************************/ - /* Check for top blue zones alignement */ - { - T1_Int num_blues = hints->num_blue_zones - - hints->num_bottom_zones; - - T1_Snap_Zone* blue = hints->blue_zones + - hints->num_bottom_zones; - - T1_Snap_Zone* blue_limit = blue + num_blues; - - for ( ; blue < blue_limit; blue++ ) - { - if ( top_pix < blue->min ) - break; - - if ( top_pix <= blue->max ) - { - align |= T1_ALIGN_TOP; - top = ROUND( blue->pix ); - - /* implements blue shift */ - if (!hints->supress_overshoots) - { - T1_Pos delta = top - blue->pix; - - delta = ( delta < blueShift ? 0 : ROUND( delta ) ); - top += delta; - } - } - } - } - - - /******************************************************************/ - /* compute the hinted stem position, according to its alignment */ - switch (align) - { - case T1_ALIGN_BOTTOM: /* bottom zone alignement */ - bottom_pix = bottom; - top_pix = bottom + width_pix; - break; - - case T1_ALIGN_TOP: /* top zone alignement */ - top_pix = top; - bottom_pix = top - width_pix; - - break; - - case T1_ALIGN_BOTH: /* bottom+top zone alignement */ - bottom_pix = bottom; - top_pix = top; - break; - - default: /* no alignement */ - - /* XXXX : TODO : Add management of controlled stems */ - bottom = ( SCALE(bottom_orus+top_orus) - width_pix )/2; - - bottom_pix = ROUND(bottom); - top_pix = bottom_pix + width_pix; - } - - stem->min_edge.pix = bottom_pix; - stem->max_edge.pix = top_pix; - } - } - - - - -/************************************************************************ - * - * - * t1_hint_vertical_stems - * - * - * Compute the location of each scaled vertical stem hint. - * This takes care of the vertical stem snap table - * - * - * table :: the vertical stem hints table - * hints :: the current size's hint structure - * scale :: the 16.16 scale used to convert outline - * units to 26.6 pixels - * - * - * For now, all stems are hinted independently from each other. - * It might be necessary, for better performance, to introduce - * the notion of "controlled" hints describing things like - * counter-stems, stem3 as well as overlapping stems control. - * - ************************************************************************/ - - /* compute the location of each scaled vertical stem hint. */ - /* Take care of blue zones and stem snap table */ - static - void t1_hint_vertical_stems( T1_Stem_Table* table, - T1_Size_Hints* hints, - T1_Fixed scale ) - { - T1_Stem_Hint* stem = table->stems; - T1_Stem_Hint* limit = stem + table->num_stems; - - for ( ; stem < limit; stem++ ) - { - T1_Pos stem_left = stem->min_edge.orus; - T1_Pos stem_right = stem->max_edge.orus; - T1_Pos width_pix, left; - - width_pix = SCALE( stem_right - stem_left ); - - /* Snap pixel width if in stem snap range */ - { - T1_Snap_Zone* zone = hints->snap_widths; - T1_Snap_Zone* zone_limit = zone + hints->num_snap_widths; - - for ( ; zone < zone_limit; zone++ ) - { - if ( width_pix < zone->min ) - break; - - if ( width_pix <= zone->max ) - { - width_pix = zone->pix; - break; - } - } - } - - /* round width - minimum 1 pixel if this isn't a ghost stem */ - if ( width_pix > 0 ) - width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : - ROUND( width_pix ) ); - - /* now place the snapped and rounded stem */ - - /* XXXX : TODO : implement controlled stems for the overlapping */ - /* cases.. */ - - left = ( SCALE(stem_left+stem_right) - width_pix )/2; - - stem->min_edge.pix = ROUND(left); - stem->max_edge.pix = stem->min_edge.pix + width_pix; - } - } - - - - -/************************************************************************ - * - * - * t1_hint_point - * - * - * Grid-fit a coordinate with regards to a given stem hints table - * - * - * table :: the source stem hints table - * coord :: original coordinate, expressed in font units - * scale :: the 16.16 scale used to convert font units into - * 26.6 pixels - * - * - * the hinted/scaled value in 26.6 pixels - * - * - * For now, all stems are hinted independently from each other. - * It might be necessary, for better performance, to introduce - * the notion of "controlled" hints describing things like - * counter-stems, stem3 as well as overlapping stems control. - * - ************************************************************************/ - - static - T1_Pos t1_hint_point( T1_Stem_Table* table, - T1_Pos coord, - T1_Fixed scale ) - { - T1_Int num_active = table->num_active; - T1_Int n; - T1_Stem_Hint* prev = 0; - T1_Stem_Hint* cur = 0; - T1_Edge* min; - T1_Edge* max; - T1_Pos delta; - - /* only hint when there is at least one stem defined */ - if (num_active <= 0) - return SCALE(coord); - - /* scan the stem table to determine placement of coordinate */ - /* relative to the list of sorted and stems */ - for ( n = 0; n < num_active; n++, prev = cur ) - { - cur = table->stems + table->sort[n]; - - /* is it on the left of the current edge ? */ - delta = cur->min_edge.orus - coord; - if ( delta == 0 ) return cur->min_edge.pix; - - if (delta > 0) - { - /* if this is the left of the first edge, simply shift */ - if (!prev) return cur->min_edge.pix - SCALE(delta); - - /* otherwise, interpolate between the maximum of the */ - /* previous stem, and the minimum of the current one */ - min = &prev->max_edge; - max = &cur->min_edge; - goto Interpolate; - } - - /* is it within the current edge ? */ - delta = cur->max_edge.orus - coord; - if ( delta == 0 ) return cur->max_edge.pix; - - if (delta > 0) - { - /* interpolate within the stem */ - min = &cur->min_edge; - max = &cur->max_edge; - goto Interpolate; - } - } - - /* apparently, this coordinate is on the right of the last stem */ - delta = coord - cur->max_edge.orus; - return cur->max_edge.pix + SCALE(delta); - - Interpolate: - return min->pix + - FT_MulDiv( coord - min->orus, - max->pix - min->pix, - max->orus - min->orus ); - } - - - - - - -#if 1 - -/************************************************************************ - * - * - * T1_Hint_Points - * - * - * this function grid-fits several points in a given Type 1 builder - * at once. - * - * - * builder :: handle to target Type 1 builder - * first :: first point to hint in builder's current outline - * last :: last point to hint in builder's current outline - * - ************************************************************************/ - - LOCAL_FUNC - void T1_Hint_Points( T1_Builder* builder ) - { - T1_Int first = builder->hint_point; - T1_Int last = builder->current.n_points-1; - - T1_Size size = builder->size; - T1_Fixed scale_x = size->root.metrics.x_scale; - T1_Fixed scale_y = size->root.metrics.y_scale; - - T1_Glyph_Hints* hints = builder->glyph->hints; - T1_Stem_Table* hori_stems = &hints->hori_stems; - T1_Stem_Table* vert_stems = &hints->vert_stems; - - T1_Vector* cur = builder->current.points + first; - T1_Vector* limit = cur + last - first + 1; - - /* first of all, sort the active stem hints */ - t1_sort_hints( hori_stems ); - t1_sort_hints( vert_stems ); - - for ( ; cur < limit; cur++ ) - { - cur->x = t1_hint_point( vert_stems, cur->x, scale_x ); - cur->y = t1_hint_point( hori_stems, cur->y, scale_y ); - } - - builder->hint_point = builder->current.n_points; - } - - -/************************************************************************ - * - * - * T1_Hint_Stems - * - * - * This function is used to compute the location of each stem hint - * between the first and second passes of the glyph loader on the - * charstring. - * - * - * builder :: handle to target builder - * - ************************************************************************/ - - LOCAL_FUNC - void T1_Hint_Stems( T1_Builder* builder ) - { - T1_Glyph_Hints* hints = builder->glyph->hints; - T1_Font* priv = &builder->face->type1; - - T1_Size size = builder->size; - T1_Fixed scale_x = size->root.metrics.x_scale; - T1_Fixed scale_y = size->root.metrics.y_scale; - - t1_hint_horizontal_stems( &hints->hori_stems, - builder->size->hints, - priv->blue_shift, - scale_y ); - - t1_hint_vertical_stems( &hints->vert_stems, - builder->size->hints, - scale_x ); - } - -#endif diff --git a/src/type1z/t1hinter.h b/src/type1z/t1hinter.h deleted file mode 100644 index 4bf753af9..000000000 --- a/src/type1z/t1hinter.h +++ /dev/null @@ -1,380 +0,0 @@ -/******************************************************************* - * - * t1hinter.h 1.2 - * - * Type1 hinter. - * - * Copyright 1996-1999 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. - * - * - * The Hinter is in charge of fitting th scaled outline to the - * pixel grid in order to considerably improve the quality of - * the Type 1 font driver's output.. - * - ******************************************************************/ - -#ifndef T1HINTER_H -#define T1HINTER_H - -#include -#include - -#ifdef __cplusplus - extern "C" { -#endif - - -/************************************************************************ - * - * - * T1_Snap_Zone - * - * - * A "snap zone" is used to model either a blue zone or a stem width - * at a given character size. It is made of a minimum and maximum - * edge, defined in 26.6 pixels, as well as one "original" and - * "scaled" position. - * - * the position corresponds to the stem width (for stem snap zones) - * or to the blue position (for blue zones) - * - * - * orus :: original position in font units - * pix :: current position in sub-pixel units - * min :: minimum boundary in sub-pixel units - * max :: maximim boundary in sub-pixel units - * - ************************************************************************/ - - typedef struct T1_Snap_Zone_ - { - T1_Pos orus; - T1_Pos pix; - T1_Pos min; - T1_Pos max; - - } T1_Snap_Zone; - - -/************************************************************************ - * - * - * T1_Edge - * - * - * A very simply structure used to model an stem edge - * - * - * orus :: original edge position in font units - * pix :: scaled edge position in sub-pixel units - * - ************************************************************************/ - - typedef struct T1_Edge_ - { - T1_Pos orus; - T1_Pos pix; - - } T1_Edge; - - -/************************************************************************ - * - * - * T1_Stem_Hint - * - * - * A simple structure used to model a stem hint - * - * - * min_edge :: the hint's minimum edge - * max_edge :: the hint's maximum edge - * hint_flags :: some flags describing the stem properties - * - * - * the min and max edges of a ghost stem have the same position, - * even if they're coded in a weird way in the charstrings - * - ************************************************************************/ - - typedef struct T1_Stem_Hint_ - { - T1_Edge min_edge; - T1_Edge max_edge; - T1_Int hint_flags; - - } T1_Stem_Hint; - - -#define T1_HINT_FLAG_ACTIVE 1 /* indicates an active stem */ -#define T1_HINT_FLAG_MIN_BORDER 2 /* unused for now.. */ -#define T1_HINT_FLAG_MAX_BORDER 4 /* unused for now.. */ - - -/* hinter's configuration constants */ -#define T1_HINTER_MAX_BLUES 24 /* maximum number of blue zones */ -#define T1_HINTER_MAX_SNAPS 16 /* maximum number of stem snap zones */ -#define T1_HINTER_MAX_EDGES 64 /* maximum number of stem hints */ - - -/************************************************************************ - * - * - * T1_Size_Hints - * - * - * A structure used to model the hinting information related to - * a size object - * - * - * supress_overshoots :: a boolean flag to tell when overshoot - * supression should occur. - * - * num_blue_zones :: the total number of blue zones (top+bottom) - * num_bottom_zones :: the number of bottom zones - * - * blue_zones :: the blue zones table. bottom zones are - * stored first in the table, followed by - * all top zones - * - * num_stem_snapH :: number of horizontal stem snap zones - * stem_snapH :: horizontal stem snap zones - * - * num_stem_snapV :: number of vertical stem snap zones - * stem_snapV :: vertical stem snap zones - * - ************************************************************************/ - - struct T1_Size_Hints_ - { - T1_Bool supress_overshoots; - - T1_Int num_blue_zones; - T1_Int num_bottom_zones; - T1_Snap_Zone blue_zones[ T1_HINTER_MAX_BLUES ]; - - T1_Int num_snap_widths; - T1_Snap_Zone snap_widths[ T1_HINTER_MAX_SNAPS ]; - - T1_Int num_snap_heights; - T1_Snap_Zone snap_heights[ T1_HINTER_MAX_SNAPS ]; - }; - - - -/************************************************************************ - * - * - * T1_Stem_Table - * - * - * A simple structure used to model a set of stem hints in a - * single direction during the loading of a given glyph outline. - * Not all stem hints are active at a time. Moreover, stems must - * be sorted regularly - * - * - * num_stems :: total number of stems in table - * num_active :: number of active stems in table - * - * stems :: the table of all stems - * sort :: a table of indices into the stems table, used - * to keep a sorted list of the active stems - * - ************************************************************************/ - - typedef struct T1_Stem_Table_ - { - T1_Int num_stems; - T1_Int num_active; - - T1_Stem_Hint stems[ T1_HINTER_MAX_EDGES ]; - T1_Int sort [ T1_HINTER_MAX_EDGES ]; - - } T1_Stem_Table; - - - -/************************************************************************ - * - * - * T1_Glyph_Hints - * - * - * A structure used to model the stem hints of a given glyph outline - * during glyph loading. - * - * - * hori_stems :: horizontal stem hints table - * vert_stems :: vertical stem hints table - * - ************************************************************************/ - - struct T1_Glyph_Hints_ - { - T1_Stem_Table hori_stems; - T1_Stem_Table vert_stems; - }; - - - -/************************************************************************ - * - * - * t1_hinter_funcs - * - * - * A table containing the address of various functions used during - * the loading of an hinted scaled outline - * - ************************************************************************/ - - LOCAL_DEF - const T1_Hinter_Funcs t1_hinter_funcs; - - -/************************************************************************ - * - * - * T1_New_Size_Hinter - * - * - * Allocates a new hinter structure for a given size object - * - * - * size :: handle to target size object - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_DEF - T1_Error T1_New_Size_Hinter( T1_Size size ); - - -/************************************************************************ - * - * - * T1_Done_Size_Hinter - * - * - * Releases a given size object's hinter structure - * - * - * size :: handle to target size object - * - ************************************************************************/ - - LOCAL_DEF - void T1_Done_Size_Hinter( T1_Size size ); - - -/************************************************************************ - * - * - * T1_Reset_Size_Hinter - * - * - * Recomputes hinting information when a given size object has - * changed its resolutions/char sizes/pixel sizes - * - * - * size :: handle to size object - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_DEF - T1_Error T1_Reset_Size_Hinter( T1_Size size ); - - -/************************************************************************ - * - * - * T1_New_Glyph_Hinter - * - * - * Allocates a new hinter structure for a given glyph slot - * - * - * glyph :: handle to target glyph slot - * - * - * Error code. 0 means success - * - ************************************************************************/ - - LOCAL_DEF - T1_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ); - - -/************************************************************************ - * - * - * T1_Done_Glyph_Hinter - * - * - * Releases a given glyph slot's hinter structure - * - * - * glyph :: handle to glyph slot - * - ************************************************************************/ - - LOCAL_DEF - void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ); - - - - -/************************************************************************ - * - * - * T1_Hint_Points - * - * - * this function grid-fits several points in a given Type 1 builder - * at once. - * - * - * builder :: handle to target Type 1 builder - * - ************************************************************************/ - - LOCAL_DEF - void T1_Hint_Points( T1_Builder* builder ); - - -/************************************************************************ - * - * - * T1_Hint_Stems - * - * - * This function is used to compute the location of each stem hint - * between the first and second passes of the glyph loader on the - * charstring. - * - * - * builder :: handle to target builder - * - ************************************************************************/ - - LOCAL_DEF - void T1_Hint_Stems( T1_Builder* builder ); - -#ifdef __cplusplus - } -#endif - -#endif /* T1HINTER_H */