diff --git a/ChangeLog b/ChangeLog index e7c523981..25b8047fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,13 +1,26 @@ +2001-11-20 David Turner + + * src/pshinter/{pshalgo2.c, pshalgo1.c}: fixed stupid bug in sorting + routine that created nasty alignment artefacts. + + * src/pshinter/pshrec.c, tests/gview.c: debugging updates.. + + * src/smooth/ftgrays.c: de-activated experimental gamme support, + apparently, "optimal" gamma tables depend on the monitor type, + resolution and general karma, so it's better to compute them outside + of the rasterizer itself.. + + 2001-10-29 David Turner * src/smooth/ftgrays.c: adding experimental "gamma" support. This produces smoother glyphs at small sizes for very little cost - + * src/autohint/ahglyph.c, src/autohint/ahhint.c: various fixes to the auto-hinter. They merely improve the output of sans-serif fonts. Note that there are still problems with serifed fonts and composites (accented characters) - + * tests/gview.c: updated the debugging glyph viewer to show the hints generated by the "autohint" module @@ -22,15 +35,15 @@ * include/freetype/ftcache.h, include/freetype/cache/*.h, src/cache/*.c: Major re-design of the cache sub-system to provide better performance as well as an "Acquire"/"Release" API.. - + seems to work well here.. but probably needs a bit more testing.. - + 2001-10-26 Leonard Rosenthol * updated Mac OS README (builds/mac/) to reflect my taking over the project and that is now being actively maintained. - + * Applied patches from Paul Miller () to /src/base/ftmac.c to support loading a face other than the first from a FOND resource. @@ -61,7 +74,7 @@ improvements to the memory debugger to report more information in case of errors. Also, some allocations that occured through REALLOC couldn't be previously catched correctly.. - + * src/autohint/ahglyph.c, src/raster/ftraster.c, src/smooth/ftgrays.c: replaced liberal uses of "memset" by the @@ -87,10 +100,10 @@ the FT_DEBUG_MEMORY macro in "ftoption.h" to enable it. It will record every memory block allocated and report simple errors like memory leaks and double deletes. - + * include/freetype/config/ftoption.h: added the FT_DEBUG_MEMORY macro definition - + * src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory): modified the base component to use the debugging memory manager when the macro FT_DEBUG_MEMORY is defined.. @@ -115,7 +128,7 @@ 2001-10-20 Tom Kacvinsky - + * src/type1/t1load.c (parse_encoding): Add a test to make sure that custom encodings (i.e., neither StandardEncoding nor ExpertEncoding) are not loaded twice when the Type 1 font is @@ -162,7 +175,7 @@ some strange bugs in the Postscript hinter * src/cid/cidgload.c: adding support to new postscript hinter - + * include/freetype/internal/psglobal.h, include/freetype/internal/pshints.h, include/freetype/config/ftmodule.h, @@ -276,7 +289,7 @@ Provide a public API to manage multiple size objects for a given FT_Face in the new header file `ftsizes.h'. - * include/freetype/ftsizes.h: New header file, + * include/freetype/ftsizes.h: New header file, * include/freetype/internal/ftobjs.h: Use it. Remove declarations of FT_New_Size and FT_Done_Size (moved to ftsizes.h). @@ -520,7 +533,7 @@ 2001-06-22 David Turner * docs/PATENTS: Added patents disclaimer. This one was missing! - + * docs/CHANGES, docs/todo: Updated for the upcoming 2.0.4 release. 2001-06-20 Werner Lemberg diff --git a/src/pshinter/pshalgo1.c b/src/pshinter/pshalgo1.c index e649cdef8..9d61bcaad 100644 --- a/src/pshinter/pshalgo1.c +++ b/src/pshinter/pshalgo1.c @@ -15,7 +15,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + /* return true iff two stem hints overlap */ static FT_Int psh1_hint_overlap( PSH1_Hint hint1, @@ -24,8 +24,8 @@ return ( hint1->org_pos + hint1->org_len >= hint2->org_pos && hint2->org_pos + hint2->org_len >= hint1->org_pos ); } - - + + /* destroy hints table */ static void psh1_hint_table_done( PSH1_Hint_Table table, @@ -34,7 +34,7 @@ FREE( table->zones ); table->num_zones = 0; table->zone = 0; - + FREE( table->sort ); FREE( table->hints ); table->num_hints = 0; @@ -49,7 +49,7 @@ { FT_UInt count = table->max_hints; PSH1_Hint hint = table->hints; - + for ( ; count > 0; count--, hint++ ) { psh1_hint_deactivate(hint); @@ -70,13 +70,13 @@ FT_ERROR(( "%s.activate: invalid hint index %d\n", index )); return; } - + /* ignore active hints */ if ( psh1_hint_is_active(hint) ) return; - + psh1_hint_activate(hint); - + /* now scan the current active hint set in order to determine */ /* if we're overlapping with another segment.. */ { @@ -84,11 +84,11 @@ FT_UInt count = table->num_hints; PSH1_Hint hint2; - hint->parent = 0; + hint->parent = 0; for ( ; count > 0; count--, sorted++ ) { hint2 = sorted[0]; - + if ( psh1_hint_overlap( hint, hint2 ) ) { hint->parent = hint2; @@ -96,7 +96,7 @@ } } } - + if ( table->num_hints < table->max_hints ) table->sort_global[ table->num_hints++ ] = hint; else @@ -115,14 +115,14 @@ FT_Byte* cursor = hint_mask->bytes; FT_UInt index, limit; - limit = hint_mask->num_bits; - + limit = hint_mask->num_bits; + if ( limit != table->max_hints ) { FT_ERROR(( "%s.activate_mask: invalid bit count (%d instead of %d)\n", "ps.fitter", hint_mask->num_bits, table->max_hints )); } - + for ( index = 0; index < limit; index++ ) { if ( mask == 0 ) @@ -130,10 +130,10 @@ val = *cursor++; mask = 0x80; } - + if ( val & mask ) psh1_hint_table_record( table, index ); - + mask >>= 1; } } @@ -151,24 +151,24 @@ FT_Error error; FT_UNUSED(counter_masks); - + /* allocate our tables */ if ( ALLOC_ARRAY( table->sort, 2*count, PSH1_Hint ) || ALLOC_ARRAY( table->hints, count, PSH1_HintRec ) || ALLOC_ARRAY( table->zones, 2*count+1, PSH1_ZoneRec ) ) goto Exit; - + table->max_hints = count; table->sort_global = table->sort + count; table->num_hints = 0; table->num_zones = 0; table->zone = 0; - + /* now, initialise the "hints" array */ { PSH1_Hint write = table->hints; PS_Hint read = hints->hints; - + for ( ; count > 0; count--, write++, read++ ) { write->org_pos = read->pos; @@ -185,22 +185,22 @@ PS_Mask mask = hint_masks->masks; table->hint_masks = hint_masks; - + for ( ; count > 0; count--, mask++ ) psh1_hint_table_record_mask( table, mask ); } - + /* now, do a linear parse in case some hints were left alone */ if ( table->num_hints != table->max_hints ) { FT_UInt index, count; - + FT_ERROR(( "%s.init: missing/incorrect hint masks !!\n" )); count = table->max_hints; for ( index = 0; index < count; index++ ) psh1_hint_table_record( table, index ); - } - + } + Exit: return error; } @@ -215,11 +215,11 @@ FT_Byte* cursor = hint_mask->bytes; FT_UInt index, limit, count; - limit = hint_mask->num_bits; + limit = hint_mask->num_bits; count = 0; psh1_hint_table_deactivate( table ); - + for ( index = 0; index < limit; index++ ) { if ( mask == 0 ) @@ -227,17 +227,17 @@ val = *cursor++; mask = 0x80; } - + if ( val & mask ) { PSH1_Hint hint = &table->hints[index]; - + if ( !psh1_hint_is_active(hint) ) { PSH1_Hint* sort = table->sort; FT_UInt count2; PSH1_Hint hint2; - + for ( count2 = count; count2 > 0; count2--, sort++ ) { hint2 = sort[0]; @@ -248,7 +248,7 @@ break; } } - + if ( count2 == 0 ) { psh1_hint_activate( hint ); @@ -258,15 +258,15 @@ { FT_ERROR(( "%s.activate_mask: too many active hints\n", "psf.hint" )); - } + } } } } - + mask >>= 1; } table->num_hints = count; - + /* now, sort the hints, they're guaranteed to not overlap */ /* so we can compare their "org_pos" field directly.. */ { @@ -284,9 +284,9 @@ hint2 = sort[i2]; if ( hint2->org_pos < hint1->org_pos ) break; - - sort[i1] = hint2; - sort[i2] = hint1; + + sort[i2+1] = hint2; + sort[i2] = hint1; } } } @@ -305,7 +305,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + #ifdef DEBUG_HINTER void ps_simple_scale( PSH1_Hint_Table table, @@ -315,7 +315,7 @@ { PSH1_Hint hint; FT_UInt count; - + for ( count = 0; count < table->num_hints; count++ ) { hint = table->sort[count]; @@ -323,12 +323,12 @@ { hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta; hint->cur_len = FT_MulFix( hint->org_len, scale ); - + if (ps1_debug_hint_func) ps1_debug_hint_func( hint, vertical ); } } - } + } #endif FT_LOCAL_DEF FT_Error @@ -349,7 +349,7 @@ ps_simple_scale( table, scale, delta, vertical ); return 0; } - + if ( ps_debug_no_horz_hints && !vertical ) { ps_simple_scale( table, scale, delta, vertical ); @@ -359,10 +359,10 @@ /* XXXX: for now, we only scale the hints to test all other aspects */ /* of the Postscript Hinter.. */ - { + { PSH1_Hint hint; FT_UInt count; - + for ( count = 0; count < table->num_hints; count++ ) { hint = table->sort[count]; @@ -371,10 +371,10 @@ # if 1 FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; FT_Pos len = FT_MulFix( hint->org_len, scale ); - + FT_Pos fit_center; FT_Pos fit_len; - + PSH_AlignmentRec align; /* compute fitted width/height */ @@ -383,9 +383,9 @@ fit_len = 64; else fit_len = (fit_len + 32 ) & -64; - + hint->cur_len = fit_len; - + /* check blue zones for horizontal stems */ align.align = 0; align.align_bot = align.align_top = 0; @@ -405,14 +405,14 @@ hint->cur_pos = align.align_top - fit_len; break; } - + case PSH_BLUE_ALIGN_BOT: { /* the bottom of the stem is aligned against a blue zone */ hint->cur_pos = align.align_bot; break; } - + case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: { /* both edges of the stem are aligned against blue zones */ @@ -420,7 +420,7 @@ hint->cur_len = align.align_top - align.align_bot; } break; - + default: /* normal processing */ if ( (fit_len/64) & 1 ) @@ -433,22 +433,22 @@ /* even number of pixels */ fit_center = (pos + (len >> 1) + 32) & -64; } - + hint->cur_pos = fit_center - (fit_len >> 1); } # else hint->cur_pos = (FT_MulFix( hint->org_pos, scale ) + delta + 32) & -64; hint->cur_len = FT_MulFix( hint->org_len, scale ); -# endif +# endif #ifdef DEBUG_HINTER if (ps1_debug_hint_func) ps1_debug_hint_func( hint, vertical ); -#endif +#endif } } } - + return 0; } @@ -462,7 +462,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + #define PSH1_ZONE_MIN -3200000 #define PSH1_ZONE_MAX +3200000 @@ -497,9 +497,9 @@ FT_UInt count; PSH1_Zone zone; PSH1_Hint *sort, hint, hint2; - + zone = table->zones; - + /* special case, no hints defined */ if ( table->num_hints == 0 ) { @@ -507,26 +507,26 @@ zone->delta = delta; zone->min = PSH1_ZONE_MIN; zone->max = PSH1_ZONE_MAX; - + table->num_zones = 1; table->zone = zone; return; } - + /* the first zone is before the first hint */ /* x' = (x-x0)*s + x0' = x*s + ( x0' - x0*s ) */ sort = table->sort; hint = sort[0]; - + zone->scale = scale; zone->delta = hint->cur_pos - FT_MulFix( hint->org_pos, scale ); zone->min = PSH1_ZONE_MIN; zone->max = hint->org_pos; - + print_zone( zone ); - + zone++; - + for ( count = table->num_hints; count > 0; count-- ) { FT_Fixed scale2; @@ -536,7 +536,7 @@ /* setup a zone for inner-stem interpolation */ /* (x' - x0') = (x - x0)*(x1'-x0')/(x1-x0) */ /* x' = x*s2 + x0' - x0*s2 */ - + scale2 = FT_DivFix( hint->cur_len, hint->org_len ); zone->scale = scale2; zone->min = hint->org_pos; @@ -544,16 +544,16 @@ zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale2 ); print_zone( zone ); - + zone++; } - + if ( count == 1 ) break; - + sort++; hint2 = sort[0]; - + /* setup zone for inter-stem interpolation */ /* (x'-x1') = (x-x1)*(x2'-x1')/(x2-x1) */ /* x' = x*s3 + x1' - x1*s3 */ @@ -565,9 +565,9 @@ zone->delta = hint->cur_pos + hint->cur_len - FT_MulFix( zone->min, scale2 ); print_zone( zone ); - + zone++; - + hint = hint2; } @@ -578,30 +578,30 @@ zone->delta = hint->cur_pos + hint->cur_len - FT_MulFix( zone->min, scale ); print_zone( zone ); - + zone++; - + table->num_zones = zone - table->zones; table->zone = table->zones; } - /* tune a single coordinate with the current interpolation zones */ + /* tune a single coordinate with the current interpolation zones */ static FT_Pos psh1_hint_table_tune_coord( PSH1_Hint_Table table, FT_Int coord ) { PSH1_Zone zone; - + zone = table->zone; - + if ( coord < zone->min ) { do { if ( zone == table->zones ) break; - + zone--; } while ( coord < zone->min ); @@ -613,13 +613,13 @@ { if ( zone == table->zones + table->num_zones - 1 ) break; - + zone++; } while ( coord > zone->max ); table->zone = zone; } - + return FT_MulFix( coord, zone->scale ) + zone->delta; } @@ -639,7 +639,7 @@ PSH_Dimension dim = &globals->dimension[vertical]; FT_Fixed scale = dim->scale_mult; FT_Fixed delta = dim->scale_delta; - + if ( hint_masks && hint_masks->num_masks > 0 ) { first = 0; @@ -648,40 +648,40 @@ for ( ; count > 0; count--, mask++ ) { last = mask->end_point; - + if ( last > first ) { FT_Vector* vec; FT_Int count2; - + psh1_hint_table_activate_mask( table, mask ); psh1_hint_table_optimize( table, globals, outline, vertical ); psh1_hint_table_setup_zones( table, scale, delta ); last = mask->end_point; - + vec = outline->points + first; count2 = last - first; for ( ; count2 > 0; count2--, vec++ ) { FT_Pos x, *px; - + px = vertical ? &vec->x : &vec->y; x = *px; - + *px = psh1_hint_table_tune_coord( table, (FT_Int)x ); } } - + first = last; } } else /* no hints in this glyph, simply scale the outline */ { FT_Vector* vec; - + vec = outline->points; count = outline->n_points; - + if ( vertical ) { for ( ; count > 0; count--, vec++ ) @@ -694,8 +694,8 @@ } } } - - + + /************************************************************************/ /************************************************************************/ /***** *****/ @@ -703,7 +703,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + FT_Error ps1_hints_apply( PS_Hints ps_hints, FT_Outline* outline, @@ -712,11 +712,11 @@ PSH1_Hint_TableRec hints; FT_Error error = 0; FT_Int dimension; - + for ( dimension = 1; dimension >= 0; dimension-- ) { PS_Dimension dim = &ps_hints->dimension[dimension]; - + /* initialise hints table */ memset( &hints, 0, sizeof(hints) ); error = psh1_hint_table_init( &hints, @@ -725,15 +725,15 @@ &dim->counters, ps_hints->memory ); if (error) goto Exit; - + psh1_hint_table_tune_outline( &hints, outline, globals, dimension ); - + psh1_hint_table_done( &hints, ps_hints->memory ); } - + Exit: - return error; + return error; } diff --git a/src/pshinter/pshalgo2.c b/src/pshinter/pshalgo2.c index 95f167a66..86ede1d3c 100644 --- a/src/pshinter/pshalgo2.c +++ b/src/pshinter/pshalgo2.c @@ -4,7 +4,7 @@ #include "pshalgo2.h" -#ifdef DEBUG_HINTER +#ifdef DEBUG_HINTER extern PSH2_Hint_Table ps2_debug_hint_table = 0; extern PSH2_HintFunc ps2_debug_hint_func = 0; extern PSH2_Glyph ps2_debug_glyph = 0; @@ -17,7 +17,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + /* return true iff two stem hints overlap */ static FT_Int psh2_hint_overlap( PSH2_Hint hint1, @@ -26,8 +26,8 @@ return ( hint1->org_pos + hint1->org_len >= hint2->org_pos && hint2->org_pos + hint2->org_len >= hint1->org_pos ); } - - + + /* destroy hints table */ static void psh2_hint_table_done( PSH2_Hint_Table table, @@ -36,7 +36,7 @@ FREE( table->zones ); table->num_zones = 0; table->zone = 0; - + FREE( table->sort ); FREE( table->hints ); table->num_hints = 0; @@ -51,7 +51,7 @@ { FT_UInt count = table->max_hints; PSH2_Hint hint = table->hints; - + for ( ; count > 0; count--, hint++ ) { psh2_hint_deactivate(hint); @@ -72,13 +72,13 @@ FT_ERROR(( "%s.activate: invalid hint index %d\n", index )); return; } - + /* ignore active hints */ if ( psh2_hint_is_active(hint) ) return; - + psh2_hint_activate(hint); - + /* now scan the current active hint set in order to determine */ /* if we're overlapping with another segment.. */ { @@ -86,11 +86,11 @@ FT_UInt count = table->num_hints; PSH2_Hint hint2; - hint->parent = 0; + hint->parent = 0; for ( ; count > 0; count--, sorted++ ) { hint2 = sorted[0]; - + if ( psh2_hint_overlap( hint, hint2 ) ) { hint->parent = hint2; @@ -98,7 +98,7 @@ } } } - + if ( table->num_hints < table->max_hints ) table->sort_global[ table->num_hints++ ] = hint; else @@ -117,8 +117,8 @@ FT_Byte* cursor = hint_mask->bytes; FT_UInt index, limit; - limit = hint_mask->num_bits; - + limit = hint_mask->num_bits; + for ( index = 0; index < limit; index++ ) { if ( mask == 0 ) @@ -126,10 +126,10 @@ val = *cursor++; mask = 0x80; } - + if ( val & mask ) psh2_hint_table_record( table, index ); - + mask >>= 1; } } @@ -147,24 +147,24 @@ FT_Error error; FT_UNUSED(counter_masks); - + /* allocate our tables */ if ( ALLOC_ARRAY( table->sort, 2*count, PSH2_Hint ) || ALLOC_ARRAY( table->hints, count, PSH2_HintRec ) || ALLOC_ARRAY( table->zones, 2*count+1, PSH2_ZoneRec ) ) goto Exit; - + table->max_hints = count; table->sort_global = table->sort + count; table->num_hints = 0; table->num_zones = 0; table->zone = 0; - + /* now, initialise the "hints" array */ { PSH2_Hint write = table->hints; PS_Hint read = hints->hints; - + for ( ; count > 0; count--, write++, read++ ) { write->org_pos = read->pos; @@ -181,22 +181,22 @@ PS_Mask mask = hint_masks->masks; table->hint_masks = hint_masks; - + for ( ; count > 0; count--, mask++ ) psh2_hint_table_record_mask( table, mask ); } - + /* now, do a linear parse in case some hints were left alone */ if ( table->num_hints != table->max_hints ) { FT_UInt index, count; - + FT_ERROR(( "%s.init: missing/incorrect hint masks !!\n" )); count = table->max_hints; for ( index = 0; index < count; index++ ) psh2_hint_table_record( table, index ); - } - + } + Exit: return error; } @@ -211,11 +211,11 @@ FT_Byte* cursor = hint_mask->bytes; FT_UInt index, limit, count; - limit = hint_mask->num_bits; + limit = hint_mask->num_bits; count = 0; psh2_hint_table_deactivate( table ); - + for ( index = 0; index < limit; index++ ) { if ( mask == 0 ) @@ -223,15 +223,15 @@ val = *cursor++; mask = 0x80; } - + if ( val & mask ) { PSH2_Hint hint = &table->hints[index]; - + if ( !psh2_hint_is_active(hint) ) { FT_UInt count2; - + #if 0 PSH2_Hint* sort = table->sort; PSH2_Hint hint2; @@ -248,7 +248,7 @@ #else count2 = 0; #endif - + if ( count2 == 0 ) { psh2_hint_activate( hint ); @@ -258,15 +258,15 @@ { FT_ERROR(( "%s.activate_mask: too many active hints\n", "psf.hint" )); - } + } } } } - + mask >>= 1; } table->num_hints = count; - + /* now, sort the hints, they're guaranteed to not overlap */ /* so we can compare their "org_pos" field directly.. */ { @@ -282,11 +282,12 @@ for ( i2 = i1-1; i2 >= 0; i2-- ) { hint2 = sort[i2]; + if ( hint2->org_pos < hint1->org_pos ) break; - - sort[i1] = hint2; - sort[i2] = hint1; + + sort[i2+1] = hint2; + sort[i2] = hint1; } } } @@ -305,7 +306,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + #ifdef DEBUG_HINTER static void ps2_simple_scale( PSH2_Hint_Table table, @@ -315,18 +316,18 @@ { PSH2_Hint hint; FT_UInt count; - + for ( count = 0; count < table->max_hints; count++ ) { hint = table->hints + count; hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta; hint->cur_len = FT_MulFix( hint->org_len, scale ); - + if (ps2_debug_hint_func) ps2_debug_hint_func( hint, vertical ); } - } + } #endif @@ -340,13 +341,13 @@ FT_Fixed delta = dim->scale_delta; if ( !psh2_hint_is_fitted(hint) ) - { + { FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; FT_Pos len = FT_MulFix( hint->org_len, scale ); - + FT_Pos fit_center; FT_Pos fit_len; - + PSH_AlignmentRec align; /* compute fitted width/height */ @@ -359,13 +360,13 @@ else fit_len = (fit_len + 32 ) & -64; } - + hint->cur_len = fit_len; - + /* check blue zones for horizontal stems */ align.align = 0; align.align_bot = align.align_top = 0; - + if (!vertical) { psh_blues_snap_stem( &globals->blues, @@ -382,14 +383,14 @@ hint->cur_pos = align.align_top - fit_len; break; } - + case PSH_BLUE_ALIGN_BOT: { /* the bottom of the stem is aligned against a blue zone */ hint->cur_pos = align.align_bot; break; } - + case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: { /* both edges of the stem are aligned against blue zones */ @@ -397,26 +398,26 @@ hint->cur_len = align.align_top - align.align_bot; break; } - + default: { PSH2_Hint parent = hint->parent; - + if ( parent ) { FT_Pos par_org_center, par_cur_center; FT_Pos cur_org_center, cur_delta; - + /* ensure that parent is already fitted */ if ( !psh2_hint_is_fitted(parent) ) psh2_hint_align( parent, globals, vertical ); - + par_org_center = parent->org_pos + (parent->org_len/2); par_cur_center = parent->cur_pos + (parent->cur_len/2); - cur_org_center = hint->org_pos + (hint->org_len/2); - + cur_org_center = hint->org_pos + (hint->org_len/2); + cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); -#if 0 +#if 0 if ( cur_delta >= 0 ) cur_delta = (cur_delta+16) & -64; else @@ -436,19 +437,19 @@ /* even number of pixels */ fit_center = (pos + (len >> 1) + 32) & -64; } - + hint->cur_pos = fit_center - (fit_len >> 1); } } - + psh2_hint_set_fitted(hint); - + #ifdef DEBUG_HINTER if (ps2_debug_hint_func) ps2_debug_hint_func( hint, vertical ); #endif } - } + } static void @@ -469,7 +470,7 @@ ps2_simple_scale( table, scale, delta, vertical ); return; } - + if ( ps_debug_no_horz_hints && !vertical ) { ps2_simple_scale( table, scale, delta, vertical ); @@ -491,7 +492,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + #define PSH2_ZONE_MIN -3200000 #define PSH2_ZONE_MAX +3200000 @@ -527,9 +528,9 @@ FT_UInt count; PSH2_Zone zone; PSH2_Hint *sort, hint, hint2; - + zone = table->zones; - + /* special case, no hints defined */ if ( table->num_hints == 0 ) { @@ -537,26 +538,26 @@ zone->delta = delta; zone->min = PSH2_ZONE_MIN; zone->max = PSH2_ZONE_MAX; - + table->num_zones = 1; table->zone = zone; return; } - + /* the first zone is before the first hint */ /* x' = (x-x0)*s + x0' = x*s + ( x0' - x0*s ) */ sort = table->sort; hint = sort[0]; - + zone->scale = scale; zone->delta = hint->cur_pos - FT_MulFix( hint->org_pos, scale ); zone->min = PSH2_ZONE_MIN; zone->max = hint->org_pos; - + print_zone( zone ); - + zone++; - + for ( count = table->num_hints; count > 0; count-- ) { FT_Fixed scale2; @@ -566,7 +567,7 @@ /* setup a zone for inner-stem interpolation */ /* (x' - x0') = (x - x0)*(x1'-x0')/(x1-x0) */ /* x' = x*s2 + x0' - x0*s2 */ - + scale2 = FT_DivFix( hint->cur_len, hint->org_len ); zone->scale = scale2; zone->min = hint->org_pos; @@ -574,16 +575,16 @@ zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale2 ); print_zone( zone ); - + zone++; } - + if ( count == 1 ) break; - + sort++; hint2 = sort[0]; - + /* setup zone for inter-stem interpolation */ /* (x'-x1') = (x-x1)*(x2'-x1')/(x2-x1) */ /* x' = x*s3 + x1' - x1*s3 */ @@ -595,9 +596,9 @@ zone->delta = hint->cur_pos + hint->cur_len - FT_MulFix( zone->min, scale2 ); print_zone( zone ); - + zone++; - + hint = hint2; } @@ -608,31 +609,31 @@ zone->delta = hint->cur_pos + hint->cur_len - FT_MulFix( zone->min, scale ); print_zone( zone ); - + zone++; - + table->num_zones = zone - table->zones; table->zone = table->zones; } #endif #if 0 - /* tune a single coordinate with the current interpolation zones */ + /* tune a single coordinate with the current interpolation zones */ static FT_Pos psh2_hint_table_tune_coord( PSH2_Hint_Table table, FT_Int coord ) { PSH2_Zone zone; - + zone = table->zone; - + if ( coord < zone->min ) { do { if ( zone == table->zones ) break; - + zone--; } while ( coord < zone->min ); @@ -644,13 +645,13 @@ { if ( zone == table->zones + table->num_zones - 1 ) break; - + zone++; } while ( coord > zone->max ); table->zone = zone; } - + return FT_MulFix( coord, zone->scale ) + zone->delta; } #endif @@ -671,7 +672,7 @@ PSH_Dimension dim = &globals->dimension[vertical]; FT_Fixed scale = dim->scale_mult; FT_Fixed delta = dim->scale_delta; - + if ( hint_masks && hint_masks->num_masks > 0 ) { first = 0; @@ -680,40 +681,40 @@ for ( ; count > 0; count--, mask++ ) { last = mask->end_point; - + if ( last > first ) { FT_Vector* vec; FT_Int count2; - + psh2_hint_table_activate_mask( table, mask ); psh2_hint_table_optimize( table, globals, outline, vertical ); psh2_hint_table_setup_zones( table, scale, delta ); last = mask->end_point; - + vec = outline->points + first; count2 = last - first; for ( ; count2 > 0; count2--, vec++ ) { FT_Pos x, *px; - + px = vertical ? &vec->x : &vec->y; x = *px; - + *px = psh2_hint_table_tune_coord( table, (FT_Int)x ); } } - + first = last; } } else /* no hints in this glyph, simply scale the outline */ { FT_Vector* vec; - + vec = outline->points; count = outline->n_points; - + if ( vertical ) { for ( ; count > 0; count--, vec++ ) @@ -749,17 +750,17 @@ before = before->prev; if ( before == point ) return 0; - + d_before = before->org_u - point->org_u; } while ( d_before == 0 ); - + do { after = after->next; if ( after == point ) return 0; - + d_after = after->org_u - point->org_u; } while ( d_after == 0 ); @@ -777,7 +778,7 @@ psh2_hint_table_done( &glyph->hint_tables[1], memory ); psh2_hint_table_done( &glyph->hint_tables[0], memory ); - + FREE( glyph->points ); FREE( glyph->contours ); @@ -793,10 +794,10 @@ { FT_Pos ax, ay; int result = PSH2_DIR_NONE; - + ax = ( dx >= 0 ) ? dx : -dx; ay = ( dy >= 0 ) ? dy : -dy; - + if ( ay*12 < ax ) { /* |dy| <<< |dx| means a near-horizontal segment */ @@ -819,40 +820,40 @@ { FT_Error error; FT_Memory memory; - + /* clear all fields */ memset( glyph, 0, sizeof(*glyph) ); - + memory = globals->memory; - + /* allocate and setup points + contours arrays */ if ( ALLOC_ARRAY( glyph->points, outline->n_points, PSH2_PointRec ) || ALLOC_ARRAY( glyph->contours, outline->n_contours, PSH2_ContourRec ) ) goto Exit; - + glyph->num_points = outline->n_points; glyph->num_contours = outline->n_contours; - + { FT_UInt first = 0, next, n; PSH2_Point points = glyph->points; PSH2_Contour contour = glyph->contours; - + for ( n = 0; n < glyph->num_contours; n++ ) { FT_Int count; PSH2_Point point; - + next = outline->contours[n] + 1; count = next - first; - + contour->start = points + first; contour->count = (FT_UInt)count; - + if ( count > 0 ) { point = points + first; - + point->prev = points + next - 1; point->contour = contour; for ( ; count > 1; count-- ) @@ -865,7 +866,7 @@ point->next = points + first; } - contour++; + contour++; first = next; } } @@ -875,26 +876,26 @@ PSH2_Point point = points; FT_Vector* vec = outline->points; FT_UInt n; - + for ( n = 0; n < glyph->num_points; n++, point++ ) { FT_Int n_prev = point->prev - points; FT_Int n_next = point->next - points; FT_Pos dxi, dyi, dxo, dyo; - + if ( !(outline->tags[n] & FT_Curve_Tag_On) ) point->flags = PSH2_POINT_OFF; - + dxi = vec[n].x - vec[n_prev].x; dyi = vec[n].y - vec[n_prev].y; - + point->dir_in = (FT_Char) psh2_compute_dir( dxi, dyi ); dxo = vec[n_next].x - vec[n].x; dyo = vec[n_next].y - vec[n].y; point->dir_out = (FT_Char) psh2_compute_dir( dxo, dyo ); - + /* detect smooth points */ if ( point->flags & PSH2_POINT_OFF ) { @@ -909,17 +910,17 @@ else { FT_Angle angle_in, angle_out, diff; - + angle_in = FT_Atan2( dxi, dyi ); angle_out = FT_Atan2( dxo, dyo ); - + diff = angle_in - angle_out; if ( diff < 0 ) diff = -diff; - + if ( diff > FT_ANGLE_PI ) diff = FT_ANGLE_2PI - diff; - + if ( (diff < FT_ANGLE_PI/16) ) point->flags |= PSH2_POINT_SMOOTH; } @@ -937,14 +938,14 @@ &ps_hints->dimension[0].counters, memory ); if (error) goto Exit; - + error = psh2_hint_table_init( &glyph->hint_tables [1], &ps_hints->dimension[1].hints, &ps_hints->dimension[1].masks, &ps_hints->dimension[1].counters, memory ); if (error) goto Exit; - + Exit: return error; } @@ -967,15 +968,15 @@ point->org_u = vec->x; else point->org_u = vec->y; - + #ifdef DEBUG_HINTER point->org_x = vec->x; point->org_y = vec->y; -#endif +#endif } } - + /* save hinted point coordinates back to outline */ static void psh2_glyph_save_points( PSH2_Glyph glyph, @@ -985,14 +986,14 @@ PSH2_Point point = glyph->points; FT_Vector* vec = glyph->outline->points; char* tags = glyph->outline->tags; - + for ( n = 0; n < glyph->num_points; n++ ) - { + { if (vertical) vec[n].x = point->cur_u; else vec[n].y = point->cur_u; - + if ( psh2_point_is_strong(point) ) tags[n] |= vertical ? 32 : 64; @@ -1007,12 +1008,14 @@ point->cur_y = point->cur_u; point->flags_y = point->flags; } -#endif +#endif point++; } } +#define PSH2_STRONG_THRESHOLD 10 + static void psh2_hint_table_find_strong_point( PSH2_Hint_Table table, PSH2_Point point, @@ -1020,31 +1023,31 @@ { PSH2_Hint* sort = table->sort; FT_UInt num_hints = table->num_hints; - + for ( ; num_hints > 0; num_hints--, sort++ ) { PSH2_Hint hint = sort[0]; - + if ( ABS(point->dir_in) == major_dir || ABS(point->dir_out) == major_dir ) { FT_Pos d; - + d = point->org_u - hint->org_pos; - if ( ABS(d) < 3 ) + if ( ABS(d) < PSH2_STRONG_THRESHOLD ) { Is_Strong: psh2_point_set_strong(point); point->hint = hint; break; } - + d -= hint->org_len; - if ( ABS(d) < 3 ) + if ( ABS(d) < PSH2_STRONG_THRESHOLD ) goto Is_Strong; } -#if 1 +#if 1 if ( point->org_u >= hint->org_pos && point->org_u <= hint->org_pos + hint->org_len && psh2_point_is_extremum( point ) ) @@ -1053,11 +1056,11 @@ point->hint = hint; break; } -#endif +#endif } } - - + + /* find strong points in a glyph */ static void @@ -1071,8 +1074,8 @@ PS_Mask mask = table->hint_masks->masks; FT_UInt num_masks = table->hint_masks->num_masks; FT_UInt first = 0; - FT_Int major_dir = vertical ? PSH2_DIR_UP : PSH2_DIR_RIGHT; - + FT_Int major_dir = vertical ? PSH2_DIR_UP : PSH2_DIR_RIGHT; + /* process secondary hints to "selected" points */ if ( num_masks > 1 ) { @@ -1081,28 +1084,28 @@ { FT_UInt next; FT_Int count; - + next = mask->end_point; count = next - first; if ( count > 0 ) { PSH2_Point point = glyph->points + first; - + psh2_hint_table_activate_mask( table, mask ); - + for ( ; count > 0; count--, point++ ) psh2_hint_table_find_strong_point( table, point, major_dir ); } first = next; } } - + /* process primary hints for all points */ if ( num_masks == 1 ) { FT_UInt count = glyph->num_points; PSH2_Point point = glyph->points; - + psh2_hint_table_activate_mask( table, table->hint_masks->masks ); for ( ; count > 0; count--, point++ ) { @@ -1110,13 +1113,13 @@ psh2_hint_table_find_strong_point( table, point, major_dir ); } } - + /* now, certain points may have been attached to hint and */ /* not marked as strong, update their flags then.. */ { - FT_UInt count = glyph->num_points; + FT_UInt count = glyph->num_points; PSH2_Point point = glyph->points; - + for ( ; count > 0; count--, point++ ) if ( point->hint && !psh2_point_is_strong(point) ) psh2_point_set_strong(point); @@ -1137,32 +1140,32 @@ { FT_UInt count = glyph->num_points; PSH2_Point point = glyph->points; - + for ( ; count > 0; count--, point++ ) { PSH2_Hint hint = point->hint; - + if ( hint ) { FT_Pos delta; - + delta = point->org_u - hint->org_pos; - + if ( delta <= 0 ) point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); - + else if ( delta >= hint->org_len ) point->cur_u = hint->cur_pos + hint->cur_len + FT_MulFix( delta - hint->org_len, scale ); - + else if ( hint->org_len > 0 ) point->cur_u = hint->cur_pos + FT_MulDiv( delta, hint->cur_len, hint->org_len ); else point->cur_u = hint->cur_pos; - + psh2_point_set_fitted(point); - } + } } } } @@ -1180,43 +1183,43 @@ { FT_UInt count = glyph->num_points; PSH2_Point point = glyph->points; - + for ( ; count > 0; count--, point++ ) { if ( psh2_point_is_strong(point) ) continue; - + /* sometimes, some local extremas are smooth points */ if ( psh2_point_is_smooth(point) ) { if ( point->dir_in == PSH2_DIR_NONE || point->dir_in != point->dir_out ) continue; - + if ( !psh2_point_is_extremum( point ) ) continue; - + point->flags &= ~PSH2_POINT_SMOOTH; } - + /* find best enclosing point coordinates */ { PSH2_Point before = 0; PSH2_Point after = 0; - + FT_Pos diff_before = -32000; FT_Pos diff_after = 32000; FT_Pos u = point->org_u; - + FT_Int count2 = glyph->num_points; PSH2_Point cur = glyph->points; - + for ( ; count2 > 0; count2--, cur++ ) { if ( psh2_point_is_strong(cur) ) { FT_Pos diff = cur->org_u - u;; - + if ( diff <= 0 ) { if ( diff > diff_before ) @@ -1235,12 +1238,12 @@ } } } - + if ( !before ) { if ( !after ) continue; - + /* we're before the first strong point coordinate */ /* simply translate the point.. */ point->cur_u = after->cur_u + @@ -1257,23 +1260,23 @@ { if ( diff_before == 0 ) point->cur_u = before->cur_u; - + else if ( diff_after == 0 ) point->cur_u = after->cur_u; - + else - point->cur_u = before->cur_u + + point->cur_u = before->cur_u + FT_MulDiv( u - before->org_u, after->cur_u - before->cur_u, after->org_u - before->org_u ); } - + psh2_point_set_fitted(point); } } } -#endif - } +#endif + } @@ -1287,61 +1290,61 @@ FT_Fixed delta = dim->scale_delta; PSH2_Contour contour = glyph->contours; FT_UInt num_contours = glyph->num_contours; - + for ( ; num_contours > 0; num_contours--, contour++ ) { PSH2_Point start = contour->start; PSH2_Point first, next, point; FT_UInt fit_count; - + /* count the number of strong points in this contour */ next = start + contour->count; fit_count = 0; first = 0; - + for ( point = start; point < next; point++ ) if ( psh2_point_is_fitted(point) ) { if ( !first ) first = point; - + fit_count++; } - + /* if there is less than 2 fitted points in the contour, we'll */ /* simply scale and eventually translate the contour points */ if ( fit_count < 2 ) { if ( fit_count == 1 ) delta = first->cur_u - FT_MulFix( first->org_u, scale ); - + for ( point = start; point < next; point++ ) if ( point != first ) point->cur_u = FT_MulFix( point->org_u, scale ) + delta; - + goto Next_Contour; } - + /* there are more than 2 strong points in this contour, we'll */ /* need to interpolate weak points between them.. */ start = first; do { point = first; - + /* skip consecutive fitted points */ for (;;) { - next = first->next; + next = first->next; if ( next == start ) goto Next_Contour; - + if ( !psh2_point_is_fitted(next) ) break; - + first = next; } - + /* find next fitted point after unfitted one */ for (;;) { @@ -1349,7 +1352,7 @@ if ( psh2_point_is_fitted(next) ) break; } - + /* now interpolate between them */ { FT_Pos org_a, org_ab, cur_a, cur_ab; @@ -1370,17 +1373,17 @@ org_ab = first->org_u - org_a; cur_ab = first->cur_u - cur_a; } - + scale_ab = 0x10000L; if ( org_ab > 0 ) scale_ab = FT_DivFix( cur_ab, org_ab ); - + point = first->next; do { org_c = point->org_u; org_ac = org_c - org_a; - + if ( org_ac <= 0 ) { /* on the left of the interpolation zone */ @@ -1392,28 +1395,28 @@ cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale ); } else - { + { /* within the interpolation zone */ cur_c = cur_a + FT_MulFix( org_ac, scale_ab ); } - + point->cur_u = cur_c; - + point = point->next; } while ( point != next ); } - - /* keep going until all points in the contours have been processed */ + + /* keep going until all points in the contours have been processed */ first = next; } while ( first != start ); - + Next_Contour: ; } } - + /************************************************************************/ /************************************************************************/ /***** *****/ @@ -1421,7 +1424,7 @@ /***** *****/ /************************************************************************/ /************************************************************************/ - + FT_Error ps2_hints_apply( PS_Hints ps_hints, FT_Outline* outline, @@ -1436,7 +1439,7 @@ memory = globals->memory; FT_UNUSED(glyphrec); - + #ifdef DEBUG_HINTER if ( ps2_debug_glyph ) @@ -1444,23 +1447,23 @@ psh2_glyph_done( ps2_debug_glyph ); FREE( ps2_debug_glyph ); } - + if ( ALLOC( glyph, sizeof(*glyph) ) ) return error; - + ps2_debug_glyph = glyph; -#else - glyph = &glyphrec; +#else + glyph = &glyphrec; #endif error = psh2_glyph_init( glyph, outline, ps_hints, globals ); if (error) goto Exit; - + for ( dimension = 1; dimension >= 0; dimension-- ) { /* load outline coordinates into glyph */ psh2_glyph_load_points( glyph, dimension ); - + /* compute aligned stem/hints positions */ psh2_hint_table_align_hints( &glyph->hint_tables[dimension], glyph->globals, @@ -1471,13 +1474,13 @@ psh2_glyph_interpolate_strong_points( glyph, dimension ); psh2_glyph_interpolate_normal_points( glyph, dimension ); psh2_glyph_interpolate_other_points( glyph, dimension ); - + /* save hinted coordinates back to outline */ psh2_glyph_save_points( glyph, dimension ); } - - Exit: -#ifndef DEBUG_HINTER + + Exit: +#ifndef DEBUG_HINTER psh2_glyph_done( glyph ); #endif return error; diff --git a/src/pshinter/pshalgo2.h b/src/pshinter/pshalgo2.h index 575712cc3..d043a650f 100644 --- a/src/pshinter/pshalgo2.h +++ b/src/pshinter/pshalgo2.h @@ -31,11 +31,11 @@ FT_BEGIN_HEADER PSH2_HINT_GHOST = PS_HINT_FLAG_GHOST, PSH2_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM, PSH2_HINT_ACTIVE = 4, - PSH2_HINT_FITTED = 8 + PSH2_HINT_FITTED = 8 } PSH2_Hint_Flags; #define psh2_hint_is_active(x) (((x)->flags & PSH2_HINT_ACTIVE) != 0) -#define psh2_hint_is_ghost(x) (((x)->flags & PSH2_HINT_GHOST) != 0) +#define psh2_hint_is_ghost(x) (((x)->flags & PSH2_HINT_GHOST) != 0) #define psh2_hint_is_fitted(x) (((x)->flags & PSH2_HINT_FITTED) != 0) #define psh2_hint_activate(x) (x)->flags |= PSH2_HINT_ACTIVE @@ -51,7 +51,7 @@ FT_BEGIN_HEADER FT_UInt flags; PSH2_Hint parent; FT_Int order; - + } PSH2_HintRec; @@ -64,7 +64,7 @@ FT_BEGIN_HEADER FT_Fixed delta; FT_Pos min; FT_Pos max; - + } PSH2_ZoneRec, *PSH2_Zone; @@ -80,12 +80,13 @@ FT_BEGIN_HEADER PSH2_Zone zone; PS_Mask_Table hint_masks; PS_Mask_Table counter_masks; - + } PSH2_Hint_TableRec, *PSH2_Hint_Table; + typedef struct PSH2_PointRec_* PSH2_Point; typedef struct PSH2_ContourRec_* PSH2_Contour; - + enum { PSH2_DIR_NONE = 4, @@ -94,7 +95,7 @@ FT_BEGIN_HEADER PSH2_DIR_LEFT = -2, PSH2_DIR_RIGHT = 2 }; - + enum { PSH2_POINT_OFF = 1, /* point is off the curve */ @@ -124,10 +125,11 @@ FT_BEGIN_HEADER FT_Pos cur_y; FT_UInt flags_x; FT_UInt flags_y; -#endif - +#endif + } PSH2_PointRec; + #define psh2_point_is_strong(p) ((p)->flags & PSH2_POINT_STRONG) #define psh2_point_is_fitted(p) ((p)->flags & PSH2_POINT_FITTED) #define psh2_point_is_smooth(p) ((p)->flags & PSH2_POINT_SMOOTH) @@ -140,37 +142,37 @@ FT_BEGIN_HEADER { PSH2_Point start; FT_UInt count; - + } PSH2_ContourRec; - + typedef struct PSH2_GlyphRec_ { FT_UInt num_points; FT_UInt num_contours; - + PSH2_Point points; PSH2_Contour contours; - + FT_Memory memory; FT_Outline* outline; PSH_Globals globals; PSH2_Hint_TableRec hint_tables[2]; - + FT_Bool vertical; FT_Int major_dir; FT_Int minor_dir; - + } PSH2_GlyphRec, *PSH2_Glyph; -#ifdef DEBUG_HINTER +#ifdef DEBUG_HINTER extern PSH2_Hint_Table ps2_debug_hint_table; typedef void (*PSH2_HintFunc)( PSH2_Hint hint, FT_Bool vertical ); extern PSH2_HintFunc ps2_debug_hint_func; - + extern PSH2_Glyph ps2_debug_glyph; #endif diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c index 659dc4a1f..250d9c46c 100644 --- a/src/pshinter/pshrec.c +++ b/src/pshinter/pshrec.c @@ -1009,9 +1009,9 @@ } } -#ifdef DEBUG_VIEW +#ifdef DEBUG_HINTER if (!error) - the_ps_hints = hints; + ps_debug_hints = hints; #endif return error; } diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 031a1d970..155c35273 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -86,7 +86,7 @@ /* experimental support for gamma correction within the rasterizer */ -#define GRAYS_USE_GAMMA +#define xxxGRAYS_USE_GAMMA /*************************************************************************/ /* */ @@ -209,7 +209,7 @@ /* */ /* TYPE DEFINITIONS */ /* */ - + /* don't change the following types to FT_Int or FT_Pos, since we might */ /* need to define them to "float" or "double" when experimenting with */ /* new algorithms */ @@ -220,7 +220,7 @@ /* determine the type used to store cell areas. This normally takes at */ /* least PIXEL_BYTES*2 + 1. On 16-bit systems, we need to use `long' */ /* instead of `int', otherwise bad things happen */ - + #if PIXEL_BITS <= 7 typedef int TArea; @@ -1181,9 +1181,9 @@ /* start to a new position */ x = UPSCALE( to->x ); y = UPSCALE( to->y ); - + gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); - + ((PRaster)raster)->x = x; ((PRaster)raster)->y = y; return 0; @@ -1243,7 +1243,7 @@ #ifdef GRAYS_USE_GAMMA coverage = raster->gamma[(FT_Byte)coverage]; #endif - + if ( coverage ) #if 1 MEM_Set( p + spans->x, (unsigned char)coverage, spans->len ); @@ -1400,7 +1400,7 @@ if ( ras.num_cells == 0 ) return; - + cur = ras.cells; limit = cur + ras.num_cells; @@ -1748,7 +1748,7 @@ }; volatile int error = 0; - + if ( setjmp( ras.jump_buffer ) == 0 ) { error = FT_Outline_Decompose( &ras.outline, &interface, &ras ); @@ -1778,7 +1778,7 @@ /* clip to target bitmap, exit if nothing to do */ clip = &ras.clip_box; - + if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) return 0; @@ -1841,7 +1841,7 @@ #if 1 error = gray_convert_glyph_inner( RAS_VAR ); -#else +#else error = FT_Outline_Decompose( outline, &interface, &ras ) || gray_record_cell( RAS_VAR ); #endif @@ -1987,18 +1987,18 @@ grays_init_gamma( PRaster raster ) { FT_UInt x, a; - + for ( x = 0; x < 256; x++ ) { if ( x <= M_X ) a = (x * M_Y + (M_X/2)) / M_X; else a = M_Y + ((x-M_X)*(M_MAX-M_Y) + (M_MAX-M_X)/2)/(M_MAX-M_X); - + raster->gamma[x] = (FT_Byte)a; } } - + #endif /* GRAYS_USE_GAMMA */ #ifdef _STANDALONE_ @@ -2018,7 +2018,7 @@ #ifdef GRAYS_USE_GAMMA grays_init_gamma( (PRaster)*araster ); #endif - + return 0; } diff --git a/tests/gview.c b/tests/gview.c index 4c1df3741..8e1b2421c 100644 --- a/tests/gview.c +++ b/tests/gview.c @@ -74,6 +74,7 @@ static int option_show_blues = 0; static int option_show_edges = 0; static int option_show_segments = 1; static int option_show_links = 1; +static int option_show_indices = 0; static int option_show_ps_hints = 1; static int option_show_horz_hints = 1; @@ -112,7 +113,7 @@ static NV_Path symbol_rect_v = NULL; #define EDGE_COLOR 0xF0704070 #define SEGMENT_COLOR 0xF0206040 #define LINK_COLOR 0xF0FFFF00 -#define SERIF_LINK_COLOR 0xF0FF808F +#define SERIF_LINK_COLOR 0xF0FF808F /* print message and abort program */ static void @@ -160,15 +161,15 @@ done_symbols( void ) static void reset_scale( NV_Scale scale ) -{ +{ /* compute font units -> grid pixels scale factor */ glyph_scale = target->width*0.75 / face->units_per_EM * scale; - + /* setup font units -> grid pixels transform */ nv_transform_set_scale( &glyph_transform, glyph_scale, -glyph_scale ); glyph_org_x = glyph_transform.delta.x = target->width*0.125; glyph_org_y = glyph_transform.delta.y = target->height*0.875; - + /* setup subpixels -> grid pixels transform */ nv_transform_set_scale( &size_transform, glyph_scale/nv_fromfixed(face->size->metrics.x_scale), @@ -176,8 +177,8 @@ reset_scale( NV_Scale scale ) size_transform.delta = glyph_transform.delta; } - - + + static void reset_size( int pixel_size, NV_Scale scale ) { @@ -204,7 +205,7 @@ draw_grid( void ) if ( option_show_grid ) { NV_Scale min, max, x, step; - + /* draw vertical grid bars */ step = 64. * size_transform.matrix.xx; if (step > 1.) @@ -212,12 +213,12 @@ draw_grid( void ) min = max = glyph_org_x; while ( min - step >= 0 ) min -= step; while ( max + step < target->width ) max += step; - + for ( x = min; x <= max; x += step ) nv_pixmap_fill_rect( target, (NV_Int)(x+.5), 0, 1, target->height, GRID_COLOR ); } - + /* draw horizontal grid bars */ step = -64. * size_transform.matrix.yy; if (step > 1.) @@ -225,29 +226,29 @@ draw_grid( void ) min = max = glyph_org_y; while ( min - step >= 0 ) min -= step; while ( max + step < target->height ) max += step; - + for ( x = min; x <= max; x += step ) nv_pixmap_fill_rect( target, 0, (NV_Int)(x+.5), target->width, 1, GRID_COLOR ); } - } - + } + /* draw axis */ if ( option_show_axis ) { nv_pixmap_fill_rect( target, x, 0, 1, target->height, AXIS_COLOR ); nv_pixmap_fill_rect( target, 0, y, target->width, 1, AXIS_COLOR ); } - + if ( option_show_em ) { NV_Path path; NV_Path stroke; NV_UInt units = (NV_UInt)face->units_per_EM; - + nv_path_new_rectangle( renderer, 0, 0, units, units, 0, 0, &path ); nv_path_transform( path, &glyph_transform ); - + nv_path_stroke( path, 1.5, nv_path_linecap_butt, nv_path_linejoin_miter, 4.0, &stroke ); @@ -282,12 +283,12 @@ draw_ps_blue_zones( void ) FT_Int y1, y2; FT_UInt count; PSH_Blue_Zone zone; - + /* draw top zones */ table = &blues->normal_top; count = table->count; zone = table->zones; - + for ( ; count > 0; count--, zone++ ) { v.x = 0; @@ -302,7 +303,7 @@ draw_ps_blue_zones( void ) nv_vector_transform( &v, &glyph_transform ); } y1 = (int)(v.y + 0.5); - + v.x = 0; if ( !ps_debug_no_horz_hints ) { @@ -315,34 +316,34 @@ draw_ps_blue_zones( void ) nv_vector_transform( &v, &glyph_transform ); } y2 = (int)(v.y + 0.5); - + nv_pixmap_fill_rect( target, 0, y1, target->width, y2-y1+1, BLUES_TOP_COLOR ); -#if 0 +#if 0 printf( "top [%.3f %.3f]\n", zone->cur_bottom/64.0, zone->cur_top/64.0 ); -#endif +#endif } - - + + /* draw bottom zones */ table = &blues->normal_bottom; count = table->count; zone = table->zones; - + for ( ; count > 0; count--, zone++ ) { v.x = 0; v.y = zone->cur_ref; nv_vector_transform( &v, &size_transform ); y1 = (int)(v.y + 0.5); - + v.x = 0; v.y = zone->cur_ref + zone->cur_delta; nv_vector_transform( &v, &size_transform ); y2 = (int)(v.y + 0.5); - + nv_pixmap_fill_rect( target, 0, y1, target->width, y2-y1+1, BLUES_BOT_COLOR ); @@ -372,23 +373,23 @@ draw_ps1_hint( PSH1_Hint hint, FT_Bool vertical ) { int x1, x2; NV_Vector v; - - + + if ( pshint_vertical != vertical ) { if (vertical) pshint_cpos = 40; else pshint_cpos = 10; - + pshint_vertical = vertical; } - + if (vertical) { if ( !option_show_vert_hints ) return; - + v.x = hint->cur_pos; v.y = 0; nv_vector_transform( &v, &size_transform ); @@ -420,7 +421,7 @@ draw_ps1_hint( PSH1_Hint hint, FT_Bool vertical ) { if (!option_show_horz_hints) return; - + v.y = hint->cur_pos; v.x = 0; nv_vector_transform( &v, &size_transform ); @@ -452,7 +453,7 @@ draw_ps1_hint( PSH1_Hint hint, FT_Bool vertical ) #if 0 printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' ); #endif - + pshint_cpos += 10; } @@ -473,22 +474,22 @@ draw_ps2_hint( PSH2_Hint hint, FT_Bool vertical ) { int x1, x2; NV_Vector v; - + if ( pshint_vertical != vertical ) { if (vertical) pshint_cpos = 40; else pshint_cpos = 10; - + pshint_vertical = vertical; } - + if (vertical) { if ( !option_show_vert_hints ) return; - + v.x = hint->cur_pos; v.y = 0; nv_vector_transform( &v, &size_transform ); @@ -520,7 +521,7 @@ draw_ps2_hint( PSH2_Hint hint, FT_Bool vertical ) { if (!option_show_horz_hints) return; - + v.y = hint->cur_pos; v.x = 0; nv_vector_transform( &v, &size_transform ); @@ -552,7 +553,7 @@ draw_ps2_hint( PSH2_Hint hint, FT_Bool vertical ) #if 0 printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' ); #endif - + pshint_cpos += 10; } @@ -569,15 +570,15 @@ ps2_draw_control_points( void ) NV_Path vert_rect; NV_Path horz_rect; NV_Path dot, circle; - + for ( ; count > 0; count--, point++ ) { NV_Vector vec; - + vec.x = point->cur_x; vec.y = point->cur_y; nv_vector_transform( &vec, &size_transform ); - + nv_transform_set_translate( trans, vec.x, vec.y ); if ( option_show_smooth && !psh2_point_is_smooth(point) ) @@ -585,7 +586,7 @@ ps2_draw_control_points( void ) nv_painter_set_color( painter, SMOOTH_COLOR, 256 ); nv_painter_fill_path( painter, trans, 0, symbol_circle ); } - + if (option_show_horz_hints) { if ( point->flags_y & PSH2_POINT_STRONG ) @@ -594,7 +595,7 @@ ps2_draw_control_points( void ) nv_painter_fill_path( painter, trans, 0, symbol_rect_h ); } } - + if (option_show_vert_hints) { if ( point->flags_x & PSH2_POINT_STRONG ) @@ -607,6 +608,44 @@ ps2_draw_control_points( void ) } } + +static void +ps_print_hints( void ) +{ + if ( ps_debug_hints ) + { + FT_Int dimension; + PSH_Dimension dim; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + PS_Dimension dim = &ps_debug_hints->dimension[ dimension ]; + PS_Mask mask = dim->masks.masks; + FT_UInt count = dim->masks.num_masks; + + printf( "%s hints -------------------------\n", + dimension ? "vertical" : "horizontal" ); + + for ( ; count > 0; count--, mask++ ) + { + FT_UInt index; + + printf( "mask -> %d\n", mask->end_point ); + for ( index = 0; index < mask->num_bits; index++ ) + { + if ( mask->bytes[ index >> 3 ] & (0x80 >> (index & 7)) ) + { + PS_Hint hint = dim->hints.hints + index; + + printf( "%c [%3d %3d (%4d)]\n", dimension ? "v" : "h", + hint->pos, hint->pos + hint->len, hint->len ); + } + } + } + } + } +} + /************************************************************************/ /************************************************************************/ /***** *****/ @@ -628,7 +667,7 @@ ah_link_path( NV_Vector* p1, { p2.x = p4->x; p2.y = p1->y; - + p3.x = p1->x; p3.y = p4->y; } @@ -636,25 +675,25 @@ ah_link_path( NV_Vector* p1, { p2.x = p1->x; p2.y = p4->y; - + p3.x = p4->x; p3.y = p1->y; - } - + } + nv_path_writer_new( renderer, &writer ); nv_path_writer_moveto( writer, p1 ); nv_path_writer_cubicto( writer, &p2, &p3, p4 ); nv_path_writer_end( writer ); - + path = nv_path_writer_get_path( writer ); nv_path_writer_destroy( writer ); - + nv_path_stroke( path, 1., nv_path_linecap_butt, nv_path_linejoin_round, 1., &stroke ); - + nv_path_destroy( path ); - + return stroke; -} +} static void @@ -665,20 +704,20 @@ ah_draw_smooth_points( void ) AH_Outline* glyph = ah_debug_hinter->glyph; FT_UInt count = glyph->num_points; AH_Point* point = glyph->points; - + nv_painter_set_color( painter, SMOOTH_COLOR, 256 ); - + for ( ; count > 0; count--, point++ ) { if ( !( point->flags & ah_flag_weak_interpolation ) ) { NV_Transform transform, *trans = &transform; NV_Vector vec; - + vec.x = point->x - ah_debug_hinter->pp1.x; vec.y = point->y; nv_vector_transform( &vec, &size_transform ); - + nv_transform_set_translate( &transform, vec.x, vec.y ); nv_painter_fill_path( painter, trans, 0, symbol_circle ); } @@ -696,31 +735,31 @@ ah_draw_edges( void ) FT_UInt count; AH_Edge* edge; FT_Pos pp1 = ah_debug_hinter->pp1.x; - + nv_painter_set_color( painter, EDGE_COLOR, 256 ); if ( option_show_edges ) { /* draw verticla edges */ if ( option_show_vert_hints ) - { + { count = glyph->num_vedges; edge = glyph->vert_edges; for ( ; count > 0; count--, edge++ ) { NV_Vector vec; NV_Pos x; - + vec.x = edge->pos - pp1; vec.y = 0; - + nv_vector_transform( &vec, &size_transform ); x = (FT_Pos)( vec.x + 0.5 ); - + nv_pixmap_fill_rect( target, x, 0, 1, target->height, EDGE_COLOR ); } } - + /* draw horizontal edges */ if ( option_show_horz_hints ) { @@ -730,18 +769,18 @@ ah_draw_edges( void ) { NV_Vector vec; NV_Pos x; - + vec.x = 0; vec.y = edge->pos; - + nv_vector_transform( &vec, &size_transform ); x = (FT_Pos)( vec.y + 0.5 ); - + nv_pixmap_fill_rect( target, 0, x, target->width, 1, EDGE_COLOR ); } } } - + if ( option_show_segments ) { /* draw vertical segments */ @@ -749,18 +788,18 @@ ah_draw_edges( void ) { AH_Segment* seg = glyph->vert_segments; FT_UInt count = glyph->num_vsegments; - + for ( ; count > 0; count--, seg++ ) { AH_Point *first, *last; NV_Vector v1, v2; NV_Pos y1, y2, x; - + first = seg->first; last = seg->last; - + v1.x = v2.x = first->x - pp1; - + if ( first->y <= last->y ) { v1.y = first->y; @@ -771,35 +810,35 @@ ah_draw_edges( void ) v1.y = last->y; v2.y = first->y; } - + nv_vector_transform( &v1, &size_transform ); nv_vector_transform( &v2, &size_transform ); - + y1 = (NV_Pos)( v1.y + 0.5 ); y2 = (NV_Pos)( v2.y + 0.5 ); x = (NV_Pos)( v1.x + 0.5 ); - + nv_pixmap_fill_rect( target, x-1, y2, 3, ABS(y1-y2)+1, SEGMENT_COLOR ); } } - + /* draw horizontal segments */ if ( option_show_horz_hints ) { AH_Segment* seg = glyph->horz_segments; FT_UInt count = glyph->num_hsegments; - + for ( ; count > 0; count--, seg++ ) { AH_Point *first, *last; NV_Vector v1, v2; NV_Pos y1, y2, x; - + first = seg->first; last = seg->last; - + v1.y = v2.y = first->y; - + if ( first->x <= last->x ) { v1.x = first->x - pp1; @@ -810,14 +849,14 @@ ah_draw_edges( void ) v1.x = last->x - pp1; v2.x = first->x - pp1; } - + nv_vector_transform( &v1, &size_transform ); nv_vector_transform( &v2, &size_transform ); - + y1 = (NV_Pos)( v1.x + 0.5 ); y2 = (NV_Pos)( v2.x + 0.5 ); x = (NV_Pos)( v1.y + 0.5 ); - + nv_pixmap_fill_rect( target, y1, x-1, ABS(y1-y2)+1, 3, SEGMENT_COLOR ); } } @@ -827,13 +866,13 @@ ah_draw_edges( void ) { AH_Segment* seg = glyph->vert_segments; FT_UInt count = glyph->num_vsegments; - + for ( ; count > 0; count--, seg++ ) { AH_Segment* seg2 = NULL; NV_Path link; NV_Vector v1, v2; - + if ( seg->link ) { if ( seg->link > seg ) @@ -841,19 +880,19 @@ ah_draw_edges( void ) } else if ( seg->serif ) seg2 = seg->serif; - + if ( seg2 ) { v1.x = seg->first->x - pp1; v2.x = seg2->first->x - pp1; v1.y = (seg->first->y + seg->last->y)/2; v2.y = (seg2->first->y + seg2->last->y)/2; - + link = ah_link_path( &v1, &v2, 1 ); - + nv_painter_set_color( painter, seg->serif ? SERIF_LINK_COLOR : LINK_COLOR, 256 ); nv_painter_fill_path( painter, &size_transform, 0, link ); - + nv_path_destroy( link ); } } @@ -863,13 +902,13 @@ ah_draw_edges( void ) { AH_Segment* seg = glyph->horz_segments; FT_UInt count = glyph->num_hsegments; - + for ( ; count > 0; count--, seg++ ) { AH_Segment* seg2 = NULL; NV_Path link; NV_Vector v1, v2; - + if ( seg->link ) { if ( seg->link > seg ) @@ -877,19 +916,19 @@ ah_draw_edges( void ) } else if ( seg->serif ) seg2 = seg->serif; - + if ( seg2 ) { v1.y = seg->first->y; v2.y = seg2->first->y; v1.x = (seg->first->x + seg->last->x)/2 - pp1; v2.x = (seg2->first->x + seg2->last->x)/2 - pp1; - + link = ah_link_path( &v1, &v2, 0 ); - + nv_painter_set_color( painter, seg->serif ? SERIF_LINK_COLOR : LINK_COLOR, 256 ); nv_painter_fill_path( painter, &size_transform, 0, link ); - + nv_path_destroy( link ); } } @@ -912,7 +951,7 @@ draw_glyph( int glyph_index ) NV_Path path; pshint_vertical = -1; - + ps1_debug_hint_func = option_show_ps_hints ? draw_ps1_hint : 0; ps2_debug_hint_func = option_show_ps_hints ? draw_ps2_hint : 0; @@ -922,16 +961,16 @@ draw_glyph( int glyph_index ) ? FT_LOAD_NO_BITMAP : FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING ); if (error) Panic( "could not load glyph" ); - + if ( face->glyph->format != ft_glyph_format_outline ) Panic( "could not load glyph outline" ); - + error = nv_path_new_from_outline( renderer, (NV_Outline*)&face->glyph->outline, &size_transform, &path ); if (error) Panic( "could not create glyph path" ); - + /* tracé du glyphe plein */ if ( option_show_glyph ) { @@ -942,16 +981,16 @@ draw_glyph( int glyph_index ) if ( option_show_stroke ) { NV_Path stroke; - + error = nv_path_stroke( path, 0.6, nv_path_linecap_butt, nv_path_linejoin_miter, 1.0, &stroke ); if (error) Panic( "could not stroke glyph path" ); - + nv_painter_set_color ( painter, 0xFF000040, 256 ); nv_painter_fill_path ( painter, 0, 0, stroke ); - + nv_path_destroy( stroke ); } @@ -964,7 +1003,7 @@ draw_glyph( int glyph_index ) NV_Int n, first, last; nv_path_get_outline( path, NULL, memory, &out ); - + first = 0; for ( n = 0; n < out.n_contours; n++ ) { @@ -972,47 +1011,55 @@ draw_glyph( int glyph_index ) NV_Transform trans; NV_Color color; NV_SubVector* vec; - + last = out.contours[n]; - + for ( m = first; m <= last; m++ ) { color = (out.tags[m] & FT_Curve_Tag_On) ? ON_COLOR : OFF_COLOR; - + vec = out.points + m; - nv_transform_set_translate( &trans, vec->x/64.0, vec->y/64.0 ); + nv_transform_set_translate( &trans, vec->x/64.0, vec->y/64.0 ); nv_painter_set_color( painter, color, 256 ); nv_painter_fill_path( painter, &trans, 0, symbol_dot ); + if ( option_show_indices ) + { + char temp[5]; + + sprintf( temp, "%d", m ); + nv_pixmap_cell_text( target, vec->x/64 + 4, vec->y/64 - 4, + temp, TEXT_COLOR ); + } } - + first = last + 1; } } ah_draw_smooth_points(); ah_draw_edges(); - + nv_path_destroy( path ); - + /* autre infos */ { char temp[1024]; char temp2[64]; - + sprintf( temp, "font name : %s (%s)", face->family_name, face->style_name ); nv_pixmap_cell_text( target, 0, 0, temp, TEXT_COLOR ); - + FT_Get_Glyph_Name( face, glyph_index, temp2, 63 ); temp2[63] = 0; - + sprintf( temp, "glyph %4d: %s", glyph_index, temp2 ); nv_pixmap_cell_text( target, 0, 8, temp, TEXT_COLOR ); - + if ( temp_message[0] ) { nv_pixmap_cell_text( target, 0, 16, temp_message, TEXT_COLOR ); @@ -1040,7 +1087,7 @@ draw_glyph( int glyph_index ) break; \ } - + static void handle_event( NVV_EventRec* ev ) { @@ -1065,23 +1112,23 @@ handle_event( NVV_EventRec* ev ) case NVV_KEY('s'): TOGGLE_OPTION( option_show_stroke, "glyph stroke display" ) - + case NVV_KEY('g'): TOGGLE_OPTION( option_show_glyph, "glyph fill display" ) - + case NVV_KEY('d'): TOGGLE_OPTION( option_show_dots, "control points display" ) - + case NVV_KEY('e'): TOGGLE_OPTION( option_show_em, "EM square display" ) - + case NVV_KEY('+'): { grid_scale *= 1.2; reset_scale( grid_scale ); break; } - + case NVV_KEY('-'): { if (grid_scale > 0.3) @@ -1126,12 +1173,19 @@ handle_event( NVV_EventRec* ev ) case NVV_KEY('S'): TOGGLE_OPTION( option_show_smooth, "smooth points display" ); + case NVV_KEY('i'): + TOGGLE_OPTION( option_show_indices, "point index display" ); + case NVV_KEY('b'): TOGGLE_OPTION( option_show_blues, "blue zones display" ); case NVV_KEY('h'): TOGGLE_OPTION( option_hinting, "hinting" ) - + + case NVV_KEY('H'): + ps_print_hints(); + break; + default: ; } @@ -1166,7 +1220,7 @@ parse_options( int* argc_p, char*** argv_p ) { int argc = *argc_p; char** argv = *argv_p; - + while (argc > 2 && argv[1][0] == '-') { switch (argv[1][1]) @@ -1174,28 +1228,28 @@ parse_options( int* argc_p, char*** argv_p ) OPTION2( 'f', first_glyph = atoi( argv[2] ); ) OPTION2( 's', pixel_size = atoi( argv[2] ); ) - + default: usage(); } } - + *argc_p = argc; *argv_p = argv; } - - + + int main( int argc, char** argv ) { char* filename = "/winnt/fonts/arial.ttf"; - + parse_options( &argc, &argv ); - + if ( argc >= 2 ) filename = argv[1]; - - + + /* create library */ error = nv_renderer_new( 0, &renderer ); if (error) Panic( "could not create Nirvana renderer" ); @@ -1205,7 +1259,7 @@ int main( int argc, char** argv ) error = nvv_display_new( renderer, &display ); if (error) Panic( "could not create display" ); - + error = nvv_surface_new( display, 460, 460, nv_pixmap_type_argb, &surface ); if (error) Panic( "could not create surface" ); @@ -1213,26 +1267,26 @@ int main( int argc, char** argv ) error = nv_painter_new( renderer, &painter ); if (error) Panic( "could not create painter" ); - + nv_painter_set_target( painter, target ); - + clear_background(); error = FT_Init_FreeType( &freetype ); if (error) Panic( "could not initialise FreeType" ); - + error = FT_New_Face( freetype, filename, 0, &face ); if (error) Panic( "could not open font face" ); reset_size( pixel_size, grid_scale ); - + nvv_surface_set_title( surface, "FreeType Glyph Viewer" ); { NVV_EventRec event; - glyph_index = first_glyph; + glyph_index = first_glyph; for ( ;; ) { clear_background(); @@ -1247,29 +1301,29 @@ int main( int argc, char** argv ) draw_ps_blue_zones(); draw_glyph( glyph_index ); ps2_draw_control_points(); - + nvv_surface_refresh( surface, NULL ); nvv_surface_listen( surface, 0, &event ); if ( event.key == NVV_Key_Esc ) break; - + handle_event( &event ); switch (event.key) { case NVV_Key_Esc: goto Exit; - + default: ; } } } - + Exit: /* wait for escape */ - - + + /* destroy display (and surface) */ nvv_display_unref( display );