pop-os / cosmic-text

Pure Rust multi-line text handling
https://pop-os.github.io/cosmic-text/cosmic_text/
Apache License 2.0
1.61k stars 105 forks source link

Emoji rendering with NotoColorEmoji yields an empty image #310

Open bschwind opened 2 months ago

bschwind commented 2 months ago

I might be doing something wrong or naive here, but here's a minimal example:

# Cargo.toml
[package]
name = "cosmic-text-test"
version = "0.1.0"
edition = "2021"

[dependencies]
cosmic-text = "0.12"
fontdb = "0.16"
sys-locale = "0.3"
// src/main.rs
use cosmic_text::{Attrs, Buffer, FontSystem, Metrics, Shaping, SwashCache};
use fontdb::Database;
use std::sync::Arc;

fn main() {
    // Create a custom FontSystem with only an emoji font.
    let emoji_font = Arc::new(include_bytes!("../fonts/NotoColorEmoji-Regular.ttf"));

    let mut font_db = Database::new();
    font_db.load_font_source(fontdb::Source::Binary(emoji_font));

    let locale = sys_locale::get_locale().unwrap_or_else(|| "en-US".to_string());
    let mut font_system = FontSystem::new_with_locale_and_db(locale, font_db);
    let mut swash_cache = SwashCache::new();

    // Shape a buffer
    let mut buffer = Buffer::new_empty(Metrics::relative(32.0, 1.0));
    buffer.set_size(&mut font_system, Some(3000.0), Some(3000.0));

    let default_attrs = Attrs::new();

    buffer.set_text(&mut font_system, "😂", default_attrs, Shaping::Advanced);

    let prune = true;
    buffer.shape_until_scroll(&mut font_system, prune);

    let x = 0.0;
    let y = 0.0;
    let scale = 1.0;

    // Iterate over glyphs
    for run in buffer.layout_runs() {
        dbg!(run.text);

        for glyph in run.glyphs.iter() {
            let physical_glyph = glyph.physical((x, y), scale);
            dbg!(&physical_glyph.cache_key);

            let Some(image) =
                swash_cache.get_image_uncached(&mut font_system, physical_glyph.cache_key)
            else {
                println!("No rasterization needed?");
                continue;
            };

            dbg!(image.source);
            dbg!(image.content);
            dbg!(image.placement);
            dbg!(image.data.len());
        }
    }
}
$ cargo run --release
   Compiling cosmic-text-test v0.1.0 (/Users/brian/projects/cosmic-text-test/cosmic-text-test)
    Finished `release` profile [optimized] target(s) in 1.64s
     Running `target/release/cosmic-text-test`
[src/main.rs:33:9] run.text = "😂"
[src/main.rs:37:13] &physical_glyph.cache_key = CacheKey {
    font_id: ID(
        InnerId(
            1v1,
        ),
    ),
    glyph_id: 2285,
    font_size_bits: 1107296256,
    x_bin: Zero,
    y_bin: Zero,
    flags: CacheKeyFlags(
        0x0,
    ),
}
[src/main.rs:46:13] image.source = Outline
[src/main.rs:47:13] image.content = Mask
[src/main.rs:48:13] image.placement = Placement {
    left: -1,
    top: 0,
    width: 2,
    height: 0,
}
[src/main.rs:49:13] image.data.len() = 0

I'm using the NotoColorEmoji-Regular.ttf file downloaded from Google Fonts.

Any help would be appreciated, I'm assuming this is not the expected output for shaping a singular emoji in a run of text, with a database which consists of only 1 emoji font.

bschwind commented 2 months ago

After more poking around, it seems maybe the TTF I downloaded isn't correct?

I tried substituting in this one and it seems to be rendering correctly now.

Something seems off about downloading the TTF from the google fonts website. There's even an empty issue about it.