aboutsummaryrefslogtreecommitdiffstats
path: root/components/gfx/font_context.rs
diff options
context:
space:
mode:
authorJack Moffitt <jack@metajack.im>2014-08-28 09:34:23 -0600
committerJack Moffitt <jack@metajack.im>2014-09-08 20:21:42 -0600
commitc6ab60dbfc6da7b4f800c9e40893c8b58413960c (patch)
treed1d74076cf7fa20e4f77ec7cb82cae98b67362cb /components/gfx/font_context.rs
parentdb2f642c32fc5bed445bb6f2e45b0f6f0b4342cf (diff)
downloadservo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.tar.gz
servo-c6ab60dbfc6da7b4f800c9e40893c8b58413960c.zip
Cargoify servo
Diffstat (limited to 'components/gfx/font_context.rs')
-rw-r--r--components/gfx/font_context.rs148
1 files changed, 148 insertions, 0 deletions
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
new file mode 100644
index 00000000000..0a1ef69e0ce
--- /dev/null
+++ b/components/gfx/font_context.rs
@@ -0,0 +1,148 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use font::{Font, FontGroup};
+use font::SpecifiedFontStyle;
+use platform::font_context::FontContextHandle;
+use style::computed_values::font_style;
+
+use font_cache_task::FontCacheTask;
+use font_template::FontTemplateDescriptor;
+use platform::font_template::FontTemplateData;
+use font::FontHandleMethods;
+use platform::font::FontHandle;
+use servo_util::cache::HashCache;
+
+use std::rc::{Rc, Weak};
+use std::cell::RefCell;
+use sync::Arc;
+
+use azure::AzFloat;
+use azure::azure_hl::BackendType;
+use azure::scaled_font::ScaledFont;
+
+#[cfg(target_os="linux")]
+#[cfg(target_os="android")]
+use azure::scaled_font::FontData;
+
+#[cfg(target_os="linux")]
+#[cfg(target_os="android")]
+fn create_scaled_font(backend: BackendType, template: &Arc<FontTemplateData>, pt_size: f64) -> ScaledFont {
+ ScaledFont::new(backend, FontData(&template.bytes), pt_size as AzFloat)
+}
+
+#[cfg(target_os="macos")]
+fn create_scaled_font(backend: BackendType, template: &Arc<FontTemplateData>, pt_size: f64) -> ScaledFont {
+ let cgfont = template.ctfont.get_ref().copy_to_CGFont();
+ ScaledFont::new(backend, &cgfont, pt_size as AzFloat)
+}
+
+/// A cached azure font (per render task) that
+/// can be shared by multiple text runs.
+struct RenderFontCacheEntry {
+ pt_size: f64,
+ identifier: String,
+ font: Rc<RefCell<ScaledFont>>,
+}
+
+/// The FontContext represents the per-thread/task state necessary for
+/// working with fonts. It is the public API used by the layout and
+/// render code. It talks directly to the font cache task where
+/// required.
+pub struct FontContext {
+ platform_handle: FontContextHandle,
+ font_cache_task: FontCacheTask,
+
+ /// Weak reference as the layout FontContext is persistent.
+ layout_font_cache: Vec<Weak<RefCell<Font>>>,
+
+ /// Strong reference as the render FontContext is (for now) recycled
+ /// per frame. TODO: Make this weak when incremental redraw is done.
+ render_font_cache: Vec<RenderFontCacheEntry>,
+}
+
+impl FontContext {
+ pub fn new(font_cache_task: FontCacheTask) -> FontContext {
+ let handle = FontContextHandle::new();
+ FontContext {
+ platform_handle: handle,
+ font_cache_task: font_cache_task,
+ layout_font_cache: vec!(),
+ render_font_cache: vec!(),
+ }
+ }
+
+ /// Create a font for use in layout calculations.
+ fn create_layout_font(&self, template: Arc<FontTemplateData>,
+ descriptor: FontTemplateDescriptor, pt_size: f64) -> Font {
+
+ let handle: FontHandle = FontHandleMethods::new_from_template(&self.platform_handle, template, Some(pt_size)).unwrap();
+ let metrics = handle.get_metrics();
+
+ Font {
+ handle: handle,
+ shaper: None,
+ descriptor: descriptor,
+ pt_size: pt_size,
+ metrics: metrics,
+ shape_cache: HashCache::new(),
+ glyph_advance_cache: HashCache::new(),
+ }
+ }
+
+ /// Create a group of fonts for use in layout calculations. May return
+ /// a cached font if this font instance has already been used by
+ /// this context.
+ pub fn get_layout_font_group_for_style(&mut self, style: &SpecifiedFontStyle) -> FontGroup {
+ // Remove all weak pointers that have been dropped.
+ self.layout_font_cache.retain(|maybe_font| {
+ maybe_font.upgrade().is_some()
+ });
+
+ let mut fonts: Vec<Rc<RefCell<Font>>> = vec!();
+
+ for family in style.families.iter() {
+ let desc = FontTemplateDescriptor::new(style.weight, style.style == font_style::italic);
+
+ // GWTODO: Check on real pages if this is faster as Vec() or HashMap().
+ let mut cache_hit = false;
+ for maybe_cached_font in self.layout_font_cache.iter() {
+ let cached_font = maybe_cached_font.upgrade().unwrap();
+ if cached_font.borrow().descriptor == desc {
+ fonts.push(cached_font.clone());
+ cache_hit = true;
+ break;
+ }
+ }
+
+ 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)));
+ self.layout_font_cache.push(layout_font.downgrade());
+ fonts.push(layout_font);
+ }
+ }
+
+ FontGroup::new(fonts)
+ }
+
+ /// Create a render font for use with azure. May return a cached
+ /// reference if already used by this font context.
+ pub fn get_render_font_from_template(&mut self, template: &Arc<FontTemplateData>, pt_size: f64, backend: BackendType) -> Rc<RefCell<ScaledFont>> {
+ for cached_font in self.render_font_cache.iter() {
+ if cached_font.pt_size == pt_size &&
+ cached_font.identifier == template.identifier {
+ return cached_font.font.clone();
+ }
+ }
+
+ let render_font = Rc::new(RefCell::new(create_scaled_font(backend, template, pt_size)));
+ self.render_font_cache.push(RenderFontCacheEntry{
+ font: render_font.clone(),
+ pt_size: pt_size,
+ identifier: template.identifier.clone(),
+ });
+ render_font
+ }
+}