diff --git a/sysdata/consolefonts/tamsyn/10x20b.psf b/sysdata/consolefonts/tamsyn/10x20b.psf new file mode 100644 index 000000000..4a582d9ed Binary files /dev/null and b/sysdata/consolefonts/tamsyn/10x20b.psf differ diff --git a/sysdata/consolefonts/tamsyn/10x20r.psf b/sysdata/consolefonts/tamsyn/10x20r.psf new file mode 100644 index 000000000..e9222b77d Binary files /dev/null and b/sysdata/consolefonts/tamsyn/10x20r.psf differ diff --git a/sysdata/consolefonts/tamsyn/5x9b.psf b/sysdata/consolefonts/tamsyn/5x9b.psf new file mode 100644 index 000000000..cc3ade7b8 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/5x9b.psf differ diff --git a/sysdata/consolefonts/tamsyn/5x9r.psf b/sysdata/consolefonts/tamsyn/5x9r.psf new file mode 100644 index 000000000..185806c55 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/5x9r.psf differ diff --git a/sysdata/consolefonts/tamsyn/6x12b.psf b/sysdata/consolefonts/tamsyn/6x12b.psf new file mode 100644 index 000000000..4ae9d6a44 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/6x12b.psf differ diff --git a/sysdata/consolefonts/tamsyn/6x12r.psf b/sysdata/consolefonts/tamsyn/6x12r.psf new file mode 100644 index 000000000..1373ec252 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/6x12r.psf differ diff --git a/sysdata/consolefonts/tamsyn/7x13b.psf b/sysdata/consolefonts/tamsyn/7x13b.psf new file mode 100644 index 000000000..4ec3ee59e Binary files /dev/null and b/sysdata/consolefonts/tamsyn/7x13b.psf differ diff --git a/sysdata/consolefonts/tamsyn/7x13r.psf b/sysdata/consolefonts/tamsyn/7x13r.psf new file mode 100644 index 000000000..380702de2 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/7x13r.psf differ diff --git a/sysdata/consolefonts/tamsyn/7x14b.psf b/sysdata/consolefonts/tamsyn/7x14b.psf new file mode 100644 index 000000000..a473750d7 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/7x14b.psf differ diff --git a/sysdata/consolefonts/tamsyn/7x14r.psf b/sysdata/consolefonts/tamsyn/7x14r.psf new file mode 100644 index 000000000..1ce5d8e9c Binary files /dev/null and b/sysdata/consolefonts/tamsyn/7x14r.psf differ diff --git a/sysdata/consolefonts/tamsyn/8x15b.psf b/sysdata/consolefonts/tamsyn/8x15b.psf new file mode 100644 index 000000000..6219e9958 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/8x15b.psf differ diff --git a/sysdata/consolefonts/tamsyn/8x15r.psf b/sysdata/consolefonts/tamsyn/8x15r.psf new file mode 100644 index 000000000..0054a2b4f Binary files /dev/null and b/sysdata/consolefonts/tamsyn/8x15r.psf differ diff --git a/sysdata/consolefonts/tamsyn/8x16b.psf b/sysdata/consolefonts/tamsyn/8x16b.psf new file mode 100644 index 000000000..4eb9107d3 Binary files /dev/null and b/sysdata/consolefonts/tamsyn/8x16b.psf differ diff --git a/sysdata/consolefonts/tamsyn/8x16r.psf b/sysdata/consolefonts/tamsyn/8x16r.psf new file mode 100644 index 000000000..6fd82c17f Binary files /dev/null and b/sysdata/consolefonts/tamsyn/8x16r.psf differ diff --git a/sysdata/consolefonts/tamsyn/LICENSE b/sysdata/consolefonts/tamsyn/LICENSE new file mode 100644 index 000000000..8fc49609d --- /dev/null +++ b/sysdata/consolefonts/tamsyn/LICENSE @@ -0,0 +1,10 @@ +Tamsyn font is free. You are hereby granted permission to use, copy, modify, +and distribute it as you see fit. + +Tamsyn font is provided "as is" without any express or implied warranty. + +The author makes no representations about the suitability of this font for +a particular purpose. + +In no event will the author be held liable for damages arising from the use +of this font. diff --git a/sysdata/libraries/render/TODO.md b/sysdata/libraries/render/TODO.md index 746ca4baf..c17ae888f 100644 --- a/sysdata/libraries/render/TODO.md +++ b/sysdata/libraries/render/TODO.md @@ -5,13 +5,10 @@ - Animation # API -- Font Loader - - VGA fonts - Colour operations: - Alpha Composite - Invert - Surface Operations: - - FlipV - FlipH - Resize - Wrap the colour operations @@ -20,8 +17,8 @@ - Draw operations: - Curve raster algorithm - VGA font fast blit - - VGA font render - Polygon + - Rounded rects # Backend - SVGA Driver diff --git a/sysdata/libraries/render/src/image.hb b/sysdata/libraries/render/src/image.hb index 46f5d7bd1..a07d862b9 100644 --- a/sysdata/libraries/render/src/image.hb +++ b/sysdata/libraries/render/src/image.hb @@ -36,7 +36,7 @@ surface_from_bmp := fn(bmp: ^u8): Surface { file_header := @as(^BitmapFileHeader, @bitcast(bmp)) if file_header.img_type != 0x4D42 { log.error("failed to load bmp image: not a bmp image, idiot\0") - return @as(Surface, idk) + return idk } info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader))) bmp += file_header.offset @@ -68,7 +68,7 @@ new_surface_from_bmp := fn(bmp: ^u8): Surface { file_header := @as(^BitmapFileHeader, @bitcast(bmp)) if file_header.img_type != 0x4D42 { log.error("failed to load bmp image: not a bmp image, idiot\0") - return @as(Surface, idk) + return idk } info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader))) bmp += file_header.offset diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb index 3132b3b87..87e86c34f 100644 --- a/sysdata/libraries/render/src/lib.hb +++ b/sysdata/libraries/render/src/lib.hb @@ -1,5 +1,6 @@ software := @use("software.hb") image := @use("image.hb") +text := @use("text.hb") // default mode mode := software @@ -40,6 +41,7 @@ put_filled_rect := mode.put_filled_rect put_line := mode.put_line clear := mode.clear put_surface := mode.put_surface +put_text := mode.put_text // 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 ddf939ff0..28f99e35e 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -1,5 +1,6 @@ .{math, memory, dt} := @use("../../stn/src/lib.hb"); -.{Color} := @use("lib.hb"); +.{Color, text} := @use("lib.hb"); +.{get_glyph, Font} := text; .{Vec2} := math Surface := struct { @@ -255,5 +256,65 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo } @inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1)) + return +} + +put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void { + cursor := Vec2(uint).(pos.x, pos.y) + current_char := str + + loop if *current_char == 0 break else { + if *current_char == 10 { + cursor.x = pos.x + cursor.y += font.height + font.line_gap + current_char += 1 + continue + } + + glyph_data := @inline(get_glyph, font, @intcast(*current_char)) + if glyph_data == idk { + current_char += 1 + continue + } + + if cursor.x % surface.width + font.width >= surface.width { + cursor.x = pos.x + cursor.y += font.height + font.line_gap + } + if cursor.y + font.height > surface.height break + + dest := @inline(indexptr, surface, cursor.x, cursor.y) + src := glyph_data + rows_remaining := font.height + + loop if rows_remaining == 0 break else { + byte := *glyph_data + pixel_dest := dest + mask := @as(u8, 0x80) + bits_remaining := font.width + + loop if bits_remaining == 0 break else { + if (byte & mask) != 0 { + *pixel_dest = color + } + pixel_dest += 1 + mask >>= 1 + if mask == 0 { + glyph_data += 1 + byte = *glyph_data + mask = 0x80 + } + bits_remaining -= 1 + } + + glyph_data += 1 + dest += surface.width + rows_remaining -= 1 + } + + cursor.x += font.width + font.char_gap + current_char += 1 + } + return } \ No newline at end of file diff --git a/sysdata/libraries/render/src/text.hb b/sysdata/libraries/render/src/text.hb new file mode 100644 index 000000000..468961064 --- /dev/null +++ b/sysdata/libraries/render/src/text.hb @@ -0,0 +1,75 @@ +.{log} := @use("../../stn/src/lib.hb") + +PSF1Header := packed struct { + magic: u16, + font_mode: u8, + character_size: u8, +} + +PSF2Header := packed struct { + magic: u32, + version: u32, + header_size: u32, + flags: u32, + num_glyph: u32, + bytes_per_glyph: u32, + height: u32, + width: u32, +} + +Font := struct { + data: ^u8, + width: uint, + height: uint, + num_glyphs: uint, + bytes_per_glyph: uint, + has_unicode_table: bool, + line_gap: uint, + char_gap: uint, +} + +font_from_psf1 := fn(psf: ^u8): Font { + header := @as(^PSF1Header, @bitcast(psf)) + if header.magic != 0x436 { + log.error("failed to load psf font: not a psf1 font, idiot\0") + return idk + } + + psf += @sizeof(PSF1Header) + + return .( + psf, + 8, + @intcast(header.character_size), + 256, + @intcast(header.character_size), + false, + 0, + 0, + ) +} + +font_from_psf2 := fn(psf: ^u8): Font { + header := @as(^PSF2Header, @bitcast(psf)) + if header.magic != 0x864AB572 { + log.error("failed to load psf font: not a psf2 font, idiot\0") + return idk + } + + psf += header.header_size + + return .( + psf, + @intcast(header.width), + @intcast(header.height), + @intcast(header.num_glyph), + @intcast(header.bytes_per_glyph), + (header.flags & 1) != 0, + 0, + 0, + ) +} + +get_glyph := fn(font: Font, index: uint): ^u8 { + return font.data + index * font.bytes_per_glyph +} \ No newline at end of file diff --git a/sysdata/libraries/stn/src/assets/sin_table b/sysdata/libraries/stn/src/assets/sin_table new file mode 100644 index 000000000..0d1c9d8b1 Binary files /dev/null and b/sysdata/libraries/stn/src/assets/sin_table differ diff --git a/sysdata/libraries/stn/src/assets/this-is-temporary b/sysdata/libraries/stn/src/assets/this-is-temporary new file mode 100644 index 000000000..e69de29bb diff --git a/sysdata/libraries/stn/src/math.hb b/sysdata/libraries/stn/src/math.hb index 563e9c3d6..910891940 100644 --- a/sysdata/libraries/stn/src/math.hb +++ b/sysdata/libraries/stn/src/math.hb @@ -30,26 +30,30 @@ Vec2 := fn($Expr: type): type { return struct {x: Expr, y: Expr} } -SIN_TABLE := [int].(0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, 3420, 3583, 3746, 3907, 4067, 4226, 4384, 4540, 4695, 4848, 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, 9848, 9877, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, 10000) +SIN_TABLE := @as([int; 91], @bitcast(@embed("./assets/sin_table"))) -sin_i := fn(theta_deg: int, amplitude: int): int { - theta := theta_deg % 360 +sin := fn(theta: int, amplitude: uint): int { if theta < 0 { - theta += 360 + theta += (-theta / 360 + 1) * 360 + } else if theta >= 360 { + theta -= theta / 360 * 360 } quadrant := theta / 90 - theta = theta % 90 + index := theta % 90 - sign := 1 - ((quadrant & 2) >> 1) * 2 - complement := quadrant & 1 + if @as(u8, @intcast(quadrant)) == @as(u8, 1) { + index = 90 - index + } - index := theta * (1 - complement) + (90 - theta) * complement - sin_value := SIN_TABLE[index] * sign + value := SIN_TABLE[@bitcast(index)] + if quadrant >= 2 { + value = -value + } - return (sin_value * amplitude + 5000) / 10000 + return (value * @bitcast(amplitude) + 5000) / 10000 } -cos_i := fn(theta_deg: int, amplitude: int): int { - return @inline(sin_i, theta_deg + 90, amplitude) +cos := fn(theta: int, amplitude: uint): int { + return @inline(sin, theta + 90, amplitude) } \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/text.hb b/sysdata/programs/render_example/src/examples/text.hb new file mode 100644 index 000000000..98789d645 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/text.hb @@ -0,0 +1,23 @@ +.{Vec2, sin, cos} := @use("../../../../libraries/stn/src/lib.hb").math +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + words */ + +psf := @embed("../../../../consolefonts/tamsyn/10x20r.psf") + +example := fn(): void { + screen := render.init(true) + font := render.text.font_from_psf2(@bitcast(&psf)) + t := 0 + str := "Hello, World! +This is a test +of multiline rendering\0" + loop { + render.clear(screen, render.black) + render.put_text(screen, font, .(t, t % screen.height), render.red, str) + render.sync(screen) + t += 1 + } + return +} \ 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 289d81281..3edd356e8 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/text.hb") main := example \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index a97af89b0..f5562824b 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -28,8 +28,8 @@ resolution = "1024x768x24" # [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] # path = "boot:///serial_driver.hbf" @@ -37,11 +37,11 @@ resolution = "1024x768x24" # [boot.limine.ableos.modules.serial_driver_test] # path = "boot:///serial_driver_test.hbf" -[boot.limine.ableos.modules.horizon] -path = "boot:///horizon.hbf" +# [boot.limine.ableos.modules.horizon] +# path = "boot:///horizon.hbf" -[boot.limine.ableos.modules.horizon_testing_program] -path = "boot:///horizon_testing_program.hbf" +# [boot.limine.ableos.modules.horizon_testing_program] +# path = "boot:///horizon_testing_program.hbf" # [boot.limine.ableos.modules.dt_buffer_test] # path = "boot:///dt_buffer_test.hbf"