diff options
Diffstat (limited to 'components/gfx')
-rw-r--r-- | components/gfx/font.rs | 14 | ||||
-rw-r--r-- | components/gfx/font_cache_thread.rs | 7 | ||||
-rw-r--r-- | components/gfx/font_template.rs | 85 | ||||
-rw-r--r-- | components/gfx/platform/freetype/font.rs | 58 | ||||
-rw-r--r-- | components/gfx/platform/macos/font.rs | 32 | ||||
-rw-r--r-- | components/gfx/platform/windows/font.rs | 110 | ||||
-rw-r--r-- | components/gfx/tests/font_context.rs | 7 | ||||
-rw-r--r-- | components/gfx/tests/font_template.rs | 20 |
8 files changed, 168 insertions, 165 deletions
diff --git a/components/gfx/font.rs b/components/gfx/font.rs index 09578168ea7..2cf92e6a328 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -19,7 +19,7 @@ use std::rc::Rc; use std::str; use std::sync::Arc; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; -use style::computed_values::{font_stretch, font_variant_caps, font_weight}; +use style::computed_values::{font_stretch, font_style, font_variant_caps, font_weight}; use style::properties::style_structs::Font as FontStyleStruct; use style::values::computed::font::SingleFontFamily; use text::Shaper; @@ -47,18 +47,24 @@ static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; // resources needed by the graphics layer to draw glyphs. pub trait FontHandleMethods: Sized { - fn new_from_template(fctx: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>) - -> Result<Self, ()>; + fn new_from_template( + fctx: &FontContextHandle, + template: Arc<FontTemplateData>, + pt_size: Option<Au>, + ) -> Result<Self, ()>; + fn template(&self) -> Arc<FontTemplateData>; fn family_name(&self) -> String; fn face_name(&self) -> Option<String>; - fn is_italic(&self) -> bool; + + fn style(&self) -> font_style::T; fn boldness(&self) -> font_weight::T; fn stretchiness(&self) -> font_stretch::T; fn glyph_index(&self, codepoint: char) -> Option<GlyphId>; fn glyph_h_advance(&self, GlyphId) -> Option<FractionalPixel>; fn glyph_h_kerning(&self, glyph0: GlyphId, glyph1: GlyphId) -> FractionalPixel; + /// Can this font do basic horizontal LTR shaping without Harfbuzz? fn can_do_fast_shaping(&self) -> bool; fn metrics(&self) -> FontMetrics; diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index fdb48e519fe..39375191ae1 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -18,14 +18,11 @@ use platform::font_list::system_default_family; use platform::font_template::FontTemplateData; use servo_atoms::Atom; use servo_url::ServoUrl; +use std::{fmt, f32, mem, thread}; use std::borrow::ToOwned; use std::collections::HashMap; -use std::fmt; -use std::mem; use std::ops::Deref; use std::sync::{Arc, Mutex}; -use std::thread; -use std::u32; use style::font_face::{EffectiveSources, Source}; use style::values::computed::font::{SingleFontFamily, FamilyName}; use webrender_api; @@ -63,7 +60,7 @@ impl FontTemplates { // We didn't find an exact match. Do more expensive fuzzy matching. // TODO(#190): Do a better job. - let (mut best_template_data, mut best_distance) = (None, u32::MAX); + let (mut best_template_data, mut best_distance) = (None, f32::MAX); for template in &mut self.templates { if let Some((template_data, distance)) = template.data_for_approximate_descriptor(fctx, desc) { diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index 239bfcdd8c9..13c531f4d43 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -10,7 +10,6 @@ use servo_atoms::Atom; use std::fmt::{Debug, Error, Formatter}; use std::io::Error as IoError; use std::sync::{Arc, Weak}; -use std::u32; use style::computed_values::font_stretch::T as FontStretch; use style::computed_values::font_style::T as FontStyle; use style::properties::style_structs::Font as FontStyleStruct; @@ -20,21 +19,35 @@ use style::values::computed::font::FontWeight; /// to be expanded or refactored when we support more of the font styling parameters. /// /// NB: If you change this, you will need to update `style::properties::compute_font_hash()`. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct FontTemplateDescriptor { pub weight: FontWeight, pub stretch: FontStretch, - pub italic: bool, + pub style: FontStyle, } +fn style_to_number(s: &FontStyle) -> f32 { + use style::values::generics::font::FontStyle as GenericFontStyle; + + match *s { + GenericFontStyle::Normal => 0., + GenericFontStyle::Italic => FontStyle::default_angle().0.degrees(), + GenericFontStyle::Oblique(ref angle) => angle.0.degrees(), + } +} + + impl FontTemplateDescriptor { #[inline] - pub fn new(weight: FontWeight, stretch: FontStretch, italic: bool) - -> FontTemplateDescriptor { - FontTemplateDescriptor { - weight: weight, - stretch: stretch, - italic: italic, + pub fn new( + weight: FontWeight, + stretch: FontStretch, + style: FontStyle, + ) -> Self { + Self { + weight, + stretch, + style, } } @@ -46,30 +59,15 @@ impl FontTemplateDescriptor { /// /// The policy is to care most about differences in italicness, then weight, then stretch #[inline] - fn distance_from(&self, other: &FontTemplateDescriptor) -> u32 { - let italic_part = if self.italic == other.italic { 0 } else { 1000 }; + fn distance_from(&self, other: &FontTemplateDescriptor) -> f32 { + // 0 <= style_part <= 180, since font-style obliqueness should be + // between -90 and +90deg. + let style_part = (style_to_number(&self.style) - style_to_number(&other.style)).abs(); // 0 <= weightPart <= 800 - let weight_part = ((self.weight.0 as i16) - (other.weight.0 as i16)).abs() as u32; + let weight_part = (self.weight.0 - other.weight.0).abs(); // 0 <= stretchPart <= 8 - let stretch_part = (self.stretch_number() - other.stretch_number()).abs() as u32; - italic_part + weight_part + stretch_part - } - - /// Returns a number between 1 and 9 for the stretch property. - /// 1 is ultra_condensed, 5 is normal, and 9 is ultra_expanded - #[inline] - fn stretch_number(&self) -> i32 { - match self.stretch { - FontStretch::UltraCondensed => 1, - FontStretch::ExtraCondensed => 2, - FontStretch::Condensed => 3, - FontStretch::SemiCondensed => 4, - FontStretch::Normal => 5, - FontStretch::SemiExpanded => 6, - FontStretch::Expanded => 7, - FontStretch::ExtraExpanded => 8, - FontStretch::UltraExpanded => 9, - } + let stretch_part = ((self.stretch.0).0 - (other.stretch.0).0).abs(); + style_part + weight_part + stretch_part } } @@ -78,17 +76,11 @@ impl<'a> From<&'a FontStyleStruct> for FontTemplateDescriptor { FontTemplateDescriptor { weight: style.font_weight, stretch: style.font_stretch, - italic: style.font_style == FontStyle::Italic || style.font_style == FontStyle::Oblique, + style: style.font_style, } } } -impl PartialEq for FontTemplateDescriptor { - fn eq(&self, other: &FontTemplateDescriptor) -> bool { - self.weight == other.weight && self.stretch == other.stretch && self.italic == other.italic - } -} - /// This describes all the information needed to create /// font instance handles. It contains a unique /// FontTemplateData structure that is platform specific. @@ -173,10 +165,11 @@ impl FontTemplate { /// Returns the font data along with the distance between this font's descriptor and the given /// descriptor, if the font can be loaded. - pub fn data_for_approximate_descriptor(&mut self, - font_context: &FontContextHandle, - requested_descriptor: &FontTemplateDescriptor) - -> Option<(Arc<FontTemplateData>, u32)> { + pub fn data_for_approximate_descriptor( + &mut self, + font_context: &FontContextHandle, + requested_descriptor: &FontTemplateDescriptor, + ) -> Option<(Arc<FontTemplateData>, f32)> { self.descriptor(&font_context).and_then(|descriptor| { self.data().ok().map(|data| { (data, descriptor.distance_from(requested_descriptor)) @@ -195,9 +188,11 @@ impl FontTemplate { None); self.is_valid = handle.is_ok(); let handle = handle?; - self.descriptor = Some(FontTemplateDescriptor::new(handle.boldness(), - handle.stretchiness(), - handle.is_italic())); + self.descriptor = Some(FontTemplateDescriptor::new( + handle.boldness(), + handle.stretchiness(), + handle.style(), + )); Ok(()) } diff --git a/components/gfx/platform/freetype/font.rs b/components/gfx/platform/freetype/font.rs index 940563d7d29..506d6be2117 100644 --- a/components/gfx/platform/freetype/font.rs +++ b/components/gfx/platform/freetype/font.rs @@ -24,6 +24,7 @@ use std::os::raw::{c_char, c_long}; use std::sync::Arc; use style::computed_values::font_stretch::T as FontStretch; use style::computed_values::font_weight::T as FontWeight; +use style::values::computed::font::FontStyle; use super::c_str_to_string; use text::glyph::GlyphId; use text::util::fixed_to_float; @@ -149,43 +150,44 @@ impl FontHandleMethods for FontHandle { } } - fn is_italic(&self) -> bool { - unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC as c_long != 0 } + fn style(&self) -> FontStyle { + use style::values::generics::font::FontStyle::*; + if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC as c_long != 0 } { + Italic + } else { + Normal + } } fn boldness(&self) -> FontWeight { - if let Some(os2) = self.os2_table() { - let weight = os2.us_weight_class as i32; - - if weight < 10 { - FontWeight::from_int(weight * 100).unwrap() - } else if weight >= 100 && weight < 1000 { - FontWeight::from_int(weight / 100 * 100).unwrap() - } else { - FontWeight::normal() - } - } else { - FontWeight::normal() - } + let os2 = match self.os2_table() { + None => return FontWeight::normal(), + Some(os2) => os2, + }; + let weight = os2.us_weight_class as f32; + FontWeight(weight.max(1.).min(1000.)) } fn stretchiness(&self) -> FontStretch { - if let Some(os2) = self.os2_table() { + use style::values::generics::NonNegative; + use style::values::specified::font::FontStretchKeyword; + let percentage = if let Some(os2) = self.os2_table() { match os2.us_width_class { - 1 => FontStretch::UltraCondensed, - 2 => FontStretch::ExtraCondensed, - 3 => FontStretch::Condensed, - 4 => FontStretch::SemiCondensed, - 5 => FontStretch::Normal, - 6 => FontStretch::SemiExpanded, - 7 => FontStretch::Expanded, - 8 => FontStretch::ExtraExpanded, - 9 => FontStretch::UltraExpanded, - _ => FontStretch::Normal + 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, + _ => FontStretchKeyword::Normal } } else { - FontStretch::Normal - } + FontStretchKeyword::Normal + }.compute(); + NonNegative(percentage) } fn glyph_index(&self, codepoint: char) -> Option<GlyphId> { diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index ca719ddf5b7..5eacf92ffd6 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -22,8 +22,7 @@ use servo_atoms::Atom; use std::{fmt, ptr}; use std::ops::Range; use std::sync::Arc; -use style::computed_values::font_stretch::T as FontStretch; -use style::computed_values::font_weight::T as FontWeight; +use style::values::computed::font::{FontStretch, FontStyle, FontWeight}; use text::glyph::GlyphId; const KERN_PAIR_LEN: usize = 6; @@ -204,34 +203,33 @@ impl FontHandleMethods for FontHandle { Some(self.ctfont.face_name()) } - fn is_italic(&self) -> bool { - self.ctfont.symbolic_traits().is_italic() + fn style(&self) -> FontStyle { + use style::values::generics::font::FontStyle::*; + if self.ctfont.symbolic_traits().is_italic() { + Italic + } else { + Normal + } } 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 = if normalized <= 0.0 { 4.0 + normalized * 3.0 // [1.0, 4.0] } else { 4.0 + normalized * 5.0 // [4.0, 9.0] }; // [1.0, 9.0], centered on 4.0 - FontWeight::from_int(normalized.round() as i32 * 100).unwrap() + FontWeight(normalized as f32 * 100.) } fn stretchiness(&self) -> FontStretch { + use style::values::computed::Percentage; + use style::values::generics::NonNegative; + let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0] - let normalized = (normalized + 1.0) / 2.0 * 9.0; // [0.0, 9.0] - match normalized { - v if v < 1.0 => FontStretch::UltraCondensed, - v if v < 2.0 => FontStretch::ExtraCondensed, - v if v < 3.0 => FontStretch::Condensed, - v if v < 4.0 => FontStretch::SemiCondensed, - v if v < 5.0 => FontStretch::Normal, - v if v < 6.0 => FontStretch::SemiExpanded, - v if v < 7.0 => FontStretch::Expanded, - v if v < 8.0 => FontStretch::ExtraExpanded, - _ => FontStretch::UltraExpanded, - } + NonNegative(Percentage(normalized as f32 + 1.0)) } fn glyph_index(&self, codepoint: char) -> Option<GlyphId> { diff --git a/components/gfx/platform/windows/font.rs b/components/gfx/platform/windows/font.rs index 12df6d547d2..ed94d0fc5a2 100644 --- a/components/gfx/platform/windows/font.rs +++ b/components/gfx/platform/windows/font.rs @@ -19,6 +19,10 @@ use servo_atoms::Atom; use std::sync::Arc; use style::computed_values::font_stretch::T as StyleFontStretch; use style::computed_values::font_weight::T as StyleFontWeight; +use style::values::computed::font::FontStyle as StyleFontStyle; +use style::values::generics::NonNegative; +use style::values::generics::font::FontStyle as GenericFontStyle; +use style::values::specified::font::FontStretchKeyword; use text::glyph::GlyphId; use truetype; @@ -98,7 +102,7 @@ struct FontInfo { face_name: String, weight: StyleFontWeight, stretch: StyleFontStretch, - style: FontStyle, + style: StyleFontStyle, } impl FontInfo { @@ -157,75 +161,76 @@ impl FontInfo { }, }; - let weight = - StyleFontWeight::from_int( - min(9, max(1, weight_val as i32 / 100)) * 100 - ).unwrap(); - - let stretch = match min(9, max(1, width_val)) { - 1 => StyleFontStretch::UltraCondensed, - 2 => StyleFontStretch::ExtraCondensed, - 3 => StyleFontStretch::Condensed, - 4 => StyleFontStretch::SemiCondensed, - 5 => StyleFontStretch::Normal, - 6 => StyleFontStretch::SemiExpanded, - 7 => StyleFontStretch::Expanded, - 8 => StyleFontStretch::ExtraExpanded, - 9 => StyleFontStretch::UltraExpanded, + let weight = StyleFontWeight(weight_val as f32); + + let stretch = 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 { - FontStyle::Italic + GenericFontStyle::Italic } else { - FontStyle::Normal + GenericFontStyle::Normal }; Ok(FontInfo { family_name: family, face_name: face, - weight: weight, - stretch: stretch, - style: style, + weight, + stretch, + style, }) } fn new_from_font(font: &Font) -> Result<FontInfo, ()> { - let style = font.style(); + let style = match font.style() { + FontStyle::Normal => GenericFontStyle::Normal, + FontStyle::Oblique => GenericFontStyle::Oblique(StyleFontStyle::default_angle()), + FontStyle::Italic => GenericFontStyle::Italic, + }; let weight = StyleFontWeight(match font.weight() { - FontWeight::Thin => 100, - FontWeight::ExtraLight => 200, - FontWeight::Light => 300, + FontWeight::Thin => 100., + FontWeight::ExtraLight => 200., + FontWeight::Light => 300., // slightly grayer gray - FontWeight::SemiLight => 300, - FontWeight::Regular => 400, - FontWeight::Medium => 500, - FontWeight::SemiBold => 600, - FontWeight::Bold => 700, - FontWeight::ExtraBold => 800, - FontWeight::Black => 900, + FontWeight::SemiLight => 300., + FontWeight::Regular => 400., + FontWeight::Medium => 500., + FontWeight::SemiBold => 600., + FontWeight::Bold => 700., + FontWeight::ExtraBold => 800., + FontWeight::Black => 900., // slightly blacker black - FontWeight::ExtraBlack => 900, + FontWeight::ExtraBlack => 1000., }); - let stretch = match font.stretch() { - FontStretch::Undefined => StyleFontStretch::Normal, - FontStretch::UltraCondensed => StyleFontStretch::UltraCondensed, - FontStretch::ExtraCondensed => StyleFontStretch::ExtraCondensed, - FontStretch::Condensed => StyleFontStretch::Condensed, - FontStretch::SemiCondensed => StyleFontStretch::SemiCondensed, - FontStretch::Normal => StyleFontStretch::Normal, - FontStretch::SemiExpanded => StyleFontStretch::SemiExpanded, - FontStretch::Expanded => StyleFontStretch::Expanded, - FontStretch::ExtraExpanded => StyleFontStretch::ExtraExpanded, - FontStretch::UltraExpanded => StyleFontStretch::UltraExpanded, - }; + let stretch = 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(), face_name: font.face_name(), - style: style, - weight: weight, - stretch: stretch, + style, + weight, + stretch, }) } } @@ -297,11 +302,8 @@ impl FontHandleMethods for FontHandle { Some(self.info.face_name.clone()) } - fn is_italic(&self) -> bool { - match self.info.style { - FontStyle::Normal => false, - FontStyle::Oblique | FontStyle::Italic => true, - } + fn style(&self) -> StyleFontStyle { + self.info.style } fn boldness(&self) -> StyleFontWeight { diff --git a/components/gfx/tests/font_context.rs b/components/gfx/tests/font_context.rs index f7fef58a5c2..c918ef86e90 100644 --- a/components/gfx/tests/font_context.rs +++ b/components/gfx/tests/font_context.rs @@ -22,12 +22,13 @@ use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; use std::rc::Rc; -use style::properties::longhands::font_stretch::computed_value::T as FontStretch; -use style::properties::longhands::font_style::computed_value::T as FontStyle; use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps; use style::properties::style_structs::Font as FontStyleStruct; +use style::values::computed::Percentage; use style::values::computed::font::{FamilyName, FamilyNameSyntax, FontFamily, FontFamilyList, FontSize}; use style::values::computed::font::{FontWeight, SingleFontFamily}; +use style::values::generics::NonNegative; +use style::values::generics::font::FontStyle; struct TestFontSource { handle: FontContextHandle, @@ -108,7 +109,7 @@ fn style() -> FontStyleStruct { font_variant_caps: FontVariantCaps::Normal, font_weight: FontWeight::normal(), font_size: FontSize::medium(), - font_stretch: FontStretch::Normal, + font_stretch: NonNegative(Percentage(1.)), hash: 0, }; style.compute_font_hash(); diff --git a/components/gfx/tests/font_template.rs b/components/gfx/tests/font_template.rs index 4b513d9f0c4..af31d8f229d 100644 --- a/components/gfx/tests/font_template.rs +++ b/components/gfx/tests/font_template.rs @@ -16,8 +16,10 @@ fn test_font_template_descriptor() { use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; - use style::computed_values::font_stretch::T as FontStretch; + use style::values::computed::Percentage; use style::values::computed::font::FontWeight; + use style::values::generics::NonNegative; + use style::values::generics::font::FontStyle; fn descriptor(filename: &str) -> FontTemplateDescriptor { let mut path: PathBuf = [ @@ -43,25 +45,25 @@ fn test_font_template_descriptor() { assert_eq!(descriptor("DejaVuSans"), FontTemplateDescriptor { weight: FontWeight::normal(), - stretch: FontStretch::Normal, - italic: false, + stretch: NonNegative(Percentage(1.)), + style: FontStyle::Normal, }); assert_eq!(descriptor("DejaVuSans-Bold"), FontTemplateDescriptor { weight: FontWeight::bold(), - stretch: FontStretch::Normal, - italic: false, + stretch: NonNegative(Percentage(1.)), + style: FontStyle::Normal, }); assert_eq!(descriptor("DejaVuSans-Oblique"), FontTemplateDescriptor { weight: FontWeight::normal(), - stretch: FontStretch::Normal, - italic: true, + stretch: NonNegative(Percentage(1.)), + style: FontStyle::Italic, }); assert_eq!(descriptor("DejaVuSansCondensed-BoldOblique"), FontTemplateDescriptor { weight: FontWeight::bold(), - stretch: FontStretch::SemiCondensed, - italic: true, + stretch: NonNegative(Percentage(0.875)), + style: FontStyle::Italic, }); } |