diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/extras/freetype2/tests | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/extras/freetype2/tests')
-rw-r--r-- | nx-X11/extras/freetype2/tests/Jamfile | 41 | ||||
-rw-r--r-- | nx-X11/extras/freetype2/tests/gview.c | 1292 |
2 files changed, 1333 insertions, 0 deletions
diff --git a/nx-X11/extras/freetype2/tests/Jamfile b/nx-X11/extras/freetype2/tests/Jamfile new file mode 100644 index 000000000..0470922de --- /dev/null +++ b/nx-X11/extras/freetype2/tests/Jamfile @@ -0,0 +1,41 @@ +# FreeType 2 src Jamfile (c) 2001 David Turner +# + +SubDir FT2_TOP tests ; + +test_programs = gview ; + +SubDirHdrs [ FT2_SubDir .. nirvana include ] ; + +NV_TOP = [ FT2_SubDir .. .. nirvana ] ; + +NIRVANA_LINKLIBS = $(NV_TOP)/objs/libnirvana$(SUFLIB) ; + +{ + local t ; + + for t in $(test_programs) + { + Main $(t) : $(t).c ; + + LinkLibraries $(t) : $(FT2_LIB) ; + + if $(WIN) + { + if $(TOOLSET) = MINGW + { + LINKKLIBS on $(t)$(SUFEXE) = "-luser32 -lgdi32" ; + } + else + { + LINKLIBS on $(t)$(SUFEXE) = user32.lib gdi32.lib ; + } + } + else + { + LINKLIBS on $(t)$(SUFEXE) = -L/usr/X11R6/lib -lX11 -lm ; + } + + NEEDLIBS on $(t)$(SUFEXE) += $(NIRVANA_LINKLIBS) ; + } +} diff --git a/nx-X11/extras/freetype2/tests/gview.c b/nx-X11/extras/freetype2/tests/gview.c new file mode 100644 index 000000000..f68598512 --- /dev/null +++ b/nx-X11/extras/freetype2/tests/gview.c @@ -0,0 +1,1292 @@ +#include <nirvana.h> +#include NV_VIEWPORT_H +#include <stdio.h> + +#include <ft2build.h> +#include FT_FREETYPE_H + +/* include FreeType internals to debug hints */ +#include <../src/pshinter/pshrec.h> +#include <../src/pshinter/pshalgo.h> + +#include <../src/autohint/ahtypes.h> + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** ROOT DEFINITIONS *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + + +#include <time.h> /* for clock() */ + + /* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */ + /* to get the HZ macro which is the equivalent. */ +#if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 ) +#include <sys/param.h> +#define CLOCKS_PER_SEC HZ +#endif + +static int first_glyph = 0; + +static NV_Renderer renderer; +static NV_Painter painter; +static NV_Pixmap target; +static NV_Error error; +static NV_Memory memory; +static NVV_Display display; +static NVV_Surface surface; + +static FT_Library freetype; +static FT_Face face; + + +static NV_Pos glyph_scale; +static NV_Pos glyph_org_x; +static NV_Pos glyph_org_y; +static NV_Transform glyph_transform; /* font units -> device pixels */ +static NV_Transform size_transform; /* subpixels -> device pixels */ + +static NV_Scale grid_scale = 1.0; + +static int glyph_index; +static int pixel_size = 12; + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** OPTIONS, COLORS and OTHERS *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +static int option_show_axis = 1; +static int option_show_dots = 1; +static int option_show_stroke = 0; +static int option_show_glyph = 1; +static int option_show_grid = 1; +static int option_show_em = 0; +static int option_show_smooth = 1; +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; +static int option_show_vert_hints = 1; + + +static int option_hinting = 1; + +static char temp_message[1024]; + +static NV_Path symbol_dot = NULL; +static NV_Path symbol_circle = NULL; +static NV_Path symbol_square = NULL; +static NV_Path symbol_rect_h = NULL; +static NV_Path symbol_rect_v = NULL; + + + +#define AXIS_COLOR 0xFFFF0000 +#define GRID_COLOR 0xFFD0D0D0 +#define ON_COLOR 0xFFFF2000 +#define OFF_COLOR 0xFFFF0080 +#define STRONG_COLOR 0xFF404040 +#define INTERP_COLOR 0xFF206040 +#define SMOOTH_COLOR 0xF000B040 +#define BACKGROUND_COLOR 0xFFFFFFFF +#define TEXT_COLOR 0xFF000000 +#define EM_COLOR 0x80008000 +#define BLUES_TOP_COLOR 0x4000008F +#define BLUES_BOT_COLOR 0x40008F00 + +#define GHOST_HINT_COLOR 0xE00000FF +#define STEM_HINT_COLOR 0xE02020FF +#define STEM_JOIN_COLOR 0xE020FF20 + +#define EDGE_COLOR 0xF0704070 +#define SEGMENT_COLOR 0xF0206040 +#define LINK_COLOR 0xF0FFFF00 +#define SERIF_LINK_COLOR 0xF0FF808F + + +/* print message and abort program */ +static void +Panic( const char* message ) +{ + fprintf( stderr, "PANIC: %s\n", message ); + exit(1); +} + + +static void +init_symbols( void ) +{ + nv_path_new_rectangle( renderer, -1, -1, 3, 3, 0, 0, &symbol_square ); + nv_path_new_rectangle( renderer, -1, -6, 2, 12, 0, 0, &symbol_rect_v ); + nv_path_new_rectangle( renderer, -6, -1, 12, 2, 0, 0, &symbol_rect_h ); + + nv_path_new_circle( renderer, 0, 0, 3., &symbol_dot ); + + nv_path_stroke( symbol_dot, 0.6, + nv_path_linecap_butt, + nv_path_linejoin_miter, 1., + &symbol_circle ); + + nv_path_destroy( symbol_dot ); + + nv_path_new_circle( renderer, 0, 0, 2., &symbol_dot ); + } + + +static void +done_symbols( void ) +{ + nv_path_destroy( symbol_circle ); + nv_path_destroy( symbol_dot ); + nv_path_destroy( symbol_rect_v ); + nv_path_destroy( symbol_rect_h ); + nv_path_destroy( symbol_square ); +} + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** COMMON GRID DRAWING ROUTINES *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +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 ), + -glyph_scale / nv_fromfixed( face->size->metrics.y_scale ) ); + + size_transform.delta = glyph_transform.delta; +} + + +static void +reset_size( int pixel_size, + NV_Scale scale ) +{ + FT_Set_Pixel_Sizes( face, pixel_size, pixel_size ); + reset_scale( scale ); +} + + +static void +clear_background( void ) +{ + nv_pixmap_fill_rect( target, 0, 0, target->width, target->height, + BACKGROUND_COLOR ); +} + + +static void +draw_grid( void ) +{ + int x = (int)glyph_org_x; + int y = (int)glyph_org_y; + + + /* draw grid */ + if ( option_show_grid ) + { + NV_Scale min, max, x, step; + + + /* draw vertical grid bars */ + step = 64. * size_transform.matrix.xx; + if ( step > 1. ) + { + 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. ) + { + 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 ); + + nv_painter_set_color( painter, EM_COLOR, 256 ); + nv_painter_fill_path( painter, NULL, 0, stroke ); + + nv_path_destroy( stroke ); + nv_path_destroy( path ); + } + +} + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** POSTSCRIPT GLOBALS ROUTINES *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +#include <../src/pshinter/pshglob.h> + +static void +draw_ps_blue_zones( void ) +{ + if ( option_show_blues && ps_debug_globals ) + { + PSH_Blues blues = &ps_debug_globals->blues; + PSH_Blue_Table table; + NV_Vector v; + 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; + if ( !ps_debug_no_horz_hints ) + { + v.y = zone->cur_ref + zone->cur_delta; + nv_vector_transform( &v, &size_transform ); + } + else + { + v.y = zone->org_ref + zone->org_delta; + nv_vector_transform( &v, &glyph_transform ); + } + y1 = (int)(v.y + 0.5); + + v.x = 0; + if ( !ps_debug_no_horz_hints ) + { + v.y = zone->cur_ref; + nv_vector_transform( &v, &size_transform ); + } + else + { + v.y = zone->org_ref; + 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 + printf( "top [%.3f %.3f]\n", zone->cur_bottom/64.0, zone->cur_top/64.0 ); +#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 ); + +#if 0 + printf( "bot [%.3f %.3f]\n", zone->cur_bottom/64.0, zone->cur_top/64.0 ); +#endif + } + } +} + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** POSTSCRIPT HINTER ALGORITHM ROUTINES *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +#include <../src/pshinter/pshalgo.h> + +static void +draw_ps_hint( PSH_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 ); + x1 = (int)(v.x + 0.5); + + v.x = hint->cur_pos + hint->cur_len; + v.y = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.x + 0.5); + + nv_pixmap_fill_rect( target, x1, 0, 1, target->height, + psh_hint_is_ghost( hint ) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh_hint_is_ghost( hint ) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, x2, 0, 1, target->height, + psh_hint_is_ghost( hint ) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, x1, pshint_cpos, x2 + 1 - x1, 1, + STEM_JOIN_COLOR ); + } + else + { + if ( !option_show_horz_hints ) + return; + + v.y = hint->cur_pos; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x1 = (int)(v.y + 0.5); + + v.y = hint->cur_pos + hint->cur_len; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.y + 0.5); + + nv_pixmap_fill_rect( target, 0, x1, target->width, 1, + psh_hint_is_ghost( hint ) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh_hint_is_ghost( hint ) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, 0, x2, target->width, 1, + psh_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1 + 1 - x2, + STEM_JOIN_COLOR ); + } + +#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; +} + + +static void +ps_draw_control_points( void ) +{ + if ( ps_debug_glyph ) + { + PSH_Glyph glyph = ps_debug_glyph; + PSH_Point point = glyph->points; + FT_UInt count = glyph->num_points; + NV_Transform transform, *trans = &transform; + 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 && !psh_point_is_smooth(point) ) + { + 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 & PSH_POINT_STRONG ) + { + nv_painter_set_color( painter, STRONG_COLOR, 256 ); + nv_painter_fill_path( painter, trans, 0, symbol_rect_h ); + } + } + + if ( option_show_vert_hints ) + { + if ( point->flags_x & PSH_POINT_STRONG ) + { + nv_painter_set_color( painter, STRONG_COLOR, 256 ); + nv_painter_fill_path( painter, trans, 0, symbol_rect_v ); + } + } + } + } +} + + +static void +ps_print_hints( void ) +{ + if ( ps_debug_hints ) + { + FT_Int dimension; + + + 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 ); + } + } + } + } + } +} + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** AUTOHINTER DRAWING ROUTINES *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +static NV_Path +ah_link_path( NV_Vector* p1, + NV_Vector* p4, + NV_Bool vertical ) +{ + NV_PathWriter writer; + NV_Vector p2, p3; + NV_Path path, stroke; + + + if ( vertical ) + { + p2.x = p4->x; + p2.y = p1->y; + + p3.x = p1->x; + p3.y = p4->y; + } + else + { + 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 +ah_draw_smooth_points( void ) +{ + if ( ah_debug_hinter && option_show_smooth ) + { + 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 ); + } + } + } +} + + +static void +ah_draw_edges( void ) +{ + if ( ah_debug_hinter ) + { + AH_Outline glyph = ah_debug_hinter->glyph; + 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 vertical 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 ) + { + count = glyph->num_hedges; + edge = glyph->horz_edges; + for ( ; count > 0; count--, edge++ ) + { + 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 */ + if ( option_show_vert_hints ) + { + AH_Segment seg = glyph->vert_segments; + FT_UInt count = glyph->num_vsegments; + + + for ( ; count > 0; count--, seg++ ) + { + AH_PointRec *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; + v2.y = last->y; + } + else + { + 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, + FT_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_PointRec *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; + v2.x = last->x - pp1; + } + else + { + 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, + FT_ABS( y1 - y2 ) + 1, 3, SEGMENT_COLOR ); + } + } + + if ( option_show_vert_hints && option_show_links ) + { + 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 ) + seg2 = seg->link; + } + 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 ); + } + } + } + + if ( option_show_horz_hints && option_show_links ) + { + 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 ) + seg2 = seg->link; + } + 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 ); + } + } + } + } + } +} + + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** MAIN LOOP(S) *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +static void +draw_glyph( int glyph_index ) +{ + NV_Path path; + + + pshint_vertical = -1; + + ps_debug_hint_func = option_show_ps_hints ? draw_ps_hint : 0; + + ah_debug_hinter = NULL; + + error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_BITMAP ); + 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 ) + { + nv_painter_set_color( painter, 0xFF404080, 128 ); + nv_painter_fill_path( painter, 0, 0, path ); + } + + 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 ); + } + + /* tracé des points de controle */ + if ( option_show_dots ) + { + NV_Path plot; + NV_Outline out; + NV_Scale r = 2; + NV_Int n, first, last; + + + nv_path_get_outline( path, NULL, memory, &out ); + + first = 0; + for ( n = 0; n < out.n_contours; n++ ) + { + int m; + 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_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 ); + temp_message[0] = 0; + } + } +} + + +#define TOGGLE_OPTION(var,prefix) \ + do \ + { \ + var = !var; \ + sprintf( temp_message, prefix " is now %s", \ + var ? "on" : "off" ); \ + } \ + while() + + +#define TOGGLE_OPTION_NEG(var,prefix) \ + do \ + { \ + var = !var; \ + sprintf( temp_message, prefix " is now %s", \ + !var ? "on" : "off" ); \ + } \ + while + + +static void +handle_event( NVV_EventRec* ev ) +{ + switch ( ev->key ) + { + case NVV_Key_Left: + if ( glyph_index > 0 ) + glyph_index--; + break; + + case NVV_Key_Right: + if ( glyph_index + 1 < face->num_glyphs ) + glyph_index++; + break; + + case NVV_KEY( 'x' ): + TOGGLE_OPTION( option_show_axis, "grid axis display" ); + break; + + case NVV_KEY( 's' ): + TOGGLE_OPTION( option_show_stroke, "glyph stroke display" ); + break; + + case NVV_KEY( 'g' ): + TOGGLE_OPTION( option_show_glyph, "glyph fill display" ); + break; + + case NVV_KEY( 'd' ): + TOGGLE_OPTION( option_show_dots, "control points display" ); + break + + case NVV_KEY( 'e' ): + TOGGLE_OPTION( option_show_em, "EM square display" ); + break; + + case NVV_KEY( '+' ): + grid_scale *= 1.2; + reset_scale( grid_scale ); + break; + + case NVV_KEY( '-' ): + if ( grid_scale > 0.3 ) + { + grid_scale /= 1.2; + reset_scale( grid_scale ); + } + break; + + case NVV_Key_Up: + pixel_size++; + reset_size( pixel_size, grid_scale ); + sprintf( temp_message, "pixel size = %d", pixel_size ); + break; + + case NVV_Key_Down: + if ( pixel_size > 1 ) + { + pixel_size--; + reset_size( pixel_size, grid_scale ); + sprintf( temp_message, "pixel size = %d", pixel_size ); + } + break; + + case NVV_KEY( 'z' ): + TOGGLE_OPTION_NEG( ps_debug_no_vert_hints, "vertical hints processing" ); + break; + + case NVV_KEY( 'a' ): + TOGGLE_OPTION_NEG( ps_debug_no_horz_hints, "horizontal hints processing" ); + break; + + case NVV_KEY( 'Z' ): + TOGGLE_OPTION( option_show_vert_hints, "vertical hints display" ); + break; + + case NVV_KEY( 'A' ): + TOGGLE_OPTION( option_show_horz_hints, "horizontal hints display" ); + break; + + case NVV_KEY( 'S' ): + TOGGLE_OPTION( option_show_smooth, "smooth points display" ); + break; + + case NVV_KEY( 'i' ): + TOGGLE_OPTION( option_show_indices, "point index display" ); + break; + + case NVV_KEY( 'b' ): + TOGGLE_OPTION( option_show_blues, "blue zones display" ); + break; + + case NVV_KEY( 'h' ): + ps_debug_no_horz_hints = option_hinting; + ps_debug_no_vert_hints = option_hinting; + + TOGGLE_OPTION( option_hinting, "hinting" ); + break; + + case NVV_KEY( 'H' ): + ps_print_hints(); + break; + + default: + ; + } +} + + +static void +usage() +{ + Panic( "no usage" ); +} + + +#define OPTION1(n,code) \ + case n : \ + code \ + argc--; \ + argv++; \ + break; + +#define OPTION2(n,code) \ + case n : \ + code \ + argc -= 2; \ + argv += 2; \ + break; + + +static void +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] ) + { + 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" ); + + memory = nv_renderer_get_memory( renderer ); + init_symbols(); + + 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" ); + + target = nvv_surface_get_pixmap( surface ); + + 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 initialize 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; + for ( ;; ) + { + clear_background(); + draw_grid(); + + ps_debug_hints = 0; + ah_debug_hinter = 0; + + ah_debug_disable_vert = ps_debug_no_vert_hints; + ah_debug_disable_horz = ps_debug_no_horz_hints; + + draw_ps_blue_zones(); + draw_glyph( glyph_index ); + ps_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 ); + + done_symbols(); + nv_renderer_unref( renderer ); + + return 0; +} |