Repository: alacritty/alacritty
File: font/src/ft/mod.rs (Rust)

Code before:
                // If a name was specified, try and load specifically that font
                pattern.add_style(style);
            },
        }

        pattern.config_substitute(config, fc::MatchKind::Pattern);
        pattern.default_substitute();

        // Get font list using pattern. First font is the primary one while the rest are fallbacks
        let matched_fonts =
            fc::font_sort(&config, &pattern).ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
        let mut matched_fonts = matched_fonts.into_iter();

        let primary_font =
            matched_fonts.next().ok_or_else(|| Error::MissingFont(desc.to_owned()))?;

        // We should render patterns to get values like `pixelsizefixupfactor`
        let primary_font = pattern.render_prepare(config, primary_font);

        // Hash pattern together with request pattern to include requested font size in the hash
        let primary_font_key = FontKey::from_pattern_hashes(hash, primary_font.hash());

        // Return font if we already loaded it
        if self.faces.get(&primary_font_key).is_some() {
            return Ok(primary_font_key);
        }

        // Reuse the font_key, since changing it can break library users
        let font_key = self
            .face_from_pattern(&primary_font, primary_font_key)
            .and_then(|pattern| pattern.ok_or_else(|| Error::MissingFont(desc.to_owned())))?;

        // Coverage for fallback fonts
        let coverage = CharSet::new();
        let empty_charset = CharSet::new();

        // Build fallback list
        let list: Vec<FallbackFont> = matched_fonts
            .map(|fallback_font| {
                let charset = fallback_font.get_charset().unwrap_or(&empty_charset);

                // Use original pattern to preserve loading flags
                let fallback_font = pattern.render_prepare(config, fallback_font);
                let fallback_font_key = FontKey::from_pattern_hashes(hash, fallback_font.hash());

                let _ = coverage.merge(&charset);

                FallbackFont::new(fallback_font, fallback_font_key)
            })
            .collect();


Review comment (suggestion):
Thinking about this early return, there might be an issue with fallback faces, right?

In `self.faces` both primary and fallback faces are stored. However, a primary face requires the additional computation we do in this method to load the fallback list.

So it seems like what we should do is check if the font is already loaded **and** if a fallback list exists for this font.

However even if the fallback list does not exist, we should be able to still skip the call to `face_from_pattern`. Just not the entire rest of this function.

Code after:
                // If a name was specified, try and load specifically that font
                pattern.add_style(style);
            },
        }

        pattern.config_substitute(config, fc::MatchKind::Pattern);
        pattern.default_substitute();

        // Get font list using pattern. First font is the primary one while the rest are fallbacks
        let matched_fonts =
            fc::font_sort(&config, &pattern).ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
        let mut matched_fonts = matched_fonts.into_iter();

        let primary_font =
            matched_fonts.next().ok_or_else(|| Error::MissingFont(desc.to_owned()))?;

        // We should render patterns to get values like `pixelsizefixupfactor`
        let primary_font = pattern.render_prepare(config, primary_font);

        // Hash pattern together with request pattern to include requested font size in the hash
        let primary_font_key = FontKey::from_pattern_hashes(hash, primary_font.hash());

        // Return if we already have the same primary font
        if self.fallback_lists.contains_key(&primary_font_key) {
            return Ok(primary_font_key);
        }

        // Load font if we haven't loaded it yet
        if !self.faces.contains_key(&primary_font_key) {
            self.face_from_pattern(&primary_font, primary_font_key)
                .and_then(|pattern| pattern.ok_or_else(|| Error::MissingFont(desc.to_owned())))?;
        }

        // Coverage for fallback fonts
        let coverage = CharSet::new();
        let empty_charset = CharSet::new();

        let list: Vec<FallbackFont> = matched_fonts
            .map(|fallback_font| {
                let charset = fallback_font.get_charset().unwrap_or(&empty_charset);

                // Use original pattern to preserve loading flags
                let fallback_font = pattern.render_prepare(config, fallback_font);
                let fallback_font_key = FontKey::from_pattern_hashes(hash, fallback_font.hash());

                let _ = coverage.merge(&charset);

                FallbackFont::new(fallback_font, fallback_font_key)
            })
            .collect();