X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/3fee7a57faa025c2785c79625075761e91e98dba..badb093da17186904490aa99fccd09fdf3925e79:/windows.c diff --git a/windows.c b/windows.c index b93847d..0cf8148 100644 --- a/windows.c +++ b/windows.c @@ -1,14 +1,5 @@ /* * windows.c: Windows front end for my puzzle collection. - * - * TODO: - * - * - Figure out what to do if a puzzle requests a size bigger than - * the screen will take. In principle we could put scrollbars in - * the window, although that would be pretty horrid. Another - * option is to detect in advance that this will be a problem - - * we can probably tell this using midend_size() before actually - * generating the puzzle - and simply refuse to do it. */ #include @@ -90,6 +81,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 +146,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 */ @@ -257,6 +330,24 @@ void draw_line(frontend *fe, int x1, int y1, int x2, int y2, int colour) SelectObject(fe->hdc_bm, oldpen); } +void draw_circle(frontend *fe, int cx, int cy, int radius, + int fill, int colour) +{ + if (fill) { + HBRUSH oldbrush = SelectObject(fe->hdc_bm, fe->brushes[colour]); + HPEN oldpen = SelectObject(fe->hdc_bm, fe->pens[colour]); + Ellipse(fe->hdc_bm, cx - radius, cy - radius, + cx + radius + 1, cy + radius + 1); + SelectObject(fe->hdc_bm, oldbrush); + SelectObject(fe->hdc_bm, oldpen); + } else { + HPEN oldpen = SelectObject(fe->hdc_bm, fe->pens[colour]); + MoveToEx(fe->hdc_bm, cx + radius, cy, NULL); + AngleArc(fe->hdc_bm, cx, cy, radius, 0.0F, 360.0F); + SelectObject(fe->hdc_bm, oldpen); + } +} + void draw_polygon(frontend *fe, int *coords, int npoints, int fill, int colour) {