aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpmemewarenet>2025-01-12 02:41:00 +0100
committerLibravatarLarge Libravatar memdmp <memdmpmemewarenet>2025-01-12 02:41:00 +0100
commitc8d7879f4daa41a26c534f42ce2b7050e062db8c (patch)
tree0476d9a389c864ce53990951f5ae55a93d787ebf
parentc89d4ae45320a00670c3496060d661a65183a9ed (diff)
downloadcosin25-invite-mountainbytes-c8d7879f4daa41a26c534f42ce2b7050e062db8c.tar.gz
cosin25-invite-mountainbytes-c8d7879f4daa41a26c534f42ce2b7050e062db8c.tar.bz2
cosin25-invite-mountainbytes-c8d7879f4daa41a26c534f42ce2b7050e062db8c.tar.lz
cosin25-invite-mountainbytes-c8d7879f4daa41a26c534f42ce2b7050e062db8c.zip

fix: make font rendering not wonky

-rwxr-xr-xbuild1
-rw-r--r--build.rs66
-rw-r--r--src/font.rs76
-rw-r--r--src/main.rs2
4 files changed, 109 insertions, 36 deletions
diff --git a/build b/build
index 6fc9458..3c2d560 100755
--- a/build
+++ b/build
@@ -1,3 +1,4 @@
#!/bin/sh
set -eax
RUSTFLAGS="-Zfmt-debug=none -Zlocation-detail=none" cargo +nightly build -Z build-std=std,panic_abort -Z build-std-features="optimize_for_size" -Z build-std-features=panic_immediate_abort -r
+upx --brute target/release/cosin-2025-invite-deck
diff --git a/build.rs b/build.rs
index f26f98e..97179a0 100644
--- a/build.rs
+++ b/build.rs
@@ -1,4 +1,4 @@
-use rusttype::{Font, Point, Scale};
+use rusttype::{Font, Point, Rect, Scale};
use std::fs::{self, File};
use std::io::{self, Write};
@@ -8,12 +8,41 @@ use std::io::{self, Write};
struct FontMetadata {
pub charset: &'static str,
pub name: &'static str,
+ pub scale: Scale,
pub font: Font<'static>,
}
impl FontMetadata {
pub fn render_character(&self, scale: Scale, character: char) -> Vec<u8> {
let glyph = self.font.glyph(character).scaled(scale);
- let bounding_box = glyph.exact_bounding_box().unwrap();
+ let positioned_glyph = glyph.clone().positioned(Point { x: 0.0, y: 0.0 });
+ let pixel_bounding_box = {
+ let bounding_box = positioned_glyph.pixel_bounding_box();
+ if bounding_box.is_none() {
+ Rect {
+ min: Point { x: 0, y: 0 },
+ max: Point {
+ x: glyph.h_metrics().advance_width as i32,
+ y: 0,
+ },
+ }
+ } else {
+ bounding_box.unwrap()
+ }
+ };
+ let bounding_box = {
+ let bounding_box = glyph.exact_bounding_box();
+ if bounding_box.is_none() {
+ Rect {
+ min: Point { x: 0.0, y: 0.0 },
+ max: Point {
+ x: pixel_bounding_box.width() as f32,
+ y: 0.0,
+ },
+ }
+ } else {
+ bounding_box.unwrap()
+ }
+ };
let width = bounding_box.width() as u32;
let height = bounding_box.height() as u32;
@@ -29,22 +58,27 @@ impl FontMetadata {
a[i] = v;
}
}
- define_item(&mut image, 2 + ((width as usize) * (height as usize)), 0x00);
+ define_item(
+ &mut image,
+ 10 + ((width as usize) * (height as usize)),
+ 0x00,
+ );
image[0] = (width & 0b0000_0000_1111_1111) as u8;
image[1] = (width & 0b1111_1111_0000_0000 << 8) as u8;
if (image[0] as u16) | (image[1] as u16 >> 8) != width as u16 {
panic!("Width missmatch!");
}
+ // TODO: do we *really* need i32 values here? wouldn't i16 be sufficient?
+ image[2..6].copy_from_slice(&pixel_bounding_box.min.x.to_le_bytes());
+ image[6..10].copy_from_slice(&(pixel_bounding_box.min.y + (scale.y / 2.0) as i32).to_le_bytes());
- glyph
- .positioned(Point { x: 0.0, y: 0.0 })
- .draw(|gx: u32, gy: u32, v| {
- let bit = (v * 255.0) as u8;
- if gx < width {
- define_item(&mut image, (2 + (gy * width) + gx) as usize, bit);
- }
- });
+ positioned_glyph.draw(|gx: u32, gy: u32, v| {
+ let bit = (v * 255.0) as u8;
+ if gx < width {
+ define_item(&mut image, (10 + (gy * width) + gx) as usize, bit);
+ }
+ });
image
}
pub fn img_to_hex(image: Vec<u8>) -> Vec<u8> {
@@ -81,10 +115,8 @@ impl FontMetadata {
}
fn exec(font: FontMetadata) -> io::Result<()> {
- let scale = Scale::uniform(32.0); // Set the font size
-
for c in font.unique_chars() {
- let image = font.render_character(scale, c);
+ let image = font.render_character(font.scale, c);
save_bits_to_file(&font, c as u8, &image)?;
}
@@ -164,12 +196,14 @@ use crate::font::BakedFont;
FontMetadata {
name: "Galmuri",
font: { Font::try_from_vec(fs::read("assets/fonts/Galmuri11.ttf")?).unwrap() },
- charset: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz2053:",
+ charset: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz2053: ",
+ scale: Scale::uniform(64.0),
},
FontMetadata {
name: "CherryBombOne",
font: { Font::try_from_vec(fs::read("assets/fonts/CherryBombOne.ttf")?).unwrap() },
- charset: "UwUSpace",
+ charset: "UwUSpace ",
+ scale: Scale::uniform(64.0),
},
];
for font in fonts {
diff --git a/src/font.rs b/src/font.rs
index 0baa862..fc5217e 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -1,6 +1,12 @@
use std::sync::LazyLock;
-use sdl2::{pixels::{Color, PixelFormatEnum}, rect::Rect, render::{Texture, TextureCreator, TextureValueError}, surface::Surface, video::WindowContext};
+use sdl2::{
+ pixels::{Color, PixelFormatEnum},
+ rect::{Point, Rect},
+ render::{Texture, TextureCreator, TextureValueError},
+ surface::Surface,
+ video::WindowContext,
+};
pub struct RenderableCharacter {
/** The width of the character, indicating where to break into a newline */
@@ -9,6 +15,8 @@ pub struct RenderableCharacter {
pub height: u16,
/** The raw alpha layer of the character */
pub data: &'static [u8],
+ /** The offset to draw the character at */
+ pub offset: Point,
}
/**
A trait describing a generated font.
@@ -19,11 +27,19 @@ pub trait BakedFont {
fn get_char_bytes(&self, character: char) -> &'static [u8];
fn get_char(&self, character: char) -> RenderableCharacter {
let bytes = self.get_char_bytes(character);
- let width = (bytes[0] as u16) | (bytes[1] as u16 >> 8);
- let data = &bytes[2..];
+ let width = u16::from_le_bytes(bytes[0..2].try_into().unwrap());
+ let offset_x = i32::from_le_bytes(bytes[2..6].try_into().unwrap());
+ let offset_y = i32::from_le_bytes(bytes[6..10].try_into().unwrap());
+ let data = &bytes[10..];
+ let height = if data.len() == 0 {
+ 0
+ } else {
+ data.len() as u16 / width
+ };
RenderableCharacter {
width,
- height: data.len() as u16 / width,
+ height,
+ offset: Point::new(offset_x, offset_y),
data,
}
}
@@ -32,23 +48,39 @@ impl RenderableCharacter {
/** Alpha value of colour is currently ignored! */
pub fn to_surface(&self, colour: Color) -> Surface<'static> {
let mut surface = Surface::new(
- self.width.into(),
- self.height.into(),
+ if self.width == 0 {
+ 1
+ } else {
+ self.width.into()
+ },
+ if self.height == 0 {
+ 1
+ } else {
+ self.height.into()
+ },
PixelFormatEnum::RGBA32,
)
.unwrap();
- surface.with_lock_mut(|buffer: &mut [u8]| {
- let mut idx: usize = 0;
- print!("{} ({}x{})", self.data.len() * 4, self.width, self.height);
- for pixel in self.data {
- let index = idx * 4;
- buffer[index] = colour.r; // Red
- buffer[index + 1] = colour.g; // Green
- buffer[index + 2] = colour.b; // Blue
- buffer[index + 3] = *pixel; // Alpha
- idx += 1;
- }
- });
+ if self.width != 0 || self.height != 0 {
+ surface.with_lock_mut(|buffer: &mut [u8]| {
+ let mut idx: usize = 0;
+ for pixel in self.data {
+ let index = idx * 4;
+ buffer[index] = colour.r; // Red
+ buffer[index + 1] = colour.g; // Green
+ buffer[index + 2] = colour.b; // Blue
+ buffer[index + 3] = *pixel; // Alpha
+ idx += 1;
+ }
+ });
+ } else {
+ // Blank
+ surface.with_lock_mut(|buffer: &mut [u8]| {
+ for index in 0..buffer.len() {
+ buffer[index] = 0;
+ }
+ })
+ }
surface
}
/** Colour Alpha Channel is ignored */
@@ -61,6 +93,12 @@ impl RenderableCharacter {
surface.as_texture(texture_creator)
}
pub fn to_rect(&self, x: i32, y: i32) -> Rect {
- Rect::new(x, y, self.width.into(), self.height.into())
+ println!("{:#?}",self.offset);
+ Rect::new(
+ x + self.offset.x,
+ y + self.offset.y,
+ i32::from(self.width).try_into().unwrap(),
+ i32::from(self.height).try_into().unwrap(),
+ )
}
}
diff --git a/src/main.rs b/src/main.rs
index 287847d..ebe73d7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -27,7 +27,7 @@ pub fn main() {
// let uwu_font = font::UwUFont::new(&texture_creator);
canvas.clear();
let mut offset: u16 = 0;
- for c in "UwUSpace".chars() {
+ for c in "UwU Space".chars() {
let char = FONT_CHERRY_BOMB_ONE.get_char(c);
canvas
.copy(