From c2d142281cdd53e3f2f74f29c9f7ba6509809dca Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Sun, 3 Nov 2024 09:01:21 +0100 Subject: [PATCH] move fonts' functions into their own files --- Makefile | 3 +- src/x49gpng/tiny_font.c | 203 ------- src/x49gpng/ui.c | 618 +------------------- src/x49gpng/ui_regular_font.c | 310 ++++++++++ src/x49gpng/ui_regular_font.h | 13 + src/x49gpng/ui_tiny_font.c | 519 ++++++++++++++++ src/x49gpng/{tiny_font.h => ui_tiny_font.h} | 3 + 7 files changed, 852 insertions(+), 817 deletions(-) delete mode 100644 src/x49gpng/tiny_font.c create mode 100644 src/x49gpng/ui_regular_font.c create mode 100644 src/x49gpng/ui_regular_font.h create mode 100644 src/x49gpng/ui_tiny_font.c rename src/x49gpng/{tiny_font.h => ui_tiny_font.h} (87%) diff --git a/Makefile b/Makefile index 906fe5e..e440f72 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,8 @@ SRCS = ./src/x49gpng/main.c \ ./src/x49gpng/s3c2410_arm.c \ ./src/x49gpng/ui.c \ ./src/x49gpng/timer.c \ - ./src/x49gpng/tiny_font.c \ + ./src/x49gpng/ui_tiny_font.c \ + ./src/x49gpng/ui_regular_font.c \ ./src/x49gpng/symbol.c \ ./src/x49gpng/gdbstub.c \ ./src/x49gpng/block.c \ diff --git a/src/x49gpng/tiny_font.c b/src/x49gpng/tiny_font.c deleted file mode 100644 index 7bb8756..0000000 --- a/src/x49gpng/tiny_font.c +++ /dev/null @@ -1,203 +0,0 @@ -/* $Id: tiny_font.c,v 1.6 2008/12/11 12:18:17 ecd Exp $ - */ - -#include - -#include "tiny_font.h" - -#include "bitmaps/tiny_notdef.xbm" - -#include "bitmaps/tiny_quotedbl.xbm" -#include "bitmaps/tiny_numbersign.xbm" -#include "bitmaps/tiny_ampersand.xbm" -#include "bitmaps/tiny_parenleft.xbm" -#include "bitmaps/tiny_parenright.xbm" -#include "bitmaps/tiny_comma.xbm" -#include "bitmaps/tiny_hyphen.xbm" -#include "bitmaps/tiny_period.xbm" -#include "bitmaps/tiny_slash.xbm" -#include "bitmaps/tiny_colon.xbm" -#include "bitmaps/tiny_less.xbm" -#include "bitmaps/tiny_equal.xbm" -#include "bitmaps/tiny_greater.xbm" -#include "bitmaps/tiny_bracketleft.xbm" -#include "bitmaps/tiny_bracketright.xbm" -#include "bitmaps/tiny_underscore.xbm" -#include "bitmaps/tiny_braceleft.xbm" -#include "bitmaps/tiny_braceright.xbm" - -#include "bitmaps/tiny_guillemotleft.xbm" -#include "bitmaps/tiny_guillemotright.xbm" -#include "bitmaps/tiny_arrowleft.xbm" -#include "bitmaps/tiny_arrowright.xbm" - -#include "bitmaps/tiny_large_comma.xbm" -#include "bitmaps/tiny_overscore.xbm" - -#include "bitmaps/tiny_xsuperior.xbm" -#include "bitmaps/tiny_twosuperior.xbm" - -#include "bitmaps/tiny_math_e.xbm" -#include "bitmaps/tiny_math_x.xbm" -#include "bitmaps/tiny_math_y.xbm" -#include "bitmaps/tiny_math_pi.xbm" -#include "bitmaps/tiny_math_summation.xbm" -#include "bitmaps/tiny_math_radical.xbm" -#include "bitmaps/tiny_math_partialdiff.xbm" -#include "bitmaps/tiny_math_integral.xbm" -#include "bitmaps/tiny_math_infinity.xbm" - -#include "bitmaps/tiny_math_numbersign.xbm" -#include "bitmaps/tiny_math_less.xbm" -#include "bitmaps/tiny_math_greater.xbm" -#include "bitmaps/tiny_math_lessequal.xbm" -#include "bitmaps/tiny_math_greaterequal.xbm" -#include "bitmaps/tiny_math_equal.xbm" -#include "bitmaps/tiny_math_notequal.xbm" - -#include "bitmaps/tiny_math_arrowleft.xbm" -#include "bitmaps/tiny_math_arrowright.xbm" -#include "bitmaps/tiny_math_downarrowleft.xbm" -#include "bitmaps/tiny_math_downarrowright.xbm" - -#include "bitmaps/tiny_zero.xbm" -#include "bitmaps/tiny_one.xbm" -#include "bitmaps/tiny_two.xbm" -#include "bitmaps/tiny_three.xbm" - -#include "bitmaps/tiny_A.xbm" -#include "bitmaps/tiny_B.xbm" -#include "bitmaps/tiny_C.xbm" -#include "bitmaps/tiny_D.xbm" -#include "bitmaps/tiny_E.xbm" -#include "bitmaps/tiny_F.xbm" -#include "bitmaps/tiny_G.xbm" -#include "bitmaps/tiny_H.xbm" -#include "bitmaps/tiny_I.xbm" -#include "bitmaps/tiny_J.xbm" -#include "bitmaps/tiny_K.xbm" -#include "bitmaps/tiny_L.xbm" -#include "bitmaps/tiny_M.xbm" -#include "bitmaps/tiny_N.xbm" -#include "bitmaps/tiny_O.xbm" -#include "bitmaps/tiny_P.xbm" -#include "bitmaps/tiny_Q.xbm" -#include "bitmaps/tiny_R.xbm" -#include "bitmaps/tiny_S.xbm" -#include "bitmaps/tiny_T.xbm" -#include "bitmaps/tiny_U.xbm" -#include "bitmaps/tiny_V.xbm" -#include "bitmaps/tiny_W.xbm" -#include "bitmaps/tiny_X.xbm" -#include "bitmaps/tiny_Y.xbm" -#include "bitmaps/tiny_Z.xbm" - -#include "bitmaps/tiny__i.xbm" - -const tiny_font_t tiny_font = { - 7, - -3, - { GLYPH( tiny, notdef ), - - SPACE( "space", 4, 0 ), - GLYPH( tiny, quotedbl ), - GLYPH( tiny, numbersign ), - GLYPH( tiny, ampersand ), - GLYPH( tiny, parenleft ), - GLYPH( tiny, parenright ), - GLYPH( tiny, comma ), - GLYPH( tiny, hyphen ), - GLYPH( tiny, period ), - GLYPH( tiny, slash ), - - GLYPH( tiny, zero ), - GLYPH( tiny, one ), - GLYPH( tiny, two ), - GLYPH( tiny, three ), - - GLYPH( tiny, colon ), - - GLYPH( tiny, less ), - GLYPH( tiny, equal ), - GLYPH( tiny, greater ), - - GLYPH( tiny, A ), - GLYPH( tiny, B ), - GLYPH( tiny, C ), - GLYPH( tiny, D ), - GLYPH( tiny, E ), - GLYPH( tiny, F ), - GLYPH( tiny, G ), - GLYPH( tiny, H ), - GLYPH( tiny, I ), - GLYPH( tiny, J ), - GLYPH( tiny, K ), - GLYPH( tiny, L ), - GLYPH( tiny, M ), - GLYPH( tiny, N ), - GLYPH( tiny, O ), - GLYPH( tiny, P ), - GLYPH( tiny, Q ), - GLYPH( tiny, R ), - GLYPH( tiny, S ), - GLYPH( tiny, T ), - GLYPH( tiny, U ), - GLYPH( tiny, V ), - GLYPH( tiny, W ), - GLYPH( tiny, X ), - GLYPH( tiny, Y ), - GLYPH( tiny, Z ), - - GLYPH( tiny, bracketleft ), - GLYPH( tiny, bracketright ), - GLYPH( tiny, underscore ), - - GLYPH( tiny, i ), - - GLYPH( tiny, overscore ), - GLYPH( tiny, arrowleft ), - GLYPH( tiny, arrowright ), - GLYPH( tiny, guillemotleft ), - GLYPH( tiny, guillemotright ), - - GLYPH( tiny, braceleft ), - GLYPH( tiny, braceright ), - - GLYPH( tiny, large_comma ), - - GLYPH( tiny, xsuperior ), - GLYPH( tiny, twosuperior ), - - GLYPH( tiny, math_e ), - GLYPH( tiny, math_x ), - GLYPH( tiny, math_y ), - GLYPH( tiny, math_pi ), - GLYPH( tiny, math_summation ), - GLYPH( tiny, math_radical ), - GLYPH( tiny, math_partialdiff ), - GLYPH( tiny, math_integral ), - GLYPH( tiny, math_infinity ), - - GLYPH( tiny, math_numbersign ), - GLYPH( tiny, math_less ), - GLYPH( tiny, math_greater ), - GLYPH( tiny, math_lessequal ), - GLYPH( tiny, math_greaterequal ), - GLYPH( tiny, math_equal ), - GLYPH( tiny, math_notequal ), - - GLYPH( tiny, math_arrowleft ), - GLYPH( tiny, math_arrowright ), - GLYPH( tiny, math_downarrowleft ), - GLYPH( tiny, math_downarrowright ), - - SPACE( "kern-1", -1, -1 ), - SPACE( "kern-2", -2, -2 ), - SPACE( "kern-3", -3, -3 ), - SPACE( "kern-4", -4, -4 ), - SPACE( "kern-5", -5, -5 ), - SPACE( "kern-6", -6, -6 ), - SPACE( "kern-7", -7, -7 ), - - { NULL } } -}; diff --git a/src/x49gpng/ui.c b/src/x49gpng/ui.c index a845997..49754fe 100644 --- a/src/x49gpng/ui.c +++ b/src/x49gpng/ui.c @@ -23,7 +23,8 @@ #include "x49gp_ui.h" #include "s3c2410.h" #include "bitmaps.h" -#include "tiny_font.h" +#include "ui_tiny_font.h" +#include "ui_regular_font.h" #include "symbol.h" #include "glyphname.h" @@ -1029,37 +1030,6 @@ static x49gp_ui_key_t ui_keys[ NB_KEYS ] = { /*************/ /* functions */ /*************/ -static void _regular_font_symbol_path( cairo_t* cr, double size, double xoffset, double yoffset, const x49gp_symbol_t* symbol ) -{ - const symbol_path_t* path; - const cairo_path_data_t* data; - - path = symbol->path; - if ( NULL == path ) - return; - - cairo_move_to( cr, xoffset, yoffset ); - - for ( int i = 0; i < path->num_data; i += path->data[ i ].header.length ) { - data = &path->data[ i ]; - - switch ( data->header.type ) { - case CAIRO_PATH_MOVE_TO: - cairo_rel_move_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y ); - break; - case CAIRO_PATH_LINE_TO: - cairo_rel_line_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y ); - break; - case CAIRO_PATH_CURVE_TO: - cairo_rel_curve_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y, size * data[ 2 ].point.x, - -size * data[ 2 ].point.y, size * data[ 3 ].point.x, -size * data[ 3 ].point.y ); - break; - case CAIRO_PATH_CLOSE_PATH: - cairo_close_path( cr ); - break; - } - } -} /* static void x49gp_ui_draw_symbol( cairo_t* cr, GdkColor* color, double size, double line_width, gboolean fill, double xoffset, */ /* double yoffset, const x49gp_symbol_t* symbol ) */ @@ -1078,586 +1048,6 @@ static void _regular_font_symbol_path( cairo_t* cr, double size, double xoffset, /* cairo_stroke( cr ); */ /* } */ -static bool _regular_font_lookup_glyph( const char* name, int namelen, gunichar* glyph ) -{ - for ( int i = 0; i < NR_GLYPHNAMES; i++ ) { - if ( ( strlen( x49gp_glyphs[ i ].name ) == namelen ) && !strncmp( x49gp_glyphs[ i ].name, name, namelen ) ) { - if ( glyph ) - *glyph = x49gp_glyphs[ i ].unichar; - - return true; - } - } - - return false; -} - -static int _regular_font_text_strlen( const char* text ) -{ - const char *p, *q; - char c; - int namelen; - int n = 0; - - p = text; - while ( ( c = *p++ ) ) { - if ( c != '\\' ) { - n++; - continue; - } - - q = p; - while ( *q ) { - if ( ( *q == '\\' ) || ( *q == ' ' ) ) - break; - q++; - } - if ( q == p ) { - n++; - p++; - continue; - } - namelen = q - p; - if ( *q == ' ' ) - q++; - - if ( symbol_lookup_glyph_by_name( p, namelen, NULL ) ) { - p = q; - n++; - continue; - } - - if ( _regular_font_lookup_glyph( p, namelen, NULL ) ) { - p = q; - n++; - continue; - } - - /* - * Insert symbol .notdef here... - */ - p = q; - n++; - } - - return n; -} - -static int _regular_font_text_to_ucs4( const char* text, gunichar** ucs4p ) -{ - const char *p, *q; - gunichar glyph; - gunichar* ucs4; - char c; - int namelen; - int i = 0; - int n = _regular_font_text_strlen( text ); - - if ( n <= 0 ) - return n; - - ucs4 = malloc( n * sizeof( gunichar ) ); - - p = text; - while ( ( c = *p++ ) ) { - if ( i == n ) { - free( ucs4 ); - return -1; - } - - if ( c != '\\' ) { - ucs4[ i++ ] = c; - continue; - } - - q = p; - while ( *q ) { - if ( ( *q == '\\' ) || ( *q == ' ' ) ) - break; - q++; - } - if ( q == p ) { - ucs4[ i++ ] = *p++; - continue; - } - namelen = q - p; - if ( *q == ' ' ) - q++; - - if ( symbol_lookup_glyph_by_name( p, namelen, &glyph ) ) { - ucs4[ i++ ] = glyph; - p = q; - continue; - } - - if ( _regular_font_lookup_glyph( p, namelen, &glyph ) ) { - ucs4[ i++ ] = glyph; - p = q; - continue; - } - - /* - * Insert symbol .notdef here... - */ - ucs4[ i++ ] = 0xe000; - p = q; - } - - *ucs4p = ucs4; - - return n; -} - -static void _regular_font_vtext_path( cairo_t* cr, double size, double x, double y, va_list ap ) -{ - cairo_text_extents_t extents; - cairo_font_weight_t weight; - cairo_font_slant_t slant; - const x49gp_symbol_t* symbol; - const char* text; - gunichar* ucs4; - char out[ 8 ]; - int bytes; - int len; - - slant = va_arg( ap, cairo_font_slant_t ); - weight = va_arg( ap, cairo_font_weight_t ); - text = va_arg( ap, const char* ); - - cairo_select_font_face( cr, opt.font, slant, weight ); - cairo_set_font_size( cr, size ); - - ucs4 = NULL; - len = _regular_font_text_to_ucs4( text, &ucs4 ); - if ( len <= 0 ) - return; - - for ( int j = 0; j < len; j++ ) { - if ( g_unichar_type( ucs4[ j ] ) == G_UNICODE_PRIVATE_USE ) { - /* - * Draw Symbol, Increment x... - */ - symbol = symbol_get_by_glyph( ucs4[ j ] ); - if ( NULL == symbol ) - symbol = symbol_get_by_glyph( 0xe000 ); - - size *= symbol->prescale; - - _regular_font_symbol_path( cr, size, x, y, symbol ); - - x += size * symbol->x_advance; - y -= size * symbol->y_advance; - - size *= symbol->postscale; - - if ( symbol->prescale * symbol->postscale != 1. ) - cairo_set_font_size( cr, size ); - - continue; - } - - bytes = g_unichar_to_utf8( ucs4[ j ], out ); - out[ bytes ] = '\0'; - - cairo_text_extents( cr, out, &extents ); - - cairo_move_to( cr, x, y ); - - cairo_text_path( cr, out ); - - x += extents.x_advance; - y += extents.y_advance; - } - - free( ucs4 ); -} - -static void regular_font_measure_text( cairo_t* cr, double size, double* x_bearing, double* y_bearing, double* width, double* height, - double* ascent, double* descent, ... ) -{ - va_list ap0, ap1; - cairo_font_extents_t font_extents; - cairo_font_weight_t weight; - cairo_font_slant_t slant; - double x1, y1, x2, y2, a, d; - const char* text; - - va_start( ap0, descent ); - va_copy( ap1, ap0 ); - - _regular_font_vtext_path( cr, size, 0.0, 0.0, ap0 ); - - va_end( ap0 ); - - cairo_fill_extents( cr, &x1, &y1, &x2, &y2 ); - - if ( y2 < 0.0 ) - y2 = 0.0; - - a = 0.0; - d = 0.0; - - slant = va_arg( ap1, cairo_font_slant_t ); - weight = va_arg( ap1, cairo_font_weight_t ); - text = va_arg( ap1, const char* ); - ( void )text; - - cairo_select_font_face( cr, opt.font, slant, weight ); - cairo_set_font_size( cr, size ); - - cairo_font_extents( cr, &font_extents ); - - /* - * Cairo seems to return overall height in ascent, - * so fix this by calculating ascent = height - descent. - */ - if ( font_extents.ascent - font_extents.descent > a ) - a = font_extents.ascent - font_extents.descent; - if ( font_extents.descent > -d ) - d = -font_extents.descent; - - *x_bearing = x1; - *y_bearing = y2; - *width = x2 - x1; - *height = y2 - y1; - *ascent = a; - *descent = d; - - va_end( ap1 ); -} - -static void regular_font_draw_text( cairo_t* cr, GdkColor* color, double size, double line_width, int xoffset, int yoffset, ... ) -{ - va_list ap; - - va_start( ap, yoffset ); - - cairo_set_line_width( cr, line_width ); - cairo_set_source_rgb( cr, ( ( double )color->red ) / 65535.0, ( ( double )color->green ) / 65535.0, - ( ( double )color->blue ) / 65535.0 ); - - _regular_font_vtext_path( cr, size, xoffset, yoffset, ap ); - - if ( line_width == 0.0 ) - cairo_fill( cr ); - else - cairo_stroke( cr ); - - va_end( ap ); -} - -static unsigned char _tiny_font_lookup_glyph( const char* name, int namelen ) -{ - for ( int i = 0; tiny_font.glyphs[ i ].name; i++ ) - if ( ( strlen( tiny_font.glyphs[ i ].name ) == namelen ) && !strncmp( tiny_font.glyphs[ i ].name, name, namelen ) ) - return i; - - return 0; -} - -static unsigned char _tiny_font_lookup_ascii( char c ) -{ - int namelen = 0; - char* name; - - switch ( c ) { - case ' ': - name = "space"; - break; - case '!': - name = "exclam"; - break; - case '"': - name = "quotedbl"; - break; - case '#': - name = "numbersign"; - break; - case '$': - name = "dollar"; - break; - case '%': - name = "percent"; - break; - case '&': - name = "ampersand"; - break; - case '(': - name = "parenleft"; - break; - case ')': - name = "parenright"; - break; - case '*': - name = "asterisk"; - break; - case '+': - name = "plus"; - break; - case ',': - name = "comma"; - break; - case '-': - name = "hyphen"; - break; - case '.': - name = "period"; - break; - case '/': - name = "slash"; - break; - case '0': - name = "zero"; - break; - case '1': - name = "one"; - break; - case '2': - name = "two"; - break; - case '3': - name = "three"; - break; - case '4': - name = "four"; - break; - case '5': - name = "five"; - break; - case '6': - name = "six"; - break; - case '7': - name = "seven"; - break; - case '8': - name = "eight"; - break; - case '9': - name = "nine"; - break; - case ':': - name = "colon"; - break; - case ';': - name = "semicolon"; - break; - case '<': - name = "less"; - break; - case '=': - name = "equal"; - break; - case '>': - name = "greater"; - break; - case '?': - name = "question"; - break; - case '@': - name = "at"; - break; - case '[': - name = "bracketleft"; - break; - case '\\': - name = "backslash"; - break; - case ']': - name = "bracketright"; - break; - case '^': - name = "asciicircum"; - break; - case '_': - name = "underscore"; - break; - case '`': - name = "quoteleft"; - break; - case '{': - name = "braceleft"; - break; - case '|': - name = "bar"; - break; - case '}': - name = "braceright"; - break; - case '~': - name = "asciitilde"; - break; - default: - name = &c; - namelen = 1; - break; - } - - if ( 0 == namelen ) - namelen = strlen( name ); - - return _tiny_font_lookup_glyph( name, namelen ); -} - -static inline int _tiny_font_strlen( const char* text ) -{ - const char *p, *q; - char c; - int n = 0; - - p = text; - while ( ( c = *p++ ) ) { - if ( c != '\\' ) { - n++; - continue; - } - - q = p; - while ( *q ) { - if ( ( *q == '\\' ) || ( *q == ' ' ) ) - break; - q++; - } - if ( q == p ) { - n++; - p++; - continue; - } - if ( *q == ' ' ) - q++; - - n++; - p = q; - } - - return n; -} - -static int _tiny_font_text_to_glyphs( const char* text, unsigned char** glyphp ) -{ - unsigned char* glyphs; - const char *p, *q; - unsigned char c; - int namelen; - int i, n; - - n = _tiny_font_strlen( text ); - if ( n <= 0 ) - return n; - - glyphs = malloc( n ); - - i = 0; - - p = text; - while ( ( c = *p++ ) ) { - if ( i == n ) { - free( glyphs ); - return -1; - } - - if ( c != '\\' ) { - glyphs[ i++ ] = _tiny_font_lookup_ascii( c ); - continue; - } - - q = p; - while ( *q ) { - if ( ( *q == '\\' ) || ( *q == ' ' ) ) - break; - q++; - } - if ( q == p ) { - glyphs[ i++ ] = _tiny_font_lookup_ascii( *p++ ); - continue; - } - namelen = q - p; - if ( *q == ' ' ) - q++; - - glyphs[ i++ ] = _tiny_font_lookup_glyph( p, namelen ); - p = q; - } - - *glyphp = glyphs; - return n; -} - -static void tiny_font_measure_text( const char* text, int* width, int* height, int* ascent, int* descent ) -{ - const tiny_glyph_t* glyph; - unsigned char* glyphs; - int n, w, a, d; - - w = 0; - a = 0; - d = 0; - - n = _tiny_font_text_to_glyphs( text, &glyphs ); - - for ( int i = 0; i < n; i++ ) { - glyph = &tiny_font.glyphs[ glyphs[ i ] ]; - - w += glyph->width; - - if ( glyph->ascent > a ) - a = glyph->ascent; - if ( glyph->descent < d ) - d = glyph->descent; - } - - *width = w - 1; - *height = tiny_font.ascent - tiny_font.descent; - *ascent = a; - *descent = d; - - if ( n > 0 ) - free( glyphs ); -} - -static void tiny_font_draw_text( GdkDrawable* drawable, GdkColor* color, int x, int y, const char* text ) -{ - const tiny_glyph_t* glyph; - unsigned char* glyphs; - GdkBitmap* bitmap; - GdkGC* gc; - int n, w, h; - - gc = gdk_gc_new( drawable ); - gdk_gc_set_rgb_fg_color( gc, color ); - - n = _tiny_font_text_to_glyphs( text, &glyphs ); - - for ( int i = 0; i < n; i++ ) { - glyph = &tiny_font.glyphs[ glyphs[ i ] ]; - - w = glyph->width - glyph->kern; - h = glyph->ascent - glyph->descent; - - if ( w <= 0 || h <= 0 ) { - x += glyph->width; - continue; - } - - bitmap = gdk_bitmap_create_from_data( NULL, ( char* )glyph->bits, w, h ); - - gdk_gc_set_ts_origin( gc, x + glyph->kern, y + tiny_font.ascent - glyph->ascent ); - gdk_gc_set_stipple( gc, bitmap ); - gdk_gc_set_fill( gc, GDK_STIPPLED ); - - gdk_draw_rectangle( drawable, gc, true, x + glyph->kern, y + tiny_font.ascent - glyph->ascent, w, h ); - - g_object_unref( bitmap ); - - x += glyph->width; - } - - g_object_unref( gc ); - - if ( n > 0 ) - free( glyphs ); -} - static gboolean handler_button_press( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) { x49gp_ui_button_t* button = user_data; @@ -2745,10 +2135,12 @@ static int ui_load( x49gp_module_t* module, GKeyFile* keyfile ) _ui_load__init_button_style_and_pixmap( x49gp, button, ui_keys[ i ].color ); if ( ui_keys[ i ].label ) { - button->label = gtk_label_new( "" ); + button->label = gtk_label_new( NULL ); gtk_widget_set_style( button->label, gtk_widget_get_style( button->button ) ); gtk_container_add( GTK_CONTAINER( button->button ), button->label ); + /* gtk_label_set_markup( GTK_LABEL( button->label ), ui_keys[ i ].label ); */ + g_signal_connect( G_OBJECT( button->label ), "expose-event", G_CALLBACK( handler_button_expose ), button ); g_signal_connect_after( G_OBJECT( button->label ), "realize", G_CALLBACK( handler_button_realize ), button ); diff --git a/src/x49gpng/ui_regular_font.c b/src/x49gpng/ui_regular_font.c new file mode 100644 index 0000000..f4080fa --- /dev/null +++ b/src/x49gpng/ui_regular_font.c @@ -0,0 +1,310 @@ +#include +#include + +#include +#include + +#include "options.h" +#include "symbol.h" +#include "glyphname.h" +#include "ui_regular_font.h" + +static void _regular_font_symbol_path( cairo_t* cr, double size, double xoffset, double yoffset, const x49gp_symbol_t* symbol ) +{ + const symbol_path_t* path; + const cairo_path_data_t* data; + + path = symbol->path; + if ( NULL == path ) + return; + + cairo_move_to( cr, xoffset, yoffset ); + + for ( int i = 0; i < path->num_data; i += path->data[ i ].header.length ) { + data = &path->data[ i ]; + + switch ( data->header.type ) { + case CAIRO_PATH_MOVE_TO: + cairo_rel_move_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y ); + break; + case CAIRO_PATH_LINE_TO: + cairo_rel_line_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y ); + break; + case CAIRO_PATH_CURVE_TO: + cairo_rel_curve_to( cr, size * data[ 1 ].point.x, -size * data[ 1 ].point.y, size * data[ 2 ].point.x, + -size * data[ 2 ].point.y, size * data[ 3 ].point.x, -size * data[ 3 ].point.y ); + break; + case CAIRO_PATH_CLOSE_PATH: + cairo_close_path( cr ); + break; + } + } +} + +static bool _regular_font_lookup_glyph( const char* name, int namelen, gunichar* glyph ) +{ + for ( int i = 0; i < NR_GLYPHNAMES; i++ ) { + if ( ( strlen( x49gp_glyphs[ i ].name ) == namelen ) && !strncmp( x49gp_glyphs[ i ].name, name, namelen ) ) { + if ( glyph ) + *glyph = x49gp_glyphs[ i ].unichar; + + return true; + } + } + + return false; +} + +static int _regular_font_text_strlen( const char* text ) +{ + const char *p, *q; + char c; + int namelen; + int n = 0; + + p = text; + while ( ( c = *p++ ) ) { + if ( c != '\\' ) { + n++; + continue; + } + + q = p; + while ( *q ) { + if ( ( *q == '\\' ) || ( *q == ' ' ) ) + break; + q++; + } + if ( q == p ) { + n++; + p++; + continue; + } + namelen = q - p; + if ( *q == ' ' ) + q++; + + if ( symbol_lookup_glyph_by_name( p, namelen, NULL ) ) { + p = q; + n++; + continue; + } + + if ( _regular_font_lookup_glyph( p, namelen, NULL ) ) { + p = q; + n++; + continue; + } + + /* + * Insert symbol .notdef here... + */ + p = q; + n++; + } + + return n; +} + +static int _regular_font_text_to_ucs4( const char* text, gunichar** ucs4p ) +{ + const char *p, *q; + gunichar glyph; + gunichar* ucs4; + char c; + int namelen; + int i = 0; + int n = _regular_font_text_strlen( text ); + + if ( n <= 0 ) + return n; + + ucs4 = malloc( n * sizeof( gunichar ) ); + + p = text; + while ( ( c = *p++ ) ) { + if ( i == n ) { + free( ucs4 ); + return -1; + } + + if ( c != '\\' ) { + ucs4[ i++ ] = c; + continue; + } + + q = p; + while ( *q ) { + if ( ( *q == '\\' ) || ( *q == ' ' ) ) + break; + q++; + } + if ( q == p ) { + ucs4[ i++ ] = *p++; + continue; + } + namelen = q - p; + if ( *q == ' ' ) + q++; + + if ( symbol_lookup_glyph_by_name( p, namelen, &glyph ) ) { + ucs4[ i++ ] = glyph; + p = q; + continue; + } + + if ( _regular_font_lookup_glyph( p, namelen, &glyph ) ) { + ucs4[ i++ ] = glyph; + p = q; + continue; + } + + /* + * Insert symbol .notdef here... + */ + ucs4[ i++ ] = 0xe000; + p = q; + } + + *ucs4p = ucs4; + + return n; +} + +static void _regular_font_vtext_path( cairo_t* cr, double size, double x, double y, va_list ap ) +{ + cairo_text_extents_t extents; + cairo_font_weight_t weight; + cairo_font_slant_t slant; + const x49gp_symbol_t* symbol; + const char* text; + gunichar* ucs4; + char out[ 8 ]; + int bytes; + int len; + + slant = va_arg( ap, cairo_font_slant_t ); + weight = va_arg( ap, cairo_font_weight_t ); + text = va_arg( ap, const char* ); + + cairo_select_font_face( cr, opt.font, slant, weight ); + cairo_set_font_size( cr, size ); + + ucs4 = NULL; + len = _regular_font_text_to_ucs4( text, &ucs4 ); + if ( len <= 0 ) + return; + + for ( int j = 0; j < len; j++ ) { + if ( g_unichar_type( ucs4[ j ] ) == G_UNICODE_PRIVATE_USE ) { + /* + * Draw Symbol, Increment x... + */ + symbol = symbol_get_by_glyph( ucs4[ j ] ); + if ( NULL == symbol ) + symbol = symbol_get_by_glyph( 0xe000 ); + + size *= symbol->prescale; + + _regular_font_symbol_path( cr, size, x, y, symbol ); + + x += size * symbol->x_advance; + y -= size * symbol->y_advance; + + size *= symbol->postscale; + + if ( symbol->prescale * symbol->postscale != 1. ) + cairo_set_font_size( cr, size ); + + continue; + } + + bytes = g_unichar_to_utf8( ucs4[ j ], out ); + out[ bytes ] = '\0'; + + cairo_text_extents( cr, out, &extents ); + + cairo_move_to( cr, x, y ); + + cairo_text_path( cr, out ); + + x += extents.x_advance; + y += extents.y_advance; + } + + free( ucs4 ); +} + +void regular_font_measure_text( cairo_t* cr, double size, double* x_bearing, double* y_bearing, double* width, double* height, + double* ascent, double* descent, ... ) +{ + va_list ap0, ap1; + cairo_font_extents_t font_extents; + cairo_font_weight_t weight; + cairo_font_slant_t slant; + double x1, y1, x2, y2, a, d; + const char* text; + + va_start( ap0, descent ); + va_copy( ap1, ap0 ); + + _regular_font_vtext_path( cr, size, 0.0, 0.0, ap0 ); + + va_end( ap0 ); + + cairo_fill_extents( cr, &x1, &y1, &x2, &y2 ); + + if ( y2 < 0.0 ) + y2 = 0.0; + + a = 0.0; + d = 0.0; + + slant = va_arg( ap1, cairo_font_slant_t ); + weight = va_arg( ap1, cairo_font_weight_t ); + text = va_arg( ap1, const char* ); + ( void )text; + + cairo_select_font_face( cr, opt.font, slant, weight ); + cairo_set_font_size( cr, size ); + + cairo_font_extents( cr, &font_extents ); + + /* + * Cairo seems to return overall height in ascent, + * so fix this by calculating ascent = height - descent. + */ + if ( font_extents.ascent - font_extents.descent > a ) + a = font_extents.ascent - font_extents.descent; + if ( font_extents.descent > -d ) + d = -font_extents.descent; + + *x_bearing = x1; + *y_bearing = y2; + *width = x2 - x1; + *height = y2 - y1; + *ascent = a; + *descent = d; + + va_end( ap1 ); +} + +void regular_font_draw_text( cairo_t* cr, GdkColor* color, double size, double line_width, int xoffset, int yoffset, ... ) +{ + va_list ap; + + va_start( ap, yoffset ); + + cairo_set_line_width( cr, line_width ); + cairo_set_source_rgb( cr, ( ( double )color->red ) / 65535.0, ( ( double )color->green ) / 65535.0, + ( ( double )color->blue ) / 65535.0 ); + + _regular_font_vtext_path( cr, size, xoffset, yoffset, ap ); + + if ( line_width == 0.0 ) + cairo_fill( cr ); + else + cairo_stroke( cr ); + + va_end( ap ); +} diff --git a/src/x49gpng/ui_regular_font.h b/src/x49gpng/ui_regular_font.h new file mode 100644 index 0000000..5f2ddf6 --- /dev/null +++ b/src/x49gpng/ui_regular_font.h @@ -0,0 +1,13 @@ +/* $Id: bitmap_font.h,v 1.5 2008/12/11 12:18:17 ecd Exp $ + */ + +#ifndef _REGULAR_FONT_H +#define _REGULAR_FONT_H 1 + +#include + +void regular_font_measure_text( cairo_t* cr, double size, double* x_bearing, double* y_bearing, double* width, double* height, + double* ascent, double* descent, ... ); +void regular_font_draw_text( cairo_t* cr, GdkColor* color, double size, double line_width, int xoffset, int yoffset, ... ); + +#endif /* !(_REGULAR_FONT_H) */ diff --git a/src/x49gpng/ui_tiny_font.c b/src/x49gpng/ui_tiny_font.c new file mode 100644 index 0000000..848d051 --- /dev/null +++ b/src/x49gpng/ui_tiny_font.c @@ -0,0 +1,519 @@ +/* $Id: tiny_font.c,v 1.6 2008/12/11 12:18:17 ecd Exp $ + */ + +#include +#include +#include + +#include + +#include "ui_tiny_font.h" + +#include "bitmaps/tiny_notdef.xbm" + +#include "bitmaps/tiny_quotedbl.xbm" +#include "bitmaps/tiny_numbersign.xbm" +#include "bitmaps/tiny_ampersand.xbm" +#include "bitmaps/tiny_parenleft.xbm" +#include "bitmaps/tiny_parenright.xbm" +#include "bitmaps/tiny_comma.xbm" +#include "bitmaps/tiny_hyphen.xbm" +#include "bitmaps/tiny_period.xbm" +#include "bitmaps/tiny_slash.xbm" +#include "bitmaps/tiny_colon.xbm" +#include "bitmaps/tiny_less.xbm" +#include "bitmaps/tiny_equal.xbm" +#include "bitmaps/tiny_greater.xbm" +#include "bitmaps/tiny_bracketleft.xbm" +#include "bitmaps/tiny_bracketright.xbm" +#include "bitmaps/tiny_underscore.xbm" +#include "bitmaps/tiny_braceleft.xbm" +#include "bitmaps/tiny_braceright.xbm" + +#include "bitmaps/tiny_guillemotleft.xbm" +#include "bitmaps/tiny_guillemotright.xbm" +#include "bitmaps/tiny_arrowleft.xbm" +#include "bitmaps/tiny_arrowright.xbm" + +#include "bitmaps/tiny_large_comma.xbm" +#include "bitmaps/tiny_overscore.xbm" + +#include "bitmaps/tiny_xsuperior.xbm" +#include "bitmaps/tiny_twosuperior.xbm" + +#include "bitmaps/tiny_math_e.xbm" +#include "bitmaps/tiny_math_x.xbm" +#include "bitmaps/tiny_math_y.xbm" +#include "bitmaps/tiny_math_pi.xbm" +#include "bitmaps/tiny_math_summation.xbm" +#include "bitmaps/tiny_math_radical.xbm" +#include "bitmaps/tiny_math_partialdiff.xbm" +#include "bitmaps/tiny_math_integral.xbm" +#include "bitmaps/tiny_math_infinity.xbm" + +#include "bitmaps/tiny_math_numbersign.xbm" +#include "bitmaps/tiny_math_less.xbm" +#include "bitmaps/tiny_math_greater.xbm" +#include "bitmaps/tiny_math_lessequal.xbm" +#include "bitmaps/tiny_math_greaterequal.xbm" +#include "bitmaps/tiny_math_equal.xbm" +#include "bitmaps/tiny_math_notequal.xbm" + +#include "bitmaps/tiny_math_arrowleft.xbm" +#include "bitmaps/tiny_math_arrowright.xbm" +#include "bitmaps/tiny_math_downarrowleft.xbm" +#include "bitmaps/tiny_math_downarrowright.xbm" + +#include "bitmaps/tiny_zero.xbm" +#include "bitmaps/tiny_one.xbm" +#include "bitmaps/tiny_two.xbm" +#include "bitmaps/tiny_three.xbm" + +#include "bitmaps/tiny_A.xbm" +#include "bitmaps/tiny_B.xbm" +#include "bitmaps/tiny_C.xbm" +#include "bitmaps/tiny_D.xbm" +#include "bitmaps/tiny_E.xbm" +#include "bitmaps/tiny_F.xbm" +#include "bitmaps/tiny_G.xbm" +#include "bitmaps/tiny_H.xbm" +#include "bitmaps/tiny_I.xbm" +#include "bitmaps/tiny_J.xbm" +#include "bitmaps/tiny_K.xbm" +#include "bitmaps/tiny_L.xbm" +#include "bitmaps/tiny_M.xbm" +#include "bitmaps/tiny_N.xbm" +#include "bitmaps/tiny_O.xbm" +#include "bitmaps/tiny_P.xbm" +#include "bitmaps/tiny_Q.xbm" +#include "bitmaps/tiny_R.xbm" +#include "bitmaps/tiny_S.xbm" +#include "bitmaps/tiny_T.xbm" +#include "bitmaps/tiny_U.xbm" +#include "bitmaps/tiny_V.xbm" +#include "bitmaps/tiny_W.xbm" +#include "bitmaps/tiny_X.xbm" +#include "bitmaps/tiny_Y.xbm" +#include "bitmaps/tiny_Z.xbm" + +#include "bitmaps/tiny__i.xbm" + +const tiny_font_t tiny_font = { + 7, + -3, + { GLYPH( tiny, notdef ), + + SPACE( "space", 4, 0 ), + GLYPH( tiny, quotedbl ), + GLYPH( tiny, numbersign ), + GLYPH( tiny, ampersand ), + GLYPH( tiny, parenleft ), + GLYPH( tiny, parenright ), + GLYPH( tiny, comma ), + GLYPH( tiny, hyphen ), + GLYPH( tiny, period ), + GLYPH( tiny, slash ), + + GLYPH( tiny, zero ), + GLYPH( tiny, one ), + GLYPH( tiny, two ), + GLYPH( tiny, three ), + + GLYPH( tiny, colon ), + + GLYPH( tiny, less ), + GLYPH( tiny, equal ), + GLYPH( tiny, greater ), + + GLYPH( tiny, A ), + GLYPH( tiny, B ), + GLYPH( tiny, C ), + GLYPH( tiny, D ), + GLYPH( tiny, E ), + GLYPH( tiny, F ), + GLYPH( tiny, G ), + GLYPH( tiny, H ), + GLYPH( tiny, I ), + GLYPH( tiny, J ), + GLYPH( tiny, K ), + GLYPH( tiny, L ), + GLYPH( tiny, M ), + GLYPH( tiny, N ), + GLYPH( tiny, O ), + GLYPH( tiny, P ), + GLYPH( tiny, Q ), + GLYPH( tiny, R ), + GLYPH( tiny, S ), + GLYPH( tiny, T ), + GLYPH( tiny, U ), + GLYPH( tiny, V ), + GLYPH( tiny, W ), + GLYPH( tiny, X ), + GLYPH( tiny, Y ), + GLYPH( tiny, Z ), + + GLYPH( tiny, bracketleft ), + GLYPH( tiny, bracketright ), + GLYPH( tiny, underscore ), + + GLYPH( tiny, i ), + + GLYPH( tiny, overscore ), + GLYPH( tiny, arrowleft ), + GLYPH( tiny, arrowright ), + GLYPH( tiny, guillemotleft ), + GLYPH( tiny, guillemotright ), + + GLYPH( tiny, braceleft ), + GLYPH( tiny, braceright ), + + GLYPH( tiny, large_comma ), + + GLYPH( tiny, xsuperior ), + GLYPH( tiny, twosuperior ), + + GLYPH( tiny, math_e ), + GLYPH( tiny, math_x ), + GLYPH( tiny, math_y ), + GLYPH( tiny, math_pi ), + GLYPH( tiny, math_summation ), + GLYPH( tiny, math_radical ), + GLYPH( tiny, math_partialdiff ), + GLYPH( tiny, math_integral ), + GLYPH( tiny, math_infinity ), + + GLYPH( tiny, math_numbersign ), + GLYPH( tiny, math_less ), + GLYPH( tiny, math_greater ), + GLYPH( tiny, math_lessequal ), + GLYPH( tiny, math_greaterequal ), + GLYPH( tiny, math_equal ), + GLYPH( tiny, math_notequal ), + + GLYPH( tiny, math_arrowleft ), + GLYPH( tiny, math_arrowright ), + GLYPH( tiny, math_downarrowleft ), + GLYPH( tiny, math_downarrowright ), + + SPACE( "kern-1", -1, -1 ), + SPACE( "kern-2", -2, -2 ), + SPACE( "kern-3", -3, -3 ), + SPACE( "kern-4", -4, -4 ), + SPACE( "kern-5", -5, -5 ), + SPACE( "kern-6", -6, -6 ), + SPACE( "kern-7", -7, -7 ), + + { NULL } } +}; + +static unsigned char _tiny_font_lookup_glyph( const char* name, int namelen ) +{ + for ( int i = 0; tiny_font.glyphs[ i ].name; i++ ) + if ( ( strlen( tiny_font.glyphs[ i ].name ) == namelen ) && !strncmp( tiny_font.glyphs[ i ].name, name, namelen ) ) + return i; + + return 0; +} + +static unsigned char _tiny_font_lookup_ascii( char c ) +{ + int namelen = 0; + char* name; + + switch ( c ) { + case ' ': + name = "space"; + break; + case '!': + name = "exclam"; + break; + case '"': + name = "quotedbl"; + break; + case '#': + name = "numbersign"; + break; + case '$': + name = "dollar"; + break; + case '%': + name = "percent"; + break; + case '&': + name = "ampersand"; + break; + case '(': + name = "parenleft"; + break; + case ')': + name = "parenright"; + break; + case '*': + name = "asterisk"; + break; + case '+': + name = "plus"; + break; + case ',': + name = "comma"; + break; + case '-': + name = "hyphen"; + break; + case '.': + name = "period"; + break; + case '/': + name = "slash"; + break; + case '0': + name = "zero"; + break; + case '1': + name = "one"; + break; + case '2': + name = "two"; + break; + case '3': + name = "three"; + break; + case '4': + name = "four"; + break; + case '5': + name = "five"; + break; + case '6': + name = "six"; + break; + case '7': + name = "seven"; + break; + case '8': + name = "eight"; + break; + case '9': + name = "nine"; + break; + case ':': + name = "colon"; + break; + case ';': + name = "semicolon"; + break; + case '<': + name = "less"; + break; + case '=': + name = "equal"; + break; + case '>': + name = "greater"; + break; + case '?': + name = "question"; + break; + case '@': + name = "at"; + break; + case '[': + name = "bracketleft"; + break; + case '\\': + name = "backslash"; + break; + case ']': + name = "bracketright"; + break; + case '^': + name = "asciicircum"; + break; + case '_': + name = "underscore"; + break; + case '`': + name = "quoteleft"; + break; + case '{': + name = "braceleft"; + break; + case '|': + name = "bar"; + break; + case '}': + name = "braceright"; + break; + case '~': + name = "asciitilde"; + break; + default: + name = &c; + namelen = 1; + break; + } + + if ( 0 == namelen ) + namelen = strlen( name ); + + return _tiny_font_lookup_glyph( name, namelen ); +} + +static inline int _tiny_font_strlen( const char* text ) +{ + const char *p, *q; + char c; + int n = 0; + + p = text; + while ( ( c = *p++ ) ) { + if ( c != '\\' ) { + n++; + continue; + } + + q = p; + while ( *q ) { + if ( ( *q == '\\' ) || ( *q == ' ' ) ) + break; + q++; + } + if ( q == p ) { + n++; + p++; + continue; + } + if ( *q == ' ' ) + q++; + + n++; + p = q; + } + + return n; +} + +static int _tiny_font_text_to_glyphs( const char* text, unsigned char** glyphp ) +{ + unsigned char* glyphs; + const char *p, *q; + unsigned char c; + int namelen; + int i, n; + + n = _tiny_font_strlen( text ); + if ( n <= 0 ) + return n; + + glyphs = malloc( n ); + + i = 0; + + p = text; + while ( ( c = *p++ ) ) { + if ( i == n ) { + free( glyphs ); + return -1; + } + + if ( c != '\\' ) { + glyphs[ i++ ] = _tiny_font_lookup_ascii( c ); + continue; + } + + q = p; + while ( *q ) { + if ( ( *q == '\\' ) || ( *q == ' ' ) ) + break; + q++; + } + if ( q == p ) { + glyphs[ i++ ] = _tiny_font_lookup_ascii( *p++ ); + continue; + } + namelen = q - p; + if ( *q == ' ' ) + q++; + + glyphs[ i++ ] = _tiny_font_lookup_glyph( p, namelen ); + p = q; + } + + *glyphp = glyphs; + return n; +} + +void tiny_font_measure_text( const char* text, int* width, int* height, int* ascent, int* descent ) +{ + const tiny_glyph_t* glyph; + unsigned char* glyphs; + int n, w, a, d; + + w = 0; + a = 0; + d = 0; + + n = _tiny_font_text_to_glyphs( text, &glyphs ); + + for ( int i = 0; i < n; i++ ) { + glyph = &tiny_font.glyphs[ glyphs[ i ] ]; + + w += glyph->width; + + if ( glyph->ascent > a ) + a = glyph->ascent; + if ( glyph->descent < d ) + d = glyph->descent; + } + + *width = w - 1; + *height = tiny_font.ascent - tiny_font.descent; + *ascent = a; + *descent = d; + + if ( n > 0 ) + free( glyphs ); +} + +void tiny_font_draw_text( GdkDrawable* drawable, GdkColor* color, int x, int y, const char* text ) +{ + const tiny_glyph_t* glyph; + unsigned char* glyphs; + GdkBitmap* bitmap; + GdkGC* gc; + int n, w, h; + + gc = gdk_gc_new( drawable ); + gdk_gc_set_rgb_fg_color( gc, color ); + + n = _tiny_font_text_to_glyphs( text, &glyphs ); + + for ( int i = 0; i < n; i++ ) { + glyph = &tiny_font.glyphs[ glyphs[ i ] ]; + + w = glyph->width - glyph->kern; + h = glyph->ascent - glyph->descent; + + if ( w <= 0 || h <= 0 ) { + x += glyph->width; + continue; + } + + bitmap = gdk_bitmap_create_from_data( NULL, ( char* )glyph->bits, w, h ); + + gdk_gc_set_ts_origin( gc, x + glyph->kern, y + tiny_font.ascent - glyph->ascent ); + gdk_gc_set_stipple( gc, bitmap ); + gdk_gc_set_fill( gc, GDK_STIPPLED ); + + gdk_draw_rectangle( drawable, gc, true, x + glyph->kern, y + tiny_font.ascent - glyph->ascent, w, h ); + + g_object_unref( bitmap ); + + x += glyph->width; + } + + g_object_unref( gc ); + + if ( n > 0 ) + free( glyphs ); +} diff --git a/src/x49gpng/tiny_font.h b/src/x49gpng/ui_tiny_font.h similarity index 87% rename from src/x49gpng/tiny_font.h rename to src/x49gpng/ui_tiny_font.h index 9959aa9..408dd32 100644 --- a/src/x49gpng/tiny_font.h +++ b/src/x49gpng/ui_tiny_font.h @@ -31,4 +31,7 @@ typedef struct { extern const tiny_font_t tiny_font; +void tiny_font_measure_text( const char* text, int* width, int* height, int* ascent, int* descent ); +void tiny_font_draw_text( GdkDrawable* drawable, GdkColor* color, int x, int y, const char* text ); + #endif /* !(_X49GP_TINY_FONT_H) */