Format gfx platform #21373

This commit is contained in:
kingdido999 2018-09-05 08:39:05 +08:00
parent 5063ac465b
commit c57c99d9f7
13 changed files with 496 additions and 372 deletions

View file

@ -116,21 +116,18 @@ struct FontFamily {
struct FontAlias {
from: String,
to: String,
weight: Option<i32>
weight: Option<i32>,
}
struct FontList {
families: Vec<FontFamily>,
aliases: Vec<FontAlias>
aliases: Vec<FontAlias>,
}
impl FontList {
fn new() -> FontList {
// Possible paths containing the font mapping xml file.
let paths = [
"/etc/fonts.xml",
"/system/etc/system_fonts.xml"
];
let paths = ["/etc/fonts.xml", "/system/etc/system_fonts.xml"];
// Try to load and parse paths until one of them success.
let mut result = None;
@ -146,7 +143,7 @@ impl FontList {
None => FontList {
families: Self::fallback_font_families(),
aliases: Vec::new(),
}
},
}
}
@ -154,25 +151,26 @@ impl FontList {
fn from_path(path: &str) -> Option<FontList> {
let xml = match Self::load_file(path) {
Ok(xml) => xml,
_=> { return None; },
_ => {
return None;
},
};
let dom: RcDom = parse_document(RcDom::default(), Default::default())
.one(xml);
let dom: RcDom = parse_document(RcDom::default(), Default::default()).one(xml);
let doc = &dom.document;
// find familyset root node
let children = doc.children.borrow();
let familyset = children.iter().find(|child| {
match child.data {
NodeData::Element { ref name, .. } => &*name.local == "familyset",
_ => false,
}
let familyset = children.iter().find(|child| match child.data {
NodeData::Element { ref name, .. } => &*name.local == "familyset",
_ => false,
});
let familyset = match familyset {
Some(node) => node,
_ => { return None; }
_ => {
return None;
},
};
// Parse familyset node
@ -181,7 +179,11 @@ impl FontList {
for node in familyset.children.borrow().iter() {
match node.data {
NodeData::Element { ref name, ref attrs, .. } => {
NodeData::Element {
ref name,
ref attrs,
..
} => {
if &*name.local == "family" {
Self::parse_family(&node, attrs, &mut families);
} else if &*name.local == "alias" {
@ -191,13 +193,13 @@ impl FontList {
}
}
},
_=> {}
_ => {},
}
}
Some(FontList {
families: families,
aliases: aliases
aliases: aliases,
})
}
@ -209,17 +211,16 @@ impl FontList {
("Droid Sans", "DroidSans.ttf"),
];
alternatives.iter().filter(|item| {
Path::new(&Self::font_absolute_path(item.1)).exists()
}).map(|item| {
FontFamily {
alternatives
.iter()
.filter(|item| Path::new(&Self::font_absolute_path(item.1)).exists())
.map(|item| FontFamily {
name: item.0.into(),
fonts: vec![Font {
filename: item.1.into(),
weight: None,
}]
}
}). collect()
}],
}).collect()
}
// All Android fonts are located in /system/fonts
@ -227,15 +228,14 @@ impl FontList {
format!("/system/fonts/{}", filename)
}
fn find_family(&self, name: &str) -> Option<&FontFamily>{
fn find_family(&self, name: &str) -> Option<&FontFamily> {
self.families.iter().find(|f| f.name == name)
}
fn find_alias(&self, name: &str) -> Option<&FontAlias>{
fn find_alias(&self, name: &str) -> Option<&FontAlias> {
self.aliases.iter().find(|f| f.from == name)
}
fn load_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut content = String::new();
@ -253,14 +253,16 @@ impl FontList {
// <font weight="300" style="italic">Roboto-LightItalic.ttf</font>
// <font weight="400" style="normal">Roboto-Regular.ttf</font>
// </family>
fn parse_family(familyset: &Node, attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<FontFamily>) {
fn parse_family(familyset: &Node, attrs: &RefCell<Vec<Attribute>>, out: &mut Vec<FontFamily>) {
// Fallback to old Android API v17 xml format if required
let using_api_17 = familyset.children.borrow().iter().any(|node| {
match node.data {
let using_api_17 = familyset
.children
.borrow()
.iter()
.any(|node| match node.data {
NodeData::Element { ref name, .. } => &*name.local == "nameset",
_=> false,
}
});
_ => false,
});
if using_api_17 {
Self::parse_family_v17(familyset, out);
return;
@ -269,25 +271,31 @@ impl FontList {
// Parse family name
let name = match Self::find_attrib("name", attrs) {
Some(name) => name,
_ => { return; },
_ => {
return;
},
};
let mut fonts = Vec::new();
// Parse font variants
for node in familyset.children.borrow().iter() {
match node.data {
NodeData::Element { ref name, ref attrs, .. } => {
NodeData::Element {
ref name,
ref attrs,
..
} => {
if &*name.local == "font" {
FontList::parse_font(&node, attrs, &mut fonts);
}
},
_=> {}
_ => {},
}
}
out.push(FontFamily {
name: name,
fonts: fonts
fonts: fonts,
});
}
@ -308,7 +316,7 @@ impl FontList {
// <file>Roboto-BoldItalic.ttf</file>
// </fileset>
// </family>
fn parse_family_v17(familyset: &Node, out:&mut Vec<FontFamily>) {
fn parse_family_v17(familyset: &Node, out: &mut Vec<FontFamily>) {
let mut nameset = Vec::new();
let mut fileset = Vec::new();
for node in familyset.children.borrow().iter() {
@ -320,21 +328,23 @@ impl FontList {
Self::collect_contents_with_tag(node, "file", &mut fileset);
}
},
_=> {}
_ => {},
}
}
// Create a families for each variation
for name in nameset {
let fonts: Vec<Font> = fileset.iter().map(|f| Font {
filename: f.clone(),
weight: None,
}).collect();
let fonts: Vec<Font> = fileset
.iter()
.map(|f| Font {
filename: f.clone(),
weight: None,
}).collect();
if !fonts.is_empty() {
out.push(FontFamily {
name: name,
fonts: fonts
fonts: fonts,
})
}
}
@ -342,11 +352,13 @@ impl FontList {
// Example:
// <font weight="100" style="normal">Roboto-Thin.ttf</font>
fn parse_font(node: &Node, attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<Font>) {
fn parse_font(node: &Node, attrs: &RefCell<Vec<Attribute>>, out: &mut Vec<Font>) {
// Parse font filename
let filename = match Self::text_content(node) {
Some(filename) => filename,
_ => { return; }
_ => {
return;
},
};
// Parse font weight
@ -367,17 +379,21 @@ impl FontList {
// <alias name="helvetica" to="sans-serif" />
// <alias name="tahoma" to="sans-serif" />
// <alias name="verdana" to="sans-serif" />
fn parse_alias(attrs: &RefCell<Vec<Attribute>>, out:&mut Vec<FontAlias>) {
fn parse_alias(attrs: &RefCell<Vec<Attribute>>, out: &mut Vec<FontAlias>) {
// Parse alias name and referenced font
let from = match Self::find_attrib("name", attrs) {
Some(from) => from,
_ => { return; },
_ => {
return;
},
};
// Parse referenced font
let to = match Self::find_attrib("to", attrs) {
Some(to) => to,
_ => { return; },
_ => {
return;
},
};
// Parse optional weight filter
@ -391,23 +407,28 @@ impl FontList {
}
fn find_attrib(name: &str, attrs: &RefCell<Vec<Attribute>>) -> Option<String> {
attrs.borrow().iter().find(|attr| &*attr.name.local == name).map(|s| String::from(&s.value))
attrs
.borrow()
.iter()
.find(|attr| &*attr.name.local == name)
.map(|s| String::from(&s.value))
}
fn text_content(node: &Node) -> Option<String> {
node.children.borrow().get(0).and_then(|child| {
match child.data {
node.children
.borrow()
.get(0)
.and_then(|child| match child.data {
NodeData::Text { ref contents } => {
let mut result = String::new();
result.push_str(&contents.borrow());
Some(result)
},
_ => None
}
})
_ => None,
})
}
fn collect_contents_with_tag(node: &Node, tag: &str, out:&mut Vec<String>) {
fn collect_contents_with_tag(node: &Node, tag: &str, out: &mut Vec<String>) {
for child in node.children.borrow().iter() {
match child.data {
NodeData::Element { ref name, .. } => {
@ -417,14 +438,17 @@ impl FontList {
}
}
},
_=> {}
_ => {},
}
}
}
}
// Functions used by FontCacheThread
pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),
{
for family in &FONT_LIST.families {
callback(family.name.clone());
}
@ -434,7 +458,8 @@ pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
}
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
where F: FnMut(String)
where
F: FnMut(String),
{
if let Some(family) = FONT_LIST.find_family(family_name) {
for font in &family.fonts {
@ -453,7 +478,7 @@ pub fn for_each_variation<F>(family_name: &str, mut callback: F)
callback(FontList::font_absolute_path(&font.filename))
}
},
_ => {}
_ => {},
}
}
}
@ -473,46 +498,44 @@ pub fn system_default_family(generic_name: &str) -> Option<String> {
// Based on gfxAndroidPlatform::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
let mut families = vec!();
let mut families = vec![];
if let Some(block) = codepoint.and_then(|c| c.block()) {
match block {
UnicodeBlock::Armenian => {
families.push("Droid Sans Armenian");
}
},
UnicodeBlock::Hebrew => {
families.push("Droid Sans Hebrew");
}
},
UnicodeBlock::Arabic => {
families.push("Droid Sans Arabic");
}
},
UnicodeBlock::Devanagari => {
families.push("Noto Sans Devanagari");
families.push("Droid Sans Devanagari");
}
},
UnicodeBlock::Tamil => {
families.push("Noto Sans Tamil");
families.push("Droid Sans Tamil");
}
},
UnicodeBlock::Thai => {
families.push("Noto Sans Thai");
families.push("Droid Sans Thai");
}
},
UnicodeBlock::Georgian |
UnicodeBlock::GeorgianSupplement => {
UnicodeBlock::Georgian | UnicodeBlock::GeorgianSupplement => {
families.push("Droid Sans Georgian");
}
},
UnicodeBlock::Ethiopic |
UnicodeBlock::EthiopicSupplement => {
UnicodeBlock::Ethiopic | UnicodeBlock::EthiopicSupplement => {
families.push("Droid Sans Ethiopic");
}
},
_ => {
if is_cjk(codepoint.unwrap()) {
@ -520,7 +543,7 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Noto Sans CJK JP");
families.push("Droid Sans Japanese");
}
}
},
}
}

View file

@ -98,14 +98,21 @@ fn create_face(
let face_index = 0 as FT_Long;
let result = if let Some(ref bytes) = template.bytes {
FT_New_Memory_Face(lib, bytes.as_ptr(), bytes.len() as FT_Long, face_index, &mut face)
FT_New_Memory_Face(
lib,
bytes.as_ptr(),
bytes.len() as FT_Long,
face_index,
&mut face,
)
} else {
// This will trigger a synchronous file read in the layout thread, which we may want to
// revisit at some point. See discussion here:
//
// https://github.com/servo/servo/pull/20506#issuecomment-378838800
let filename = CString::new(&*template.identifier).expect("filename contains NUL byte!");
let filename =
CString::new(&*template.identifier).expect("filename contains NUL byte!");
FT_New_Face(lib, filename.as_ptr(), face_index, &mut face)
};
@ -122,25 +129,27 @@ fn create_face(
}
impl FontHandleMethods for FontHandle {
fn new_from_template(fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>)
-> Result<FontHandle, ()> {
fn new_from_template(
fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<FontHandle, ()> {
let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); }
if ft_ctx.is_null() {
return Err(());
}
let face = create_face(ft_ctx, &template, pt_size)?;
let mut handle = FontHandle {
face: face,
font_data: template.clone(),
handle: fctx.clone(),
can_do_fast_shaping: false,
face: face,
font_data: template.clone(),
handle: fctx.clone(),
can_do_fast_shaping: false,
};
// TODO (#11310): Implement basic support for GPOS and GSUB.
handle.can_do_fast_shaping = handle.has_table(KERN) &&
!handle.has_table(GPOS) &&
!handle.has_table(GSUB);
handle.can_do_fast_shaping =
handle.has_table(KERN) && !handle.has_table(GPOS) && !handle.has_table(GSUB);
Ok(handle)
}
@ -203,7 +212,7 @@ impl FontHandleMethods for FontHandle {
7 => FontStretchKeyword::Expanded,
8 => FontStretchKeyword::ExtraExpanded,
9 => FontStretchKeyword::UltraExpanded,
_ => FontStretchKeyword::Normal
_ => FontStretchKeyword::Normal,
}
} else {
FontStretchKeyword::Normal
@ -218,20 +227,26 @@ impl FontHandleMethods for FontHandle {
if idx != 0 as FT_UInt {
Some(idx as GlyphId)
} else {
debug!("Invalid codepoint: U+{:04X} ('{}')", codepoint as u32, codepoint);
debug!(
"Invalid codepoint: U+{:04X} ('{}')",
codepoint as u32, codepoint
);
None
}
}
}
fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId)
-> FractionalPixel {
fn glyph_h_kerning(&self, first_glyph: GlyphId, second_glyph: GlyphId) -> FractionalPixel {
assert!(!self.face.is_null());
let mut delta = FT_Vector { x: 0, y: 0 };
unsafe {
FT_Get_Kerning(self.face, first_glyph, second_glyph,
FT_Kerning_Mode::FT_KERNING_DEFAULT as FT_UInt,
&mut delta);
FT_Get_Kerning(
self.face,
first_glyph,
second_glyph,
FT_Kerning_Mode::FT_KERNING_DEFAULT as FT_UInt,
&mut delta,
);
}
fixed_to_float_ft(delta.x as i32)
}
@ -243,9 +258,7 @@ impl FontHandleMethods for FontHandle {
fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
assert!(!self.face.is_null());
unsafe {
let res = FT_Load_Glyph(self.face,
glyph as FT_UInt,
GLYPH_LOAD_FLAGS);
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, GLYPH_LOAD_FLAGS);
if succeeded(res) {
let void_glyph = (*self.face).glyph;
let slot: FT_GlyphSlot = mem::transmute(void_glyph);
@ -291,23 +304,24 @@ impl FontHandleMethods for FontHandle {
x_height = self.font_units_to_au(os2.sx_height as f64);
}
let average_advance = self.glyph_index('0')
.and_then(|idx| self.glyph_h_advance(idx))
.map_or(max_advance, |advance| self.font_units_to_au(advance));
let average_advance = self
.glyph_index('0')
.and_then(|idx| self.glyph_h_advance(idx))
.map_or(max_advance, |advance| self.font_units_to_au(advance));
let metrics = FontMetrics {
underline_size: underline_size,
underline_size: underline_size,
underline_offset: underline_offset,
strikeout_size: strikeout_size,
strikeout_size: strikeout_size,
strikeout_offset: strikeout_offset,
leading: leading,
x_height: x_height,
em_size: em_size,
ascent: ascent,
descent: -descent, // linux font's seem to use the opposite sign from mac
max_advance: max_advance,
average_advance: average_advance,
line_gap: height,
leading: leading,
x_height: x_height,
em_size: em_size,
ascent: ascent,
descent: -descent, // linux font's seem to use the opposite sign from mac
max_advance: max_advance,
average_advance: average_advance,
line_gap: height,
};
debug!("Font metrics (@{}px): {:?}", em_size.to_f32_px(), metrics);
@ -320,13 +334,25 @@ impl FontHandleMethods for FontHandle {
unsafe {
// Get the length
let mut len = 0;
if !succeeded(FT_Load_Sfnt_Table(self.face, tag, 0, ptr::null_mut(), &mut len)) {
return None
if !succeeded(FT_Load_Sfnt_Table(
self.face,
tag,
0,
ptr::null_mut(),
&mut len,
)) {
return None;
}
// Get the bytes
let mut buf = vec![0u8; len as usize];
if !succeeded(FT_Load_Sfnt_Table(self.face, tag, 0, buf.as_mut_ptr(), &mut len)) {
return None
if !succeeded(FT_Load_Sfnt_Table(
self.face,
tag,
0,
buf.as_mut_ptr(),
&mut len,
)) {
return None;
}
Some(FontTable { buffer: buf })
}
@ -338,25 +364,33 @@ impl FontHandleMethods for FontHandle {
}
impl<'a> FontHandle {
fn set_char_size(face: FT_Face, pt_size: Au) -> Result<(), ()>{
fn set_char_size(face: FT_Face, pt_size: Au) -> Result<(), ()> {
let char_size = pt_size.to_f64_px() * 64.0 + 0.5;
unsafe {
let result = FT_Set_Char_Size(face, char_size as FT_F26Dot6, 0, 0, 0);
if succeeded(result) { Ok(()) } else { Err(()) }
if succeeded(result) {
Ok(())
} else {
Err(())
}
}
}
fn has_table(&self, tag: FontTableTag) -> bool {
unsafe {
succeeded(FT_Load_Sfnt_Table(self.face, tag as FT_ULong, 0, ptr::null_mut(), &mut 0))
succeeded(FT_Load_Sfnt_Table(
self.face,
tag as FT_ULong,
0,
ptr::null_mut(),
&mut 0,
))
}
}
fn face_rec_mut(&'a self) -> &'a mut FT_FaceRec {
unsafe {
&mut (*self.face)
}
unsafe { &mut (*self.face) }
}
fn font_units_to_au(&self, value: f64) -> Au {
@ -378,11 +412,12 @@ impl<'a> FontHandle {
fn os2_table(&self) -> Option<OS2Table> {
unsafe {
let os2 = FT_Get_Sfnt_Table(self.face_rec_mut(), FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2;
let os2 =
FT_Get_Sfnt_Table(self.face_rec_mut(), FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2;
let valid = !os2.is_null() && (*os2).version != 0xffff;
if !valid {
return None
return None;
}
Some(OS2Table {

View file

@ -23,10 +23,10 @@ pub struct User {
size: usize,
}
extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
extern "C" fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
unsafe {
let ptr = malloc(req_size as usize);
let ptr = ptr as *mut c_void; // libc::c_void vs std::os::raw::c_void
let ptr = ptr as *mut c_void; // libc::c_void vs std::os::raw::c_void
let actual_size = usable_size(ptr);
let user = (*mem).user as *mut User;
(*user).size += actual_size;
@ -34,7 +34,7 @@ extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
}
}
extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
extern "C" fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
unsafe {
let actual_size = usable_size(ptr);
let user = (*mem).user as *mut User;
@ -43,8 +43,12 @@ extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
}
}
extern fn ft_realloc(mem: FT_Memory, _old_size: c_long, new_req_size: c_long,
old_ptr: *mut c_void) -> *mut c_void {
extern "C" fn ft_realloc(
mem: FT_Memory,
_old_size: c_long,
new_req_size: c_long,
old_ptr: *mut c_void,
) -> *mut c_void {
unsafe {
let old_actual_size = usable_size(old_ptr);
let new_ptr = realloc(old_ptr as *mut _, new_req_size as usize);
@ -108,9 +112,7 @@ impl MallocSizeOf for FontContextHandle {
impl FontContextHandle {
pub fn new() -> FontContextHandle {
let user = Box::into_raw(Box::new(User {
size: 0,
}));
let user = Box::into_raw(Box::new(User { size: 0 }));
let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
user: user as *mut c_void,
alloc: Some(ft_alloc),
@ -121,12 +123,18 @@ impl FontContextHandle {
let mut ctx: FT_Library = ptr::null_mut();
let result = FT_New_Library(mem, &mut ctx);
if !succeeded(result) { panic!("Unable to initialize FreeType library"); }
if !succeeded(result) {
panic!("Unable to initialize FreeType library");
}
FT_Add_Default_Modules(ctx);
FontContextHandle {
ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
ctx: Rc::new(FreeTypeLibraryHandle {
ctx: ctx,
mem: mem,
user: user,
}),
}
}
}

View file

@ -20,7 +20,10 @@ static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";
static FC_FONTFORMAT: &'static [u8] = b"fontformat\0";
pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),
{
unsafe {
let config = FcConfigGetCurrent();
let font_set = FcConfigGetFonts(config, FcSetSystem);
@ -29,19 +32,21 @@ pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
let mut family: *mut FcChar8 = ptr::null_mut();
let mut format: *mut FcChar8 = ptr::null_mut();
let mut v: c_int = 0;
if FcPatternGetString(*font, FC_FONTFORMAT.as_ptr() as *mut c_char, v, &mut format) != FcResultMatch {
if FcPatternGetString(*font, FC_FONTFORMAT.as_ptr() as *mut c_char, v, &mut format) !=
FcResultMatch
{
continue;
}
// Skip bitmap fonts. They aren't supported by FreeType.
let fontformat = c_str_to_string(format as *const c_char);
if fontformat != "TrueType" &&
fontformat != "CFF" &&
fontformat != "Type 1" {
if fontformat != "TrueType" && fontformat != "CFF" && fontformat != "Type 1" {
continue;
}
while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) ==
FcResultMatch
{
let family_name = c_str_to_string(family as *const c_char);
callback(family_name);
v += 1;
@ -51,7 +56,8 @@ pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
}
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
where F: FnMut(String)
where
F: FnMut(String),
{
debug!("getting variations for {}", family_name);
unsafe {
@ -62,7 +68,11 @@ pub fn for_each_variation<F>(family_name: &str, mut callback: F)
assert!(!pattern.is_null());
let family_name_c = CString::new(family_name).unwrap();
let family_name = family_name_c.as_ptr();
let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
let ok = FcPatternAddString(
pattern,
FC_FAMILY.as_ptr() as *mut c_char,
family_name as *mut FcChar8,
);
assert_ne!(ok, 0);
let object_set = FcObjectSetCreate();
@ -85,7 +95,8 @@ pub fn for_each_variation<F>(family_name: &str, mut callback: F)
panic!();
};
let mut index: libc::c_int = 0;
let result = FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index);
let result =
FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index);
let index = if result == FcResultMatch {
index
} else {
@ -119,7 +130,12 @@ pub fn system_default_family(generic_name: &str) -> Option<String> {
let family_name = if result == FcResultMatch {
let mut match_string: *mut FcChar8 = ptr::null_mut();
FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
FcPatternGetString(
family_match,
FC_FAMILY.as_ptr() as *mut c_char,
0,
&mut match_string,
);
let result = c_str_to_string(match_string as *const c_char);
FcPatternDestroy(family_match);
Some(result)
@ -136,12 +152,7 @@ pub static SANS_SERIF_FONT_FAMILY: &'static str = "DejaVu Sans";
// Based on gfxPlatformGtk::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
let mut families = vec!(
"DejaVu Serif",
"FreeSerif",
"DejaVu Sans",
"FreeSans",
);
let mut families = vec!["DejaVu Serif", "FreeSerif", "DejaVu Sans", "FreeSans"];
if let Some(codepoint) = codepoint {
if is_cjk(codepoint) {

View file

@ -15,7 +15,6 @@ use webrender_api::NativeFontHandle;
#[derive(Deserialize, Serialize)]
pub struct FontTemplateData {
// If you add members here, review the Debug impl below
pub bytes: Option<Vec<u8>>,
pub identifier: Atom,
}
@ -23,9 +22,11 @@ pub struct FontTemplateData {
impl fmt::Debug for FontTemplateData {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("FontTemplateData")
.field("bytes", &self.bytes.as_ref().map(|b| format!("[{} bytes]", b.len())))
.field("identifier", &self.identifier)
.finish()
.field(
"bytes",
&self.bytes.as_ref().map(|b| format!("[{} bytes]", b.len())),
).field("identifier", &self.identifier)
.finish()
}
}

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// Implementation of Quartz (CoreGraphics) fonts.
use app_units::Au;
use byteorder::{BigEndian, ByteOrder};
use core_foundation::base::CFIndex;
@ -111,8 +110,8 @@ impl FontHandle {
return None;
}
let pt_per_font_unit = self.ctfont.pt_size() as f64 /
self.ctfont.units_per_em() as f64;
let pt_per_font_unit =
self.ctfont.pt_size() as f64 / self.ctfont.units_per_em() as f64;
result.px_per_font_unit = pt_to_px(pt_per_font_unit);
}
start = end;
@ -160,15 +159,15 @@ impl fmt::Debug for CachedKernTable {
}
}
impl FontHandleMethods for FontHandle {
fn new_from_template(_fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>)
-> Result<FontHandle, ()> {
fn new_from_template(
_fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<FontHandle, ()> {
let size = match pt_size {
Some(s) => s.to_f64_px(),
None => 0.0
None => 0.0,
};
match template.ctfont(size) {
Some(ref ctfont) => {
@ -181,13 +180,11 @@ impl FontHandleMethods for FontHandle {
handle.h_kern_subtable = handle.find_h_kern_subtable();
// TODO (#11310): Implement basic support for GPOS and GSUB.
handle.can_do_fast_shaping = handle.h_kern_subtable.is_some() &&
handle.table_for_tag(GPOS).is_none() &&
handle.table_for_tag(GSUB).is_none();
handle.table_for_tag(GPOS).is_none() &&
handle.table_for_tag(GSUB).is_none();
Ok(handle)
}
None => {
Err(())
}
},
None => Err(()),
}
}
@ -213,13 +210,13 @@ impl FontHandleMethods for FontHandle {
}
fn boldness(&self) -> FontWeight {
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to
// align with css-fonts-4's range of [1, 1000].
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to
// align with css-fonts-4's range of [1, 1000].
let normalized = if normalized <= 0.0 {
4.0 + normalized * 3.0 // [1.0, 4.0]
4.0 + normalized * 3.0 // [1.0, 4.0]
} else {
4.0 + normalized * 5.0 // [4.0, 9.0]
4.0 + normalized * 5.0 // [4.0, 9.0]
}; // [1.0, 9.0], centered on 4.0
FontWeight(normalized as f32 * 100.)
}
@ -228,7 +225,7 @@ impl FontHandleMethods for FontHandle {
use style::values::computed::Percentage;
use style::values::generics::NonNegative;
let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0]
let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0]
FontStretch(NonNegative(Percentage(normalized as f32 + 1.0)))
}
@ -237,9 +234,9 @@ impl FontHandleMethods for FontHandle {
let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph];
let count: CFIndex = 1;
let result = self.ctfont.get_glyphs_for_characters(&characters[0],
&mut glyphs[0],
count);
let result = self
.ctfont
.get_glyphs_for_characters(&characters[0], &mut glyphs[0], count);
if !result {
// No glyph for this character
@ -265,10 +262,12 @@ impl FontHandleMethods for FontHandle {
fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
let glyphs = [glyph as CGGlyph];
let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation,
&glyphs[0],
ptr::null_mut(),
1);
let advance = self.ctfont.get_advances_for_glyphs(
kCTFontDefaultOrientation,
&glyphs[0],
ptr::null_mut(),
1,
);
Some(advance as FractionalPixel)
}
@ -283,39 +282,42 @@ impl FontHandleMethods for FontHandle {
let line_gap = (ascent + descent + leading + 0.5).floor();
let max_advance_width = au_from_pt(bounding_rect.size.width as f64);
let average_advance = self.glyph_index('0')
.and_then(|idx| self.glyph_h_advance(idx))
.map(Au::from_f64_px)
.unwrap_or(max_advance_width);
let average_advance = self
.glyph_index('0')
.and_then(|idx| self.glyph_h_advance(idx))
.map(Au::from_f64_px)
.unwrap_or(max_advance_width);
let metrics = FontMetrics {
underline_size: au_from_pt(self.ctfont.underline_thickness() as f64),
underline_size: au_from_pt(self.ctfont.underline_thickness() as f64),
// TODO(Issue #201): underline metrics are not reliable. Have to pull out of font table
// directly.
//
// see also: https://bugs.webkit.org/show_bug.cgi?id=16768
// see also: https://bugreports.qt-project.org/browse/QTBUG-13364
underline_offset: au_from_pt(self.ctfont.underline_position() as f64),
strikeout_size: Au(0), // FIXME(Issue #942)
strikeout_size: Au(0), // FIXME(Issue #942)
strikeout_offset: Au(0), // FIXME(Issue #942)
leading: au_from_pt(leading),
x_height: au_from_pt((self.ctfont.x_height() as f64) * scale),
em_size: em_size,
ascent: au_from_pt(ascent * scale),
descent: au_from_pt(descent * scale),
max_advance: max_advance_width,
average_advance: average_advance,
line_gap: Au::from_f64_px(line_gap),
leading: au_from_pt(leading),
x_height: au_from_pt((self.ctfont.x_height() as f64) * scale),
em_size: em_size,
ascent: au_from_pt(ascent * scale),
descent: au_from_pt(descent * scale),
max_advance: max_advance_width,
average_advance: average_advance,
line_gap: Au::from_f64_px(line_gap),
};
debug!("Font metrics (@{} pt): {:?}", self.ctfont.pt_size() as f64, metrics);
debug!(
"Font metrics (@{} pt): {:?}",
self.ctfont.pt_size() as f64,
metrics
);
metrics
}
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
let result: Option<CFData> = self.ctfont.get_font_table(tag);
result.and_then(|data| {
Some(FontTable::wrap(data))
})
result.and_then(|data| Some(FontTable::wrap(data)))
}
fn identifier(&self) -> Atom {

View file

@ -6,7 +6,7 @@ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
#[derive(Clone, Debug)]
pub struct FontContextHandle {
ctx: ()
ctx: (),
}
impl FontContextHandle {

View file

@ -6,14 +6,20 @@ use core_text;
use text::util::unicode_plane;
use ucd::{Codepoint, UnicodeBlock};
pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),
{
let family_names = core_text::font_collection::get_family_names();
for family_name in family_names.iter() {
callback(family_name.to_string());
}
}
pub fn for_each_variation<F>(family_name: &str, mut callback: F) where F: FnMut(String) {
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
where
F: FnMut(String),
{
debug!("Looking for faces of family: {}", family_name);
let family_collection = core_text::font_collection::create_for_family(family_name);
@ -31,7 +37,7 @@ pub fn system_default_family(_generic_name: &str) -> Option<String> {
// Based on gfxPlatformMac::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
let mut families = vec!("Lucida Grande");
let mut families = vec!["Lucida Grande"];
if let Some(codepoint) = codepoint {
match unicode_plane(codepoint) {
@ -45,66 +51,65 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::Thaana |
UnicodeBlock::NKo => {
families.push("Geeza Pro");
}
},
UnicodeBlock::Devanagari => {
families.push("Devanagari Sangam MN");
}
},
UnicodeBlock::Gurmukhi => {
families.push("Gurmukhi MN");
}
},
UnicodeBlock::Gujarati => {
families.push("Gujarati Sangam MN");
}
},
UnicodeBlock::Tamil => {
families.push("Tamil MN");
}
},
UnicodeBlock::Lao => {
families.push("Lao MN");
}
},
UnicodeBlock::Tibetan => {
families.push("Songti SC");
}
},
UnicodeBlock::Myanmar => {
families.push("Myanmar MN");
}
},
UnicodeBlock::Ethiopic |
UnicodeBlock::EthiopicSupplement |
UnicodeBlock::EthiopicExtended |
UnicodeBlock::EthiopicExtendedA => {
families.push("Kefa");
}
},
UnicodeBlock::Cherokee => {
families.push("Plantagenet Cherokee");
}
},
UnicodeBlock::UnifiedCanadianAboriginalSyllabics |
UnicodeBlock::UnifiedCanadianAboriginalSyllabicsExtended => {
families.push("Euphemia UCAS");
}
},
UnicodeBlock::Mongolian |
UnicodeBlock::YiSyllables |
UnicodeBlock::YiRadicals => {
families.push("STHeiti");
}
},
UnicodeBlock::Khmer |
UnicodeBlock::KhmerSymbols => {
UnicodeBlock::Khmer | UnicodeBlock::KhmerSymbols => {
families.push("Khmer MN");
}
},
UnicodeBlock::TaiLe => {
families.push("Microsoft Tai Le");
}
},
UnicodeBlock::GeneralPunctuation |
UnicodeBlock::SuperscriptsandSubscripts |
@ -134,11 +139,11 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Apple Symbols");
families.push("Menlo");
families.push("STIXGeneral");
}
},
UnicodeBlock::BraillePatterns => {
families.push("Apple Braille");
}
},
UnicodeBlock::Bopomofo |
UnicodeBlock::HangulCompatibilityJamo |
@ -147,7 +152,7 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::CJKStrokes |
UnicodeBlock::KatakanaPhoneticExtensions => {
families.push("Hiragino Sans GB");
}
},
UnicodeBlock::YijingHexagramSymbols |
UnicodeBlock::CyrillicExtendedB |
@ -158,27 +163,27 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::HalfwidthandFullwidthForms |
UnicodeBlock::Specials => {
families.push("Apple Symbols");
}
},
_ => {}
_ => {},
}
}
}
},
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
1 => {
families.push("Apple Symbols");
families.push("STIXGeneral");
}
},
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Ideographic_Plane
2 => {
// Systems with MS Office may have these fonts
families.push("MingLiU-ExtB");
families.push("SimSun-ExtB");
}
},
_ => {}
_ => {},
}
}

View file

@ -27,7 +27,6 @@ use webrender_api::NativeFontHandle;
#[derive(Deserialize, Serialize)]
pub struct FontTemplateData {
// If you add members here, review the Debug impl below
/// The `CTFont` object, if present. This is cached here so that we don't have to keep creating
/// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
/// `font_data` fields.
@ -38,21 +37,21 @@ pub struct FontTemplateData {
ctfont: CachedCTFont,
pub identifier: Atom,
pub font_data: Option<Arc<Vec<u8>>>
pub font_data: Option<Arc<Vec<u8>>>,
}
impl fmt::Debug for FontTemplateData {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("FontTemplateData")
.field("ctfont", &self.ctfont)
.field("identifier", &self.identifier)
.field(
"font_data",
&self.font_data
.field("ctfont", &self.ctfont)
.field("identifier", &self.identifier)
.field(
"font_data",
&self
.font_data
.as_ref()
.map(|bytes| format!("[{} bytes]", bytes.len()))
)
.finish()
.map(|bytes| format!("[{} bytes]", bytes.len())),
).finish()
}
}
@ -64,7 +63,7 @@ impl FontTemplateData {
Ok(FontTemplateData {
ctfont: CachedCTFont(Mutex::new(HashMap::new())),
identifier: identifier.to_owned(),
font_data: font_data.map(Arc::new)
font_data: font_data.map(Arc::new),
})
}
@ -83,10 +82,10 @@ impl FontTemplateData {
match cgfont_result {
Ok(cgfont) => {
Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
}
Err(_) => None
},
Err(_) => None,
}
}
},
None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(),
};
if let Some(ctfont) = ctfont {
@ -104,16 +103,23 @@ impl FontTemplateData {
return font_data;
}
let path = ServoUrl::parse(&*self.ctfont(0.0)
.expect("No Core Text font available!")
.url()
.expect("No URL for Core Text font!")
.get_string()
.to_string()).expect("Couldn't parse Core Text font URL!")
.as_url().to_file_path()
.expect("Core Text font didn't name a path!");
let path = ServoUrl::parse(
&*self
.ctfont(0.0)
.expect("No Core Text font available!")
.url()
.expect("No URL for Core Text font!")
.get_string()
.to_string(),
).expect("Couldn't parse Core Text font URL!")
.as_url()
.to_file_path()
.expect("Core Text font didn't name a path!");
let mut bytes = Vec::new();
File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap();
File::open(path)
.expect("Couldn't open font file!")
.read_to_end(&mut bytes)
.unwrap();
bytes
}
@ -125,7 +131,8 @@ impl FontTemplateData {
/// Returns the native font that underlies this font template, if applicable.
pub fn native_font(&self) -> Option<NativeFontHandle> {
self.ctfont(0.0).map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont()))
self.ctfont(0.0)
.map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont()))
}
}
@ -140,14 +147,19 @@ impl Deref for CachedCTFont {
}
impl Serialize for CachedCTFont {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_none()
}
}
impl<'de> Deserialize<'de> for CachedCTFont {
fn deserialize<D>(deserializer: D) -> Result<CachedCTFont, D::Error>
where D: Deserializer<'de> {
where
D: Deserializer<'de>,
{
struct NoneOptionVisitor;
impl<'de> Visitor<'de> for NoneOptionVisitor {
@ -158,7 +170,10 @@ impl<'de> Deserialize<'de> for CachedCTFont {
}
#[inline]
fn visit_none<E>(self) -> Result<CachedCTFont, E> where E: Error {
fn visit_none<E>(self) -> Result<CachedCTFont, E>
where
E: Error,
{
Ok(CachedCTFont(Mutex::new(HashMap::new())))
}
}

View file

@ -23,7 +23,9 @@ mod freetype {
/// Creates a String from the given null-terminated buffer.
/// Panics if the buffer does not contain UTF-8.
unsafe fn c_str_to_string(s: *const c_char) -> String {
str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap().to_owned()
str::from_utf8(CStr::from_ptr(s).to_bytes())
.unwrap()
.to_owned()
}
pub mod font;

View file

@ -27,10 +27,18 @@ use text::glyph::GlyphId;
use truetype;
// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
fn pt_to_px(pt: f64) -> f64 { pt / 72. * 96. }
fn em_to_px(em: f64) -> f64 { em * 16. }
fn au_from_em(em: f64) -> Au { Au::from_f64_px(em_to_px(em)) }
fn au_from_pt(pt: f64) -> Au { Au::from_f64_px(pt_to_px(pt)) }
fn pt_to_px(pt: f64) -> f64 {
pt / 72. * 96.
}
fn em_to_px(em: f64) -> f64 {
em * 16.
}
fn au_from_em(em: f64) -> Au {
Au::from_f64_px(em_to_px(em))
}
fn au_from_pt(pt: f64) -> Au {
Au::from_f64_px(pt_to_px(pt))
}
pub struct FontTable {
data: Vec<u8>,
@ -38,7 +46,9 @@ pub struct FontTable {
impl FontTable {
pub fn wrap(data: &[u8]) -> FontTable {
FontTable { data: data.to_vec() }
FontTable {
data: data.to_vec(),
}
}
}
@ -139,7 +149,7 @@ impl FontInfo {
} else {
return Err(());
}
}
},
};
let mut os2_table_cursor = Cursor::new(os2_table_bytes.as_ref().unwrap());
@ -163,18 +173,20 @@ impl FontInfo {
let weight = StyleFontWeight(weight_val as f32);
let stretch = StyleFontStretch(NonNegative(match min(9, max(1, width_val)) {
1 => FontStretchKeyword::UltraCondensed,
2 => FontStretchKeyword::ExtraCondensed,
3 => FontStretchKeyword::Condensed,
4 => FontStretchKeyword::SemiCondensed,
5 => FontStretchKeyword::Normal,
6 => FontStretchKeyword::SemiExpanded,
7 => FontStretchKeyword::Expanded,
8 => FontStretchKeyword::ExtraExpanded,
9 => FontStretchKeyword::UltraExpanded,
_ => return Err(()),
}.compute()));
let stretch = StyleFontStretch(NonNegative(
match min(9, max(1, width_val)) {
1 => FontStretchKeyword::UltraCondensed,
2 => FontStretchKeyword::ExtraCondensed,
3 => FontStretchKeyword::Condensed,
4 => FontStretchKeyword::SemiCondensed,
5 => FontStretchKeyword::Normal,
6 => FontStretchKeyword::SemiExpanded,
7 => FontStretchKeyword::Expanded,
8 => FontStretchKeyword::ExtraExpanded,
9 => FontStretchKeyword::UltraExpanded,
_ => return Err(()),
}.compute(),
));
let style = if italic_bool {
GenericFontStyle::Italic
@ -212,18 +224,20 @@ impl FontInfo {
// slightly blacker black
FontWeight::ExtraBlack => 1000.,
});
let stretch = StyleFontStretch(NonNegative(match font.stretch() {
FontStretch::Undefined => FontStretchKeyword::Normal,
FontStretch::UltraCondensed => FontStretchKeyword::UltraCondensed,
FontStretch::ExtraCondensed => FontStretchKeyword::ExtraCondensed,
FontStretch::Condensed => FontStretchKeyword::Condensed,
FontStretch::SemiCondensed => FontStretchKeyword::SemiCondensed,
FontStretch::Normal => FontStretchKeyword::Normal,
FontStretch::SemiExpanded => FontStretchKeyword::SemiExpanded,
FontStretch::Expanded => FontStretchKeyword::Expanded,
FontStretch::ExtraExpanded => FontStretchKeyword::ExtraExpanded,
FontStretch::UltraExpanded => FontStretchKeyword::UltraExpanded,
}.compute()));
let stretch = StyleFontStretch(NonNegative(
match font.stretch() {
FontStretch::Undefined => FontStretchKeyword::Normal,
FontStretch::UltraCondensed => FontStretchKeyword::UltraCondensed,
FontStretch::ExtraCondensed => FontStretchKeyword::ExtraCondensed,
FontStretch::Condensed => FontStretchKeyword::Condensed,
FontStretch::SemiCondensed => FontStretchKeyword::SemiCondensed,
FontStretch::Normal => FontStretchKeyword::Normal,
FontStretch::SemiExpanded => FontStretchKeyword::SemiExpanded,
FontStretch::Expanded => FontStretchKeyword::Expanded,
FontStretch::ExtraExpanded => FontStretchKeyword::ExtraExpanded,
FontStretch::UltraExpanded => FontStretchKeyword::UltraExpanded,
}.compute(),
));
Ok(FontInfo {
family_name: font.family_name(),
@ -246,13 +260,14 @@ pub struct FontHandle {
scaled_du_to_px: f32,
}
impl FontHandle {
}
impl FontHandle {}
impl FontHandleMethods for FontHandle {
fn new_from_template(_: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
-> Result<Self, ()>
{
fn new_from_template(
_: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<Self, ()> {
let (info, face) = if let Some(ref raw_font) = template.bytes {
let font_file = FontFile::new_from_data(&raw_font);
if font_file.is_none() {
@ -260,7 +275,9 @@ impl FontHandleMethods for FontHandle {
return Err(());
}
let face = font_file.unwrap().create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
let face = font_file
.unwrap()
.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
let info = FontInfo::new_from_face(&face)?;
(info, face)
} else {
@ -350,32 +367,34 @@ impl FontHandleMethods for FontHandle {
let dm = self.face.metrics();
let au_from_du = |du| -> Au { Au::from_f32_px(du as f32 * self.du_to_px) };
let au_from_du_s = |du| -> Au { Au:: from_f32_px(du as f32 * self.scaled_du_to_px) };
let au_from_du_s = |du| -> Au { Au::from_f32_px(du as f32 * self.scaled_du_to_px) };
// anything that we calculate and don't just pull out of self.face.metrics
// is pulled out here for clarity
let leading = dm.ascent - dm.capHeight;
let metrics = FontMetrics {
underline_size: au_from_du(dm.underlineThickness as i32),
underline_size: au_from_du(dm.underlineThickness as i32),
underline_offset: au_from_du_s(dm.underlinePosition as i32),
strikeout_size: au_from_du(dm.strikethroughThickness as i32),
strikeout_size: au_from_du(dm.strikethroughThickness as i32),
strikeout_offset: au_from_du_s(dm.strikethroughPosition as i32),
leading: au_from_du_s(leading as i32),
x_height: au_from_du_s(dm.xHeight as i32),
em_size: au_from_em(self.em_size as f64),
ascent: au_from_du_s(dm.ascent as i32),
descent: au_from_du_s(dm.descent as i32),
max_advance: au_from_pt(0.0), // FIXME
average_advance: au_from_pt(0.0), // FIXME
line_gap: au_from_du_s((dm.ascent + dm.descent + dm.lineGap as u16) as i32),
leading: au_from_du_s(leading as i32),
x_height: au_from_du_s(dm.xHeight as i32),
em_size: au_from_em(self.em_size as f64),
ascent: au_from_du_s(dm.ascent as i32),
descent: au_from_du_s(dm.descent as i32),
max_advance: au_from_pt(0.0), // FIXME
average_advance: au_from_pt(0.0), // FIXME
line_gap: au_from_du_s((dm.ascent + dm.descent + dm.lineGap as u16) as i32),
};
debug!("Font metrics (@{} pt): {:?}", self.em_size * 12., metrics);
metrics
}
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
self.face.get_font_table(tag).map(|bytes| FontTable { data: bytes })
self.face
.get_font_table(tag)
.map(|bytes| FontTable { data: bytes })
}
fn identifier(&self) -> Atom {

View file

@ -21,7 +21,10 @@ pub fn system_default_family(_: &str) -> Option<String> {
Some("Verdana".to_owned())
}
pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),
{
let system_fc = FontCollection::system();
for family in system_fc.families_iter() {
callback(family.name());
@ -37,7 +40,10 @@ pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
// we'll stringify, and then put them all in a HashMap with
// the actual FontDescriptor there.
pub fn for_each_variation<F>(family_name: &str, mut callback: F) where F: FnMut(String) {
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
where
F: FnMut(String),
{
let system_fc = FontCollection::system();
if let Some(family) = system_fc.get_font_family_by_name(family_name) {
let count = family.get_font_count();
@ -65,12 +71,14 @@ pub fn descriptor_from_atom(ident: &Atom) -> FontDescriptor {
pub fn font_from_atom(ident: &Atom) -> Font {
let fonts = FONT_ATOM_MAP.lock().unwrap();
FontCollection::system().get_font_from_descriptor(fonts.get(ident).unwrap()).unwrap()
FontCollection::system()
.get_font_from_descriptor(fonts.get(ident).unwrap())
.unwrap()
}
// Based on gfxWindowsPlatform::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
let mut families = vec!("Arial");
let mut families = vec!["Arial"];
if let Some(codepoint) = codepoint {
match unicode_plane(codepoint) {
@ -83,31 +91,29 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::Hebrew => {
families.push("Estrangelo Edessa");
families.push("Cambria");
}
},
UnicodeBlock::Arabic |
UnicodeBlock::ArabicSupplement => {
UnicodeBlock::Arabic | UnicodeBlock::ArabicSupplement => {
families.push("Microsoft Uighur");
}
},
UnicodeBlock::Syriac => {
families.push("Estrangelo Edessa");
}
},
UnicodeBlock::Thaana => {
families.push("MV Boli");
}
},
UnicodeBlock::NKo => {
families.push("Ebrima");
}
},
UnicodeBlock::Devanagari |
UnicodeBlock::Bengali => {
UnicodeBlock::Devanagari | UnicodeBlock::Bengali => {
families.push("Nirmala UI");
families.push("Utsaah");
families.push("Aparajita");
}
},
UnicodeBlock::Gurmukhi |
UnicodeBlock::Gujarati |
@ -123,21 +129,21 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::SundaneseSupplement |
UnicodeBlock::VedicExtensions => {
families.push("Nirmala UI");
}
},
UnicodeBlock::Thai => {
families.push("Leelawadee UI");
}
},
UnicodeBlock::Lao => {
families.push("Lao UI");
}
},
UnicodeBlock::Myanmar |
UnicodeBlock::MyanmarExtendedA |
UnicodeBlock::MyanmarExtendedB => {
families.push("Myanmar Text");
}
},
UnicodeBlock::HangulJamo |
UnicodeBlock::HangulJamoExtendedA |
@ -145,48 +151,47 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::HangulJamoExtendedB |
UnicodeBlock::HangulCompatibilityJamo => {
families.push("Malgun Gothic");
}
},
UnicodeBlock::Ethiopic |
UnicodeBlock::EthiopicSupplement |
UnicodeBlock::EthiopicExtended |
UnicodeBlock::EthiopicExtendedA => {
families.push("Nyala");
}
},
UnicodeBlock::Cherokee => {
families.push("Plantagenet Cherokee");
}
},
UnicodeBlock::UnifiedCanadianAboriginalSyllabics |
UnicodeBlock::UnifiedCanadianAboriginalSyllabicsExtended => {
families.push("Euphemia");
families.push("Segoe UI");
}
},
UnicodeBlock::Khmer |
UnicodeBlock::KhmerSymbols => {
UnicodeBlock::Khmer | UnicodeBlock::KhmerSymbols => {
families.push("Khmer UI");
families.push("Leelawadee UI");
}
},
UnicodeBlock::Mongolian => {
families.push("Mongolian Baiti");
}
},
UnicodeBlock::TaiLe => {
families.push("Microsoft Tai Le");
}
},
UnicodeBlock::NewTaiLue => {
families.push("Microsoft New Tai Lue");
}
},
UnicodeBlock::Buginese |
UnicodeBlock::TaiTham |
UnicodeBlock::CombiningDiacriticalMarksExtended => {
families.push("Leelawadee UI");
}
},
UnicodeBlock::GeneralPunctuation |
UnicodeBlock::SuperscriptsandSubscripts |
@ -220,7 +225,7 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Meiryo");
families.push("Lucida Sans Unicode");
families.push("Ebrima");
}
},
UnicodeBlock::GeorgianSupplement |
UnicodeBlock::Tifinagh |
@ -232,11 +237,11 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Segoe UI");
families.push("Segoe UI Symbol");
families.push("Meiryo");
}
},
UnicodeBlock::BraillePatterns => {
families.push("Segoe UI Symbol");
}
},
UnicodeBlock::CJKSymbolsandPunctuation |
UnicodeBlock::Hiragana |
@ -249,21 +254,20 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::CJKUnifiedIdeographs => {
families.push("Microsoft YaHei");
families.push("Yu Gothic");
}
},
UnicodeBlock::EnclosedCJKLettersandMonths => {
families.push("Malgun Gothic");
}
},
UnicodeBlock::YijingHexagramSymbols => {
families.push("Segoe UI Symbol");
}
},
UnicodeBlock::YiSyllables |
UnicodeBlock::YiRadicals => {
UnicodeBlock::YiSyllables | UnicodeBlock::YiRadicals => {
families.push("Microsoft Yi Baiti");
families.push("Segoe UI");
}
},
UnicodeBlock::Vai |
UnicodeBlock::CyrillicExtendedB |
@ -273,36 +277,34 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Ebrima");
families.push("Segoe UI");
families.push("Cambria Math");
}
},
UnicodeBlock::SylotiNagri |
UnicodeBlock::CommonIndicNumberForms |
UnicodeBlock::Phagspa |
UnicodeBlock::Saurashtra |
UnicodeBlock::DevanagariExtended => {
families.push("Microsoft PhagsPa");
families.push("Nirmala UI");
}
families.push("Microsoft PhagsPa");
families.push("Nirmala UI");
},
UnicodeBlock::KayahLi |
UnicodeBlock::Rejang |
UnicodeBlock::Javanese => {
families.push("Malgun Gothic");
families.push("Javanese Text");
families.push("Leelawadee UI");
}
UnicodeBlock::KayahLi | UnicodeBlock::Rejang | UnicodeBlock::Javanese => {
families.push("Malgun Gothic");
families.push("Javanese Text");
families.push("Leelawadee UI");
},
UnicodeBlock::AlphabeticPresentationForms => {
families.push("Microsoft Uighur");
families.push("Gabriola");
families.push("Sylfaen");
}
},
UnicodeBlock::ArabicPresentationFormsA |
UnicodeBlock::ArabicPresentationFormsB => {
families.push("Traditional Arabic");
families.push("Arabic Typesetting");
}
},
UnicodeBlock::VariationSelectors |
UnicodeBlock::VerticalForms |
@ -312,12 +314,12 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
UnicodeBlock::HalfwidthandFullwidthForms |
UnicodeBlock::Specials => {
families.push("Microsoft JhengHei");
}
},
_ => {}
_ => {},
}
}
}
},
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
1 => {
@ -325,9 +327,9 @@ pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
families.push("Ebrima");
families.push("Nirmala UI");
families.push("Cambria Math");
}
},
_ => {}
_ => {},
}
}

View file

@ -11,7 +11,6 @@ use webrender_api::NativeFontHandle;
#[derive(Deserialize, Serialize)]
pub struct FontTemplateData {
// If you add members here, review the Debug impl below
pub bytes: Option<Vec<u8>>,
pub identifier: Atom,
}
@ -19,20 +18,22 @@ pub struct FontTemplateData {
impl fmt::Debug for FontTemplateData {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("FontTemplateData")
.field(
"bytes",
&self.bytes
.field(
"bytes",
&self
.bytes
.as_ref()
.map(|bytes| format!("[{} bytes]", bytes.len()))
)
.field("identifier", &self.identifier)
.finish()
.map(|bytes| format!("[{} bytes]", bytes.len())),
).field("identifier", &self.identifier)
.finish()
}
}
impl FontTemplateData {
pub fn new(identifier: Atom,
font_data: Option<Vec<u8>>) -> Result<FontTemplateData, io::Error> {
pub fn new(
identifier: Atom,
font_data: Option<Vec<u8>>,
) -> Result<FontTemplateData, io::Error> {
Ok(FontTemplateData {
bytes: font_data,
identifier: identifier,