New front end functions to save and restore a region of the puzzle

bitmap. Can be used to implement sprite-like animations: for
example, useful for games that wish to implement a user interface
which involves dragging an object around the playing area.

[originally from svn r5987]
This commit is contained in:
Simon Tatham
2005-06-22 08:30:31 +00:00
parent 64fbdf60ee
commit b176767dfa
4 changed files with 186 additions and 0 deletions

51
gtk.c
View File

@ -334,6 +334,57 @@ void draw_polygon(frontend *fe, int *coords, int npoints,
sfree(points);
}
struct blitter {
GdkPixmap *pixmap;
int w, h, x, y;
};
blitter *blitter_new(int w, int h)
{
/*
* We can't create the pixmap right now, because fe->window
* might not yet exist. So we just cache w and h and create it
* during the firs call to blitter_save.
*/
blitter *bl = snew(blitter);
bl->pixmap = NULL;
bl->w = w;
bl->h = h;
return bl;
}
void blitter_free(blitter *bl)
{
if (bl->pixmap)
gdk_pixmap_unref(bl->pixmap);
sfree(bl);
}
void blitter_save(frontend *fe, blitter *bl, int x, int y)
{
if (!bl->pixmap)
bl->pixmap = gdk_pixmap_new(fe->area->window, bl->w, bl->h, -1);
bl->x = x;
bl->y = y;
gdk_draw_pixmap(bl->pixmap,
fe->area->style->fg_gc[GTK_WIDGET_STATE(fe->area)],
fe->pixmap,
x, y, 0, 0, bl->w, bl->h);
}
void blitter_load(frontend *fe, blitter *bl, int x, int y)
{
assert(bl->pixmap);
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
x = bl->x;
y = bl->y;
}
gdk_draw_pixmap(fe->pixmap,
fe->area->style->fg_gc[GTK_WIDGET_STATE(fe->area)],
bl->pixmap,
0, 0, x, y, bl->w, bl->h);
}
void draw_update(frontend *fe, int x, int y, int w, int h)
{
if (fe->bbox_l > x ) fe->bbox_l = x ;

42
osx.m
View File

@ -1232,6 +1232,48 @@ void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize,
[string drawAtPoint:point withAttributes:attr];
}
struct blitter {
int w, h;
int x, y;
NSImage *img;
};
blitter *blitter_new(int w, int h)
{
blitter *bl = snew(blitter);
bl->x = bl->y = -1;
bl->w = w;
bl->h = h;
bl->img = [[NSImage alloc] initWithSize:NSMakeSize(w, h)];
[bl->img setFlipped:YES];
return bl;
}
void blitter_free(blitter *bl)
{
[bl->img release];
sfree(bl);
}
void blitter_save(frontend *fe, blitter *bl, int x, int y)
{
[fe->image unlockFocus];
[bl->img lockFocus];
[fe->image drawInRect:NSMakeRect(0, 0, bl->w, bl->h)
fromRect:NSMakeRect(x, y, bl->w, bl->h)
operation:NSCompositeCopy fraction:1.0];
[bl->img unlockFocus];
[fe->image lockFocus];
bl->x = x;
bl->y = y;
}
void blitter_load(frontend *fe, blitter *bl, int x, int y)
{
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
x = bl->x;
y = bl->y;
}
[bl->img drawInRect:NSMakeRect(x, y, bl->w, bl->h)
fromRect:NSMakeRect(0, 0, bl->w, bl->h)
operation:NSCompositeCopy fraction:1.0];
}
void draw_update(frontend *fe, int x, int y, int w, int h)
{
[fe->view setNeedsDisplayInRect:NSMakeRect(x,y,w,h)];

View File

@ -74,6 +74,7 @@ typedef struct game_aux_info game_aux_info;
typedef struct game_ui game_ui;
typedef struct game_drawstate game_drawstate;
typedef struct game game;
typedef struct blitter blitter;
#define ALIGN_VNORMAL 0x000
#define ALIGN_VCENTRE 0x100
@ -146,6 +147,16 @@ void activate_timer(frontend *fe);
void status_bar(frontend *fe, char *text);
void get_random_seed(void **randseed, int *randseedsize);
blitter *blitter_new(int w, int h);
void blitter_free(blitter *bl);
/* save puts the portion of the current display with top-left corner
* (x,y) to the blitter. load puts it back again to the specified
* coords, or else wherever it was saved from
* (if x = y = BLITTER_FROMSAVED). */
void blitter_save(frontend *fe, blitter *bl, int x, int y);
#define BLITTER_FROMSAVED (-1)
void blitter_load(frontend *fe, blitter *bl, int x, int y);
/*
* midend.c
*/

View File

@ -90,6 +90,12 @@ struct cfg_aux {
int ctlid;
};
struct blitter {
HBITMAP bitmap;
frontend *fe;
int x, y, w, h;
};
struct frontend {
midend_data *me;
HWND hwnd, statusbar, cfgbox;
@ -149,6 +155,82 @@ void status_bar(frontend *fe, char *text)
}
}
blitter *blitter_new(int w, int h)
{
blitter *bl = snew(blitter);
memset(bl, 0, sizeof(blitter));
bl->w = w;
bl->h = h;
bl->bitmap = 0;
return bl;
}
void blitter_free(blitter *bl)
{
if (bl->bitmap) DeleteObject(bl->bitmap);
sfree(bl);
}
static void blitter_mkbitmap(frontend *fe, blitter *bl)
{
HDC hdc = GetDC(fe->hwnd);
bl->bitmap = CreateCompatibleBitmap(hdc, bl->w, bl->h);
ReleaseDC(fe->hwnd, hdc);
}
/* BitBlt(dstDC, dstX, dstY, dstW, dstH, srcDC, srcX, srcY, dType) */
void blitter_save(frontend *fe, blitter *bl, int x, int y)
{
HDC hdc_win, hdc_blit;
HBITMAP prev_blit;
if (!bl->bitmap) blitter_mkbitmap(fe, bl);
bl->x = x; bl->y = y;
hdc_win = GetDC(fe->hwnd);
hdc_blit = CreateCompatibleDC(hdc_win);
if (!hdc_blit) fatal("hdc_blit failed: 0x%x", GetLastError());
prev_blit = SelectObject(hdc_blit, bl->bitmap);
if (prev_blit == NULL || prev_blit == HGDI_ERROR)
fatal("SelectObject for hdc_main failed: 0x%x", GetLastError());
if (!BitBlt(hdc_blit, 0, 0, bl->w, bl->h,
fe->hdc_bm, x, y, SRCCOPY))
fatal("BitBlt failed: 0x%x", GetLastError());
SelectObject(hdc_blit, prev_blit);
DeleteDC(hdc_blit);
ReleaseDC(fe->hwnd, hdc_win);
}
void blitter_load(frontend *fe, blitter *bl, int x, int y)
{
HDC hdc_win, hdc_blit;
HBITMAP prev_blit;
assert(bl->bitmap); /* we should always have saved before loading */
if (x == BLITTER_FROMSAVED) x = bl->x;
if (y == BLITTER_FROMSAVED) y = bl->y;
hdc_win = GetDC(fe->hwnd);
hdc_blit = CreateCompatibleDC(hdc_win);
prev_blit = SelectObject(hdc_blit, bl->bitmap);
BitBlt(fe->hdc_bm, x, y, bl->w, bl->h,
hdc_blit, 0, 0, SRCCOPY);
SelectObject(hdc_blit, prev_blit);
DeleteDC(hdc_blit);
ReleaseDC(fe->hwnd, hdc_win);
}
void frontend_default_colour(frontend *fe, float *output)
{
DWORD c = GetSysColor(COLOR_MENU); /* ick */