<commit_before>/* 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 collections::hashmap::HashMap;
use font::SpecifiedFontStyle;
use gfx_font::FontHandleMethods;
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use platform::font_list::FontListHandle;
use style::computed_values::{font_weight, font_style};

use servo_util::time::{ProfilerChan, profile};
use servo_util::time;

pub type FontFamilyMap = HashMap<~str, FontFamily>;

trait FontListHandleMethods {
    fn get_available_families(&self, fctx: &FontContextHandle) -> FontFamilyMap;
    fn load_variations_for_family(&self, family: &mut FontFamily);
    fn get_last_resort_font_families() -> ~[~str];
}

/// The platform-independent font list abstraction.
pub struct FontList {
    family_map: FontFamilyMap,
    handle: FontListHandle,
    prof_chan: ProfilerChan,
}

impl FontList {
    pub fn new(fctx: &FontContextHandle,
           prof_chan: ProfilerChan)
           -> FontList {
        let handle = FontListHandle::new(fctx);
        let mut list = FontList {
            handle: handle,
            family_map: HashMap::new(),
            prof_chan: prof_chan.clone(),
        };
        list.refresh(fctx);
        list
    }

    fn refresh(&mut self, _: &FontContextHandle) {
        // TODO(Issue #186): don't refresh unless something actually
        // changed.  Does OSX have a notification for this event?
        //
        // Should font families with entries be invalidated/refreshed too?
        profile(time::GfxRegenAvailableFontsCategory, self.prof_chan.clone(), || {
            self.family_map = self.handle.get_available_families();
        });
    }

    pub fn find_font_in_family<'a>(&'a mut self,
                                   family_name: &~str,
                                   style: &SpecifiedFontStyle) -> Option<&'a FontEntry> {
        // TODO(Issue #188): look up localized font family names if canonical name not found
        // look up canonical name
        if self.family_map.contains_key(family_name) {
            //FIXME call twice!(ksh8281)
            debug!("FontList: Found font family with name={:s}", family_name.to_str());
            let s: &'a mut FontFamily = self.family_map.get_mut(family_name);
            // TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
            // if such family exists, try to match style to a font
            let result = s.find_font_for_style(&mut self.handle, style);
            if result.is_some() {
                return result;
            }

            None
        } else {
            debug!("FontList: Couldn't find font family with name={:s}", family_name.to_str());
            None
        }
    }

    pub fn get_last_resort_font_families() -> ~[~str] {
        let last_resort = FontListHandle::get_last_resort_font_families();
        last_resort
    }
}

// Holds a specific font family, and the various
pub struct FontFamily {
    pub family_name: ~str,
    pub entries: ~[FontEntry],
}

impl FontFamily {
    pub fn new(family_name: &str) -> FontFamily {
        FontFamily {
            family_name: family_name.to_str(),
            entries: ~[],
        }
    }

    fn load_family_variations(&mut self, list: &FontListHandle) {
        if self.entries.len() > 0 {
            return
        }
        list.load_variations_for_family(self);
        assert!(self.entries.len() > 0)
    }

    pub fn find_font_for_style<'a>(&'a mut self, list: &FontListHandle, style: &SpecifiedFontStyle)
                               -> Option<&'a FontEntry> {
        self.load_family_variations(list);
<commit_msg>~[] to Vec in gfx/font_list.rs<commit_after>/* 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 collections::hashmap::HashMap;
use font::SpecifiedFontStyle;
use gfx_font::FontHandleMethods;
use platform::font::FontHandle;
use platform::font_context::FontContextHandle;
use platform::font_list::FontListHandle;
use style::computed_values::{font_weight, font_style};

use servo_util::time::{ProfilerChan, profile};
use servo_util::time;

pub type FontFamilyMap = HashMap<~str, FontFamily>;

trait FontListHandleMethods {
    fn get_available_families(&self, fctx: &FontContextHandle) -> FontFamilyMap;
    fn load_variations_for_family(&self, family: &mut FontFamily);
    fn get_last_resort_font_families() -> ~[~str];
}

/// The platform-independent font list abstraction.
pub struct FontList {
    family_map: FontFamilyMap,
    handle: FontListHandle,
    prof_chan: ProfilerChan,
}

impl FontList {
    pub fn new(fctx: &FontContextHandle,
           prof_chan: ProfilerChan)
           -> FontList {
        let handle = FontListHandle::new(fctx);
        let mut list = FontList {
            handle: handle,
            family_map: HashMap::new(),
            prof_chan: prof_chan.clone(),
        };
        list.refresh(fctx);
        list
    }

    fn refresh(&mut self, _: &FontContextHandle) {
        // TODO(Issue #186): don't refresh unless something actually
        // changed.  Does OSX have a notification for this event?
        //
        // Should font families with entries be invalidated/refreshed too?
        profile(time::GfxRegenAvailableFontsCategory, self.prof_chan.clone(), || {
            self.family_map = self.handle.get_available_families();
        });
    }

    pub fn find_font_in_family<'a>(&'a mut self,
                                   family_name: &~str,
                                   style: &SpecifiedFontStyle) -> Option<&'a FontEntry> {
        // TODO(Issue #188): look up localized font family names if canonical name not found
        // look up canonical name
        if self.family_map.contains_key(family_name) {
            //FIXME call twice!(ksh8281)
            debug!("FontList: Found font family with name={:s}", family_name.to_str());
            let s: &'a mut FontFamily = self.family_map.get_mut(family_name);
            // TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
            // if such family exists, try to match style to a font
            let result = s.find_font_for_style(&mut self.handle, style);
            if result.is_some() {
                return result;
            }

            None
        } else {
            debug!("FontList: Couldn't find font family with name={:s}", family_name.to_str());
            None
        }
    }

    pub fn get_last_resort_font_families() -> ~[~str] {
        let last_resort = FontListHandle::get_last_resort_font_families();
        last_resort
    }
}

// Holds a specific font family, and the various
pub struct FontFamily {
    pub family_name: ~str,
    pub entries: Vec<FontEntry>,
}

impl FontFamily {
    pub fn new(family_name: &str) -> FontFamily {
        FontFamily {
            family_name: family_name.to_str(),
            entries: Vec::new(),
        }
    }

    fn load_family_variations(&mut self, list: &FontListHandle) {
        if self.entries.len() > 0 {
            return
        }
        list.load_variations_for_family(self);
        assert!(self.entries.len() > 0)
    }

    pub fn find_font_for_style<'a>(&'a mut self, list: &FontListHandle, style: &SpecifiedFontStyle)
                               -> Option<&'a FontEntry> {
        self.load_family_variations(list);

{'fraction_non_alphanumeric': 0.10905511811023622, 'fraction_numerical': 0.0049868766404199474, 'mean_word_length': 2.4910673385249655, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4128787', 'n_tokens_mistral': 2303, 'n_tokens_neox': 2227, 'n_words': 589}