Move all crates to a top-level crates folder
Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
d768224182
commit
fdfed3d7db
282 changed files with 195588 additions and 16 deletions
151
crates/gpui/src/platform/mac/sprite_cache.rs
Normal file
151
crates/gpui/src/platform/mac/sprite_cache.rs
Normal file
|
@ -0,0 +1,151 @@
|
|||
use super::atlas::AtlasAllocator;
|
||||
use crate::{
|
||||
fonts::{FontId, GlyphId},
|
||||
geometry::vector::{vec2f, Vector2F, Vector2I},
|
||||
platform,
|
||||
};
|
||||
use metal::{MTLPixelFormat, TextureDescriptor};
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::{borrow::Cow, collections::HashMap, sync::Arc};
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct GlyphDescriptor {
|
||||
font_id: FontId,
|
||||
font_size: OrderedFloat<f32>,
|
||||
glyph_id: GlyphId,
|
||||
subpixel_variant: (u8, u8),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GlyphSprite {
|
||||
pub atlas_id: usize,
|
||||
pub atlas_origin: Vector2I,
|
||||
pub offset: Vector2I,
|
||||
pub size: Vector2I,
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct IconDescriptor {
|
||||
path: Cow<'static, str>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IconSprite {
|
||||
pub atlas_id: usize,
|
||||
pub atlas_origin: Vector2I,
|
||||
pub size: Vector2I,
|
||||
}
|
||||
|
||||
pub struct SpriteCache {
|
||||
fonts: Arc<dyn platform::FontSystem>,
|
||||
atlases: AtlasAllocator,
|
||||
glyphs: HashMap<GlyphDescriptor, Option<GlyphSprite>>,
|
||||
icons: HashMap<IconDescriptor, IconSprite>,
|
||||
}
|
||||
|
||||
impl SpriteCache {
|
||||
pub fn new(
|
||||
device: metal::Device,
|
||||
size: Vector2I,
|
||||
fonts: Arc<dyn platform::FontSystem>,
|
||||
) -> Self {
|
||||
let descriptor = TextureDescriptor::new();
|
||||
descriptor.set_pixel_format(MTLPixelFormat::A8Unorm);
|
||||
descriptor.set_width(size.x() as u64);
|
||||
descriptor.set_height(size.y() as u64);
|
||||
Self {
|
||||
fonts,
|
||||
atlases: AtlasAllocator::new(device, descriptor),
|
||||
glyphs: Default::default(),
|
||||
icons: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_glyph(
|
||||
&mut self,
|
||||
font_id: FontId,
|
||||
font_size: f32,
|
||||
glyph_id: GlyphId,
|
||||
target_position: Vector2F,
|
||||
scale_factor: f32,
|
||||
) -> Option<GlyphSprite> {
|
||||
const SUBPIXEL_VARIANTS: u8 = 4;
|
||||
|
||||
let target_position = target_position * scale_factor;
|
||||
let fonts = &self.fonts;
|
||||
let atlases = &mut self.atlases;
|
||||
let subpixel_variant = (
|
||||
(target_position.x().fract() * SUBPIXEL_VARIANTS as f32).round() as u8
|
||||
% SUBPIXEL_VARIANTS,
|
||||
(target_position.y().fract() * SUBPIXEL_VARIANTS as f32).round() as u8
|
||||
% SUBPIXEL_VARIANTS,
|
||||
);
|
||||
self.glyphs
|
||||
.entry(GlyphDescriptor {
|
||||
font_id,
|
||||
font_size: OrderedFloat(font_size),
|
||||
glyph_id,
|
||||
subpixel_variant,
|
||||
})
|
||||
.or_insert_with(|| {
|
||||
let subpixel_shift = vec2f(
|
||||
subpixel_variant.0 as f32 / SUBPIXEL_VARIANTS as f32,
|
||||
subpixel_variant.1 as f32 / SUBPIXEL_VARIANTS as f32,
|
||||
);
|
||||
let (glyph_bounds, mask) = fonts.rasterize_glyph(
|
||||
font_id,
|
||||
font_size,
|
||||
glyph_id,
|
||||
subpixel_shift,
|
||||
scale_factor,
|
||||
)?;
|
||||
|
||||
let (alloc_id, atlas_bounds) = atlases.upload(glyph_bounds.size(), &mask);
|
||||
Some(GlyphSprite {
|
||||
atlas_id: alloc_id.atlas_id,
|
||||
atlas_origin: atlas_bounds.origin(),
|
||||
offset: glyph_bounds.origin(),
|
||||
size: glyph_bounds.size(),
|
||||
})
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn render_icon(
|
||||
&mut self,
|
||||
size: Vector2I,
|
||||
path: Cow<'static, str>,
|
||||
svg: usvg::Tree,
|
||||
) -> IconSprite {
|
||||
let atlases = &mut self.atlases;
|
||||
self.icons
|
||||
.entry(IconDescriptor {
|
||||
path,
|
||||
width: size.x(),
|
||||
height: size.y(),
|
||||
})
|
||||
.or_insert_with(|| {
|
||||
let mut pixmap = tiny_skia::Pixmap::new(size.x() as u32, size.y() as u32).unwrap();
|
||||
resvg::render(&svg, usvg::FitTo::Width(size.x() as u32), pixmap.as_mut());
|
||||
let mask = pixmap
|
||||
.pixels()
|
||||
.iter()
|
||||
.map(|a| a.alpha())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let (alloc_id, atlas_bounds) = atlases.upload(size, &mask);
|
||||
IconSprite {
|
||||
atlas_id: alloc_id.atlas_id,
|
||||
atlas_origin: atlas_bounds.origin(),
|
||||
size,
|
||||
}
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn atlas_texture(&self, atlas_id: usize) -> Option<&metal::TextureRef> {
|
||||
self.atlases.texture(atlas_id)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue