split code up and clean up a small bit
This commit is contained in:
parent
f964d57ca1
commit
970ae0e449
3 changed files with 174 additions and 175 deletions
185
src/main.rs
185
src/main.rs
|
@ -1,15 +1,18 @@
|
||||||
use cosmic_text::{Attrs, Buffer, Color, FontSystem, Metrics, Shaping, SwashCache};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
fs::{self},
|
||||||
fs::{self, File},
|
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use font_kit::loader::Loader;
|
use log::info;
|
||||||
use log::{debug, info};
|
use raqote::DrawTarget;
|
||||||
use logos::{Lexer, Logos};
|
|
||||||
use raqote::{DrawOptions, DrawTarget, Point, SolidSource, Source};
|
use parse::parse_the_shit_out_of_this_but_manually;
|
||||||
|
|
||||||
|
use render::render_text;
|
||||||
|
|
||||||
|
mod parse;
|
||||||
|
mod render;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Parser)]
|
#[derive(Clone, Debug, Parser)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
@ -41,171 +44,3 @@ fn main() {
|
||||||
|
|
||||||
dt.write_png("out.png").unwrap();
|
dt.write_png("out.png").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_the_shit_out_of_this_but_manually(text: &str) -> Vec<LanguageStructureThingy> {
|
|
||||||
let mut lex = Token::lexer(text);
|
|
||||||
let mut r = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match lex.next() {
|
|
||||||
Some(Ok(Token::Text(s))) => r.push(LanguageStructureThingy::Text(s)),
|
|
||||||
Some(Ok(Token::ParenOpen)) => hehe_sexpression_funy(&mut r, &mut lex),
|
|
||||||
Some(Ok(Token::ParenClose)) => todo!(),
|
|
||||||
Some(Ok(Token::String(_))) => todo!(),
|
|
||||||
Some(Ok(Token::Equals)) => todo!(),
|
|
||||||
Some(Ok(Token::Asterisk)) => todo!(),
|
|
||||||
Some(Ok(Token::Underscore)) => todo!(),
|
|
||||||
Some(Ok(Token::Backslash)) => todo!(),
|
|
||||||
Some(Ok(Token::WavyThing)) => todo!(),
|
|
||||||
Some(Ok(Token::Sparkles)) => todo!(),
|
|
||||||
Some(Ok(Token::HeadingLevelIndicator)) => todo!(),
|
|
||||||
Some(Err(_)) => panic!("mauuu~ :("),
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hehe_sexpression_funy(r: &mut Vec<LanguageStructureThingy>, lex: &mut Lexer<'_, Token>) {
|
|
||||||
if let Some(Ok(Token::Text(s))) = lex.next() {
|
|
||||||
let strs = s.trim_start().split_whitespace().collect::<Vec<&str>>();
|
|
||||||
|
|
||||||
let name = strs[0].to_owned();
|
|
||||||
let mut attrs = HashMap::new();
|
|
||||||
|
|
||||||
if strs.len() == 1 {
|
|
||||||
} else if strs.len() == 2 && (lex.next() == Some(Ok(Token::Equals))) {
|
|
||||||
if let Some(Ok(Token::Text(next))) = lex.next() {
|
|
||||||
let _ = attrs.insert(strs[1].to_owned(), next.trim_end().to_owned());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = if let Some(Ok(Token::String(s))) = lex.next() {
|
|
||||||
Box::new(LanguageStructureThingy::Text(s))
|
|
||||||
} else {
|
|
||||||
todo!()
|
|
||||||
};
|
|
||||||
|
|
||||||
r.push(LanguageStructureThingy::Sexpression {
|
|
||||||
name,
|
|
||||||
attrs,
|
|
||||||
content,
|
|
||||||
});
|
|
||||||
if let Some(Ok(Token::ParenClose)) = lex.next() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// handle other things too
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HswtRenderer {
|
|
||||||
dt: DrawTarget,
|
|
||||||
font_system: FontSystem,
|
|
||||||
swash_cache: SwashCache,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_text(dt: &mut DrawTarget) {
|
|
||||||
// A FontSystem provides access to detected system fonts, create one per application
|
|
||||||
let mut font_system = FontSystem::new();
|
|
||||||
|
|
||||||
// A SwashCache stores rasterized glyphs, create one per application
|
|
||||||
let mut swash_cache = SwashCache::new();
|
|
||||||
|
|
||||||
// Text metrics indicate the font size and line height of a buffer
|
|
||||||
let metrics = Metrics::new(48.0, 60.0);
|
|
||||||
|
|
||||||
// A Buffer provides shaping and layout for a UTF-8 string, create one per text widget
|
|
||||||
let mut buffer = Buffer::new(&mut font_system, metrics);
|
|
||||||
|
|
||||||
// Borrow buffer together with the font system for more convenient method calls
|
|
||||||
let mut buffer = buffer.borrow_with(&mut font_system);
|
|
||||||
|
|
||||||
// Set a size for the text buffer, in pixels
|
|
||||||
buffer.set_size(1920.0, 1080.0);
|
|
||||||
|
|
||||||
// Attributes indicate what font to choose
|
|
||||||
let attrs = Attrs::new();
|
|
||||||
|
|
||||||
// Add some text!
|
|
||||||
buffer.set_text("Hello, Rust! 🦀\n", attrs, Shaping::Advanced);
|
|
||||||
|
|
||||||
// Perform shaping as desired
|
|
||||||
buffer.shape_until_scroll();
|
|
||||||
|
|
||||||
// Inspect the output runs
|
|
||||||
for run in buffer.layout_runs() {
|
|
||||||
for glyph in run.glyphs.iter() {
|
|
||||||
println!("{:#?}", glyph);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a default text color
|
|
||||||
let text_color = Color::rgb(0xFF, 0xFF, 0xFF);
|
|
||||||
|
|
||||||
// Draw the buffer (for performance, instead use SwashCache directly)
|
|
||||||
buffer.draw(&mut swash_cache, text_color, |x, y, w, h, color| {
|
|
||||||
let (r, g, b, a) = color.as_rgba_tuple();
|
|
||||||
dt.fill_rect(
|
|
||||||
x as f32,
|
|
||||||
y as f32,
|
|
||||||
w as f32,
|
|
||||||
h as f32,
|
|
||||||
&Source::Solid(SolidSource::from_unpremultiplied_argb(a, r, g, b)),
|
|
||||||
&DrawOptions {
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum LanguageStructureThingy {
|
|
||||||
Text(String),
|
|
||||||
Newline,
|
|
||||||
Sexpression {
|
|
||||||
name: String,
|
|
||||||
attrs: HashMap<String, String>,
|
|
||||||
content: Box<LanguageStructureThingy>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ObjectStyles {
|
|
||||||
height: Option<Size>,
|
|
||||||
width: Option<Size>,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Size {
|
|
||||||
Absolute(u16),
|
|
||||||
Relative(f32),
|
|
||||||
Auto,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Logos, Debug, PartialEq)]
|
|
||||||
enum Token {
|
|
||||||
#[regex("[a-zA-Z\\d\\w]+", |lex| lex.slice().to_owned())]
|
|
||||||
Text(String),
|
|
||||||
#[token("(")]
|
|
||||||
ParenOpen,
|
|
||||||
#[token(")")]
|
|
||||||
ParenClose,
|
|
||||||
#[regex(r#""([^"\\]|\\["\\bnfrt]|u[a-fA-F0-9]{4})*""#, |lex| lex.slice().to_owned())]
|
|
||||||
String(String),
|
|
||||||
#[token("=")]
|
|
||||||
Equals,
|
|
||||||
#[token("*")]
|
|
||||||
Asterisk,
|
|
||||||
#[token("_")]
|
|
||||||
Underscore,
|
|
||||||
#[token("\\")]
|
|
||||||
Backslash,
|
|
||||||
#[token("~")]
|
|
||||||
WavyThing,
|
|
||||||
#[token("✨")]
|
|
||||||
Sparkles,
|
|
||||||
#[token("|| ")]
|
|
||||||
HeadingLevelIndicator,
|
|
||||||
}
|
|
||||||
|
|
102
src/parse.rs
Normal file
102
src/parse.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use logos::{Lexer, Logos};
|
||||||
|
|
||||||
|
#[derive(Logos, Debug, PartialEq)]
|
||||||
|
pub enum Token {
|
||||||
|
#[regex("[a-zA-Z\\d\\w]+", |lex| lex.slice().to_owned())]
|
||||||
|
Text(String),
|
||||||
|
#[token("(")]
|
||||||
|
ParenOpen,
|
||||||
|
#[token(")")]
|
||||||
|
ParenClose,
|
||||||
|
#[regex(r#""([^"\\]|\\["\\bnfrt]|u[a-fA-F0-9]{4})*""#, |lex| lex.slice().to_owned())]
|
||||||
|
String(String),
|
||||||
|
#[token("=")]
|
||||||
|
Equals,
|
||||||
|
#[token("*")]
|
||||||
|
Asterisk,
|
||||||
|
#[token("_")]
|
||||||
|
Underscore,
|
||||||
|
#[token("\\")]
|
||||||
|
Backslash,
|
||||||
|
#[token("~")]
|
||||||
|
WavyThing,
|
||||||
|
#[token("✨")]
|
||||||
|
Sparkles,
|
||||||
|
#[token("|| ")]
|
||||||
|
HeadingLevelIndicator,
|
||||||
|
#[token("\n")]
|
||||||
|
Newline,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LanguageStructureThingy {
|
||||||
|
Text(String),
|
||||||
|
Sexpression {
|
||||||
|
name: String,
|
||||||
|
attrs: HashMap<String, String>,
|
||||||
|
content: Box<LanguageStructureThingy>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_the_shit_out_of_this_but_manually(text: &str) -> Vec<LanguageStructureThingy> {
|
||||||
|
let mut lex = Token::lexer(text);
|
||||||
|
let mut r = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match lex.next() {
|
||||||
|
Some(Ok(Token::Text(s))) => r.push(LanguageStructureThingy::Text(s)),
|
||||||
|
Some(Ok(Token::Newline)) => r.push(LanguageStructureThingy::Text("\n".to_owned())),
|
||||||
|
Some(Ok(Token::ParenOpen)) => hehe_sexpression_funy(&mut r, &mut lex),
|
||||||
|
Some(Ok(Token::ParenClose)) => todo!(),
|
||||||
|
Some(Ok(Token::String(_))) => todo!(),
|
||||||
|
Some(Ok(Token::Equals)) => todo!(),
|
||||||
|
Some(Ok(Token::Asterisk)) => todo!(),
|
||||||
|
Some(Ok(Token::Underscore)) => todo!(),
|
||||||
|
Some(Ok(Token::Backslash)) => todo!(),
|
||||||
|
Some(Ok(Token::WavyThing)) => todo!(),
|
||||||
|
Some(Ok(Token::Sparkles)) => todo!(),
|
||||||
|
Some(Ok(Token::HeadingLevelIndicator)) => todo!(),
|
||||||
|
Some(Err(e)) => panic!("mauuu~ :(, e: {e:?}"),
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hehe_sexpression_funy(r: &mut Vec<LanguageStructureThingy>, lex: &mut Lexer<'_, Token>) {
|
||||||
|
if let Some(Ok(Token::Text(s))) = lex.next() {
|
||||||
|
let strs = s.trim_start().split_whitespace().collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
let name = strs[0].to_owned();
|
||||||
|
let mut attrs = HashMap::new();
|
||||||
|
|
||||||
|
if strs.len() == 1 {
|
||||||
|
} else if strs.len() == 2 && (lex.next() == Some(Ok(Token::Equals))) {
|
||||||
|
if let Some(Ok(Token::Text(next))) = lex.next() {
|
||||||
|
let _ = attrs.insert(strs[1].to_owned(), next.trim_end().to_owned());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = if let Some(Ok(Token::String(s))) = lex.next() {
|
||||||
|
Box::new(LanguageStructureThingy::Text(s))
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
};
|
||||||
|
|
||||||
|
r.push(LanguageStructureThingy::Sexpression {
|
||||||
|
name,
|
||||||
|
attrs,
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
if let Some(Ok(Token::ParenClose)) = lex.next() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// handle other things too
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
62
src/render.rs
Normal file
62
src/render.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use cosmic_text::{Attrs, Buffer, Color, FontSystem, Metrics, Shaping, SwashCache};
|
||||||
|
use raqote::{DrawOptions, DrawTarget, SolidSource, Source};
|
||||||
|
|
||||||
|
struct HswtRenderer {
|
||||||
|
dt: DrawTarget,
|
||||||
|
font_system: FontSystem,
|
||||||
|
swash_cache: SwashCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_text(dt: &mut DrawTarget) {
|
||||||
|
// A FontSystem provides access to detected system fonts, create one per application
|
||||||
|
let mut font_system = FontSystem::new();
|
||||||
|
|
||||||
|
// A SwashCache stores rasterized glyphs, create one per application
|
||||||
|
let mut swash_cache = SwashCache::new();
|
||||||
|
|
||||||
|
// Text metrics indicate the font size and line height of a buffer
|
||||||
|
let metrics = Metrics::new(48.0, 60.0);
|
||||||
|
|
||||||
|
// A Buffer provides shaping and layout for a UTF-8 string, create one per text widget
|
||||||
|
let mut buffer = Buffer::new(&mut font_system, metrics);
|
||||||
|
|
||||||
|
// Borrow buffer together with the font system for more convenient method calls
|
||||||
|
let mut buffer = buffer.borrow_with(&mut font_system);
|
||||||
|
|
||||||
|
// Set a size for the text buffer, in pixels
|
||||||
|
buffer.set_size(1920.0, 1080.0);
|
||||||
|
|
||||||
|
// Attributes indicate what font to choose
|
||||||
|
let attrs = Attrs::new();
|
||||||
|
|
||||||
|
// Add some text!
|
||||||
|
buffer.set_text("Hello, Rust! 🦀\n", attrs, Shaping::Advanced);
|
||||||
|
|
||||||
|
// Perform shaping as desired
|
||||||
|
buffer.shape_until_scroll();
|
||||||
|
|
||||||
|
// Inspect the output runs
|
||||||
|
for run in buffer.layout_runs() {
|
||||||
|
for glyph in run.glyphs.iter() {
|
||||||
|
println!("{:#?}", glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a default text color
|
||||||
|
let text_color = Color::rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
|
||||||
|
// Draw the buffer (for performance, instead use SwashCache directly)
|
||||||
|
buffer.draw(&mut swash_cache, text_color, |x, y, w, h, color| {
|
||||||
|
let (r, g, b, a) = color.as_rgba_tuple();
|
||||||
|
dt.fill_rect(
|
||||||
|
x as f32,
|
||||||
|
y as f32,
|
||||||
|
w as f32,
|
||||||
|
h as f32,
|
||||||
|
&Source::Solid(SolidSource::from_unpremultiplied_argb(a, r, g, b)),
|
||||||
|
&DrawOptions {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue