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