mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
layout: Implement text-rendering
per SVG 1.1 § 11.7.4.
Like Gecko, we treat `geometricprecision` the same as `optimizelegibility` for now.
This commit is contained in:
parent
112ab49706
commit
53b74ae853
5 changed files with 60 additions and 10 deletions
|
@ -105,7 +105,9 @@ bitflags! {
|
||||||
#[doc="Set if the text is entirely whitespace."]
|
#[doc="Set if the text is entirely whitespace."]
|
||||||
const IS_WHITESPACE_SHAPING_FLAG = 0x01,
|
const IS_WHITESPACE_SHAPING_FLAG = 0x01,
|
||||||
#[doc="Set if we are to ignore ligatures."]
|
#[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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
extern crate harfbuzz;
|
extern crate harfbuzz;
|
||||||
|
|
||||||
use font::{Font, FontHandleMethods, FontTableMethods, FontTableTag, IGNORE_LIGATURES_SHAPING_FLAG};
|
use font::{DISABLE_KERNING_SHAPING_FLAG, Font, FontHandleMethods, FontTableMethods, FontTableTag};
|
||||||
use font::{ShapingOptions};
|
use font::{IGNORE_LIGATURES_SHAPING_FLAG, ShapingOptions};
|
||||||
use platform::font::FontTable;
|
use platform::font::FontTable;
|
||||||
use text::glyph::{CharIndex, GlyphStore, GlyphId, GlyphData};
|
use text::glyph::{CharIndex, GlyphStore, GlyphId, GlyphData};
|
||||||
use text::shaping::ShaperMethods;
|
use text::shaping::ShaperMethods;
|
||||||
|
@ -50,6 +50,8 @@ use std::ptr;
|
||||||
static NO_GLYPH: i32 = -1;
|
static NO_GLYPH: i32 = -1;
|
||||||
static CONTINUATION_BYTE: i32 = -2;
|
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) |
|
static LIGA: u32 = ((b'l' as u32) << 24) | ((b'i' as u32) << 16) | ((b'g' as u32) << 8) |
|
||||||
(b'a' as u32);
|
(b'a' as u32);
|
||||||
|
|
||||||
|
@ -242,6 +244,14 @@ impl ShaperMethods for Shaper {
|
||||||
_end: hb_buffer_get_length(hb_buffer),
|
_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);
|
hb_shape(self.hb_font, hb_buffer, features.as_mut_ptr(), features.len() as u32);
|
||||||
self.save_glyph_results(text, options, glyphs, hb_buffer);
|
self.save_glyph_results(text, options, glyphs, hb_buffer);
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
use fragment::{Fragment, SpecificFragmentInfo, ScannedTextFragmentInfo};
|
use fragment::{Fragment, SpecificFragmentInfo, ScannedTextFragmentInfo};
|
||||||
use inline::InlineFragments;
|
use inline::InlineFragments;
|
||||||
|
|
||||||
use gfx::font::{FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG, RunMetrics, ShapingFlags};
|
use gfx::font::{DISABLE_KERNING_SHAPING_FLAG, FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG};
|
||||||
use gfx::font::{ShapingOptions};
|
use gfx::font::{RunMetrics, ShapingFlags, ShapingOptions};
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
use gfx::text::glyph::CharIndex;
|
use gfx::text::glyph::CharIndex;
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
|
@ -23,7 +23,8 @@ use servo_util::smallvec::{SmallVec, SmallVec1};
|
||||||
use std::collections::DList;
|
use std::collections::DList;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use style::ComputedValues;
|
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 style::style_structs::Font as FontStyle;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -108,6 +109,7 @@ impl TextRunScanner {
|
||||||
let text_transform;
|
let text_transform;
|
||||||
let letter_spacing;
|
let letter_spacing;
|
||||||
let word_spacing;
|
let word_spacing;
|
||||||
|
let text_rendering;
|
||||||
{
|
{
|
||||||
let in_fragment = self.clump.front().unwrap();
|
let in_fragment = self.clump.front().unwrap();
|
||||||
let font_style = in_fragment.style().get_font_arc();
|
let font_style = in_fragment.style().get_font_arc();
|
||||||
|
@ -120,6 +122,7 @@ impl TextRunScanner {
|
||||||
text_transform = inherited_text_style.text_transform;
|
text_transform = inherited_text_style.text_transform;
|
||||||
letter_spacing = inherited_text_style.letter_spacing;
|
letter_spacing = inherited_text_style.letter_spacing;
|
||||||
word_spacing = inherited_text_style.word_spacing.unwrap_or(Au(0));
|
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.
|
// 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
|
// 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
|
// example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not
|
||||||
// `fi n a l l y`.
|
// `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 {
|
let options = ShapingOptions {
|
||||||
letter_spacing: letter_spacing,
|
letter_spacing: letter_spacing,
|
||||||
word_spacing: word_spacing,
|
word_spacing: word_spacing,
|
||||||
flags: match letter_spacing {
|
flags: flags,
|
||||||
Some(Au(0)) | None => ShapingFlags::empty(),
|
|
||||||
Some(_) => IGNORE_LIGATURES_SHAPING_FLAG,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Arc::new(box TextRun::new(&mut *fontgroup.fonts.get(0).borrow_mut(),
|
Arc::new(box TextRun::new(&mut *fontgroup.fonts.get(0).borrow_mut(),
|
||||||
|
|
|
@ -1483,6 +1483,8 @@ pub mod longhands {
|
||||||
// TODO(pcwalton): `full-width`
|
// TODO(pcwalton): `full-width`
|
||||||
${single_keyword("text-transform", "none capitalize uppercase lowercase")}
|
${single_keyword("text-transform", "none capitalize uppercase lowercase")}
|
||||||
|
|
||||||
|
${single_keyword("text-rendering", "auto optimizespeed optimizelegibility geometricprecision")}
|
||||||
|
|
||||||
// CSS 2.1, Section 17 - Tables
|
// CSS 2.1, Section 17 - Tables
|
||||||
${new_style_struct("Table", is_inherited=False)}
|
${new_style_struct("Table", is_inherited=False)}
|
||||||
|
|
||||||
|
|
27
tests/html/text_rendering.html
Normal file
27
tests/html/text_rendering.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-size: 24pt;
|
||||||
|
font-family: "PT Sans";
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#a {
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
}
|
||||||
|
#b {
|
||||||
|
text-rendering: geometricprecision;
|
||||||
|
}
|
||||||
|
#c {
|
||||||
|
text-rendering: optimizespeed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=a>Harry finally caught the Snitch.</div>
|
||||||
|
<div id=b>Harry finally caught the Snitch.</div>
|
||||||
|
<div id=c>Harry finally caught the Snitch.</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue