mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
Add font-fallback on OpenHarmony and fix several compilation issues (#32141)
* Add OpenHarmony support for allocator / profile Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * gfx: Build harfbuzz from source on OHOS Updates `freetype-sys` to v0.20.1, which includes a build fix for OpenHarmony. Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * gfx: Don't depend on fontconfig on OpenHarmony Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * gfx: Add ohos font fallback Hardcode HarmonyOS_Sans_SC_Regular for Chinese Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * libservo: OHOS useragent, and explicitly opt out of sandboxing Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> * libservo: Disable get_native_media_display_and_gl_context on ohos Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com> --------- Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com>
This commit is contained in:
parent
9acf2182cd
commit
ca064eaa51
8 changed files with 307 additions and 27 deletions
241
components/gfx/platform/freetype/ohos/font_list.rs
Normal file
241
components/gfx/platform/freetype/ohos/font_list.rs
Normal file
|
@ -0,0 +1,241 @@
|
|||
/* 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::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use style::values::computed::{
|
||||
FontStretch as StyleFontStretch, FontStyle as StyleFontStyle, FontWeight as StyleFontWeight,
|
||||
};
|
||||
use style::Atom;
|
||||
use ucd::{Codepoint, UnicodeBlock};
|
||||
use webrender_api::NativeFontHandle;
|
||||
|
||||
use crate::font_template::{FontTemplate, FontTemplateDescriptor};
|
||||
use crate::text::util::is_cjk;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref FONT_LIST: FontList = FontList::new();
|
||||
}
|
||||
|
||||
/// An identifier for a local font on OpenHarmony systems.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct LocalFontIdentifier {
|
||||
/// The path to the font.
|
||||
pub path: Atom,
|
||||
}
|
||||
|
||||
impl LocalFontIdentifier {
|
||||
pub(crate) fn index(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
File::open(Path::new(&*self.path))
|
||||
.expect("Couldn't open font file!")
|
||||
.read_to_end(&mut bytes)
|
||||
.unwrap();
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
struct Font {
|
||||
filename: String,
|
||||
weight: Option<i32>,
|
||||
style: Option<String>,
|
||||
}
|
||||
|
||||
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 {
|
||||
// We don't support parsing `/system/etc/fontconfig.json` yet.
|
||||
FontList {
|
||||
families: Self::fallback_font_families(),
|
||||
aliases: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// Fonts expected to exist in OpenHarmony devices.
|
||||
// Used until parsing of the fontconfig.json file is implemented.
|
||||
fn fallback_font_families() -> Vec<FontFamily> {
|
||||
let alternatives = [
|
||||
("HarmonyOS Sans", "HarmonyOS_Sans_SC_Regular.ttf"),
|
||||
("sans-serif", "HarmonyOS_Sans_SC_Regular.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,
|
||||
style: None,
|
||||
}],
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// OHOS fonts are located in /system/fonts
|
||||
fn font_absolute_path(filename: &str) -> String {
|
||||
if filename.starts_with("/") {
|
||||
String::from(filename)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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(FontTemplate),
|
||||
{
|
||||
let mut produce_font = |font: &Font| {
|
||||
let local_font_identifier = LocalFontIdentifier {
|
||||
path: Atom::from(FontList::font_absolute_path(&font.filename)),
|
||||
};
|
||||
let stretch = StyleFontStretch::NORMAL;
|
||||
let weight = font
|
||||
.weight
|
||||
.map(|w| StyleFontWeight::from_float(w as f32))
|
||||
.unwrap_or(StyleFontWeight::NORMAL);
|
||||
let style = match font.style.as_deref() {
|
||||
Some("italic") => StyleFontStyle::ITALIC,
|
||||
Some("normal") => StyleFontStyle::NORMAL,
|
||||
Some(value) => {
|
||||
warn!(
|
||||
"unknown value \"{value}\" for \"style\" attribute in the font {}",
|
||||
font.filename
|
||||
);
|
||||
StyleFontStyle::NORMAL
|
||||
},
|
||||
None => StyleFontStyle::NORMAL,
|
||||
};
|
||||
let descriptor = FontTemplateDescriptor {
|
||||
weight,
|
||||
stretch,
|
||||
style,
|
||||
};
|
||||
callback(FontTemplate::new_local(local_font_identifier, descriptor));
|
||||
};
|
||||
|
||||
if let Some(family) = FONT_LIST.find_family(family_name) {
|
||||
for font in &family.fonts {
|
||||
produce_font(font);
|
||||
}
|
||||
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, _) => produce_font(font),
|
||||
(Some(w1), Some(w2)) if w1 == w2 => produce_font(font),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
FONT_LIST.families.get(0).map(|family| family.name.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// Based on fonts present in OpenHarmony.
|
||||
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
|
||||
let mut families = vec![];
|
||||
|
||||
if let Some(block) = codepoint.and_then(|c| c.block()) {
|
||||
match block {
|
||||
UnicodeBlock::Hebrew => {
|
||||
families.push("Noto Sans Hebrew");
|
||||
},
|
||||
|
||||
UnicodeBlock::Arabic => {
|
||||
families.push("HarmonyOS Sans Naskh Arabic");
|
||||
},
|
||||
|
||||
UnicodeBlock::Devanagari => {
|
||||
families.push("Noto Sans Devanagari");
|
||||
},
|
||||
|
||||
UnicodeBlock::Tamil => {
|
||||
families.push("Noto Sans Tamil");
|
||||
},
|
||||
|
||||
UnicodeBlock::Thai => {
|
||||
families.push("Noto Sans Thai");
|
||||
},
|
||||
|
||||
UnicodeBlock::Georgian | UnicodeBlock::GeorgianSupplement => {
|
||||
families.push("Noto Sans Georgian");
|
||||
},
|
||||
|
||||
UnicodeBlock::Ethiopic | UnicodeBlock::EthiopicSupplement => {
|
||||
families.push("Noto Sans Ethiopic");
|
||||
},
|
||||
|
||||
_ => {
|
||||
if is_cjk(codepoint.unwrap()) {
|
||||
families.push("Noto Sans JP");
|
||||
families.push("Noto Sans KR");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
families.push("HarmonyOS Sans");
|
||||
families
|
||||
}
|
||||
|
||||
pub static SANS_SERIF_FONT_FAMILY: &'static str = "HarmonyOS Sans";
|
|
@ -26,7 +26,7 @@ mod freetype {
|
|||
|
||||
pub mod font;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
|
||||
pub mod font_list;
|
||||
#[cfg(target_os = "android")]
|
||||
mod android {
|
||||
|
@ -35,6 +35,12 @@ mod freetype {
|
|||
}
|
||||
#[cfg(target_os = "android")]
|
||||
pub use self::android::font_list;
|
||||
#[cfg(target_env = "ohos")]
|
||||
mod ohos {
|
||||
pub mod font_list;
|
||||
}
|
||||
#[cfg(target_env = "ohos")]
|
||||
pub use self::ohos::font_list;
|
||||
|
||||
pub mod library_handle;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue