From c5161f182322915dc9884f96358718d842383dc7 Mon Sep 17 00:00:00 2001 From: "Brian J. Burg" Date: Fri, 9 Nov 2012 17:43:48 -0800 Subject: [PATCH] Finish collecting and storing FontList data. --- src/rust-core-text | 2 +- src/rust-layers | 2 +- src/servo/gfx/font.rs | 11 ++++++- src/servo/gfx/font_list.rs | 18 ++++++----- src/servo/gfx/quartz/font.rs | 54 ++++++++++++++++++++++++++----- src/servo/gfx/quartz/font_list.rs | 42 ++++++++++++++++-------- src/servo/layout/box.rs | 2 +- 7 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/rust-core-text b/src/rust-core-text index 0b37b31edb1..9c398db2b06 160000 --- a/src/rust-core-text +++ b/src/rust-core-text @@ -1 +1 @@ -Subproject commit 0b37b31edb11c94916b1255221d522c170dce739 +Subproject commit 9c398db2b0627b150eba88edc0eb861dfb4a28ac diff --git a/src/rust-layers b/src/rust-layers index ce1f192686d..eb86bb090d6 160000 --- a/src/rust-layers +++ b/src/rust-layers @@ -1 +1 @@ -Subproject commit ce1f192686d0d4acebdcdc8280c9054826c81bf1 +Subproject commit eb86bb090d6bbf5f543c75756b52ba42d1ec3ddf diff --git a/src/servo/gfx/font.rs b/src/servo/gfx/font.rs index 4e398b6fd44..37d27a40760 100644 --- a/src/servo/gfx/font.rs +++ b/src/servo/gfx/font.rs @@ -171,7 +171,16 @@ pub impl FontSelector : cmp::Eq { // Holds a specific font family, and the various pub struct FontFamily { family_name: @str, - entries: ~[@FontEntry], + entries: DVec<@FontEntry>, +} + +pub impl FontFamily { + static fn new(family_name: &str) -> FontFamily { + FontFamily { + family_name: str::from_slice(family_name).to_managed(), + entries: DVec(), + } + } } // This struct is the result of mapping a specified FontStyle into the diff --git a/src/servo/gfx/font_list.rs b/src/servo/gfx/font_list.rs index e7a75e8e655..575b90ab630 100644 --- a/src/servo/gfx/font_list.rs +++ b/src/servo/gfx/font_list.rs @@ -3,6 +3,7 @@ use gfx::{ }; use dvec::DVec; +use send_map::{linear, SendMap}; #[cfg(target_os = "macos")] type FontListHandle/& = quartz::font_list::QuartzFontListHandle; @@ -22,9 +23,11 @@ pub impl FontListHandle { } } +type FontFamilyMap = linear::LinearMap<~str, @FontFamily>; + pub struct FontList { - families: DVec<@FontFamily>, - handle: FontListHandle, + mut family_map: FontFamilyMap, + mut handle: FontListHandle, } pub impl FontList { @@ -32,18 +35,17 @@ pub impl FontList { let handle = result::unwrap(FontListHandle::new(fctx)); let list = FontList { handle: move handle, - families: DVec(), + family_map: linear::LinearMap(), }; list.refresh(fctx); return move list; } priv fn refresh(fctx: &native::FontContextHandle) { - // TODO: don't refresh unless something actually changed. - // Does OSX have a notification for this event? - // It would be better to do piecemeal. - do self.families.swap |_old_families: ~[@FontFamily]| { - self.handle.get_available_families(fctx) + // TODO(Issue #186): don't refresh unless something actually + // changed. Does OSX have a notification for this event? + do util::time::time("gfx::font_list: regenerating available font families and faces") { + self.family_map = self.handle.get_available_families(fctx); } } } \ No newline at end of file diff --git a/src/servo/gfx/quartz/font.rs b/src/servo/gfx/quartz/font.rs index b0c0fdae426..3d1c2f43fae 100644 --- a/src/servo/gfx/quartz/font.rs +++ b/src/servo/gfx/quartz/font.rs @@ -8,7 +8,15 @@ use gfx::font::{ CSSFontWeight, FontHandleMethods, FontMetrics, + FontWeight100, + FontWeight200, + FontWeight300, + FontWeight400, FontWeight500, + FontWeight600, + FontWeight700, + FontWeight800, + FontWeight900, FractionalPixel }; use text::glyph::GlyphIndex; @@ -40,15 +48,20 @@ use ct = core_text; use ct::font::CTFont; use ct::font_descriptor::{ kCTFontDefaultOrientation, + CTFontSymbolicTraits, + SymbolicTraitAccessors, }; pub struct QuartzFontHandle { - cgfont: CGFontRef, + priv mut cgfont: Option, ctfont: CTFont, drop { - assert self.cgfont.is_not_null(); - CGFontRelease(self.cgfont); + // TODO(Issue #152): use a wrapped CGFont. + do (copy self.cgfont).iter |cgfont| { + assert cgfont.is_not_null(); + CGFontRelease(*cgfont); + } } } @@ -64,7 +77,7 @@ pub impl QuartzFontHandle { let ctfont = CTFont::new_from_CGFont(cgfont, pt_size); let result = Ok(QuartzFontHandle { - cgfont : cgfont, + cgfont : Some(cgfont), ctfont : move ctfont, }); @@ -72,28 +85,53 @@ pub impl QuartzFontHandle { } static fn new_from_CTFont(_fctx: &QuartzFontContextHandle, ctfont: CTFont) -> Result { - let cgfont = ctfont.copy_to_CGFont(); let result = Ok(QuartzFontHandle { - cgfont: cgfont, + mut cgfont: None, ctfont: move ctfont, }); return move result; } + + fn get_CGFont() -> CGFontRef { + match self.cgfont { + Some(cg) => cg, + None => { + let cgfont = self.ctfont.copy_to_CGFont(); + self.cgfont = Some(cgfont); + cgfont + } + } + } } pub impl QuartzFontHandle : FontHandleMethods { + pure fn family_name() -> ~str { + self.ctfont.family_name() + } pure fn face_name() -> ~str { self.ctfont.face_name() } pure fn is_italic() -> bool { - false // FIXME + self.ctfont.symbolic_traits().is_italic() } pure fn boldness() -> CSSFontWeight { - FontWeight500 // FIXME + // -1.0 to 1.0 + let normalized = unsafe { self.ctfont.all_traits().normalized_weight() }; + // 0.0 to 9.0 + let normalized = (normalized + 1.0) / 2.0 * 9.0; + if normalized < 1.0 { return FontWeight100; } + if normalized < 2.0 { return FontWeight200; } + if normalized < 3.0 { return FontWeight300; } + if normalized < 4.0 { return FontWeight400; } + if normalized < 5.0 { return FontWeight500; } + if normalized < 6.0 { return FontWeight600; } + if normalized < 7.0 { return FontWeight700; } + if normalized < 8.0 { return FontWeight800; } + else { return FontWeight900; } } diff --git a/src/servo/gfx/quartz/font_list.rs b/src/servo/gfx/quartz/font_list.rs index 7421e39c126..df774906215 100644 --- a/src/servo/gfx/quartz/font_list.rs +++ b/src/servo/gfx/quartz/font_list.rs @@ -16,9 +16,16 @@ use ct::font_descriptor::{ debug_descriptor, }; -use gfx::font::FontFamily; +use gfx::font::{ + FontEntry, + FontFamily, + FontHandle, +}; + +use font::{QuartzFontHandle}; use dvec::DVec; +use send_map::{linear, SendMap}; pub struct QuartzFontListHandle { collection: CTFontCollection, @@ -29,23 +36,32 @@ pub impl QuartzFontListHandle { QuartzFontListHandle { collection: CTFontCollection::new() } } - fn get_available_families(fctx: &native::FontContextHandle) -> ~[@FontFamily] { - // TODO: make a hashtable from family name to DVec + fn get_available_families(&const self,fctx: &native::FontContextHandle) -> linear::LinearMap<~str, @FontFamily> { + // since we mutate it repeatedly, must be mut variable. + let mut family_map : linear::LinearMap<~str, @FontFamily> = linear::LinearMap(); let descriptors : CFArray; descriptors = self.collection.get_descriptors(); for descriptors.each |desc: &CTFontDescriptor| { - //debug!("%?", { debug_descriptor(desc); () }); // TODO: for each descriptor, make a FontEntry. let font = CTFont::new_from_descriptor(desc, 0.0); - debug!("family: %s", font.family_name()); - debug!("face: %s", font.face_name()); - debug!("%s", { debug_font_traits(&font); ~"--- DEBUG CTFONT TRAITS ---" }); + let handle = result::unwrap(QuartzFontHandle::new_from_CTFont(fctx, move font)); + let family_name = handle.family_name(); + debug!("Looking for family name: %s", family_name); + let family = match family_map.find(&family_name) { + Some(fam) => fam, + None => { + debug!("Creating new FontFamily for family: %s", family_name); + let new_family = @FontFamily::new(family_name); + family_map.insert(move family_name, new_family); + new_family + } + }; + + debug!("Creating new FontEntry for face: %s", handle.face_name()); + let entry = @FontEntry::new(family, move handle); + family.entries.push(entry); // TODO: append FontEntry to hashtable value } - - let families: DVec<@FontFamily> = DVec(); - // TODO: iterate over (key,val) pairs and create FontFamily instances - - return move dvec::unwrap(move families); + return move family_map; } -} \ No newline at end of file +} diff --git a/src/servo/layout/box.rs b/src/servo/layout/box.rs index 289d5be1d44..0e68b56e5e1 100644 --- a/src/servo/layout/box.rs +++ b/src/servo/layout/box.rs @@ -390,7 +390,7 @@ impl RenderBox : RenderBoxMethods { * `origin` - Total offset from display list root flow to this box's owning flow * `list` - List to which items should be appended */ - fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect, + fn build_display_list(@self, _builder: &DisplayListBuilder, dirty: &Rect, offset: &Point2D, list: &mut DisplayList) { let box_bounds = self.d().position;