diff --git a/components/gfx/font.rs b/components/gfx/font.rs index 270e0447ed1..3c6379988bc 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -105,7 +105,9 @@ bitflags! { #[doc="Set if the text is entirely whitespace."] const IS_WHITESPACE_SHAPING_FLAG = 0x01, #[doc="Set if we are to ignore ligatures."] - const IGNORE_LIGATURES_SHAPING_FLAG = 0x02 + const IGNORE_LIGATURES_SHAPING_FLAG = 0x02, + #[doc="Set if we are to disable kerning."] + const DISABLE_KERNING_SHAPING_FLAG = 0x04 } } diff --git a/components/gfx/text/shaping/harfbuzz.rs b/components/gfx/text/shaping/harfbuzz.rs index 11c01a65948..813e4aa33f7 100644 --- a/components/gfx/text/shaping/harfbuzz.rs +++ b/components/gfx/text/shaping/harfbuzz.rs @@ -4,8 +4,8 @@ extern crate harfbuzz; -use font::{Font, FontHandleMethods, FontTableMethods, FontTableTag, IGNORE_LIGATURES_SHAPING_FLAG}; -use font::{ShapingOptions}; +use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontHandleMethods, FontTableMethods, FontTableTag}; +use font::{IGNORE_LIGATURES_SHAPING_FLAG, ShapingOptions}; use platform::font::FontTable; use text::glyph::{CharIndex, GlyphStore, GlyphId, GlyphData}; use text::shaping::ShaperMethods; @@ -50,6 +50,8 @@ use std::ptr; static NO_GLYPH: i32 = -1; static CONTINUATION_BYTE: i32 = -2; +static KERN: u32 = ((b'k' as u32) << 24) | ((b'e' as u32) << 16) | ((b'r' as u32) << 8) | + (b'n' as u32); static LIGA: u32 = ((b'l' as u32) << 24) | ((b'i' as u32) << 16) | ((b'g' as u32) << 8) | (b'a' as u32); @@ -242,6 +244,14 @@ impl ShaperMethods for Shaper { _end: hb_buffer_get_length(hb_buffer), }) } + if options.flags.contains(DISABLE_KERNING_SHAPING_FLAG) { + features.push(hb_feature_t { + _tag: KERN, + _value: 0, + _start: 0, + _end: hb_buffer_get_length(hb_buffer), + }) + } hb_shape(self.hb_font, hb_buffer, features.as_mut_ptr(), features.len() as u32); self.save_glyph_results(text, options, glyphs, hb_buffer); diff --git a/components/layout/text.rs b/components/layout/text.rs index e92197b7257..ae4ad5ec0de 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -9,8 +9,8 @@ use fragment::{Fragment, SpecificFragmentInfo, ScannedTextFragmentInfo}; use inline::InlineFragments; -use gfx::font::{FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG, RunMetrics, ShapingFlags}; -use gfx::font::{ShapingOptions}; +use gfx::font::{DISABLE_KERNING_SHAPING_FLAG, FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG}; +use gfx::font::{RunMetrics, ShapingFlags, ShapingOptions}; use gfx::font_context::FontContext; use gfx::text::glyph::CharIndex; use gfx::text::text_run::TextRun; @@ -23,7 +23,8 @@ use servo_util::smallvec::{SmallVec, SmallVec1}; use std::collections::DList; use std::mem; use style::ComputedValues; -use style::computed_values::{line_height, text_orientation, text_transform, white_space}; +use style::computed_values::{line_height, text_orientation, text_rendering, text_transform}; +use style::computed_values::{white_space}; use style::style_structs::Font as FontStyle; use std::sync::Arc; @@ -108,6 +109,7 @@ impl TextRunScanner { let text_transform; let letter_spacing; let word_spacing; + let text_rendering; { let in_fragment = self.clump.front().unwrap(); let font_style = in_fragment.style().get_font_arc(); @@ -120,6 +122,7 @@ impl TextRunScanner { text_transform = inherited_text_style.text_transform; letter_spacing = inherited_text_style.letter_spacing; word_spacing = inherited_text_style.word_spacing.unwrap_or(Au(0)); + text_rendering = inherited_text_style.text_rendering; } // First, transform/compress text of all the nodes. @@ -161,13 +164,19 @@ impl TextRunScanner { // as the default space, user agents should not use ligatures." This ensures that, for // example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not // `fi n a l l y`. + let mut flags = ShapingFlags::empty(); + match letter_spacing { + Some(Au(0)) | None => {} + Some(_) => flags.insert(IGNORE_LIGATURES_SHAPING_FLAG), + } + if text_rendering == text_rendering::T::optimizespeed { + flags.insert(IGNORE_LIGATURES_SHAPING_FLAG); + flags.insert(DISABLE_KERNING_SHAPING_FLAG) + } let options = ShapingOptions { letter_spacing: letter_spacing, word_spacing: word_spacing, - flags: match letter_spacing { - Some(Au(0)) | None => ShapingFlags::empty(), - Some(_) => IGNORE_LIGATURES_SHAPING_FLAG, - }, + flags: flags, }; Arc::new(box TextRun::new(&mut *fontgroup.fonts.get(0).borrow_mut(), diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index 3726152f026..fc4a49d1848 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1483,6 +1483,8 @@ pub mod longhands { // TODO(pcwalton): `full-width` ${single_keyword("text-transform", "none capitalize uppercase lowercase")} + ${single_keyword("text-rendering", "auto optimizespeed optimizelegibility geometricprecision")} + // CSS 2.1, Section 17 - Tables ${new_style_struct("Table", is_inherited=False)} diff --git a/tests/html/text_rendering.html b/tests/html/text_rendering.html new file mode 100644 index 00000000000..13e69236f4f --- /dev/null +++ b/tests/html/text_rendering.html @@ -0,0 +1,27 @@ + + +
+ + + +