1216 lines
34 KiB
C
1216 lines
34 KiB
C
/***************************************************************************/
|
|
/* */
|
|
/* gxdemo.c */
|
|
/* */
|
|
/* Demo program for AAT/TrueTypeGX font driver implementation (body). */
|
|
/* */
|
|
/* Copyright 2003 by */
|
|
/* Masatake YAMATO and Redhat K.K. */
|
|
/* */
|
|
/* This file may only be used, */
|
|
/* modified, and distributed under the terms of the FreeType project */
|
|
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
|
|
/* this file you indicate that you have read the license and */
|
|
/* understand and accept it fully. */
|
|
/* */
|
|
/***************************************************************************/
|
|
|
|
/***************************************************************************/
|
|
/* Development of the code in this file is support of */
|
|
/* Information-technology Promotion Agency, Japan. */
|
|
/***************************************************************************/
|
|
|
|
#define _XOPEN_SOURCE
|
|
#include <stdlib.h>
|
|
|
|
#include <ft2build.h>
|
|
#include FT_GXLAYOUT_H
|
|
#include FT_BBOX_H
|
|
#include FT_OUTLINE_H
|
|
#include FT_INTERNAL_DEBUG_H
|
|
|
|
#include <stdio.h>
|
|
#include <popt.h>
|
|
#include <glib.h>
|
|
#include <glib/gslist.h>
|
|
#include <glib-object.h>
|
|
#include <gtk/gtk.h>
|
|
#include <errno.h>
|
|
#include <libgnomecanvas/libgnomecanvas.h>
|
|
|
|
#include "gxdump.h"
|
|
#include "gxfeatreg.h"
|
|
#include "gxtypes.h"
|
|
#include "gxload.h"
|
|
#include "gxaccess.h"
|
|
|
|
#define DEFAULT_UNIT 1024
|
|
#define BUFFER_LENGTH 1024
|
|
|
|
static char buffer[BUFFER_LENGTH];
|
|
static GHashTable * setting_buttons = NULL;
|
|
static gulong dump_flags = GX_DUMP_mort|GX_DUMP_morx|GX_DUMP_feat|GX_DUMP_kern;
|
|
static gboolean dump_glyph_metrics = FALSE;
|
|
static GtkAdjustment * gid_spinner_adj;
|
|
static GtkWidget *glyph_canvas;
|
|
|
|
static GnomeCanvasItem *root_rect_item = NULL;
|
|
static GnomeCanvasItem *bbox_item = NULL;
|
|
static GnomeCanvasItem *h_advance_item = NULL;
|
|
static GnomeCanvasItem *v_advance_item = NULL;
|
|
static GnomeCanvasItem *pixbuf_item = NULL;
|
|
static GSList *div_items = NULL;
|
|
|
|
static int default_gid = 19;
|
|
|
|
void create_window ( GX_Face face );
|
|
void destroy_window ( GtkObject * unused, GXL_FeaturesRequest request );
|
|
|
|
void radio_toggled( GtkToggleButton * toggle, gpointer setting );
|
|
void check_toggled( GtkToggleButton * toggle, gpointer setting);
|
|
void run_layout_engine ( GtkButton * button, gpointer request );
|
|
void reset_feature_request( GtkButton * button, gpointer request );
|
|
void check_table ( GtkToggleButton * toggle_button, gpointer flag);
|
|
void dump_feature_request( GtkButton * button, gpointer request );
|
|
void dump_feature_registry( GtkButton * button, gpointer request );
|
|
void dump_language_id ( GtkButton * button, gpointer face );
|
|
|
|
void horizontal_radio_toggled( GtkToggleButton * toggle, gpointer request );
|
|
void vertical_radio_toggled( GtkToggleButton * toggle, gpointer request );
|
|
|
|
void dump_file(FT_Library library, const char * file, gint verbose);
|
|
void dump_face(FT_Face face, const char* file, gint verbose);
|
|
void dump_glyph(FT_Face face, FT_UShort gid, FTL_Direction direction);
|
|
|
|
void activate_chain_trace( void );
|
|
|
|
void set_dump_glyph_metrics ( GtkWidget * check_button, gpointer data );
|
|
void render_glyph ( GtkWidget * button, gpointer request );
|
|
|
|
void set_trace_level( GtkAdjustment * adj, gpointer trace );
|
|
|
|
#define DUMP_DESC "Supported tables are mort,morx,feat,prop,trak,kern,just,lcar,opbd,bsln,fmtx,fdsc"
|
|
static const GDebugKey dump_keys[] = {
|
|
{"mort", GX_DUMP_mort},
|
|
{"morx", GX_DUMP_morx},
|
|
{"feat", GX_DUMP_feat},
|
|
{"prop", GX_DUMP_prop},
|
|
{"trak", GX_DUMP_trak},
|
|
{"kern", GX_DUMP_kern},
|
|
{"just", GX_DUMP_just},
|
|
{"lcar", GX_DUMP_lcar},
|
|
{"opbd", GX_DUMP_opbd},
|
|
{"bsln", GX_DUMP_bsln},
|
|
{"fmtx", GX_DUMP_fmtx},
|
|
{"fdsc", GX_DUMP_fdsc},
|
|
};
|
|
|
|
int
|
|
main(int argc, char ** argv)
|
|
{
|
|
FT_Library library;
|
|
FT_Face face;
|
|
poptContext optCon;
|
|
int rc;
|
|
const char * file;
|
|
|
|
static char* arg_debug = NULL;
|
|
static int arg_batch = 0;
|
|
static int arg_memprof = 0;
|
|
static int arg_verbose = 0;
|
|
static int arg_trace_chain = 0;
|
|
|
|
const int ndump_keys = sizeof(dump_keys)/sizeof(GDebugKey);
|
|
struct poptOption optTable [] = {
|
|
{ "trace-chain", '\0', POPT_ARG_NONE, &arg_trace_chain, 0, "Dump chains selection", ""},
|
|
{ "default-gid", '\0', POPT_ARG_INT, &default_gid, 0, "Default GID", ""},
|
|
{ "batch", 'b', POPT_ARG_NONE, &arg_batch, 0, "batch mode", ""},
|
|
{ "table", 't', POPT_ARG_STRING, &arg_debug, 0, DUMP_DESC, "tableName"},
|
|
{ "memprof", 'm', POPT_ARG_NONE, &arg_memprof, 0, "Enter to infinite loop to run under memprof", ""},
|
|
{ "verbose", 'v', POPT_ARG_NONE, &arg_verbose, 0, "Print extra infomation to stdout", ""},
|
|
POPT_AUTOHELP
|
|
POPT_TABLEEND
|
|
};
|
|
FTL_EngineType engine_type;
|
|
|
|
gtk_init(&argc, &argv);
|
|
optCon = poptGetContext(argv[0], argc, (const char **)argv, optTable, 0);
|
|
poptSetOtherOptionHelp(optCon, "[options] gxfont\n");
|
|
rc = poptReadDefaultConfig (optCon, 0);
|
|
if (rc < 0)
|
|
{
|
|
fprintf(stderr, "Fail to read .popt config file: %s\n",
|
|
poptStrerror(rc));
|
|
exit (1);
|
|
}
|
|
while ((rc = poptGetNextOpt(optCon)) > 0)
|
|
if (rc != -1)
|
|
{
|
|
fprintf(stderr, "Bad argument %s: %s\n",
|
|
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
|
|
poptStrerror(rc));
|
|
exit (1);
|
|
}
|
|
|
|
if (arg_trace_chain)
|
|
activate_chain_trace();
|
|
|
|
if (FT_Init_FreeType (&library))
|
|
{
|
|
fprintf(stderr, "Error in %s\n", "FT_Init_FreeType");
|
|
exit (1);
|
|
}
|
|
|
|
if (arg_debug)
|
|
dump_flags = g_parse_debug_string (arg_debug,
|
|
(GDebugKey *) dump_keys,
|
|
ndump_keys);
|
|
|
|
file = poptGetArg(optCon);
|
|
if (!file)
|
|
{
|
|
poptPrintHelp(optCon, stderr, 0);
|
|
exit(1);
|
|
}
|
|
|
|
if ( arg_batch )
|
|
{
|
|
fprintf(stdout, "<meta>\n");
|
|
do {
|
|
dump_file( library, file, arg_verbose );
|
|
file = poptGetArg(optCon);
|
|
} while (file);
|
|
fprintf(stdout, "</meta>\n");
|
|
goto Exit;
|
|
}
|
|
|
|
if ( FT_New_Face (library, file, 0, &face) )
|
|
{
|
|
fprintf(stderr, "Error in %s: %s\n", "FT_New_Face", file);
|
|
exit (1);
|
|
}
|
|
|
|
#if 0
|
|
if ( FT_HAS_VERTICAL(face) )
|
|
fprintf(stdout, "Face has vertical infomation\n");
|
|
else
|
|
fprintf(stdout, "Face does not have vertical infomation\n");
|
|
#endif /* 0 */
|
|
|
|
if (( FTL_Query_EngineType( face, &engine_type ) )
|
|
|| ( engine_type != FTL_TRUETYPEGX_ENGINE ))
|
|
{
|
|
fprintf(stderr, "No GX table is existed: %s\n", file);
|
|
exit ( 1 );
|
|
}
|
|
setting_buttons = g_hash_table_new(NULL, NULL);
|
|
create_window( (GX_Face)face );
|
|
|
|
if ( FT_Done_Face ( face ) )
|
|
fprintf(stderr, "Error in %s: %s\n", "FT_Done_Face", file);
|
|
|
|
Exit:
|
|
if ( FT_Done_FreeType (library) )
|
|
{
|
|
fprintf(stderr, "Error in %s\n", "FT_Done_FreeType");
|
|
exit(1);
|
|
}
|
|
if ( arg_memprof || getenv("_MEMPROF_SOCKET") )
|
|
{
|
|
fprintf(stderr, "Enter infinite loop for memprof\n");
|
|
while (1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
GtkWidget * create_gx_window( GX_Face face );
|
|
GtkWidget * create_feat_area( GXL_FeaturesRequest request );
|
|
GtkWidget * create_dump_area( GX_Face face,
|
|
GXL_FeaturesRequest request );
|
|
GtkWidget * create_trace_area(void);
|
|
|
|
void
|
|
create_window (GX_Face face)
|
|
{
|
|
GtkWidget * window;
|
|
|
|
window = create_gx_window ( face );
|
|
gtk_widget_show(window);
|
|
gtk_window_resize( GTK_WINDOW(window), 1, 400);
|
|
gtk_window_set_title (GTK_WINDOW( window ), ((FT_Face)face)->family_name);
|
|
gtk_main();
|
|
}
|
|
|
|
GtkWidget *
|
|
create_gx_window( GX_Face face )
|
|
{
|
|
|
|
GtkWidget * window;
|
|
GtkWidget * feat;
|
|
GtkWidget * dump;
|
|
GtkWidget * trace;
|
|
GtkWidget * vbox;
|
|
GtkWidget * hbox;
|
|
GtkWidget * button;
|
|
GtkWidget * notebook;
|
|
GtkWidget * label;
|
|
GXL_FeaturesRequest request;
|
|
GtkWidget *gid_spinner;
|
|
|
|
FTL_New_FeaturesRequest ( (FT_Face)face,
|
|
(FTL_FeaturesRequest*)&request );
|
|
|
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
g_signal_connect (G_OBJECT (window), "destroy",
|
|
G_CALLBACK ( destroy_window ), request);
|
|
gtk_container_set_border_width (GTK_CONTAINER (window), 4);
|
|
notebook = gtk_notebook_new ();
|
|
gtk_widget_show( notebook );
|
|
gtk_container_add ( GTK_CONTAINER( window ),
|
|
notebook );
|
|
|
|
/* Features */
|
|
vbox = gtk_vbox_new ( FALSE, 8 );
|
|
label = gtk_label_new("Features");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
vbox,
|
|
label );
|
|
|
|
gtk_widget_show( vbox );
|
|
|
|
feat = create_feat_area ( request );
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
feat,
|
|
TRUE,
|
|
TRUE,
|
|
4 );
|
|
hbox = gtk_hbox_new ( TRUE, 4 );
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
hbox,
|
|
FALSE,
|
|
TRUE,
|
|
4 );
|
|
gtk_widget_show( hbox );
|
|
|
|
button = gtk_button_new_with_label ("Reset");
|
|
gtk_widget_show ( button );
|
|
g_signal_connect ( G_OBJECT( button ), "clicked",
|
|
G_CALLBACK ( reset_feature_request ), request );
|
|
gtk_box_pack_start ( GTK_BOX ( hbox ),
|
|
button,
|
|
TRUE,
|
|
TRUE,
|
|
4 );
|
|
|
|
button = gtk_button_new_with_label ("Run");
|
|
gtk_widget_show ( button );
|
|
g_signal_connect ( G_OBJECT( button ), "clicked",
|
|
G_CALLBACK ( run_layout_engine ), request );
|
|
gtk_box_pack_start ( GTK_BOX ( hbox ),
|
|
button,
|
|
TRUE,
|
|
TRUE,
|
|
4 );
|
|
|
|
/* Glyph */
|
|
vbox = gtk_vbox_new ( FALSE, 8 );
|
|
label = gtk_label_new("Glyph");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
vbox,
|
|
label );
|
|
gtk_widget_show ( vbox );
|
|
hbox = gtk_hbox_new ( TRUE, 4 );
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
hbox,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
gtk_widget_show ( hbox );
|
|
gid_spinner_adj = (GtkAdjustment *) gtk_adjustment_new ((gdouble)default_gid, 0.0, (gdouble)0xFFFF,
|
|
1.0, 5.0, 5.0);
|
|
gid_spinner = gtk_spin_button_new (gid_spinner_adj, 1.0, 0);
|
|
gtk_box_pack_start ( GTK_BOX ( hbox ),
|
|
gid_spinner,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
gtk_widget_show(gid_spinner);
|
|
|
|
button = gtk_button_new_with_label("Render");
|
|
gtk_box_pack_start ( GTK_BOX ( hbox ),
|
|
button,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
g_signal_connect( button,
|
|
"clicked",
|
|
G_CALLBACK( render_glyph ),
|
|
request );
|
|
|
|
gtk_widget_push_visual (gdk_rgb_get_visual ());
|
|
gtk_widget_push_colormap (gdk_rgb_get_cmap ());
|
|
glyph_canvas = gnome_canvas_new_aa ();
|
|
gtk_widget_pop_colormap ();
|
|
gtk_widget_pop_visual ();
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
glyph_canvas,
|
|
TRUE,
|
|
TRUE,
|
|
4 );
|
|
gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(glyph_canvas),0.2);
|
|
gnome_canvas_set_scroll_region(GNOME_CANVAS(glyph_canvas),0.0,0.0,
|
|
(double)DEFAULT_UNIT,
|
|
(double)-DEFAULT_UNIT );
|
|
gtk_widget_show( glyph_canvas );
|
|
|
|
gtk_widget_show ( button );
|
|
|
|
/* Styles */
|
|
vbox = gtk_vbox_new ( FALSE, 8 );
|
|
label = gtk_label_new("Styles");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
vbox,
|
|
label );
|
|
|
|
gtk_widget_show ( vbox );
|
|
|
|
/* Variations */
|
|
vbox = gtk_vbox_new ( FALSE, 8 );
|
|
label = gtk_label_new("Variations");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
vbox,
|
|
label );
|
|
/* gtk_widget_show ( vbox ); */
|
|
|
|
/* Dump */
|
|
dump = create_dump_area( face, request );
|
|
label = gtk_label_new("Dump");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
dump,
|
|
label );
|
|
gtk_widget_show ( dump );
|
|
|
|
/* Trace */
|
|
trace = create_trace_area();
|
|
label = gtk_label_new("Trace");
|
|
gtk_notebook_append_page ( GTK_NOTEBOOK(notebook),
|
|
trace,
|
|
label );
|
|
gtk_widget_show ( trace );
|
|
|
|
return window;
|
|
}
|
|
|
|
GtkWidget *
|
|
create_feat_area( GXL_FeaturesRequest request )
|
|
{
|
|
GtkWidget * features_vbox;
|
|
GtkWidget * feature_frame;
|
|
GtkWidget * settings_vbox;
|
|
GtkWidget * setting_toggle;
|
|
GtkWidget * setting_radio;
|
|
GtkWidget * scrolled;
|
|
GtkWidget * sep;
|
|
|
|
gint i_feat, j_string, k_setting;
|
|
gint nFeatures = GXL_FeaturesRequest_Get_Feature_Count ( request );
|
|
GXL_Feature feature;
|
|
FT_SfntName feature_name;
|
|
|
|
gint nSettings;
|
|
GXL_Setting setting;
|
|
FT_SfntName setting_name;
|
|
|
|
char * c_string;
|
|
|
|
static GSList * group = NULL;
|
|
|
|
scrolled = gtk_scrolled_window_new(NULL, NULL);
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled),
|
|
GTK_POLICY_NEVER,
|
|
GTK_POLICY_AUTOMATIC );
|
|
features_vbox = gtk_vbox_new( FALSE, 4 );
|
|
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled ),
|
|
features_vbox );
|
|
|
|
feature_frame = gtk_frame_new ( "Direction" );
|
|
gtk_box_pack_start( GTK_BOX( features_vbox ),
|
|
feature_frame,
|
|
FALSE,
|
|
FALSE,
|
|
2 );
|
|
settings_vbox = gtk_vbox_new( FALSE, 4 );
|
|
gtk_container_add( GTK_CONTAINER( feature_frame ),
|
|
settings_vbox );
|
|
|
|
setting_radio = gtk_radio_button_new_with_label( group, "Horizontal" );
|
|
gtk_box_pack_start( GTK_BOX(settings_vbox),
|
|
setting_radio,
|
|
FALSE,
|
|
FALSE,
|
|
0 );
|
|
g_signal_connect ( setting_radio,
|
|
"toggled",
|
|
G_CALLBACK(horizontal_radio_toggled),
|
|
request );
|
|
group = gtk_radio_button_get_group( GTK_RADIO_BUTTON (setting_radio) );
|
|
|
|
setting_radio = gtk_radio_button_new_with_label( group, "Vertical" );
|
|
gtk_box_pack_start( GTK_BOX(settings_vbox),
|
|
setting_radio,
|
|
FALSE,
|
|
FALSE,
|
|
0 );
|
|
g_signal_connect ( setting_radio,
|
|
"toggled",
|
|
G_CALLBACK(vertical_radio_toggled),
|
|
request );
|
|
|
|
sep = gtk_hseparator_new();
|
|
gtk_box_pack_start( GTK_BOX(features_vbox),
|
|
sep,
|
|
FALSE,
|
|
FALSE,
|
|
0 );
|
|
|
|
for ( i_feat = 0; i_feat < nFeatures; i_feat++ )
|
|
{
|
|
group = NULL;
|
|
feature = GXL_FeaturesRequest_Get_Feature ( request, i_feat );
|
|
if ( GXL_Feature_Get_Name ( feature, 0, 0, 0, &feature_name ) )
|
|
{
|
|
fprintf(stderr, "Cannot find name\n");
|
|
exit (1);
|
|
}
|
|
|
|
c_string = g_new(char, feature_name.string_len + 1 );
|
|
c_string[feature_name.string_len] = '\0';
|
|
for (j_string = 0; j_string < feature_name.string_len; j_string++)
|
|
c_string[j_string] = feature_name.string[j_string];
|
|
feature_frame = gtk_frame_new ( c_string );
|
|
g_free(c_string);
|
|
gtk_box_pack_start( GTK_BOX( features_vbox ),
|
|
feature_frame,
|
|
FALSE,
|
|
FALSE,
|
|
2 );
|
|
settings_vbox = gtk_vbox_new( FALSE, 4 );
|
|
gtk_container_add( GTK_CONTAINER( feature_frame ),
|
|
settings_vbox );
|
|
nSettings = GXL_Feature_Get_Setting_Count( feature );
|
|
for ( k_setting = 0; k_setting < nSettings; k_setting++ )
|
|
{
|
|
setting = GXL_Feature_Get_Setting( feature, k_setting );
|
|
if ( GXL_Setting_Get_Name ( setting, 0, 0, 0, &setting_name ) )
|
|
{
|
|
fprintf (stderr, "Cannot find setting name\n");
|
|
exit (1);
|
|
}
|
|
c_string = g_new(char, setting_name.string_len + 1 );
|
|
c_string[setting_name.string_len] = '\0';
|
|
for (j_string = 0; j_string < setting_name.string_len; j_string++)
|
|
c_string[j_string] = setting_name.string[j_string];
|
|
if ( GXL_Feature_Is_Setting_Exclusive (feature) )
|
|
{
|
|
setting_radio = gtk_radio_button_new_with_label(group, c_string);
|
|
group = gtk_radio_button_get_group( GTK_RADIO_BUTTON (setting_radio) );
|
|
g_free(c_string);
|
|
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(setting_radio),
|
|
GXL_Setting_Get_State (setting) );
|
|
g_signal_connect ( setting_radio,
|
|
"toggled",
|
|
G_CALLBACK(radio_toggled),
|
|
setting );
|
|
gtk_box_pack_start( GTK_BOX(settings_vbox),
|
|
setting_radio,
|
|
FALSE,
|
|
FALSE,
|
|
0 );
|
|
gtk_container_set_border_width (GTK_CONTAINER (setting_radio), 2);
|
|
g_hash_table_insert ( setting_buttons, setting_radio, setting );
|
|
}
|
|
else
|
|
{
|
|
setting_toggle = gtk_check_button_new_with_label(c_string);
|
|
g_free(c_string);
|
|
gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(setting_toggle),
|
|
GXL_Setting_Get_State (setting) );
|
|
g_signal_connect ( setting_toggle,
|
|
"toggled",
|
|
G_CALLBACK(check_toggled),
|
|
setting );
|
|
gtk_box_pack_start( GTK_BOX(settings_vbox),
|
|
setting_toggle,
|
|
FALSE,
|
|
FALSE,
|
|
0 );
|
|
gtk_container_set_border_width (GTK_CONTAINER (setting_toggle), 2);
|
|
g_hash_table_insert ( setting_buttons, setting_toggle, setting );
|
|
}
|
|
}
|
|
group = NULL;
|
|
}
|
|
gtk_widget_show_all(scrolled);
|
|
return scrolled;
|
|
}
|
|
|
|
void dump_face_cb( GtkButton * button, gpointer face );
|
|
|
|
GtkWidget *
|
|
create_dump_area( GX_Face face,
|
|
GXL_FeaturesRequest request )
|
|
|
|
{
|
|
GtkWidget * vbox = gtk_vbox_new ( FALSE, 0 );
|
|
GtkWidget * button;
|
|
GtkWidget * frame;
|
|
GtkWidget * dump_face_vbox;
|
|
GtkWidget * dump_tables_vbox;
|
|
GtkWidget * check_button;
|
|
|
|
/* Language ID */
|
|
button = gtk_button_new_with_label("Dump Language ID");
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
button,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
g_signal_connect ( G_OBJECT( button ), "clicked",
|
|
G_CALLBACK ( dump_language_id ), face );
|
|
gtk_widget_show ( button );
|
|
|
|
/* Feature Request */
|
|
button = gtk_button_new_with_label("Dump Feature Request");
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
button,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
g_signal_connect ( G_OBJECT( button ), "clicked",
|
|
G_CALLBACK ( dump_feature_request ), request );
|
|
gtk_widget_show ( button );
|
|
|
|
|
|
/* Feature Registry */
|
|
button = gtk_button_new_with_label("Dump Feature Registry");
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
button,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
g_signal_connect ( G_OBJECT( button ), "clicked",
|
|
G_CALLBACK ( dump_feature_registry ), NULL );
|
|
gtk_widget_show ( button );
|
|
|
|
/* Dump Glyph Metrics */
|
|
button = gtk_check_button_new_with_label ("Enable to Dump Glyph Metrics");
|
|
gtk_box_pack_start ( GTK_BOX ( vbox ),
|
|
button,
|
|
FALSE,
|
|
TRUE,
|
|
0 );
|
|
g_signal_connect ( G_OBJECT( button ), "toggled",
|
|
G_CALLBACK ( set_dump_glyph_metrics ), &dump_glyph_metrics );
|
|
gtk_widget_show ( button );
|
|
|
|
/* Dump tables */
|
|
frame = gtk_frame_new ( "Dump Tables" );
|
|
gtk_box_pack_start( GTK_BOX( vbox ), frame, FALSE, FALSE, 2 );
|
|
dump_face_vbox = gtk_vbox_new ( FALSE, 0 );
|
|
gtk_container_add( GTK_CONTAINER( frame ), dump_face_vbox );
|
|
dump_tables_vbox = gtk_vbox_new ( FALSE, 0 );
|
|
gtk_container_add( GTK_CONTAINER( dump_face_vbox ), dump_tables_vbox );
|
|
|
|
#define MAKE_CHECK_BUTTON(tag) \
|
|
check_button = gtk_check_button_new_with_label(#tag); \
|
|
gtk_container_add( GTK_CONTAINER( dump_tables_vbox ), check_button ); \
|
|
gtk_widget_show(check_button); \
|
|
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(check_button), \
|
|
( dump_flags & GX_DUMP_##tag )? TRUE: FALSE ); \
|
|
g_signal_connect ( G_OBJECT( check_button ), \
|
|
"toggled", \
|
|
G_CALLBACK(check_table), \
|
|
GINT_TO_POINTER(GX_DUMP_##tag) )
|
|
|
|
MAKE_CHECK_BUTTON(mort);
|
|
MAKE_CHECK_BUTTON(morx);
|
|
MAKE_CHECK_BUTTON(feat);
|
|
MAKE_CHECK_BUTTON(prop);
|
|
MAKE_CHECK_BUTTON(trak);
|
|
MAKE_CHECK_BUTTON(kern);
|
|
MAKE_CHECK_BUTTON(just);
|
|
MAKE_CHECK_BUTTON(lcar);
|
|
MAKE_CHECK_BUTTON(opbd);
|
|
MAKE_CHECK_BUTTON(bsln);
|
|
MAKE_CHECK_BUTTON(fmtx);
|
|
MAKE_CHECK_BUTTON(fdsc);
|
|
|
|
button = gtk_button_new_with_label("Dump Font Tables");
|
|
g_signal_connect (G_OBJECT (button), "clicked",
|
|
G_CALLBACK ( dump_face_cb ), face);
|
|
gtk_container_add( GTK_CONTAINER( dump_face_vbox ), button );
|
|
gtk_widget_show ( button );
|
|
|
|
gtk_widget_show ( dump_tables_vbox );
|
|
gtk_widget_show ( dump_face_vbox );
|
|
gtk_widget_show ( frame );
|
|
|
|
return vbox;
|
|
}
|
|
|
|
GtkWidget*
|
|
create_trace_area(void)
|
|
{
|
|
int count = FT_Trace_Get_Count();
|
|
int i;
|
|
GtkWidget * vbox, *hbox;
|
|
GtkWidget * label;
|
|
GtkWidget * scrolled;
|
|
const char * label_string;
|
|
GtkObject * adj;
|
|
GtkWidget * spinner;
|
|
int level;
|
|
|
|
scrolled = gtk_scrolled_window_new(NULL, NULL);
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled),
|
|
GTK_POLICY_NEVER,
|
|
GTK_POLICY_AUTOMATIC );
|
|
|
|
vbox = gtk_vbox_new ( TRUE, 1 );
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
hbox = gtk_hbox_new( TRUE, 2 );
|
|
label_string = FT_Trace_Get_Name( i );
|
|
label = gtk_label_new( label_string );
|
|
gtk_container_add(GTK_CONTAINER(hbox), label);
|
|
gtk_widget_show(label);
|
|
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
level = (gdouble)ft_trace_levels[i];
|
|
#else
|
|
level = 0;
|
|
#endif /* FT_DEBUG_LEVEL_TRACE */
|
|
|
|
adj = gtk_adjustment_new(level,
|
|
0.0, (gdouble)7, 1.0, 1.0, 1.0);
|
|
spinner = gtk_spin_button_new( GTK_ADJUSTMENT(adj), 1.0, 0 );
|
|
gtk_spin_button_set_range(GTK_SPIN_BUTTON(spinner), 0.0, 7.0);
|
|
gtk_box_pack_end( GTK_BOX(hbox), spinner, FALSE, TRUE, 0 );
|
|
gtk_widget_show(spinner);
|
|
g_signal_connect( G_OBJECT(adj),
|
|
"value_changed",
|
|
G_CALLBACK(set_trace_level),
|
|
GINT_TO_POINTER(i));
|
|
gtk_container_add( GTK_CONTAINER(vbox), hbox);
|
|
gtk_widget_show(hbox);
|
|
}
|
|
gtk_widget_show(vbox);
|
|
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled ),
|
|
vbox );
|
|
return scrolled;
|
|
}
|
|
|
|
void
|
|
dump_face_cb( GtkButton * button, gpointer face )
|
|
{
|
|
dump_face( face, ((FT_Face)face)->family_name, 1);
|
|
}
|
|
|
|
void
|
|
check_table ( GtkToggleButton * toggle_button, gpointer flag)
|
|
{
|
|
if ( gtk_toggle_button_get_active( toggle_button ) )
|
|
dump_flags |= GPOINTER_TO_INT(flag);
|
|
else
|
|
dump_flags &= (~(GPOINTER_TO_INT(flag)));
|
|
}
|
|
|
|
void
|
|
destroy_window ( GtkObject * unused, GXL_FeaturesRequest request )
|
|
{
|
|
FTL_Done_FeaturesRequest ( (FTL_FeaturesRequest)request );
|
|
gtk_main_quit();
|
|
}
|
|
|
|
void
|
|
radio_toggled( GtkToggleButton * toggle, gpointer setting )
|
|
{
|
|
gboolean state = gtk_toggle_button_get_active(toggle);
|
|
GXL_Setting_Set_State( setting, state );
|
|
}
|
|
|
|
void
|
|
check_toggled( GtkToggleButton * toggle, gpointer setting )
|
|
{
|
|
gboolean state = gtk_toggle_button_get_active(toggle);
|
|
GXL_Setting_Set_State( setting, state );
|
|
}
|
|
|
|
void
|
|
run_layout_engine ( GtkButton * button, gpointer request )
|
|
{
|
|
FTL_GlyphArray in, out;
|
|
FT_Face face = ((FTL_FeaturesRequest)request)->font->face;
|
|
FT_Memory memory = face->driver->root.memory;
|
|
|
|
char * tmp, *next;
|
|
long value, length = 0, i;
|
|
|
|
printf( "Input: ");
|
|
tmp = fgets(buffer, BUFFER_LENGTH, stdin);
|
|
if ( !tmp )
|
|
{
|
|
fprintf(stderr, "Fail to read string\n");
|
|
return;
|
|
}
|
|
|
|
FTL_New_Glyphs_Array ( memory, &in );
|
|
FTL_New_Glyphs_Array ( memory, &out );
|
|
|
|
tmp = buffer;
|
|
while ( 1 )
|
|
{
|
|
value = strtol(tmp, &next, 10);
|
|
if (( value == 0 ) && ( tmp == next ))
|
|
break;
|
|
else
|
|
{
|
|
length++;
|
|
tmp = next;
|
|
}
|
|
}
|
|
FTL_Set_Glyphs_Array_Length ( in, length );
|
|
|
|
tmp = buffer;
|
|
for ( i = 0; i < length; i++ )
|
|
in->glyphs[i].gid = (FT_UShort)strtol(tmp, &tmp, 10);
|
|
|
|
FTL_Activate_FeaturesRequest( request );
|
|
FTL_Substitute_Glyphs ( face, in, out );
|
|
|
|
fprintf(stdout, "Substituted: ");
|
|
for ( i = 0; i < length; i++ )
|
|
fprintf(stdout, "%u%s ", out->glyphs[i].gid,
|
|
(out->glyphs[i].gid == 0xFFFF)? "<empty>": "");
|
|
fprintf(stdout, "\n");
|
|
|
|
if ( dump_glyph_metrics )
|
|
{
|
|
fprintf(stdout, "\nGlyph Metrics\n");
|
|
fprintf(stdout, "---------------\n");
|
|
for ( i = 0; i < length; i++ )
|
|
dump_glyph(face,
|
|
out->glyphs[i].gid,
|
|
FTL_Get_FeaturesRequest_Direction((FTL_FeaturesRequest)request));
|
|
}
|
|
|
|
FTL_Done_Glyphs_Array ( in );
|
|
FTL_Done_Glyphs_Array ( out );
|
|
}
|
|
|
|
void
|
|
reflect_request ( gpointer key, gpointer value, gpointer user_data );
|
|
void
|
|
reset_feature_request( GtkButton * button, gpointer request )
|
|
{
|
|
FTL_Reset_FeaturesRequest( request );
|
|
g_hash_table_foreach(setting_buttons, reflect_request, NULL);
|
|
}
|
|
void
|
|
reflect_request ( gpointer key, gpointer value, gpointer user_data )
|
|
{
|
|
GtkWidget * button = GTK_WIDGET(key);
|
|
GXL_Setting setting = value;
|
|
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(button),
|
|
GXL_Setting_Get_State (setting) );
|
|
}
|
|
|
|
void
|
|
dump_feature_request( GtkButton * button, gpointer request )
|
|
{
|
|
gxl_features_request_dump(request, stdout);
|
|
}
|
|
|
|
void
|
|
dump_feature_registry( GtkButton * button, gpointer request )
|
|
{
|
|
fprintf(stdout, "Contents of registry data base\n");
|
|
fprintf(stdout, "------------------------------\n");
|
|
gx_feature_registory_dump(stdout);
|
|
}
|
|
|
|
void
|
|
horizontal_radio_toggled( GtkToggleButton * toggle,
|
|
gpointer request )
|
|
{
|
|
if ( gtk_toggle_button_get_active( toggle ) )
|
|
FTL_Set_FeaturesRequest_Direction ( request,
|
|
FTL_HORIZONTAL );
|
|
|
|
}
|
|
|
|
void
|
|
vertical_radio_toggled( GtkToggleButton * toggle,
|
|
gpointer request )
|
|
{
|
|
if ( gtk_toggle_button_get_active( toggle ) )
|
|
FTL_Set_FeaturesRequest_Direction ( request,
|
|
FTL_VERTICAL );
|
|
|
|
}
|
|
|
|
void
|
|
dump_face( FT_Face face, const char * file, gint verbose)
|
|
{
|
|
FT_Bool gx_p;
|
|
FTL_EngineType engine_type;
|
|
|
|
gx_p = !((FTL_Query_EngineType (face, &engine_type))
|
|
|| (engine_type != FTL_TRUETYPEGX_ENGINE));
|
|
if ( verbose )
|
|
{
|
|
if ( gx_p )
|
|
fprintf(stderr, "ok\n");
|
|
else if (((TT_Face)face)->extra.data)
|
|
fprintf(stderr, "failed(no gx, cff)\n");
|
|
else
|
|
fprintf(stderr, "failed(no gx)\n");
|
|
}
|
|
|
|
if ( gx_p )
|
|
gx_face_dump(face, dump_flags, file);
|
|
|
|
fflush ( stdout );
|
|
}
|
|
|
|
void
|
|
dump_file( FT_Library library, const char * file, gint verbose)
|
|
{
|
|
FT_Face face;
|
|
|
|
if ( FT_New_Face (library, file, 0, &face) )
|
|
{
|
|
fprintf(stderr, "Error in %s: %s\n", "FT_New_Face", file);
|
|
return;
|
|
}
|
|
|
|
if ( verbose )
|
|
fprintf(stderr, "loading %s...", file);
|
|
/* dump_language_id( NULL, face ); */
|
|
dump_face( face, file, verbose );
|
|
if ( FT_Done_Face ( face ) )
|
|
fprintf(stderr, "Error in %s: %s\n", "FT_Done_Face", file);
|
|
}
|
|
|
|
void
|
|
dump_language_id ( GtkButton * unused, gpointer face )
|
|
{
|
|
/* See ttnameid.h */
|
|
FT_CharMap * charmaps = ((FT_Face)face)->charmaps;
|
|
FT_Int i, num_charmaps = ((FT_Face)face)->num_charmaps;
|
|
FT_ULong langid;
|
|
|
|
fprintf(stdout, "Laguage ID for the charmaps in the face(see ttnameid.h)\n");
|
|
fprintf(stdout, "---------------------------------------\n");
|
|
|
|
for ( i = 0; i < num_charmaps; i++ )
|
|
{
|
|
langid = FT_Get_CMap_Language_ID ( charmaps[i] );
|
|
switch ( i )
|
|
{
|
|
case 0:
|
|
fprintf(stdout, "Laguage ID for the 1st charmap: %lu\n", langid );
|
|
break;
|
|
case 1:
|
|
fprintf(stdout, "Laguage ID for the 2nd charmap: %lu\n", langid );
|
|
break;
|
|
case 2:
|
|
fprintf(stdout, "Laguage ID for the 3rd charmap: %lu\n", langid );
|
|
break;
|
|
default:
|
|
fprintf(stdout, "Laguage ID for the %dth charmap: %lu\n", i, langid );
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
activate_chain_trace( void )
|
|
{
|
|
char * tmp = getenv("FT2_DEBUG");
|
|
if ( !tmp )
|
|
tmp = g_strdup("FT2_DEBUG=gxchain:6");
|
|
else
|
|
tmp = g_strconcat (tmp, " gxchain:6", NULL);
|
|
putenv(tmp);
|
|
}
|
|
|
|
void
|
|
dump_glyph(FT_Face face, FT_UShort gid, FTL_Direction dir)
|
|
{
|
|
FT_Int32 vmask;
|
|
FT_BBox bbox;
|
|
FT_UShort i, ligcount, div, new_div;
|
|
|
|
fprintf(stdout, "gid: %u\n", gid);
|
|
|
|
if ( gid == 0xFFFF )
|
|
{
|
|
fprintf(stdout, "\t<null glyph>\n");
|
|
return ;
|
|
}
|
|
|
|
ligcount = FTL_Get_LigatureCaret_Count ( face, gid );
|
|
vmask = (dir == FTL_VERTICAL)? FT_LOAD_VERTICAL_LAYOUT: 0;
|
|
FT_Load_Glyph (face, gid,
|
|
vmask | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
|
|
|
|
FT_Outline_Get_CBox (&face->glyph->outline, &bbox);
|
|
|
|
if ( ligcount == 0 )
|
|
{
|
|
fprintf(stdout, "\twidth: %g\n\theight: %g\n",
|
|
(double)bbox.xMax - (double)bbox.xMin,
|
|
(double)bbox.yMax - (double)bbox.yMin );
|
|
fprintf(stdout, "\tbbox: [xmin: %g ymin: %g xmax: %g ymax: %g]\n",
|
|
(double)bbox.xMin, (double)bbox.yMin, (double)bbox.xMax, (double)bbox.yMax);
|
|
}
|
|
else
|
|
{
|
|
div = bbox.xMin;
|
|
for ( i = 0; i < ligcount; i++ )
|
|
{
|
|
new_div = FTL_Get_LigatureCaret_Division( face, gid, i );
|
|
fprintf(stdout, "\twidth[%d]: %u\n\theight[%d]: %g\n",
|
|
i, new_div - div,
|
|
i, (double)bbox.yMax - (double)bbox.yMin );
|
|
fprintf(stdout, "\tbbox[%d]: [xmin: %g ymin: %g xmax: %g ymax: %g]\n",
|
|
i, (double)div, (double)bbox.yMin, (double)new_div, (double)bbox.yMax);
|
|
div = new_div;
|
|
fprintf(stdout, "\t----------------\n");
|
|
}
|
|
fprintf(stdout, "\twidth[%d]: %g\n\theight[%d]: %g\n",
|
|
i, (double)bbox.xMax - (double)div,
|
|
i, (double)bbox.yMax - (double)bbox.yMin );
|
|
fprintf(stdout, "\tbbox[%d]: [xmin: %g ymin: %g xmax: %g ymax: %g]\n",
|
|
i, (double)div, (double)bbox.yMin, (double)bbox.xMax, (double)bbox.yMax);
|
|
}
|
|
}
|
|
|
|
void
|
|
set_dump_glyph_metrics ( GtkWidget * check_button, gpointer data )
|
|
{
|
|
*(gboolean*)data = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON(check_button) );
|
|
}
|
|
|
|
void
|
|
render_glyph ( GtkWidget * button, gpointer request )
|
|
{
|
|
FT_Error error;
|
|
GnomeCanvasGroup *root = gnome_canvas_root(GNOME_CANVAS(glyph_canvas));
|
|
GnomeCanvasItem *div_item;
|
|
GdkPixbuf *pixbuf;
|
|
|
|
FT_Face face = ((FTL_FeaturesRequest)request)->font->face;
|
|
FTL_Direction dir = FTL_Get_FeaturesRequest_Direction((FTL_FeaturesRequest)request);
|
|
FT_UShort gid = (FT_UShort)gtk_adjustment_get_value(gid_spinner_adj);
|
|
|
|
FT_Int32 vmask;
|
|
FT_BBox bbox;
|
|
FT_UShort i, ligcount, div;
|
|
double affine[6] = {1.0, 0.0, 0.0, -1.0, 0.0, 0.0};
|
|
double affine_with_bearing[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
|
|
double factor = (double)DEFAULT_UNIT/(double)face->units_per_EM;
|
|
|
|
if ( dump_glyph_metrics )
|
|
dump_glyph ( face, gid, dir );
|
|
|
|
if ( pixbuf_item )
|
|
{
|
|
gtk_object_destroy( GTK_OBJECT(pixbuf_item) );
|
|
pixbuf_item = NULL;
|
|
}
|
|
if ( root_rect_item )
|
|
gtk_object_destroy( GTK_OBJECT(root_rect_item) );
|
|
if ( bbox_item )
|
|
gtk_object_destroy( GTK_OBJECT(bbox_item) );
|
|
if ( h_advance_item )
|
|
gtk_object_destroy( GTK_OBJECT(h_advance_item) );
|
|
if ( v_advance_item )
|
|
gtk_object_destroy( GTK_OBJECT(v_advance_item) );
|
|
|
|
if ( div_items )
|
|
{
|
|
GSList * tmp;
|
|
for ( tmp = div_items; tmp; tmp = tmp->next )
|
|
gtk_object_destroy( tmp->data );
|
|
g_slist_free ( div_items );
|
|
div_items = NULL;
|
|
}
|
|
|
|
error = FT_Set_Pixel_Sizes(face, 0, DEFAULT_UNIT );
|
|
if ( error )
|
|
{
|
|
fprintf(stderr, "Fail in FT_Set_Pixel_Sizes\n");
|
|
return ;
|
|
}
|
|
vmask = (dir == FTL_VERTICAL)? FT_LOAD_VERTICAL_LAYOUT: 0;
|
|
error = FT_Load_Glyph (face, gid,
|
|
vmask | FT_LOAD_NO_BITMAP);
|
|
if ( error )
|
|
{
|
|
fprintf(stderr, "Fail in FT_Load_Glyph[0]\n");
|
|
return ;
|
|
}
|
|
error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
|
|
if ( error )
|
|
{
|
|
fprintf(stderr, "Fail in FT_Render_Glyph\n");
|
|
return ;
|
|
}
|
|
#if 0
|
|
fprintf(stdout, "gid: %d row: %d, width: %d, pitch: %d\n",
|
|
gid,
|
|
face->glyph->bitmap.rows, face->glyph->bitmap.width,
|
|
face->glyph->bitmap.pitch);
|
|
#endif /* 0 */
|
|
|
|
if ( face->glyph->bitmap.width == 0 )
|
|
goto IGNORE_PIXBUF;
|
|
|
|
pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB,
|
|
TRUE,
|
|
8,
|
|
face->glyph->bitmap.width,
|
|
face->glyph->bitmap.rows );
|
|
|
|
{
|
|
int x, y;
|
|
unsigned char src;
|
|
unsigned char* src_buffer;
|
|
guchar *dist_buffer = gdk_pixbuf_get_pixels (pixbuf);
|
|
guchar * dist;
|
|
int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
|
|
for ( y = 0; y < face->glyph->bitmap.rows; y++ )
|
|
{
|
|
src_buffer = &(face->glyph->bitmap.buffer[y*face->glyph->bitmap.pitch]);
|
|
for (x = 0; x < face->glyph->bitmap.width; x++ )
|
|
{
|
|
src = src_buffer[x];
|
|
dist = dist_buffer + y * rowstride + x * 4;
|
|
dist[0] = dist[1] = dist[2] = 255 - src;
|
|
|
|
if (255 - src)
|
|
dist[3] = 0;
|
|
else
|
|
dist[3] = 255;
|
|
}
|
|
}
|
|
}
|
|
pixbuf_item = gnome_canvas_item_new(root,
|
|
GNOME_TYPE_CANVAS_PIXBUF,
|
|
"pixbuf", pixbuf,
|
|
NULL);
|
|
g_object_unref(pixbuf);
|
|
|
|
IGNORE_PIXBUF:
|
|
error = FT_Load_Glyph (face, gid,
|
|
vmask | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
|
|
if ( error )
|
|
{
|
|
fprintf(stderr, "Fail in FT_Load_Glyph[1]\n");
|
|
return ;
|
|
}
|
|
|
|
FT_Outline_Get_CBox (&face->glyph->outline, &bbox);
|
|
if ( error )
|
|
{
|
|
fprintf(stderr, "Fail in FT_Outline_Get_CBox\n");
|
|
return ;
|
|
}
|
|
|
|
root_rect_item = gnome_canvas_item_new(root,
|
|
GNOME_TYPE_CANVAS_RECT,
|
|
"x1", (double)0,
|
|
"y1", (double)0,
|
|
"x2", (double)DEFAULT_UNIT,
|
|
"y2", (double)DEFAULT_UNIT,
|
|
"outline_color", "black",
|
|
NULL);
|
|
gnome_canvas_item_affine_relative( root_rect_item, affine );
|
|
|
|
affine[0] *= factor;
|
|
affine[3] *= factor;
|
|
|
|
h_advance_item = gnome_canvas_item_new( root,
|
|
GNOME_TYPE_CANVAS_RECT,
|
|
"x1", (double)0,
|
|
"y1", (double)0,
|
|
"x2", (double)face->glyph->metrics.horiAdvance,
|
|
"y2", (double)0,
|
|
"outline_color", "red",
|
|
NULL);
|
|
gnome_canvas_item_affine_relative( h_advance_item, affine );
|
|
|
|
{
|
|
/* Next line is workaround against libart(?)'s bug */
|
|
double vertAdvance = ((face->glyph->metrics.vertAdvance)/2)*2.0;
|
|
v_advance_item = gnome_canvas_item_new( root,
|
|
GNOME_TYPE_CANVAS_RECT,
|
|
"x1", (double)0,
|
|
"y1", (double)0,
|
|
"x2", (double)0,
|
|
"y2", (double)vertAdvance,
|
|
"outline_color", "red",
|
|
NULL);
|
|
}
|
|
gnome_canvas_item_affine_relative( v_advance_item, affine );
|
|
|
|
bbox_item = gnome_canvas_item_new(root,
|
|
GNOME_TYPE_CANVAS_RECT,
|
|
"x1", (double)bbox.xMin,
|
|
"y1", (double)bbox.yMin,
|
|
"x2", (double)bbox.xMax,
|
|
"y2", (double)bbox.yMax,
|
|
"outline_color", "blue",
|
|
NULL);
|
|
gnome_canvas_item_affine_relative( bbox_item, affine );
|
|
|
|
ligcount = FTL_Get_LigatureCaret_Count ( face, gid );
|
|
for ( i = 0; i < ligcount; i++ )
|
|
{
|
|
/* Here, we will ignore the direction. */
|
|
div = FTL_Get_LigatureCaret_Division( face, gid, i );
|
|
div_item = gnome_canvas_item_new(gnome_canvas_root(GNOME_CANVAS(glyph_canvas)),
|
|
GNOME_TYPE_CANVAS_RECT,
|
|
"x1", (double)div,
|
|
"y1", (double)0,
|
|
"x2", (double)div,
|
|
"y2", (double)DEFAULT_UNIT,
|
|
"outline_color", "red",
|
|
NULL);
|
|
gnome_canvas_item_affine_relative( div_item, affine );
|
|
div_items = g_slist_append ( div_items, div_item );
|
|
}
|
|
|
|
if ( pixbuf_item )
|
|
{
|
|
affine_with_bearing[4] = (double)bbox.xMin * factor;
|
|
affine_with_bearing[5] = -(double)bbox.yMax * factor;
|
|
gnome_canvas_item_affine_relative( pixbuf_item, affine_with_bearing );
|
|
}
|
|
}
|
|
|
|
void
|
|
set_trace_level( GtkAdjustment * adj, gpointer trace )
|
|
{
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
gint index = GPOINTER_TO_INT(trace);
|
|
gint level = (gint)gtk_adjustment_get_value(adj);
|
|
ft_trace_levels[index] = level;
|
|
#endif /* FT_DEBUG_LEVEL_TRACE */
|
|
}
|
|
|
|
|
|
/* END */
|