我正在开发一个使用ICED图形用户界面的Rust桌面应用程序.我用来加载用于ICED小工具的自定义字体:

// fonts module:
use iced::Font;

pub const NOTO_SANS_REGULAR: Font = Font::External {
    name: "noto-sans-regular",
    bytes: include_bytes!("../../../resources/fonts/noto-sans-regular.ttf"),
};

pub const NOTO_SANS_BOLD: Font = Font::External {
    name: "noto-sans-bold",
    bytes: include_bytes!("../../../resources/fonts/noto-sans-bold.ttf"),
};

// usage:
fonts::NOTO_SANS_REGULAR

但现在我正在try 在运行时加载这些字体,这样它们就不会被Bundle 到可执行文件中并增加其大小.以下是我的 idea :

// fonts module:
use once_cell::sync::OnceCell;
use iced::Font;
use tokio::runtime::Runtime;

pub static NOTO_SANS_REGULAR: OnceCell<Font> = OnceCell::new();
pub static NOTO_SANS_BOLD: OnceCell<Font> = OnceCell::new();

async fn download_font(name: &'static str, url: &str) -> Result<Font, reqwest::Error> {
    let response = reqwest::get(url).await?;
    let bytes = response.bytes().await?;
    let font_data = Box::new(bytes);
    let font = Font::External {
        name: name,
        bytes: &*Box::leak(font_data)
    };
    Ok(font)
}

pub fn load_fonts() {
    let runtime = Runtime::new().unwrap();

    runtime.spawn(async move {
        let noto_sans_regular = download_font("noto-sans-regular", "https://raw.githubusercontent.com/googlefonts/noto-fonts/main/unhinted/ttf/NotoSans/NotoSans-Regular.ttf");
        let noto_sans_bold = download_font("noto-sans-bold", "https://raw.githubusercontent.com/googlefonts/noto-fonts/main/unhinted/ttf/NotoSans/NotoSans-Bold.ttf");

        // Await all font downloads and store them in the OnceCell instances
        if let Ok(noto_sans_regular) = noto_sans_regular.await {
            NOTO_SANS_REGULAR.set(noto_sans_regular).ok();
        }
        if let Ok(noto_sans_bold) = noto_sans_bold.await {
            NOTO_SANS_BOLD.set(noto_sans_bold).ok();
        }
    });
}

// usage:
fonts::NOTO_SANS_REGULAR.get().unwrap_or(&Font::Default).clone()

问题是,我在那里的GET请求上收到了DNS错误,因此我不确定整个过程是否会正常工作.

无法下载字体:reqwest::Error{种类:请求,url:url{ 方案:"HTTPS",Cannot_be_a_base:FALSE,用户名:"",密码: None,主机:Some(域("raw.githebusercontent.com")),端口:None, 路径: "/googlefonts/noto-fonts/main/unhinted/ttf/NotoSans/NotoSans-Regular.ttf", Query:None,Fragment:None},来源:Hyper::Error(连接, ConnectError("dns Error",自定义{Kind:Interrupt,Error: JoinError::已取消(ID(8))})

推荐答案

如果您所要做的就是创建一个默认的Runtime,然后等待它运行Future直到完成,这正是tokio::main宏所做的,所以您可以使用它:

#[tokio::main]
pub async fn load_fonts() {
    let noto_sans_regular = download_font("noto-sans-regular", "https://raw.githubusercontent.com/googlefonts/noto-fonts/main/unhinted/ttf/NotoSans/NotoSans-Regular.ttf");
    let noto_sans_bold = download_font("noto-sans-bold", "https://raw.githubusercontent.com/googlefonts/noto-fonts/main/unhinted/ttf/NotoSans/NotoSans-Bold.ttf");

    // Await all font downloads and store them in the OnceCell instances
    if let Ok(noto_sans_regular) = noto_sans_regular.await {
        NOTO_SANS_REGULAR.set(noto_sans_regular).ok();
    }
    if let Ok(noto_sans_bold) = noto_sans_bold.await {
        NOTO_SANS_BOLD.set(noto_sans_bold).ok();
    }
}

Rust相关问答推荐

为什么我需要在这个代码示例中使用&

go 掉包装 struct 中的泛型

在函数内定义impl和在函数外定义impl的区别

如何删除Mac Tauri上的停靠图标?

如何将单个 struct 实例与插入器一起传递到Rust中的映射

Rust将String上的迭代器转换为&;[&;str]

装箱特性如何影响传递给它的参数的生命周期 ?(举一个非常具体的例子)

为什么比较Option<;字符串>;具有常数Option<&;str>;需要显式类型转换吗?

如何从宏调用闭包?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

从 Rust 中的 if/else 中的引用创建 MappedRwLockWriteGuard

是否可以在 Rust 中的特定字符上实现特征?

n 个范围的笛卡尔积

在 Rust 中如何将值推送到枚举 struct 内的 vec?

为什么具有 Vec 变体的枚举没有内存开销?

为什么指定生命周期让我返回一个引用?

使用 `.` 将 T 转换为 &mut T?

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

为什么 Bevy 的 Trait 边界不满足 Rapier 物理插件?