diff --git a/examples/hello-world.rs b/examples/hello-world.rs index cd8bb18..25f0fa4 100644 --- a/examples/hello-world.rs +++ b/examples/hello-world.rs @@ -3,7 +3,8 @@ use glyphon::{Color, HasColor, Resolution, TextAtlas, TextRenderer}; use wgpu::{ Backends, CommandEncoderDescriptor, CompositeAlphaMode, DeviceDescriptor, Features, Instance, Limits, LoadOp, Operations, PresentMode, RenderPassColorAttachment, RenderPassDescriptor, - RequestAdapterOptions, SurfaceConfiguration, TextureUsages, TextureViewDescriptor, + RequestAdapterOptions, SurfaceConfiguration, TextureFormat, TextureUsages, + TextureViewDescriptor, }; use winit::{ event::{Event, WindowEvent}, @@ -53,7 +54,8 @@ async fn run() { let window = Window::new(&event_loop).unwrap(); let surface = unsafe { instance.create_surface(&window) }; let size = window.inner_size(); - let swapchain_format = surface.get_supported_formats(&adapter)[0]; + // TODO: handle srgb + let swapchain_format = TextureFormat::Bgra8Unorm; let mut config = SurfaceConfiguration { usage: TextureUsages::RENDER_ATTACHMENT, format: swapchain_format, diff --git a/src/shader.wgsl b/src/shader.wgsl index 88a1320..51bb6e6 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -77,5 +77,5 @@ fn vs_main(in_vert: VertexInput) -> VertexOutput { @fragment fn fs_main(in_frag: VertexOutput) -> @location(0) vec4 { - return in_frag.color * textureSample(atlas_texture, atlas_sampler, in_frag.uv).x; + return in_frag.color * textureSample(atlas_texture, atlas_sampler, in_frag.uv); } diff --git a/src/text_atlas.rs b/src/text_atlas.rs index b7acca0..6e233dc 100644 --- a/src/text_atlas.rs +++ b/src/text_atlas.rs @@ -13,6 +13,8 @@ use wgpu::{ use crate::{GlyphDetails, GlyphToRender, Params, RecentlyUsedMap, Resolution}; +pub(crate) const NUM_ATLAS_CHANNELS: usize = 4usize; + /// An atlas containing a cache of rasterized glyphs that can be rendered. pub struct TextAtlas { pub(crate) texture_pending: Vec, @@ -35,8 +37,9 @@ impl TextAtlas { let height = max_texture_dimension_2d; let packer = BucketedAtlasAllocator::new(size2(width as i32, height as i32)); + // Create a texture to use for our atlas - let texture_pending = vec![0; (width * height) as usize]; + let texture_pending = vec![0; (width * height) as usize * NUM_ATLAS_CHANNELS]; let texture = device.create_texture(&TextureDescriptor { label: Some("glyphon atlas"), size: Extent3d { @@ -47,7 +50,7 @@ impl TextAtlas { mip_level_count: 1, sample_count: 1, dimension: TextureDimension::D2, - format: TextureFormat::R8Unorm, + format: TextureFormat::Rgba8Unorm, usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST, }); let texture_view = texture.create_view(&TextureViewDescriptor::default()); diff --git a/src/text_render.rs b/src/text_render.rs index a0fe7f4..ada8d5d 100644 --- a/src/text_render.rs +++ b/src/text_render.rs @@ -1,4 +1,4 @@ -use cosmic_text::{CacheKey, SwashCache, TextBuffer}; +use cosmic_text::{CacheKey, SwashCache, SwashContent, TextBuffer}; use etagere::{size2, Allocation}; use std::{collections::HashSet, iter, mem::size_of, num::NonZeroU32, slice}; @@ -8,8 +8,8 @@ use wgpu::{ }; use crate::{ - GlyphDetails, GlyphToRender, GpuCache, Params, PrepareError, RenderError, Resolution, - TextAtlas, TextOverflow, + text_atlas::NUM_ATLAS_CHANNELS, GlyphDetails, GlyphToRender, GpuCache, Params, PrepareError, + RenderError, Resolution, TextAtlas, TextOverflow, }; /// A text renderer that uses cached glyphs to render text into an existing render pass. @@ -110,7 +110,23 @@ impl TextRenderer { .swash_cache .get_image_uncached(&buffer.font_matches, glyph.cache_key) .unwrap(); - let bitmap = image.data.as_slice(); + let mut bitmap = image.data; + + match image.content { + SwashContent::Color => {} + SwashContent::Mask => { + // Technically only one channel is needed, but store the mask in every + // for now. + bitmap = bitmap + .iter() + .flat_map(|color| iter::repeat(*color).take(NUM_ATLAS_CHANNELS)) + .collect(); + } + SwashContent::SubpixelMask => { + // Not implemented yet, but don't panic if this happens. + } + } + let width = image.placement.width as usize; let height = image.placement.height as usize; @@ -129,8 +145,10 @@ impl TextRenderer { let y_offset = atlas_min.y as usize; let x_offset = (y_offset + row) * atlas.width as usize + atlas_min.x as usize; - let bitmap_row = &bitmap[row * width..(row + 1) * width]; - atlas.texture_pending[x_offset..x_offset + width] + let bitmap_row = &bitmap[row * width * NUM_ATLAS_CHANNELS + ..(row + 1) * width * NUM_ATLAS_CHANNELS]; + atlas.texture_pending[x_offset * NUM_ATLAS_CHANNELS + ..(x_offset + width) * NUM_ATLAS_CHANNELS] .copy_from_slice(bitmap_row); } @@ -194,7 +212,7 @@ impl TextRenderer { &atlas.texture_pending[ub.y_min * atlas.width as usize + ub.x_min..], ImageDataLayout { offset: 0, - bytes_per_row: NonZeroU32::new(atlas.width), + bytes_per_row: NonZeroU32::new(atlas.width * NUM_ATLAS_CHANNELS as u32), rows_per_image: NonZeroU32::new(atlas.height), }, Extent3d { @@ -284,7 +302,8 @@ impl TextRenderer { pos: [x as i32, y as i32], dim: [width as u16, height as u16], uv: [atlas_x, atlas_y], - color: [255, 0, 255, 255], + // TODO + color: [255, 255, 255, 255], }) .take(4), );