mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Format gfx platform #21373
This commit is contained in:
parent
5063ac465b
commit
c57c99d9f7
13 changed files with 496 additions and 372 deletions
|
@ -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 {
|
||||
|
|
|
@ -6,7 +6,7 @@ use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FontContextHandle {
|
||||
ctx: ()
|
||||
ctx: (),
|
||||
}
|
||||
|
||||
impl FontContextHandle {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
},
|
||||
|
||||
_ => {}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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())))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue