aboutsummaryrefslogtreecommitdiffstats
path: root/components/fonts/platform/windows/font_list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/fonts/platform/windows/font_list.rs')
-rw-r--r--components/fonts/platform/windows/font_list.rs379
1 files changed, 379 insertions, 0 deletions
diff --git a/components/fonts/platform/windows/font_list.rs b/components/fonts/platform/windows/font_list.rs
new file mode 100644
index 00000000000..31c1d631160
--- /dev/null
+++ b/components/fonts/platform/windows/font_list.rs
@@ -0,0 +1,379 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use std::hash::Hash;
+use std::sync::Arc;
+
+use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod};
+use dwrote::{Font, FontCollection, FontDescriptor, FontStretch, FontStyle};
+use malloc_size_of_derive::MallocSizeOf;
+use serde::{Deserialize, Serialize};
+use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight};
+use style::values::specified::font::FontStretchKeyword;
+
+use crate::{
+ EmojiPresentationPreference, FallbackFontSelectionOptions, FontTemplate, FontTemplateDescriptor,
+};
+
+pub static SANS_SERIF_FONT_FAMILY: &str = "Arial";
+
+pub fn system_default_family(_: &str) -> Option<String> {
+ Some("Verdana".to_owned())
+}
+
+pub fn for_each_available_family<F>(mut callback: F)
+where
+ F: FnMut(String),
+{
+ let system_fc = FontCollection::system();
+ for family in system_fc.families_iter() {
+ callback(family.name());
+ }
+}
+
+/// An identifier for a local font on a Windows system.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub struct LocalFontIdentifier {
+ /// The FontDescriptor of this font.
+ #[ignore_malloc_size_of = "dwrote does not support MallocSizeOf"]
+ pub font_descriptor: Arc<FontDescriptor>,
+}
+
+impl LocalFontIdentifier {
+ pub fn index(&self) -> u32 {
+ FontCollection::system()
+ .get_font_from_descriptor(&self.font_descriptor)
+ .map_or(0, |font| font.create_font_face().get_index())
+ }
+
+ pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
+ let font = FontCollection::system()
+ .get_font_from_descriptor(&self.font_descriptor)
+ .unwrap();
+ let face = font.create_font_face();
+ let files = face.get_files();
+ assert!(!files.is_empty());
+ files[0].get_font_file_bytes()
+ }
+}
+
+impl Eq for LocalFontIdentifier {}
+
+impl Hash for LocalFontIdentifier {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.font_descriptor.family_name.hash(state);
+ self.font_descriptor.weight.to_u32().hash(state);
+ self.font_descriptor.stretch.to_u32().hash(state);
+ self.font_descriptor.style.to_u32().hash(state);
+ }
+}
+
+pub fn for_each_variation<F>(family_name: &str, mut callback: F)
+where
+ F: FnMut(FontTemplate),
+{
+ let system_fc = FontCollection::system();
+ if let Some(family) = system_fc.get_font_family_by_name(family_name) {
+ let count = family.get_font_count();
+ for i in 0..count {
+ let font = family.get_font(i);
+ let template_descriptor = (&font).into();
+ let local_font_identifier = LocalFontIdentifier {
+ font_descriptor: Arc::new(font.to_descriptor()),
+ };
+ callback(FontTemplate::new_for_local_font(
+ local_font_identifier,
+ template_descriptor,
+ ))
+ }
+ }
+}
+
+// Based on gfxWindowsPlatform::GetCommonFallbackFonts() in Gecko
+pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'static str> {
+ let mut families = Vec::new();
+ if options.presentation_preference == EmojiPresentationPreference::Emoji {
+ families.push("Segoe UI Emoji");
+ }
+
+ families.push("Arial");
+ match unicode_plane(options.character) {
+ // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
+ 0 => {
+ if let Some(block) = options.character.block() {
+ match block {
+ UnicodeBlock::CyrillicSupplement |
+ UnicodeBlock::Armenian |
+ UnicodeBlock::Hebrew => {
+ families.push("Estrangelo Edessa");
+ families.push("Cambria");
+ },
+
+ UnicodeBlock::Arabic | UnicodeBlock::ArabicSupplement => {
+ families.push("Microsoft Uighur");
+ },
+
+ UnicodeBlock::Syriac => {
+ families.push("Estrangelo Edessa");
+ },
+
+ UnicodeBlock::Thaana => {
+ families.push("MV Boli");
+ },
+
+ UnicodeBlock::NKo => {
+ families.push("Ebrima");
+ },
+
+ UnicodeBlock::Devanagari | UnicodeBlock::Bengali => {
+ families.push("Nirmala UI");
+ families.push("Utsaah");
+ families.push("Aparajita");
+ },
+
+ UnicodeBlock::Gurmukhi |
+ UnicodeBlock::Gujarati |
+ UnicodeBlock::Oriya |
+ UnicodeBlock::Tamil |
+ UnicodeBlock::Telugu |
+ UnicodeBlock::Kannada |
+ UnicodeBlock::Malayalam |
+ UnicodeBlock::Sinhala |
+ UnicodeBlock::Lepcha |
+ UnicodeBlock::OlChiki |
+ UnicodeBlock::CyrillicExtendedC |
+ UnicodeBlock::SundaneseSupplement |
+ UnicodeBlock::VedicExtensions => {
+ families.push("Nirmala UI");
+ },
+
+ UnicodeBlock::Thai => {
+ families.push("Leelawadee UI");
+ },
+
+ UnicodeBlock::Lao => {
+ families.push("Lao UI");
+ },
+
+ UnicodeBlock::Myanmar |
+ UnicodeBlock::MyanmarExtendedA |
+ UnicodeBlock::MyanmarExtendedB => {
+ families.push("Myanmar Text");
+ },
+
+ UnicodeBlock::HangulJamo |
+ UnicodeBlock::HangulJamoExtendedA |
+ UnicodeBlock::HangulSyllables |
+ UnicodeBlock::HangulJamoExtendedB |
+ UnicodeBlock::HangulCompatibilityJamo => {
+ families.push("Malgun Gothic");
+ },
+
+ UnicodeBlock::Ethiopic |
+ UnicodeBlock::EthiopicSupplement |
+ UnicodeBlock::EthiopicExtended |
+ UnicodeBlock::EthiopicExtendedA => {
+ families.push("Nyala");
+ },
+
+ UnicodeBlock::Cherokee => {
+ families.push("Plantagenet Cherokee");
+ },
+
+ UnicodeBlock::UnifiedCanadianAboriginalSyllabics |
+ UnicodeBlock::UnifiedCanadianAboriginalSyllabicsExtended => {
+ families.push("Euphemia");
+ families.push("Segoe UI");
+ },
+
+ UnicodeBlock::Khmer | UnicodeBlock::KhmerSymbols => {
+ families.push("Khmer UI");
+ families.push("Leelawadee UI");
+ },
+
+ UnicodeBlock::Mongolian => {
+ families.push("Mongolian Baiti");
+ },
+
+ UnicodeBlock::TaiLe => {
+ families.push("Microsoft Tai Le");
+ },
+
+ UnicodeBlock::NewTaiLue => {
+ families.push("Microsoft New Tai Lue");
+ },
+
+ UnicodeBlock::Buginese |
+ UnicodeBlock::TaiTham |
+ UnicodeBlock::CombiningDiacriticalMarksExtended => {
+ families.push("Leelawadee UI");
+ },
+
+ UnicodeBlock::GeneralPunctuation |
+ UnicodeBlock::SuperscriptsandSubscripts |
+ UnicodeBlock::CurrencySymbols |
+ UnicodeBlock::CombiningDiacriticalMarksforSymbols |
+ UnicodeBlock::LetterlikeSymbols |
+ UnicodeBlock::NumberForms |
+ UnicodeBlock::Arrows |
+ UnicodeBlock::MathematicalOperators |
+ UnicodeBlock::MiscellaneousTechnical |
+ UnicodeBlock::ControlPictures |
+ UnicodeBlock::OpticalCharacterRecognition |
+ UnicodeBlock::EnclosedAlphanumerics |
+ UnicodeBlock::BoxDrawing |
+ UnicodeBlock::BlockElements |
+ UnicodeBlock::GeometricShapes |
+ UnicodeBlock::MiscellaneousSymbols |
+ UnicodeBlock::Dingbats |
+ UnicodeBlock::MiscellaneousMathematicalSymbolsA |
+ UnicodeBlock::SupplementalArrowsA |
+ UnicodeBlock::SupplementalArrowsB |
+ UnicodeBlock::MiscellaneousMathematicalSymbolsB |
+ UnicodeBlock::SupplementalMathematicalOperators |
+ UnicodeBlock::MiscellaneousSymbolsandArrows |
+ UnicodeBlock::Glagolitic |
+ UnicodeBlock::LatinExtendedC |
+ UnicodeBlock::Coptic => {
+ families.push("Segoe UI");
+ families.push("Segoe UI Symbol");
+ families.push("Cambria");
+ families.push("Meiryo");
+ families.push("Lucida Sans Unicode");
+ families.push("Ebrima");
+ },
+
+ UnicodeBlock::GeorgianSupplement |
+ UnicodeBlock::Tifinagh |
+ UnicodeBlock::CyrillicExtendedA |
+ UnicodeBlock::SupplementalPunctuation |
+ UnicodeBlock::CJKRadicalsSupplement |
+ UnicodeBlock::KangxiRadicals |
+ UnicodeBlock::IdeographicDescriptionCharacters => {
+ families.push("Segoe UI");
+ families.push("Segoe UI Symbol");
+ families.push("Meiryo");
+ },
+
+ UnicodeBlock::BraillePatterns => {
+ families.push("Segoe UI Symbol");
+ },
+
+ UnicodeBlock::CJKSymbolsandPunctuation |
+ UnicodeBlock::Hiragana |
+ UnicodeBlock::Katakana |
+ UnicodeBlock::Bopomofo |
+ UnicodeBlock::Kanbun |
+ UnicodeBlock::BopomofoExtended |
+ UnicodeBlock::CJKStrokes |
+ UnicodeBlock::KatakanaPhoneticExtensions |
+ UnicodeBlock::CJKUnifiedIdeographs => {
+ families.push("Microsoft YaHei");
+ families.push("Yu Gothic");
+ },
+
+ UnicodeBlock::EnclosedCJKLettersandMonths => {
+ families.push("Malgun Gothic");
+ },
+
+ UnicodeBlock::YijingHexagramSymbols => {
+ families.push("Segoe UI Symbol");
+ },
+
+ UnicodeBlock::YiSyllables | UnicodeBlock::YiRadicals => {
+ families.push("Microsoft Yi Baiti");
+ families.push("Segoe UI");
+ },
+
+ UnicodeBlock::Vai |
+ UnicodeBlock::CyrillicExtendedB |
+ UnicodeBlock::Bamum |
+ UnicodeBlock::ModifierToneLetters |
+ UnicodeBlock::LatinExtendedD => {
+ families.push("Ebrima");
+ families.push("Segoe UI");
+ families.push("Cambria Math");
+ },
+
+ UnicodeBlock::SylotiNagri |
+ UnicodeBlock::CommonIndicNumberForms |
+ UnicodeBlock::Phagspa |
+ UnicodeBlock::Saurashtra |
+ UnicodeBlock::DevanagariExtended => {
+ families.push("Microsoft PhagsPa");
+ families.push("Nirmala UI");
+ },
+
+ UnicodeBlock::KayahLi | UnicodeBlock::Rejang | UnicodeBlock::Javanese => {
+ families.push("Malgun Gothic");
+ families.push("Javanese Text");
+ families.push("Leelawadee UI");
+ },
+
+ UnicodeBlock::AlphabeticPresentationForms => {
+ families.push("Microsoft Uighur");
+ families.push("Gabriola");
+ families.push("Sylfaen");
+ },
+
+ UnicodeBlock::ArabicPresentationFormsA |
+ UnicodeBlock::ArabicPresentationFormsB => {
+ families.push("Traditional Arabic");
+ families.push("Arabic Typesetting");
+ },
+
+ UnicodeBlock::VariationSelectors |
+ UnicodeBlock::VerticalForms |
+ UnicodeBlock::CombiningHalfMarks |
+ UnicodeBlock::CJKCompatibilityForms |
+ UnicodeBlock::SmallFormVariants |
+ UnicodeBlock::HalfwidthandFullwidthForms |
+ UnicodeBlock::Specials => {
+ families.push("Microsoft JhengHei");
+ },
+
+ _ => {},
+ }
+ }
+ },
+
+ // https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
+ 1 => {
+ families.push("Segoe UI Symbol");
+ families.push("Ebrima");
+ families.push("Nirmala UI");
+ families.push("Cambria Math");
+ },
+
+ _ => {},
+ }
+
+ families.push("Arial Unicode MS");
+ families
+}
+
+impl From<&Font> for FontTemplateDescriptor {
+ fn from(font: &Font) -> Self {
+ let style = match font.style() {
+ FontStyle::Normal => StyleFontStyle::NORMAL,
+ FontStyle::Oblique => StyleFontStyle::OBLIQUE,
+ FontStyle::Italic => StyleFontStyle::ITALIC,
+ };
+ let weight = StyleFontWeight::from_float(font.weight().to_u32() as f32);
+ let stretch = match font.stretch() {
+ FontStretch::Undefined => FontStretchKeyword::Normal,
+ FontStretch::UltraCondensed => FontStretchKeyword::UltraCondensed,
+ FontStretch::ExtraCondensed => FontStretchKeyword::ExtraCondensed,
+ FontStretch::Condensed => FontStretchKeyword::Condensed,
+ FontStretch::SemiCondensed => FontStretchKeyword::SemiCondensed,
+ FontStretch::Normal => FontStretchKeyword::Normal,
+ FontStretch::SemiExpanded => FontStretchKeyword::SemiExpanded,
+ FontStretch::Expanded => FontStretchKeyword::Expanded,
+ FontStretch::ExtraExpanded => FontStretchKeyword::ExtraExpanded,
+ FontStretch::UltraExpanded => FontStretchKeyword::UltraExpanded,
+ }
+ .compute();
+ FontTemplateDescriptor::new(weight, stretch, style)
+ }
+}