Add Brush tool warning; move font list loading to document creation time
This commit is contained in:
parent
457619794b
commit
de366f9514
|
|
@ -3,8 +3,6 @@ use crate::messages::dialog::DialogMessageData;
|
||||||
use crate::messages::portfolio::document::node_graph::document_node_definitions;
|
use crate::messages::portfolio::document::node_graph::document_node_definitions;
|
||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
|
|
||||||
use graphene_core::text::Font;
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Dispatcher {
|
pub struct Dispatcher {
|
||||||
buffered_queue: Option<Vec<VecDeque<Message>>>,
|
buffered_queue: Option<Vec<VecDeque<Message>>>,
|
||||||
|
|
@ -135,10 +133,6 @@ impl Dispatcher {
|
||||||
// Display the menu bar at the top of the window
|
// Display the menu bar at the top of the window
|
||||||
queue.add(MenuBarMessage::SendLayout);
|
queue.add(MenuBarMessage::SendLayout);
|
||||||
|
|
||||||
// Load the default font
|
|
||||||
let font = Font::new(graphene_core::consts::DEFAULT_FONT_FAMILY.into(), graphene_core::consts::DEFAULT_FONT_STYLE.into());
|
|
||||||
queue.add(FrontendMessage::TriggerFontLoad { font, is_default: true });
|
|
||||||
|
|
||||||
// Send the information for tooltips and categories for each node/input.
|
// Send the information for tooltips and categories for each node/input.
|
||||||
queue.add(FrontendMessage::SendUIMetadata {
|
queue.add(FrontendMessage::SendUIMetadata {
|
||||||
input_type_descriptions: Vec::new(),
|
input_type_descriptions: Vec::new(),
|
||||||
|
|
|
||||||
|
|
@ -61,34 +61,34 @@ impl PreferencesDialogMessageHandler {
|
||||||
.widget_holder(),
|
.widget_holder(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let imaginate_server_hostname = vec![
|
// TODO: Reenable when Imaginate is restored
|
||||||
TextLabel::new("Imaginate").min_width(60).italic(true).widget_holder(),
|
// let imaginate_server_hostname = vec![
|
||||||
TextLabel::new("Server Hostname").table_align(true).widget_holder(),
|
// TextLabel::new("Imaginate").min_width(60).italic(true).widget_holder(),
|
||||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
// TextLabel::new("Server Hostname").table_align(true).widget_holder(),
|
||||||
TextInput::new(&preferences.imaginate_server_hostname)
|
// Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||||
.min_width(200)
|
// TextInput::new(&preferences.imaginate_server_hostname)
|
||||||
.on_update(|text_input: &TextInput| PreferencesMessage::ImaginateServerHostname { hostname: text_input.value.clone() }.into())
|
// .min_width(200)
|
||||||
.widget_holder(),
|
// .on_update(|text_input: &TextInput| PreferencesMessage::ImaginateServerHostname { hostname: text_input.value.clone() }.into())
|
||||||
];
|
// .widget_holder(),
|
||||||
|
// ];
|
||||||
let imaginate_refresh_frequency = vec![
|
// let imaginate_refresh_frequency = vec![
|
||||||
TextLabel::new("").min_width(60).widget_holder(),
|
// TextLabel::new("").min_width(60).widget_holder(),
|
||||||
TextLabel::new("Refresh Frequency").table_align(true).widget_holder(),
|
// TextLabel::new("Refresh Frequency").table_align(true).widget_holder(),
|
||||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
// Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||||
NumberInput::new(Some(preferences.imaginate_refresh_frequency))
|
// NumberInput::new(Some(preferences.imaginate_refresh_frequency))
|
||||||
.unit(" seconds")
|
// .unit(" seconds")
|
||||||
.min(0.)
|
// .min(0.)
|
||||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
// .max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||||
.min_width(200)
|
// .min_width(200)
|
||||||
.on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into())
|
// .on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into())
|
||||||
.widget_holder(),
|
// .widget_holder(),
|
||||||
];
|
// ];
|
||||||
|
|
||||||
Layout::WidgetLayout(WidgetLayout::new(vec![
|
Layout::WidgetLayout(WidgetLayout::new(vec![
|
||||||
LayoutGroup::Row { widgets: zoom_with_scroll },
|
LayoutGroup::Row { widgets: zoom_with_scroll },
|
||||||
LayoutGroup::Row { widgets: use_vello },
|
LayoutGroup::Row { widgets: use_vello },
|
||||||
LayoutGroup::Row { widgets: imaginate_server_hostname },
|
// LayoutGroup::Row { widgets: imaginate_server_hostname },
|
||||||
LayoutGroup::Row { widgets: imaginate_refresh_frequency },
|
// LayoutGroup::Row { widgets: imaginate_refresh_frequency },
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,6 @@ pub enum FrontendMessage {
|
||||||
},
|
},
|
||||||
TriggerFontLoad {
|
TriggerFontLoad {
|
||||||
font: Font,
|
font: Font,
|
||||||
#[serde(rename = "isDefault")]
|
|
||||||
is_default: bool,
|
|
||||||
},
|
},
|
||||||
TriggerImport,
|
TriggerImport,
|
||||||
TriggerIndexedDbRemoveDocument {
|
TriggerIndexedDbRemoveDocument {
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,6 @@ impl LayoutMessageHandler {
|
||||||
|
|
||||||
responses.add(PortfolioMessage::LoadFont {
|
responses.add(PortfolioMessage::LoadFont {
|
||||||
font: Font::new(font_family.into(), font_style.into()),
|
font: Font::new(font_family.into(), font_style.into()),
|
||||||
is_default: false,
|
|
||||||
});
|
});
|
||||||
(font_input.on_update.callback)(font_input)
|
(font_input.on_update.callback)(font_input)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1676,7 +1676,7 @@ impl DocumentMessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for font in fonts {
|
for font in fonts {
|
||||||
responses.add_front(FrontendMessage::TriggerFontLoad { font, is_default: false });
|
responses.add_front(FrontendMessage::TriggerFontLoad { font });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ pub enum PortfolioMessage {
|
||||||
font_style: String,
|
font_style: String,
|
||||||
preview_url: String,
|
preview_url: String,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
is_default: bool,
|
|
||||||
},
|
},
|
||||||
ImaginateCheckServerStatus,
|
ImaginateCheckServerStatus,
|
||||||
ImaginatePollServerStatus,
|
ImaginatePollServerStatus,
|
||||||
|
|
@ -63,7 +62,6 @@ pub enum PortfolioMessage {
|
||||||
},
|
},
|
||||||
LoadFont {
|
LoadFont {
|
||||||
font: Font,
|
font: Font,
|
||||||
is_default: bool,
|
|
||||||
},
|
},
|
||||||
NewDocumentWithName {
|
NewDocumentWithName {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
||||||
|
|
@ -278,11 +278,10 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||||
font_style,
|
font_style,
|
||||||
preview_url,
|
preview_url,
|
||||||
data,
|
data,
|
||||||
is_default,
|
|
||||||
} => {
|
} => {
|
||||||
let font = Font::new(font_family, font_style);
|
let font = Font::new(font_family, font_style);
|
||||||
|
|
||||||
self.persistent_data.font_cache.insert(font, preview_url, data, is_default);
|
self.persistent_data.font_cache.insert(font, preview_url, data);
|
||||||
self.executor.update_font_cache(self.persistent_data.font_cache.clone());
|
self.executor.update_font_cache(self.persistent_data.font_cache.clone());
|
||||||
for document_id in self.document_ids.iter() {
|
for document_id in self.document_ids.iter() {
|
||||||
let _ = self.executor.submit_node_graph_evaluation(
|
let _ = self.executor.submit_node_graph_evaluation(
|
||||||
|
|
@ -334,9 +333,9 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
||||||
document.load_layer_resources(responses);
|
document.load_layer_resources(responses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PortfolioMessage::LoadFont { font, is_default } => {
|
PortfolioMessage::LoadFont { font } => {
|
||||||
if !self.persistent_data.font_cache.loaded_font(&font) {
|
if !self.persistent_data.font_cache.loaded_font(&font) {
|
||||||
responses.add_front(FrontendMessage::TriggerFontLoad { font, is_default });
|
responses.add_front(FrontendMessage::TriggerFontLoad { font });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PortfolioMessage::NewDocumentWithName { name } => {
|
PortfolioMessage::NewDocumentWithName { name } => {
|
||||||
|
|
@ -939,6 +938,10 @@ impl PortfolioMessageHandler {
|
||||||
if self.active_document().is_some() {
|
if self.active_document().is_some() {
|
||||||
responses.add(BroadcastEvent::ToolAbort);
|
responses.add(BroadcastEvent::ToolAbort);
|
||||||
responses.add(ToolMessage::DeactivateTools);
|
responses.add(ToolMessage::DeactivateTools);
|
||||||
|
} else {
|
||||||
|
// Load the default font upon creating the first document
|
||||||
|
let font = Font::new(graphene_core::consts::DEFAULT_FONT_FAMILY.into(), graphene_core::consts::DEFAULT_FONT_STYLE.into());
|
||||||
|
responses.add(FrontendMessage::TriggerFontLoad { font });
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove this and find a way to fix the issue where creating a new document when the node graph is open causes the transform in the new document to be incorrect
|
// TODO: Remove this and find a way to fix the issue where creating a new document when the node graph is open causes the transform in the new document to be incorrect
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,10 @@ impl MessageHandler<PreferencesMessage, ()> for PreferencesMessageHandler {
|
||||||
if let Ok(deserialized_preferences) = serde_json::from_str::<PreferencesMessageHandler>(&preferences) {
|
if let Ok(deserialized_preferences) = serde_json::from_str::<PreferencesMessageHandler>(&preferences) {
|
||||||
*self = deserialized_preferences;
|
*self = deserialized_preferences;
|
||||||
|
|
||||||
responses.add(PortfolioMessage::ImaginateServerHostname);
|
// TODO: Reenable when Imaginate is restored
|
||||||
responses.add(PortfolioMessage::ImaginateCheckServerStatus);
|
// responses.add(PortfolioMessage::ImaginateServerHostname);
|
||||||
|
// responses.add(PortfolioMessage::ImaginateCheckServerStatus);
|
||||||
|
|
||||||
responses.add(PortfolioMessage::EditorPreferences);
|
responses.add(PortfolioMessage::EditorPreferences);
|
||||||
responses.add(PortfolioMessage::UpdateVelloPreference);
|
responses.add(PortfolioMessage::UpdateVelloPreference);
|
||||||
responses.add(PreferencesMessage::ModifyLayout {
|
responses.add(PreferencesMessage::ModifyLayout {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ pub struct BrushTool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BrushOptions {
|
pub struct BrushOptions {
|
||||||
|
legacy_warning_was_shown: bool,
|
||||||
diameter: f64,
|
diameter: f64,
|
||||||
hardness: f64,
|
hardness: f64,
|
||||||
flow: f64,
|
flow: f64,
|
||||||
|
|
@ -41,6 +42,7 @@ pub struct BrushOptions {
|
||||||
impl Default for BrushOptions {
|
impl Default for BrushOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
legacy_warning_was_shown: false,
|
||||||
diameter: DEFAULT_BRUSH_SIZE,
|
diameter: DEFAULT_BRUSH_SIZE,
|
||||||
hardness: 0.,
|
hardness: 0.,
|
||||||
flow: 100.,
|
flow: 100.,
|
||||||
|
|
@ -78,6 +80,7 @@ pub enum BrushToolMessageOptionsUpdate {
|
||||||
Hardness(f64),
|
Hardness(f64),
|
||||||
Spacing(f64),
|
Spacing(f64),
|
||||||
WorkingColors(Option<Color>, Option<Color>),
|
WorkingColors(Option<Color>, Option<Color>),
|
||||||
|
NoDisplayLegacyWarning,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
|
|
@ -217,6 +220,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for BrushTo
|
||||||
self.options.color.primary_working_color = primary;
|
self.options.color.primary_working_color = primary;
|
||||||
self.options.color.secondary_working_color = secondary;
|
self.options.color.secondary_working_color = secondary;
|
||||||
}
|
}
|
||||||
|
BrushToolMessageOptionsUpdate::NoDisplayLegacyWarning => self.options.legacy_warning_was_shown = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_layout(responses, LayoutTarget::ToolOptions);
|
self.send_layout(responses, LayoutTarget::ToolOptions);
|
||||||
|
|
@ -308,6 +312,20 @@ impl Fsm for BrushToolFsmState {
|
||||||
document, global_tool_data, input, ..
|
document, global_tool_data, input, ..
|
||||||
} = tool_action_data;
|
} = tool_action_data;
|
||||||
|
|
||||||
|
if !tool_options.legacy_warning_was_shown {
|
||||||
|
responses.add(DialogMessage::DisplayDialogError {
|
||||||
|
title: "Unsupported tool".into(),
|
||||||
|
description: "
|
||||||
|
The current Brush tool is a legacy feature with\n\
|
||||||
|
significant quality and performance limitations.\n\
|
||||||
|
It will be replaced soon by a new implementation.\n\
|
||||||
|
"
|
||||||
|
.trim()
|
||||||
|
.into(),
|
||||||
|
});
|
||||||
|
responses.add(BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::NoDisplayLegacyWarning));
|
||||||
|
}
|
||||||
|
|
||||||
let ToolMessage::Brush(event) = event else {
|
let ToolMessage::Brush(event) = event else {
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,33 @@ export function createFontsState(editor: Editor) {
|
||||||
// TODO: Do some code cleanup to remove the need for this empty store
|
// TODO: Do some code cleanup to remove the need for this empty store
|
||||||
const { subscribe } = writable({});
|
const { subscribe } = writable({});
|
||||||
|
|
||||||
function createURL(font: string): URL {
|
function createURL(font: string, weight: string): URL {
|
||||||
const url = new URL("https://fonts.googleapis.com/css2");
|
const url = new URL("https://fonts.googleapis.com/css2");
|
||||||
url.searchParams.set("display", "swap");
|
url.searchParams.set("display", "swap");
|
||||||
url.searchParams.set("family", font);
|
url.searchParams.set("family", `${font}:wght@${weight}`);
|
||||||
url.searchParams.set("text", font);
|
url.searchParams.set("text", font);
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fontNames(): Promise<{ name: string; url: URL | undefined }[]> {
|
async function fontNames(): Promise<{ name: string; url: URL | undefined }[]> {
|
||||||
return (await fontList).map((font) => ({ name: font.family, url: createURL(font.family) }));
|
const pickPreviewWeight = (variants: string[]) => {
|
||||||
|
const weights = variants.map((variant) => Number(variant.match(/.* \((\d+)\)/)?.[1] || "NaN"));
|
||||||
|
const weightGoal = 400;
|
||||||
|
const sorted = weights.map((weight) => [weight, Math.abs(weightGoal - weight - 1)]);
|
||||||
|
sorted.sort(([_, a], [__, b]) => a - b);
|
||||||
|
return sorted[0][0].toString();
|
||||||
|
};
|
||||||
|
return (await loadFontList()).map((font) => ({ name: font.family, url: createURL(font.family, pickPreviewWeight(font.variants)) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFontStyles(fontFamily: string): Promise<{ name: string; url: URL | undefined }[]> {
|
async function getFontStyles(fontFamily: string): Promise<{ name: string; url: URL | undefined }[]> {
|
||||||
const font = (await fontList).find((value) => value.family === fontFamily);
|
const font = (await loadFontList()).find((value) => value.family === fontFamily);
|
||||||
return font?.variants.map((variant) => ({ name: variant, url: undefined })) || [];
|
return font?.variants.map((variant) => ({ name: variant, url: undefined })) || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFontFileUrl(fontFamily: string, fontStyle: string): Promise<string | undefined> {
|
async function getFontFileUrl(fontFamily: string, fontStyle: string): Promise<string | undefined> {
|
||||||
const font = (await fontList).find((value) => value.family === fontFamily);
|
const font = (await loadFontList()).find((value) => value.family === fontFamily);
|
||||||
const fontFileUrl = font?.files.get(fontStyle);
|
const fontFileUrl = font?.files.get(fontStyle);
|
||||||
return fontFileUrl?.replace("http://", "https://");
|
return fontFileUrl?.replace("http://", "https://");
|
||||||
}
|
}
|
||||||
|
|
@ -47,33 +55,41 @@ export function createFontsState(editor: Editor) {
|
||||||
return `${weightName}${isItalic ? " Italic" : ""} (${weight})`;
|
return `${weightName}${isItalic ? " Italic" : ""} (${weight})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fontList: Promise<{ family: string; variants: string[]; files: Map<string, string> }[]> | undefined;
|
||||||
|
|
||||||
|
async function loadFontList(): Promise<{ family: string; variants: string[]; files: Map<string, string> }[]> {
|
||||||
|
if (fontList) return fontList;
|
||||||
|
|
||||||
|
fontList = new Promise<{ family: string; variants: string[]; files: Map<string, string> }[]>((resolve) => {
|
||||||
|
fetch(fontListAPI)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((fontListResponse) => {
|
||||||
|
const fontListData = fontListResponse.items as { family: string; variants: string[]; files: Record<string, string> }[];
|
||||||
|
const result = fontListData.map((font) => {
|
||||||
|
const { family } = font;
|
||||||
|
const variants = font.variants.map(formatFontStyleName);
|
||||||
|
const files = new Map(font.variants.map((x) => [formatFontStyleName(x), font.files[x]]));
|
||||||
|
return { family, variants, files };
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return fontList;
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe to process backend events
|
// Subscribe to process backend events
|
||||||
editor.subscriptions.subscribeJsMessage(TriggerFontLoad, async (triggerFontLoad) => {
|
editor.subscriptions.subscribeJsMessage(TriggerFontLoad, async (triggerFontLoad) => {
|
||||||
const url = await getFontFileUrl(triggerFontLoad.font.fontFamily, triggerFontLoad.font.fontStyle);
|
const url = await getFontFileUrl(triggerFontLoad.font.fontFamily, triggerFontLoad.font.fontStyle);
|
||||||
if (url) {
|
if (url) {
|
||||||
const response = await (await fetch(url)).arrayBuffer();
|
const response = await (await fetch(url)).arrayBuffer();
|
||||||
editor.handle.onFontLoad(triggerFontLoad.font.fontFamily, triggerFontLoad.font.fontStyle, url, new Uint8Array(response), triggerFontLoad.isDefault);
|
editor.handle.onFontLoad(triggerFontLoad.font.fontFamily, triggerFontLoad.font.fontStyle, url, new Uint8Array(response));
|
||||||
} else {
|
} else {
|
||||||
editor.handle.errorDialog("Failed to load font", `The font ${triggerFontLoad.font.fontFamily} with style ${triggerFontLoad.font.fontStyle} does not exist`);
|
editor.handle.errorDialog("Failed to load font", `The font ${triggerFontLoad.font.fontFamily} with style ${triggerFontLoad.font.fontStyle} does not exist`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const fontList = new Promise<{ family: string; variants: string[]; files: Map<string, string> }[]>((resolve) => {
|
|
||||||
fetch(fontListAPI)
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((fontListResponse) => {
|
|
||||||
const fontListData = fontListResponse.items as { family: string; variants: string[]; files: Record<string, string> }[];
|
|
||||||
const result = fontListData.map((font) => {
|
|
||||||
const { family } = font;
|
|
||||||
const variants = font.variants.map(formatFontStyleName);
|
|
||||||
const files = new Map(font.variants.map((x) => [formatFontStyleName(x), font.files[x]]));
|
|
||||||
return { family, variants, files };
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
fontNames,
|
fontNames,
|
||||||
|
|
|
||||||
|
|
@ -892,8 +892,6 @@ export class Font {
|
||||||
export class TriggerFontLoad extends JsMessage {
|
export class TriggerFontLoad extends JsMessage {
|
||||||
@Type(() => Font)
|
@Type(() => Font)
|
||||||
font!: Font;
|
font!: Font;
|
||||||
|
|
||||||
isDefault!: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TriggerVisitLink extends JsMessage {
|
export class TriggerVisitLink extends JsMessage {
|
||||||
|
|
|
||||||
|
|
@ -442,13 +442,12 @@ impl EditorHandle {
|
||||||
|
|
||||||
/// A font has been downloaded
|
/// A font has been downloaded
|
||||||
#[wasm_bindgen(js_name = onFontLoad)]
|
#[wasm_bindgen(js_name = onFontLoad)]
|
||||||
pub fn on_font_load(&self, font_family: String, font_style: String, preview_url: String, data: Vec<u8>, is_default: bool) -> Result<(), JsValue> {
|
pub fn on_font_load(&self, font_family: String, font_style: String, preview_url: String, data: Vec<u8>) -> Result<(), JsValue> {
|
||||||
let message = PortfolioMessage::FontLoaded {
|
let message = PortfolioMessage::FontLoaded {
|
||||||
font_family,
|
font_family,
|
||||||
font_style,
|
font_style,
|
||||||
preview_url,
|
preview_url,
|
||||||
data,
|
data,
|
||||||
is_default,
|
|
||||||
};
|
};
|
||||||
self.dispatch(message);
|
self.dispatch(message);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,16 @@ pub struct FontCache {
|
||||||
font_file_data: HashMap<Font, Vec<u8>>,
|
font_file_data: HashMap<Font, Vec<u8>>,
|
||||||
/// Web font preview URLs used for showing fonts when live editing
|
/// Web font preview URLs used for showing fonts when live editing
|
||||||
preview_urls: HashMap<Font, String>,
|
preview_urls: HashMap<Font, String>,
|
||||||
/// The default font (used as a fallback)
|
|
||||||
default_font: Option<Font>,
|
|
||||||
}
|
}
|
||||||
impl FontCache {
|
impl FontCache {
|
||||||
/// Returns the font family name if the font is cached, otherwise returns the default font family name if that is cached
|
/// Returns the font family name if the font is cached, otherwise returns the fallback font family name if that is cached
|
||||||
pub fn resolve_font<'a>(&'a self, font: &'a Font) -> Option<&'a Font> {
|
pub fn resolve_font<'a>(&'a self, font: &'a Font) -> Option<&'a Font> {
|
||||||
if self.loaded_font(font) {
|
if self.font_file_data.contains_key(font) {
|
||||||
Some(font)
|
Some(font)
|
||||||
} else {
|
} else {
|
||||||
self.default_font.as_ref().filter(|font| self.loaded_font(font))
|
self.font_file_data
|
||||||
|
.keys()
|
||||||
|
.find(|font| font.font_family == crate::consts::DEFAULT_FONT_FAMILY && font.font_style == crate::consts::DEFAULT_FONT_STYLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,19 +51,11 @@ impl FontCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a new font into the cache
|
/// Insert a new font into the cache
|
||||||
pub fn insert(&mut self, font: Font, perview_url: String, data: Vec<u8>, is_default: bool) {
|
pub fn insert(&mut self, font: Font, perview_url: String, data: Vec<u8>) {
|
||||||
if is_default {
|
|
||||||
self.default_font = Some(font.clone());
|
|
||||||
}
|
|
||||||
self.font_file_data.insert(font.clone(), data);
|
self.font_file_data.insert(font.clone(), data);
|
||||||
self.preview_urls.insert(font, perview_url);
|
self.preview_urls.insert(font, perview_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the font cache has a default font
|
|
||||||
pub fn has_default(&self) -> bool {
|
|
||||||
self.default_font.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the preview URL for showing in text field when live editing
|
/// Gets the preview URL for showing in text field when live editing
|
||||||
pub fn get_preview_url(&self, font: &Font) -> Option<&String> {
|
pub fn get_preview_url(&self, font: &Font) -> Option<&String> {
|
||||||
self.preview_urls.get(font)
|
self.preview_urls.get(font)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue