Commit 639389e8 authored by Florian Blasius's avatar Florian Blasius 🤘
Browse files

Initial cairo backend. Add runner struct.

parent 6fe4d8fb
Pipeline #2334 passed with stage
in 3 minutes
This diff is collapsed.
......@@ -8,10 +8,11 @@ edition = "2018"
stdweb = "0.4.12"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
winit = "0.18"
glutin = "0.19"
gleam = "0.6.8"
glium = "0.22.0"
euclid = "0.19"
webrender = { git = "https://github.com/servo/webrender.git" }
#winit = "0.18"
#glutin = "0.19"
#gleam = "0.6.8"
#glium = "0.22.0"
#euclid = "0.19"
#webrender = { git = "https://github.com/servo/webrender.git" }
rust-cairo = { git = "https://gitlab.redox-os.org/redox-os/rust-cairo.git" }
orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient.git" }
\ No newline at end of file
This diff is collapsed.
use orbrender;
use orbrender::backend::Runner;
use orbrender::prelude::*;
use stdweb;
use time::PreciseTime;
use std::sync::atomic::{self, AtomicBool};
use std::sync::Arc;
fn main() {
let mut window = WindowBuilder::new()
.with_title("OrbRender - drawing example")
......@@ -50,41 +55,64 @@ fn main() {
.with_text("OrbRender")
.with_position(Point::new(10.0, 80.0))
.with_foreground(Color::rgb(100, 100, 100))
.with_font(FontConfig::default().with_family("Roboto").with_size(22.0))
.with_font(FontConfig::default().with_family("Roboto").with_size(22.0)),
);
window.push_image(
window.push_image(
Image::default()
.with_position(Point::new(10.0, 100.0))
.with_source("res/orbtk-space.png")
.with_source("res/orbtk-space.png"),
);
// let mut draw = false;
let mut running = true;
let mut update = true;
let update = Arc::new(AtomicBool::new(true));
loop {
if !running {
break;
}
// let start = PreciseTime::now();
if update {
let mut runner = Runner::new(Box::new(move || {
if update.load(atomic::Ordering::Acquire) {
window.render();
update = false;
update.store(false, atomic::Ordering::Release);
}
for event in window.events() {
match event {
Event::System(system_event) => match system_event {
SystemEvent::Quit => {
running = false;
// running = false;
}
_ => {}
},
_ => {}
}
}
// let end = PreciseTime::now();
// println!("{} seconds for whatever you did.", start.to(end));
}
}));
runner.run();
// let mut draw = false;
// let mut running = true;
// let mut update = true;
//
// loop {
// if !running {
// break;
// }
// // let start = PreciseTime::now();
// if update {
// window.render();
// update = false;
// }
//
// for event in window.events() {
// match event {
// Event::System(system_event) => match system_event {
// SystemEvent::Quit => {
// running = false;
// }
// _ => {}
// },
// _ => {}
// }
// }
// // let end = PreciseTime::now();
// // println!("{} seconds for whatever you did.", start.to(end));
// }
}
use orbclient;
use orbclient::Renderer;
use rust_cairo::*;
use std::ffi::CString;
use std::os::raw::c_char;
use crate::{
events::{Event, SystemEvent},
render_objects::{Image, Rectangle, RenderStorage, Text},
structs::Color,
traits::Window,
window::WindowBuilder,
};
pub struct Runner {
run: Box<FnMut()>,
}
impl Runner {
pub fn new(run: Box<FnMut()>) -> Self {
Runner {
run
}
}
pub fn run(mut self) {
loop {
(self.run)();
}
}
}
unsafe fn rounded_rect(
x: f64,
y: f64,
w: f64,
h: f64,
r: f64,
context: *mut cairo_t,
color: &Color,
) {
let m_pi = 3.14159265;
let degrees = m_pi / 180.0;
//draw object
cairo_new_sub_path(context);
cairo_arc(
context,
(x + w - r) as f64,
(y + r) as f64,
(r) as f64,
-90.0 * degrees,
0.0 * degrees,
);
cairo_arc(
context,
(x + w - r) as f64,
(y + h - r) as f64,
(r) as f64,
0.0 * degrees,
90.0 * degrees,
);
cairo_arc(
context,
(x + r) as f64,
(y + h - r) as f64,
(r) as f64,
90.0 * degrees,
180.0 * degrees,
);
cairo_arc(
context,
(x + r) as f64,
(y + r) as f64,
(r) as f64,
180.0 * degrees,
270.0 * degrees,
);
cairo_close_path(context);
cairo_set_source_rgba(
context,
color.r_f() as f64,
color.g_f() as f64,
color.b_f() as f64,
color.a_f() as f64,
);
cairo_fill(context);
}
pub fn build_window(window_builder: WindowBuilder) -> Box<Window> {
Box::new(CairoWindow::from(window_builder))
}
pub fn initialize() {}
/// Backend for Cairo library.
pub struct CairoWindow {
inner_window: orbclient::Window,
render_storage: RenderStorage,
background: Color,
cairo_context: *mut _cairo,
}
impl Window for CairoWindow {
fn render(&mut self) {
// window background
self.inner_window.set(orbclient::Color::rgba(
self.background.r(),
self.background.g(),
self.background.b(),
self.background.a(),
));
for render_object in self.render_storage.into_iter() {
unsafe {
// Render rectangles
if let Some(rectangle) = render_object.downcast_ref::<Rectangle>() {
let size = rectangle.size;
let position = rectangle.position;
let border_thickness = rectangle.border_thickness;
// Render border
if border_thickness.left > 0.0
|| border_thickness.top > 0.0
|| border_thickness.right > 0.0
|| border_thickness.bottom > 0.0
{
// todo: use border_thickness
if let Some(border_color) = rectangle.border_color {
if rectangle.radius > 0.0 {
rounded_rect(
position.x as f64,
position.y as f64,
size.width as f64,
size.height as f64,
rectangle.radius as f64,
self.cairo_context,
&border_color,
);
} else {
cairo_rectangle(self.cairo_context, position.x as f64,
position.y as f64,
size.width as f64,
size.height as f64);
cairo_set_source_rgba(
self.cairo_context,
border_color.r_f() as f64,
border_color.g_f() as f64,
border_color.b_f() as f64,
border_color.a_f() as f64,
);
cairo_fill(self.cairo_context);
}
}
}
if let Some(background) = rectangle.background {
if rectangle.radius > 0.0 {
rounded_rect(
(position.x + border_thickness.left) as f64,
(position.y + border_thickness.top) as f64,
(size.width - border_thickness.left - border_thickness.right) as f64,
(size.height - border_thickness.top - border_thickness.bottom) as f64,
rectangle.radius as f64,
self.cairo_context,
&background,
);
} else {
cairo_rectangle(self.cairo_context, (position.x + border_thickness.left) as f64,
(position.y + border_thickness.top) as f64,
(size.width - border_thickness.left - border_thickness.right) as f64,
(size.height - border_thickness.top - border_thickness.bottom) as f64);
cairo_set_source_rgba(
self.cairo_context,
background.r_f() as f64,
background.g_f() as f64,
background.b_f() as f64,
background.a_f() as f64,
);
cairo_fill(self.cairo_context);
}
}
}
if let Some(tx) = render_object.downcast_ref::<Text>() {
let position = tx.position;
cairo_set_source_rgba(self.cairo_context, tx.foreground.r_f() as f64,
tx.foreground.g_f() as f64,
tx.foreground.b_f() as f64,
tx.foreground.a_f() as f64);
let font = CString::new(tx.font.family.clone()).expect("CString::new failed");
let text = CString::new(tx.text.clone()).expect("CString::new failed");
cairo_select_font_face(self.cairo_context, font.as_ptr(), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
// if self.text_bold {
// cairo_select_font_face(cr, font.as_ptr(), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
// }
cairo_set_font_size(self.cairo_context, tx.font.size as f64);
let mut text_extens = cairo_text_extents_t {
x_bearing: 0.0,
y_bearing: 0.0,
width: 0.0,
height: 0.0,
x_advance: 0.0,
y_advance: 0.0,
};
cairo_text_extents(self.cairo_context, text.as_ptr(), &mut text_extens as *mut cairo_text_extents_t);
cairo_move_to(self.cairo_context, position.x as f64, position.y as f64);
cairo_show_text(self.cairo_context, text.as_ptr());
}
if let Some(img) = render_object.downcast_ref::<Image>() {
// cairo_new_sub_path(self.cairo_context);
// let image = Image::from_path(img.source);
// let c_image = cairo_image_surface_create_for_data()
// cairo_set_source_surface(self.cairo_context, )
}
}
}
self.inner_window.sync();
}
fn background(&mut self, background: Color) {
self.background = background;
}
fn push_rectangle_with_z(&mut self, rectangle: Rectangle, z: usize) -> usize {
self.render_storage.push_with_z(rectangle, z)
}
fn push_text_with_z(&mut self, text: Text, z: usize) -> usize {
self.render_storage.push_with_z(text, z)
}
fn push_image_with_z(&mut self, image: Image, z: usize) -> usize {
self.render_storage.push_with_z(image, z)
}
fn remove_render_objet(&mut self, index: usize) {
self.render_storage.remove(index);
}
fn clear(&mut self) {
self.render_storage.clear();
}
fn events(&mut self) -> Vec<Event> {
let mut events = vec![];
for event in self.inner_window.events() {
match event.to_option() {
orbclient::EventOption::Quit(_) => {
events.push(Event::System(SystemEvent::Quit));
}
_ => {}
}
}
events
}
}
impl From<WindowBuilder> for CairoWindow {
fn from(builder: WindowBuilder) -> CairoWindow {
let mut flags = vec![];
if builder.transparent {
flags.push(orbclient::WindowFlag::Transparent);
}
if !builder.decorations {
flags.push(orbclient::WindowFlag::Borderless);
}
let mut inner_window = orbclient::Window::new_flags(
0,
0,
builder.size.width as u32,
builder.size.height as u32,
&builder.title[..],
&flags,
)
.unwrap();
let mut cr;
unsafe {
let surface = cairo_image_surface_create_for_data(
inner_window.data_mut().as_mut_ptr() as *mut u8,
CAIRO_FORMAT_ARGB32,
builder.size.width as i32,
builder.size.height as i32,
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, builder.size.width as i32),
);
cr = cairo_create(surface);
//WHY I DO THIS?????
//The Answer -> https://mobtowers.com/2013/04/15/html5-canvas-crisp-lines-every-time/
// cairo_translate(cr, 0.5, 0.5);
}
CairoWindow {
inner_window,
render_storage: RenderStorage::default(),
background: builder.background,
cairo_context: cr,
}
}
}
#[cfg(target_arch = "wasm32")]
pub use self::stdweb::{build_window, initialize};
pub use self::stdweb::{build_window, initialize, Runner};
#[cfg(target_arch = "wasm32")]
mod stdweb;
#[cfg(not(target_arch = "wasm32"))]
pub use self::orbclient::{build_window, initialize};
pub use self::cairo::{build_window, initialize, Runner};
#[cfg(not(target_arch = "wasm32"))]
mod orbclient;
\ No newline at end of file
mod cairo;
////
//#[cfg(not(target_arch = "wasm32"))]
//pub use self::orbclient::{build_window, initialize};
//
//#[cfg(not(target_arch = "wasm32"))]
//mod orbclient;
////#[cfg(feature="webren")]
//pub use self::webrender::{build_window, initialize};
//
////#[cfg(feature="webren")]
//mod webrender;
\ No newline at end of file
......@@ -5,6 +5,23 @@ use stdweb::{
web::{document, html_element::{CanvasElement, ImageElement}, window, CanvasRenderingContext2d, FillRule},
};
pub struct Runner {
run: Box<FnMut()>,
}
impl Runner {
pub fn new(run: Box<FnMut()>) -> Self {
Runner {
run
}
}
pub fn run(mut self) {
(self.run)();
window().request_animation_frame(|_| self.run());
}
}
// Shamelessly stolen from webplatform's TodoMVC example.
macro_rules! enclose {
( ($( $x:ident ),*) $y:expr ) => {
......@@ -186,7 +203,7 @@ impl Window for StdWebWindow {
}
fn events(&mut self) -> Vec<Event> {
stdweb::event_loop();
vec![Event::System(SystemEvent::Quit)]
}
}
......@@ -206,6 +223,8 @@ impl From<WindowBuilder> for StdWebWindow {
canvas.set_width(builder.size.width as u32);
canvas.set_height(builder.size.height as u32);
stdweb::event_loop();
StdWebWindow {
canvas,
context,
......
......@@ -15,12 +15,14 @@ use winit;
use crate::{
enums::WindowMode,
events::{Event as OrbEvent, SystemEvent},
render_objects::{Rectangle, RenderStorage},
render_objects::{Rectangle, Text, RenderStorage, Image},
structs::Color,
traits::Window,
window::WindowBuilder,
};
pub fn initialize() {}
pub fn build_window(window_builder: WindowBuilder) -> Box<Window> {
Box::new(WebRenderWindow::from(window_builder))
}
......@@ -251,8 +253,12 @@ impl Window for WebRenderWindow {
self.render_storage.push_with_z(rectangle, z)
}
fn push_rectangle(&mut self, rectangle: Rectangle) -> usize {
self.render_storage.push_with_z(rectangle, 0)
fn push_text_with_z(&mut self, text: Text, z: usize) -> usize {
self.render_storage.push_with_z(text, z)
}
fn push_image_with_z(&mut self, image: Image, z: usize) -> usize {
self.render_storage.push_with_z(image, z)
}
fn remove_render_objet(&mut self, index: usize) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment