svg_img: Render SVGs with text tags (#390)

<img width="620" alt="image"
src="https://github.com/user-attachments/assets/61f2a1f8-6926-484d-bcb8-076a9d85e89c">
This commit is contained in:
Floyd Wang 2024-11-07 11:39:06 +08:00 committed by GitHub
parent 270493f3ce
commit 6d0b332071
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 605 additions and 513 deletions

1011
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,23 +1,23 @@
[workspace] [workspace]
members = ["crates/app", "crates/ui", "crates/story"] members = ["crates/app", "crates/story", "crates/ui"]
default-members = ["crates/app"] default-members = ["crates/app"]
resolver = "2" resolver = "2"
[workspace.dependencies] [workspace.dependencies]
anyhow = "1"
gpui = { git = "https://github.com/huacnlee/zed.git", branch = "export-platform-window" } gpui = { git = "https://github.com/huacnlee/zed.git", branch = "export-platform-window" }
log = "0.4"
serde = "1.0.203"
serde_json = "1"
smallvec = "1"
story = { path = "crates/story" }
ui = { path = "crates/ui" }
windows = { version = "0.58.0", features = [ windows = { version = "0.58.0", features = [
"Wdk", "Wdk",
"Wdk_System", "Wdk_System",
"Wdk_System_SystemServices", "Wdk_System_SystemServices",
] } ] }
ui = { path = "crates/ui" }
story = { path = "crates/story" }
anyhow = "1"
log = "0.4"
serde = "1.0.203"
serde_json = "1"
smallvec = "1"
[workspace.lints.clippy] [workspace.lints.clippy]
almost_complete_range = "allow" almost_complete_range = "allow"
@ -35,13 +35,13 @@ todo = "deny"
type_complexity = "allow" type_complexity = "allow"
[profile.dev] [profile.dev]
split-debuginfo = "unpacked"
debug = "limited"
codegen-units = 16 codegen-units = 16
debug = "limited"
split-debuginfo = "unpacked"
[profile.dev.package] [profile.dev.package]
taffy = { opt-level = 3 }
cranelift-codegen = { opt-level = 3 } cranelift-codegen = { opt-level = 3 }
resvg = { opt-level = 3 } resvg = { opt-level = 3 }
rustybuzz = { opt-level = 3 } rustybuzz = { opt-level = 3 }
taffy = { opt-level = 3 }
ttf-parser = { opt-level = 3 } ttf-parser = { opt-level = 3 }

View file

@ -1,10 +1,10 @@
{ {
"border_radius": 2, "border_radius": 8,
"width": 400, "font_family": "sans-serif",
"height": 300, "height": 400,
"inner_radius": 30, "inner_radius": 30,
"legend_margin": { "legend_margin": {
"top": 0 "top": 50
}, },
"legend_show": true, "legend_show": true,
"radius": 110, "radius": 110,
@ -12,39 +12,56 @@
"series_list": [ "series_list": [
{ {
"name": "rose 1", "name": "rose 1",
"data": [40] "data": [
40
]
}, },
{ {
"name": "rose 2", "name": "rose 2",
"data": [38] "data": [
38
]
}, },
{ {
"name": "rose 3", "name": "rose 3",
"data": [32] "data": [
32
]
}, },
{ {
"name": "rose 4", "name": "rose 4",
"data": [30] "data": [
30
]
}, },
{ {
"name": "rose 5", "name": "rose 5",
"data": [28] "data": [
28
]
}, },
{ {
"name": "rose 6", "name": "rose 6",
"data": [26] "data": [
26
]
}, },
{ {
"name": "rose 7", "name": "rose 7",
"data": [22] "data": [
22
]
}, },
{ {
"name": "rose 8", "name": "rose 8",
"data": [18] "data": [
18
]
} }
], ],
"sub_title_text": "Sub Title", "sub_title_text": "Sub Title",
"theme": "light", "theme": "light",
"title_text": "Nightingale Chart", "title_text": "Nightingale Chart",
"type": "pie" "type": "pie",
} "width": 600
}

View file

@ -28,7 +28,7 @@ impl ImageStory {
Self { Self {
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
google_logo: svg_img().source(GOOGLE_LOGO.as_bytes(), px(300.), px(300.)), google_logo: svg_img().source(GOOGLE_LOGO.as_bytes(), px(300.), px(300.)),
pie_chart: svg_img().source(chart.svg().unwrap().as_bytes(), px(400.), px(400.)), pie_chart: svg_img().source(chart.svg().unwrap().as_bytes(), px(600.), px(400.)),
inbox_img: svg_img().source("icons/inbox.svg", px(300.), px(300.)), inbox_img: svg_img().source("icons/inbox.svg", px(300.), px(300.)),
} }
} }

View file

@ -1,32 +1,38 @@
[package] [package]
name = "ui"
description = "UI components for the GPUI" description = "UI components for the GPUI"
version = "0.1.0"
edition = "2021" edition = "2021"
name = "ui"
publish = false publish = false
version = "0.1.0"
[lib] [lib]
doctest = false doctest = false
[dependencies] [dependencies]
gpui.workspace = true
anyhow = "1" anyhow = "1"
gpui.workspace = true
itertools = "0.13.0" itertools = "0.13.0"
serde = "1.0.203" serde = "1.0.203"
serde_json = "1" serde_json = "1"
smallvec = "1.13.2"
unicode-segmentation = "1.11.0"
image = "0.25.1" image = "0.25.1"
resvg = { version = "0.41.0", default-features = false }
usvg = { version = "0.41.0", default-features = false }
paste = "1"
once_cell = "1.19.0" once_cell = "1.19.0"
wry = "0.46.3" paste = "1"
smol = "1"
regex = "1" regex = "1"
resvg = { version = "0.44.0", default-features = false, features = [
"system-fonts",
"text",
] }
rust-i18n = "3" rust-i18n = "3"
smallvec = "1.13.2"
smol = "1"
unicode-segmentation = "1.11.0"
usvg = { version = "0.44.0", default-features = false, features = [
"system-fonts",
"text",
] }
uuid = "1.10" uuid = "1.10"
wry = "0.46.3"
# Calendar # Calendar
chrono = "0.4.38" chrono = "0.4.38"

View file

@ -103,19 +103,17 @@ impl Asset for Image {
} }
}; };
let options = usvg::Options { let mut options = usvg::Options::default();
..Default::default() options.fontdb_mut().load_system_fonts();
};
let tree = usvg::Tree::from_data(&bytes, &options)?; let tree = usvg::Tree::from_data(&bytes, &options)?;
let mut pixmap = let mut pixmap =
resvg::tiny_skia::Pixmap::new(size.width.0 as u32, size.height.0 as u32) resvg::tiny_skia::Pixmap::new(size.width.0 as u32, size.height.0 as u32)
.ok_or(usvg::Error::InvalidSize)?; .ok_or(usvg::Error::InvalidSize)?;
let transform = tree.view_box().to_transform( let transform = resvg::tiny_skia::Transform::from_scale(scale, scale);
resvg::tiny_skia::Size::from_wh(size.width.0, size.height.0)
.ok_or(usvg::Error::InvalidSize)?,
);
resvg::render(&tree, transform, &mut pixmap.as_mut()); resvg::render(&tree, transform, &mut pixmap.as_mut());
let mut buffer = ImageBuffer::from_raw(pixmap.width(), pixmap.height(), pixmap.take()) let mut buffer = ImageBuffer::from_raw(pixmap.width(), pixmap.height(), pixmap.take())