mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
Instead of three fixed-sized fonts, choose fonts (lazily) based on the size of the rect into which it's to be drawn.
This commit is contained in:
parent
6e8a1922eb
commit
d929af49ad
2 changed files with 97 additions and 58 deletions
151
linux/gtkdraw.c
151
linux/gtkdraw.c
|
@ -35,6 +35,12 @@ typedef enum {
|
|||
,XP_GTK_JUST_BOTTOMRIGHT
|
||||
} XP_GTK_JUST;
|
||||
|
||||
typedef struct FontPerSize {
|
||||
unsigned int ht;
|
||||
PangoFontDescription* fontdesc;
|
||||
PangoLayout* layout;
|
||||
} FontPerSize;
|
||||
|
||||
/* static GdkGC* newGCForColor( GdkWindow* window, XP_Color* newC ); */
|
||||
static void
|
||||
insetRect( XP_Rect* r, short i )
|
||||
|
@ -53,6 +59,7 @@ insetRect( XP_Rect* r, short i )
|
|||
#define DRAW_WHAT(dc) ((dc)->drawing_area->window)
|
||||
#endif
|
||||
|
||||
#define GTKMIN_W_HT 8
|
||||
|
||||
static void
|
||||
eraseRect( GtkDrawCtx* dctx, const XP_Rect* rect )
|
||||
|
@ -128,14 +135,62 @@ gtk_prim_draw_measureText( DrawCtx* p_dctx, XP_UCHAR* str,
|
|||
|
||||
#endif /* DRAW_WITH_PRIMITIVES */
|
||||
|
||||
static gint
|
||||
compForHt( gconstpointer a,
|
||||
gconstpointer b )
|
||||
{
|
||||
FontPerSize* fps1 = (FontPerSize*)a;
|
||||
FontPerSize* fps2 = (FontPerSize*)b;
|
||||
return fps1->ht - fps2->ht;
|
||||
}
|
||||
|
||||
static PangoLayout*
|
||||
layout_for_ht( GtkDrawCtx* dctx, XP_U16 ht )
|
||||
{
|
||||
PangoLayout* result = NULL;
|
||||
|
||||
/* Try to find a cached layout. Otherwise create a new one. */
|
||||
FontPerSize fps = { .ht = ht };
|
||||
GList* gl = g_list_find_custom( dctx->fontsPerSize, &fps,
|
||||
compForHt );
|
||||
if ( NULL != gl ) {
|
||||
result = ((FontPerSize*)gl->data)->layout;
|
||||
}
|
||||
|
||||
if ( NULL == result ) {
|
||||
FontPerSize* fps = g_malloc( sizeof(*fps) );
|
||||
dctx->fontsPerSize = g_list_insert( dctx->fontsPerSize,
|
||||
fps, 0 );
|
||||
|
||||
char font[32];
|
||||
snprintf( font, sizeof(font), "helvetica normal %d", ht );
|
||||
|
||||
fps->layout = pango_layout_new( dctx->pangoContext );
|
||||
fps->fontdesc = pango_font_description_from_string( font );
|
||||
pango_layout_set_font_description( fps->layout, fps->fontdesc );
|
||||
|
||||
/* This only happens first time??? */
|
||||
pango_layout_set_alignment( fps->layout, PANGO_ALIGN_CENTER );
|
||||
fps->ht = ht;
|
||||
result = fps->layout;
|
||||
XP_LOGF( "There are %d fonts now", g_list_length( dctx->fontsPerSize ) );
|
||||
}
|
||||
|
||||
/* FontPerSize* fps = g_list_nth_data( dctx->fontsPerSize, 0 ); */
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_string_at( GtkDrawCtx* dctx, PangoLayout* layout, const char* str,
|
||||
draw_string_at( GtkDrawCtx* dctx, const char* str, XP_U16 fontHt,
|
||||
const XP_Rect* where, XP_GTK_JUST just,
|
||||
const GdkColor* frground, const GdkColor* bkgrnd )
|
||||
{
|
||||
PangoLayout* layout;
|
||||
gint x = where->left;
|
||||
gint y = where->top;
|
||||
|
||||
layout = layout_for_ht( dctx, fontHt );
|
||||
|
||||
pango_layout_set_text( layout, str, strlen(str) );
|
||||
|
||||
if ( just != XP_GTK_JUST_NONE ) {
|
||||
|
@ -217,22 +272,29 @@ drawBitmapFromLBS( GtkDrawCtx* dctx, XP_Bitmap bm, const XP_Rect* rect )
|
|||
g_object_unref( pm );
|
||||
} /* drawBitmapFromLBS */
|
||||
|
||||
static void
|
||||
freer( gpointer data, gpointer XP_UNUSED(user_data) )
|
||||
{
|
||||
FontPerSize* fps = (FontPerSize*)data;
|
||||
pango_font_description_free( fps->fontdesc );
|
||||
g_object_unref( fps->layout );
|
||||
g_free( fps );
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_draw_destroyCtxt( DrawCtx* p_dctx )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
GtkAllocation* alloc = &dctx->drawing_area->allocation;
|
||||
XP_U16 i;
|
||||
|
||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
||||
dctx->drawing_area->style->white_gc,
|
||||
TRUE,
|
||||
0, 0, alloc->width, alloc->height );
|
||||
|
||||
for ( i = LAYOUT_BOARD; i < LAYOUT_NLAYOUTS; ++i ) {
|
||||
pango_font_description_free( dctx->fontdesc[i] );
|
||||
g_object_unref( dctx->layout[i] );
|
||||
}
|
||||
g_list_foreach( dctx->fontsPerSize, freer, NULL );
|
||||
g_list_free( dctx->fontsPerSize );
|
||||
|
||||
g_object_unref( dctx->pangoContext );
|
||||
|
||||
} /* gtk_draw_destroyCtxt */
|
||||
|
@ -397,8 +459,8 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
|
|||
foreground = &dctx->playerColors[owner];
|
||||
}
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_BOARD], letter,
|
||||
&rectInset, XP_GTK_JUST_CENTER,
|
||||
draw_string_at( dctx, letter, rectInset.height,
|
||||
&rectInset, XP_GTK_JUST_CENTER,
|
||||
foreground, NULL );
|
||||
|
||||
if ( (flags & CELL_ISBLANK) != 0 ) {
|
||||
|
@ -416,7 +478,7 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
|
|||
}
|
||||
|
||||
if ( (flags & CELL_ISSTAR) != 0 ) {
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], "*",
|
||||
draw_string_at( dctx, "*", rect->height,
|
||||
rect, XP_GTK_JUST_CENTER,
|
||||
&dctx->black, NULL );
|
||||
}
|
||||
|
@ -495,7 +557,7 @@ gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
|||
|
||||
if ( !!textP ) {
|
||||
if ( *textP != LETTER_NONE ) { /* blank */
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_LARGE], textP,
|
||||
draw_string_at( dctx, textP, formatRect.height>>1,
|
||||
&formatRect, XP_GTK_JUST_TOPLEFT,
|
||||
foreground, NULL );
|
||||
|
||||
|
@ -507,7 +569,7 @@ gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
|||
sprintf( numbuf, "%d", val );
|
||||
len = strlen( numbuf );
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], numbuf,
|
||||
draw_string_at( dctx, numbuf, formatRect.height>>2,
|
||||
&formatRect, XP_GTK_JUST_BOTTOMRIGHT,
|
||||
foreground, NULL );
|
||||
|
||||
|
@ -555,7 +617,7 @@ gtk_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
dctx->drawGC, TRUE,
|
||||
r.left, r.top, r.width, r.height );
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_LARGE], "?",
|
||||
draw_string_at( dctx, "?", r.height,
|
||||
&r, XP_GTK_JUST_CENTER,
|
||||
&dctx->playerColors[dctx->trayOwner], NULL );
|
||||
|
||||
|
@ -628,7 +690,7 @@ gtk_draw_drawBoardArrow( DrawCtx* p_dctx, const XP_Rect* rectP,
|
|||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
const char* curs = vertical? "|":"-";
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_BOARD], curs,
|
||||
draw_string_at( dctx, curs, rectP->height,
|
||||
rectP, XP_GTK_JUST_CENTER,
|
||||
&dctx->black, NULL );
|
||||
drawHintBorders( dctx, rectP, hintAtts );
|
||||
|
@ -655,7 +717,7 @@ gtkDrawDrawRemText( DrawCtx* p_dctx, const XP_Rect* r, XP_U16 nTilesLeft,
|
|||
gint left = r->left;
|
||||
gint top = r->top;
|
||||
XP_Bool draw = !widthP;
|
||||
PangoLayout* layout = dctx->layout[LAYOUT_SMALL];
|
||||
PangoLayout* layout = layout_for_ht( dctx, r->height );
|
||||
|
||||
sprintf( buf, "rem:%d", nTilesLeft );
|
||||
pango_layout_set_text( layout, buf, strlen(buf) );
|
||||
|
@ -728,14 +790,14 @@ scoreWidthAndText( GtkDrawCtx* XP_UNUSED(dctx), PangoLayout* layout, char* buf,
|
|||
} /* scoreWidthAndText */
|
||||
|
||||
static void
|
||||
gtk_draw_measureScoreText( DrawCtx* p_dctx, const XP_Rect* XP_UNUSED(r),
|
||||
gtk_draw_measureScoreText( DrawCtx* p_dctx, const XP_Rect* r,
|
||||
const DrawScoreInfo* dsi,
|
||||
XP_U16* width, XP_U16* height )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
char buf[20];
|
||||
scoreWidthAndText( dctx, dctx->layout[LAYOUT_SMALL], buf, dsi,
|
||||
width, height );
|
||||
PangoLayout* layout = layout_for_ht( dctx, r->height );
|
||||
scoreWidthAndText( dctx, layout, buf, dsi, width, height );
|
||||
} /* gtk_draw_measureScoreText */
|
||||
|
||||
static void
|
||||
|
@ -747,7 +809,8 @@ gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
XP_U16 x;
|
||||
XP_U16 width;
|
||||
|
||||
scoreWidthAndText( dctx, dctx->layout[LAYOUT_SMALL], scoreBuf, dsi,
|
||||
PangoLayout* layout = layout_for_ht( dctx, rInner->height );
|
||||
scoreWidthAndText( dctx, layout, scoreBuf, dsi,
|
||||
&width, NULL );
|
||||
x = rInner->left + ((rInner->width - width) /2);
|
||||
|
||||
|
@ -760,7 +823,7 @@ gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
eraseRect( dctx, rInner );
|
||||
}
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], scoreBuf,
|
||||
draw_string_at( dctx, scoreBuf, rInner->height - 1,
|
||||
rInner, XP_GTK_JUST_CENTER,
|
||||
&dctx->playerColors[dsi->playerNum], NULL );
|
||||
|
||||
|
@ -776,13 +839,13 @@ gtk_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
char buf[5];
|
||||
XP_U16 left;
|
||||
XP_U16 ht;
|
||||
XP_Rect localR;
|
||||
|
||||
if ( score >= 0 ) {
|
||||
sprintf( buf, "%.3d", score );
|
||||
sprintf( buf, "%.3d", score );
|
||||
} else {
|
||||
strcpy( buf, "???" );
|
||||
strcpy( buf, "???" );
|
||||
}
|
||||
|
||||
/* gdk_gc_set_clip_rectangle( dctx->drawGC, (GdkRectangle*)rect ); */
|
||||
|
@ -791,11 +854,11 @@ gtk_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
insetRect( &localR, 1 );
|
||||
eraseRect( dctx, &localR );
|
||||
|
||||
left = localR.left + 1;
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], "Pts:",
|
||||
ht = localR.height >> 2;
|
||||
draw_string_at( dctx, "Pts:", ht,
|
||||
&localR, XP_GTK_JUST_TOPLEFT,
|
||||
&dctx->black, NULL );
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], buf,
|
||||
draw_string_at( dctx, buf, ht,
|
||||
&localR, XP_GTK_JUST_BOTTOMRIGHT,
|
||||
&dctx->black, NULL );
|
||||
|
||||
|
@ -831,7 +894,7 @@ gtk_draw_drawTimer( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
|
||||
/* gdk_gc_set_clip_rectangle( dctx->drawGC, (GdkRectangle*)rInner ); */
|
||||
eraseRect( dctx, rInner );
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], buf,
|
||||
draw_string_at( dctx, buf, rInner->height-1,
|
||||
rInner, XP_GTK_JUST_CENTER,
|
||||
&dctx->black, NULL );
|
||||
} /* gtk_draw_drawTimer */
|
||||
|
@ -870,8 +933,9 @@ gtk_draw_measureMiniWText( DrawCtx* p_dctx, const XP_UCHAR* str,
|
|||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
int height, width;
|
||||
|
||||
pango_layout_set_text( dctx->layout[LAYOUT_SMALL], str, strlen(str) );
|
||||
pango_layout_get_pixel_size( dctx->layout[LAYOUT_SMALL], &width, &height );
|
||||
PangoLayout* layout = layout_for_ht( dctx, GTKMIN_W_HT );
|
||||
pango_layout_set_text( layout, str, strlen(str) );
|
||||
pango_layout_get_pixel_size( layout, &width, &height );
|
||||
*heightP = height;
|
||||
*widthP = width + 6;
|
||||
} /* gtk_draw_measureMiniWText */
|
||||
|
@ -900,7 +964,7 @@ gtk_draw_drawMiniWindow( DrawCtx* p_dctx, const XP_UCHAR* text,
|
|||
eraseRect( dctx, &localR );
|
||||
frameRect( dctx, &localR );
|
||||
|
||||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], text,
|
||||
draw_string_at( dctx, text, localR.height-2,
|
||||
&localR, XP_GTK_JUST_CENTER,
|
||||
&dctx->black, NULL );
|
||||
} /* gtk_draw_drawMiniWindow */
|
||||
|
@ -933,34 +997,10 @@ allocAndSet( GdkColormap* map, GdkColor* color, unsigned short red,
|
|||
XP_ASSERT( success );
|
||||
} /* allocAndSet */
|
||||
|
||||
static void
|
||||
setupLayouts( GtkDrawCtx* dctx, GtkWidget* drawing_area )
|
||||
{
|
||||
XP_U16 i;
|
||||
const char* fonts[] = {
|
||||
/* "Luxi Mono 12", */
|
||||
"helvetica normal 10",
|
||||
"helvetica normal 8",
|
||||
"helvetica bold 14",
|
||||
};
|
||||
PangoContext* pangoContext = gtk_widget_get_pango_context( drawing_area );
|
||||
dctx->pangoContext = pangoContext;
|
||||
|
||||
for ( i = LAYOUT_BOARD; i < LAYOUT_NLAYOUTS; ++i ) {
|
||||
dctx->layout[i] = pango_layout_new( pangoContext );
|
||||
dctx->fontdesc[i] = pango_font_description_from_string( fonts[i] );
|
||||
pango_layout_set_font_description( dctx->layout[i],
|
||||
dctx->fontdesc[i] );
|
||||
}
|
||||
|
||||
pango_layout_set_alignment( dctx->layout[LAYOUT_BOARD],
|
||||
PANGO_ALIGN_CENTER );
|
||||
}
|
||||
|
||||
DrawCtx*
|
||||
gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals )
|
||||
{
|
||||
GtkDrawCtx* dctx = g_malloc( sizeof(GtkDrawCtx) );
|
||||
GtkDrawCtx* dctx = g_malloc0( sizeof(GtkDrawCtx) );
|
||||
GdkColormap* map;
|
||||
|
||||
short i;
|
||||
|
@ -1015,6 +1055,7 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals )
|
|||
/* SET_VTABLE_ENTRY( dctx, draw_frameBoard, gtk_ ); */
|
||||
/* SET_VTABLE_ENTRY( dctx, draw_frameTray, gtk_ ); */
|
||||
|
||||
dctx->pangoContext = gtk_widget_get_pango_context( drawing_area );
|
||||
dctx->drawing_area = drawing_area;
|
||||
dctx->globals = globals;
|
||||
|
||||
|
@ -1054,8 +1095,6 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals )
|
|||
allocAndSet( map, &dctx->tileBack, 0xFFFF, 0xFFFF, 0x9999 );
|
||||
allocAndSet( map, &dctx->red, 0xFFFF, 0x0000, 0x0000 );
|
||||
|
||||
setupLayouts( dctx, drawing_area );
|
||||
|
||||
return (DrawCtx*)dctx;
|
||||
} /* gtkDrawCtxtMake */
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <sys/time.h>
|
||||
#include <pango/pango-font.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "draw.h"
|
||||
#include "main.h"
|
||||
|
@ -53,8 +54,7 @@ typedef struct GtkDrawCtx {
|
|||
|
||||
/* new for gtk 2.0 */
|
||||
PangoContext* pangoContext;
|
||||
PangoFontDescription* fontdesc[LAYOUT_NLAYOUTS];
|
||||
PangoLayout* layout[LAYOUT_NLAYOUTS];
|
||||
GList* fontsPerSize;
|
||||
|
||||
XP_U16 trayOwner;
|
||||
XP_Bool topFocus;
|
||||
|
|
Loading…
Reference in a new issue