ref: d16a4b8111c42699e352cf2e758454c9a1189bab
parent: 95bec28220c8f08d3db92d6048abc4756726fe2c
author: David Turner <[email protected]>
date: Tue Feb 15 07:56:44 EST 2000
removed obsolete hinter source code
--- a/src/type1z/t1hinter.c
+++ /dev/null
@@ -1,1269 +1,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 <ftdebug.h>
-#include <t1objs.h>
-#include <t1hinter.h>
-
-#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
-
-
-/************************************************************************
- *
- * <Function>
- * t1_set_blue_zones
- *
- * <Description>
- * Set a size object's blue zones during reset. This will compute
- * the "snap" zone corresponding to each blue zone.
- *
- * <Input>
- * size :: handle to target size object
- *
- * <Return>
- * Error code. 0 means success
- *
- * <Note>
- * 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;
- }
-
-
-
-/************************************************************************
- *
- * <Function>
- * t1_set_snap_zones
- *
- * <Description>
- * This function set a size object's stem snap zones.
- *
- * <Input>
- * size :: handle to target size object
- *
- * <Return>
- * Error code. 0 means success
- *
- * <Note>
- * 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;
- }
-
-
-/************************************************************************
- *
- * <Function>
- * T1_New_Size_Hinter
- *
- * <Description>
- * Allocates a new hinter structure for a given size object
- *
- * <Input>
- * size :: handle to target size object
- *
- * <Return>
- * 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) );
- }
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Done_Size_Hinter
- *
- * <Description>
- * Releases a given size object's hinter structure
- *
- * <Input>
- * 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 );
- }
-
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Reset_Size_Hinter
- *
- * <Description>
- * Recomputes hinting information when a given size object has
- * changed its resolutions/char sizes/pixel sizes
- *
- * <Input>
- * size :: handle to size object
- *
- * <Return>
- * 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);
- }
-
-
-
-/************************************************************************
- *
- * <Function>
- * T1_New_Glyph_Hinter
- *
- * <Description>
- * Allocates a new hinter structure for a given glyph slot
- *
- * <Input>
- * glyph :: handle to target glyph slot
- *
- * <Return>
- * 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) );
- }
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Done_Glyph_Hinter
- *
- * <Description>
- * Releases a given glyph slot's hinter structure
- *
- * <Input>
- * 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.. *********/
- /********** *********/
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
-
-/************************************************************************
- *
- * <Function>
- * t1_sort_hints
- *
- * <Description>
- * Sort the list of active stems in increasing order, through
- * the "sort" indexing table
- *
- * <Input>
- * 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;
- }
-
-
-/************************************************************************
- *
- * <Function>
- * t1_hint_horizontal_stems
- *
- * <Description>
- * Compute the location of each scaled horizontal stem hint.
- * This takes care of the blue zones and the horizontal stem
- * snap table
- *
- * <Input>
- * 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
- *
- * <Note>
- * 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;
- }
- }
-
-
-
-
-/************************************************************************
- *
- * <Function>
- * t1_hint_vertical_stems
- *
- * <Description>
- * Compute the location of each scaled vertical stem hint.
- * This takes care of the vertical stem snap table
- *
- * <Input>
- * 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
- *
- * <Note>
- * 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;
- }
- }
-
-
-
-
-/************************************************************************
- *
- * <Function>
- * t1_hint_point
- *
- * <Description>
- * Grid-fit a coordinate with regards to a given stem hints table
- *
- * <Input>
- * 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
- *
- * <Return>
- * the hinted/scaled value in 26.6 pixels
- *
- * <Note>
- * 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
-
-/************************************************************************
- *
- * <Function>
- * T1_Hint_Points
- *
- * <Description>
- * this function grid-fits several points in a given Type 1 builder
- * at once.
- *
- * <Input>
- * 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;
- }
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Hint_Stems
- *
- * <Description>
- * 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.
- *
- * <Input>
- * 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
--- a/src/type1z/t1hinter.h
+++ /dev/null
@@ -1,380 +1,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 <t1objs.h>
-#include <t1gload.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Snap_Zone
- *
- * <Description>
- * 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)
- *
- * <Fields>
- * 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;
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Edge
- *
- * <Description>
- * A very simply structure used to model an stem edge
- *
- * <Fields>
- * 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;
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Stem_Hint
- *
- * <Description>
- * A simple structure used to model a stem hint
- *
- * <Fields>
- * min_edge :: the hint's minimum edge
- * max_edge :: the hint's maximum edge
- * hint_flags :: some flags describing the stem properties
- *
- * <Note>
- * 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 */
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Size_Hints
- *
- * <Description>
- * A structure used to model the hinting information related to
- * a size object
- *
- * <Fields>
- * 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 ];
- };
-
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Stem_Table
- *
- * <Description>
- * 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
- *
- * <Fields>
- * 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;
-
-
-
-/************************************************************************
- *
- * <Struct>
- * T1_Glyph_Hints
- *
- * <Description>
- * A structure used to model the stem hints of a given glyph outline
- * during glyph loading.
- *
- * <Fields>
- * 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;
- };
-
-
-
-/************************************************************************
- *
- * <Data>
- * t1_hinter_funcs
- *
- * <Description>
- * 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;
-
-
-/************************************************************************
- *
- * <Function>
- * T1_New_Size_Hinter
- *
- * <Description>
- * Allocates a new hinter structure for a given size object
- *
- * <Input>
- * size :: handle to target size object
- *
- * <Return>
- * Error code. 0 means success
- *
- ************************************************************************/
-
- LOCAL_DEF
- T1_Error T1_New_Size_Hinter( T1_Size size );
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Done_Size_Hinter
- *
- * <Description>
- * Releases a given size object's hinter structure
- *
- * <Input>
- * size :: handle to target size object
- *
- ************************************************************************/
-
- LOCAL_DEF
- void T1_Done_Size_Hinter( T1_Size size );
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Reset_Size_Hinter
- *
- * <Description>
- * Recomputes hinting information when a given size object has
- * changed its resolutions/char sizes/pixel sizes
- *
- * <Input>
- * size :: handle to size object
- *
- * <Return>
- * Error code. 0 means success
- *
- ************************************************************************/
-
- LOCAL_DEF
- T1_Error T1_Reset_Size_Hinter( T1_Size size );
-
-
-/************************************************************************
- *
- * <Function>
- * T1_New_Glyph_Hinter
- *
- * <Description>
- * Allocates a new hinter structure for a given glyph slot
- *
- * <Input>
- * glyph :: handle to target glyph slot
- *
- * <Return>
- * Error code. 0 means success
- *
- ************************************************************************/
-
- LOCAL_DEF
- T1_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph );
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Done_Glyph_Hinter
- *
- * <Description>
- * Releases a given glyph slot's hinter structure
- *
- * <Input>
- * glyph :: handle to glyph slot
- *
- ************************************************************************/
-
- LOCAL_DEF
- void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph );
-
-
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Hint_Points
- *
- * <Description>
- * this function grid-fits several points in a given Type 1 builder
- * at once.
- *
- * <Input>
- * builder :: handle to target Type 1 builder
- *
- ************************************************************************/
-
- LOCAL_DEF
- void T1_Hint_Points( T1_Builder* builder );
-
-
-/************************************************************************
- *
- * <Function>
- * T1_Hint_Stems
- *
- * <Description>
- * 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.
- *
- * <Input>
- * builder :: handle to target builder
- *
- ************************************************************************/
-
- LOCAL_DEF
- void T1_Hint_Stems( T1_Builder* builder );
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* T1HINTER_H */