mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Extract mono-cache implementation; lay groundwork for private font matching.
This commit is contained in:
parent
a3f4b52c90
commit
b8d7824067
18 changed files with 372 additions and 88 deletions
|
@ -10,7 +10,11 @@ pub use dl = display_list;
|
|||
|
||||
pub use display_list::DisplayList;
|
||||
pub use font::Font;
|
||||
pub use font_cache::FontCache;
|
||||
pub use font::FontDescriptor;
|
||||
pub use font::FontGroup;
|
||||
pub use font::FontSelector;
|
||||
pub use font::FontStyle;
|
||||
pub use font::RunMetrics;
|
||||
pub use font_context::FontContext;
|
||||
pub use font_matcher::FontMatcher;
|
||||
pub use geometry::Au;
|
||||
|
|
|
@ -49,7 +49,7 @@ impl DisplayItem {
|
|||
match *self {
|
||||
SolidColor(_, color) => ctx.draw_solid_color(&self.d().bounds, color),
|
||||
Text(_, run, range) => {
|
||||
let new_run = @run.deserialize(ctx.font_cache);
|
||||
let new_run = @run.deserialize(ctx.font_ctx);
|
||||
let font = new_run.font;
|
||||
let origin = self.d().bounds.origin;
|
||||
let baseline_origin = Point2D(origin.x, origin.y + font.metrics.ascent);
|
||||
|
|
|
@ -38,23 +38,147 @@ enum CSSFontWeight {
|
|||
FontWeight800,
|
||||
FontWeight900,
|
||||
}
|
||||
pub impl CSSFontWeight : cmp::Eq;
|
||||
|
||||
struct FontStyle {
|
||||
// TODO: eventually this will be split into the specified and used
|
||||
// font styles. specified contains uninterpreted CSS font property
|
||||
// values, while 'used' is attached to gfx::Font to descript the
|
||||
// instance's properties.
|
||||
//
|
||||
// For now, the cases are differentiated with a typedef
|
||||
pub struct FontStyle {
|
||||
pt_size: float,
|
||||
weight: CSSFontWeight,
|
||||
italic: bool,
|
||||
oblique: bool,
|
||||
families: ~str,
|
||||
// TODO: font-stretch, text-decoration, font-variant, size-adjust
|
||||
}
|
||||
|
||||
struct FontFaceProperties {
|
||||
// TODO(Issue #181): use deriving for trivial cmp::Eq implementations
|
||||
pub impl FontStyle : cmp::Eq {
|
||||
pure fn eq(other: &FontStyle) -> bool {
|
||||
use std::cmp::FuzzyEq;
|
||||
|
||||
self.pt_size.fuzzy_eq(&other.pt_size) &&
|
||||
self.weight == other.weight &&
|
||||
self.italic == other.italic &&
|
||||
self.oblique == other.oblique &&
|
||||
self.families == other.families
|
||||
}
|
||||
pure fn ne(other: &FontStyle) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
pub type SpecifiedFontStyle = FontStyle;
|
||||
pub type UsedFontStyle = FontStyle;
|
||||
|
||||
// TODO: move me to layout
|
||||
struct ResolvedFont {
|
||||
group: @FontGroup,
|
||||
style: SpecifiedFontStyle,
|
||||
}
|
||||
|
||||
// FontDescriptor serializes a specific font and used font style
|
||||
// options, such as point size.
|
||||
|
||||
// It's used to swizzle/unswizzle gfx::Font instances when
|
||||
// communicating across tasks, such as the display list between layout
|
||||
// and render tasks.
|
||||
pub struct FontDescriptor {
|
||||
style: UsedFontStyle,
|
||||
selector: FontSelector,
|
||||
}
|
||||
|
||||
|
||||
// TODO(Issue #181): use deriving for trivial cmp::Eq implementations
|
||||
pub impl FontDescriptor : cmp::Eq {
|
||||
pure fn eq(other: &FontDescriptor) -> bool {
|
||||
self.style == other.style &&
|
||||
self.selector == other.selector
|
||||
}
|
||||
pure fn ne(other: &FontDescriptor) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
pub impl FontDescriptor {
|
||||
static pure fn new(style: &UsedFontStyle, selector: &FontSelector) -> FontDescriptor {
|
||||
FontDescriptor {
|
||||
style: copy *style,
|
||||
selector: copy *selector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A FontSelector is a platform-specific strategy for serializing face names.
|
||||
pub enum FontSelector {
|
||||
SelectorPlatformName(~str),
|
||||
SelectorStubDummy, // aka, use Josephin Sans
|
||||
}
|
||||
|
||||
// TODO(Issue #181): use deriving for trivial cmp::Eq implementations
|
||||
pub impl FontSelector : cmp::Eq {
|
||||
pure fn eq(other: &FontSelector) -> bool {
|
||||
match (self, *other) {
|
||||
(SelectorStubDummy, SelectorStubDummy) => true,
|
||||
(SelectorPlatformName(a), SelectorPlatformName(b)) => a == b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
pure fn ne(other: &FontSelector) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
// Holds a specific font family, and the various
|
||||
pub struct FontFamily {
|
||||
family_name: @str,
|
||||
face_name: ~str,
|
||||
priv weight: u16,
|
||||
priv italic: bool,
|
||||
entries: ~[@FontEntry],
|
||||
}
|
||||
|
||||
impl FontFaceProperties {
|
||||
pure fn is_bold() -> bool { self.weight >= (500 as u16) }
|
||||
// This struct is the result of mapping a specified FontStyle into the
|
||||
// available fonts on the system. It contains an ordered list of font
|
||||
// instances to be used in case the prior font cannot be used for
|
||||
// rendering the specified language.
|
||||
|
||||
// The ordering of font instances is mainly decided by the CSS
|
||||
// 'font-family' property. The last font is a system fallback font.
|
||||
pub struct FontGroup {
|
||||
families: @str,
|
||||
// style of the first western font in group, which is
|
||||
// used for purposes of calculating text run metrics.
|
||||
style: UsedFontStyle,
|
||||
fonts: ~[@Font],
|
||||
}
|
||||
|
||||
pub impl FontGroup {
|
||||
static fn new(families: @str, style: &UsedFontStyle, fonts: ~[@Font]) -> FontGroup {
|
||||
FontGroup {
|
||||
families: families,
|
||||
style: copy *style,
|
||||
fonts: move fonts,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This struct summarizes an available font's features. In the future,
|
||||
// this will include fiddly settings such as special font table handling.
|
||||
|
||||
// In the common case, each FontFamily will have a singleton FontEntry, or
|
||||
// it will have the standard four faces: Normal, Bold, Italic, BoldItalic.
|
||||
struct FontEntry {
|
||||
family: @FontFamily,
|
||||
face_name: ~str,
|
||||
priv weight: CSSFontWeight,
|
||||
priv italic: bool,
|
||||
// TODO: array of OpenType features, etc.
|
||||
}
|
||||
|
||||
impl FontEntry {
|
||||
pure fn is_bold() -> bool {
|
||||
match self.weight {
|
||||
FontWeight900 | FontWeight800 | FontWeight700 | FontWeight600 => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pure fn is_italic() -> bool { self.italic }
|
||||
}
|
||||
|
||||
|
@ -69,7 +193,7 @@ struct RunMetrics {
|
|||
}
|
||||
|
||||
/**
|
||||
A font handle. Layout can use this to calculate glyph metrics
|
||||
A font instance. Layout can use this to calculate glyph metrics
|
||||
and the renderer can use it to render text.
|
||||
*/
|
||||
struct Font {
|
||||
|
@ -77,7 +201,7 @@ struct Font {
|
|||
priv handle: FontHandle,
|
||||
priv mut azure_font: Option<AzScaledFontRef>,
|
||||
priv mut shaper: Option<@Shaper>,
|
||||
style: FontStyle,
|
||||
style: UsedFontStyle,
|
||||
metrics: FontMetrics,
|
||||
|
||||
drop {
|
||||
|
@ -88,7 +212,7 @@ struct Font {
|
|||
|
||||
impl Font {
|
||||
// TODO: who should own fontbuf?
|
||||
static fn new(fontbuf: @~[u8], handle: FontHandle, style: FontStyle) -> Font {
|
||||
static fn new(fontbuf: @~[u8], handle: FontHandle, style: UsedFontStyle) -> Font {
|
||||
let metrics = handle.get_metrics();
|
||||
|
||||
Font {
|
||||
|
@ -214,6 +338,7 @@ pub trait FontMethods {
|
|||
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>);
|
||||
fn measure_text(&TextRun, Range) -> RunMetrics;
|
||||
fn shape_text(@self, &str) -> GlyphStore;
|
||||
fn get_descriptor() -> FontDescriptor;
|
||||
|
||||
fn buf(&self) -> @~[u8];
|
||||
// these are used to get glyphs and advances in the case that the
|
||||
|
@ -315,6 +440,12 @@ pub impl Font : FontMethods {
|
|||
return move store;
|
||||
}
|
||||
|
||||
fn get_descriptor() -> FontDescriptor {
|
||||
// TODO(Issue #174): implement by-platform-name FontSelectors,
|
||||
// probably by adding such an API to FontHandle.
|
||||
FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy)
|
||||
}
|
||||
|
||||
fn buf(&self) -> @~[u8] {
|
||||
self.fontbuf
|
||||
}
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
/*
|
||||
use font::{Font, FontStyle, FontWeight300};
|
||||
use native::{FontHandle, FontContext};
|
||||
|
||||
// TODO(Issue #164): delete, and get default font from font list
|
||||
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
|
||||
|
||||
fn test_font_bin() -> ~[u8] {
|
||||
return vec::from_fn(33004, |i| TEST_FONT[i]);
|
||||
}
|
||||
|
||||
// Dummy font cache.
|
||||
// Font cache that reuses gfx::Font instances.
|
||||
|
||||
struct FontCache {
|
||||
fctx: @FontContext,
|
||||
|
@ -24,36 +18,19 @@ impl FontCache {
|
|||
}
|
||||
|
||||
pub fn get_test_font(@self) -> @Font {
|
||||
let dummy_style = FontStyle {
|
||||
pt_size: 40f,
|
||||
weight: FontWeight300,
|
||||
italic: false,
|
||||
oblique: false
|
||||
};
|
||||
|
||||
|
||||
return match self.cached_font {
|
||||
Some(font) => font,
|
||||
None => match self.get_font(&dummy_style) {
|
||||
Ok(font) => { self.cached_font = Some(font); font }
|
||||
Err(*) => /* FIXME */ fail
|
||||
Err(*) => fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: maybe FontStyle should be canonicalized when used in FontCache?
|
||||
priv fn create_font(style: &FontStyle) -> Result<@Font, ()> {
|
||||
let font_bin = @test_font_bin();
|
||||
let native_font = FontHandle::new(self.fctx, font_bin, style.pt_size);
|
||||
let native_font = if native_font.is_ok() {
|
||||
result::unwrap(move native_font)
|
||||
} else {
|
||||
return Err(native_font.get_err());
|
||||
};
|
||||
|
||||
return Ok(@Font::new(font_bin, move native_font, copy *style));
|
||||
}
|
||||
|
||||
pub fn get_font(@self, style: &FontStyle) -> Result<@Font, ()> {
|
||||
self.create_font(style)
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -1,3 +1,34 @@
|
|||
use dvec::DVec;
|
||||
|
||||
use util::cache;
|
||||
use gfx::{
|
||||
FontDescriptor,
|
||||
FontSelector,
|
||||
FontStyle,
|
||||
};
|
||||
use gfx::font::{SelectorPlatformName, SelectorStubDummy, SpecifiedFontStyle};
|
||||
use gfx::native::FontHandle;
|
||||
|
||||
// TODO(Issue #164): delete, and get default font from font list
|
||||
const TEST_FONT: [u8 * 33004] = #include_bin("JosefinSans-SemiBold.ttf");
|
||||
|
||||
fn test_font_bin() -> ~[u8] {
|
||||
return vec::from_fn(33004, |i| TEST_FONT[i]);
|
||||
}
|
||||
|
||||
// TODO(Rust #3934): creating lots of new dummy styles is a workaround
|
||||
// for not being able to store symbolic enums in top-level constants.
|
||||
pub fn dummy_style() -> FontStyle {
|
||||
use gfx::font::FontWeight300;
|
||||
return FontStyle {
|
||||
pt_size: 20f,
|
||||
weight: FontWeight300,
|
||||
italic: false,
|
||||
oblique: false,
|
||||
families: ~"Helvetica, serif",
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(Issue #163): this is a workaround for static methods and
|
||||
// typedefs not working well together. It should be removed.
|
||||
|
||||
|
@ -5,21 +36,91 @@
|
|||
// to conditionally define the entire impl.
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
type FontContext/& = quartz::font_context::QuartzFontContext;
|
||||
type FontContextHandle/& = quartz::font_context::QuartzFontContext;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
type FontContext/& = freetype::font_context::FreeTypeFontContext;
|
||||
type FontContextHandle/& = freetype::font_context::FreeTypeFontContext;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub impl FontContext {
|
||||
static pub fn new() -> FontContext {
|
||||
pub impl FontContextHandle {
|
||||
static pub fn new() -> FontContextHandle {
|
||||
quartz::font_context::QuartzFontContext::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub impl FontContext {
|
||||
static pub fn new() -> FontContext {
|
||||
pub impl FontContextHandle {
|
||||
static pub fn new() -> FontContextHandle {
|
||||
freetype::font_context::FreeTypeFontContext::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FontContext {
|
||||
instance_cache: cache::MonoCache<FontDescriptor, @Font>,
|
||||
handle: FontContextHandle,
|
||||
}
|
||||
|
||||
pub impl FontContext {
|
||||
static fn new() -> FontContext {
|
||||
FontContext {
|
||||
// TODO(Rust #3902): remove extraneous type parameters once they are inferred correctly.
|
||||
instance_cache: cache::new::<FontDescriptor, @Font, cache::MonoCache<FontDescriptor, @Font>>(10),
|
||||
handle: FontContextHandle::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_resolved_font_for_style(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||
// TODO(Issue #178, E): implement a cache of FontGroup instances.
|
||||
self.create_font_group(style)
|
||||
}
|
||||
|
||||
fn get_font_by_descriptor(desc: &FontDescriptor) -> Result<@Font, ()> {
|
||||
match self.instance_cache.find(desc) {
|
||||
Some(f) => Ok(f),
|
||||
None => {
|
||||
let result = self.create_font_instance(desc);
|
||||
match result {
|
||||
Ok(font) => {
|
||||
self.instance_cache.insert(desc, font);
|
||||
}, _ => {}
|
||||
};
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
priv fn create_font_group(style: &SpecifiedFontStyle) -> @FontGroup {
|
||||
// TODO(Issue #178, D): implement private font matching
|
||||
// TODO(Issue #174): implement by-platform-name FontSelectors
|
||||
let desc = FontDescriptor::new(&font_context::dummy_style(), &SelectorStubDummy);
|
||||
let fonts = DVec();
|
||||
match self.get_font_by_descriptor(&desc) {
|
||||
Ok(instance) => fonts.push(instance),
|
||||
Err(()) => {}
|
||||
}
|
||||
|
||||
assert fonts.len() > 0;
|
||||
// TODO(Issue #179): Split FontStyle into specified and used styles
|
||||
let used_style = copy *style;
|
||||
|
||||
@FontGroup::new(style.families.to_managed(), &used_style, dvec::unwrap(move fonts))
|
||||
}
|
||||
|
||||
priv fn create_font_instance(desc: &FontDescriptor) -> Result<@Font, ()> {
|
||||
match desc.selector {
|
||||
SelectorStubDummy => {
|
||||
let font_bin = @test_font_bin();
|
||||
let handle = FontHandle::new(&self.handle, font_bin, desc.style.pt_size);
|
||||
let handle = if handle.is_ok() {
|
||||
result::unwrap(move handle)
|
||||
} else {
|
||||
return Err(handle.get_err());
|
||||
};
|
||||
|
||||
return Ok(@Font::new(font_bin, move handle, copy desc.style));
|
||||
},
|
||||
// TODO(Issue #174): implement by-platform-name font selectors.
|
||||
SelectorPlatformName(_) => { fail ~"FontContext::create_font_instance() can't yet handle SelectorPlatformName." }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,14 +20,14 @@ pub type FontHandle/& = freetype::font_handle::FreeTypeFontHandle;
|
|||
// to conditionally define the entire impl.
|
||||
#[cfg(target_os = "macos")]
|
||||
impl FontHandle {
|
||||
static pub fn new(fctx: &native::FontContext, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
quartz::font_handle::QuartzFontHandle::new(fctx, buf, pt_size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl FontHandle {
|
||||
static pub fn new(fctx: &native::FontContext, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
static pub fn new(fctx: &native::FontContextHandle, buf: @~[u8], pt_size: float) -> Result<FontHandle, ()> {
|
||||
freetype::font_handle::FreeTypeFontHandle::new(fctx, buf, pt_size)
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
extern mod harfbuzz;
|
||||
|
||||
use gfx::au;
|
||||
use gfx::{
|
||||
au,
|
||||
|
||||
Au,
|
||||
Font,
|
||||
FontCache,
|
||||
};
|
||||
|
||||
use geom::point::Point2D;
|
||||
|
|
|
@ -5,4 +5,4 @@ Note that you still must define each of the files as a module in
|
|||
servo.rc. This is not ideal and may be changed in the future. */
|
||||
|
||||
pub use font_handle::FontHandle;
|
||||
pub use font_context::FontContext;
|
||||
pub use font_context::FontContextHandle;
|
|
@ -1,12 +1,12 @@
|
|||
use au = geometry;
|
||||
use compositor::LayerBuffer;
|
||||
use gfx::au;
|
||||
use gfx::{
|
||||
Au,
|
||||
Font,
|
||||
FontCache,
|
||||
FontContext,
|
||||
TextRun,
|
||||
};
|
||||
use image::base::Image;
|
||||
use au::Au;
|
||||
use util::range::Range;
|
||||
|
||||
use cairo::cairo_hl::ImageSurface;
|
||||
|
@ -23,7 +23,7 @@ use azure::azure_hl::{DrawTarget, Linear};
|
|||
|
||||
struct RenderContext {
|
||||
canvas: &LayerBuffer,
|
||||
font_cache: @FontCache,
|
||||
font_ctx: @FontContext,
|
||||
}
|
||||
|
||||
impl RenderContext {
|
||||
|
|
|
@ -9,7 +9,6 @@ use geom::matrix2d::Matrix2D;
|
|||
|
||||
use dl = display_list;
|
||||
use gfx::{
|
||||
FontCache,
|
||||
FontContext,
|
||||
RenderContext,
|
||||
RenderLayer,
|
||||
|
@ -42,7 +41,7 @@ pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask {
|
|||
port: po,
|
||||
compositor: move compositor,
|
||||
mut layer_buffer_set_port: Cell(move layer_buffer_set_port),
|
||||
font_cache: @FontCache::new(@FontContext::new()),
|
||||
font_ctx: @FontContext::new(),
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +50,7 @@ priv struct Renderer<C: Compositor Send> {
|
|||
port: comm::Port<Msg>,
|
||||
compositor: C,
|
||||
layer_buffer_set_port: Cell<pipes::Port<LayerBufferSet>>,
|
||||
font_cache: @FontCache
|
||||
font_ctx: @FontContext
|
||||
}
|
||||
|
||||
impl<C: Compositor Send> Renderer<C> {
|
||||
|
@ -97,7 +96,7 @@ impl<C: Compositor Send> Renderer<C> {
|
|||
|render_layer, layer_buffer| {
|
||||
let ctx = RenderContext {
|
||||
canvas: layer_buffer,
|
||||
font_cache: self.font_cache
|
||||
font_ctx: self.font_ctx
|
||||
};
|
||||
|
||||
// Apply the translation to render the tile we want.
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
use arc = std::arc;
|
||||
use arc::ARC;
|
||||
use au = gfx::geometry;
|
||||
use font::{RunMetrics, Font};
|
||||
use font_cache::FontCache;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use gfx::geometry::Au;
|
||||
use gfx::au;
|
||||
use gfx::{
|
||||
Au,
|
||||
Font,
|
||||
FontContext,
|
||||
FontDescriptor,
|
||||
RunMetrics,
|
||||
};
|
||||
use glyph::GlyphStore;
|
||||
use layout::context::LayoutContext;
|
||||
use libc::{c_void};
|
||||
|
@ -23,16 +27,20 @@ pub struct TextRun {
|
|||
// we instead use ARC<TextRun> everywhere.
|
||||
pub struct SendableTextRun {
|
||||
text: ~str,
|
||||
font_descriptor: (),
|
||||
font: FontDescriptor,
|
||||
priv glyphs: GlyphStore,
|
||||
}
|
||||
|
||||
impl SendableTextRun {
|
||||
pub fn deserialize(&self, cache: @FontCache) -> TextRun {
|
||||
pub fn deserialize(&self, fctx: @FontContext) -> TextRun {
|
||||
let font = match fctx.get_font_by_descriptor(&self.font) {
|
||||
Ok(f) => f,
|
||||
Err(_) => fail fmt!("Font descriptor deserialization failed! desc=%?", self.font)
|
||||
};
|
||||
|
||||
TextRun {
|
||||
text: copy self.text,
|
||||
// TODO: actually deserialize a font descriptor thingy
|
||||
font: cache.get_test_font(),
|
||||
font: font,
|
||||
glyphs: copy self.glyphs
|
||||
}
|
||||
}
|
||||
|
@ -49,11 +57,10 @@ impl TextRun {
|
|||
return move run;
|
||||
}
|
||||
|
||||
pub pure fn serialize(&self, _cache: @FontCache) -> SendableTextRun {
|
||||
pub fn serialize(&self) -> SendableTextRun {
|
||||
SendableTextRun {
|
||||
text: copy self.text,
|
||||
// TODO: actually serialize a font descriptor thingy
|
||||
font_descriptor: (),
|
||||
font: self.font.get_descriptor(),
|
||||
glyphs: copy self.glyphs,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,9 +409,7 @@ impl RenderBox : RenderBoxMethods {
|
|||
match *self {
|
||||
UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.",
|
||||
TextBox(_,d) => {
|
||||
list.append_item(~DisplayItem::new_Text(&abs_box_bounds,
|
||||
~d.run.serialize(builder.ctx.font_cache),
|
||||
d.range));
|
||||
list.append_item(~DisplayItem::new_Text(&abs_box_bounds, ~d.run.serialize(), d.range));
|
||||
// debug frames for text box bounds
|
||||
debug!("%?", {
|
||||
list.append_item(~DisplayItem::new_Border(&abs_box_bounds, au::from_px(1),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use geom::rect::Rect;
|
||||
use gfx::{
|
||||
Au,
|
||||
FontCache,
|
||||
FontContext,
|
||||
};
|
||||
use resource::local_image_cache::LocalImageCache;
|
||||
use std::net::url::Url;
|
||||
|
@ -9,7 +9,7 @@ use std::net::url::Url;
|
|||
/* Represents layout task context. */
|
||||
|
||||
struct LayoutContext {
|
||||
font_cache: @FontCache,
|
||||
font_ctx: @FontContext,
|
||||
image_cache: @LocalImageCache,
|
||||
doc_url: Url,
|
||||
screen_size: Rect<Au>
|
||||
|
|
|
@ -7,6 +7,7 @@ use geom::point::Point2D;
|
|||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use gfx::display_list::{DisplayList, DisplayListBuilder};
|
||||
use gfx::font::FontStyle;
|
||||
use gfx::geometry::Au;
|
||||
use layout::box::*;
|
||||
use layout::context::LayoutContext;
|
||||
|
@ -235,8 +236,13 @@ impl TextRunScanner {
|
|||
// TODO(Issue #115): use actual CSS 'white-space' property of relevant style.
|
||||
let compression = CompressWhitespaceNewline;
|
||||
let transformed_text = transform_text(text, compression);
|
||||
// TODO(Issue #116): use actual font for corresponding DOM node to create text run.
|
||||
let run = @TextRun::new(ctx.font_cache.get_test_font(), move transformed_text);
|
||||
// TODO(Issue #116): use actual font and style for corresponding
|
||||
// DOM node to create text run.
|
||||
// TODO(Issue #177): text run creation must account for text-renderability by fontgroup fonts.
|
||||
// this is probably achieved by creating fontgroup above, and then letting FontGroup decide
|
||||
// which Font to stick into the TextRun.
|
||||
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style());
|
||||
let run = @TextRun::new(fontgroup.fonts[0], move transformed_text);
|
||||
debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
|
||||
let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump.begin()].d(), run,
|
||||
Range(0, run.text.len()));
|
||||
|
@ -269,7 +275,11 @@ impl TextRunScanner {
|
|||
// create the run, then make new boxes with the run and adjusted text indices
|
||||
|
||||
// TODO(Issue #116): use actual font for corresponding DOM node to create text run.
|
||||
let run = @gfx::TextRun::new(ctx.font_cache.get_test_font(), move run_str);
|
||||
// TODO(Issue #177): text run creation must account for text-renderability by fontgroup fonts.
|
||||
// this is probably achieved by creating fontgroup above, and then letting FontGroup decide
|
||||
// which Font to stick into the TextRun.
|
||||
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&gfx::font_context::dummy_style());
|
||||
let run = @TextRun::new(fontgroup.fonts[0], move run_str);
|
||||
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
|
||||
for self.clump.eachi |i| {
|
||||
let range = new_ranges[i - self.clump.begin()];
|
||||
|
|
|
@ -11,11 +11,10 @@ use dom::node::{Node, LayoutData};
|
|||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use gfx::{au, dl};
|
||||
use gfx::{
|
||||
au, dl,
|
||||
Au,
|
||||
DisplayList,
|
||||
FontCache,
|
||||
FontContext,
|
||||
FontMatcher,
|
||||
RenderLayer,
|
||||
|
@ -81,7 +80,7 @@ struct Layout {
|
|||
local_image_cache: @LocalImageCache,
|
||||
from_content: comm::Port<Msg>,
|
||||
|
||||
font_cache: @FontCache,
|
||||
font_ctx: @FontContext,
|
||||
font_matcher: @FontMatcher,
|
||||
// This is used to root auxilliary RCU reader data
|
||||
layout_refs: DVec<@LayoutData>,
|
||||
|
@ -100,7 +99,7 @@ fn Layout(render_task: RenderTask,
|
|||
local_image_cache: @LocalImageCache(move image_cache_task),
|
||||
from_content: from_content,
|
||||
font_matcher: @FontMatcher::new(fctx),
|
||||
font_cache: @FontCache::new(fctx),
|
||||
font_ctx: fctx,
|
||||
layout_refs: DVec(),
|
||||
css_select_ctx: Mut(new_css_select_ctx())
|
||||
}
|
||||
|
@ -169,7 +168,7 @@ impl Layout {
|
|||
|
||||
let layout_ctx = LayoutContext {
|
||||
image_cache: self.local_image_cache,
|
||||
font_cache: self.font_cache,
|
||||
font_ctx: self.font_ctx,
|
||||
doc_url: move doc_url,
|
||||
screen_size: Rect(Point2D(Au(0), Au(0)), screen_size)
|
||||
};
|
||||
|
|
|
@ -142,6 +142,7 @@ pub mod resource {
|
|||
|
||||
pub mod util {
|
||||
pub mod actor;
|
||||
pub mod cache;
|
||||
pub mod range;
|
||||
pub mod text;
|
||||
pub mod time;
|
||||
|
|
59
src/servo/util/cache.rs
Normal file
59
src/servo/util/cache.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use core::cmp::*;
|
||||
|
||||
trait Cache<K: Copy Eq, V: Copy> {
|
||||
static fn new(size: uint) -> self;
|
||||
fn insert(key: &K, value: V);
|
||||
fn find(key: &K) -> Option<V>;
|
||||
fn find_or_create(key: &K, blk: pure fn&(&K) -> V) -> V;
|
||||
fn evict_all();
|
||||
}
|
||||
|
||||
pub struct MonoCache<K: Copy Eq, V: Copy> {
|
||||
mut entry: Option<(K,V)>,
|
||||
}
|
||||
|
||||
pub impl<K: Copy Eq, V: Copy> MonoCache<K,V> : Cache<K,V> {
|
||||
static fn new(_size: uint) -> MonoCache<K,V> {
|
||||
MonoCache { entry: None }
|
||||
}
|
||||
|
||||
fn insert(key: &K, value: V) {
|
||||
self.entry = Some((copy *key, value));
|
||||
}
|
||||
|
||||
fn find(key: &K) -> Option<V> {
|
||||
match self.entry {
|
||||
None => None,
|
||||
Some((ref k,v)) => if *k == *key { Some(v) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
fn find_or_create(key: &K, blk: pure fn&(&K) -> V) -> V {
|
||||
return match self.find(key) {
|
||||
None => {
|
||||
let value = blk(key);
|
||||
self.entry = Some((copy *key, copy value));
|
||||
move value
|
||||
},
|
||||
Some(v) => v
|
||||
};
|
||||
}
|
||||
fn evict_all() {
|
||||
self.entry = None;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_monocache() {
|
||||
// TODO: this is hideous because of Rust Issue #3902
|
||||
let cache = cache::new::<uint, @str, MonoCache<uint, @str>>(10);
|
||||
let one = @"one";
|
||||
let two = @"two";
|
||||
cache.insert(1, one);
|
||||
|
||||
assert cache.find(1).is_some();
|
||||
assert cache.find(2).is_none();
|
||||
cache.find_or_create(2, |_v| { two });
|
||||
assert cache.find(2).is_some();
|
||||
assert cache.find(1).is_none();
|
||||
}
|
|
@ -162,7 +162,7 @@ fn test_transform_discard_newline() {
|
|||
~"foo bar baz",
|
||||
~"foobarbaz"];
|
||||
|
||||
assert core::vec::same_length(test_strs, oracle_strs);
|
||||
assert test_strs.len() == oracle_strs.len();
|
||||
let mode = DiscardNewline;
|
||||
|
||||
for uint::range(0, test_strs.len()) |i| {
|
||||
|
@ -188,7 +188,7 @@ fn test_transform_compress_whitespace() {
|
|||
~"foo bar baz",
|
||||
~"foobarbaz\n\n"];
|
||||
|
||||
assert core::vec::same_length(test_strs, oracle_strs);
|
||||
assert test_strs.len() == oracle_strs.len();
|
||||
let mode = CompressWhitespace;
|
||||
|
||||
for uint::range(0, test_strs.len()) |i| {
|
||||
|
@ -214,7 +214,7 @@ fn test_transform_compress_whitespace_newline() {
|
|||
~"foo bar baz",
|
||||
~"foobarbaz "];
|
||||
|
||||
assert core::vec::same_length(test_strs, oracle_strs);
|
||||
assert test_strs.len() == oracle_strs.len();
|
||||
let mode = CompressWhitespaceNewline;
|
||||
|
||||
for uint::range(0, test_strs.len()) |i| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue