Skip to content

Commit

Permalink
Upgrade to vello 0.3, parley 0.2, peniko 0.2 and usvg 0.43
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoburns committed Oct 10, 2024
1 parent e3af5cf commit 4b66061
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 135 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ dioxus-devtools = { git = "https://github.com/dioxuslabs/dioxus", rev = "9ffd4b8
taffy = { git = "https://github.com/dioxuslabs/taffy", rev = "950a0eb1322f15e5d1083f4793b55d52061718de" }

# Linebender dependencies
peniko = { version = "0.1" }
vello = { git = "https://github.com/linebender/vello", rev = "aaa9f5f2d0f21f3d038501ea0cf32c989d97aab3", package = "vello", features = [ "wgpu" ] }
vello_svg = { git = "https://github.com/cfraz89/vello_svg", rev = "fc29d4ebf8d6aaee980b203f39ef2c73fe43c017" }
parley = { git = "https://github.com/nicoburns/parley", rev = "186b6e991d08731c0588dc0b247564cbba1c0435" }
peniko = { version = "0.2" }
vello = { version = "0.3", features = [ "wgpu" ] }
vello_svg = { version = "0.4" }
parley = { version = "0.2" }

# Other dependencies
tokio = { version = "1.25.0", features = ["full"] }
clipboard-rs = { version = "0.2.1" }
tracing = "0.1.40"
wgpu = "22.1.0"

Expand Down
3 changes: 2 additions & 1 deletion packages/blitz-dom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ style_dom = { workspace = true }
taffy = { workspace = true }
parley = { workspace = true }
peniko = { workspace = true }
clipboard-rs = { workspace = true }
tracing = { workspace = true, optional = true }
slab = "0.4.9"
app_units = "0.7.5"
Expand All @@ -29,5 +30,5 @@ url = { version = "2.5.0", features = ["serde"] }
data-url = "0.3.1"
image = "0.25.2"
winit = { version = "0.30.4", default-features = false }
usvg = "0.42.0"
usvg = "0.43.0"
woff = "0.3.3"
209 changes: 185 additions & 24 deletions packages/blitz-dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ use crate::node::{ImageData, NodeSpecificData, TextBrush};
use crate::{ElementNodeData, Node, NodeData, TextNodeData, Viewport};
use app_units::Au;
use html5ever::local_name;
use parley::PlainEditorOp;
use peniko::kurbo;
use string_cache::Atom;
use style::attr::{AttrIdentifier, AttrValue};
use style::values::computed::Overflow;
use style::values::GenericAtomIdent;
use winit::keyboard::{Key, NamedKey};
// use quadtree_rs::Quadtree;
use crate::util::Resource;
use parley::editor::{PointerButton, TextEvent};
use selectors::{matching::QuirksMode, Element};
use slab::Slab;
use std::any::Any;
Expand Down Expand Up @@ -79,7 +80,7 @@ pub struct Document {
/// We pin the tree to a guarantee to the nodes it creates that the tree is stable in memory.
///
/// There is no way to create the tree - publicly or privately - that would invalidate that invariant.
pub(crate) nodes: Box<Slab<Node>>,
pub nodes: Box<Slab<Node>>,

pub(crate) guard: SharedRwLock,

Expand Down Expand Up @@ -110,10 +111,10 @@ pub struct Document {
pub(crate) nodes_to_stylesheet: BTreeMap<usize, DocumentStyleSheet>,

/// A Parley font context
pub(crate) font_ctx: parley::FontContext,
pub font_ctx: parley::FontContext,

/// A Parley layout context
pub(crate) layout_ctx: parley::LayoutContext<TextBrush>,
pub layout_ctx: parley::LayoutContext<TextBrush>,

/// The node which is currently hovered (if any)
pub(crate) hover_node_id: Option<usize>,
Expand All @@ -130,7 +131,7 @@ impl DocumentLike for Document {
let event = dbg!(event);

match event.data {
EventData::Click { x, y, mods } => {
EventData::Click { x, y, .. } => {
let hit = self.hit(x, y);
if let Some(hit) = hit {
assert!(hit.node_id == event.target);
Expand All @@ -154,10 +155,10 @@ impl DocumentLike for Document {
{
let x = (hit.x - content_box_offset.x) as f64 * self.viewport.scale_f64();
let y = (hit.y - content_box_offset.y) as f64 * self.viewport.scale_f64();
text_input_data.editor.pointer_down(
kurbo::Point { x, y },
mods,
PointerButton::Primary,
text_input_data.editor.transact(
&mut self.font_ctx,
&mut self.layout_ctx,
[PlainEditorOp::MoveToPoint(x as f32, y as f32)],
);

self.set_focus_to(hit.node_id);
Expand Down Expand Up @@ -190,31 +191,191 @@ impl DocumentLike for Document {
return;
}

if !event.state.is_pressed() {
return;
}
#[allow(unused)]
let shift = mods.state().shift_key();
#[allow(unused)]
let action_mod = {
if cfg!(target_os = "macos") {
mods.state().super_key()
} else {
mods.state().control_key()
}
};

let node = &mut self.nodes[node_id];
let text_input_data = node
.raw_dom_data
.downcast_element_mut()
.and_then(|el| el.text_input_data_mut());

if let Some(input_data) = text_input_data {
let text_event = TextEvent::KeyboardKey(event, mods.state());
input_data.editor.text_event(&text_event);
macro_rules! transact {
($op:expr) => {{
input_data.editor.transact(
&mut self.font_ctx,
&mut self.layout_ctx,
[$op],
);
}};
}

match event.logical_key {
#[cfg(not(target_os = "android"))]
Key::Character(c)
if action_mod && matches!(c.as_str(), "c" | "x" | "v") =>
{
use clipboard_rs::{Clipboard, ClipboardContext};
use parley::layout::editor::ActiveText;

match c.to_lowercase().as_str() {
"c" => {
if let ActiveText::Selection(text) =
input_data.editor.active_text()
{
let cb = ClipboardContext::new().unwrap();
cb.set_text(text.to_owned()).ok();
}
}
"x" => {
if let ActiveText::Selection(text) =
input_data.editor.active_text()
{
let cb = ClipboardContext::new().unwrap();
cb.set_text(text.to_owned()).ok();
transact!(PlainEditorOp::DeleteSelection)
}
}
"v" => {
let cb = ClipboardContext::new().unwrap();
let text = cb.get_text().unwrap_or_default();
transact!(PlainEditorOp::InsertOrReplaceSelection(
text.into(),
))
}
_ => unreachable!(),
}
}
Key::Character(c)
if action_mod && matches!(c.to_lowercase().as_str(), "a") =>
{
if shift {
transact!(PlainEditorOp::CollapseSelection)
} else {
transact!(PlainEditorOp::SelectAll)
}
}
Key::Named(NamedKey::ArrowLeft) => {
if action_mod {
if shift {
transact!(PlainEditorOp::SelectWordLeft)
} else {
transact!(PlainEditorOp::MoveWordLeft)
}
} else if shift {
transact!(PlainEditorOp::SelectLeft)
} else {
transact!(PlainEditorOp::MoveLeft)
}
}
Key::Named(NamedKey::ArrowRight) => {
if action_mod {
if shift {
transact!(PlainEditorOp::SelectWordRight)
} else {
transact!(PlainEditorOp::MoveWordRight)
}
} else if shift {
transact!(PlainEditorOp::SelectRight)
} else {
transact!(PlainEditorOp::MoveRight)
}
}
Key::Named(NamedKey::ArrowUp) => {
if shift {
transact!(PlainEditorOp::SelectUp)
} else {
transact!(PlainEditorOp::MoveUp)
}
}
Key::Named(NamedKey::ArrowDown) => {
if shift {
transact!(PlainEditorOp::SelectDown)
} else {
transact!(PlainEditorOp::MoveDown)
}
}
Key::Named(NamedKey::Home) => {
if action_mod {
if shift {
transact!(PlainEditorOp::SelectToTextStart)
} else {
transact!(PlainEditorOp::MoveToTextStart)
}
} else if shift {
transact!(PlainEditorOp::SelectToLineStart)
} else {
transact!(PlainEditorOp::MoveToLineStart)
}
}
Key::Named(NamedKey::End) => {
if action_mod {
if shift {
transact!(PlainEditorOp::SelectToTextEnd)
} else {
transact!(PlainEditorOp::MoveToTextEnd)
}
} else if shift {
transact!(PlainEditorOp::SelectToLineEnd)
} else {
transact!(PlainEditorOp::MoveToLineEnd)
}
}
Key::Named(NamedKey::Delete) => {
if action_mod {
transact!(PlainEditorOp::DeleteWord)
} else {
transact!(PlainEditorOp::Delete)
}
}
Key::Named(NamedKey::Backspace) => {
if action_mod {
transact!(PlainEditorOp::BackdeleteWord)
} else {
transact!(PlainEditorOp::Backdelete)
}
}
Key::Named(NamedKey::Enter) => {
transact!(PlainEditorOp::InsertOrReplaceSelection("\n".into()))
}
Key::Named(NamedKey::Space) => {
transact!(PlainEditorOp::InsertOrReplaceSelection(" ".into()))
}
Key::Character(s) => {
transact!(PlainEditorOp::InsertOrReplaceSelection(s.into()))
}
_ => {}
};
println!("Sent text event to {}", node_id);
}
}
}
EventData::Ime(ime_event) => {
if let Some(node_id) = self.focus_node_id {
let node = &mut self.nodes[node_id];
let text_input_data = node
.raw_dom_data
.downcast_element_mut()
.and_then(|el| el.text_input_data_mut());
if let Some(input_data) = text_input_data {
let text_event = TextEvent::Ime(ime_event);
input_data.editor.text_event(&text_event);
println!("Sent ime event to {}", node_id);
}
}
EventData::Ime(_ime_event) => {
// FIXME: Implement IME events on top of PlainEditor
// if let Some(node_id) = self.focus_node_id {
// let node = &mut self.nodes[node_id];
// let text_input_data = node
// .raw_dom_data
// .downcast_element_mut()
// .and_then(|el| el.text_input_data_mut());
// if let Some(input_data) = text_input_data {
// let text_event = TextEvent::Ime(ime_event);
// input_data.editor.text_event(&text_event);
// println!("Sent ime event to {}", node_id);
// }
// }
}
EventData::Hover => {}
}
Expand Down
38 changes: 19 additions & 19 deletions packages/blitz-dom/src/layout/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ use core::str;
use std::sync::Arc;

use html5ever::{local_name, namespace_url, ns, QualName};
use parley::{
builder::TreeBuilder,
style::{FontStack, WhiteSpaceCollapse},
InlineBox,
};
use parley::{FontStack, InlineBox, PlainEditorOp, StyleProperty, TreeBuilder, WhiteSpaceCollapse};
use slab::Slab;
use style::{
data::ElementData,
Expand Down Expand Up @@ -329,7 +325,7 @@ fn marker_for_style(list_style_type: ListStyleType, index: usize) -> Option<Mark

// Override the font to our specific bullet font when rendering bullets
fn font_for_bullet_style(list_style_type: ListStyleType) -> Option<FontStack<'static>> {
let bullet_font = Some(FontStack::Source("Bullet, monospace, sans-serif"));
let bullet_font = Some("Bullet, monospace, sans-serif".into());
match list_style_type {
ListStyleType::Disc
| ListStyleType::Circle
Expand Down Expand Up @@ -497,19 +493,23 @@ fn create_text_editor(doc: &mut Document, input_element_id: usize, is_multiline:

let element = &mut node.raw_dom_data.downcast_element_mut().unwrap();
if !matches!(element.node_specific_data, NodeSpecificData::TextInput(_)) {
let initial_value = element
.attr(local_name!("value"))
.unwrap_or(" ")
.to_string();

let mut text_input_data = TextInputData::new(initial_value, 16.0, is_multiline);
text_input_data
.editor
.set_text_size(parley_style.font_size * doc.viewport.scale());
text_input_data
.editor
.set_line_height(parley_style.line_height);
text_input_data.editor.set_brush(parley_style.brush);
let mut text_input_data = TextInputData::new(is_multiline);
let text: Arc<str> = Arc::from(element.attr(local_name!("value")).unwrap_or(" "));
let styles: Arc<[_]> = Arc::from([
StyleProperty::FontSize(parley_style.font_size),
StyleProperty::LineHeight(parley_style.line_height),
StyleProperty::Brush(parley_style.brush),
]);
text_input_data.editor.transact(
&mut doc.font_ctx,
&mut doc.layout_ctx,
[
PlainEditorOp::SetText(text),
PlainEditorOp::SetScale(doc.viewport.scale_f64() as f32),
PlainEditorOp::SetWidth(10000.0),
PlainEditorOp::SetDefaultStyle(styles),
],
);
element.node_specific_data = NodeSpecificData::TextInput(text_input_data);
}
}
Expand Down
9 changes: 0 additions & 9 deletions packages/blitz-dom/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,6 @@ impl LayoutPartialTree for Document {
return taffy::LayoutOutput::HIDDEN;
}

// Perform text layout for text inputs
if inputs.run_mode == taffy::RunMode::PerformLayout {
if let Some(input_data) = element_data.text_input_data_mut() {
input_data
.editor
.rebuild(&mut tree.font_ctx, &mut tree.layout_ctx);
}
}

// todo: need to handle shadow roots by actually descending into them
if *element_data.name.local == *"input" {
match element_data.attr(local_name!("type")) {
Expand Down
Loading

0 comments on commit 4b66061

Please sign in to comment.