Draw into the whole window, not its top-left 320x200
The graphics verbs documented a coordinate transform that did not exist. With SCALE off a coordinate went straight to akgl_draw_* as a pixel address, so an 800x600 window drew a C128 listing into its corner and left the rest unused -- while the chapter said coordinates were 320x200 and stretching to fit was the host's business. akbasic_GraphicsBackend gains a size entry point, require_graphics() asks it before every verb that draws so a resized window is honoured between two statements, and 320x200 becomes the fallback for a backend that leaves it NULL. It is the record's one optional member, so a host written against the old header keeps the behaviour it had. SCALE now maps onto the device, and RGR(1)/RGR(2) report the drawing surface so a program can use a window whose size it did not choose. RGR(0) is BASIC 7.0's own field, the GRAPHIC mode. SCALE also mapped xmax onto the width rather than onto the last pixel, so SCALE 1, 319, 199 followed by DRAW 1, 319, 199 drew nothing at all -- one pixel past the surface. Fixed in the same line, because it is what makes "SCALE gives a C128 listing the whole window" true rather than nearly true. The akgl test renders against a 128x128 target, deliberately smaller than the old constants: a SCALE still dividing by them misses it entirely rather than landing somewhere plausible. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,27 @@ static akerr_ErrorContext *state_of(akbasic_GraphicsBackend *self, akbasic_AkglG
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief How big the renderer's output is, which is the space BASIC draws into.
|
||||
*
|
||||
* SDL_GetCurrentRenderOutputSize rather than the window size: the two differ on
|
||||
* a high-DPI display and on a renderer with a logical presentation set, and it
|
||||
* is the output that a coordinate handed to akgl_draw_point actually indexes.
|
||||
*/
|
||||
static akerr_ErrorContext *gfx_size(akbasic_GraphicsBackend *self, int *width, int *height)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
akbasic_AkglGraphics *state = NULL;
|
||||
|
||||
PASS(errctx, state_of(self, &state));
|
||||
FAIL_ZERO_RETURN(errctx, (width != NULL && height != NULL), AKERR_NULLPOINTER,
|
||||
"NULL destination in gfx_size");
|
||||
FAIL_ZERO_RETURN(errctx,
|
||||
SDL_GetCurrentRenderOutputSize(state->renderer->sdl_renderer, width, height),
|
||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
static akerr_ErrorContext *gfx_point(akbasic_GraphicsBackend *self, double x, double y, akbasic_Color color)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
@@ -134,9 +155,7 @@ static akerr_ErrorContext *gfx_clear(akbasic_GraphicsBackend *self, akbasic_Colo
|
||||
int h = 0;
|
||||
|
||||
PASS(errctx, state_of(self, &state));
|
||||
FAIL_ZERO_RETURN(errctx,
|
||||
SDL_GetCurrentRenderOutputSize(state->renderer->sdl_renderer, &w, &h),
|
||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||
PASS(errctx, gfx_size(self, &w, &h));
|
||||
|
||||
/*
|
||||
* A filled rectangle over the output rather than SDL_RenderClear, because
|
||||
@@ -231,6 +250,7 @@ akerr_ErrorContext *akbasic_graphics_init_akgl(akbasic_GraphicsBackend *obj, akb
|
||||
state->renderer = renderer;
|
||||
|
||||
obj->self = state;
|
||||
obj->size = gfx_size;
|
||||
obj->point = gfx_point;
|
||||
obj->line = gfx_line;
|
||||
obj->rect = gfx_rect;
|
||||
|
||||
Reference in New Issue
Block a user