Add support for embedding bitmap fonts in C++

This commit is contained in:
Simon Hausmann 2023-07-20 14:17:23 +02:00 committed by Simon Hausmann
parent 49b3e15bc8
commit 917cecff85
4 changed files with 141 additions and 8 deletions

View file

@ -155,6 +155,7 @@ fn gen_corelib(
"PointerEvent", "PointerEvent",
"Rect", "Rect",
"SortOrder", "SortOrder",
"BitmapFont",
] ]
.iter() .iter()
.chain(items.iter()) .chain(items.iter())

View file

@ -261,6 +261,12 @@ public:
} }
} }
/// Registers a bitmap font for use with the software renderer.
inline void register_bitmap_font(const cbindgen_private::BitmapFont &font)
{
cbindgen_private::slint_register_bitmap_font(&inner, &font);
}
/// \private /// \private
const cbindgen_private::WindowAdapterRcOpaque &handle() const { return inner; } const cbindgen_private::WindowAdapterRcOpaque &handle() const { return inner; }
@ -715,12 +721,18 @@ public:
/// \private /// \private
/// Internal function called by the view to register itself /// Internal function called by the view to register itself
void attach_peer(private_api::ModelPeer p) { peers.push_back(std::move(p)); } void attach_peer(private_api::ModelPeer p)
{
peers.push_back(std::move(p));
}
/// \private /// \private
/// Internal function called from within bindings to register with the currently /// Internal function called from within bindings to register with the currently
/// evaluating dependency and get notified when this model's row count changes. /// evaluating dependency and get notified when this model's row count changes.
void track_row_count_changes() const { model_row_count_dirty_property.get(); } void track_row_count_changes() const
{
model_row_count_dirty_property.get();
}
/// \private /// \private
/// Internal function called from within bindings to register with the currently /// Internal function called from within bindings to register with the currently

View file

@ -122,6 +122,15 @@ pub unsafe extern "C" fn slint_register_font_from_data(
) )
} }
#[no_mangle]
pub unsafe extern "C" fn slint_register_bitmap_font(
win: *const WindowAdapterRcOpaque,
font_data: &'static i_slint_core::graphics::BitmapFont,
) {
let window_adapter = &*(win as *const Rc<dyn WindowAdapter>);
window_adapter.renderer().register_bitmap_font(font_data);
}
#[cfg(feature = "testing")] #[cfg(feature = "testing")]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_testing_init_backend() { pub unsafe extern "C" fn slint_testing_init_backend() {

View file

@ -593,13 +593,118 @@ pub fn generate(doc: &Document) -> impl std::fmt::Display {
})) }))
} }
#[cfg(feature = "software-renderer")] #[cfg(feature = "software-renderer")]
crate::embedded_resources::EmbeddedResourcesKind::BitmapFontData(_) => { crate::embedded_resources::EmbeddedResourcesKind::BitmapFontData(
// FIXME! TODO crate::embedded_resources::BitmapFont {
family_name,
character_map,
units_per_em,
ascent,
descent,
glyphs,
weight,
italic,
},
) => {
let family_name_var = format!("slint_embedded_resource_{}_family_name", er.id);
let family_name_size = family_name.len();
file.declarations.push(Declaration::Var(Var { file.declarations.push(Declaration::Var(Var {
ty: "inline int".into(), ty: "inline uint8_t".into(),
name: family_name_var.clone(),
array_size: Some(family_name_size),
init: Some(format!(
"{{ {} }}",
family_name.as_bytes().iter().map(ToString::to_string).join(", ")
)),
}));
let charmap_var = format!("slint_embedded_resource_{}_charmap", er.id);
let charmap_size = character_map.len();
file.declarations.push(Declaration::Var(Var {
ty: "inline slint::cbindgen_private::CharacterMapEntry".into(),
name: charmap_var.clone(),
array_size: Some(charmap_size),
init: Some(format!(
"{{ {} }}",
character_map
.iter()
.map(|entry| format!(
"{{ .code_point = {}, .glyph_index = {} }}",
entry.code_point as u32, entry.glyph_index
))
.join(", ")
)),
}));
for (glyphset_index, glyphset) in glyphs.iter().enumerate() {
for (glyph_index, glyph) in glyphset.glyph_data.iter().enumerate() {
file.declarations.push(Declaration::Var(Var {
ty: "inline uint8_t".into(),
name: format!(
"slint_embedded_resource_{}_gs_{}_gd_{}",
er.id, glyphset_index, glyph_index
),
array_size: Some(glyph.data.len()),
init: Some(format!(
"{{ {} }}",
glyph.data.iter().map(ToString::to_string).join(", ")
)),
}));
}
file.declarations.push(Declaration::Var(Var{
ty: "inline slint::cbindgen_private::BitmapGlyph".into(),
name: format!("slint_embedded_resource_{}_glyphset_{}", er.id, glyphset_index),
array_size: Some(glyphset.glyph_data.len()),
init: Some(format!("{{ {} }}", glyphset.glyph_data.iter().enumerate().map(|(glyph_index, glyph)| {
format!("{{ .x = {}, .y = {}, .width = {}, .height = {}, .x_advance = {}, .data = slint::cbindgen_private::Slice<uint8_t>{{ {}, {} }} }}",
glyph.x, glyph.y, glyph.width, glyph.height, glyph.x_advance,
format!("slint_embedded_resource_{}_gs_{}_gd_{}", er.id, glyphset_index, glyph_index),
glyph.data.len()
)
}).join(", \n"))),
}));
}
let glyphsets_var = format!("slint_embedded_resource_{}_glyphsets", er.id);
let glyphsets_size = character_map.len();
file.declarations.push(Declaration::Var(Var {
ty: "inline slint::cbindgen_private::BitmapGlyphs".into(),
name: glyphsets_var.clone(),
array_size: Some(glyphsets_size),
init: Some(format!(
"{{ {} }}",
glyphs
.iter()
.enumerate()
.map(|(glyphset_index, glyphset)| format!(
"{{ .pixel_size = {}, .glyph_data = slint::cbindgen_private::Slice<slint::cbindgen_private::BitmapGlyph>{{
{}, {}
}}
}}",
glyphset.pixel_size, format!("slint_embedded_resource_{}_glyphset_{}", er.id, glyphset_index), glyphset.glyph_data.len()
))
.join(", \n")
)),
}));
let init = format!(
"slint::cbindgen_private::BitmapFont {{
.family_name = slint::cbindgen_private::Slice<uint8_t>{{ {family_name_var} , {family_name_size} }},
.character_map = slint::cbindgen_private::Slice<slint::cbindgen_private::CharacterMapEntry>{{ {charmap_var}, {charmap_size} }},
.units_per_em = {units_per_em},
.ascent = {ascent},
.descent = {descent},
.glyphs = slint::cbindgen_private::Slice<slint::cbindgen_private::BitmapGlyphs>{{ {glyphsets_var}, {glyphsets_size} }},
.weight = {weight},
.italic = {italic},
}}"
);
file.declarations.push(Declaration::Var(Var {
ty: "inline slint::cbindgen_private::BitmapFont".into(),
name: format!("slint_embedded_resource_{}", er.id), name: format!("slint_embedded_resource_{}", er.id),
array_size: None, array_size: None,
init: Some("0".into()), init: Some(init),
})) }))
} }
} }
@ -2856,8 +2961,14 @@ fn compile_builtin_function_call(
} }
} }
BuiltinFunction::RegisterBitmapFont => { BuiltinFunction::RegisterBitmapFont => {
// TODO if let [llr::Expression::NumberLiteral(resource_id)] = &arguments {
"/*TODO: REGISTER FONT*/".into() let window = access_window_field(ctx);
let resource_id: usize = *resource_id as _;
let symbol = format!("slint_embedded_resource_{}", resource_id);
format!("{window}.register_bitmap_font({symbol});")
} else {
panic!("internal error: invalid args to RegisterBitmapFont {:?}", arguments)
}
} }
BuiltinFunction::ImplicitLayoutInfo(orient) => { BuiltinFunction::ImplicitLayoutInfo(orient) => {
if let [llr::Expression::PropertyReference(pr)] = arguments { if let [llr::Expression::PropertyReference(pr)] = arguments {