Added text rendering to rust bindings

This commit is contained in:
Андреев Григорий 2026-04-19 01:09:08 +03:00
parent 40f15643d9
commit 2e9e07d568
9 changed files with 282 additions and 103 deletions

9
Cargo.lock generated
View File

@ -5,3 +5,12 @@ version = 4
[[package]]
name = "daria"
version = "0.1.0"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "1.0.0-alpha.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e136bfa874086c78f34d6eba98c423fefe464ce57f38164d16893ba8ed358e70"

View File

@ -10,3 +10,5 @@ path = "src/l3/r4/r4d.rs"
[lib]
name = "alice_and_misc"
path = "src/l2/allie_rs/lib.rs"
[dependencies]
libc = "1.0.0-alpha.3"

View File

@ -25,6 +25,7 @@ void allie_Alice_lucy_cache_add_glyphs(Alice* alice, VecLucyGlyphCachingRequest
Alice_lucy_cache_add_glyphs(alice, req);
}
// todo: transition to cvec4 from vec4 color (vec4 color makes no sense for fonts)
void allie_Alice_lucy_renderer_add_simple_label(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs,
vec4 color, S32 additional_y_advance, SpanU8 text, ivec2 start_pos
) {

103
src/l2/allie_rs/alice.rs Normal file
View File

@ -0,0 +1,103 @@
use std::ffi::{c_void};
use std::marker::PhantomData;
use crate::geom::{*};
use crate::allie;
use crate::allie::CSpan;
use crate::uint_segments::{U32Segment};
pub struct LucyFaceFixedSize {
opa: allie::LucyFaceFixedSize,
}
impl Drop for LucyFaceFixedSize {
fn drop(&mut self) {
// todo: so something
}
}
pub struct LucyFace {
opa: allie::LucyFace,
}
impl LucyFace {
pub fn of_size(&self, size: u32) -> LucyFaceFixedSize{
LucyFaceFixedSize{opa: unsafe { allie::LucyFace_of_size(self.opa, size) }}
}
}
impl Drop for LucyFace {
fn drop(&mut self) {
// todo: oh what should I do
}
}
pub struct Alice {
opa: allie::Alice,
}
pub struct AliceCallbacks<'a> {
pub on_wl_pointer_button: Box<dyn FnMut(u32, u32) + 'a>,
pub on_wl_keyboard_key: Box<dyn FnMut(u32, u32) + 'a>,
pub on_another_frame: Box<dyn FnMut(f32) + 'a>,
pub on_wl_pointer_motion: Box<dyn FnMut(vec2) +'a>,
}
pub struct LucyGlyphCachingRequest<'a> {
pub sized_face: &'a mut LucyFaceFixedSize,
pub codepoint_ranges: Vec<U32Segment>,
}
impl<'a> From<& LucyGlyphCachingRequest<'a>> for allie::LucyGlyphCachingRequest<'a> {
fn from(value: & LucyGlyphCachingRequest<'a>) -> Self {
Self{phantom: PhantomData,
sized_face: value.sized_face.opa,
codepoint_ranges: allie::CVec::<U32Segment>::from(&value.codepoint_ranges)}
}
}
impl Alice {
pub fn new() -> Self {
Alice{opa: unsafe { allie::Alice_new() }}
}
pub fn mainloop<'a>(&'a self, mut cb: AliceCallbacks<'a>) {
let guest_data = (&raw mut cb) as allie::Alice;
let a_cb = allie::AliceCallbacks {
guest: guest_data,
on_wl_pointer_button: allie::AliceCallbacks_on_wl_pointer_button,
on_wl_keyboard_key: allie::AliceCallbacks_on_wl_keyboard_key,
on_another_frame: allie::AliceCallbacks_on_another_frame,
on_wl_pointer_motion: allie::AliceCallbacks_on_wl_pointer_motion,
};
unsafe{ allie::Alice_mainloop(self.opa, &a_cb) };
}
pub fn set_clear_color(&self, color: vec4) {
unsafe { allie::Alice_set_clear_color(self.opa, color) };
}
pub fn new_lucy_face(&self, path: &str) -> LucyFace{
LucyFace{opa: unsafe { allie::Alice_new_LucyFace(self.opa, allie::CVec::<u8>::from(path)) } }
}
pub fn lucy_cache_add_glyphs(&self, req: Vec<LucyGlyphCachingRequest>){
let a_req = allie::CVec::<allie::LucyGlyphCachingRequest>::from(&req);
unsafe { allie::Alice_lucy_cache_add_glyphs(self.opa, a_req) };
}
pub fn lucy_renderer_add_simple_label(&self, ffs: &LucyFaceFixedSize, color: vec4,
additional_y_advance: i32, text: &str, start_pos: ivec2
) {
unsafe { allie::Alice_lucy_renderer_add_simple_label(self.opa, ffs.opa, color,
additional_y_advance, allie::CSpan::<u8>::from(text), start_pos) }
}
}
impl Drop for Alice {
fn drop(&mut self) {
// todo: do something
}
}

131
src/l2/allie_rs/allie.rs Normal file
View File

@ -0,0 +1,131 @@
use std::ffi::c_void;
use crate::alice;
use crate::geom::{vec2, vec4, ivec2};
use std::ptr::copy_nonoverlapping;
use std::ptr;
use libc::{calloc, free};
use std::mem::size_of;
use std::marker::PhantomData;
use crate::uint_segments::{*};
/* usize is u64, ok? */
// fn safe_calloc(nobj: usize, size: usize) -> *mut c_void{
// let p = unsafe { calloc(nobj, size) };
// if (p.is_null()){ panic!("calloc: Not enough memory\n") }
// p
// }
fn safe_calloc<T>(nobj: usize) ->* mut T {
let p = unsafe { calloc(nobj, size_of::<T>()) };
if (p.is_null()){ panic!("calloc: Not enough memory\n") }
p as *mut T
}
pub type Alice = *mut c_void;
pub type LucyFace = *mut c_void;
pub type LucyFaceFixedSize = *mut c_void;
#[repr(C)]
pub struct CSpan<'a, T> {
phantom: PhantomData<&'a T>,
data: *const T,
len: u64
}
impl<'a> From<&'a str> for CSpan<'a, u8> {
fn from(s: &'a str) -> Self {
let data: *const u8 = s.as_ptr();
Self{phantom: PhantomData, data, len: s.len() as u64}
}
}
#[repr(C)]
pub struct CVec<T> {
buf: *mut T,
len: u64, capacity: u64
}
impl<'a, Td, Ts> From<&'a Vec<Ts>> for CVec<Td> where Td: From<&'a Ts>{
fn from(value: &'a Vec<Ts>) -> Self {
let buf: *mut Td = safe_calloc(value.len());
for (i, src) in value.iter().enumerate() {
unsafe { ptr::write(buf.add(i), Td::from(src)) };
}
Self {buf, len: value.len() as u64, capacity: value.len() as u64}
}
}
impl From<&str> for CVec<u8> {
fn from(s: &str) -> Self {
let buf: *mut u8 = safe_calloc(s.len());
unsafe { copy_nonoverlapping(s.as_ptr(), buf, s.len()) };
Self{buf, len: s.len() as u64, capacity: s.len() as u64}
}
}
impl<T> Drop for CVec<T>{
fn drop(&mut self) {
unsafe { free(self.buf as *mut c_void) };
}
}
#[repr(C)]
pub struct LucyGlyphCachingRequest<'a> {
pub phantom: PhantomData<&'a u8>,
pub sized_face: LucyFaceFixedSize,
pub codepoint_ranges: CVec<U32Segment>,
}
/* Copying from Rust analog type to C allie type will be implemented outside */
#[repr(C)]
pub struct AliceCallbacks {
pub guest: Alice,
/* guest data, button, btn action */
pub on_wl_pointer_button: extern "C" fn (Alice, u32, u32),
/* guest data, keysym, key action (wl_keyboard_key_state) */
pub on_wl_keyboard_key: extern "C" fn (Alice, u32, u32),
/* guest data, passed time */
pub on_another_frame: extern "C" fn (Alice, f32),
pub on_wl_pointer_motion: extern "C" fn (Alice, vec2),
}
unsafe extern "C" {
#[link_name="Alice_new"]
pub fn Alice_new() -> Alice;
#[link_name="Alice_mainloop"]
pub fn Alice_mainloop(alice: Alice, cb: *const AliceCallbacks);
#[link_name="Alice_set_clear_color"]
pub fn Alice_set_clear_color(alice: Alice, color: vec4);
#[link_name="Alice_new_LucyFace"]
pub fn Alice_new_LucyFace(alice: Alice, path: CVec<u8>) -> LucyFace;
#[link_name="LucyFace_of_size"]
pub fn LucyFace_of_size(alice: LucyFace, size: u32) -> LucyFaceFixedSize;
#[link_name="Alice_lucy_cache_add_glyphs"]
pub fn Alice_lucy_cache_add_glyphs(alice: Alice, req: CVec<LucyGlyphCachingRequest>);
#[link_name="Alice_lucy_renderer_add_simple_label"]
pub fn Alice_lucy_renderer_add_simple_label( /* todo: make color cvec4 */
alice: Alice, ffs: LucyFaceFixedSize,
color: vec4, additional_y_advance: i32, text: CSpan<u8>, start_pos: ivec2);
}
pub extern "C" fn AliceCallbacks_on_wl_pointer_button(dt: Alice, button: u32, act: u32){
let cb: &mut alice::AliceCallbacks = unsafe { &mut *(dt as *mut alice::AliceCallbacks) };
(cb.on_wl_pointer_button)(button, act);
}
pub extern "C" fn AliceCallbacks_on_wl_keyboard_key(dt: Alice, keysym: u32, act: u32){
let cb: &mut alice::AliceCallbacks = unsafe { &mut *(dt as *mut alice::AliceCallbacks) };
(cb.on_wl_keyboard_key)(keysym, act);
}
pub extern "C" fn AliceCallbacks_on_another_frame(dt: Alice, fl: f32){
let cb: &mut alice::AliceCallbacks = unsafe { &mut *(dt as *mut alice::AliceCallbacks) };
(cb.on_another_frame)(fl);
}
pub extern "C" fn AliceCallbacks_on_wl_pointer_motion(dt: Alice, pos: vec2){
let cb: &mut alice::AliceCallbacks = unsafe { &mut *(dt as *mut alice::AliceCallbacks) };
(cb.on_wl_pointer_motion)(pos);
}

View File

@ -9,6 +9,7 @@ impl AssertTrue for Assert<true>{}
/* Turn out for tuple struct, where clause goes after the field list */
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct GeomVec<T, const N: usize> (pub [T; N]) where T: Copy + Clone;
impl<T, const N: usize> Add for GeomVec<T, N> where
@ -21,19 +22,6 @@ impl<T, const N: usize> Add for GeomVec<T, N> where
}
}
trait HasY {
fn has_foo() -> bool {
return true;
}
}
// impl<T, const N: usize> HasY for GeomVec<T, N> where
// T: Copy + Clone,
// Assert<{N >= 1}> : AssertTrue {
//
// }
impl<T, const N: usize> GeomVec<T, N> where
T: Copy + Clone,
Assert<{N >= 1}> : AssertTrue {

View File

@ -9,89 +9,6 @@
/* *c_void is nothing special, it is the same as *u8 for example */
pub mod geom;
pub mod int_primitives;
use std::ffi::{c_void};
use geom::{*};
type VoidPtr = *mut c_void;
#[repr(C)]
struct allie_AliceCallbacks{
guest: VoidPtr,
/* guest data, button, btn action */
on_wl_pointer_button: extern "C" fn (VoidPtr, u32, u32),
/* guest data, keysym, key action (wl_keyboard_key_state) */
on_wl_keyboard_key: extern "C" fn (VoidPtr, u32, u32),
/* guest data, passed time */
on_another_frame: extern "C" fn (VoidPtr, f32),
on_wl_pointer_motion: extern "C" fn (VoidPtr, vec2),
}
unsafe extern "C" {
#[link_name="Alice_new"]
fn allie_Alice_new() -> *mut c_void;
#[link_name="Alice_mainloop"]
fn allie_Alice_mainloop(alice: VoidPtr, cb: *const allie_AliceCallbacks);
#[link_name="Alice_set_clear_color"]
fn allie_Alice_set_clear_color(alice: VoidPtr, color: vec4);
}
pub struct Alice {
opa: *mut c_void,
}
pub struct AliceCallbacks {
pub on_wl_pointer_button: Box<dyn FnMut(u32, u32)>,
pub on_wl_keyboard_key: Box<dyn FnMut(u32, u32)>,
pub on_another_frame: Box<dyn FnMut(f32)>,
pub on_wl_pointer_motion: Box<dyn FnMut(vec2)>,
}
extern "C" fn allie_AliceCallbacks_on_wl_pointer_button(dt: VoidPtr, button: u32, act: u32){
let cb: &mut AliceCallbacks = unsafe { &mut *(dt as *mut AliceCallbacks) };
(cb.on_wl_pointer_button)(button, act);
}
extern "C" fn allie_AliceCallbacks_on_wl_keyboard_key(dt: VoidPtr, keysym: u32, act: u32){
let cb: &mut AliceCallbacks = unsafe { &mut *(dt as *mut AliceCallbacks) };
(cb.on_wl_keyboard_key)(keysym, act);
}
extern "C" fn allie_AliceCallbacks_on_another_frame(dt: VoidPtr, fl: f32){
let cb: &mut AliceCallbacks = unsafe { &mut *(dt as *mut AliceCallbacks) };
(cb.on_another_frame)(fl);
}
extern "C" fn allie_AliceCallbacks_on_wl_pointer_motion(dt: VoidPtr, pos: vec2){
let cb: &mut AliceCallbacks = unsafe { &mut *(dt as *mut AliceCallbacks) };
(cb.on_wl_pointer_motion)(pos);
}
impl Alice {
pub fn new() -> Self {
Alice{opa: unsafe { allie_Alice_new() }}
}
pub fn mainloop(&self, mut cb: AliceCallbacks) {
let guest_data = (&raw mut cb) as VoidPtr;
let a_cb = allie_AliceCallbacks {
guest: guest_data,
on_wl_pointer_button: allie_AliceCallbacks_on_wl_pointer_button,
on_wl_keyboard_key: allie_AliceCallbacks_on_wl_keyboard_key,
on_another_frame: allie_AliceCallbacks_on_another_frame,
on_wl_pointer_motion: allie_AliceCallbacks_on_wl_pointer_motion,
};
unsafe{ allie_Alice_mainloop(self.opa, &a_cb) };
}
pub fn set_clear_color(&self, color: vec4) {
unsafe { allie_Alice_set_clear_color(self.opa, color) };
}
}
impl Drop for Alice {
fn drop(&mut self) {
// todo: do something
}
}
mod allie;
pub mod alice;
pub mod uint_segments;

View File

@ -0,0 +1,20 @@
/* I am not proud of this */
#[repr(C)]
#[derive(Copy, Clone)]
pub struct UIntSegment<T: Copy>{
pub start: T,
pub len: T,
}
impl<T: Copy> UIntSegment<T> {
pub fn new(start: T, len: T) -> Self{ Self {start, len} }
}
pub type U32Segment = UIntSegment<u32>;
pub type U64Segment = UIntSegment<u64>;
/* Common sense decided to die */
impl<T: Copy> From<& UIntSegment<T>> for UIntSegment<T> {
fn from(value: &UIntSegment<T>) -> Self { *value }
}

View File

@ -1,11 +1,18 @@
use alice_and_misc::{*};
use alice_and_misc::alice::{*};
use alice_and_misc::geom::{*};
use alice_and_misc::uint_segments::U32Segment;
fn main() {
let v = vec2(1.0, 2.0);
let alice = Alice::new();
alice.set_clear_color(vec4(0., 1., 0., 1.));
let mut alice = Alice::new();
alice.set_clear_color(vec4(0., 0.5, 0.5, 1.));
let mut face = alice.new_lucy_face("./src/l3/fonts/DMSerifText-Regular.ttf");
let mut face_40 = face.of_size(40);
alice.lucy_cache_add_glyphs(vec![
LucyGlyphCachingRequest{sized_face: &mut face_40,
codepoint_ranges: vec![U32Segment::new(32, 126 - 32 + 1)]}
]);
alice.mainloop(AliceCallbacks{
on_wl_pointer_button: Box::new(|_: u32, _: u32| {
println!("pointer button")
@ -14,7 +21,8 @@ fn main() {
println!("keyboard key");
}),
on_another_frame: Box::new(|_: f32| {
alice.lucy_renderer_add_simple_label(&face_40, vec4(1., 0.5, 0., 1.),
0, "Hello from Rust", ivec2(40, 40));
}),
on_wl_pointer_motion: Box::new(|_: vec2| {
println!("pointer motion");