diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index bb274e74672..55829ae78d4 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -634,7 +634,7 @@ impl DisplayItem { render_context.font_ctx.get_render_font_from_template( &text.text_run.font_template, - text.text_run.pt_size, + text.text_run.actual_pt_size, render_context.opts.render_backend ).borrow().draw_text_into_context( render_context, diff --git a/components/gfx/font.rs b/components/gfx/font.rs index 5d4af74d0a9..b3f85edf823 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -8,7 +8,7 @@ use std::string; use std::rc::Rc; use std::cell::RefCell; use servo_util::cache::{Cache, HashCache}; -use style::computed_values::{font_weight, font_style}; +use style::computed_values::{font_weight, font_style, font_variant}; use sync::Arc; use servo_util::geometry::Au; @@ -93,7 +93,8 @@ pub struct FontStyle { pub weight: font_weight::T, pub style: font_style::T, pub families: Vec, - // TODO(Issue #198): font-stretch, text-decoration, font-variant, size-adjust + pub variant: font_variant::T, + // TODO(Issue #198): font-stretch, text-decoration, size-adjust } pub type SpecifiedFontStyle = FontStyle; @@ -102,8 +103,10 @@ pub type UsedFontStyle = FontStyle; pub struct Font { pub handle: FontHandle, pub metrics: FontMetrics, + pub variant: font_variant::T, pub descriptor: FontTemplateDescriptor, - pub pt_size: f64, + pub requested_pt_size: f64, + pub actual_pt_size: f64, pub shaper: Option, pub shape_cache: HashCache>, pub glyph_advance_cache: HashCache, @@ -147,6 +150,10 @@ impl Font { } pub fn glyph_index(&self, codepoint: char) -> Option { + let codepoint = match self.variant { + font_variant::small_caps => codepoint.to_uppercase(), + font_variant::normal => codepoint, + }; self.handle.glyph_index(codepoint) } diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 3520da107f5..42a67cf0151 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -5,7 +5,7 @@ use font::{Font, FontGroup}; use font::SpecifiedFontStyle; use platform::font_context::FontContextHandle; -use style::computed_values::font_style; +use style::computed_values::{font_style, font_variant}; use font_cache_task::FontCacheTask; use font_template::FontTemplateDescriptor; @@ -38,6 +38,8 @@ fn create_scaled_font(backend: BackendType, template: &Arc, pt ScaledFont::new(backend, &cgfont, pt_size as AzFloat) } +static SMALL_CAPS_SCALE_FACTOR: f64 = 0.8; // Matches FireFox (see gfxFont.h) + struct LayoutFontCacheEntry { family: String, font: Rc>, @@ -80,16 +82,27 @@ impl FontContext { /// Create a font for use in layout calculations. fn create_layout_font(&self, template: Arc, - descriptor: FontTemplateDescriptor, pt_size: f64) -> Font { + descriptor: FontTemplateDescriptor, pt_size: f64, + variant: font_variant::T) -> Font { + // TODO: (Bug #3463): Currently we only support fake small-caps + // rendering. We should also support true small-caps (where the + // font supports it) in the future. + let actual_pt_size = match variant { + font_variant::small_caps => pt_size * SMALL_CAPS_SCALE_FACTOR, + font_variant::normal => pt_size, + }; - let handle: FontHandle = FontHandleMethods::new_from_template(&self.platform_handle, template, Some(pt_size)).unwrap(); + let handle: FontHandle = FontHandleMethods::new_from_template(&self.platform_handle, + template, Some(actual_pt_size)).unwrap(); let metrics = handle.get_metrics(); Font { handle: handle, shaper: None, + variant: variant, descriptor: descriptor, - pt_size: pt_size, + requested_pt_size: pt_size, + actual_pt_size: actual_pt_size, metrics: metrics, shape_cache: HashCache::new(), glyph_advance_cache: HashCache::new(), @@ -114,7 +127,8 @@ impl FontContext { if cached_font_entry.family == *family { let cached_font = cached_font_entry.font.borrow(); if cached_font.descriptor == desc && - cached_font.pt_size == style.pt_size { + cached_font.requested_pt_size == style.pt_size && + cached_font.variant == style.variant { fonts.push(cached_font_entry.font.clone()); cache_hit = true; break; @@ -124,7 +138,8 @@ impl FontContext { if !cache_hit { let font_template = self.font_cache_task.get_font_template(family.clone(), desc.clone()); - let layout_font = Rc::new(RefCell::new(self.create_layout_font(font_template, desc.clone(), style.pt_size))); + let layout_font = Rc::new(RefCell::new(self.create_layout_font(font_template, + desc.clone(), style.pt_size, style.variant))); self.layout_font_cache.push(LayoutFontCacheEntry { family: family.clone(), font: layout_font.clone(), diff --git a/components/gfx/text/shaping/harfbuzz.rs b/components/gfx/text/shaping/harfbuzz.rs index f41ea82cf6d..674e5f7bcec 100644 --- a/components/gfx/text/shaping/harfbuzz.rs +++ b/components/gfx/text/shaping/harfbuzz.rs @@ -164,7 +164,7 @@ impl Shaper { let hb_font: *mut hb_font_t = hb_font_create(hb_face); // Set points-per-em. if zero, performs no hinting in that direction. - let pt_size = font.pt_size; + let pt_size = font.actual_pt_size; hb_font_set_ppem(hb_font, pt_size as c_uint, pt_size as c_uint); // Set scaling. Note that this takes 16.16 fixed point. diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index 57ca437e4f2..cdf7e5c9ddf 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -17,7 +17,7 @@ use platform::font_template::FontTemplateData; pub struct TextRun { pub text: Arc, pub font_template: Arc, - pub pt_size: f64, + pub actual_pt_size: f64, pub font_metrics: FontMetrics, /// The glyph runs that make up this text run. pub glyphs: Arc>, @@ -123,7 +123,7 @@ impl<'a> TextRun { text: Arc::new(text), font_metrics: font.metrics.clone(), font_template: font.handle.get_template(), - pt_size: font.pt_size, + actual_pt_size: font.actual_pt_size, glyphs: Arc::new(glyphs), }; return run; diff --git a/components/layout/text.rs b/components/layout/text.rs index e2ab1d545d5..36384e24290 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -309,6 +309,7 @@ pub fn computed_style_to_font_style(style: &ComputedValues) -> FontStyle { pt_size: font_size, weight: style.get_font().font_weight, style: style.get_font().font_style, + variant: style.get_font().font_variant, families: font_families.collect(), } } diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index 5f457dfcd49..d45a413caaf 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -802,7 +802,7 @@ pub mod longhands { ${single_keyword("font-style", "normal italic oblique")} - ${single_keyword("font-variant", "normal")} // Add small-caps when supported + ${single_keyword("font-variant", "normal small-caps")} <%self:single_component_value name="font-weight"> #[deriving(Clone)]