mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Merge pull request #3256 from glennw/font-fixes
Improve quality of font rendering on Linux (and Android).
This commit is contained in:
commit
6eeac023a9
4 changed files with 65 additions and 29 deletions
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use platform::font_list::get_available_families;
|
use platform::font_list::get_available_families;
|
||||||
|
use platform::font_list::get_system_default_family;
|
||||||
use platform::font_list::get_variations_for_family;
|
use platform::font_list::get_variations_for_family;
|
||||||
use platform::font_list::get_last_resort_font_families;
|
use platform::font_list::get_last_resort_font_families;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
@ -90,6 +91,16 @@ struct FontCache {
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_generic_font(generic_fonts: &mut HashMap<String, String>,
|
||||||
|
generic_name: &str, mapped_name: &str) {
|
||||||
|
let opt_system_default = get_system_default_family(generic_name);
|
||||||
|
let family_name = match opt_system_default {
|
||||||
|
Some(system_default) => system_default,
|
||||||
|
None => mapped_name.to_string(),
|
||||||
|
};
|
||||||
|
generic_fonts.insert(generic_name.to_string(), family_name);
|
||||||
|
}
|
||||||
|
|
||||||
impl FontCache {
|
impl FontCache {
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
|
@ -223,11 +234,11 @@ impl FontCacheTask {
|
||||||
spawn(proc() {
|
spawn(proc() {
|
||||||
// TODO: Allow users to specify these.
|
// TODO: Allow users to specify these.
|
||||||
let mut generic_fonts = HashMap::with_capacity(5);
|
let mut generic_fonts = HashMap::with_capacity(5);
|
||||||
generic_fonts.insert("serif".to_string(), "Times New Roman".to_string());
|
add_generic_font(&mut generic_fonts, "serif", "Times New Roman");
|
||||||
generic_fonts.insert("sans-serif".to_string(), "Arial".to_string());
|
add_generic_font(&mut generic_fonts, "sans-serif", "Arial");
|
||||||
generic_fonts.insert("cursive".to_string(), "Apple Chancery".to_string());
|
add_generic_font(&mut generic_fonts, "cursive", "Apple Chancery");
|
||||||
generic_fonts.insert("fantasy".to_string(), "Papyrus".to_string());
|
add_generic_font(&mut generic_fonts, "fantasy", "Papyrus");
|
||||||
generic_fonts.insert("monospace".to_string(), "Menlo".to_string());
|
add_generic_font(&mut generic_fonts, "monospace", "Menlo");
|
||||||
|
|
||||||
let mut cache = FontCache {
|
let mut cache = FontCache {
|
||||||
port: port,
|
port: port,
|
||||||
|
|
|
@ -260,13 +260,10 @@ impl FontHandleMethods for FontHandle {
|
||||||
|
|
||||||
impl<'a> FontHandle {
|
impl<'a> FontHandle {
|
||||||
fn set_char_size(face: FT_Face, pt_size: f64) -> Result<(), ()>{
|
fn set_char_size(face: FT_Face, pt_size: f64) -> Result<(), ()>{
|
||||||
let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
let char_width = float_to_fixed_ft((0.5f64 + pt_size).floor()) as FT_F26Dot6;
|
||||||
let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
|
||||||
let h_dpi = 72;
|
|
||||||
let v_dpi = 72;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = FT_Set_Char_Size(face, char_width, char_height, h_dpi, v_dpi);
|
let result = FT_Set_Char_Size(face, char_width, 0, 0, 0);
|
||||||
if result.succeeded() { Ok(()) } else { Err(()) }
|
if result.succeeded() { Ok(()) } else { Err(()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,12 @@ extern crate fontconfig;
|
||||||
|
|
||||||
use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
|
use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
|
||||||
use fontconfig::fontconfig::{
|
use fontconfig::fontconfig::{
|
||||||
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
|
FcConfigGetCurrent, FcConfigGetFonts,
|
||||||
|
FcConfigSubstitute, FcDefaultSubstitute,
|
||||||
|
FcFontMatch,
|
||||||
|
FcNameParse, FcPatternGetString,
|
||||||
FcPatternDestroy, FcFontSetDestroy,
|
FcPatternDestroy, FcFontSetDestroy,
|
||||||
|
FcMatchPattern,
|
||||||
FcPatternCreate, FcPatternAddString,
|
FcPatternCreate, FcPatternAddString,
|
||||||
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
|
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
|
||||||
FcObjectSetAdd, FcPatternGetInteger
|
FcObjectSetAdd, FcPatternGetInteger
|
||||||
|
@ -21,6 +25,10 @@ use libc::c_int;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::string;
|
use std::string;
|
||||||
|
|
||||||
|
static FC_FAMILY: &'static [u8] = b"family\0";
|
||||||
|
static FC_FILE: &'static [u8] = b"file\0";
|
||||||
|
static FC_INDEX: &'static [u8] = b"index\0";
|
||||||
|
|
||||||
pub fn get_available_families(callback: |String|) {
|
pub fn get_available_families(callback: |String|) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let config = FcConfigGetCurrent();
|
let config = FcConfigGetCurrent();
|
||||||
|
@ -29,9 +37,7 @@ pub fn get_available_families(callback: |String|) {
|
||||||
let font = (*fontSet).fonts.offset(i);
|
let font = (*fontSet).fonts.offset(i);
|
||||||
let mut family: *mut FcChar8 = ptr::mut_null();
|
let mut family: *mut FcChar8 = ptr::mut_null();
|
||||||
let mut v: c_int = 0;
|
let mut v: c_int = 0;
|
||||||
let mut FC_FAMILY_C = "family".to_c_str();
|
while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut i8, v, &mut family) == FcResultMatch {
|
||||||
let FC_FAMILY = FC_FAMILY_C.as_mut_ptr();
|
|
||||||
while FcPatternGetString(*font, FC_FAMILY, v, &mut family) == FcResultMatch {
|
|
||||||
let family_name = string::raw::from_buf(family as *const i8 as *const u8);
|
let family_name = string::raw::from_buf(family as *const i8 as *const u8);
|
||||||
callback(family_name);
|
callback(family_name);
|
||||||
v += 1;
|
v += 1;
|
||||||
|
@ -48,22 +54,16 @@ pub fn get_variations_for_family(family_name: &str, callback: |String|) {
|
||||||
let font_set_array_ptr = &mut font_set;
|
let font_set_array_ptr = &mut font_set;
|
||||||
let pattern = FcPatternCreate();
|
let pattern = FcPatternCreate();
|
||||||
assert!(pattern.is_not_null());
|
assert!(pattern.is_not_null());
|
||||||
let mut FC_FAMILY_C = "family".to_c_str();
|
|
||||||
let FC_FAMILY = FC_FAMILY_C.as_mut_ptr();
|
|
||||||
let mut family_name_c = family_name.to_c_str();
|
let mut family_name_c = family_name.to_c_str();
|
||||||
let family_name = family_name_c.as_mut_ptr();
|
let family_name = family_name_c.as_mut_ptr();
|
||||||
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *mut FcChar8);
|
let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut i8, family_name as *mut FcChar8);
|
||||||
assert!(ok != 0);
|
assert!(ok != 0);
|
||||||
|
|
||||||
let object_set = FcObjectSetCreate();
|
let object_set = FcObjectSetCreate();
|
||||||
assert!(object_set.is_not_null());
|
assert!(object_set.is_not_null());
|
||||||
|
|
||||||
let mut FC_FILE_C = "file".to_c_str();
|
FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut i8);
|
||||||
let FC_FILE = FC_FILE_C.as_mut_ptr();
|
FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut i8);
|
||||||
FcObjectSetAdd(object_set, FC_FILE);
|
|
||||||
let mut FC_INDEX_C = "index".to_c_str();
|
|
||||||
let FC_INDEX = FC_INDEX_C.as_mut_ptr();
|
|
||||||
FcObjectSetAdd(object_set, FC_INDEX);
|
|
||||||
|
|
||||||
let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);
|
let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);
|
||||||
|
|
||||||
|
@ -71,18 +71,14 @@ pub fn get_variations_for_family(family_name: &str, callback: |String|) {
|
||||||
|
|
||||||
for i in range(0, (*matches).nfont as int) {
|
for i in range(0, (*matches).nfont as int) {
|
||||||
let font = (*matches).fonts.offset(i);
|
let font = (*matches).fonts.offset(i);
|
||||||
let mut FC_FILE_C = "file".to_c_str();
|
|
||||||
let FC_FILE = FC_FILE_C.as_mut_ptr();
|
|
||||||
let mut file: *mut FcChar8 = ptr::mut_null();
|
let mut file: *mut FcChar8 = ptr::mut_null();
|
||||||
let file = if FcPatternGetString(*font, FC_FILE, 0, &mut file) == FcResultMatch {
|
let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut i8, 0, &mut file) == FcResultMatch {
|
||||||
string::raw::from_buf(file as *const i8 as *const u8)
|
string::raw::from_buf(file as *const i8 as *const u8)
|
||||||
} else {
|
} else {
|
||||||
fail!();
|
fail!();
|
||||||
};
|
};
|
||||||
let mut FC_INDEX_C = "index".to_c_str();
|
|
||||||
let FC_INDEX = FC_INDEX_C.as_mut_ptr();
|
|
||||||
let mut index: libc::c_int = 0;
|
let mut index: libc::c_int = 0;
|
||||||
let index = if FcPatternGetInteger(*font, FC_INDEX, 0, &mut index) == FcResultMatch {
|
let index = if FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut i8, 0, &mut index) == FcResultMatch {
|
||||||
index
|
index
|
||||||
} else {
|
} else {
|
||||||
fail!();
|
fail!();
|
||||||
|
@ -100,6 +96,34 @@ pub fn get_variations_for_family(family_name: &str, callback: |String|) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_system_default_family(generic_name: &str) -> Option<String> {
|
||||||
|
let mut generic_name_c = generic_name.to_c_str();
|
||||||
|
let generic_name_ptr = generic_name_c.as_mut_ptr();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);
|
||||||
|
|
||||||
|
FcConfigSubstitute(ptr::mut_null(), pattern, FcMatchPattern);
|
||||||
|
FcDefaultSubstitute(pattern);
|
||||||
|
|
||||||
|
let mut result = 0;
|
||||||
|
let family_match = FcFontMatch(ptr::mut_null(), pattern, &mut result);
|
||||||
|
|
||||||
|
let family_name = if result == FcResultMatch {
|
||||||
|
let mut match_string: *mut FcChar8 = ptr::mut_null();
|
||||||
|
FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut i8, 0, &mut match_string);
|
||||||
|
let result = string::raw::from_buf(match_string as *const i8 as *const u8);
|
||||||
|
FcPatternDestroy(family_match);
|
||||||
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
FcPatternDestroy(pattern);
|
||||||
|
family_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os="linux")]
|
#[cfg(target_os="linux")]
|
||||||
pub fn get_last_resort_font_families() -> Vec<String> {
|
pub fn get_last_resort_font_families() -> Vec<String> {
|
||||||
vec!(
|
vec!(
|
||||||
|
|
|
@ -32,6 +32,10 @@ pub fn get_variations_for_family(family_name: &str, callback: |String|) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_system_default_family(_generic_name: &str) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_last_resort_font_families() -> Vec<String> {
|
pub fn get_last_resort_font_families() -> Vec<String> {
|
||||||
vec!("Arial Unicode MS".to_string(), "Arial".to_string())
|
vec!("Arial Unicode MS".to_string(), "Arial".to_string())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue