mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Improve quality of font rendering on Linux (and Android).
The freetype hinting only works on integer pixel sizes. For this reason, the advance width metrics for a font of size 12.99 are the same as the advance metrics for a font of size 12.0. This results in small fonts appearing to overlap slightly, which is particularly noticeable on parts of Wikipedia. Round the font size up to a pixel boundary inside the freetype system. Also fetch the system default fonts for the generic font families rather than hard coding them. These two changes make the font rendering on Linux very close to the Firefox font rendering on Wikipedia.
This commit is contained in:
parent
05f2d0ca83
commit
cc24e68186
4 changed files with 57 additions and 11 deletions
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
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_last_resort_font_families;
|
||||
use platform::font_context::FontContextHandle;
|
||||
|
@ -90,6 +91,16 @@ struct FontCache {
|
|||
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 {
|
||||
fn run(&mut self) {
|
||||
loop {
|
||||
|
@ -223,11 +234,11 @@ impl FontCacheTask {
|
|||
spawn(proc() {
|
||||
// TODO: Allow users to specify these.
|
||||
let mut generic_fonts = HashMap::with_capacity(5);
|
||||
generic_fonts.insert("serif".to_string(), "Times New Roman".to_string());
|
||||
generic_fonts.insert("sans-serif".to_string(), "Arial".to_string());
|
||||
generic_fonts.insert("cursive".to_string(), "Apple Chancery".to_string());
|
||||
generic_fonts.insert("fantasy".to_string(), "Papyrus".to_string());
|
||||
generic_fonts.insert("monospace".to_string(), "Menlo".to_string());
|
||||
add_generic_font(&mut generic_fonts, "serif", "Times New Roman");
|
||||
add_generic_font(&mut generic_fonts, "sans-serif", "Arial");
|
||||
add_generic_font(&mut generic_fonts, "cursive", "Apple Chancery");
|
||||
add_generic_font(&mut generic_fonts, "fantasy", "Papyrus");
|
||||
add_generic_font(&mut generic_fonts, "monospace", "Menlo");
|
||||
|
||||
let mut cache = FontCache {
|
||||
port: port,
|
||||
|
|
|
@ -260,13 +260,10 @@ impl FontHandleMethods for FontHandle {
|
|||
|
||||
impl<'a> FontHandle {
|
||||
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_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
||||
let h_dpi = 72;
|
||||
let v_dpi = 72;
|
||||
let char_width = float_to_fixed_ft((0.5f64 + pt_size).floor()) as FT_F26Dot6;
|
||||
|
||||
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(()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,12 @@ extern crate fontconfig;
|
|||
|
||||
use fontconfig::fontconfig::{FcChar8, FcResultMatch, FcSetSystem};
|
||||
use fontconfig::fontconfig::{
|
||||
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
|
||||
FcConfigGetCurrent, FcConfigGetFonts,
|
||||
FcConfigSubstitute, FcDefaultSubstitute,
|
||||
FcFontMatch,
|
||||
FcNameParse, FcPatternGetString,
|
||||
FcPatternDestroy, FcFontSetDestroy,
|
||||
FcMatchPattern,
|
||||
FcPatternCreate, FcPatternAddString,
|
||||
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
|
||||
FcObjectSetAdd, FcPatternGetInteger
|
||||
|
@ -100,6 +104,36 @@ 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 FC_FAMILY_C = "family".to_c_str();
|
||||
let FC_FAMILY = FC_FAMILY_C.as_mut_ptr();
|
||||
let mut match_string: *mut FcChar8 = ptr::mut_null();
|
||||
FcPatternGetString(family_match, FC_FAMILY, 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")]
|
||||
pub fn get_last_resort_font_families() -> Vec<String> {
|
||||
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> {
|
||||
vec!("Arial Unicode MS".to_string(), "Arial".to_string())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue