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

@ -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())))
}
}