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:
@@ -148,6 +148,43 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_draw_reaches_pixels(void)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The renderer's own size is the space BASIC draws into.
|
||||
*
|
||||
* The one test that puts a real SDL renderer behind item 9. The target here is
|
||||
* 128x128 -- deliberately *smaller* than the 320x200 fallback -- so a `SCALE`
|
||||
* that still divided by the old constants would put its far corner at 2.5 times
|
||||
* the target's width and light nothing at all.
|
||||
*/
|
||||
static akerr_ErrorContext AKERR_NOIGNORE *test_size_is_the_renderer(void)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
SDL_Surface *shot = NULL;
|
||||
|
||||
PASS(errctx, clear_target());
|
||||
PASS(errctx, start_runtime("10 PRINT RGR(1)\n20 PRINT RGR(2)\n"));
|
||||
TEST_REQUIRE_STR(OUTPUT, "128\n128\n");
|
||||
stop_runtime();
|
||||
|
||||
PASS(errctx, clear_target());
|
||||
PASS(errctx, start_runtime("10 SCALE 1, 1000, 1000\n"
|
||||
"20 DRAW 1, 1000, 1000\n"));
|
||||
TEST_REQUIRE_STR(OUTPUT, "");
|
||||
|
||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||
/*
|
||||
* The far corner of the user space lands on the far corner of the target.
|
||||
* The old code divided by the 320x200 constants, which would have put this
|
||||
* at (400, 400) -- off a 128x128 surface entirely, lighting nothing.
|
||||
*/
|
||||
TEST_REQUIRE(pixel_is(shot, TARGET_SIZE - 1, TARGET_SIZE - 1, 0xff, 0xff, 0xff),
|
||||
"SCALE 1,1000,1000 then DRAW 1,1000,1000 should reach the bottom-right pixel");
|
||||
SDL_DestroySurface(shot);
|
||||
stop_runtime();
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/** @brief A BOX outlines: its corners are lit and its middle is not. */
|
||||
static akerr_ErrorContext AKERR_NOIGNORE *test_box_outlines(void)
|
||||
{
|
||||
@@ -519,6 +556,7 @@ int main(void)
|
||||
"Couldn't open %s: %s", AKBASIC_TEST_FONT, SDL_GetError());
|
||||
|
||||
CATCH(errctx, test_draw_reaches_pixels());
|
||||
CATCH(errctx, test_size_is_the_renderer());
|
||||
CATCH(errctx, test_box_outlines());
|
||||
CATCH(errctx, test_paint_fills_region());
|
||||
CATCH(errctx, test_shape_roundtrip());
|
||||
|
||||
Reference in New Issue
Block a user