From 0dc2c394cc45ec9cb60fdeb1544006c5a6c4c01c Mon Sep 17 00:00:00 2001 From: Joshua Thijssen Date: Tue, 24 Dec 2024 12:27:45 +0100 Subject: [PATCH 1/2] Added functionality to render tree from html-source instead of url --- crates/gosub_interface/src/draw.rs | 13 ++++++ crates/gosub_renderer/src/draw.rs | 8 +++- crates/gosub_renderer/src/render_tree.rs | 50 +++++++++++++++--------- src/prelude.rs | 2 + 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/crates/gosub_interface/src/draw.rs b/crates/gosub_interface/src/draw.rs index 41cec5f6..98e3b209 100644 --- a/crates/gosub_interface/src/draw.rs +++ b/crates/gosub_interface/src/draw.rs @@ -27,6 +27,19 @@ pub trait TreeDrawer { where Self: Sized; + fn from_source( + // The initial url that the source was loaded from + url: Url, + // Actual loaded source HTML + source_html: &str, + // Layouter that renders the tree + layouter: C::Layouter, + // Debug flag + debug: bool, + ) -> impl Future> + where + Self: Sized; + fn clear_buffers(&mut self); fn toggle_debug(&mut self); diff --git a/crates/gosub_renderer/src/draw.rs b/crates/gosub_renderer/src/draw.rs index c9681199..23b086be 100644 --- a/crates/gosub_renderer/src/draw.rs +++ b/crates/gosub_renderer/src/draw.rs @@ -212,7 +212,13 @@ where } async fn from_url(url: Url, layouter: C::Layouter, debug: bool) -> Result { - let (rt, fetcher) = load_html_rendertree::(url.clone()).await?; + let (rt, fetcher) = load_html_rendertree::(url.clone(), None).await?; + + Ok(Self::new(rt, layouter, fetcher, debug)) + } + + async fn from_source(url: Url, source_html: &str, layouter: C::Layouter, debug: bool) -> Result { + let (rt, fetcher) = load_html_rendertree::(url, Some(source_html)).await?; Ok(Self::new(rt, layouter, fetcher, debug)) } diff --git a/crates/gosub_renderer/src/render_tree.rs b/crates/gosub_renderer/src/render_tree.rs index 0e39e9a6..502acf8d 100644 --- a/crates/gosub_renderer/src/render_tree.rs +++ b/crates/gosub_renderer/src/render_tree.rs @@ -10,40 +10,31 @@ use gosub_shared::byte_stream::{ByteStream, Encoding}; use std::fs; use url::Url; +/// Generates a render tree from the given URL.. if the source is given, the URL is not loaded, but the source HTML is used instead pub(crate) async fn load_html_rendertree< C: HasRenderTree, RenderTree = RenderTree> + HasHtmlParser, >( url: Url, + source: Option<&str>, ) -> gosub_shared::types::Result<(RenderTree, Fetcher)> { let fetcher = Fetcher::new(url.clone()); - let rt = load_html_rendertree_fetcher::(url, &fetcher).await?; + let rt = match source { + Some(source) => load_html_rendertree_source::(url, source).await?, + None => load_html_rendertree_fetcher::(url, &fetcher).await?, + }; Ok((rt, fetcher)) } -pub(crate) async fn load_html_rendertree_fetcher< +pub(crate) async fn load_html_rendertree_source< C: HasRenderTree, RenderTree = RenderTree> + HasHtmlParser, >( url: Url, - fetcher: &Fetcher, + source_html: &str, ) -> gosub_shared::types::Result> { - let html = if url.scheme() == "http" || url.scheme() == "https" { - // Fetch the html from the url - let response = fetcher.get(url.as_ref()).await?; - if response.status != 200 { - bail!(format!("Could not get url. Status code {}", response.status)); - } - - String::from_utf8(response.body.clone())? - } else if url.scheme() == "file" { - fs::read_to_string(url.as_str().trim_start_matches("file://"))? - } else { - bail!("Unsupported url scheme: {}", url.scheme()); - }; - let mut stream = ByteStream::new(Encoding::UTF8, None); - stream.read_from_str(&html, Some(Encoding::UTF8)); + stream.read_from_str(source_html, Some(Encoding::UTF8)); stream.close(); let mut doc_handle = C::DocumentBuilder::new_document(Some(url)); @@ -61,3 +52,26 @@ pub(crate) async fn load_html_rendertree_fetcher< generate_render_tree(DocumentHandle::clone(&doc_handle)) } + +pub(crate) async fn load_html_rendertree_fetcher< + C: HasRenderTree, RenderTree = RenderTree> + HasHtmlParser, +>( + url: Url, + fetcher: &Fetcher, +) -> gosub_shared::types::Result> { + let html = if url.scheme() == "http" || url.scheme() == "https" { + // Fetch the html from the url + let response = fetcher.get(url.as_ref()).await?; + if response.status != 200 { + bail!(format!("Could not get url. Status code {}", response.status)); + } + + String::from_utf8(response.body.clone())? + } else if url.scheme() == "file" { + fs::read_to_string(url.as_str().trim_start_matches("file://"))? + } else { + bail!("Unsupported url scheme: {}", url.scheme()); + }; + + load_html_rendertree_source(url, &html).await +} diff --git a/src/prelude.rs b/src/prelude.rs index a6d998ff..49b050c8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,7 @@ pub use gosub_interface::config::*; +pub use gosub_interface::draw::TreeDrawer; pub use gosub_interface::render_backend::ImageBuffer; +pub use gosub_interface::render_backend::RenderBackend; pub use gosub_interface::render_backend::WindowedEventLoop; pub use gosub_shared::geo::*; From 9c53acad66102956cccdb4eda8c58630e4482074 Mon Sep 17 00:00:00 2001 From: Joshua Thijssen Date: Tue, 24 Dec 2024 15:07:58 +0100 Subject: [PATCH 2/2] Moved function to sync --- crates/gosub_interface/src/draw.rs | 2 +- crates/gosub_renderer/src/draw.rs | 7 ++++--- crates/gosub_renderer/src/render_tree.rs | 9 ++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/gosub_interface/src/draw.rs b/crates/gosub_interface/src/draw.rs index 98e3b209..f86f5f77 100644 --- a/crates/gosub_interface/src/draw.rs +++ b/crates/gosub_interface/src/draw.rs @@ -36,7 +36,7 @@ pub trait TreeDrawer { layouter: C::Layouter, // Debug flag debug: bool, - ) -> impl Future> + ) -> gosub_shared::types::Result where Self: Sized; diff --git a/crates/gosub_renderer/src/draw.rs b/crates/gosub_renderer/src/draw.rs index 23b086be..f0eb582b 100644 --- a/crates/gosub_renderer/src/draw.rs +++ b/crates/gosub_renderer/src/draw.rs @@ -2,7 +2,7 @@ use crate::debug::scale::px_scale; use crate::draw::img::request_img; use crate::draw::img_cache::ImageCache; use crate::draw::testing::{test_add_element, test_restyle_element}; -use crate::render_tree::{load_html_rendertree, load_html_rendertree_fetcher}; +use crate::render_tree::{load_html_rendertree, load_html_rendertree_fetcher, load_html_rendertree_source}; use anyhow::anyhow; use gosub_interface::config::{HasDrawComponents, HasHtmlParser}; use gosub_interface::css3::{CssProperty, CssPropertyMap, CssValue}; @@ -217,8 +217,9 @@ where Ok(Self::new(rt, layouter, fetcher, debug)) } - async fn from_source(url: Url, source_html: &str, layouter: C::Layouter, debug: bool) -> Result { - let (rt, fetcher) = load_html_rendertree::(url, Some(source_html)).await?; + fn from_source(url: Url, source_html: &str, layouter: C::Layouter, debug: bool) -> Result { + let fetcher = Fetcher::new(url.clone()); + let rt = load_html_rendertree_source::(url, source_html)?; Ok(Self::new(rt, layouter, fetcher, debug)) } diff --git a/crates/gosub_renderer/src/render_tree.rs b/crates/gosub_renderer/src/render_tree.rs index 502acf8d..a6a80b57 100644 --- a/crates/gosub_renderer/src/render_tree.rs +++ b/crates/gosub_renderer/src/render_tree.rs @@ -20,14 +20,16 @@ pub(crate) async fn load_html_rendertree< let fetcher = Fetcher::new(url.clone()); let rt = match source { - Some(source) => load_html_rendertree_source::(url, source).await?, + Some(source) => load_html_rendertree_source::(url, source)?, None => load_html_rendertree_fetcher::(url, &fetcher).await?, }; Ok((rt, fetcher)) } -pub(crate) async fn load_html_rendertree_source< +// Generate a render tree from the given source HTML. THe URL is needed to resolve relative URLs +// and also to set the base URL for the document. +pub(crate) fn load_html_rendertree_source< C: HasRenderTree, RenderTree = RenderTree> + HasHtmlParser, >( url: Url, @@ -53,6 +55,7 @@ pub(crate) async fn load_html_rendertree_source< generate_render_tree(DocumentHandle::clone(&doc_handle)) } +/// Generates a render tree from the given URL. The complete HTML source is fetched from the URL async. pub(crate) async fn load_html_rendertree_fetcher< C: HasRenderTree, RenderTree = RenderTree> + HasHtmlParser, >( @@ -73,5 +76,5 @@ pub(crate) async fn load_html_rendertree_fetcher< bail!("Unsupported url scheme: {}", url.scheme()); }; - load_html_rendertree_source(url, &html).await + load_html_rendertree_source(url, &html) }