📄 t1hinter.c
字号:
/******************************************************************* * * 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -