mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Initial commit for a new software rendering backend for use in MCUs
This adds the skeleton, including a winit driven simulator window and a dummy ItemRenderer implementation.
This commit is contained in:
parent
8f940a446e
commit
abb423ed33
7 changed files with 586 additions and 0 deletions
|
@ -5,6 +5,7 @@ members = [
|
||||||
'sixtyfps_runtime/interpreter',
|
'sixtyfps_runtime/interpreter',
|
||||||
'sixtyfps_runtime/rendering_backends/gl',
|
'sixtyfps_runtime/rendering_backends/gl',
|
||||||
'sixtyfps_runtime/rendering_backends/qt',
|
'sixtyfps_runtime/rendering_backends/qt',
|
||||||
|
'sixtyfps_runtime/rendering_backends/mcu',
|
||||||
'sixtyfps_runtime/rendering_backends/default',
|
'sixtyfps_runtime/rendering_backends/default',
|
||||||
'sixtyfps_runtime/rendering_backends/testing',
|
'sixtyfps_runtime/rendering_backends/testing',
|
||||||
'sixtyfps_compiler',
|
'sixtyfps_compiler',
|
||||||
|
@ -47,6 +48,7 @@ default-members = [
|
||||||
'sixtyfps_runtime/interpreter',
|
'sixtyfps_runtime/interpreter',
|
||||||
'sixtyfps_runtime/rendering_backends/gl',
|
'sixtyfps_runtime/rendering_backends/gl',
|
||||||
'sixtyfps_runtime/rendering_backends/qt',
|
'sixtyfps_runtime/rendering_backends/qt',
|
||||||
|
'sixtyfps_runtime/rendering_backends/mcu',
|
||||||
'sixtyfps_runtime/rendering_backends/default',
|
'sixtyfps_runtime/rendering_backends/default',
|
||||||
'sixtyfps_compiler',
|
'sixtyfps_compiler',
|
||||||
'api/sixtyfps-rs',
|
'api/sixtyfps-rs',
|
||||||
|
|
38
sixtyfps_runtime/rendering_backends/mcu/Cargo.toml
Normal file
38
sixtyfps_runtime/rendering_backends/mcu/Cargo.toml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
[package]
|
||||||
|
name = "sixtyfps-rendering-backend-mcu"
|
||||||
|
version = "0.1.5"
|
||||||
|
authors = ["SixtyFPS <info@sixtyfps.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "GPL-3.0-only"
|
||||||
|
description = "Rendering backend for SixtyFPS for use on Microcontrollers"
|
||||||
|
repository = "https://github.com/sixtyfpsui/sixtyfps"
|
||||||
|
homepage = "https://sixtyfps.io"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
simulator = ["winit", "glutin", "femtovg", "embedded-graphics-simulator"]
|
||||||
|
default = ["simulator"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sixtyfps-corelib = { version = "=0.1.5", path = "../../corelib" }
|
||||||
|
const-field-offset = { version = "0.1", path = "../../../helper_crates/const-field-offset" }
|
||||||
|
rgb = "0.8.27"
|
||||||
|
imgref = "1.6.1"
|
||||||
|
vtable = { version = "0.1", path = "../../../helper_crates/vtable" }
|
||||||
|
by_address = "1.0.4"
|
||||||
|
euclid = "0.22.1"
|
||||||
|
pin-weak = "1"
|
||||||
|
scoped-tls-hkt = "0.1"
|
||||||
|
smallvec = "1.7"
|
||||||
|
once_cell = "1.5"
|
||||||
|
derive_more = "0.99.5"
|
||||||
|
winit = { version = "0.25", default-features = false, optional = true }
|
||||||
|
glutin = { version = "0.27", default-features = false, optional = true }
|
||||||
|
femtovg = { version = "0.2.8", optional = true }
|
||||||
|
embedded-graphics = "0.7.1"
|
||||||
|
embedded-graphics-simulator = { version = "0.3.0", optional = true, default-features = false }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
|
cocoa = { version = "0.24.0" }
|
102
sixtyfps_runtime/rendering_backends/mcu/lib.rs
Normal file
102
sixtyfps_runtime/rendering_backends/mcu/lib.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* LICENSE BEGIN
|
||||||
|
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||||
|
Copyright (c) 2021 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||||
|
Copyright (c) 2021 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
This file is also available under commercial licensing terms.
|
||||||
|
Please contact info@sixtyfps.io for more information.
|
||||||
|
LICENSE END */
|
||||||
|
/*!
|
||||||
|
|
||||||
|
**NOTE**: This library is an **internal** crate for the [SixtyFPS project](https://sixtyfps.io).
|
||||||
|
This crate should **not be used directly** by applications using SixtyFPS.
|
||||||
|
You should use the `sixtyfps` crate instead.
|
||||||
|
|
||||||
|
**WARNING**: This crate does not follow the semver convention for versioning and can
|
||||||
|
only be used with `version = "=x.y.z"` in Cargo.toml.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#![doc(html_logo_url = "https://sixtyfps.io/resources/logo.drawio.svg")]
|
||||||
|
|
||||||
|
use sixtyfps_corelib::{
|
||||||
|
graphics::{Image, Size},
|
||||||
|
window::Window,
|
||||||
|
ImageInner,
|
||||||
|
};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[cfg(feature = "simulator")]
|
||||||
|
mod simulator;
|
||||||
|
|
||||||
|
#[cfg(feature = "simulator")]
|
||||||
|
use simulator::*;
|
||||||
|
|
||||||
|
mod renderer;
|
||||||
|
|
||||||
|
pub struct Backend;
|
||||||
|
|
||||||
|
impl sixtyfps_corelib::backend::Backend for Backend {
|
||||||
|
fn create_window(&'static self) -> Rc<Window> {
|
||||||
|
sixtyfps_corelib::window::Window::new(|window| SimulatorWindow::new(window))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_event_loop(&'static self, behavior: sixtyfps_corelib::backend::EventLoopQuitBehavior) {
|
||||||
|
simulator::event_loop::run(behavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quit_event_loop(&'static self) {
|
||||||
|
crate::event_loop::with_window_target(|event_loop| {
|
||||||
|
event_loop.event_loop_proxy().send_event(simulator::event_loop::CustomEvent::Exit).ok();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_font_from_memory(
|
||||||
|
&'static self,
|
||||||
|
_data: &'static [u8],
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_font_from_path(
|
||||||
|
&'static self,
|
||||||
|
_path: &std::path::Path,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_clipboard_text(&'static self, _text: String) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clipboard_text(&'static self) -> Option<String> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_event(&'static self, event: Box<dyn FnOnce() + Send>) {
|
||||||
|
let e = crate::event_loop::CustomEvent::UserEvent(event);
|
||||||
|
crate::event_loop::GLOBAL_PROXY.get_or_init(Default::default).lock().unwrap().send_event(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn image_size(&'static self, image: &Image) -> Size {
|
||||||
|
let inner: &ImageInner = image.into();
|
||||||
|
match inner {
|
||||||
|
ImageInner::None => Default::default(),
|
||||||
|
ImageInner::AbsoluteFilePath(_) => todo!(),
|
||||||
|
ImageInner::EmbeddedData { .. } => todo!(),
|
||||||
|
ImageInner::EmbeddedImage(buffer) => {
|
||||||
|
[buffer.width() as f32, buffer.height() as f32].into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type NativeWidgets = ();
|
||||||
|
pub type NativeGlobals = ();
|
||||||
|
pub mod native_widgets {}
|
||||||
|
pub const HAS_NATIVE_STYLE: bool = false;
|
||||||
|
pub const IS_AVAILABLE: bool = true;
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
sixtyfps_corelib::backend::instance_or_init(|| Box::new(Backend));
|
||||||
|
}
|
112
sixtyfps_runtime/rendering_backends/mcu/renderer.rs
Normal file
112
sixtyfps_runtime/rendering_backends/mcu/renderer.rs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* LICENSE BEGIN
|
||||||
|
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||||
|
Copyright (c) 2021 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||||
|
Copyright (c) 2021 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
This file is also available under commercial licensing terms.
|
||||||
|
Please contact info@sixtyfps.io for more information.
|
||||||
|
LICENSE END */
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct SoftwareRenderer<'a, Target: embedded_graphics::draw_target::DrawTarget + 'static> {
|
||||||
|
pub draw_target: &'a mut Target,
|
||||||
|
pub window: Rc<sixtyfps_corelib::window::Window>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Target: embedded_graphics::draw_target::DrawTarget>
|
||||||
|
sixtyfps_corelib::item_rendering::ItemRenderer for SoftwareRenderer<'_, Target>
|
||||||
|
{
|
||||||
|
fn draw_rectangle(&mut self, _rect: std::pin::Pin<&sixtyfps_corelib::items::Rectangle>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_border_rectangle(
|
||||||
|
&mut self,
|
||||||
|
_rect: std::pin::Pin<&sixtyfps_corelib::items::BorderRectangle>,
|
||||||
|
) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_image(&mut self, _image: std::pin::Pin<&sixtyfps_corelib::items::ImageItem>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_clipped_image(
|
||||||
|
&mut self,
|
||||||
|
_image: std::pin::Pin<&sixtyfps_corelib::items::ClippedImage>,
|
||||||
|
) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_text(&mut self, _text: std::pin::Pin<&sixtyfps_corelib::items::Text>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_text_input(&mut self, _text_input: std::pin::Pin<&sixtyfps_corelib::items::TextInput>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_path(&mut self, _path: std::pin::Pin<&sixtyfps_corelib::items::Path>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_box_shadow(&mut self, _box_shadow: std::pin::Pin<&sixtyfps_corelib::items::BoxShadow>) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combine_clip(
|
||||||
|
&mut self,
|
||||||
|
_rect: sixtyfps_corelib::graphics::Rect,
|
||||||
|
_radius: f32,
|
||||||
|
_border_width: f32,
|
||||||
|
) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_current_clip(&self) -> sixtyfps_corelib::graphics::Rect {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate(&mut self, _x: f32, _y: f32) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rotate(&mut self, _angle_in_degrees: f32) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_opacity(&mut self, _opacity: f32) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_state(&mut self) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore_state(&mut self) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_factor(&self) -> f32 {
|
||||||
|
// TODO
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_cached_pixmap(
|
||||||
|
&mut self,
|
||||||
|
_item_cache: &sixtyfps_corelib::item_rendering::CachedRenderingData,
|
||||||
|
_update_fn: &dyn Fn(&mut dyn FnMut(u32, u32, &[u8])),
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn window(&self) -> sixtyfps_corelib::window::WindowRc {
|
||||||
|
self.window.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut dyn core::any::Any {
|
||||||
|
self.draw_target
|
||||||
|
}
|
||||||
|
}
|
330
sixtyfps_runtime/rendering_backends/mcu/simulator.rs
Normal file
330
sixtyfps_runtime/rendering_backends/mcu/simulator.rs
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
/* LICENSE BEGIN
|
||||||
|
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||||
|
Copyright (c) 2021 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||||
|
Copyright (c) 2021 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
This file is also available under commercial licensing terms.
|
||||||
|
Please contact info@sixtyfps.io for more information.
|
||||||
|
LICENSE END */
|
||||||
|
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
|
use embedded_graphics::prelude::*;
|
||||||
|
use embedded_graphics_simulator::SimulatorDisplay;
|
||||||
|
use rgb::FromSlice;
|
||||||
|
use sixtyfps_corelib::component::ComponentRc;
|
||||||
|
use sixtyfps_corelib::input::KeyboardModifiers;
|
||||||
|
use sixtyfps_corelib::items::ItemRef;
|
||||||
|
use sixtyfps_corelib::layout::Orientation;
|
||||||
|
use sixtyfps_corelib::window::PlatformWindow;
|
||||||
|
use sixtyfps_corelib::Color;
|
||||||
|
|
||||||
|
use self::event_loop::WinitWindow;
|
||||||
|
|
||||||
|
type Canvas = femtovg::Canvas<femtovg::renderer::OpenGl>;
|
||||||
|
type CanvasRc = Rc<RefCell<Canvas>>;
|
||||||
|
|
||||||
|
pub mod event_loop;
|
||||||
|
mod glcontext;
|
||||||
|
use glcontext::*;
|
||||||
|
|
||||||
|
pub struct SimulatorWindow {
|
||||||
|
self_weak: Weak<sixtyfps_corelib::window::Window>,
|
||||||
|
keyboard_modifiers: std::cell::Cell<KeyboardModifiers>,
|
||||||
|
currently_pressed_key_code: std::cell::Cell<Option<winit::event::VirtualKeyCode>>,
|
||||||
|
canvas: CanvasRc,
|
||||||
|
opengl_context: OpenGLContext,
|
||||||
|
constraints: Cell<(sixtyfps_corelib::layout::LayoutInfo, sixtyfps_corelib::layout::LayoutInfo)>,
|
||||||
|
visible: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimulatorWindow {
|
||||||
|
pub(crate) fn new(window_weak: &Weak<sixtyfps_corelib::window::Window>) -> Rc<Self> {
|
||||||
|
let window_builder = winit::window::WindowBuilder::new().with_visible(false);
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
let (opengl_context, renderer) =
|
||||||
|
OpenGLContext::new_context_and_renderer(window_builder, &self.canvas_id);
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
let (opengl_context, renderer) = OpenGLContext::new_context_and_renderer(window_builder);
|
||||||
|
|
||||||
|
let canvas = femtovg::Canvas::new(renderer).unwrap();
|
||||||
|
|
||||||
|
opengl_context.make_not_current();
|
||||||
|
|
||||||
|
let canvas = Rc::new(RefCell::new(canvas));
|
||||||
|
|
||||||
|
let window_rc = Rc::new(Self {
|
||||||
|
self_weak: window_weak.clone(),
|
||||||
|
keyboard_modifiers: Default::default(),
|
||||||
|
currently_pressed_key_code: Default::default(),
|
||||||
|
canvas,
|
||||||
|
opengl_context,
|
||||||
|
constraints: Default::default(),
|
||||||
|
visible: Default::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let runtime_window = window_weak.upgrade().unwrap();
|
||||||
|
runtime_window.set_scale_factor(window_rc.opengl_context.window().scale_factor() as _);
|
||||||
|
|
||||||
|
window_rc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SimulatorWindow {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
crate::event_loop::unregister_window(self.opengl_context.window().id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlatformWindow for SimulatorWindow {
|
||||||
|
fn show(self: Rc<Self>) {
|
||||||
|
if self.visible.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.visible.set(true);
|
||||||
|
|
||||||
|
let runtime_window = self.runtime_window();
|
||||||
|
let component_rc = runtime_window.component();
|
||||||
|
let component = ComponentRc::borrow_pin(&component_rc);
|
||||||
|
let root_item = component.as_ref().get_item_ref(0);
|
||||||
|
|
||||||
|
let platform_window = self.opengl_context.window();
|
||||||
|
|
||||||
|
if let Some(window_item) =
|
||||||
|
ItemRef::downcast_pin::<sixtyfps_corelib::items::WindowItem>(root_item)
|
||||||
|
{
|
||||||
|
platform_window.set_title(&window_item.title());
|
||||||
|
platform_window.set_decorations(!window_item.no_frame());
|
||||||
|
};
|
||||||
|
|
||||||
|
if std::env::var("SIXTYFPS_FULLSCREEN").is_ok() {
|
||||||
|
platform_window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(None)))
|
||||||
|
} else {
|
||||||
|
let layout_info_h = component.as_ref().layout_info(Orientation::Horizontal);
|
||||||
|
let layout_info_v = component.as_ref().layout_info(Orientation::Vertical);
|
||||||
|
let s = winit::dpi::LogicalSize::new(
|
||||||
|
layout_info_h.preferred_bounded(),
|
||||||
|
layout_info_v.preferred_bounded(),
|
||||||
|
);
|
||||||
|
if s.width > 0. && s.height > 0. {
|
||||||
|
// Make sure that the window's inner size is in sync with the root window item's
|
||||||
|
// width/height.
|
||||||
|
runtime_window.set_window_item_geometry(s.width, s.height);
|
||||||
|
platform_window.set_inner_size(s)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
platform_window.set_visible(true);
|
||||||
|
let id = platform_window.id();
|
||||||
|
drop(platform_window);
|
||||||
|
crate::event_loop::register_window(id, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hide(self: Rc<Self>) {
|
||||||
|
self.opengl_context.window().set_visible(false);
|
||||||
|
self.visible.set(false);
|
||||||
|
crate::event_loop::unregister_window(self.opengl_context.window().id());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_redraw(&self) {
|
||||||
|
if self.visible.get() {
|
||||||
|
self.opengl_context.window().request_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_graphics_resources<'a>(
|
||||||
|
&self,
|
||||||
|
_items: &mut dyn Iterator<Item = std::pin::Pin<sixtyfps_corelib::items::ItemRef<'a>>>,
|
||||||
|
) {
|
||||||
|
// Nothing to do until we start caching stuff that needs freeing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_popup(
|
||||||
|
&self,
|
||||||
|
_popup: &sixtyfps_corelib::component::ComponentRc,
|
||||||
|
_position: sixtyfps_corelib::graphics::Point,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_window_properties_update(&self) {
|
||||||
|
let window_id = self.opengl_context.window().id();
|
||||||
|
crate::event_loop::with_window_target(|event_loop| {
|
||||||
|
event_loop
|
||||||
|
.event_loop_proxy()
|
||||||
|
.send_event(crate::event_loop::CustomEvent::UpdateWindowProperties(window_id))
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_window_properties(
|
||||||
|
&self,
|
||||||
|
window_item: std::pin::Pin<&sixtyfps_corelib::items::WindowItem>,
|
||||||
|
) {
|
||||||
|
WinitWindow::apply_window_properties(self as &dyn WinitWindow, window_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_geometry_constraint(
|
||||||
|
&self,
|
||||||
|
constraints_horizontal: sixtyfps_corelib::layout::LayoutInfo,
|
||||||
|
constraints_vertical: sixtyfps_corelib::layout::LayoutInfo,
|
||||||
|
) {
|
||||||
|
self.apply_constraints(constraints_horizontal, constraints_vertical)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_size(
|
||||||
|
&self,
|
||||||
|
_font_request: sixtyfps_corelib::graphics::FontRequest,
|
||||||
|
_text: &str,
|
||||||
|
_max_width: Option<f32>,
|
||||||
|
) -> sixtyfps_corelib::graphics::Size {
|
||||||
|
// TODO
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_input_byte_offset_for_position(
|
||||||
|
&self,
|
||||||
|
_text_input: std::pin::Pin<&sixtyfps_corelib::items::TextInput>,
|
||||||
|
_pos: sixtyfps_corelib::graphics::Point,
|
||||||
|
) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_input_position_for_byte_offset(
|
||||||
|
&self,
|
||||||
|
_text_input: std::pin::Pin<&sixtyfps_corelib::items::TextInput>,
|
||||||
|
_byte_offset: usize,
|
||||||
|
) -> sixtyfps_corelib::graphics::Point {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn core::any::Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinitWindow for SimulatorWindow {
|
||||||
|
fn runtime_window(&self) -> Rc<sixtyfps_corelib::window::Window> {
|
||||||
|
self.self_weak.upgrade().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn currently_pressed_key_code(&self) -> &Cell<Option<winit::event::VirtualKeyCode>> {
|
||||||
|
&self.currently_pressed_key_code
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_keyboard_modifiers(&self) -> &Cell<KeyboardModifiers> {
|
||||||
|
&self.keyboard_modifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(self: Rc<Self>) {
|
||||||
|
let runtime_window = self.self_weak.upgrade().unwrap();
|
||||||
|
runtime_window.clone().draw_contents(|components| {
|
||||||
|
let size = self.opengl_context.window().inner_size();
|
||||||
|
|
||||||
|
self.opengl_context.with_current_context(|| {
|
||||||
|
self.opengl_context.ensure_resized();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
|
// We pass 1.0 as dpi / device pixel ratio as femtovg only uses this factor to scale
|
||||||
|
// text metrics. Since we do the entire translation from logical pixels to physical
|
||||||
|
// pixels on our end, we don't need femtovg to scale a second time.
|
||||||
|
canvas.set_size(size.width, size.height, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut display: SimulatorDisplay<embedded_graphics::pixelcolor::Rgb888> =
|
||||||
|
SimulatorDisplay::new(Size { width: size.width, height: size.height });
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
{
|
||||||
|
use embedded_graphics::{
|
||||||
|
pixelcolor::Rgb888,
|
||||||
|
prelude::*,
|
||||||
|
primitives::{PrimitiveStyleBuilder, Rectangle},
|
||||||
|
};
|
||||||
|
|
||||||
|
let style = PrimitiveStyleBuilder::new()
|
||||||
|
.stroke_color(Rgb888::RED)
|
||||||
|
.stroke_width(3)
|
||||||
|
.fill_color(Rgb888::GREEN)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Rectangle::new(Point::new(30, 20), Size::new(10, 15))
|
||||||
|
.into_styled(style)
|
||||||
|
.draw(&mut display)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut renderer = crate::renderer::SoftwareRenderer {
|
||||||
|
draw_target: &mut display,
|
||||||
|
window: runtime_window.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (component, origin) in components {
|
||||||
|
sixtyfps_corelib::item_rendering::render_component_items(
|
||||||
|
&component,
|
||||||
|
&mut renderer,
|
||||||
|
origin.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_image = display
|
||||||
|
.to_rgb_output_image(&embedded_graphics_simulator::OutputSettings::default());
|
||||||
|
let image_buffer = output_image.as_image_buffer();
|
||||||
|
let image_ref: imgref::ImgRef<rgb::RGB8> = imgref::ImgRef::new(
|
||||||
|
image_buffer.as_rgb(),
|
||||||
|
image_buffer.width() as usize,
|
||||||
|
image_buffer.height() as usize,
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
|
let image_id =
|
||||||
|
canvas.create_image(image_ref, femtovg::ImageFlags::empty()).unwrap();
|
||||||
|
|
||||||
|
let mut path = femtovg::Path::new();
|
||||||
|
path.rect(0., 0., image_ref.width() as _, image_ref.height() as _);
|
||||||
|
|
||||||
|
let fill_paint = femtovg::Paint::image(
|
||||||
|
image_id,
|
||||||
|
0.,
|
||||||
|
0.,
|
||||||
|
image_ref.width() as _,
|
||||||
|
image_ref.height() as _,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.fill_path(&mut path, fill_paint);
|
||||||
|
|
||||||
|
canvas.flush();
|
||||||
|
canvas.delete_image(image_id);
|
||||||
|
|
||||||
|
self.opengl_context.swap_buffers();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_window_handle(&self, callback: &mut dyn FnMut(&winit::window::Window)) {
|
||||||
|
callback(&*self.opengl_context.window())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn constraints(
|
||||||
|
&self,
|
||||||
|
) -> (sixtyfps_corelib::layout::LayoutInfo, sixtyfps_corelib::layout::LayoutInfo) {
|
||||||
|
self.constraints.get()
|
||||||
|
}
|
||||||
|
fn set_constraints(
|
||||||
|
&self,
|
||||||
|
constraints: (sixtyfps_corelib::layout::LayoutInfo, sixtyfps_corelib::layout::LayoutInfo),
|
||||||
|
) {
|
||||||
|
self.constraints.set(constraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_background_color(&self, _color: Color) {}
|
||||||
|
fn set_icon(&self, _icon: sixtyfps_corelib::graphics::Image) {}
|
||||||
|
}
|
1
sixtyfps_runtime/rendering_backends/mcu/simulator/event_loop.rs
Symbolic link
1
sixtyfps_runtime/rendering_backends/mcu/simulator/event_loop.rs
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../gl/event_loop.rs
|
1
sixtyfps_runtime/rendering_backends/mcu/simulator/glcontext.rs
Symbolic link
1
sixtyfps_runtime/rendering_backends/mcu/simulator/glcontext.rs
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../gl/glcontext.rs
|
Loading…
Add table
Add a link
Reference in a new issue