diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-10-04 20:06:29 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-04 20:06:29 -0500 |
commit | eb3333eb2f6dbac75ecf23e84cbb12149b3dc969 (patch) | |
tree | d8e13d18da7dca35cb20872fd46e62d88d082eec | |
parent | 710bd7e1dc8f314399d937e968f160f94143e500 (diff) | |
parent | 08496072396b2b049ff9b676084ec34a9ba94124 (diff) | |
download | servo-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.toml | 8 | ||||
-rw-r--r-- | components/gfx/lib.rs | 8 | ||||
-rw-r--r-- | components/gfx/platform/mod.rs | 25 | ||||
-rw-r--r-- | components/gfx/platform/windows/font_list.rs | 74 | ||||
-rw-r--r-- | components/gfx/platform/windows/font_template.rs | 89 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 2 |
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)", ] |