Checkpoint
This commit is contained in:
parent
da211bef96
commit
1e0ff65337
7 changed files with 57 additions and 46 deletions
|
@ -6,8 +6,8 @@ mod mac;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId, GlyphRasterParams,
|
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId, Pixels, Point,
|
||||||
Pixels, Point, Result, Scene, ShapedLine, SharedString, Size,
|
RenderGlyphParams, Result, Scene, ShapedLine, SharedString, Size,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
|
@ -147,7 +147,7 @@ pub trait PlatformWindow {
|
||||||
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool;
|
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool;
|
||||||
fn draw(&self, scene: Scene);
|
fn draw(&self, scene: Scene);
|
||||||
|
|
||||||
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<GlyphRasterParams>>;
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformDispatcher: Send + Sync {
|
pub trait PlatformDispatcher: Send + Sync {
|
||||||
|
@ -163,8 +163,8 @@ pub trait PlatformTextSystem: Send + Sync {
|
||||||
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>>;
|
fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>>;
|
||||||
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>>;
|
fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>>;
|
||||||
fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
|
fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
|
||||||
fn glyph_raster_bounds(&self, params: &GlyphRasterParams) -> Result<Bounds<DevicePixels>>;
|
fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>>;
|
||||||
fn rasterize_glyph(&self, params: &GlyphRasterParams) -> Result<(Size<DevicePixels>, Vec<u8>)>;
|
fn rasterize_glyph(&self, params: &RenderGlyphParams) -> Result<(Size<DevicePixels>, Vec<u8>)>;
|
||||||
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[(usize, FontId)]) -> ShapedLine;
|
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[(usize, FontId)]) -> ShapedLine;
|
||||||
fn wrap_line(
|
fn wrap_line(
|
||||||
&self,
|
&self,
|
||||||
|
@ -175,10 +175,22 @@ pub trait PlatformTextSystem: Send + Sync {
|
||||||
) -> Vec<usize>;
|
) -> Vec<usize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformAtlas<Key>: Send + Sync {
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||||
|
pub enum AtlasKey {
|
||||||
|
Glyph(RenderGlyphParams),
|
||||||
|
// Svg(RenderSvgParams),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RenderGlyphParams> for AtlasKey {
|
||||||
|
fn from(params: RenderGlyphParams) -> Self {
|
||||||
|
Self::Glyph(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait PlatformAtlas: Send + Sync {
|
||||||
fn get_or_insert_with(
|
fn get_or_insert_with(
|
||||||
&self,
|
&self,
|
||||||
key: &Key,
|
key: &AtlasKey,
|
||||||
build: &mut dyn FnMut() -> Result<(Size<DevicePixels>, Vec<u8>)>,
|
build: &mut dyn FnMut() -> Result<(Size<DevicePixels>, Vec<u8>)>,
|
||||||
) -> Result<AtlasTile>;
|
) -> Result<AtlasTile>;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::{AtlasTextureId, AtlasTile, Bounds, DevicePixels, PlatformAtlas, Point, Size};
|
use crate::{
|
||||||
|
AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels, PlatformAtlas, Point, Size,
|
||||||
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
|
@ -7,11 +9,10 @@ use foreign_types::ForeignType;
|
||||||
use metal::{Device, TextureDescriptor};
|
use metal::{Device, TextureDescriptor};
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel, sel_impl};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
pub struct MetalAtlas<Key>(Mutex<MetalAtlasState<Key>>);
|
pub struct MetalAtlas(Mutex<MetalAtlasState>);
|
||||||
|
|
||||||
impl<Key> MetalAtlas<Key> {
|
impl MetalAtlas {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
size: Size<DevicePixels>,
|
size: Size<DevicePixels>,
|
||||||
pixel_format: metal::MTLPixelFormat,
|
pixel_format: metal::MTLPixelFormat,
|
||||||
|
@ -34,20 +35,17 @@ impl<Key> MetalAtlas<Key> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MetalAtlasState<Key> {
|
struct MetalAtlasState {
|
||||||
device: AssertSend<Device>,
|
device: AssertSend<Device>,
|
||||||
texture_descriptor: AssertSend<TextureDescriptor>,
|
texture_descriptor: AssertSend<TextureDescriptor>,
|
||||||
textures: Vec<MetalAtlasTexture>,
|
textures: Vec<MetalAtlasTexture>,
|
||||||
tiles_by_key: HashMap<Key, AtlasTile>,
|
tiles_by_key: HashMap<AtlasKey, AtlasTile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Key> PlatformAtlas<Key> for MetalAtlas<Key>
|
impl PlatformAtlas for MetalAtlas {
|
||||||
where
|
|
||||||
Key: Clone + Eq + Hash + Send,
|
|
||||||
{
|
|
||||||
fn get_or_insert_with(
|
fn get_or_insert_with(
|
||||||
&self,
|
&self,
|
||||||
key: &Key,
|
key: &AtlasKey,
|
||||||
build: &mut dyn FnMut() -> Result<(Size<DevicePixels>, Vec<u8>)>,
|
build: &mut dyn FnMut() -> Result<(Size<DevicePixels>, Vec<u8>)>,
|
||||||
) -> Result<AtlasTile> {
|
) -> Result<AtlasTile> {
|
||||||
let mut lock = self.0.lock();
|
let mut lock = self.0.lock();
|
||||||
|
@ -75,7 +73,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Key> MetalAtlasState<Key> {
|
impl MetalAtlasState {
|
||||||
fn push_texture(&mut self, min_size: Size<DevicePixels>) -> &mut MetalAtlasTexture {
|
fn push_texture(&mut self, min_size: Size<DevicePixels>) -> &mut MetalAtlasTexture {
|
||||||
let default_atlas_size = Size {
|
let default_atlas_size = Size {
|
||||||
width: self.texture_descriptor.width().into(),
|
width: self.texture_descriptor.width().into(),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, size, AtlasTextureId, DevicePixels, GlyphRasterParams, MetalAtlas, MonochromeSprite,
|
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad, Scene, Size,
|
||||||
Quad, Scene, Size,
|
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
base::{NO, YES},
|
base::{NO, YES},
|
||||||
|
@ -21,7 +20,7 @@ pub struct MetalRenderer {
|
||||||
sprites_pipeline_state: metal::RenderPipelineState,
|
sprites_pipeline_state: metal::RenderPipelineState,
|
||||||
unit_vertices: metal::Buffer,
|
unit_vertices: metal::Buffer,
|
||||||
instances: metal::Buffer,
|
instances: metal::Buffer,
|
||||||
glyph_atlas: Arc<MetalAtlas<GlyphRasterParams>>,
|
glyph_atlas: Arc<MetalAtlas>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalRenderer {
|
impl MetalRenderer {
|
||||||
|
@ -124,7 +123,7 @@ impl MetalRenderer {
|
||||||
&*self.layer
|
&*self.layer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<GlyphRasterParams>> {
|
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas> {
|
||||||
&self.glyph_atlas
|
&self.glyph_atlas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, Bounds, DevicePixels, Font, FontFeatures, FontId, FontMetrics, FontStyle,
|
point, px, size, Bounds, DevicePixels, Font, FontFeatures, FontId, FontMetrics, FontStyle,
|
||||||
FontWeight, GlyphId, GlyphRasterParams, Pixels, PlatformTextSystem, Point, Result, ShapedGlyph,
|
FontWeight, GlyphId, Pixels, PlatformTextSystem, Point, RenderGlyphParams, Result, ShapedGlyph,
|
||||||
ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
@ -134,13 +134,13 @@ impl PlatformTextSystem for MacTextSystem {
|
||||||
self.0.read().glyph_for_char(font_id, ch)
|
self.0.read().glyph_for_char(font_id, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_raster_bounds(&self, params: &GlyphRasterParams) -> Result<Bounds<DevicePixels>> {
|
fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
||||||
self.0.read().raster_bounds(params)
|
self.0.read().raster_bounds(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &GlyphRasterParams,
|
glyph_id: &RenderGlyphParams,
|
||||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
self.0.read().rasterize_glyph(glyph_id)
|
self.0.read().rasterize_glyph(glyph_id)
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ impl MacTextSystemState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raster_bounds(&self, params: &GlyphRasterParams) -> Result<Bounds<DevicePixels>> {
|
fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
||||||
let font = &self.fonts[params.font_id.0];
|
let font = &self.fonts[params.font_id.0];
|
||||||
let scale = Transform2F::from_scale(params.scale_factor);
|
let scale = Transform2F::from_scale(params.scale_factor);
|
||||||
Ok(font
|
Ok(font
|
||||||
|
@ -248,7 +248,7 @@ impl MacTextSystemState {
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rasterize_glyph(&self, params: &GlyphRasterParams) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
fn rasterize_glyph(&self, params: &RenderGlyphParams) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
let glyph_bounds = self.raster_bounds(params)?;
|
let glyph_bounds = self.raster_bounds(params)?;
|
||||||
if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
|
if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
|
||||||
Err(anyhow!("glyph bounds are empty"))
|
Err(anyhow!("glyph bounds are empty"))
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use super::{ns_string, MetalRenderer, NSRange};
|
use super::{ns_string, MetalRenderer, NSRange};
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, AnyWindowHandle, Bounds, Event, GlyphRasterParams, KeyDownEvent, Keystroke,
|
point, px, size, AnyWindowHandle, Bounds, Event, KeyDownEvent, Keystroke, MacScreen, Modifiers,
|
||||||
MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent,
|
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
|
||||||
MouseUpEvent, NSRectExt, Pixels, Platform, PlatformAtlas, PlatformDispatcher,
|
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
|
||||||
PlatformInputHandler, PlatformScreen, PlatformWindow, Point, Scene, Size, Timer,
|
PlatformWindow, Point, Scene, Size, Timer, WindowAppearance, WindowBounds, WindowKind,
|
||||||
WindowAppearance, WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
|
WindowOptions, WindowPromptLevel,
|
||||||
};
|
};
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
|
@ -886,7 +886,7 @@ impl PlatformWindow for MacWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<GlyphRasterParams>> {
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas> {
|
||||||
self.0.lock().renderer.glyph_atlas().clone()
|
self.0.lock().renderer.glyph_atlas().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,13 +215,13 @@ impl TextSystem {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raster_bounds(&self, params: &GlyphRasterParams) -> Result<Bounds<DevicePixels>> {
|
pub fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
||||||
self.platform_text_system.glyph_raster_bounds(params)
|
self.platform_text_system.glyph_raster_bounds(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rasterize_glyph(
|
pub fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &GlyphRasterParams,
|
glyph_id: &RenderGlyphParams,
|
||||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
self.platform_text_system.rasterize_glyph(glyph_id)
|
self.platform_text_system.rasterize_glyph(glyph_id)
|
||||||
}
|
}
|
||||||
|
@ -384,7 +384,7 @@ pub struct ShapedGlyph {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct GlyphRasterParams {
|
pub struct RenderGlyphParams {
|
||||||
pub(crate) font_id: FontId,
|
pub(crate) font_id: FontId,
|
||||||
pub(crate) glyph_id: GlyphId,
|
pub(crate) glyph_id: GlyphId,
|
||||||
pub(crate) font_size: Pixels,
|
pub(crate) font_size: Pixels,
|
||||||
|
@ -392,9 +392,9 @@ pub struct GlyphRasterParams {
|
||||||
pub(crate) scale_factor: f32,
|
pub(crate) scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for GlyphRasterParams {}
|
impl Eq for RenderGlyphParams {}
|
||||||
|
|
||||||
impl Hash for GlyphRasterParams {
|
impl Hash for RenderGlyphParams {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.font_id.0.hash(state);
|
self.font_id.0.hash(state);
|
||||||
self.glyph_id.0.hash(state);
|
self.glyph_id.0.hash(state);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AnyView, AppContext, AvailableSpace, BorrowAppContext, Bounds, Context, Corners, Effect,
|
px, AnyView, AppContext, AvailableSpace, BorrowAppContext, Bounds, Context, Corners, Effect,
|
||||||
Element, EntityId, FontId, GlyphId, GlyphRasterParams, Handle, Hsla, IsZero, LayerId, LayoutId,
|
Element, EntityId, FontId, GlyphId, Handle, Hsla, IsZero, LayerId, LayoutId, MainThread,
|
||||||
MainThread, MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point,
|
MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point, Reference,
|
||||||
Reference, ScaledPixels, Scene, Size, Style, TaffyLayoutEngine, WeakHandle, WindowOptions,
|
RenderGlyphParams, ScaledPixels, Scene, Size, Style, TaffyLayoutEngine, WeakHandle,
|
||||||
SUBPIXEL_VARIANTS,
|
WindowOptions, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
@ -16,7 +16,7 @@ pub struct AnyWindow {}
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
|
platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
|
||||||
glyph_atlas: Arc<dyn PlatformAtlas<GlyphRasterParams>>,
|
glyph_atlas: Arc<dyn PlatformAtlas>,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
content_size: Size<Pixels>,
|
content_size: Size<Pixels>,
|
||||||
layout_engine: TaffyLayoutEngine,
|
layout_engine: TaffyLayoutEngine,
|
||||||
|
@ -222,7 +222,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
};
|
};
|
||||||
let params = GlyphRasterParams {
|
let params = RenderGlyphParams {
|
||||||
font_id,
|
font_id,
|
||||||
glyph_id,
|
glyph_id,
|
||||||
font_size,
|
font_size,
|
||||||
|
@ -236,7 +236,9 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
let tile = self
|
let tile = self
|
||||||
.window
|
.window
|
||||||
.glyph_atlas
|
.glyph_atlas
|
||||||
.get_or_insert_with(¶ms, &mut || self.text_system().rasterize_glyph(¶ms))?;
|
.get_or_insert_with(¶ms.clone().into(), &mut || {
|
||||||
|
self.text_system().rasterize_glyph(¶ms)
|
||||||
|
})?;
|
||||||
let bounds = Bounds {
|
let bounds = Bounds {
|
||||||
origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
|
origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
|
||||||
size: tile.bounds.size.map(Into::into),
|
size: tile.bounds.size.map(Into::into),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue