mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Ged rid of libfontconfig in Android. Query available fonts from Android system font configuration files.
This commit is contained in:
parent
fa158a78b6
commit
19fbec9d54
7 changed files with 498 additions and 11 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1055,6 +1055,7 @@ dependencies = [
|
||||||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"webrender_traits 0.39.0 (git+https://github.com/servo/webrender)",
|
"webrender_traits 0.39.0 (git+https://github.com/servo/webrender)",
|
||||||
"xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"xml5ever 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -50,8 +50,13 @@ core-text = "4.0"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||||
freetype = "0.2"
|
freetype = "0.2"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
servo-fontconfig = "0.2.1"
|
servo-fontconfig = "0.2.1"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
|
xml5ever = {version = "0.7", features = ["unstable"]}
|
||||||
|
|
||||||
[target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies]
|
[target.'cfg(any(target_feature = "sse2", target_feature = "neon"))'.dependencies]
|
||||||
simd = "0.2.0"
|
simd = "0.2.0"
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ extern crate bitflags;
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(target_os = "linux")]
|
||||||
extern crate fontconfig;
|
extern crate fontconfig;
|
||||||
extern crate fontsan;
|
extern crate fontsan;
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
@ -73,6 +73,8 @@ extern crate unicode_bidi;
|
||||||
extern crate unicode_script;
|
extern crate unicode_script;
|
||||||
extern crate webrender_traits;
|
extern crate webrender_traits;
|
||||||
extern crate xi_unicode;
|
extern crate xi_unicode;
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
extern crate xml5ever;
|
||||||
|
|
||||||
#[deny(unsafe_code)]
|
#[deny(unsafe_code)]
|
||||||
pub mod display_list;
|
pub mod display_list;
|
||||||
|
|
481
components/gfx/platform/freetype/android/font_list.rs
Normal file
481
components/gfx/platform/freetype/android/font_list.rs
Normal file
|
@ -0,0 +1,481 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, Read};
|
||||||
|
use std::path::Path;
|
||||||
|
use xml5ever::Attribute;
|
||||||
|
use xml5ever::driver::parse_document;
|
||||||
|
use xml5ever::rcdom::*;
|
||||||
|
use xml5ever::rcdom::{Node, RcDom};
|
||||||
|
use xml5ever::tendril::TendrilSink;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref FONT_LIST: FontList = FontList::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android doesn't provide an API to query system fonts until Android O:
|
||||||
|
// https://developer.android.com/reference/android/text/FontConfig.html
|
||||||
|
// System font configuration files must be parsed until Android O version is set as the minimum target.
|
||||||
|
// Android uses XML files to handle font mapping configurations.
|
||||||
|
// On Android API 21+ font mappings are loaded from /etc/fonts.xml.
|
||||||
|
// Each entry consists of a family with various font names, or a font alias.
|
||||||
|
// Example:
|
||||||
|
// <familyset>
|
||||||
|
// <!-- first font is default -->
|
||||||
|
// <family name="sans-serif">
|
||||||
|
// <font weight="100" style="normal">Roboto-Thin.ttf</font>
|
||||||
|
// <font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
|
||||||
|
// <font weight="300" style="normal">Roboto-Light.ttf</font>
|
||||||
|
// <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
|
||||||
|
// <font weight="400" style="normal">Roboto-Regular.ttf</font>
|
||||||
|
// <font weight="400" style="italic">Roboto-Italic.ttf</font>
|
||||||
|
// <font weight="500" style="normal">Roboto-Medium.ttf</font>
|
||||||
|
// <font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
|
||||||
|
// <font weight="900" style="normal">Roboto-Black.ttf</font>
|
||||||
|
// <font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
|
||||||
|
// <font weight="700" style="normal">Roboto-Bold.ttf</font>
|
||||||
|
// <font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
|
||||||
|
// </family>//
|
||||||
|
|
||||||
|
// <!-- Note that aliases must come after the fonts they reference. -->
|
||||||
|
// <alias name="sans-serif-thin" to="sans-serif" weight="100" />
|
||||||
|
// <alias name="sans-serif-light" to="sans-serif" weight="300" />
|
||||||
|
// <alias name="sans-serif-medium" to="sans-serif" weight="500" />
|
||||||
|
// <alias name="sans-serif-black" to="sans-serif" weight="900" />
|
||||||
|
// <alias name="arial" to="sans-serif" />
|
||||||
|
// <alias name="helvetica" to="sans-serif" />
|
||||||
|
// <alias name="tahoma" to="sans-serif" />
|
||||||
|
// <alias name="verdana" to="sans-serif" />
|
||||||
|
|
||||||
|
// <family name="sans-serif-condensed">
|
||||||
|
// <font weight="300" style="normal">RobotoCondensed-Light.ttf</font>
|
||||||
|
// <font weight="300" style="italic">RobotoCondensed-LightItalic.ttf</font>
|
||||||
|
// <font weight="400" style="normal">RobotoCondensed-Regular.ttf</font>
|
||||||
|
// <font weight="400" style="italic">RobotoCondensed-Italic.ttf</font>
|
||||||
|
// <font weight="700" style="normal">RobotoCondensed-Bold.ttf</font>
|
||||||
|
// <font weight="700" style="italic">RobotoCondensed-BoldItalic.ttf</font>
|
||||||
|
// </family>
|
||||||
|
// <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
|
||||||
|
// </familyset>
|
||||||
|
// On Android API 17-20 font mappings are loaded from /system/etc/system_fonts.xml
|
||||||
|
// Each entry consists of a family with a nameset and a fileset.
|
||||||
|
// Example:
|
||||||
|
// <familyset>
|
||||||
|
// <family>
|
||||||
|
// <nameset>
|
||||||
|
// <name>sans-serif</name>
|
||||||
|
// <name>arial</name>
|
||||||
|
// <name>helvetica</name>
|
||||||
|
// <name>tahoma</name>
|
||||||
|
// <name>verdana</name>
|
||||||
|
// </nameset>
|
||||||
|
// <fileset>
|
||||||
|
// <file>Roboto-Regular.ttf</file>
|
||||||
|
// <file>Roboto-Bold.ttf</file>
|
||||||
|
// <file>Roboto-Italic.ttf</file>
|
||||||
|
// <file>Roboto-BoldItalic.ttf</file>
|
||||||
|
// </fileset>
|
||||||
|
// </family>//
|
||||||
|
|
||||||
|
// <family>
|
||||||
|
// <nameset>
|
||||||
|
// <name>sans-serif-light</name>
|
||||||
|
// </nameset>
|
||||||
|
// <fileset>
|
||||||
|
// <file>Roboto-Light.ttf</file>
|
||||||
|
// <file>Roboto-LightItalic.ttf</file>
|
||||||
|
// </fileset>
|
||||||
|
// </family>//
|
||||||
|
|
||||||
|
// <family>
|
||||||
|
// <nameset>
|
||||||
|
// <name>sans-serif-thin</name>
|
||||||
|
// </nameset>
|
||||||
|
// <fileset>
|
||||||
|
// <file>Roboto-Thin.ttf</file>
|
||||||
|
// <file>Roboto-ThinItalic.ttf</file>
|
||||||
|
// </fileset>
|
||||||
|
// </family>
|
||||||
|
// </familyset>
|
||||||
|
|
||||||
|
struct Font {
|
||||||
|
filename: String,
|
||||||
|
weight: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FontFamily {
|
||||||
|
name: String,
|
||||||
|
fonts: Vec<Font>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FontAlias {
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
weight: Option<i32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FontList {
|
||||||
|
families: Vec<FontFamily>,
|
||||||
|
aliases: Vec<FontAlias>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontList {
|
||||||
|
fn new() -> FontList {
|
||||||
|
// Possible paths containing the font mapping xml file.
|
||||||
|
let paths = [
|
||||||
|
"/etc/fonts.xml",
|
||||||
|
"/system/etc/system_fonts.xml"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Try to load and parse paths until one of them success.
|
||||||
|
let mut result = None;
|
||||||
|
paths.iter().all(|path| {
|
||||||
|
result = Self::from_path(path);
|
||||||
|
!result.is_some()
|
||||||
|
});
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Some(result) => result,
|
||||||
|
// If no xml mapping file is found fallback to some default
|
||||||
|
// fonts expected to be on all Android devices.
|
||||||
|
None => FontList {
|
||||||
|
families: Self::fallback_font_families(),
|
||||||
|
aliases: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new FontList from a path to the font mapping xml file.
|
||||||
|
fn from_path(path: &str) -> Option<FontList> {
|
||||||
|
let xml = match Self::load_file(path) {
|
||||||
|
Ok(xml) => xml,
|
||||||
|
_=> { return None; },
|
||||||
|
};
|
||||||
|
|
||||||
|
let dom: RcDom = parse_document(RcDom::default(), Default::default())
|
||||||
|
.one(xml);
|
||||||
|
let doc = &dom.document;
|
||||||
|
|
||||||
|
// find familyset root node
|
||||||
|
let children = doc.children.borrow();
|
||||||
|
let familyset = children.iter().find(|child| {
|
||||||
|
match child.data {
|
||||||
|
NodeData::Element { ref name, .. } => &*name.local == "familyset",
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let familyset = match familyset {
|
||||||
|
Some(node) => node,
|
||||||
|
_ => { return None; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse familyset node
|
||||||
|
let mut families = Vec::new();
|
||||||
|
let mut aliases = Vec::new();
|
||||||
|
|
||||||
|
for node in familyset.children.borrow().iter() {
|
||||||
|
match node.data {
|
||||||
|
NodeData::Element { ref name, ref attrs, .. } => {
|
||||||
|
if &*name.local == "family" {
|
||||||
|
Self::parse_family(&node, attrs, &mut families);
|
||||||
|
} else if &*name.local == "alias" {
|
||||||
|
// aliases come after the fonts they reference. -->
|
||||||
|
if !families.is_empty() {
|
||||||
|
Self::parse_alias(attrs, &mut aliases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_=> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(FontList {
|
||||||
|
families: families,
|
||||||
|
aliases: aliases
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonts expected to exist in Android devices.
|
||||||
|
// Only used in the unlikely case where no font xml mapping files are found.
|
||||||
|
fn fallback_font_families() -> Vec<FontFamily> {
|
||||||
|
let alternatives = [
|
||||||
|
("san-serif", "Roboto-Regular.ttf"),
|
||||||
|
("Droid Sans", "DroidSans.ttf"),
|
||||||
|
];
|
||||||
|
|
||||||
|
alternatives.iter().filter(|item| {
|
||||||
|
Path::new(&Self::font_absolute_path(item.1)).exists()
|
||||||
|
}).map(|item| {
|
||||||
|
FontFamily {
|
||||||
|
name: item.0.into(),
|
||||||
|
fonts: vec![Font {
|
||||||
|
filename: item.1.into(),
|
||||||
|
weight: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}). collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// All Android fonts are located in /system/fonts
|
||||||
|
fn font_absolute_path(filename: &str) -> String {
|
||||||
|
format!("/system/fonts/{}", filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_family(&self, name: &str) -> Option<&FontFamily>{
|
||||||
|
self.families.iter().find(|f| f.name == name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_alias(&self, name: &str) -> Option<&FontAlias>{
|
||||||
|
self.aliases.iter().find(|f| f.from == name)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn load_file(path: &str) -> Result<String, io::Error> {
|
||||||
|
let mut file = try!(File::open(path));
|
||||||
|
let mut content = String::new();
|
||||||
|
try!(file.read_to_string(&mut content));
|
||||||
|
|
||||||
|
Ok(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse family and font file names
|
||||||
|
// Example:
|
||||||
|
// <family name="sans-serif">
|
||||||
|
// <font weight="100" style="normal">Roboto-Thin.ttf</font>
|
||||||
|
// <font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
|
||||||
|
// <font weight="300" style="normal">Roboto-Light.ttf</font>
|
||||||
|
// <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
|
||||||
|
// <font weight="400" style="normal">Roboto-Regular.ttf</font>
|
||||||
|
// </family>
|
||||||
|
fn parse_family(familyset: &Node, attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<FontFamily>) {
|
||||||
|
// Fallback to old Android API v17 xml format if required
|
||||||
|
let using_api_17 = familyset.children.borrow().iter().any(|node| {
|
||||||
|
match node.data {
|
||||||
|
NodeData::Element { ref name, .. } => &*name.local == "nameset",
|
||||||
|
_=> false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if using_api_17 {
|
||||||
|
Self::parse_family_v17(familyset, out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse family name
|
||||||
|
let name = match Self::find_attrib("name", attrs) {
|
||||||
|
Some(name) => name,
|
||||||
|
_ => { return; },
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut fonts = Vec::new();
|
||||||
|
// Parse font variants
|
||||||
|
for node in familyset.children.borrow().iter() {
|
||||||
|
match node.data {
|
||||||
|
NodeData::Element { ref name, ref attrs, .. } => {
|
||||||
|
if &*name.local == "font" {
|
||||||
|
FontList::parse_font(&node, attrs, &mut fonts);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_=> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(FontFamily {
|
||||||
|
name: name,
|
||||||
|
fonts: fonts
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse family and font file names for Androi API < 21
|
||||||
|
// Example:
|
||||||
|
// <family>
|
||||||
|
// <nameset>
|
||||||
|
// <name>sans-serif</name>
|
||||||
|
// <name>arial</name>
|
||||||
|
// <name>helvetica</name>
|
||||||
|
// <name>tahoma</name>
|
||||||
|
// <name>verdana</name>
|
||||||
|
// </nameset>
|
||||||
|
// <fileset>
|
||||||
|
// <file>Roboto-Regular.ttf</file>
|
||||||
|
// <file>Roboto-Bold.ttf</file>
|
||||||
|
// <file>Roboto-Italic.ttf</file>
|
||||||
|
// <file>Roboto-BoldItalic.ttf</file>
|
||||||
|
// </fileset>
|
||||||
|
// </family>
|
||||||
|
fn parse_family_v17(familyset: &Node, out:&mut Vec<FontFamily>) {
|
||||||
|
let mut nameset = Vec::new();
|
||||||
|
let mut fileset = Vec::new();
|
||||||
|
for node in familyset.children.borrow().iter() {
|
||||||
|
match node.data {
|
||||||
|
NodeData::Element { ref name, .. } => {
|
||||||
|
if &*name.local == "nameset" {
|
||||||
|
Self::collect_contents_with_tag(node, "name", &mut nameset);
|
||||||
|
} else if &*name.local == "fileset" {
|
||||||
|
Self::collect_contents_with_tag(node, "file", &mut fileset);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_=> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a families for each variation
|
||||||
|
for name in nameset {
|
||||||
|
let fonts: Vec<Font> = fileset.iter().map(|f| Font {
|
||||||
|
filename: f.clone(),
|
||||||
|
weight: None,
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
if !fonts.is_empty() {
|
||||||
|
out.push(FontFamily {
|
||||||
|
name: name,
|
||||||
|
fonts: fonts
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example:
|
||||||
|
// <font weight="100" style="normal">Roboto-Thin.ttf</font>
|
||||||
|
fn parse_font(node: &Node, attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<Font>) {
|
||||||
|
// Parse font filename
|
||||||
|
let filename = match Self::text_content(node) {
|
||||||
|
Some(filename) => filename,
|
||||||
|
_ => { return; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse font weight
|
||||||
|
let weight = Self::find_attrib("weight", attrs).and_then(|w| w.parse().ok());
|
||||||
|
|
||||||
|
out.push(Font {
|
||||||
|
filename: filename,
|
||||||
|
weight: weight,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example:
|
||||||
|
// <alias name="sans-serif-thin" to="sans-serif" weight="100" />
|
||||||
|
// <alias name="sans-serif-light" to="sans-serif" weight="300" />
|
||||||
|
// <alias name="sans-serif-medium" to="sans-serif" weight="500" />
|
||||||
|
// <alias name="sans-serif-black" to="sans-serif" weight="900" />
|
||||||
|
// <alias name="arial" to="sans-serif" />
|
||||||
|
// <alias name="helvetica" to="sans-serif" />
|
||||||
|
// <alias name="tahoma" to="sans-serif" />
|
||||||
|
// <alias name="verdana" to="sans-serif" />
|
||||||
|
fn parse_alias(attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<FontAlias>) {
|
||||||
|
// Parse alias name and referenced font
|
||||||
|
let from = match Self::find_attrib("name", attrs) {
|
||||||
|
Some(from) => from,
|
||||||
|
_ => { return; },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse referenced font
|
||||||
|
let to = match Self::find_attrib("to", attrs) {
|
||||||
|
Some(to) => to,
|
||||||
|
_ => { return; },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse optional weight filter
|
||||||
|
let weight = Self::find_attrib("weight", attrs).and_then(|w| w.parse().ok());
|
||||||
|
|
||||||
|
out.push(FontAlias {
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
weight: weight,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_attrib(name: &str, attrs: &RefCell<Vec<Attribute>>) -> Option<String> {
|
||||||
|
attrs.borrow().iter().find(|attr| &*attr.name.local == name).map(|s| String::from(&s.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_content(node: &Node) -> Option<String> {
|
||||||
|
node.children.borrow().get(0).and_then(|child| {
|
||||||
|
match child.data {
|
||||||
|
NodeData::Text { ref contents } => {
|
||||||
|
let mut result = String::new();
|
||||||
|
result.push_str(&contents.borrow());
|
||||||
|
Some(result)
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_contents_with_tag(node: &Node, tag: &str, out:&mut Vec<String>) {
|
||||||
|
for child in node.children.borrow().iter() {
|
||||||
|
match child.data {
|
||||||
|
NodeData::Element { ref name, .. } => {
|
||||||
|
if &*name.local == tag {
|
||||||
|
if let Some(content) = Self::text_content(child) {
|
||||||
|
out.push(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_=> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions used by FontCacheThread
|
||||||
|
pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
|
||||||
|
for family in &FONT_LIST.families {
|
||||||
|
callback(family.name.clone());
|
||||||
|
}
|
||||||
|
for alias in &FONT_LIST.aliases {
|
||||||
|
callback(alias.from.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
|
||||||
|
where F: FnMut(String)
|
||||||
|
{
|
||||||
|
println!("Variatioooon {:?}", family_name);
|
||||||
|
if let Some(family) = FONT_LIST.find_family(family_name) {
|
||||||
|
for font in &family.fonts {
|
||||||
|
callback(FontList::font_absolute_path(&font.filename));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(alias) = FONT_LIST.find_alias(family_name) {
|
||||||
|
if let Some(family) = FONT_LIST.find_family(&alias.to) {
|
||||||
|
for font in &family.fonts {
|
||||||
|
match (alias.weight, font.weight) {
|
||||||
|
(None, _) => callback(FontList::font_absolute_path(&font.filename)),
|
||||||
|
(Some(w1), Some(w2)) => {
|
||||||
|
if w1 == w2 {
|
||||||
|
callback(FontList::font_absolute_path(&font.filename))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn system_default_family(generic_name: &str) -> Option<String> {
|
||||||
|
if let Some(family) = FONT_LIST.find_family(&generic_name) {
|
||||||
|
Some(family.name.clone())
|
||||||
|
} else if let Some(alias) = FONT_LIST.find_alias(&generic_name) {
|
||||||
|
Some(alias.from.clone())
|
||||||
|
} else {
|
||||||
|
// First font defined in the fonts.xml is the default on Android.
|
||||||
|
FONT_LIST.families.get(0).map(|family| family.name.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn last_resort_font_families() -> Vec<String> {
|
||||||
|
vec!(
|
||||||
|
"sans-serif".to_owned(),
|
||||||
|
"Droid Sans".to_owned(),
|
||||||
|
"serif".to_owned(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static SANS_SERIF_FONT_FAMILY: &'static str = "sans-serif";
|
|
@ -141,11 +141,6 @@ pub fn last_resort_font_families() -> Vec<String> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
|
||||||
pub fn last_resort_font_families() -> Vec<String> {
|
|
||||||
vec!("Roboto".to_owned())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn last_resort_font_families() -> Vec<String> {
|
pub fn last_resort_font_families() -> Vec<String> {
|
||||||
vec!(
|
vec!(
|
||||||
|
@ -153,9 +148,6 @@ pub fn last_resort_font_families() -> Vec<String> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
|
||||||
pub static SANS_SERIF_FONT_FAMILY: &'static str = "Roboto";
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans";
|
pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans";
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,14 @@ mod freetype {
|
||||||
pub mod font;
|
pub mod font;
|
||||||
pub mod font_context;
|
pub mod font_context;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod font_list;
|
pub mod font_list;
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
mod android {
|
||||||
|
pub mod font_list;
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
pub use self::android::font_list;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
pub mod font_template;
|
pub mod font_template;
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl app::NestedEventLoopListener for BrowserWrapper {
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
fn setup_logging() {
|
fn setup_logging() {
|
||||||
// Piping logs from stdout/stderr to logcat happens in android_injected_glue.
|
// Piping logs from stdout/stderr to logcat happens in android_injected_glue.
|
||||||
::std::env::set_var("RUST_LOG", "debug");
|
::std::env::set_var("RUST_LOG", "error");
|
||||||
|
|
||||||
unsafe { android_injected_glue::ffi::app_dummy() };
|
unsafe { android_injected_glue::ffi::app_dummy() };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue