summaryrefslogtreecommitdiff
path: root/src/pshinter/pshglob.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pshinter/pshglob.c')
-rw-r--r--src/pshinter/pshglob.c541
1 files changed, 367 insertions, 174 deletions
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index c8b1ec429..480116db4 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -1,27 +1,24 @@
+#include <ft2build.h>
#include "pshglob.h"
/* "simple" ps hinter globals management, inspired from the new auto-hinter */
- FT_LOCAL void
- psh_globals_init( PSH_Globals globals,
- FT_Memory memory )
- {
- memset( globals, 0, sizeof(*globals) );
- globals->memory = memory;
- globals->x_scale = 0x10000L;
- globals->y_scale = 0x10000L;
- }
-
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STANDARD WIDTHS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
/* reset the widths/heights table */
- static FT_Error
+ static void
psh_globals_reset_widths( PSH_Globals globals,
FT_UInt direction,
PS_Globals_Widths widths )
{
- PSH_Dimension dim = &globals->dim[direction];
- FT_Memory memory = globals->memory;
- FT_Error error = 0;
+ PSH_Dimension dim = &globals->dimension[direction];
/* simple copy of the original widths values - no sorting */
{
@@ -37,8 +34,6 @@
read++;
}
}
-
- return error;
}
@@ -47,10 +42,11 @@
psh_globals_scale_widths( PSH_Globals globals,
FT_UInt direction )
{
- PSH_Widths std = &globals->std[direction];
- FT_UInt count = std->count;
- PSH_Width width = std->widths;
- FT_Fixed scale = globals->scale[direction];
+ PSH_Dimension dim = &globals->dimension[direction];
+ PSH_Widths std = &dim->std;
+ FT_UInt count = std->count;
+ PSH_Width width = std->widths;
+ FT_Fixed scale = dim->scale_mult;
for ( ; count > 0; count--, width++ )
{
@@ -59,219 +55,416 @@
}
}
+
- /* reset the blues table */
- static FT_Error
- psh_globals_reset_blues( PSH_Globals globals,
- PS_Globals_Blues blues )
+ FT_LOCAL_DEF FT_Pos
+ psh_dimension_snap_width( PSH_Dimension dimension,
+ FT_Int org_width )
{
- FT_Error error = 0;
- FT_Memory memory = globals->memory;
+ FT_UInt n;
+ FT_Pos width = FT_MulFix( org_width, dimension->scale_mult );
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
- if ( !FT_REALLOC_ARRAY( globals->blues.zones, globals->blues.count,
- blues->count, PSH_Blue_ZoneRec ) )
+ for ( n = 0; n < dimension->std.count; n++ )
{
- FT_UInt count = 0;
-
- globals->blyes.count = blues->count;
-
- /* first of all, build a sorted table of blue zones */
+ FT_Pos w;
+ FT_Pos dist;
+
+ w = dimension->std.widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
{
- FT_Int16* read = blue->zones;
- FT_UInt n, i, j;
- FT_Pos reference, overshoot, delta;
+ best = dist;
+ reference = w;
+ }
+ }
- for ( n = 0; n < blues->count; n++, read++ )
- {
- PSH_Blue_Zone zone;
+ if ( width >= reference )
+ {
+ width -= 0x21;
+ if ( width < reference )
+ width = reference;
+ }
+ else
+ {
+ width += 0x21;
+ if ( width > reference )
+ width = reference;
+ }
- /* read new blue zone entry, find top and bottom coordinates */
- reference = read[0];
- overshoot = read[1];
- delta = overshoot - reference;
+ return width;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BLUE ZONES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static void
+ psh_blues_reset_zones( PSH_Blues target,
+ PS_Globals_Blues source,
+ FT_Int family )
+ {
+ PSH_Blue_Table top_table, bot_table;
+ FT_Int16* read;
+ FT_Int read_count, count, count_top, count_bot;
+
+ if ( family )
+ {
+ top_table = &target->family_top;
+ bot_table = &target->family_bottom;
+ read = source->zones_family;
+ read_count = (FT_Int)source->count_family;
+ }
+ else
+ {
+ top_table = &target->normal_top;
+ bot_table = &target->normal_bottom;
+ read = source->zones;
+ read_count = (FT_Int)source->count;
+ }
+
+ /* read the input blue zones, and build two sorted tables */
+ /* (one for the top zones, the other for the bottom zones */
+ count_top = 0;
+ count_bot = 0;
+ for ( ; read_count > 0; read_count-- )
+ {
+ FT_Int reference, delta;
+ PSH_Blue_Zone zones, zone;
+
+ /* read blue zone entry, and select target top/bottom zone */
+ reference = read[0];
+ delta = read[1] - reference;
+
+ if ( delta >= 0 )
+ {
+ zones = top_table->zones;
+ count = count_top;
+ }
+ else
+ {
+ zones = bot_table->zones;
+ count = count_bot;
+ }
+
+ /* insert into sorted table */
+ zone = zones;
+ for ( ; count > 0; count--, zone++ )
+ {
+ if ( reference < zone->org_ref )
+ break;
+
+ if ( reference == zone->org_ref )
+ {
+ FT_Int delta0 = zone->org_delta;
- /* now, insert in the blue zone table, sorted by reference position */
- zone = globals->blues.zones;
- for ( i = 0; i < count; i++, zone++ )
+ /* we have two zones on the same reference position */
+ /* only keep the largest one.. */
+ if ( delta < 0 )
{
- if ( reference > zone->org_ref )
- break;
-
- if ( reference == zone->org_ref )
- {
- /* on the same reference coordinate, place bottom zones */
- /* before top zones.. */
- if ( delta < 0 || zone->org_delta >= 0 )
- break;
- }
+ if ( delta < delta0 )
+ zone->org_delta = delta;
+ }
+ else
+ {
+ if ( delta > delta0 )
+ zone->org_delta = delta;
+ }
+ goto Skip;
+ }
+ }
+
+ for ( ; count > 0; count-- )
+ zone[count] = zone[count-1];
+
+ zone->org_ref = reference;
+ zone->org_delta = delta;
+
+ if ( delta >= 0 )
+ count_top ++;
+ else
+ count_bot ++;
+
+ Skip:
+ read += 2;
+ }
- for ( j = count - i; j > 0; j-- )
- zone[j+1] = zone[j];
+ top_table->count = count_top;
+ bot_table->count = count_bot;
- zone->org_ref = reference;
+ /* sanitize top table */
+ {
+ PSH_Blue_Zone zone = top_table->zones;
+
+ for ( count = count_top-1; count > 0; count--, zone++ )
+ {
+ FT_Int delta;
+
+ delta = zone[1].org_ref - zone[0].org_ref;
+ if ( zone->org_delta > delta )
zone->org_delta = delta;
-
- count++;
- }
+
+ zone->org_bottom = zone->org_ref;
+ zone->org_top = zone->org_delta + zone->org_ref;
}
+ }
+
+ /* sanitize bottom table */
+ {
+ PSH_Blue_Zone zone = bot_table->zones;
- /* now, get rid of blue zones located on the same reference position */
- /* (only keep the largest zone).. */
+ for ( count = count_bot-1; count > 0; count--, zone++ )
{
- PSH_Blue_Zone zone, limit;
+ FT_Int delta;
+
+ delta = zone[0].org_ref - zone[1].org_ref;
+ if ( zone->org_delta < delta )
+ zone->org_delta = delta;
+
+ zone->org_top = zone->org_ref;
+ zone->org_bottom = zone->org_delta + zone->org_ref;
+ }
+ }
- zone = globals->blues.zones;
- limit = zone + count;
- for ( ; zone+1 < limit; zone++ )
+ /* expand top and bottom tables with blue fuzz */
+ {
+ FT_Int dim, top, bot, delta, fuzz;
+ PSH_Blue_Zone zone;
+
+ fuzz = source->fuzz;
+ zone = top_table->zones;
+ count = count_top;
+
+ for ( dim = 1; dim >= 0; dim-- )
+ {
+ if ( count > 0 )
{
- if ( zone[0].org_ref == zone[1].org_ref )
+ /* expand the bottom of the lowest zone normally */
+ zone->org_bottom -= fuzz;
+
+ /* expand the top and bottom of intermediate zones */
+ /* checking that the interval is smaller than the fuzz */
+ top = zone->org_top;
+
+ for ( count--; count > 0; count--, zone++ )
{
- FT_Int delta0 = zone[0].org_delta;
- FT_Int delta1 = zone[1].org_delta;
-
- /* these two zones are located on the same reference coordinate */
- /* we need to merge them when they're in the same direction.. */
- if ( ( delta0 < 0 ) ^ ( delta1 < 0 ) ) == 0 )
+ bot = zone[1].org_bottom;
+ delta = bot - top;
+ if ( delta < 2*fuzz )
+ {
+ zone[0].org_top = zone[1].org_bottom = top + delta/2;
+ }
+ else
{
- /* ok, take the biggest one */
- if ( delta0 < 0 )
- {
- if ( delta1 < delta0 )
- delta0 = delta1;
- }
- else
- {
- if ( delta1 > delta0 )
- delta0 = delta1;
- }
-
- zone[0].org_delta = delta0;
-
- {
- PSH_Blue_Zone cur = zone+1;
- FT_UInt count2 = limit - cur;
-
- for ( ; count2 > 0; count2--, cur++ )
- {
- cur[0].org_ref = cur[1].org_ref;
- cur[0].org_delta = cur[1].org_delta;
- }
- }
- count--;
- limit--;
+ zone[0].org_top = top + fuzz;
+ zone[1].org_bottom = bot - fuzz;
}
+
+ zone++;
+ top = zone->org_top;
}
+
+ /* expand the top of the highest zone normally */
+ zone->org_top = top + fuzz;
}
+ zone = bot_table->zones;
+ count = count_bot;
}
-
- globals->blues.count = count;
- globals->blues.org_shift = blues->shift;
- globals->blues.org_fuzz = blues->fuzz;
}
-
- return error;
}
+ /* reset the blues table */
static void
- psh_globals_scale_blues( PSH_Globals globals,
- PS_Globals_Blues blues )
+ psh_blues_scale_zones( PSH_Blues blues,
+ FT_Fixed scale,
+ FT_Pos delta )
{
- FT_Fixed y_scale = globals->scale[1];
- FT_Fixed y_delta = globals->delta[1];
- FT_Pos prev_top;
- PSH_Blue_Zone zone, prev;
- FT_UInt count;
-
- zone = globals->blues.zones;
- prev = 0;
- prev_top = 0;
- for ( count = globals->blues.count; count > 0; count-- )
+ FT_UInt count;
+ FT_UInt num;
+ PSH_Blue_Table table = 0;
+
+ for ( num = 0; num < 4; num++ )
{
- FT_Pos ref, delta, top, bottom;
+ PSH_Blue_Zone zone;
+
+ switch (num)
+ {
+ case 0: table = &blues->normal_top; break;
+ case 1: table = &blues->normal_bottom; break;
+ case 2: table = &blues->family_top; break;
+ default: table = &blues->family_bottom;
+ }
+
+ zone = table->zones;
+ count = table->count;
+ for ( ; count > 0; count--, zone++ )
+ {
+ zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta;
+ zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;
+ zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta;
+ zone->cur_delta = FT_MulFix( zone->org_delta, scale );
+
+ /* round scaled reference position */
+ zone->cur_ref = ( zone->cur_ref + 32 ) & -64;
+ }
+ }
+
+ /* XXX: we should process the family / normal tables here !! */
+ }
- ref = FT_MulFix( zone->org_ref, y_scale ) + y_delta;
- delta = FT_MulFix( zone->org_delta, y_scale );
- ref = (ref+32) & -64;
- if ( delta < 0 )
+ FT_LOCAL_DEF void
+ psh_blues_snap_stem( PSH_Blues blues,
+ FT_Int stem_top,
+ FT_Int stem_bot,
+ PSH_Blue_Alignement alignment )
+ {
+ PSH_Blue_Table table;
+ FT_UInt count;
+ PSH_Blue_Zone zone;
+
+ alignment->align = 0;
+
+ /* lookup stem top in top zones table */
+ table = &blues->normal_top;
+ count = table->count;
+ zone = table->zones;
+ for ( ; count > 0; count-- )
+ {
+ if ( stem_top < zone->org_bottom )
+ break;
+
+ if ( stem_top <= zone->org_top )
{
- top = ref;
- bottom = ref + delta;
+ alignment->align |= PSH_BLUE_ALIGN_TOP;
+ alignment->align_top = zone->cur_ref;
+ break;
}
- else
+ }
+
+ /* lookup stem bottom in bottom zones table */
+ table = &blues->normal_bottom;
+ count = table->count;
+ zone = table->zones;
+ for ( ; count > 0; count-- )
+ {
+ if ( stem_bot < zone->org_bottom )
+ break;
+
+ if ( stem_bot <= zone->org_top )
{
- bottom = ref;
- top = ref + delta;
+ alignment->align |= PSH_BLUE_ALIGN_BOT;
+ alignment->align_bot = zone->cur_ref;
}
+ }
+ }
- zone->cur_ref = ref;
- zone->cur_delta = delta;
- zone->cur_top = top;
- zone->cur_bottom = bottom;
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** GLOBAL HINTS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
- if
- prev = zone;
- zone++;
+ static void
+ psh_globals_destroy( PSH_Globals globals )
+ {
+ if (globals)
+ {
+ FT_Memory memory;
+
+ memory = globals->memory;
+ globals->dimension[0].std.count = 0;
+ globals->dimension[1].std.count = 0;
+
+ globals->blues.normal_top.count = 0;
+ globals->blues.normal_bottom.count = 0;
+ globals->blues.family_top.count = 0;
+ globals->blues.family_bottom.count = 0;
+
+ FREE( globals );
}
- /* XXXX: test overshoot supression !! */
}
- FT_LOCAL FT_Error
- psh_globals_reset( PSH_Globals globals,
- T1_Fitter_Globals public_globals )
+
+ static FT_Error
+ psh_globals_new( FT_Memory memory, PSH_Globals *aglobals )
{
- psh_globals_reset_widths( globals, 0, &public_globals->horizontal );
- psh_globals_scale_widths( globals, 0 );
+ PSH_Globals globals;
+ FT_Error error;
+
+ if ( !ALLOC( globals, sizeof(*globals) ) )
+ globals->memory = memory;
+
+ *aglobals = globals;
+ return error;
+ }
- psh_globals_reset_widths( globals, 1, &public_globals->vertical );
- psh_globals_scale_widths( globals, 1 );
- psh_globals_reset_blues( globals, public_globals );
- psh_globals_scale_blues( globals );
+ static FT_Error
+ psh_globals_reset( PSH_Globals globals,
+ PS_Globals ps_globals )
+ {
+ psh_globals_reset_widths( globals, 0, &ps_globals->horizontal );
+ psh_globals_reset_widths( globals, 1, &ps_globals->vertical );
+ psh_blues_reset_zones( &globals->blues, &ps_globals->blues, 0 );
+ psh_blues_reset_zones( &globals->blues, &ps_globals->blues, 1 );
+
+ globals->dimension[0].scale_mult = 0;
+ globals->dimension[0].scale_delta = 0;
+ globals->dimension[1].scale_mult = 0;
+ globals->dimension[1].scale_delta = 0;
+
+ return 0;
}
- FT_LOCAL void
+ static FT_Error
psh_globals_set_scale( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed x_delta,
FT_Fixed y_scale,
FT_Fixed y_delta )
{
- FT_Memory memory = globals->memory;
-
- if ( x_scale != globals->scale[0] ||
- y_scale != globals->scale[1] ||
- x_delta != globals->delta[0] ||
- y_delta != globals->delta[1] )
+ PSH_Dimension dim = &globals->dimension[0];
+
+ dim = &globals->dimension[0];
+ if ( x_scale != dim->scale_mult ||
+ x_delta != dim->scale_delta )
{
- globals->scale[0] = x_scale;
- globals->scale[1] = y_scale;
- globals->delta[0] = x_delta;
- globals->delta[1] = y_delta;
-
+ dim->scale_mult = x_scale;
+ dim->scale_delta = x_delta;
+
psh_globals_scale_widths( globals, 0 );
+ }
+
+ dim = &globals->dimension[1];
+ if ( y_scale != dim->scale_mult ||
+ y_delta != dim->scale_delta )
+ {
psh_globals_scale_widths( globals, 1 );
- psh_globals_scale_blues ( globals );
+ psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
}
+
+ return 0;
}
- FT_LOCAL void
- psh_globals_done( PSH_Globals globals )
+ FT_LOCAL_DEF void
+ psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs )
{
- if (globals)
- {
- FT_Memory memory = globals->memory;
-
- FT_FREE( globals->std[0].widths );
- globals->std[0].count = 0;
-
- FT_FREE( globals->std[1].widths );
- globals->std[1].count = 0;
-
- FT_FREE( globals->blues.zones );
- globals->blues.count = 0;
- }
+ funcs->create = psh_globals_new;
+ funcs->reset = psh_globals_reset;
+ funcs->set_scale = psh_globals_set_scale;
+ funcs->destroy = psh_globals_destroy;
}