unoptimised text load & render
This commit is contained in:
parent
5af5631755
commit
eaace7d9c1
BIN
sysdata/consolefonts/tamsyn/10x20b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/10x20b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/10x20r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/10x20r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/5x9b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/5x9b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/5x9r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/5x9r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/6x12b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/6x12b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/6x12r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/6x12r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/7x13b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/7x13b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/7x13r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/7x13r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/7x14b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/7x14b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/7x14r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/7x14r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/8x15b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/8x15b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/8x15r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/8x15r.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/8x16b.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/8x16b.psf
Normal file
Binary file not shown.
BIN
sysdata/consolefonts/tamsyn/8x16r.psf
Normal file
BIN
sysdata/consolefonts/tamsyn/8x16r.psf
Normal file
Binary file not shown.
10
sysdata/consolefonts/tamsyn/LICENSE
Normal file
10
sysdata/consolefonts/tamsyn/LICENSE
Normal file
|
@ -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.
|
|
@ -5,13 +5,10 @@
|
||||||
- Animation
|
- Animation
|
||||||
|
|
||||||
# API
|
# API
|
||||||
- Font Loader
|
|
||||||
- VGA fonts
|
|
||||||
- Colour operations:
|
- Colour operations:
|
||||||
- Alpha Composite
|
- Alpha Composite
|
||||||
- Invert
|
- Invert
|
||||||
- Surface Operations:
|
- Surface Operations:
|
||||||
- FlipV
|
|
||||||
- FlipH
|
- FlipH
|
||||||
- Resize
|
- Resize
|
||||||
- Wrap the colour operations
|
- Wrap the colour operations
|
||||||
|
@ -20,8 +17,8 @@
|
||||||
- Draw operations:
|
- Draw operations:
|
||||||
- Curve raster algorithm
|
- Curve raster algorithm
|
||||||
- VGA font fast blit
|
- VGA font fast blit
|
||||||
- VGA font render
|
|
||||||
- Polygon
|
- Polygon
|
||||||
|
- Rounded rects
|
||||||
|
|
||||||
# Backend
|
# Backend
|
||||||
- SVGA Driver
|
- SVGA Driver
|
||||||
|
|
|
@ -36,7 +36,7 @@ surface_from_bmp := fn(bmp: ^u8): Surface {
|
||||||
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
||||||
if file_header.img_type != 0x4D42 {
|
if file_header.img_type != 0x4D42 {
|
||||||
log.error("failed to load bmp image: not a bmp image, idiot\0")
|
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)))
|
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
|
||||||
bmp += file_header.offset
|
bmp += file_header.offset
|
||||||
|
@ -68,7 +68,7 @@ new_surface_from_bmp := fn(bmp: ^u8): Surface {
|
||||||
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
||||||
if file_header.img_type != 0x4D42 {
|
if file_header.img_type != 0x4D42 {
|
||||||
log.error("failed to load bmp image: not a bmp image, idiot\0")
|
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)))
|
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
|
||||||
bmp += file_header.offset
|
bmp += file_header.offset
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
software := @use("software.hb")
|
software := @use("software.hb")
|
||||||
image := @use("image.hb")
|
image := @use("image.hb")
|
||||||
|
text := @use("text.hb")
|
||||||
|
|
||||||
// default mode
|
// default mode
|
||||||
mode := software
|
mode := software
|
||||||
|
@ -40,6 +41,7 @@ put_filled_rect := mode.put_filled_rect
|
||||||
put_line := mode.put_line
|
put_line := mode.put_line
|
||||||
clear := mode.clear
|
clear := mode.clear
|
||||||
put_surface := mode.put_surface
|
put_surface := mode.put_surface
|
||||||
|
put_text := mode.put_text
|
||||||
// thanks peony for these three!
|
// thanks peony for these three!
|
||||||
put_trirect := mode.put_trirect
|
put_trirect := mode.put_trirect
|
||||||
put_vline := mode.put_vline
|
put_vline := mode.put_vline
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.{math, memory, dt} := @use("../../stn/src/lib.hb");
|
.{math, memory, dt} := @use("../../stn/src/lib.hb");
|
||||||
.{Color} := @use("lib.hb");
|
.{Color, text} := @use("lib.hb");
|
||||||
|
.{get_glyph, Font} := text;
|
||||||
.{Vec2} := math
|
.{Vec2} := math
|
||||||
|
|
||||||
Surface := struct {
|
Surface := struct {
|
||||||
|
@ -257,3 +258,63 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
|
||||||
|
|
||||||
return
|
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
|
||||||
|
}
|
75
sysdata/libraries/render/src/text.hb
Normal file
75
sysdata/libraries/render/src/text.hb
Normal file
|
@ -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
|
||||||
|
}
|
BIN
sysdata/libraries/stn/src/assets/sin_table
Normal file
BIN
sysdata/libraries/stn/src/assets/sin_table
Normal file
Binary file not shown.
0
sysdata/libraries/stn/src/assets/this-is-temporary
Normal file
0
sysdata/libraries/stn/src/assets/this-is-temporary
Normal file
|
@ -30,26 +30,30 @@ Vec2 := fn($Expr: type): type {
|
||||||
return struct {x: Expr, y: Expr}
|
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 {
|
sin := fn(theta: int, amplitude: uint): int {
|
||||||
theta := theta_deg % 360
|
|
||||||
if theta < 0 {
|
if theta < 0 {
|
||||||
theta += 360
|
theta += (-theta / 360 + 1) * 360
|
||||||
|
} else if theta >= 360 {
|
||||||
|
theta -= theta / 360 * 360
|
||||||
}
|
}
|
||||||
|
|
||||||
quadrant := theta / 90
|
quadrant := theta / 90
|
||||||
theta = theta % 90
|
index := theta % 90
|
||||||
|
|
||||||
sign := 1 - ((quadrant & 2) >> 1) * 2
|
if @as(u8, @intcast(quadrant)) == @as(u8, 1) {
|
||||||
complement := quadrant & 1
|
index = 90 - index
|
||||||
|
}
|
||||||
|
|
||||||
index := theta * (1 - complement) + (90 - theta) * complement
|
value := SIN_TABLE[@bitcast(index)]
|
||||||
sin_value := SIN_TABLE[index] * sign
|
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 {
|
cos := fn(theta: int, amplitude: uint): int {
|
||||||
return @inline(sin_i, theta_deg + 90, amplitude)
|
return @inline(sin, theta + 90, amplitude)
|
||||||
}
|
}
|
23
sysdata/programs/render_example/src/examples/text.hb
Normal file
23
sysdata/programs/render_example/src/examples/text.hb
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
.{example} := @use("./examples/surface.hb")
|
.{example} := @use("./examples/text.hb")
|
||||||
|
|
||||||
main := example
|
main := example
|
|
@ -28,8 +28,8 @@ resolution = "1024x768x24"
|
||||||
# [boot.limine.ableos.modules.diskio_driver]
|
# [boot.limine.ableos.modules.diskio_driver]
|
||||||
# path = "boot:///diskio_driver.hbf"
|
# path = "boot:///diskio_driver.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.render_example]
|
[boot.limine.ableos.modules.render_example]
|
||||||
# path = "boot:///render_example.hbf"
|
path = "boot:///render_example.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.serial_driver]
|
# [boot.limine.ableos.modules.serial_driver]
|
||||||
# path = "boot:///serial_driver.hbf"
|
# path = "boot:///serial_driver.hbf"
|
||||||
|
@ -37,11 +37,11 @@ resolution = "1024x768x24"
|
||||||
# [boot.limine.ableos.modules.serial_driver_test]
|
# [boot.limine.ableos.modules.serial_driver_test]
|
||||||
# path = "boot:///serial_driver_test.hbf"
|
# path = "boot:///serial_driver_test.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.horizon]
|
# [boot.limine.ableos.modules.horizon]
|
||||||
path = "boot:///horizon.hbf"
|
# path = "boot:///horizon.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.horizon_testing_program]
|
# [boot.limine.ableos.modules.horizon_testing_program]
|
||||||
path = "boot:///horizon_testing_program.hbf"
|
# path = "boot:///horizon_testing_program.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.dt_buffer_test]
|
# [boot.limine.ableos.modules.dt_buffer_test]
|
||||||
# path = "boot:///dt_buffer_test.hbf"
|
# path = "boot:///dt_buffer_test.hbf"
|
||||||
|
|
Loading…
Reference in a new issue