mirror of
https://github.com/servo/servo.git
synced 2025-06-30 12:03:38 +01:00
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 -->
This commit is contained in:
commit
eb3333eb2f
7 changed files with 195 additions and 13 deletions
|
@ -58,9 +58,15 @@ core-foundation = "0.2"
|
||||||
core-graphics = "0.4"
|
core-graphics = "0.4"
|
||||||
core-text = "2.0"
|
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"}
|
freetype = {git = "https://github.com/servo/rust-freetype"}
|
||||||
|
|
||||||
|
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||||
servo-fontconfig = "0.2.1"
|
servo-fontconfig = "0.2.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
||||||
simd = {git = "https://github.com/huonw/simd"}
|
simd = {git = "https://github.com/huonw/simd"}
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
winapi = "0.2"
|
||||||
|
gdi32-sys = "0.2"
|
||||||
|
|
|
@ -33,14 +33,18 @@ extern crate bitflags;
|
||||||
#[cfg(target_os = "macos")] extern crate core_graphics;
|
#[cfg(target_os = "macos")] extern crate core_graphics;
|
||||||
#[cfg(target_os = "macos")] extern crate core_text;
|
#[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 euclid;
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
|
|
||||||
// Platforms that use Freetype/Fontconfig library dependencies
|
// 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 fontconfig;
|
||||||
extern crate fontsan;
|
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 freetype;
|
||||||
|
|
||||||
extern crate gfx_traits;
|
extern crate gfx_traits;
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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")))]
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
|
||||||
pub use platform::freetype::{font, font_context, font_list, font_template};
|
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")]
|
#[cfg(target_os = "macos")]
|
||||||
pub use platform::macos::{font, font_context, font_list, font_template};
|
pub use platform::macos::{font, font_context, font_list, font_template};
|
||||||
|
|
||||||
#[cfg(all(target_os = "windows", target_env = "msvc"))]
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
|
||||||
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")))]
|
|
||||||
mod freetype {
|
mod freetype {
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -25,7 +28,11 @@ mod freetype {
|
||||||
|
|
||||||
pub mod font;
|
pub mod font;
|
||||||
pub mod font_context;
|
pub mod font_context;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
pub mod font_list;
|
pub mod font_list;
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
pub mod font_template;
|
pub mod font_template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +44,8 @@ mod macos {
|
||||||
pub mod font_template;
|
pub mod font_template;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_os = "windows", target_env = "msvc"))]
|
#[cfg(target_os = "windows")]
|
||||||
mod dummy {
|
mod windows {
|
||||||
pub mod font;
|
|
||||||
pub mod font_context;
|
|
||||||
pub mod font_list;
|
pub mod font_list;
|
||||||
pub mod font_template;
|
pub mod font_template;
|
||||||
}
|
}
|
||||||
|
|
74
components/gfx/platform/windows/font_list.rs
Normal file
74
components/gfx/platform/windows/font_list.rs
Normal file
|
@ -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());
|
||||||
|
}
|
89
components/gfx/platform/windows/font_template.rs
Normal file
89
components/gfx/platform/windows/font_template.rs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
2
components/servo/Cargo.lock
generated
2
components/servo/Cargo.lock
generated
|
@ -796,6 +796,7 @@ dependencies = [
|
||||||
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
|
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
|
||||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
"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",
|
"gfx_traits 0.0.1",
|
||||||
"harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
"webrender_traits 0.5.1 (git+https://github.com/servo/webrender)",
|
"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)",
|
"xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
2
ports/cef/Cargo.lock
generated
2
ports/cef/Cargo.lock
generated
|
@ -712,6 +712,7 @@ dependencies = [
|
||||||
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
|
"fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
|
||||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
"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",
|
"gfx_traits 0.0.1",
|
||||||
"harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
"webrender_traits 0.5.1 (git+https://github.com/servo/webrender)",
|
"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)",
|
"xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue