aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/allocator/Cargo.toml4
-rw-r--r--components/allocator/lib.rs13
-rw-r--r--components/gfx/Cargo.toml8
-rw-r--r--components/gfx/platform/freetype/ohos/font_list.rs241
-rw-r--r--components/gfx/platform/mod.rs8
-rw-r--r--components/profile/Cargo.toml1
-rw-r--r--components/profile/mem.rs14
-rw-r--r--components/servo/lib.rs45
8 files changed, 307 insertions, 27 deletions
diff --git a/components/allocator/Cargo.toml b/components/allocator/Cargo.toml
index e6467da3737..3978241094d 100644
--- a/components/allocator/Cargo.toml
+++ b/components/allocator/Cargo.toml
@@ -12,7 +12,7 @@ path = "lib.rs"
[features]
use-system-allocator = ["libc"]
-[target.'cfg(not(any(windows, target_os = "android")))'.dependencies]
+[target.'cfg(not(any(windows, target_os = "android", target_env = "ohos")))'.dependencies]
jemallocator = { workspace = true }
jemalloc-sys = { workspace = true }
libc = { workspace = true, optional = true }
@@ -20,5 +20,5 @@ libc = { workspace = true, optional = true }
[target.'cfg(windows)'.dependencies]
winapi = { workspace = true, features = ["heapapi"] }
-[target.'cfg(target_os = "android")'.dependencies]
+[target.'cfg(any(target_os = "android", target_env = "ohos"))'.dependencies]
libc = { workspace = true }
diff --git a/components/allocator/lib.rs b/components/allocator/lib.rs
index 20ac30e8022..a28916375df 100644
--- a/components/allocator/lib.rs
+++ b/components/allocator/lib.rs
@@ -9,7 +9,12 @@ static ALLOC: Allocator = Allocator;
pub use crate::platform::*;
-#[cfg(not(any(windows, target_os = "android", feature = "use-system-allocator")))]
+#[cfg(not(any(
+ windows,
+ target_os = "android",
+ feature = "use-system-allocator",
+ target_env = "ohos"
+)))]
mod platform {
use std::os::raw::c_void;
@@ -32,7 +37,11 @@ mod platform {
#[cfg(all(
not(windows),
- any(target_os = "android", feature = "use-system-allocator")
+ any(
+ target_os = "android",
+ feature = "use-system-allocator",
+ target_env = "ohos"
+ )
))]
mod platform {
pub use std::alloc::System as Allocator;
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml
index 06982af6aee..5174f593572 100644
--- a/components/gfx/Cargo.toml
+++ b/components/gfx/Cargo.toml
@@ -22,7 +22,7 @@ euclid = { workspace = true }
fnv = { workspace = true }
fontsan = { git = "https://github.com/servo/fontsan" }
gfx_traits = { workspace = true }
-harfbuzz-sys = "0.6"
+harfbuzz-sys = "0.6.1"
ipc-channel = { workspace = true }
lazy_static = { workspace = true }
libc = { workspace = true }
@@ -55,12 +55,16 @@ harfbuzz-sys = { version = "0.6", features = ["bundled"] }
freetype = "0.7"
servo_allocator = { path = "../allocator" }
-[target.'cfg(target_os = "linux")'.dependencies]
+[target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies]
fontconfig_sys = { package = "yeslogic-fontconfig-sys", version = "5" }
[target.'cfg(target_os = "android")'.dependencies]
xml-rs = "0.8"
+[target.'cfg(target_env = "ohos")'.dependencies]
+harfbuzz-sys = { version = "0.6.1", features = ["bundled"] }
+
+
[target.'cfg(target_os = "windows")'.dependencies]
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
dwrote = "0.11"
diff --git a/components/gfx/platform/freetype/ohos/font_list.rs b/components/gfx/platform/freetype/ohos/font_list.rs
new file mode 100644
index 00000000000..95d7209c6ad
--- /dev/null
+++ b/components/gfx/platform/freetype/ohos/font_list.rs
@@ -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";
diff --git a/components/gfx/platform/mod.rs b/components/gfx/platform/mod.rs
index 5509c214531..7b2efa41671 100644
--- a/components/gfx/platform/mod.rs
+++ b/components/gfx/platform/mod.rs
@@ -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;
}
diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml
index da55faa6a00..36aca49b6df 100644
--- a/components/profile/Cargo.toml
+++ b/components/profile/Cargo.toml
@@ -25,4 +25,5 @@ regex = { workspace = true }
[target.'cfg(not(any(target_os = "windows", target_os = "android")))'.dependencies]
libc = { workspace = true }
+[target.'cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))'.dependencies]
jemalloc-sys = { workspace = true }
diff --git a/components/profile/mem.rs b/components/profile/mem.rs
index 0fdeb76715c..56bcdeb5a0d 100644
--- a/components/profile/mem.rs
+++ b/components/profile/mem.rs
@@ -387,16 +387,16 @@ impl ReportsForest {
//---------------------------------------------------------------------------
mod system_reporter {
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
use std::ffi::CString;
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
use std::mem::size_of;
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
use std::ptr::null_mut;
#[cfg(target_os = "linux")]
use libc::c_int;
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
use libc::{c_void, size_t};
use profile_traits::mem::{Report, ReportKind, ReporterRequest};
use profile_traits::path;
@@ -499,10 +499,10 @@ mod system_reporter {
None
}
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
use jemalloc_sys::mallctl;
- #[cfg(not(any(target_os = "windows", target_os = "android")))]
+ #[cfg(not(any(target_os = "windows", target_os = "android", target_env = "ohos")))]
fn jemalloc_stat(value_name: &str) -> Option<usize> {
// Before we request the measurement of interest, we first send an "epoch"
// request. Without that jemalloc gives cached statistics(!) which can be
@@ -549,7 +549,7 @@ mod system_reporter {
Some(value as usize)
}
- #[cfg(any(target_os = "windows", target_os = "android"))]
+ #[cfg(any(target_os = "windows", target_os = "android", target_env = "ohos"))]
fn jemalloc_stat(_value_name: &str) -> Option<usize> {
None
}
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index a638c2942ab..28ae62f1fec 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -42,7 +42,8 @@ use compositing_traits::{
not(target_os = "ios"),
not(target_os = "android"),
not(target_arch = "arm"),
- not(target_arch = "aarch64")
+ not(target_arch = "aarch64"),
+ not(target_env = "ohos"),
))]
use constellation::content_process_sandbox_profile;
use constellation::{
@@ -58,7 +59,8 @@ use euclid::Scale;
not(target_os = "ios"),
not(target_os = "android"),
not(target_arch = "arm"),
- not(target_arch = "aarch64")
+ not(target_arch = "aarch64"),
+ not(target_env = "ohos"),
))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
@@ -81,12 +83,12 @@ use script_traits::{ScriptToConstellationChan, WindowSizeData};
use servo_config::{opts, pref, prefs};
use servo_media::player::context::GlContext;
use servo_media::ServoMedia;
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::connection::NativeConnection as LinuxNativeConnection;
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::context::NativeContext as LinuxNativeContext;
use surfman::{GLApi, GLVersion};
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::{NativeConnection, NativeContext};
use webrender::{RenderApiSender, ShaderPrecacheFlags};
use webrender_api::{
@@ -253,6 +255,9 @@ where
Some(ref ua) if ua == "desktop" => {
default_user_agent_string_for(UserAgent::Desktop).into()
},
+ Some(ref ua) if ua == "ohos" => {
+ default_user_agent_string_for(UserAgent::OpenHarmony).into()
+ },
Some(ua) => ua.into(),
None => embedder
.get_user_agent_string()
@@ -492,7 +497,7 @@ where
}
}
- #[cfg(target_os = "linux")]
+ #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
fn get_native_media_display_and_gl_context(
rendering_context: &RenderingContext,
) -> Option<(NativeDisplay, GlContext)> {
@@ -529,7 +534,10 @@ where
Some((native_display, gl_context))
}
- #[cfg(not(any(target_os = "windows", target_os = "linux")))]
+ #[cfg(not(any(
+ target_os = "windows",
+ all(target_os = "linux", not(target_env = "ohos"))
+ )))]
fn get_native_media_display_and_gl_context(
_rendering_context: &RenderingContext,
) -> Option<(NativeDisplay, GlContext)> {
@@ -1196,7 +1204,8 @@ pub fn run_content_process(token: String) {
not(target_os = "ios"),
not(target_os = "android"),
not(target_arch = "arm"),
- not(target_arch = "aarch64")
+ not(target_arch = "aarch64"),
+ not(target_env = "ohos"),
))]
fn create_sandbox() {
ChildSandbox::new(content_process_sandbox_profile())
@@ -1209,7 +1218,8 @@ fn create_sandbox() {
target_os = "ios",
target_os = "android",
target_arch = "arm",
- target_arch = "aarch64"
+ target_arch = "aarch64",
+ target_env = "ohos",
))]
fn create_sandbox() {
panic!("Sandboxing is not supported on Windows, iOS, ARM targets and android.");
@@ -1218,15 +1228,20 @@ fn create_sandbox() {
enum UserAgent {
Desktop,
Android,
+ OpenHarmony,
#[allow(non_camel_case_types)]
iOS,
}
fn default_user_agent_string_for(agent: UserAgent) -> &'static str {
- #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
+ #[cfg(all(target_os = "linux", target_arch = "x86_64", not(target_env = "ohos")))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Servo/1.0 Firefox/111.0";
- #[cfg(all(target_os = "linux", not(target_arch = "x86_64")))]
+ #[cfg(all(
+ target_os = "linux",
+ not(target_arch = "x86_64"),
+ not(target_env = "ohos")
+ ))]
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (X11; Linux i686; rv:109.0) Servo/1.0 Firefox/111.0";
@@ -1241,12 +1256,13 @@ fn default_user_agent_string_for(agent: UserAgent) -> &'static str {
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Servo/1.0 Firefox/111.0";
- #[cfg(target_os = "android")]
+ #[cfg(any(target_os = "android", target_env = "ohos"))]
const DESKTOP_UA_STRING: &'static str = "";
match agent {
UserAgent::Desktop => DESKTOP_UA_STRING,
UserAgent::Android => "Mozilla/5.0 (Android; Mobile; rv:109.0) Servo/1.0 Firefox/111.0",
+ UserAgent::OpenHarmony => "Mozilla/5.0 (OpenHarmony; Mobile; rv:109.0) Servo/1.0 Firefox/111.0",
UserAgent::iOS => {
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_4 like Mac OS X; rv:109.0) Servo/1.0 Firefox/111.0"
},
@@ -1256,8 +1272,11 @@ fn default_user_agent_string_for(agent: UserAgent) -> &'static str {
#[cfg(target_os = "android")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android;
+#[cfg(target_env = "ohos")]
+const DEFAULT_USER_AGENT: UserAgent = UserAgent::OpenHarmony;
+
#[cfg(target_os = "ios")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::iOS;
-#[cfg(not(any(target_os = "android", target_os = "ios")))]
+#[cfg(not(any(target_os = "android", target_os = "ios", target_env = "ohos")))]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop;