1
0
Fork 0
forked from Miroirs/x49gp

move fonts' functions into their own files

This commit is contained in:
Gwenhael Le Moine 2024-11-03 09:01:21 +01:00
parent e28b228c09
commit c2d142281c
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
7 changed files with 852 additions and 817 deletions

View file

@ -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 \

View file

@ -1,203 +0,0 @@
/* $Id: tiny_font.c,v 1.6 2008/12/11 12:18:17 ecd Exp $
*/
#include <stdlib.h>
#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 } }
};

View file

@ -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 );

View file

@ -0,0 +1,310 @@
#include <stdbool.h>
#include <stddef.h>
#include <gdk/gdk.h>
#include <cairo.h>
#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 );
}

View file

@ -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 <cairo.h>
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) */

519
src/x49gpng/ui_tiny_font.c Normal file
View file

@ -0,0 +1,519 @@
/* $Id: tiny_font.c,v 1.6 2008/12/11 12:18:17 ecd Exp $
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <gdk/gdk.h>
#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 );
}

View file

@ -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) */