aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-10-04 20:06:29 -0500
committerGitHub <noreply@github.com>2016-10-04 20:06:29 -0500
commiteb3333eb2f6dbac75ecf23e84cbb12149b3dc969 (patch)
treed8e13d18da7dca35cb20872fd46e62d88d082eec
parent710bd7e1dc8f314399d937e968f160f94143e500 (diff)
parent08496072396b2b049ff9b676084ec34a9ba94124 (diff)
downloadservo-eb3333eb2f6dbac75ecf23e84cbb12149b3dc969.tar.gz
servo-eb3333eb2f6dbac75ecf23e84cbb12149b3dc969.zip
Auto merge of #13567 - glennw:win-fonts, r=larsbergstrom
Minimal Win32 font platform implementation. This uses a (very simple) Win32 API call to enumerate font families available, and load them as byte buffers. The font rasterization itself is done by freetype. This gets Servo + WR + Windows working, but should be improved by adding a proper implementation that matches fonts correctly and also uses DirectWrite (or GDI) to handle font rasterization. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13567) <!-- Reviewable:end -->
-rw-r--r--components/gfx/Cargo.toml8
-rw-r--r--components/gfx/lib.rs8
-rw-r--r--components/gfx/platform/mod.rs25
-rw-r--r--components/gfx/platform/windows/font_list.rs74
-rw-r--r--components/gfx/platform/windows/font_template.rs89
-rw-r--r--components/servo/Cargo.lock2
-rw-r--r--ports/cef/Cargo.lock2
7 files changed, 195 insertions, 13 deletions
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml
index 129e0d99bd1..ba387d19bb0 100644
--- a/components/gfx/Cargo.toml
+++ b/components/gfx/Cargo.toml
@@ -58,9 +58,15 @@ core-foundation = "0.2"
core-graphics = "0.4"
core-text = "2.0"
-[target.'cfg(any(target_os = "linux", target_os = "android", all(target_os = "windows", target_env = "gnu")))'.dependencies]
+[target.'cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))'.dependencies]
freetype = {git = "https://github.com/servo/rust-freetype"}
+
+[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
servo-fontconfig = "0.2.1"
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
simd = {git = "https://github.com/huonw/simd"}
+
+[target.'cfg(target_os = "windows")'.dependencies]
+winapi = "0.2"
+gdi32-sys = "0.2"
diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs
index f8e8febc96c..7315c579416 100644
--- a/components/gfx/lib.rs
+++ b/components/gfx/lib.rs
@@ -33,14 +33,18 @@ extern crate bitflags;
#[cfg(target_os = "macos")] extern crate core_graphics;
#[cfg(target_os = "macos")] extern crate core_text;
+// Windows-specific library dependencies
+#[cfg(target_os = "windows")] extern crate gdi32;
+#[cfg(target_os = "windows")] extern crate winapi;
+
extern crate euclid;
extern crate fnv;
// Platforms that use Freetype/Fontconfig library dependencies
-#[cfg(any(target_os = "linux", target_os = "android", all(target_os = "windows", target_env = "gnu")))]
+#[cfg(any(target_os = "linux", target_os = "android"))]
extern crate fontconfig;
extern crate fontsan;
-#[cfg(any(target_os = "linux", target_os = "android", all(target_os = "windows", target_env = "gnu")))]
+#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
extern crate freetype;
extern crate gfx_traits;
diff --git a/components/gfx/platform/mod.rs b/components/gfx/platform/mod.rs
index 9f81d124b29..47ba97cc1e0 100644
--- a/components/gfx/platform/mod.rs
+++ b/components/gfx/platform/mod.rs
@@ -2,16 +2,19 @@
* 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/. */
-#[cfg(any(target_os = "linux", target_os = "android", all(target_os = "windows", target_env = "gnu")))]
-pub use platform::freetype::{font, font_context, font_list, font_template};
+#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
+pub use platform::freetype::{font, font_context};
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub use platform::freetype::{font_list, font_template};
+
+#[cfg(target_os = "windows")]
+pub use platform::windows::{font_list, font_template};
#[cfg(target_os = "macos")]
pub use platform::macos::{font, font_context, font_list, font_template};
-#[cfg(all(target_os = "windows", target_env = "msvc"))]
-pub use platform::dummy::{font, font_context, font_list, font_template};
-
-#[cfg(any(target_os = "linux", target_os = "android", all(target_os = "windows", target_env = "gnu")))]
+#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
mod freetype {
use libc::c_char;
use std::ffi::CStr;
@@ -25,7 +28,11 @@ mod freetype {
pub mod font;
pub mod font_context;
+
+ #[cfg(any(target_os = "linux", target_os = "android"))]
pub mod font_list;
+
+ #[cfg(any(target_os = "linux", target_os = "android"))]
pub mod font_template;
}
@@ -37,10 +44,8 @@ mod macos {
pub mod font_template;
}
-#[cfg(all(target_os = "windows", target_env = "msvc"))]
-mod dummy {
- pub mod font;
- pub mod font_context;
+#[cfg(target_os = "windows")]
+mod windows {
pub mod font_list;
pub mod font_template;
}
diff --git a/components/gfx/platform/windows/font_list.rs b/components/gfx/platform/windows/font_list.rs
new file mode 100644
index 00000000000..ed7657f5519
--- /dev/null
+++ b/components/gfx/platform/windows/font_list.rs
@@ -0,0 +1,74 @@
+/* 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 gdi32;
+use std::ffi::OsString;
+use std::os::windows::ffi::OsStringExt;
+use std::ptr;
+use winapi::{LOGFONTW, LPARAM, OUT_TT_ONLY_PRECIS, VOID};
+use winapi::{c_int, DWORD, LF_FACESIZE};
+
+pub static SANS_SERIF_FONT_FAMILY: &'static str = "Arial";
+
+pub fn system_default_family(_: &str) -> Option<String> {
+ None
+}
+
+pub fn last_resort_font_families() -> Vec<String> {
+ vec!("Arial".to_owned())
+}
+
+unsafe extern "system" fn enum_font_callback(lpelfe: *const LOGFONTW,
+ _: *const VOID,
+ _: DWORD,
+ lparam: LPARAM) -> c_int {
+ let name = (*lpelfe).lfFaceName;
+ let term_pos = name.iter().position(|c| *c == 0).unwrap();
+ let name = OsString::from_wide(&name[0..term_pos]).into_string().unwrap();
+
+ let fonts = lparam as *mut Vec<String>;
+ let fonts = &mut *fonts;
+ fonts.push(name);
+
+ 1
+}
+
+pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
+ let mut fonts = Vec::new();
+
+ let mut config = LOGFONTW {
+ lfHeight: 0,
+ lfWidth: 0,
+ lfEscapement: 0,
+ lfOrientation: 0,
+ lfWeight: 0,
+ lfItalic: 0,
+ lfUnderline: 0,
+ lfStrikeOut: 0,
+ lfCharSet: 0,
+ lfOutPrecision: OUT_TT_ONLY_PRECIS as u8,
+ lfClipPrecision: 0,
+ lfQuality: 0,
+ lfPitchAndFamily: 0,
+ lfFaceName: [0; LF_FACESIZE],
+ };
+
+ unsafe {
+ let hdc = gdi32::CreateCompatibleDC(ptr::null_mut());
+ gdi32::EnumFontFamiliesExW(hdc,
+ &mut config,
+ Some(enum_font_callback),
+ &mut fonts as *mut Vec<String> as LPARAM,
+ 0);
+ gdi32::DeleteDC(hdc);
+ }
+
+ for family in fonts {
+ callback(family);
+ }
+}
+
+pub fn for_each_variation<F>(family_name: &str, mut callback: F) where F: FnMut(String) {
+ callback(family_name.to_owned());
+}
diff --git a/components/gfx/platform/windows/font_template.rs b/components/gfx/platform/windows/font_template.rs
new file mode 100644
index 00000000000..39cf1a0b80b
--- /dev/null
+++ b/components/gfx/platform/windows/font_template.rs
@@ -0,0 +1,89 @@
+/* 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 gdi32;
+use std::ffi::OsString;
+use std::io::Error;
+use std::os::windows::ffi::OsStrExt;
+use std::ptr;
+use string_cache::Atom;
+use webrender_traits::NativeFontHandle;
+use winapi::{DWORD, LF_FACESIZE, LOGFONTW, OUT_TT_ONLY_PRECIS, WCHAR};
+
+const GDI_ERROR: DWORD = 0xffffffff;
+
+#[derive(Deserialize, Serialize, Debug)]
+pub struct FontTemplateData {
+ pub bytes: Vec<u8>,
+ pub identifier: Atom,
+}
+
+impl FontTemplateData {
+ pub fn new(identifier: Atom,
+ font_data: Option<Vec<u8>>) -> Result<FontTemplateData, Error> {
+ let bytes = match font_data {
+ Some(bytes) => {
+ bytes
+ },
+ None => {
+ assert!(identifier.len() < LF_FACESIZE);
+ let name = OsString::from(identifier.as_ref());
+ let buffer: Vec<WCHAR> = name.encode_wide().collect();
+ let mut string: [WCHAR; LF_FACESIZE] = [0; LF_FACESIZE];
+
+ for (src, dest) in buffer.iter().zip(string.iter_mut()) {
+ *dest = *src;
+ }
+
+ let config = LOGFONTW {
+ lfHeight: 0,
+ lfWidth: 0,
+ lfEscapement: 0,
+ lfOrientation: 0,
+ lfWeight: 0,
+ lfItalic: 0,
+ lfUnderline: 0,
+ lfStrikeOut: 0,
+ lfCharSet: 0,
+ lfOutPrecision: OUT_TT_ONLY_PRECIS as u8,
+ lfClipPrecision: 0,
+ lfQuality: 0,
+ lfPitchAndFamily: 0,
+ lfFaceName: string,
+ };
+
+ unsafe {
+ let hdc = gdi32::CreateCompatibleDC(ptr::null_mut());
+ let hfont = gdi32::CreateFontIndirectW(&config as *const _);
+ gdi32::SelectObject(hdc, hfont as *mut _);
+ let size = gdi32::GetFontData(hdc, 0, 0, ptr::null_mut(), 0);
+ assert!(size != GDI_ERROR);
+ let mut buffer: Vec<u8> = vec![0; size as usize];
+ let actual_size = gdi32::GetFontData(hdc, 0, 0, buffer.as_mut_ptr() as *mut _, size);
+ assert!(actual_size == size);
+ gdi32::DeleteDC(hdc);
+ gdi32::DeleteObject(hfont as *mut _);
+ buffer
+ }
+ }
+ };
+
+ Ok(FontTemplateData {
+ bytes: bytes,
+ identifier: identifier,
+ })
+ }
+
+ pub fn bytes(&self) -> Vec<u8> {
+ self.bytes.clone()
+ }
+
+ pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
+ Some(self.bytes())
+ }
+
+ pub fn native_font(&self) -> Option<NativeFontHandle> {
+ None
+ }
+}
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index de7c74f5af4..e6c73ef7b1e 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -796,6 +796,7 @@ dependencies = [
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -827,6 +828,7 @@ dependencies = [
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webrender_traits 0.5.1 (git+https://github.com/servo/webrender)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index a081b0328a5..cf6a99a43d9 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -712,6 +712,7 @@ dependencies = [
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_traits 0.0.1",
"harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -743,6 +744,7 @@ dependencies = [
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"webrender_traits 0.5.1 (git+https://github.com/servo/webrender)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]