From 4b4c76d80f6280db71ae4097c5ec779e7cae7af2 Mon Sep 17 00:00:00 2001 From: "Spencer C. Imbleau" Date: Sat, 20 Jul 2024 14:26:59 -0400 Subject: [PATCH 1/3] refactor: add default_font, change font api --- CHANGELOG.md | 9 +++++ Cargo.toml | 3 +- examples/text/Cargo.toml | 2 +- examples/text/src/main.rs | 62 ++++++++++++++++------------------- src/debug.rs | 12 +++---- src/lib.rs | 6 ++-- src/plugin.rs | 9 ++++- src/render/extract.rs | 13 +++----- src/render/systems.rs | 7 ++-- src/text/FiraMono-subset.ttf | Bin 0 -> 18848 bytes src/text/font.rs | 22 ++++++------- src/text/mod.rs | 2 +- src/text/vello_text.rs | 34 ++++++++++++++----- 13 files changed, 100 insertions(+), 81 deletions(-) create mode 100644 src/text/FiraMono-subset.ttf diff --git a/CHANGELOG.md b/CHANGELOG.md index 1466e25..05c1ee7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,17 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe ## Unreleased +### Added + +- There is now a `default_font` feature that uses the same `FiraMono-subset.ttf` font used in the bevy/default_font feature. + ### Changed +- The font API has changed significantly. Please visit `examples/text` for further usage. This is to prepare for additional text features such as linebreak behavior, bounded text, and text justification. + - `VelloText` has been renamed to `VelloTextSection`. + - `VelloText.content` has been renamed to `VelloText.value`. + - There is now a `VelloTextStyle` struct and it is a required field of `VelloText`. + - `VelloFont` has been removed from `VelloTextBundle` and moved into `VelloTextStyle`. - The field `VelloAssetBundle.vector` was renamed to `VelloAssetBundle.asset`. - Renamed `VelloAssetAlignment` to `VelloAssetAnchor`. Fields were renamed `alignment` were renamed to `asset_anchor`. - Renamed `VelloTextAlignment` to `VelloTextAnchor`. Fields were renamed `alignment` were renamed to `text_anchor`. diff --git a/Cargo.toml b/Cargo.toml index 9bfffe3..cf74bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,8 @@ once_cell = "1.19.0" wasm-bindgen-test = "0.3.42" [features] -default = [] +default = ["default_font"] svg = [] lottie = [] experimental-dotLottie = ["lottie"] +default_font = [] diff --git a/examples/text/Cargo.toml b/examples/text/Cargo.toml index 520851f..07eaba2 100644 --- a/examples/text/Cargo.toml +++ b/examples/text/Cargo.toml @@ -8,5 +8,5 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bevy_vello = { path = "../../" } +bevy_vello = { path = "../../", features = ["default_font"] } bevy = { workspace = true } diff --git a/examples/text/src/main.rs b/examples/text/src/main.rs index f778bad..291b117 100644 --- a/examples/text/src/main.rs +++ b/examples/text/src/main.rs @@ -16,7 +16,6 @@ fn main() { (setup_camera, setup_screenspace_text, setup_worldspace_text), ); embedded_asset!(app, "assets/Rubik-Medium.ttf"); - embedded_asset!(app, "assets/Rubik-Medium.ttf"); app.run(); } @@ -26,39 +25,41 @@ fn setup_camera(mut commands: Commands) { fn setup_worldspace_text(mut commands: Commands, asset_server: ResMut) { commands.spawn(VelloTextBundle { - font: asset_server.load("embedded://text/assets/Rubik-Medium.ttf"), - text: VelloText { - content: "This text is centered\non x and y axes".to_string(), - size: 50.0, - brush: None, + text: VelloTextSection { + value: "Default font\nand multi-line support.".to_string(), + ..default() }, text_anchor: VelloTextAnchor::Center, - transform: Transform::from_xyz(100.0, 100.0, 0.0), + transform: Transform::from_xyz(0.0, 100.0, 0.0), debug_visualizations: DebugVisualizations::Visible, ..default() }); commands.spawn(VelloTextBundle { - font: asset_server.load("embedded://text/assets/Rubik-Medium.ttf"), - text: VelloText { - content: "WXYZ".to_string(), - size: 100.0, - brush: None, + text: VelloTextSection { + value: "Rubik-Medium Font".to_string(), + style: VelloTextStyle { + font: asset_server.load("embedded://text/assets/Rubik-Medium.ttf"), + font_size: 100.0, + ..default() + }, }, - transform: Transform::from_xyz(-100.0, -100.0, 0.0), + text_anchor: VelloTextAnchor::Center, + transform: Transform::from_xyz(0.0, -100.0, 0.0), debug_visualizations: DebugVisualizations::Visible, ..default() }); } -fn setup_screenspace_text(mut commands: Commands, asset_server: ResMut) { +fn setup_screenspace_text(mut commands: Commands) { // Vello text commands.spawn(VelloTextBundle { - font: asset_server.load("embedded://text/assets/Rubik-Medium.ttf"), - text: VelloText { - content: "Text rendered by Vello!".to_string(), - size: 15.0, - brush: Some(peniko::Brush::Solid(peniko::Color::RED)), + text: VelloTextSection { + value: "World-space text rendered by Vello!".to_string(), + style: VelloTextStyle { + brush: peniko::Brush::Solid(peniko::Color::RED), + ..default() + }, }, text_anchor: bevy_vello::text::VelloTextAnchor::TopLeft, transform: Transform::from_xyz(100.0, 85.0, 0.0), @@ -67,22 +68,15 @@ fn setup_screenspace_text(mut commands: Commands, asset_server: ResMut, - &VelloText, + &VelloTextSection, &VelloTextAnchor, &GlobalTransform, &CoordinateSpace, @@ -104,11 +104,11 @@ fn render_text_debug( }; // Show world-space vectors - for (font, text, text_anchor, gtransform, space, _) in query_world + for (text, text_anchor, gtransform, space, _) in query_world .iter() - .filter(|(_, _, _, _, _, d)| **d == DebugVisualizations::Visible) + .filter(|(_, _, _, _, d)| **d == DebugVisualizations::Visible) { - if let Some(font) = fonts.get(font) { + if let Some(font) = fonts.get(text.style.font.id()) { let rect = text.bb_in_world_space(font, gtransform); let mut origin = gtransform.translation().xy(); match space { diff --git a/src/lib.rs b/src/lib.rs index 1f49b66..8213584 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ pub mod prelude { debug::DebugVisualizations, integrations::{VectorFile, VelloAsset, VelloAssetAnchor}, render::VelloCanvasMaterial, - text::{VelloFont, VelloText, VelloTextAnchor}, + text::{VelloFont, VelloTextAnchor, VelloTextSection, VelloTextStyle}, CoordinateSpace, VelloAssetBundle, VelloScene, VelloSceneBundle, VelloTextBundle, }; @@ -91,10 +91,8 @@ pub struct VelloSceneBundle { #[derive(Bundle, Default)] pub struct VelloTextBundle { - /// Font to render - pub font: Handle, /// Text to render - pub text: VelloText, + pub text: VelloTextSection, /// How the text is positioned relative to its [`Transform`]. pub text_anchor: VelloTextAnchor, /// The coordinate space in which this text should be rendered. diff --git a/src/plugin.rs b/src/plugin.rs index 3573ccb..e50e168 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -2,7 +2,7 @@ use crate::{ debug::DebugVisualizationsPlugin, render::VelloRenderPlugin, text::VelloFontLoader, VelloAsset, VelloFont, }; -use bevy::prelude::*; +use bevy::{asset::load_internal_binary_asset, prelude::*}; pub struct VelloPlugin; @@ -19,5 +19,12 @@ impl Plugin for VelloPlugin { app.add_plugins(crate::integrations::lottie::LottieIntegrationPlugin); #[cfg(feature = "experimental-dotLottie")] app.add_plugins(crate::integrations::dot_lottie::DotLottieIntegrationPlugin); + #[cfg(feature = "default_font")] + load_internal_binary_asset!( + app, + Handle::default(), + "text/FiraMono-subset.ttf", + |bytes: &[u8], _path: String| { VelloFont::new(bytes.to_vec()) } + ); } } diff --git a/src/render/extract.rs b/src/render/extract.rs index 81a088a..5607309 100644 --- a/src/render/extract.rs +++ b/src/render/extract.rs @@ -1,6 +1,6 @@ use crate::{ - text::VelloTextAnchor, CoordinateSpace, VelloAsset, VelloAssetAnchor, VelloFont, VelloScene, - VelloText, + text::VelloTextAnchor, CoordinateSpace, VelloAsset, VelloAssetAnchor, VelloScene, + VelloTextSection, }; use bevy::{ prelude::*, @@ -166,8 +166,7 @@ pub fn scene_instances( #[derive(Component, Clone)] pub struct ExtractedRenderText { - pub font: Handle, - pub text: VelloText, + pub text: VelloTextSection, pub text_anchor: VelloTextAnchor, pub transform: GlobalTransform, pub render_mode: CoordinateSpace, @@ -175,8 +174,7 @@ pub struct ExtractedRenderText { impl ExtractComponent for ExtractedRenderText { type QueryData = ( - &'static Handle, - &'static VelloText, + &'static VelloTextSection, &'static VelloTextAnchor, &'static GlobalTransform, &'static CoordinateSpace, @@ -187,13 +185,12 @@ impl ExtractComponent for ExtractedRenderText { type Out = Self; fn extract_component( - (vello_font_handle, text, text_anchor, transform, render_mode): bevy::ecs::query::QueryItem< + (text, text_anchor, transform, render_mode): bevy::ecs::query::QueryItem< '_, Self::QueryData, >, ) -> Option { Some(Self { - font: vello_font_handle.clone(), text: text.clone(), text_anchor: *text_anchor, transform: *transform, diff --git a/src/render/systems.rs b/src/render/systems.rs index 32c5401..fd53266 100644 --- a/src/render/systems.rs +++ b/src/render/systems.rs @@ -205,12 +205,9 @@ pub fn render_scene( scene_buffer.append(scene, Some(*affine)); } RenderItem::Text(ExtractedRenderText { - font, - text, - text_anchor, - .. + text, text_anchor, .. }) => { - if let Some(font) = font_render_assets.get_mut(font) { + if let Some(font) = font_render_assets.get_mut(text.style.font.id()) { font.render(&mut scene_buffer, *affine, text, *text_anchor); } } diff --git a/src/text/FiraMono-subset.ttf b/src/text/FiraMono-subset.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6989c2e4835006627b2daf6660f65b40cfa5edc4 GIT binary patch literal 18848 zcmc(H33yvqo$op4YV&SMmSkIAu6(VQzLgx564ceqdy<}J&&v5@anlkp8Jn= zFlLN1Rued~99uG&KI_3+K8!aWL5D7r5959b_mxMEZ=SW>mxpJC0ry{DJ+T--!12CB}5WSwC@VGvkJgMaFu+hw-1RZ!E7L z|7Z5!7|X-{>`_Lvk^-NtzkK`42lB$dX5|vC%f3|*`xm;tc<6@}Ol*6^f;5R+0~6GX zA3P^Lk@zj(nqh4Fb+MqXlpITbYt){Dte0uk4#6r}fSp16>+I)hk0fTm35<%1vM;=`v`LX(CMAEm#x5s{V9O^>ncali4jv7^Ek7#sXuH(4fc{mvE68R%Z^i z2WzYA|A0NnYFR7GVfE}4w#h!sqUgybAo z4SwnVmhEkP%iG)AKT6GHT&FS&-MA75(_B=0s1wU;v^u>ZBQq;ICpRzOXfhXAthU0U zVtYwxS-I?}P%51+x2LMw>#M1)tKZe&4+I-SP0cN>;kNdUNM~0!G^>C2z~IpE$ez)$ z@rlW)z0><udj2s^un{mV=QM(*(qE=HhDsLqx#g^h8bfxa(cs-5R)6D0_W@G?y zF($_|$7UALBhy$WwHm3_xL{w1Mx*vP_eP^ioQ=&aN24`y$tU;9ag8$ufVACXGjXlb z71t?U06!Y%3pH_#PXS!=(w6pMmrNtc&FMQXE%YwNrD_NIyXA}WMXbG5uXO^g@tK7& zdu$>)qeL+pnVi9posdfHToc#&;`(myB?yyB8XazxE(Ii3x?*v0@KBsDV*j|dx+bpo z$pmCp_u?}eb`VnlW@I5sQxNbcy9NC zd~rdJ=YnW8@qFLV)XbJFNfIboBs6y83)_SXF@qc|pp7ix>Nqei(}xn01&%XmlgzmICbG1S?~O zg5aMzC7#jkUA|bW$a451)@r^oEY~L2h-3rkRp?${E{km!!t(O!r`ci;R>3?RWUD}AvhyMi71 zfEO<6E?DmmYyv>YSZZJZKzl6&3a0%{kYL3a9(Jlg;2WNXtlX8oAQ3G@0~xz(T`3wU zVUVU(?T#Cu;IiDO^wVafJ-->nG%MSEid;)n>w{qqM{Bogc>xr#W2YP3ywV-n=~ic_ zAH8Nyr!U^*O^;l&XqPYE?7avXB4N1*wfwz}!Is*1E%xtL$wdN~rY;GW0_WvQl_^(JG(T(g&SZT65uHv^Nnu4*Hh><30AK~vH$`gnwJa$m- z2g;VDa>Cm~56!jl0CaKpTl5dW=JEn_Jcv1izIX_iA);C@=qmTYt)=NS>?3iE4}q*B zKI8#CXzW3QQ)AS3iK{(hXsA8oG^ZCs6Eue!lQf4KQ#6MfdudK58q+j~8vAGtHD+iI zHKH`98;x0-Lyb9_Lyi43hZ@(>oIW(>X%00G&>U(k&>U*SXigUz2Wbv97HJMOmS_$& zmVNP-9Wo!Hn|M3A538*Xw2r9qgzgA#R($c+o!Lj}MxA|3ZPDyiwMA2p`{Lo9scUqj zPCcQvXzIG!qNyi+@wT0*8+4;iJ*Bp2>ZaPFsi%EUXJ|w^ctgw@ecHXED< zvtG)seui(~8P~iWKBQ+$yVS$}ugxPjpSXHQgoMS9QP88}x_t-!WtxrVI}mzGV1iMsdcGjQca5 z$@rH{Yi1yGE%TwwzsX`*eOVW>zLoXMY&koUy`KGn>@Q^hGRK-zowFxrHRrCJhjL!e zJ(T-+o+fWB??d?$`4{tlV5~Jx8{cbu%@j7BHGRk2Vt%opvfyCBlLcQcc*EkcOk3`< z{Lu2cb;|lM@DRwE8Lt)(gN1rli-@!?d`Yhv_<6&YPW!#^B}t&kz$bKTsr!;%H~2>Q z5~qH@(P4D^jf#V3{Pcwv#KV^lIVjl|><8Pw;%C4W3E8+aQh|MV6t<>$NW&#b%rPOl z#IQ!A$gbV`LQ7-;nKxdXX3lz6=k+3PF+-~9Q@-}aTu2-nI{ zsuAo#{tx`G#7ip7fuXo_CSv(`7c_=qW z==FwZcBU{G!azxg7BO5>Qc_-0URG)^E-JJE5wi(jQwc!FDgo6HD^yAjt7!0`Fe6D#x2{-p2ICA8`K=*NXc=u%N zy5;D=32#N+z_hDgd|u}*@7QJdM)~5@=*jH&+^-3^dV00Lljr;TmNFjr6@0q4;NzEn zYMONgt)xO)mb3lOVpx1hm6KxNQOBktQd3l9I9(ejs(S2*O#Iw+~8a5Q!4Vl!CL>6(uefdHsG=q#A zv_j~(Si}RGIX%~CR4k=ACP`h=umUBj_Egj;HCRNhFjhJ1(-Cp+fGkC`PDH zig$Er=YDfV8re{gk4(8cig!6`>Lc|$Z*279&=LRWP+QBcXiH8_xGd7HG#kaU71hlp zMGanG+gReY+2#Yydtyc@Z=|tys3!4nb!TPMpsnC1Bu}qE2Uk=btVwEM7U^3Q;H&xv zbBx=)xFyvm<@=a1Ul^>a>b-JVJUP^XKHx8*F-{@#KM*d1j^wA%$hWl@R_W`VrH9m|rUb=b>MuMD_YInN`@{`_u zgULmP_Eq!Gz5C|=^dh@&xt|sx$Zz1=@FKaaBvO=}m6>6H)M=pj*(eJ#lpBXjIb?~4 zY=#QX6GjZCJo!6+M#8A(&3GZcF{ObJvK zCM4+R```DzgYS9ILB14y=%MICgvSfpJ*Y>240you8psF^3UGq)eYmI$;;5)HjOSP- zAXG^jkjIsfN^(D+4CdsI?5j6gg07DRTvng5^|fq|%@v@v&+sh%zxZM3YhlEKj%yg4 zVz0yEIKz)79^i*b_Bs0+e8GKyCySXQ5DJ#IL6r`Y28d`wS_Qw>@IV9xg1*&StDoDXb_f$+l%%P5F2>voZtpxY{D5bqD58QKc#EogO)R z_S7kS!tL#0`jog_B_&R0iFoc)Pd)YNPe1k4r=~Bw^QvzqmLv zGs9oLZqJ3wk7FvCbb2?~!lxDkO}Cul&Dn{`3+DsjKuw3dyXxqGcrGv#YCH9|BeQ#N ze*2O?5O%nmg25ylZt#Hv4iD>!bhx-i>*NxQxsV_moUEM01eajrG#c%kj%&4m3xKAW zf;BwMUFlGqKE0tR37Jlxgb#!#g;tF=bWpt}K}D=EzSKAp?u)i>40d1d?k(Bl?HszR zHK#hz+ZC+takS3dD4weut8bsq)lZMKE`)Z~g)1t0TFy;01$TwYu8_3g6AX<;E3Jc-8ZFn5570&7U654TeMecD1h$-a6IQIv&~G7AUMK zo#eNR`RD9`#h%_{t+O4SBYnF&v$FX?f(`LDU@HXvh0vhgk=}fWrV*%Hxki$?R-+lz zfd&8)(4_*2&LKTmnC4zl5yVOlo8ojCu1J@vHl*r^Hb}l2{U&n0Xo02tzL`Ml z;jWuDJ8zmA?eNwH`=&H)vBH)WPj8WE>EvH(Sn3~GZ+rSrPCa#?dUxsVr^XW(rgp#6 z>pHnYvOm53nvg(K9V?9#YgKy(?vcq(#++=}Xe3J$;*Oxh!Y^_|;(7j5;ui&?Z)WWB zyD?8<&A`1JxEJFL%FjFzr?)ImkV=vUsRj#zDoJTnt9@P%g-`5?bdvE@Ehu3L#%SQg z+R;boT1@ap$>5?fD5R#A-htK=L&L|L?rLgiTMV_vS`(iyYpnOVn*9EzpSe2Q=Q`Wl zyZJxvc9hSzHO&PA(a`nb(t+mI$?B@HW>2-H50w%MjNYDoUWkQn0pk60fKO~uuJ)q*GA(JSEEimI2*-~yV!b4`SE@c2=5MTpB zI=vcB04Gyps8PiQArgP+?AQ};FM8X%Gb3|Nv;MZD-DT}1BGl8;))ExY-haz|TPw=A z^Ts0sym6^};Am6g?Ufa$7l#M?yGYKy1%Gg-$W(20c?2hFN&OEGsm3Z9?NnA)I*7m~ zNO{^j0{B1YFKQ!0Gn;-Od32yI|1i#3%6u^wF3q(=TlIruHgkbrD|yED;|h zGC*RkBME_V;$O-3SjlawcE4B{;LCOJVLAyujOTE@Gw2kC#7FqPP~to^)9{VI8Gj}AiVF92 z>fH3u>#By43GqSzL!h_!U9Q*ASO_=8Io)xKK$Pk2l)r+!&mnwzE5VA ze9l#S3){tamfFhxlA)P94M_MX{}a#o2CLm6#bzn=H<*)7}hJtCgKO{y0y9XX|Ph`mD6hdR=deN{eQ_|@rXmbW~387yECpgpbMNnAP z2=YgW8MK|6;i@XessdI1x*GCEuF6W6Gn2d#;LYU}Ub_{#s#$7-%}6N&;iZP*gqTQa zdMM~p_*d^N>I%Dp#X@83362dNSsWfJD=o6=9Q!Am)><0RKXlSp?sQjX6(e%^!LxUL zXwugyS2y0Ya{ew);_thIJ*Q6|f7e8nzhgZSpI#asuB&)0hj?Vb*BES`9&y61NNomq z!(pG{J7A)vgJ4qg5GB5dB@CEr$TVbPt{(EDhfxmck^7pJIs|inS%2nx_kZuk`ohJ< z#~&A$F7J7Kmd_-fB%)BP;=vxdh^fj+d$QmOAP8@A0&r0&AArpqm5yqMgWO`J&dZHS z|7{oVxvjjUe`4~n zjrGT-i1zR-Vi)LQz?&sxzfulDb=9haNYX*IUprK&Dcvd`Laey%^}Li6ZvE4p9Fn)W1c7Pb1|gN}DMi zK+tVO1oz|L{f_TS%<)HZ5 zRHSJh(!$sy{=Gswt^iNJ`m69i`{Cv${_&Q?m&B#S%e?6F9$F7s4D2EC1hj(zXMG-3DKy-k>Y?=u960D0ERYASu>?z)ulUTwMe;G?Yi|`ON zkV^fI0AN>y)GHm@JdgYDH172xk})gd-#=5{$2&Dt3167ahm)CF#)e zaShKs;(puW{C#|^t8KJ4QOm#OKN^t}TY$NN{|&*LmW5o34fSelNJ%g;Pc@E4i_uK< zHCrtt2xeFWkU{xC{^19|r_VV2pcwklTH*yD@$tbkW4r|dA(#uY-vHUCT=OdZza~IT z$1j!X00L2r>LAn#6N12oyKlYqZu*?*85-*89USWU_!pji{6o+G)#LZvamT%P-*Lx1 zAevwc_zHk#nao7e2fczDX7F0cq(CJ_PjheO=N|v? z7oU6L-rMiE_nzBtzZb9|6B7f#Hydwoc_SY1N(&j$f|FX;Csu?1`5MP8D4NnHAJxbbH#9iRbc<>09k zG;q?cg@~GqC^tvkoTl_Od8*=5RIRL}I3S&TAudSylT?ypDFA)Q^*KAvOguUt*|Xk0 zUKDORwc57Y^S1qM{rj7GOM5$(R_>e+?C;;*5-hKF7%S#SLVN2bd)sQgc2~K%Y@P}N zfX@NCG=VO9W{(u^7#^@cDaENU&;bGj9eRZ?Z+=tQvR@EW^Yh8)+kl@P&zsWEJ zwPDY83=K?!YHU@jz)@_M{AT{Q*MIkp@80ymq-nYQS>Pt{Je}ZVlU>Nv3o;0xJ8Bpb z*#)xOSd>B;lgVgG*@Z0FDKZB5$A5cIPyfZ4^~S+7y^$k)JHfH|=lL%axdQnHha@r4 zgY~n>5@zZ(6vy&GBzI)K$Qr1&5W`s}lZhe)vn}M8%nG(JOHbT+_l?i~-EHrG_{MKO zD=xkMdg6K`nd|vqBtFIa6Vn7^E7mE&IvEsap~8(cg|ap>uH<2o=O$`x6=cB587#wSN>+zZ zwn-+oq9i-vIVQNW3C7L@#H+p%9!`*W$25z1Ivp?%+>G6H&?c#=AYz@#MURvEN_p z?3XP1#PB@hdw~-nf*K?RFeG+bs&A1``-{XYPdvem*GI)~FoWi_i9BJK1`w^o-@r1d z2{{uRBoHeQ2J$ytaZ@}i?5A$N@zm#*MBewm&s*?p!}fr1ZGRXJ?k#JTHUv5i{Ix{( z9F;2ZOkAw-k4R2Dld3hEQSFTf{<=bZZT2QG32b6b&?SpNmV@-5FVbxTv#j6~)ksjm zMqkz9$yo!3eot+s>*J#b|GUa_YkKc+zLf?Uf`5DLt>PR?4 zconf-FJgYd8cvtYK|Ux=v9ZYI z#8D5($Bjx_Y*dJilzjRTJtOtpUNjUB*Dfyk=Og2R$J*Aq>Z&@#OP5PJU7q*eHhxQg z3(raX{ejqX!~aHtEm#+5X9Ml5knHA2Bcf7?tU0U@1&N5}Nr2NJgV?E~M4Qc4YAZ1p zIGqj>*XpDHe55P5nrdD=c1mejM%Mw({Gbd0B_8jI?#DIhj=Vm%x zE0GK-l08y{TP&eti&srk$D$FqEi7rF$la_MD27P#yOjGOiR4NBYF@&BvAe?G9%$Ig z`Ox~=v;O^I@oM=VtEYN?GO@xRoIKDlT#c1LzaZY!_X~Q*yodcsB&#l4a04G~=6bMv z7nH1tF@1)fWvnxePOH;s*Wop|FmRl3W@PB+m|hQ25JESHx-Yn{)v9)*o$zRUt4Fb| zP9t>JEOF(*XvEag($dq??e+!~voq*2W#J^6L&SF~$8^Ba%GFA8G9mUOY9ZGjK>VoI zIMPK;Yhy^0u3_SY)L%N_udjz})!4JLJNGxu?7HWC^ssly))E@)3)Ri_50sVEd7G9Z z)630?Z^ME$1P=4xWa_P5b%C+k41+Dl$t&K%*48lIWetdauzq)9;| z^c8t;-N4{_rAO(st>b@hxIN>;iCg)4T~&=EahLc}c9NH?U}%P9hJUxPgGotq5Fn5* z&bx^@YI#0+_@7S6?U8Z}Lkc+}^glQw8Yw`vm0k_V&&$op#`2k!hBqBKA)QbALzJRq zho?#&xj(V^XAg0MWUhkW@RXH%E_X~!@YM-`BvAkM@E25AZEW~s`FTS0Cn2T;Em`0M z#Hq@GdeB&aYLQw{q)NUDJ-VZjT$n;As|pomgjXMgnelo63c^9vPru9Kamave-$%Dh z=WqKak4R=uIRREyb$S0gACjjFj~?OE6MzkFRYah>l!wZZQek3py z?gxMDT#-WludlD)`?Gt0^x_3F^8Up4xP!`~kb?%;D2_AdT%1tgtQcpbSJ?tf8XFh@ z!aV76@Fobh7l?4kLZo}~CWu*4OEgZhmsAZx+)F`7=a|P=5*i6lzi|*mC zPhfATxu}JGENA;8*(El?wWdtOKxBzbP;V2orLq;Aq}LGVpjE77xy%(!>G{d z;DAzt(Fh%gmNRI8Niiwr3>@u%>M4oUUv>54FaaJ3U;H;si#gWn$~pR4nlcmxD*Flw zn<_9LTcFT%NJGC$X_zUn>OD2kD_-|V9jVb6&Fqv$Q#A4@# z7Q33^qb#5DKjb&nVn_6o=1Q}o2IA%H2S zsM)}-V3E&}xD)UQmdr`YAZ|7~aYN}6evZoVsu@iCXSFbY<$(6hh54%wX!#>I-Ewl{ z=37s;wT1C792RBoJAeLx_guK;p?&kQgV)U;j9rI)qp;I<&>yP(i{7Xb4JRy!aa2pI2>a24lm7LXzHGFntHtW>Y-tGuMOor!H^0B-^&Iij z9#8c&f}Ga<2bZZZM6~lD&LA9$2nYB;sIH0ws5q!ah39G<7~w#iO|w#s(@LQE0cbV z^ds#I@KU3y+!ls|VuTn*ld9Y{y%HqOr;WTS3jB4qc`P(ucr@|tJ$pV_P#*0Pr8!?* z<k3rt{H*t6X3a$jBPoS^APuxLx~aFLUTznlCiBCq$TU$3ahAAyp+{e z!l$Qd6i6%7SSMYf*eNdZJ#D7O#(n!XVyCC-`$v~-O`++%cP-vN-Rc6f9Qig&NX+LxWuUWyi z0jLV9rG?ZQNQmlzsTkYn|BBO9*wyIj@w_N^3kGpzen4`)LSn9El z2k#N7^$@BxBr5_c093>@R@UW-hE2sCr0?w>hlOe@J?Jl>LIleZw4K@ zt647=5^SB^NO%Yet~wXY&t}fpNcL0lptOqLLsH@TJ@M&gpy$Mlk&Nv zxq*l)&voex(PZIx#+1R)PzA`_`4$;b~iXJ$4wnKGWKk|#U&puZZ@-@(kUR))EYwr_4lMHo6vcx2L=tBO z=p~U;GY8=8Qi87&TK&Vr{VG~2%Hc>y8&Ga*l6ncJkLK1^&w6Wf|2ttcDOWv{VQdOz zWHmMAXFTI^Oado`{UcuF`%`#4#%q_IgJmTa3mR(8 zoH3c-1&ESAW9+e1o3ngwNwo#j^Tt$LV#Rzj)z)AR{y&BKDBgeN|CDO$Sf0pEwe>6@ z((4;owPZ~7<19zIm}+M+tMvU;JDXWGm8o_PYtf|FM}(uTNcBT!wBxC^k?FK6kQJ_> z^5CQRB-@{qF_V7c6tYD+A@+f!`~aDQj2tp#3RNVRo1?f=(QThES&l2qHkro?Ab z?F=?7ssD2t`(`npw3X`5M*BCZb`IOrw5Hm*ETBoRna@nxwp727Woze3!A46-AonY(i9NSQ59YL?mK7vmJ?DH;s*Q8oOygMzkDRu-a$apXE z1lC%?{|;YOSLwt3X||SHcLjHAm=#ld=&5DQTV{vU{uS&=J5S;b@=kh-yl3U`%I3-q z%S-Z7Y%?Y=o>)J(v2ysxru-4P0so1+246v+JauGQ9yxKt%Ia!N?mKaM4RcpctjV#p zC3$Ljb@|YVwUxz~JXza`75f0%hPnv>x`q#dOsKB_Ow?ZcRyJZ-ZS90Svb?l%8a)#j zK8!)a2S#CH`S9u07#e;+NVI4~?YSG6^dPWp-Ps_$e9g7X`)eEO8(Zlw0JPFhv{6lZ zqyGYI(|~OQ@1>{ddIcsny}WUX$e`|c1@X6l>yH9v1v?S%WXJ*$aS6L0SE+IgeJ8-h zx0Zu$jBh}m=$j-g2{CbGhu|xxWW4yh5nEb59@{u3pEz_4XS+{qte@CWS&OH-)onMh zToR}^FHfS_&klllGG2<8@n;+e*fk)qjwhDcF_mxx{2G2`h#L+%yJH(0Cjdoyt7WDO(1O?e>+pvk=(ko?nhlUO zNej9^L6UrAb923=uI|j4GqsCJ#A+8$Q2+mnMTSAe#S}%8h9jxuB#tB=Nn$O;)0`O$l)&bHfY)6}~;!0Z{25CnDFhaK!2~RC< ztgLUIsy(%`T6<#SaNTGh#(rO0uZS|cR_W6Uj&Kp40zcayhvlGX>CHa})n1fZD2PD( zt4D=1183J+h*EQqMCPF`Zp0a+88rwC@&p@R6fHs)Zf7N^Ia6gtW)4;XPhW|XSQp;K z^sp+#VqVzj8sJx#vfX~X-4%r83gNGM&|eB^#mo6^>fa8DKoz`KW)LgRBC6bvzcVtA7b6#-7lawd-|@&(F+?=ZB2;7q zE-2ojFBiW!F$Sa*leFQx6TkS+jaY+YjRW|O;TMq=o+X+QrP7~Fc7c5Y2aX3d|8aGZnEM-8?i-Jfxl<7$~-4FmexR9f|U5CVy}MVOMOZU?peW^ zYET{3bj)i6?UJokV3TaUgMBpBdY*kpZE4s~*c;r$>s7o2cyGme#ptT z$Ln^+>oCqCHAH#(NmKHzdugBaTmf0?!Rj1RM->lx>e}%JNW`_{fBaqq4M~IPkAREj z;sgk?pQHiZqvV7SL6z*M8T6B;O>&g(GNA*t*T_xbj@%$Qp@-DJJwuJ;^X&Wo^Q-Fd K|J8p_=>Gr=x%t5W literal 0 HcmV?d00001 diff --git a/src/text/font.rs b/src/text/font.rs index 5f2ebe0..c83f688 100644 --- a/src/text/font.rs +++ b/src/text/font.rs @@ -1,4 +1,4 @@ -use super::{vello_text::VelloText, VelloTextAnchor}; +use super::{vello_text::VelloTextSection, VelloTextAnchor}; use bevy::{prelude::*, reflect::TypePath, render::render_asset::RenderAsset}; use std::sync::Arc; use vello::{ @@ -7,13 +7,13 @@ use vello::{ Glyph, }, kurbo::Affine, - peniko::{self, Blob, Brush, Color, Font}, + peniko::{self, Blob, Font}, Scene, }; const VARIATIONS: &[(&str, f32)] = &[]; -#[derive(Asset, TypePath, Clone)] +#[derive(Asset, TypePath, Debug, Clone)] pub struct VelloFont { pub font: peniko::Font, } @@ -38,9 +38,9 @@ impl VelloFont { } } - pub fn sizeof(&self, text: &VelloText) -> Vec2 { + pub fn sizeof(&self, text: &VelloTextSection) -> Vec2 { let font = FontRef::new(self.font.data.data()).expect("Vello font creation error"); - let font_size = vello::skrifa::instance::Size::new(text.size); + let font_size = vello::skrifa::instance::Size::new(text.style.font_size); let charmap = font.charmap(); let axes = font.axes(); // TODO: What do Variations here do? Any font nerds know? I'm definitely not doing this @@ -54,7 +54,7 @@ impl VelloFont { let mut pen_x = 0.0; let mut pen_y: f32 = 0.0; let mut width: f32 = 0.0; - for ch in text.content.chars() { + for ch in text.value.chars() { if ch == '\n' { pen_y += line_height; pen_x = 0.0; @@ -74,12 +74,12 @@ impl VelloFont { &self, scene: &mut Scene, mut transform: Affine, - text: &VelloText, + text: &VelloTextSection, text_anchor: VelloTextAnchor, ) { let font = FontRef::new(self.font.data.data()).expect("Vello font creation error"); - let font_size = vello::skrifa::instance::Size::new(text.size); + let font_size = vello::skrifa::instance::Size::new(text.style.font_size); let charmap = font.charmap(); let axes = font.axes(); let var_loc = axes.location(VARIATIONS); @@ -91,7 +91,7 @@ impl VelloFont { let mut pen_y = 0f32; let mut width = 0f32; let glyphs: Vec = text - .content + .value .chars() .filter_map(|ch| { if ch == '\n' { @@ -149,10 +149,10 @@ impl VelloFont { scene .draw_glyphs(&self.font) - .font_size(text.size) + .font_size(text.style.font_size) .transform(transform) .normalized_coords(var_loc.coords()) - .brush(&text.brush.clone().unwrap_or(Brush::Solid(Color::WHITE))) + .brush(&text.style.brush.clone()) .draw(vello::peniko::Fill::EvenOdd, glyphs.into_iter()); } } diff --git a/src/text/mod.rs b/src/text/mod.rs index 9dc1437..898af15 100644 --- a/src/text/mod.rs +++ b/src/text/mod.rs @@ -6,4 +6,4 @@ mod vello_text; pub use font::VelloFont; pub(crate) use font_loader::VelloFontLoader; -pub use vello_text::{VelloText, VelloTextAnchor}; +pub use vello_text::{VelloTextAnchor, VelloTextSection, VelloTextStyle}; diff --git a/src/text/vello_text.rs b/src/text/vello_text.rs index 3b0b126..192b009 100644 --- a/src/text/vello_text.rs +++ b/src/text/vello_text.rs @@ -1,6 +1,29 @@ use crate::VelloFont; use bevy::prelude::*; -use vello::peniko::Brush; +use vello::peniko::{self, Brush}; + +#[derive(Component, Default, Clone)] +pub struct VelloTextSection { + pub value: String, + pub style: VelloTextStyle, +} + +#[derive(Component, Clone)] +pub struct VelloTextStyle { + pub font: Handle, + pub font_size: f32, + pub brush: Brush, +} + +impl Default for VelloTextStyle { + fn default() -> Self { + Self { + font: Default::default(), + font_size: 24.0, + brush: Brush::Solid(peniko::Color::WHITE), + } + } +} /// Describes how the text is positioned relative to its [`Transform`]. It defaults to [`VelloTextAnchor::BottomLeft`]. #[derive(Component, Default, Clone, Copy, PartialEq, Eq)] @@ -28,14 +51,7 @@ pub enum VelloTextAnchor { TopRight, } -#[derive(Component, Default, Clone)] -pub struct VelloText { - pub content: String, - pub size: f32, - pub brush: Option, -} - -impl VelloText { +impl VelloTextSection { /// Returns the bounding box in world space pub fn bb_in_world_space(&self, font: &VelloFont, gtransform: &GlobalTransform) -> Rect { let size = font.sizeof(self); From f9c783d7465d3f92b7f540064e2154844d4103c6 Mon Sep 17 00:00:00 2001 From: "Spencer C. Imbleau" Date: Sat, 20 Jul 2024 15:10:49 -0400 Subject: [PATCH 2/3] chore: update cargo_run_wasm --- examples/run_wasm/Cargo.toml | 2 +- examples/run_wasm/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/run_wasm/Cargo.toml b/examples/run_wasm/Cargo.toml index 76068dd..6a8b1ee 100644 --- a/examples/run_wasm/Cargo.toml +++ b/examples/run_wasm/Cargo.toml @@ -6,4 +6,4 @@ repository.workspace = true publish = false [dependencies] -cargo-run-wasm = "0.3.2" +cargo-run-wasm = "0.4.0" diff --git a/examples/run_wasm/src/main.rs b/examples/run_wasm/src/main.rs index d3a5732..a303415 100644 --- a/examples/run_wasm/src/main.rs +++ b/examples/run_wasm/src/main.rs @@ -10,5 +10,5 @@ /// ``` fn main() { - cargo_run_wasm::run_wasm_with_css("body { margin: 0px; }"); + cargo_run_wasm::run_wasm_cli_with_css("body { margin: 0px; }"); } From c6f4d86f765ff33ca6fd8770fe8301c92f50d577 Mon Sep 17 00:00:00 2001 From: "Spencer C. Imbleau" Date: Sat, 20 Jul 2024 15:11:03 -0400 Subject: [PATCH 3/3] docs: fix typos in cargo features --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9fb86ce..11afc81 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,9 @@ cargo run -p demo |Cargo feature|Description|Default?| |---|---|----| -|`svg`|Render `.svg` files with [`vello_svg`](https://github.com/linebender/vello_svg)|Yes| -|`lottie`|Render `.json` Lottie files with [`velato`](https://github.com/linebender/velato)|Yes| +|`default_font`|Include a default font, containing only ASCII characters, at the cost of a 20kB binary size increase|Yes| +|`svg`|Render `.svg` files with [`vello_svg`](https://github.com/linebender/vello_svg)|No| +|`lottie`|Render `.json` Lottie files with [`velato`](https://github.com/linebender/velato)|No| |`experimental-dotLottie`|Render `.lottie` Lottie files. **Work in Progress**|No| ## Examples