diff --git a/Cargo.lock b/Cargo.lock index ca14e5d6..56dc2fc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -228,12 +228,12 @@ dependencies = [ [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7865d692a156c1d31f63b8f04b5d51472d1ff30a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7865d692a156c1d31f63b8f04b5d51472d1ff30a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248" dependencies = [ "hashbrown 0.15.1", "hbbytecode", @@ -245,7 +245,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7865d692a156c1d31f63b8f04b5d51472d1ff30a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248" dependencies = [ "hbbytecode", ] diff --git a/sysdata/libraries/render/src/image/bmp.hb b/sysdata/libraries/render/src/image/bmp.hb index 690198b3..d9950c62 100644 --- a/sysdata/libraries/render/src/image/bmp.hb +++ b/sysdata/libraries/render/src/image/bmp.hb @@ -35,17 +35,14 @@ BitmapColorHeader := packed struct { from := fn(bmp: ^u8): ?Surface { file_header := @as(^BitmapFileHeader, @bitcast(bmp)) info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader))) - bmp += file_header.offset if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 { log.error("Invalid BMP image.\0") return null } - width := @as(uint, info_header.width) - height := @as(uint, info_header.height) - lhs := Surface.(@bitcast(bmp), width, height) - rhs := new_surface(width, height) + lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height) + rhs := new_surface(info_header.width, info_header.height) put_surface(rhs, lhs, .(0, 0), true) return rhs diff --git a/sysdata/libraries/render/src/image/qoi.hb b/sysdata/libraries/render/src/image/qoi.hb index ca6e8c1c..23a49079 100644 --- a/sysdata/libraries/render/src/image/qoi.hb +++ b/sysdata/libraries/render/src/image/qoi.hb @@ -28,7 +28,7 @@ QuiteOkayHeader := packed struct { } be_to_le := fn(big: u32): u32 { - return (big & 0xFF000000) >> 24 | (big & 0xFF0000) >> 8 | (big & 0xFF00) << 8 | (big & 0xFF) << 24 + return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24 } from := fn(qoi: ^u8): ?Surface { diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index 7b9c6c12..efc8d92e 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -20,25 +20,12 @@ new_surface := fn(width: uint, height: uint): Surface { ) } -surface_from_ptr := fn(ptr: ^Color, width: uint, height: uint): Surface { - return .( - ptr, - width, - height, - ) -} - clone_surface := fn(surface: ^Surface): Surface { new := new_surface(surface.width, surface.height) @inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height)) return new } -// ! is broken, check memory.free function -free_surface := fn(surface: Surface): void { - return @inline(memory.free, Color, surface.buf, @intcast(surface.width * surface.height), false) -} - init := fn(doublebuffer: bool): Surface { framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0") width := dt.get(uint, "framebuffer/fb0/width\0") @@ -55,7 +42,6 @@ clear := fn(surface: Surface, color: Color): void { } sync := fn(surface: Surface): void { - // vague safety if surface.buf == framebuffer { return } @@ -81,9 +67,8 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: rows_to_fill := tr.y loop if rows_to_fill <= 1 break else { - // inline is broked - memory.set(Color, &color, top_start_idx, @bitcast(tr.x)) - memory.set(Color, &color, bottom_start_idx, @bitcast(tr.x)) + @inline(memory.set, Color, &color, top_start_idx, tr.x) + @inline(memory.set, Color, &color, bottom_start_idx, tr.x) top_start_idx += surface.width bottom_start_idx -= surface.width @@ -91,7 +76,7 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: } if rows_to_fill == 1 { - @inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x)) + @inline(memory.set, Color, &color, top_start_idx, tr.x) } return @@ -181,30 +166,36 @@ put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): } put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void { - top_start_idx := @inline(indexptr, surface, pos.x, pos.y) - bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1) + src_top_cursor := top.buf + src_bottom_cursor := top.buf + top.width * (top.height - 1) + + dst_top_idx := @inline(indexptr, surface, pos.x, pos.y) + dst_bottom_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1) + + dst_increment := surface.width + + if flip_v { + dst_increment = -dst_increment + tmp := dst_top_idx + dst_top_idx = dst_bottom_idx + dst_bottom_idx = tmp + } + rows_to_copy := top.height - top_cursor := top.buf - bottom_cursor := top.buf + top.width * (top.height - 1) loop if rows_to_copy <= 1 break else { - if flip_v { - @inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width)) - @inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width)) - } else { - @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width)) - @inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width)) - } + @inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width) + @inline(memory.copy, Color, src_bottom_cursor, dst_bottom_idx, top.width) - top_start_idx += surface.width - bottom_start_idx -= surface.width - top_cursor += top.width - bottom_cursor -= top.width + dst_top_idx += dst_increment + dst_bottom_idx -= dst_increment + src_top_cursor += top.width + src_bottom_cursor -= top.width rows_to_copy -= 2 } if rows_to_copy == 1 { - @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width)) + @inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width) } return @@ -260,126 +251,138 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo return } +utf8_len_table := [u8].(0, 0, 2, 3) 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 { - glyph_data := memory.dangling(u8) + max_y := surface.height - font.height + next_line_y := font.height + font.line_gap + char_advance := font.width + font.char_gap + surface_width := surface.width - if font.unicode != null { - code_point := @as(uint, 0) - first_byte := *current_char - num_bytes := 1 + loop if *str == 0 break else { + if cursor.y > max_y break - if (first_byte & 0x80) == 0 { - code_point = first_byte - } else if (first_byte & 0xE0) == 0xC0 { - num_bytes = 2 - code_point = first_byte & 0x1F - } else if (first_byte & 0xF0) == 0xE0 { - num_bytes = 3 - code_point = first_byte & 0xF - } else if (first_byte & 0xF8) == 0xF0 { - // handle later - current_char += 1 - continue - } else { - current_char += 1 + glyph_data := @as(^u8, idk) + code_point := @as(uint, 0) + + if (*str & 0x80) == 0 { + if *str == 10 { + cursor.x = pos.x + cursor.y += next_line_y + str += 1 continue } + if font.unicode == null { + if *str > font.num_glyphs { + str += 1 + continue + } + glyph_data = @inline(get_glyph, font, *str) + } else { + if *str < UNC_TABLE_SIZE { + glyph_index := *(font.unicode + *str) + if glyph_index == 0xFFFF { + str += 1 + continue + } + glyph_data = font.data + glyph_index * font.bytes_per_glyph + } else { + str += 1 + continue + } + } + str += 1 + } else if font.unicode != null { + first_byte := *str + num_bytes := @as(uint, 0) + + num_bytes = utf8_len_table[first_byte >> 5 & 0x3] + + if num_bytes == 0 { + str += 1 + continue + } + + code_point = first_byte & (0x7F >> num_bytes | 0x1F) + valid_sequence := true - i := 1 - loop if i >= num_bytes break else { - current_char += 1 - // have to check twice due to odd compiler bug...? - if *current_char == 0 | (*current_char & 0xC0) != 0x80 { + bytes_processed := 1 + + loop if bytes_processed >= num_bytes break else { + str += 1 + if *str == 0 | (*str & 0xC0) != 0x80 { valid_sequence = false } if valid_sequence == false { break } - code_point = code_point << 6 | *current_char & 0x3F - i += 1 + code_point = code_point << 6 | *str & 0x3F + bytes_processed += 1 } if valid_sequence == false { - current_char += 1 + str += 1 continue } - current_char += 1 + str += 1 if code_point == 10 { cursor.x = pos.x - cursor.y += font.height + font.line_gap + cursor.y += next_line_y continue } - if code_point < UNC_TABLE_SIZE { - glyph_index := *(font.unicode + code_point) + if code_point >= UNC_TABLE_SIZE { + continue + } - if glyph_index == 0xFFFF { - continue - } - glyph_data = font.data + glyph_index * font.bytes_per_glyph - } else { + glyph_index := *(font.unicode + code_point) + if glyph_index == 0xFFFF { continue } - } else { - if *current_char > font.num_glyphs { - continue - } - glyph_data = @inline(get_glyph, font, *current_char) - if *current_char == 10 { - cursor.x = pos.x - cursor.y += font.height + font.line_gap - current_char += 1 - continue - } - current_char += 1 + glyph_data = font.data + glyph_index * font.bytes_per_glyph } - if cursor.y + font.height > surface.height break - - if cursor.x % surface.width + font.width >= surface.width { + if cursor.x + font.width >= surface_width { cursor.x = pos.x - cursor.y += font.height + font.line_gap + cursor.y += next_line_y } dest := @inline(indexptr, surface, cursor.x, cursor.y) - rows_remaining := font.height + rows := font.height - loop if rows_remaining == 0 break else { + loop if rows == 0 break else { byte := *glyph_data pixel_dest := dest mask := @as(u8, 0x80) - bits_remaining := font.width + bits := font.width - loop if bits_remaining == 0 break else { + loop if bits == 0 break else { if (byte & mask) != 0 { *pixel_dest = color } pixel_dest += 1 mask >>= 1 - if mask == 0 & bits_remaining > 0 { + if mask == 0 & bits > 0 { glyph_data += 1 byte = *glyph_data mask = 0x80 } - bits_remaining -= 1 + bits -= 1 } if mask != 0x80 { glyph_data += 1 } - dest += surface.width - rows_remaining -= 1 + dest += surface_width + rows -= 1 } - cursor.x += font.width + font.char_gap + cursor.x += char_advance } return