diff --git a/components/gfx/font.rs b/components/gfx/font.rs index cfc79b6248c..324e755f438 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -10,7 +10,7 @@ use std::rc::Rc; use std::cell::RefCell; use servo_util::cache::HashCache; use servo_util::smallvec::{SmallVec, SmallVec8}; -use style::computed_values::{font_variant, font_weight}; +use style::computed_values::{font_stretch, font_variant, font_weight}; use style::style_structs::Font as FontStyle; use std::sync::Arc; @@ -37,6 +37,7 @@ pub trait FontHandleMethods { fn face_name(&self) -> String; fn is_italic(&self) -> bool; fn boldness(&self) -> font_weight::T; + fn stretchiness(&self) -> font_stretch::T; fn glyph_index(&self, codepoint: char) -> Option; fn glyph_h_advance(&self, GlyphId) -> Option; diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 34e92b21540..e67027cf53c 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -140,7 +140,9 @@ impl FontContext { // so they will never be released. Find out a good time to drop them. let desc = FontTemplateDescriptor::new(style.font_weight, - style.font_style == font_style::T::italic || style.font_style == font_style::T::oblique); + style.font_stretch, + style.font_style == font_style::T::italic || + style.font_style == font_style::T::oblique); let mut fonts = SmallVec8::new(); for family in style.font_family.iter() { diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index d90df2b3bdb..fee0bc69642 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -2,14 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use style::computed_values::font_weight; +use font::FontHandleMethods; use platform::font_context::FontContextHandle; use platform::font::FontHandle; use platform::font_template::FontTemplateData; use std::borrow::ToOwned; use std::sync::{Arc, Weak}; -use font::FontHandleMethods; +use style::computed_values::{font_stretch, font_weight}; /// Describes how to select a font from a given family. /// This is very basic at the moment and needs to be @@ -18,13 +18,17 @@ use font::FontHandleMethods; #[derive(Clone, Copy)] pub struct FontTemplateDescriptor { pub weight: font_weight::T, + pub stretch: font_stretch::T, pub italic: bool, } impl FontTemplateDescriptor { - pub fn new(weight: font_weight::T, italic: bool) -> FontTemplateDescriptor { + #[inline] + pub fn new(weight: font_weight::T, stretch: font_stretch::T, italic: bool) + -> FontTemplateDescriptor { FontTemplateDescriptor { weight: weight, + stretch: stretch, italic: italic, } } @@ -33,7 +37,8 @@ impl FontTemplateDescriptor { impl PartialEq for FontTemplateDescriptor { fn eq(&self, other: &FontTemplateDescriptor) -> bool { self.weight.is_bold() == other.weight.is_bold() && - self.italic == other.italic + self.stretch == other.stretch && + self.italic == other.italic } } @@ -44,7 +49,8 @@ pub struct FontTemplate { identifier: String, descriptor: Option, weak_ref: Option>, - strong_ref: Option>, // GWTODO: Add code path to unset the strong_ref for web fonts! + // GWTODO: Add code path to unset the strong_ref for web fonts! + strong_ref: Option>, is_valid: bool, } @@ -82,8 +88,10 @@ impl FontTemplate { } /// Get the data for creating a font if it matches a given descriptor. - pub fn get_if_matches(&mut self, fctx: &FontContextHandle, - requested_desc: &FontTemplateDescriptor) -> Option> { + pub fn get_if_matches(&mut self, + fctx: &FontContextHandle, + requested_desc: &FontTemplateDescriptor) + -> Option> { // The font template data can be unloaded when nothing is referencing // it (via the Weak reference to the Arc above). However, if we have // already loaded a font, store the style information about it separately, @@ -97,42 +105,42 @@ impl FontTemplate { None } }, - None => { - if self.is_valid { - let data = self.get_data(); - let handle: Result = FontHandleMethods::new_from_template(fctx, data.clone(), None); - match handle { - Ok(handle) => { - let actual_desc = FontTemplateDescriptor::new(handle.boldness(), - handle.is_italic()); - let desc_match = actual_desc == *requested_desc; + None if self.is_valid => { + let data = self.get_data(); + let handle: Result = + FontHandleMethods::new_from_template(fctx, data.clone(), None); + match handle { + Ok(handle) => { + let actual_desc = FontTemplateDescriptor::new(handle.boldness(), + handle.stretchiness(), + handle.is_italic()); + let desc_match = actual_desc == *requested_desc; - self.descriptor = Some(actual_desc); - self.is_valid = true; - if desc_match { - Some(data) - } else { - None - } - } - Err(()) => { - self.is_valid = false; - debug!("Unable to create a font from template {}", self.identifier); + self.descriptor = Some(actual_desc); + self.is_valid = true; + if desc_match { + Some(data) + } else { None } } - } else { - None + Err(()) => { + self.is_valid = false; + debug!("Unable to create a font from template {}", self.identifier); + None + } } } + None => None, } } /// Get the data for creating a font. pub fn get(&mut self) -> Option> { - match self.is_valid { - true => Some(self.get_data()), - false => None + if self.is_valid { + Some(self.get_data()) + } else { + None } } @@ -145,14 +153,13 @@ impl FontTemplate { None => None, }; - match maybe_data { - Some(data) => data, - None => { - assert!(self.strong_ref.is_none()); - let template_data = Arc::new(FontTemplateData::new(self.identifier.as_slice(), None)); - self.weak_ref = Some(template_data.downgrade()); - template_data - } + if let Some(data) = maybe_data { + return data } + + assert!(self.strong_ref.is_none()); + let template_data = Arc::new(FontTemplateData::new(self.identifier.as_slice(), None)); + self.weak_ref = Some(template_data.downgrade()); + template_data } } diff --git a/components/gfx/platform/freetype/font.rs b/components/gfx/platform/freetype/font.rs index 2e13a4f39aa..3a5d61ef373 100644 --- a/components/gfx/platform/freetype/font.rs +++ b/components/gfx/platform/freetype/font.rs @@ -12,7 +12,7 @@ use servo_util::str::c_str_to_string; use platform::font_context::FontContextHandle; use text::glyph::GlyphId; use text::util::{float_to_fixed, fixed_to_float}; -use style::computed_values::font_weight; +use style::computed_values::{font_stretch, font_weight}; use platform::font_template::FontTemplateData; use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name}; @@ -161,6 +161,10 @@ impl FontHandleMethods for FontHandle { } } } + fn stretchiness(&self) -> font_stretch::T { + // TODO(pcwalton): Implement this. + font_stretch::T::normal + } fn glyph_index(&self, codepoint: char) -> Option { assert!(!self.face.is_null()); diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index db168c657e6..fb7f12782c0 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -15,7 +15,7 @@ use servo_util::geometry::{Au, px_to_pt}; use servo_util::geometry; use platform::macos::font_context::FontContextHandle; use text::glyph::GlyphId; -use style::computed_values::font_weight; +use style::computed_values::{font_stretch, font_weight}; use platform::font_template::FontTemplateData; use core_foundation::base::CFIndex; @@ -111,6 +111,21 @@ impl FontHandleMethods for FontHandle { return font_weight::T::Weight900; } + fn stretchiness(&self) -> font_stretch::T { + let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0] + match (normalized + 1.0) / 2.0 * 9.0 { // [0.0, 9.0] + v if v < 1.0 => font_stretch::T::ultra_condensed, + v if v < 2.0 => font_stretch::T::extra_condensed, + v if v < 3.0 => font_stretch::T::condensed, + v if v < 4.0 => font_stretch::T::semi_condensed, + v if v < 5.0 => font_stretch::T::normal, + v if v < 6.0 => font_stretch::T::semi_expanded, + v if v < 7.0 => font_stretch::T::expanded, + v if v < 8.0 => font_stretch::T::extra_expanded, + _ => font_stretch::T::ultra_expanded, + } + } + fn glyph_index(&self, codepoint: char) -> Option { let characters: [UniChar; 1] = [codepoint as UniChar]; let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph]; diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index afe511b7e1f..8efb88af268 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -127,6 +127,7 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString font; [TreatNullAs=EmptyString] attribute DOMString fontFamily; [TreatNullAs=EmptyString] attribute DOMString fontSize; + [TreatNullAs=EmptyString] attribute DOMString fontStretch; [TreatNullAs=EmptyString] attribute DOMString fontStyle; [TreatNullAs=EmptyString] attribute DOMString fontVariant; [TreatNullAs=EmptyString] attribute DOMString fontWeight; diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index c4833972501..652276d37da 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1149,6 +1149,9 @@ pub mod longhands { } + ${single_keyword("font-stretch", + "normal ultra-condensed extra-condensed condensed semi-condensed semi-expanded expanded extra-expanded ultra-expanded")} + // CSS 2.1, Section 16 - Text ${new_style_struct("InheritedText", is_inherited=True)} diff --git a/tests/html/font_stretch.html b/tests/html/font_stretch.html new file mode 100644 index 00000000000..1d5e1809217 --- /dev/null +++ b/tests/html/font_stretch.html @@ -0,0 +1,24 @@ + + + + + + +
Felis silvestris catus
+
Felis silvestris catus
+ + +