From deb993d9c360c6534a919742a43ebab8fe4a3752 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Oct 2022 12:42:23 -0600 Subject: [PATCH] Support color emoji --- examples/text/src/font/layout.rs | 51 ++++++++++++++++++++++++++------ examples/text/src/font/shape.rs | 9 +++++- examples/text/src/main.rs | 6 ++-- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/examples/text/src/font/layout.rs b/examples/text/src/font/layout.rs index dc5cf735..7fbf9954 100644 --- a/examples/text/src/font/layout.rs +++ b/examples/text/src/font/layout.rs @@ -22,7 +22,7 @@ pub struct FontLayoutLine<'a> { } impl<'a> FontLayoutLine<'a> { - pub fn draw(&self, mut f: F) { + pub fn draw(&self, base: u32, mut f: F) { for glyph in self.glyphs.iter() { #[cfg(feature = "ab_glyph")] if let Some(ref outline) = glyph.inner { @@ -30,7 +30,11 @@ impl<'a> FontLayoutLine<'a> { let x = bb.min.x as i32; let y = bb.min.y as i32; outline.draw(|off_x, off_y, v| { - f(x + off_x as i32, y + off_y as i32, (v * 255.0) as u8); + //TODO: ensure v * 255.0 does not overflow! + let color = + ((v * 255.0) as u32) << 24 | + base & 0xFFFFFF; + f(x + off_x as i32, y + off_y as i32, color); }); } @@ -39,22 +43,51 @@ impl<'a> FontLayoutLine<'a> { let x = bb.min.x; let y = bb.min.y; glyph.inner.draw(|off_x, off_y, v| { - f(x + off_x as i32, y + off_y as i32, (v * 255.0) as u8); + //TODO: ensure v * 255.0 does not overflow! + let color = + ((v * 255.0) as u32) << 24 | + base & 0xFFFFFF; + f(x + off_x as i32, y + off_y as i32, color); }); } #[cfg(feature = "swash")] if let Some(ref image) = glyph.inner.2 { - assert_eq!(image.content, swash::scale::image::Content::Mask); + use swash::scale::image::Content; let x = glyph.inner.0 + image.placement.left; let y = glyph.inner.1 - image.placement.top; - let mut i = 0; - for off_y in 0..image.placement.height as i32 { - for off_x in 0..image.placement.width as i32 { - f(x + off_x, y + off_y, image.data[i]); - i += 1; + match image.content { + Content::Mask => { + let mut i = 0; + for off_y in 0..image.placement.height as i32 { + for off_x in 0..image.placement.width as i32 { + let color = + (image.data[i] as u32) << 24 | + base & 0xFFFFFF; + f(x + off_x, y + off_y, color); + i += 1; + } + } + }, + Content::Color => { + let mut i = 0; + for off_y in 0..image.placement.height as i32 { + for off_x in 0..image.placement.width as i32 { + println!("{}, {}, {:x?}", off_x, off_y, &image.data[i..i + 4]); + let color = + (image.data[i + 3] as u32) << 24 | + (image.data[i] as u32) << 16 | + (image.data[i + 1] as u32) << 8 | + (image.data[i + 2] as u32); + f(x + off_x, y + off_y, color); + i += 4; + } + } + }, + Content::SubpixelMask => { + println!("TODO: SubpixelMask"); } } } diff --git a/examples/text/src/font/shape.rs b/examples/text/src/font/shape.rs index ed6065a2..f006039f 100644 --- a/examples/text/src/font/shape.rs +++ b/examples/text/src/font/shape.rs @@ -74,7 +74,14 @@ impl<'a> FontShapeGlyph<'a> { let offset = Vector::new((x + x_offset).fract(), (y - y_offset).fract()); // Select our source order - let image_opt = Render::new(&[Source::Outline]) + let image_opt = Render::new(&[ + // Color outline with the first palette + Source::ColorOutline(0), + // Color bitmap with best fit selection mode + Source::ColorBitmap(StrikeWith::BestFit), + // Standard scalable outline + Source::Outline, + ]) // Select a subpixel format .format(Format::Alpha) // Apply the fractional offset diff --git a/examples/text/src/main.rs b/examples/text/src/main.rs index 79541379..04adfa50 100644 --- a/examples/text/src/main.rs +++ b/examples/text/src/main.rs @@ -203,10 +203,8 @@ fn main() { } } - line.draw(|x, y, alpha| { - window.pixel(line_x + x, line_y + y, Color { - data: (alpha as u32) << 24 | (font_color.data & 0x00FF_FFFF) - }); + line.draw(font_color.data, |x, y, color| { + window.pixel(line_x + x, line_y + y, Color { data: color }); }); line_y += line_height;