produce, store and display actual snapshot

Done in a way that won't work for Android just to try out the gtk
way. Tweaks and reuses the existing draw context and board, which is
precisely what the android version can't easily do.
This commit is contained in:
Eric House 2016-08-05 09:42:55 -07:00
parent aeee2d801a
commit 3c0a128266
8 changed files with 107 additions and 73 deletions

View file

@ -306,6 +306,12 @@ board_setDraw( BoardCtxt* board, DrawCtx* draw )
} }
} }
DrawCtx*
board_getDraw( const BoardCtxt* board )
{
return board->draw;
}
void void
board_writeToStream( const BoardCtxt* board, XWStreamCtxt* stream ) board_writeToStream( const BoardCtxt* board, XWStreamCtxt* stream )
{ {

View file

@ -65,6 +65,7 @@ BoardCtxt* board_makeFromStream( MPFORMAL XWStreamCtxt* stream,
DrawCtx* draw, XW_UtilCtxt* util, DrawCtx* draw, XW_UtilCtxt* util,
XP_U16 nPlayers ); XP_U16 nPlayers );
void board_setDraw( BoardCtxt* board, DrawCtx* draw ); void board_setDraw( BoardCtxt* board, DrawCtx* draw );
DrawCtx* board_getDraw( const BoardCtxt* board );
void board_destroy( BoardCtxt* board ); void board_destroy( BoardCtxt* board );

View file

@ -19,6 +19,9 @@
*/ */
#include "gamesdb.h" #include "gamesdb.h"
#include "gtkboard.h"
#include "gtkdraw.h"
#include "linuxutl.h"
#include "main.h" #include "main.h"
static void getColumnText( sqlite3_stmt *ppStmt, int iCol, XP_UCHAR* buf, static void getColumnText( sqlite3_stmt *ppStmt, int iCol, XP_UCHAR* buf,
@ -164,26 +167,24 @@ writeToDB( XWStreamCtxt* stream, void* closure )
} }
static void static void
addSnap( sqlite3* pDb, sqlite3_int64 curRow ) addSnap( CommonGlobals* cGlobals )
{ {
LOG_FUNC(); LOG_FUNC();
char* filename = "./red.png"; BoardCtxt* board = cGlobals->game.board;
GError *error = NULL; GtkDrawCtx* dctx = (GtkDrawCtx*)board_getDraw( board );
GdkPixbuf* snap = gdk_pixbuf_new_from_file_at_size( filename, 80, 80, &error ); addSurface( dctx, 100, 100 );
XP_ASSERT( !!snap ); board_invalAll( board );
board_draw( board );
board_invalAll( board );
gchar* buffer; XWStreamCtxt* stream = make_simple_stream( cGlobals );
gsize buffer_size; getImage( dctx, stream );
gboolean worked = gdk_pixbuf_save_to_buffer( snap, &buffer, &buffer_size, removeSurface( dctx );
"png", &error, NULL ); sqlite3_int64 newRow = writeBlobColumnStream( stream, cGlobals->pDb,
XP_ASSERT( worked ); cGlobals->selRow, "snap" );
sqlite3_int64 newRow = writeBlobColumnData( (const XP_U8*)buffer, buffer_size, XP_ASSERT( cGlobals->selRow == newRow );
CUR_STREAM_VERS, pDb, curRow, "snap" ); stream_destroy( stream );
XP_ASSERT( curRow == newRow );
g_free( buffer );
g_object_unref( snap );
} }
void void
@ -255,7 +256,7 @@ summarize( CommonGlobals* cGlobals )
sqlite3_finalize( stmt ); sqlite3_finalize( stmt );
XP_USE( result ); XP_USE( result );
addSnap( cGlobals->pDb, cGlobals->selRow ); addSnap( cGlobals );
} }
GSList* GSList*

View file

@ -45,6 +45,7 @@ typedef struct GtkDrawCtx {
/* GdkDrawable* pixmap; */ /* GdkDrawable* pixmap; */
GtkWidget* drawing_area; GtkWidget* drawing_area;
cairo_surface_t* surface;
struct GtkGameGlobals* globals; struct GtkGameGlobals* globals;
#ifdef USE_CAIRO #ifdef USE_CAIRO
@ -62,8 +63,6 @@ typedef struct GtkDrawCtx {
GdkRGBA bonusColors[4]; GdkRGBA bonusColors[4];
GdkRGBA playerColors[MAX_NUM_PLAYERS]; GdkRGBA playerColors[MAX_NUM_PLAYERS];
/* new for gtk 2.0 */
PangoContext* pangoContext;
GList* fontsPerSize; GList* fontsPerSize;
struct { struct {

View file

@ -62,12 +62,6 @@ gtkInsetRect( XP_Rect* r, short i )
r->height -= i; r->height -= i;
} /* gtkInsetRect */ } /* gtkInsetRect */
#if 0
#define DRAW_WHAT(dc) ((dc)->globals->pixmap)
#else
#define DRAW_WHAT(dc) (gtk_widget_get_window((dc)->drawing_area))
#endif
#define GTKMIN_W_HT 12 #define GTKMIN_W_HT 12
#ifdef USE_CAIRO #ifdef USE_CAIRO
@ -87,7 +81,15 @@ initCairo( GtkDrawCtx* dctx )
{ {
/* XP_LOGF( "%s(dctx=%p)", __func__, dctx ); */ /* XP_LOGF( "%s(dctx=%p)", __func__, dctx ); */
XP_ASSERT( !dctx->_cairo ); XP_ASSERT( !dctx->_cairo );
cairo_t* cairo = gdk_cairo_create( gtk_widget_get_window(dctx->drawing_area) ); cairo_t* cairo = NULL;
if ( !!dctx->surface ) {
cairo = cairo_create( dctx->surface );
} else if ( !!dctx->drawing_area ) {
cairo = gdk_cairo_create( gtk_widget_get_window(dctx->drawing_area) );
} else {
XP_ASSERT( 0 );
}
XP_Bool inited = !!cairo; XP_Bool inited = !!cairo;
if ( inited ) { if ( inited ) {
dctx->_cairo = cairo; dctx->_cairo = cairo;
@ -116,8 +118,6 @@ getCairo( const GtkDrawCtx* dctx )
static void static void
draw_rectangle( const GtkDrawCtx* dctx, draw_rectangle( const GtkDrawCtx* dctx,
GDKDRAWABLE* XP_UNUSED_CAIRO(drawable),
GDKGC* XP_UNUSED_CAIRO(gc),
gboolean fill, gint left, gint top, gint width, gboolean fill, gint left, gint top, gint width,
gint height ) gint height )
{ {
@ -154,9 +154,8 @@ static void
gtkFillRect( GtkDrawCtx* dctx, const XP_Rect* rect, const GdkRGBA* color ) gtkFillRect( GtkDrawCtx* dctx, const XP_Rect* rect, const GdkRGBA* color )
{ {
gtkSetForeground( dctx, color ); gtkSetForeground( dctx, color );
draw_rectangle( dctx, DRAW_WHAT(dctx), NULL, TRUE, draw_rectangle( dctx, TRUE, rect->left, rect->top,
rect->left, rect->top, rect->width, rect->width, rect->height );
rect->height );
} }
static void static void
@ -175,8 +174,7 @@ gtkEraseRect( const GtkDrawCtx* dctx, const XP_Rect* rect )
{ {
set_color_cairo( dctx, 0xFFFF, 0xFFFF, 0xFFFF ); set_color_cairo( dctx, 0xFFFF, 0xFFFF, 0xFFFF );
// const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area ); // const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area );
draw_rectangle( dctx, DRAW_WHAT(dctx), NULL, //style->white_gc, draw_rectangle( dctx, TRUE, rect->left, rect->top,
TRUE, rect->left, rect->top,
rect->width, rect->height ); rect->width, rect->height );
} /* gtkEraseRect */ } /* gtkEraseRect */
@ -266,7 +264,9 @@ layout_for_ht( GtkDrawCtx* dctx, XP_U16 ht )
char font[32]; char font[32];
snprintf( font, sizeof(font), "helvetica normal %dpx", ht ); snprintf( font, sizeof(font), "helvetica normal %dpx", ht );
layout = pango_layout_new( dctx->pangoContext ); PangoContext* pc = pango_cairo_create_context( getCairo(dctx) );
layout = pango_layout_new( pc );
g_object_unref( pc );
fps->fontdesc = pango_font_description_from_string( font ); fps->fontdesc = pango_font_description_from_string( font );
pango_layout_set_font_description( layout, fps->fontdesc ); pango_layout_set_font_description( layout, fps->fontdesc );
fps->layout = g_object_ref( layout ); fps->layout = g_object_ref( layout );
@ -352,7 +352,7 @@ drawBitmapFromLBS( GtkDrawCtx* dctx, const XP_Bitmap bm, const XP_Rect* rect )
nBytes = lbs->nBytes; nBytes = lbs->nBytes;
#ifdef USE_CAIRO #ifdef USE_CAIRO
draw_rectangle( dctx, NULL, NULL, TRUE, 0, 0, nCols, nRows ); draw_rectangle( dctx, TRUE, 0, 0, nCols, nRows );
#else #else
const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area ); const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area );
GdkPixmap* pm = gdk_pixmap_new( DRAW_WHAT(dctx), nCols, nRows, -1 ); GdkPixmap* pm = gdk_pixmap_new( DRAW_WHAT(dctx), nCols, nRows, -1 );
@ -417,8 +417,7 @@ gtk_draw_destroyCtxt( DrawCtx* p_dctx )
gtk_widget_get_allocation( dctx->drawing_area, &alloc ); gtk_widget_get_allocation( dctx->drawing_area, &alloc );
#ifdef USE_CAIRO #ifdef USE_CAIRO
draw_rectangle( dctx, NULL, NULL, TRUE, draw_rectangle( dctx, TRUE, 0, 0, alloc.width, alloc.height );
0, 0, alloc.width, alloc.height );
#else #else
const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area ); const GtkStyle* style = gtk_widget_get_style( dctx->drawing_area );
draw_rectangle( dctx, DRAW_WHAT(dctx), style->white_gc, TRUE, draw_rectangle( dctx, DRAW_WHAT(dctx), style->white_gc, TRUE,
@ -428,8 +427,6 @@ gtk_draw_destroyCtxt( DrawCtx* p_dctx )
g_list_foreach( dctx->fontsPerSize, freer, NULL ); g_list_foreach( dctx->fontsPerSize, freer, NULL );
g_list_free( dctx->fontsPerSize ); g_list_free( dctx->fontsPerSize );
g_object_unref( dctx->pangoContext );
} /* gtk_draw_destroyCtxt */ } /* gtk_draw_destroyCtxt */
@ -535,25 +532,21 @@ drawHintBorders( GtkDrawCtx* dctx, const XP_Rect* rect, HintAtts hintAtts)
gtkSetForeground( dctx, &dctx->black ); gtkSetForeground( dctx, &dctx->black );
if ( (hintAtts & HINT_BORDER_LEFT) != 0 ) { if ( (hintAtts & HINT_BORDER_LEFT) != 0 ) {
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, lrect.left, lrect.top,
NULL, FALSE, lrect.left, lrect.top,
0, lrect.height); 0, lrect.height);
} }
if ( (hintAtts & HINT_BORDER_TOP) != 0 ) { if ( (hintAtts & HINT_BORDER_TOP) != 0 ) {
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, lrect.left, lrect.top,
NULL, FALSE, lrect.left, lrect.top,
lrect.width, 0/*rectInset.height*/); lrect.width, 0/*rectInset.height*/);
} }
if ( (hintAtts & HINT_BORDER_RIGHT) != 0 ) { if ( (hintAtts & HINT_BORDER_RIGHT) != 0 ) {
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, lrect.left+lrect.width,
NULL, FALSE, lrect.left+lrect.width,
lrect.top, lrect.top,
0, lrect.height); 0, lrect.height);
} }
if ( (hintAtts & HINT_BORDER_BOTTOM) != 0 ) { if ( (hintAtts & HINT_BORDER_BOTTOM) != 0 ) {
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, lrect.left,
NULL, FALSE, lrect.left, lrect.top+lrect.height,
lrect.top+lrect.height,
lrect.width, 0 ); lrect.width, 0 );
} }
} }
@ -609,11 +602,8 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
#else #else
gdk_gc_set_foreground( dctx->drawGC, &dctx->black ); gdk_gc_set_foreground( dctx->drawGC, &dctx->black );
#endif #endif
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, rect->left, rect->top,
NULL, rect->width, rect->height );
FALSE,
rect->left, rect->top, rect->width,
rect->height );
} }
/* We draw just an empty, potentially colored, square IFF there's nothing /* We draw just an empty, potentially colored, square IFF there's nothing
@ -654,8 +644,7 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
} else if ( !highlight ) { } else if ( !highlight ) {
gtkSetForeground( dctx, &dctx->tileBack ); gtkSetForeground( dctx, &dctx->tileBack );
} }
draw_rectangle( dctx, DRAW_WHAT(dctx), NULL, TRUE, draw_rectangle( dctx, TRUE, rectInset.left, rectInset.top,
rectInset.left, rectInset.top,
rectInset.width+1, rectInset.height+1 ); rectInset.width+1, rectInset.height+1 );
if ( isBlank && 0 == strcmp("_",letter ) ) { if ( isBlank && 0 == strcmp("_",letter ) ) {
@ -771,17 +760,13 @@ gtkDrawTileImpl( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
/* frame the tile */ /* frame the tile */
gtkSetForeground( dctx, &dctx->black ); gtkSetForeground( dctx, &dctx->black );
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE,
NULL, insetR.left, insetR.top, insetR.width,
FALSE,
insetR.left, insetR.top, insetR.width,
insetR.height ); insetR.height );
if ( (flags & CELL_HIGHLIGHT) != 0 ) { if ( (flags & CELL_HIGHLIGHT) != 0 ) {
gtkInsetRect( &insetR, 1 ); gtkInsetRect( &insetR, 1 );
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, FALSE, insetR.left, insetR.top,
NULL,
FALSE, insetR.left, insetR.top,
insetR.width, insetR.height); insetR.width, insetR.height);
} }
} }
@ -848,9 +833,7 @@ gtk_draw_drawTrayDivider( DrawCtx* p_dctx, const XP_Rect* rect,
} }
gtkSetForeground( dctx, &dctx->black ); gtkSetForeground( dctx, &dctx->black );
draw_rectangle( dctx, DRAW_WHAT(dctx), draw_rectangle( dctx, !selected,
NULL,
!selected,
r.left, r.top, r.width, r.height); r.left, r.top, r.width, r.height);
} /* gtk_draw_drawTrayDivider */ } /* gtk_draw_drawTrayDivider */
@ -1000,8 +983,7 @@ gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
} }
} }
draw_rectangle( dctx, DRAW_WHAT(dctx), NULL, draw_rectangle( dctx, TRUE, selRect.left, selRect.top,
TRUE, selRect.left, selRect.top,
selRect.width, selRect.height ); selRect.width, selRect.height );
if ( hasCursor ) { if ( hasCursor ) {
gtkFillRect( dctx, rInner, cursor ); gtkFillRect( dctx, rInner, cursor );
@ -1443,7 +1425,6 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkGameGlobals* globals )
SET_VTABLE_ENTRY( dctx->vtable, draw_dictChanged, gtk ); SET_VTABLE_ENTRY( dctx->vtable, draw_dictChanged, gtk );
#endif #endif
dctx->pangoContext = gtk_widget_get_pango_context( drawing_area );
dctx->drawing_area = drawing_area; dctx->drawing_area = drawing_area;
dctx->globals = globals; dctx->globals = globals;
@ -1485,6 +1466,42 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkGameGlobals* globals )
return (DrawCtx*)dctx; return (DrawCtx*)dctx;
} /* gtkDrawCtxtMake */ } /* gtkDrawCtxtMake */
void
addSurface( GtkDrawCtx* dctx, int width, int height )
{
XP_ASSERT( !dctx->surface );
dctx->surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, width, height );
XP_ASSERT( !!dctx->surface );
}
void
removeSurface( GtkDrawCtx* dctx )
{
XP_ASSERT( !!dctx->surface );
g_object_unref( dctx->surface );
dctx->surface = NULL;
}
static cairo_status_t
write_func( void *closure, const unsigned char *data,
unsigned int length )
{
XWStreamCtxt* stream = (XWStreamCtxt*)closure;
stream_putBytes( stream, data, length );
return CAIRO_STATUS_SUCCESS;
}
void
getImage( GtkDrawCtx* dctx, XWStreamCtxt* stream )
{
LOG_FUNC();
XP_ASSERT( !!dctx->surface );
cairo_status_t status =
cairo_surface_write_to_png_stream( dctx->surface,
write_func, stream );
XP_ASSERT( CAIRO_STATUS_SUCCESS == status );
}
void void
draw_gtk_status( GtkDrawCtx* dctx, char ch ) draw_gtk_status( GtkDrawCtx* dctx, char ch )
{ {

View file

@ -26,5 +26,8 @@ DrawCtx* gtkDrawCtxtMake( GtkWidget *widget, GtkGameGlobals* globals );
void draw_gtk_status( GtkDrawCtx* draw, char ch ); void draw_gtk_status( GtkDrawCtx* draw, char ch );
void frame_active_rect( GtkDrawCtx* dctx, const XP_Rect* rect ); void frame_active_rect( GtkDrawCtx* dctx, const XP_Rect* rect );
void addSurface( GtkDrawCtx* dctx, int width, int height );
void removeSurface( GtkDrawCtx* dctx );
void getImage( GtkDrawCtx* dctx, XWStreamCtxt* stream );
#endif #endif

View file

@ -663,6 +663,16 @@ storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 msglen,
return inUse; return inUse;
} }
XWStreamCtxt*
make_simple_stream( CommonGlobals* cGlobals )
{
XWStreamCtxt* stream =
mem_stream_make( MPPARM(cGlobals->util->mpool)
cGlobals->params->vtMgr,
cGlobals, CHANNEL_NONE, NULL );
return stream;
}
void void
writeNoConnMsgs( CommonGlobals* cGlobals, int fd ) writeNoConnMsgs( CommonGlobals* cGlobals, int fd )
{ {
@ -675,10 +685,7 @@ writeNoConnMsgs( CommonGlobals* cGlobals, int fd )
guint nMsgs = g_slist_length( list ); guint nMsgs = g_slist_length( list );
XP_ASSERT( 0 < nMsgs ); XP_ASSERT( 0 < nMsgs );
XWStreamCtxt* stream = XWStreamCtxt* stream = make_simple_stream( cGlobals );
mem_stream_make( MPPARM(cGlobals->util->mpool)
cGlobals->params->vtMgr,
cGlobals, CHANNEL_NONE, NULL );
stream_putU16( stream, 1 ); /* number of relayIDs */ stream_putU16( stream, 1 ); /* number of relayIDs */
stream_catString( stream, relayID ); stream_catString( stream, relayID );
stream_putU8( stream, '\n' ); stream_putU8( stream, '\n' );

View file

@ -47,7 +47,7 @@ void initNoConnStorage( CommonGlobals* cGlobals );
XP_Bool storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len, XP_Bool storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len,
const XP_UCHAR* relayID ); const XP_UCHAR* relayID );
void writeNoConnMsgs( CommonGlobals* cGlobals, int fd ); void writeNoConnMsgs( CommonGlobals* cGlobals, int fd );
XWStreamCtxt* make_simple_stream( CommonGlobals* cGlobals );
#ifdef STREAM_VERS_BIGBOARD #ifdef STREAM_VERS_BIGBOARD
void setSquareBonuses( const CommonGlobals* cGlobals ); void setSquareBonuses( const CommonGlobals* cGlobals );