From ad351155da49bf53213589ce9fd5756d5af411f3 Mon Sep 17 00:00:00 2001 From: peony Date: Sat, 19 Oct 2024 17:35:20 +0200 Subject: [PATCH] Added `put_scaled`. --- sysdata/libraries/render/src/lib.hb | 1 + sysdata/libraries/render/src/software.hb | 106 +++++++++++++++--- .../render_example/src/examples/scale.hb | 17 +++ sysdata/programs/render_example/src/main.hb | 2 +- sysdata/system_config.toml | 8 +- 5 files changed, 111 insertions(+), 23 deletions(-) create mode 100644 sysdata/programs/render_example/src/examples/scale.hb diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb index 3bb56c3..526daa4 100644 --- a/sysdata/libraries/render/src/lib.hb +++ b/sysdata/libraries/render/src/lib.hb @@ -62,6 +62,7 @@ put_filled_rect := mode.put_filled_rect put_line := mode.put_line clear := mode.clear put_surface := mode.put_surface +put_scaled := mode.put_scaled // thanks peony for these three! put_trirect := mode.put_trirect put_vline := mode.put_vline diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index ae8905b..8151328 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -23,18 +23,18 @@ sync := fn(surface: Surface): void { return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height)) } -screenidx := fn(surface: Surface, x: int, y: int): int { - return x + surface.width * y +surfaceidx := fn(surface: Surface, x: int, y: int): ^Color { + return surface.buf + x + surface.width * y } put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void { - *(surface.buf + @inline(screenidx, surface, pos.x, pos.y)) = color + *@inline(surfaceidx, surface, pos.x, pos.y) = color return } put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { - top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) - bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y - 1) + top_start_idx := @inline(surfaceidx, surface, pos.x, pos.y) + bottom_start_idx := @inline(surfaceidx, surface, pos.x, pos.y + tr.y - 1) rows_to_fill := tr.y loop if rows_to_fill <= 1 break else { @@ -54,19 +54,19 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Co } put_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { - start_idx := @inline(screenidx, surface, pos.x, pos.y) - end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y) - right_start_idx := @inline(screenidx, surface, pos.x + tr.x, pos.y) + start_idx := @inline(surfaceidx, surface, pos.x, pos.y) + end_idx := @inline(surfaceidx, surface, pos.x, pos.y + tr.y) + right_start_idx := @inline(surfaceidx, surface, pos.x + tr.x, pos.y) loop if start_idx > end_idx break else { - *(surface.buf + start_idx) = color; - *(surface.buf + right_start_idx) = color + *start_idx = color; + *right_start_idx = color start_idx += surface.width right_start_idx += surface.width } - @inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y), @bitcast(tr.x + 1)) - @inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) + @inline(memory.set, Color, &color, @inline(surfaceidx, surface, pos.x, pos.y), @bitcast(tr.x + 1)) + @inline(memory.set, Color, &color, @inline(surfaceidx, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) return } @@ -83,7 +83,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color) y := p0.y x := p0.x loop if x == p1.x break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(surfaceidx, surface, x, y) = color if D > 0 { y += yi D += 2 * (dy - dx) @@ -107,7 +107,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color x := p0.x y := p0.y loop if y == p1.y break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(surfaceidx, surface, x, y) = color if D > 0 { x += xi D += 2 * (dx - dy) @@ -137,8 +137,8 @@ put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): vo } put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void { - top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) - bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + top.height - 1) + top_start_idx := @inline(surfaceidx, surface, pos.x, pos.y) + bottom_start_idx := @inline(surfaceidx, surface, pos.x, pos.y + top.height - 1) rows_to_copy := top.height top_cursor := top.buf bottom_cursor := top.buf + top.width * (top.height - 1) @@ -161,6 +161,76 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void { return } +put_scaled := fn(surface: Surface, source: Surface, pos: Vec2(int), size: Vec2(int)): void { + step := Vec2(int).(1, 1) + if size.x < 0 { + pos.x += source.width - 1 + size.x = -size.x + step.x = -1 + } + if size.y < 0 { + pos.y += source.height - 1 + size.y = -size.y + step.y = -1 + } + surface_idx := @inline(surfaceidx, surface, pos.x, pos.y) + + source_pos := Vec2(int).(0, 0) + subpixel_pos := Vec2(int).(0, 0) + step_size := size / .(source.width, source.height) + if size.x < source.width { + step_size.x = source.width / size.x + } + if size.y < source.height { + step_size.y = source.height / size.y + } + one_up_step := size / (size - step_size * .(source.width, source.height)) + + pos = .(0, 0) + loop if pos.y >= size.y break else { + loop if pos.x >= size.x break else { + *surface_idx = *@inline(surfaceidx, source, source_pos.x, source_pos.y) + surface_idx += step.x + + if size.x < source.width { + if source_pos.x % one_up_step.x == 0 { + source_pos.x += 1 + } + source_pos.x += step_size.x + } else { + subpixel_pos.x += 1 + if subpixel_pos.x > step_size.x | source_pos.x % one_up_step.x == 0 & subpixel_pos.x >= step_size.x { + source_pos.x += 1 + subpixel_pos.x = 0 + } + } + + pos.x += 1 + } + + if size.y < source.width { + if source_pos.y % one_up_step.y == 0 { + source_pos.y += 1 + } + source_pos.y += step_size.y + subpixel_pos.y += 1 + if subpixel_pos.y > step_size.y | source_pos.y % one_up_step.y == 0 & subpixel_pos.y >= step_size.y { + source_pos.y += 1 + subpixel_pos.y = 0 + } + } + + surface_idx += surface.width * step.y - size.x * step.x + + source_pos.x = 0 + pos.x = 0 + + pos.y += 1 + } + + return +} + // peony-made put_trirect := fn(surface: Surface, pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void { step := Vec2(int).(1, 1) @@ -193,7 +263,7 @@ put_vline := fn(surface: Surface, x: int, y0: int, y1: int, color: Color): void y := y0 loop if y == y1 break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(surfaceidx, surface, x, y) = color y += 1 } @@ -210,7 +280,7 @@ put_hline := fn(surface: Surface, y: int, x0: int, x1: int, color: Color): void x := x0 loop if x == x1 break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(surfaceidx, surface, x, y) = color x += 1 } diff --git a/sysdata/programs/render_example/src/examples/scale.hb b/sysdata/programs/render_example/src/examples/scale.hb new file mode 100644 index 0000000..2a3ee90 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/scale.hb @@ -0,0 +1,17 @@ +.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math +render := @use("../../../../libraries/render/src/lib.hb") + +bmp_1 := @embed("./assets/able.bmp") +bmp_2 := @embed("./assets/mini.bmp") + +example := fn(): void { + screen := render.init(true) + + image := render.image.surface_from_bmp(@bitcast(&bmp_2)) + + loop { + render.clear(screen, render.black) + render.put_scaled(screen, image, .(100, 100), .(image.width / 2 + image.width / 4, image.height * 3)) + render.sync(screen) + } +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 289d812..f8260e8 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1,3 +1,3 @@ -.{example} := @use("./examples/surface.hb") +.{example} := @use("./examples/scale.hb") main := example \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index fab084e..9b95d71 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -20,8 +20,8 @@ resolution = "1600x900x24" [boot.limine.ableos.modules] -[boot.limine.ableos.modules.tests] -path = "boot:///tests.hbf" +# [boot.limine.ableos.modules.tests] +# path = "boot:///tests.hbf" # [boot.limine.ableos.modules.serial_driver] # path = "boot:///serial_driver.hbf" @@ -29,8 +29,8 @@ path = "boot:///tests.hbf" # [boot.limine.ableos.modules.diskio_driver] # path = "boot:///diskio_driver.hbf" -# [boot.limine.ableos.modules.render_example] -# path = "boot:///render_example.hbf" +[boot.limine.ableos.modules.render_example] +path = "boot:///render_example.hbf" # [boot.limine.ableos.modules.serial_driver_test] # path = "boot:///serial_driver_test.hbf"