Checkpoint
This commit is contained in:
parent
3698e89b88
commit
a8c1958c75
13 changed files with 248 additions and 186 deletions
|
@ -28,6 +28,15 @@ impl<T: Clone + Debug> Point<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Point<Pixels> {
|
||||||
|
pub fn scale(&self, factor: f32) -> Point<ScaledPixels> {
|
||||||
|
Point {
|
||||||
|
x: self.x.scale(factor),
|
||||||
|
y: self.y.scale(factor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, Rhs> Mul<Rhs> for Point<T>
|
impl<T, Rhs> Mul<Rhs> for Point<T>
|
||||||
where
|
where
|
||||||
T: Mul<Rhs, Output = T> + Clone + Debug,
|
T: Mul<Rhs, Output = T> + Clone + Debug,
|
||||||
|
@ -122,6 +131,15 @@ impl<T: Clone + Debug> Size<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Size<Pixels> {
|
||||||
|
pub fn scale(&self, factor: f32) -> Size<ScaledPixels> {
|
||||||
|
Size {
|
||||||
|
width: self.width.scale(factor),
|
||||||
|
height: self.height.scale(factor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Clone + Debug + Ord> Size<T> {
|
impl<T: Clone + Debug + Ord> Size<T> {
|
||||||
pub fn max(&self, other: &Self) -> Self {
|
pub fn max(&self, other: &Self) -> Self {
|
||||||
Size {
|
Size {
|
||||||
|
@ -207,7 +225,6 @@ pub struct Bounds<T: Clone + Debug> {
|
||||||
pub size: Size<T>,
|
pub size: Size<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bounds<f32> * Pixels = Bounds<Pixels>
|
|
||||||
impl<T, Rhs> Mul<Rhs> for Bounds<T>
|
impl<T, Rhs> Mul<Rhs> for Bounds<T>
|
||||||
where
|
where
|
||||||
T: Mul<Rhs, Output = Rhs> + Clone + Debug,
|
T: Mul<Rhs, Output = Rhs> + Clone + Debug,
|
||||||
|
@ -277,6 +294,15 @@ impl<T: Clone + Debug + PartialOrd + Add<T, Output = T>> Bounds<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Bounds<Pixels> {
|
||||||
|
pub fn scale(&self, factor: f32) -> Bounds<ScaledPixels> {
|
||||||
|
Bounds {
|
||||||
|
origin: self.origin.scale(factor),
|
||||||
|
size: self.size.scale(factor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
|
impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
|
||||||
|
|
||||||
#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
|
#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
|
||||||
|
@ -462,8 +488,8 @@ impl Pixels {
|
||||||
Self(self.0.floor())
|
Self(self.0.floor())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_device_pixels(&self, scale: f32) -> DevicePixels {
|
pub fn scale(&self, factor: f32) -> ScaledPixels {
|
||||||
DevicePixels((self.0 * scale).ceil() as u32)
|
ScaledPixels(self.0 * factor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,22 +568,22 @@ impl From<Pixels> for f64 {
|
||||||
SubAssign,
|
SubAssign,
|
||||||
)]
|
)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct DevicePixels(pub(crate) u32);
|
pub struct DevicePixels(pub(crate) i32);
|
||||||
|
|
||||||
impl DevicePixels {
|
impl DevicePixels {
|
||||||
pub fn to_bytes(&self, bytes_per_pixel: u8) -> u32 {
|
pub fn to_bytes(&self, bytes_per_pixel: u8) -> u32 {
|
||||||
self.0 * bytes_per_pixel as u32
|
self.0 as u32 * bytes_per_pixel as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DevicePixels> for u32 {
|
impl From<DevicePixels> for i32 {
|
||||||
fn from(device_pixels: DevicePixels) -> Self {
|
fn from(device_pixels: DevicePixels) -> Self {
|
||||||
device_pixels.0
|
device_pixels.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u32> for DevicePixels {
|
impl From<i32> for DevicePixels {
|
||||||
fn from(val: u32) -> Self {
|
fn from(val: i32) -> Self {
|
||||||
DevicePixels(val)
|
DevicePixels(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,7 +596,25 @@ impl From<DevicePixels> for u64 {
|
||||||
|
|
||||||
impl From<u64> for DevicePixels {
|
impl From<u64> for DevicePixels {
|
||||||
fn from(val: u64) -> Self {
|
fn from(val: u64) -> Self {
|
||||||
DevicePixels(val as u32)
|
DevicePixels(val as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, Add, AddAssign, Sub, SubAssign, Div, PartialEq, PartialOrd)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ScaledPixels(pub(crate) f32);
|
||||||
|
|
||||||
|
impl Eq for ScaledPixels {}
|
||||||
|
|
||||||
|
impl Debug for ScaledPixels {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} px (scaled)", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ScaledPixels> for DevicePixels {
|
||||||
|
fn from(scaled: ScaledPixels) -> Self {
|
||||||
|
DevicePixels(scaled.0.ceil() as i32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId, Pixels, Point,
|
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId, Pixels, Point,
|
||||||
RasterizedGlyphId, Result, Scene, ShapedLine, SharedString, Size,
|
RasterizeGlyphParams, 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<RasterizedGlyphId>>;
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<RasterizeGlyphParams>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformDispatcher: Send + Sync {
|
pub trait PlatformDispatcher: Send + Sync {
|
||||||
|
@ -165,8 +165,8 @@ pub trait PlatformTextSystem: Send + Sync {
|
||||||
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 rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizedGlyphId,
|
glyph_id: &RasterizeGlyphParams,
|
||||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)>;
|
) -> 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,
|
||||||
|
@ -197,7 +197,7 @@ pub struct AtlasTile {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(crate) struct AtlasTextureId(pub(crate) u32);
|
pub(crate) struct AtlasTextureId(pub(crate) u32); // We use u32 instead of usize for Metal Shader Language compatibility
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -28,6 +28,10 @@ impl<Key> MetalAtlas<Key> {
|
||||||
tiles_by_key: Default::default(),
|
tiles_by_key: Default::default(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn texture(&self, id: AtlasTextureId) -> metal::Texture {
|
||||||
|
self.0.lock().textures[id.0 as usize].metal_texture.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MetalAtlasState<Key> {
|
struct MetalAtlasState<Key> {
|
||||||
|
@ -123,10 +127,10 @@ impl MetalAtlasTexture {
|
||||||
bounds: allocation.rectangle.into(),
|
bounds: allocation.rectangle.into(),
|
||||||
};
|
};
|
||||||
let region = metal::MTLRegion::new_2d(
|
let region = metal::MTLRegion::new_2d(
|
||||||
u32::from(tile.bounds.origin.x) as u64,
|
tile.bounds.origin.x.into(),
|
||||||
u32::from(tile.bounds.origin.y) as u64,
|
tile.bounds.origin.y.into(),
|
||||||
u32::from(tile.bounds.size.width) as u64,
|
tile.bounds.size.width.into(),
|
||||||
u32::from(tile.bounds.size.height) as u64,
|
tile.bounds.size.height.into(),
|
||||||
);
|
);
|
||||||
self.metal_texture.replace_region(
|
self.metal_texture.replace_region(
|
||||||
region,
|
region,
|
||||||
|
@ -149,15 +153,15 @@ impl MetalAtlasTexture {
|
||||||
|
|
||||||
impl From<Size<DevicePixels>> for etagere::Size {
|
impl From<Size<DevicePixels>> for etagere::Size {
|
||||||
fn from(size: Size<DevicePixels>) -> Self {
|
fn from(size: Size<DevicePixels>) -> Self {
|
||||||
etagere::Size::new(u32::from(size.width) as i32, u32::from(size.width) as i32)
|
etagere::Size::new(size.width.into(), size.width.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<etagere::Point> for Point<DevicePixels> {
|
impl From<etagere::Point> for Point<DevicePixels> {
|
||||||
fn from(value: etagere::Point) -> Self {
|
fn from(value: etagere::Point) -> Self {
|
||||||
Point {
|
Point {
|
||||||
x: DevicePixels::from(value.x as u32),
|
x: DevicePixels::from(value.x),
|
||||||
y: DevicePixels::from(value.y as u32),
|
y: DevicePixels::from(value.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,8 +169,8 @@ impl From<etagere::Point> for Point<DevicePixels> {
|
||||||
impl From<etagere::Size> for Size<DevicePixels> {
|
impl From<etagere::Size> for Size<DevicePixels> {
|
||||||
fn from(size: etagere::Size) -> Self {
|
fn from(size: etagere::Size) -> Self {
|
||||||
Size {
|
Size {
|
||||||
width: DevicePixels::from(size.width as u32),
|
width: DevicePixels::from(size.width),
|
||||||
height: DevicePixels::from(size.height as u32),
|
height: DevicePixels::from(size.height),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad,
|
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad,
|
||||||
RasterizedGlyphId, Scene, Size,
|
RasterizeGlyphParams, Scene, Size,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
base::{NO, YES},
|
base::{NO, YES},
|
||||||
|
@ -18,10 +18,11 @@ pub struct MetalRenderer {
|
||||||
device: metal::Device,
|
device: metal::Device,
|
||||||
layer: metal::MetalLayer,
|
layer: metal::MetalLayer,
|
||||||
command_queue: CommandQueue,
|
command_queue: CommandQueue,
|
||||||
quad_pipeline_state: metal::RenderPipelineState,
|
quads_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<RasterizedGlyphId>>,
|
glyph_atlas: Arc<MetalAtlas<RasterizeGlyphParams>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalRenderer {
|
impl MetalRenderer {
|
||||||
|
@ -81,15 +82,24 @@ impl MetalRenderer {
|
||||||
MTLResourceOptions::StorageModeManaged,
|
MTLResourceOptions::StorageModeManaged,
|
||||||
);
|
);
|
||||||
|
|
||||||
let quad_pipeline_state = build_pipeline_state(
|
let quads_pipeline_state = build_pipeline_state(
|
||||||
&device,
|
&device,
|
||||||
&library,
|
&library,
|
||||||
"quad",
|
"quads",
|
||||||
"quad_vertex",
|
"quad_vertex",
|
||||||
"quad_fragment",
|
"quad_fragment",
|
||||||
PIXEL_FORMAT,
|
PIXEL_FORMAT,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let sprites_pipeline_state = build_pipeline_state(
|
||||||
|
&device,
|
||||||
|
&library,
|
||||||
|
"sprites",
|
||||||
|
"monochrome_sprite_vertex",
|
||||||
|
"monochrome_sprite_fragment",
|
||||||
|
PIXEL_FORMAT,
|
||||||
|
);
|
||||||
|
|
||||||
let command_queue = device.new_command_queue();
|
let command_queue = device.new_command_queue();
|
||||||
let glyph_atlas = Arc::new(MetalAtlas::new(
|
let glyph_atlas = Arc::new(MetalAtlas::new(
|
||||||
Size {
|
Size {
|
||||||
|
@ -104,7 +114,8 @@ impl MetalRenderer {
|
||||||
device,
|
device,
|
||||||
layer,
|
layer,
|
||||||
command_queue,
|
command_queue,
|
||||||
quad_pipeline_state,
|
quads_pipeline_state,
|
||||||
|
sprites_pipeline_state,
|
||||||
unit_vertices,
|
unit_vertices,
|
||||||
instances,
|
instances,
|
||||||
glyph_atlas,
|
glyph_atlas,
|
||||||
|
@ -115,7 +126,7 @@ impl MetalRenderer {
|
||||||
&*self.layer
|
&*self.layer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizedGlyphId>> {
|
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizeGlyphParams>> {
|
||||||
&self.glyph_atlas
|
&self.glyph_atlas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +134,8 @@ impl MetalRenderer {
|
||||||
let layer = self.layer.clone();
|
let layer = self.layer.clone();
|
||||||
let viewport_size = layer.drawable_size();
|
let viewport_size = layer.drawable_size();
|
||||||
let viewport_size: Size<DevicePixels> = size(
|
let viewport_size: Size<DevicePixels> = size(
|
||||||
(viewport_size.width.ceil() as u32).into(),
|
(viewport_size.width.ceil() as i32).into(),
|
||||||
(viewport_size.height.ceil() as u32).into(),
|
(viewport_size.height.ceil() as i32).into(),
|
||||||
);
|
);
|
||||||
let drawable = if let Some(drawable) = layer.next_drawable() {
|
let drawable = if let Some(drawable) = layer.next_drawable() {
|
||||||
drawable
|
drawable
|
||||||
|
@ -144,8 +155,8 @@ impl MetalRenderer {
|
||||||
depth_texture_desc.set_pixel_format(metal::MTLPixelFormat::Depth32Float);
|
depth_texture_desc.set_pixel_format(metal::MTLPixelFormat::Depth32Float);
|
||||||
depth_texture_desc.set_storage_mode(metal::MTLStorageMode::Private);
|
depth_texture_desc.set_storage_mode(metal::MTLStorageMode::Private);
|
||||||
depth_texture_desc.set_usage(metal::MTLTextureUsage::RenderTarget);
|
depth_texture_desc.set_usage(metal::MTLTextureUsage::RenderTarget);
|
||||||
depth_texture_desc.set_width(u32::from(viewport_size.width) as u64);
|
depth_texture_desc.set_width(i32::from(viewport_size.width) as u64);
|
||||||
depth_texture_desc.set_height(u32::from(viewport_size.height) as u64);
|
depth_texture_desc.set_height(i32::from(viewport_size.height) as u64);
|
||||||
let depth_texture = self.device.new_texture(&depth_texture_desc);
|
let depth_texture = self.device.new_texture(&depth_texture_desc);
|
||||||
let depth_attachment = render_pass_descriptor.depth_attachment().unwrap();
|
let depth_attachment = render_pass_descriptor.depth_attachment().unwrap();
|
||||||
|
|
||||||
|
@ -168,8 +179,8 @@ impl MetalRenderer {
|
||||||
command_encoder.set_viewport(metal::MTLViewport {
|
command_encoder.set_viewport(metal::MTLViewport {
|
||||||
originX: 0.0,
|
originX: 0.0,
|
||||||
originY: 0.0,
|
originY: 0.0,
|
||||||
width: u32::from(viewport_size.width) as f64,
|
width: i32::from(viewport_size.width) as f64,
|
||||||
height: u32::from(viewport_size.height) as f64,
|
height: i32::from(viewport_size.height) as f64,
|
||||||
znear: 0.0,
|
znear: 0.0,
|
||||||
zfar: 1.0,
|
zfar: 1.0,
|
||||||
});
|
});
|
||||||
|
@ -226,7 +237,7 @@ impl MetalRenderer {
|
||||||
}
|
}
|
||||||
align_offset(offset);
|
align_offset(offset);
|
||||||
|
|
||||||
command_encoder.set_render_pipeline_state(&self.quad_pipeline_state);
|
command_encoder.set_render_pipeline_state(&self.quads_pipeline_state);
|
||||||
command_encoder.set_vertex_buffer(
|
command_encoder.set_vertex_buffer(
|
||||||
QuadInputIndex::Vertices as u64,
|
QuadInputIndex::Vertices as u64,
|
||||||
Some(&self.unit_vertices),
|
Some(&self.unit_vertices),
|
||||||
|
@ -273,12 +284,77 @@ impl MetalRenderer {
|
||||||
fn draw_monochrome_sprites(
|
fn draw_monochrome_sprites(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture_id: AtlasTextureId,
|
texture_id: AtlasTextureId,
|
||||||
monochrome: &[MonochromeSprite],
|
sprites: &[MonochromeSprite],
|
||||||
offset: &mut usize,
|
offset: &mut usize,
|
||||||
viewport_size: Size<DevicePixels>,
|
viewport_size: Size<DevicePixels>,
|
||||||
command_encoder: &metal::RenderCommandEncoderRef,
|
command_encoder: &metal::RenderCommandEncoderRef,
|
||||||
) {
|
) {
|
||||||
// todo!()
|
// dbg!(sprites);
|
||||||
|
|
||||||
|
if sprites.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
align_offset(offset);
|
||||||
|
|
||||||
|
let texture = self.glyph_atlas.texture(texture_id);
|
||||||
|
let texture_size = size(
|
||||||
|
DevicePixels(texture.width() as i32),
|
||||||
|
DevicePixels(texture.height() as i32),
|
||||||
|
);
|
||||||
|
command_encoder.set_render_pipeline_state(&self.sprites_pipeline_state);
|
||||||
|
command_encoder.set_vertex_buffer(
|
||||||
|
MonochromeSpriteInputIndex::Vertices as u64,
|
||||||
|
Some(&self.unit_vertices),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
command_encoder.set_vertex_buffer(
|
||||||
|
MonochromeSpriteInputIndex::Sprites as u64,
|
||||||
|
Some(&self.instances),
|
||||||
|
*offset as u64,
|
||||||
|
);
|
||||||
|
command_encoder.set_vertex_bytes(
|
||||||
|
MonochromeSpriteInputIndex::ViewportSize as u64,
|
||||||
|
mem::size_of_val(&viewport_size) as u64,
|
||||||
|
&viewport_size as *const Size<DevicePixels> as *const _,
|
||||||
|
);
|
||||||
|
command_encoder.set_vertex_bytes(
|
||||||
|
MonochromeSpriteInputIndex::AtlasTextureSize as u64,
|
||||||
|
mem::size_of_val(&texture_size) as u64,
|
||||||
|
&texture_size as *const Size<DevicePixels> as *const _,
|
||||||
|
);
|
||||||
|
command_encoder.set_fragment_buffer(
|
||||||
|
MonochromeSpriteInputIndex::Sprites as u64,
|
||||||
|
Some(&self.instances),
|
||||||
|
*offset as u64,
|
||||||
|
);
|
||||||
|
command_encoder.set_fragment_texture(
|
||||||
|
MonochromeSpriteInputIndex::AtlasTexture as u64,
|
||||||
|
Some(&texture),
|
||||||
|
);
|
||||||
|
|
||||||
|
let sprite_bytes_len = mem::size_of::<MonochromeSprite>() * sprites.len();
|
||||||
|
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
sprites.as_ptr() as *const u8,
|
||||||
|
buffer_contents,
|
||||||
|
sprite_bytes_len,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_offset = *offset + sprite_bytes_len;
|
||||||
|
assert!(
|
||||||
|
next_offset <= INSTANCE_BUFFER_SIZE,
|
||||||
|
"instance buffer exhausted"
|
||||||
|
);
|
||||||
|
|
||||||
|
command_encoder.draw_primitives_instanced(
|
||||||
|
metal::MTLPrimitiveType::Triangle,
|
||||||
|
0,
|
||||||
|
6,
|
||||||
|
sprites.len() as u64,
|
||||||
|
);
|
||||||
|
*offset = next_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +410,6 @@ enum MonochromeSpriteInputIndex {
|
||||||
Vertices = 0,
|
Vertices = 0,
|
||||||
Sprites = 1,
|
Sprites = 1,
|
||||||
ViewportSize = 2,
|
ViewportSize = 2,
|
||||||
AtlasSize = 3,
|
AtlasTextureSize = 3,
|
||||||
AtlasTexture = 4,
|
AtlasTexture = 4,
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
|
||||||
constant Size_DevicePixels *viewport_size
|
constant Size_DevicePixels *viewport_size
|
||||||
[[buffer(MonochromeSpriteInputIndex_ViewportSize)]],
|
[[buffer(MonochromeSpriteInputIndex_ViewportSize)]],
|
||||||
constant Size_DevicePixels *atlas_size
|
constant Size_DevicePixels *atlas_size
|
||||||
[[buffer(MonochromeSpriteInputIndex_AtlasSize)]]) {
|
[[buffer(MonochromeSpriteInputIndex_AtlasTextureSize)]]) {
|
||||||
|
|
||||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||||
MonochromeSprite sprite = sprites[sprite_id];
|
MonochromeSprite sprite = sprites[sprite_id];
|
||||||
|
@ -149,11 +149,13 @@ fragment float4 monochrome_sprite_fragment(
|
||||||
MonochromeSpriteVertexOutput input [[stage_in]],
|
MonochromeSpriteVertexOutput input [[stage_in]],
|
||||||
constant MonochromeSprite *sprites
|
constant MonochromeSprite *sprites
|
||||||
[[buffer(MonochromeSpriteInputIndex_Sprites)]],
|
[[buffer(MonochromeSpriteInputIndex_Sprites)]],
|
||||||
texture2d<float> atlas
|
texture2d<float> atlas_texture
|
||||||
[[texture(MonochromeSpriteInputIndex_AtlasTexture)]]) {
|
[[texture(MonochromeSpriteInputIndex_AtlasTexture)]]) {
|
||||||
MonochromeSprite sprite = sprites[input.sprite_id];
|
MonochromeSprite sprite = sprites[input.sprite_id];
|
||||||
constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
|
constexpr sampler atlas_texture_sampler(mag_filter::linear,
|
||||||
float4 sample = atlas.sample(atlas_sampler, input.tile_position);
|
min_filter::linear);
|
||||||
|
float4 sample =
|
||||||
|
atlas_texture.sample(atlas_texture_sampler, input.tile_position);
|
||||||
float clip_distance =
|
float clip_distance =
|
||||||
quad_sdf(input.position.xy, sprite.clip_bounds, sprite.clip_corner_radii);
|
quad_sdf(input.position.xy, sprite.clip_bounds, sprite.clip_corner_radii);
|
||||||
float4 color = input.color;
|
float4 color = input.color;
|
||||||
|
@ -256,52 +258,3 @@ float quad_sdf(float2 point, Bounds_Pixels bounds,
|
||||||
|
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct SpriteFragmentInput {
|
|
||||||
// float4 position [[position]];
|
|
||||||
// float2 atlas_position;
|
|
||||||
// float4 color [[flat]];
|
|
||||||
// uchar compute_winding [[flat]];
|
|
||||||
// };
|
|
||||||
|
|
||||||
// vertex SpriteFragmentInput sprite_vertex(
|
|
||||||
// uint unit_vertex_id [[vertex_id]],
|
|
||||||
// uint sprite_id [[instance_id]],
|
|
||||||
// constant float2 *unit_vertices
|
|
||||||
// [[buffer(GPUISpriteVertexInputIndexVertices)]], constant GPUISprite
|
|
||||||
// *sprites [[buffer(GPUISpriteVertexInputIndexSprites)]], constant float2
|
|
||||||
// *viewport_size [[buffer(GPUISpriteVertexInputIndexViewportSize)]],
|
|
||||||
// constant float2 *atlas_size
|
|
||||||
// [[buffer(GPUISpriteVertexInputIndexAtlasSize)]]
|
|
||||||
// ) {
|
|
||||||
// float2 unit_vertex = unit_vertices[unit_vertex_id];
|
|
||||||
// GPUISprite sprite = sprites[sprite_id];
|
|
||||||
// float2 position = unit_vertex * sprite.target_size + sprite.origin;
|
|
||||||
// float4 device_position = to_device_position(position, *viewport_size);
|
|
||||||
// float2 atlas_position = (unit_vertex * sprite.source_size +
|
|
||||||
// sprite.atlas_origin) / *atlas_size;
|
|
||||||
|
|
||||||
// return SpriteFragmentInput {
|
|
||||||
// device_position,
|
|
||||||
// atlas_position,
|
|
||||||
// coloru_to_colorf(sprite.color),
|
|
||||||
// sprite.compute_winding
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fragment float4 sprite_fragment(
|
|
||||||
// SpriteFragmentInput input [[stage_in]],
|
|
||||||
// texture2d<float> atlas [[ texture(GPUISpriteFragmentInputIndexAtlas) ]]
|
|
||||||
// ) {
|
|
||||||
// constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
|
|
||||||
// float4 color = input.color;
|
|
||||||
// float4 sample = atlas.sample(atlas_sampler, input.atlas_position);
|
|
||||||
// float mask;
|
|
||||||
// if (input.compute_winding) {
|
|
||||||
// mask = 1. - abs(1. - fmod(sample.r, 2.));
|
|
||||||
// } else {
|
|
||||||
// mask = sample.a;
|
|
||||||
// }
|
|
||||||
// color.a *= mask;
|
|
||||||
// return color;
|
|
||||||
// }
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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, Pixels, PlatformTextSystem, Point, RasterizedGlyphId, Result, ShapedGlyph,
|
FontWeight, GlyphId, Pixels, PlatformTextSystem, Point, RasterizeGlyphParams, Result,
|
||||||
ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
ShapedGlyph, ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use cocoa::appkit::{CGFloat, CGPoint};
|
use cocoa::appkit::{CGFloat, CGPoint};
|
||||||
|
@ -136,8 +136,8 @@ impl PlatformTextSystem for MacTextSystem {
|
||||||
|
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizedGlyphId,
|
glyph_id: &RasterizeGlyphParams,
|
||||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
self.0.read().rasterize_glyph(glyph_id)
|
self.0.read().rasterize_glyph(glyph_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +232,8 @@ impl MacTextSystemState {
|
||||||
|
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizedGlyphId,
|
glyph_id: &RasterizeGlyphParams,
|
||||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
let font = &self.fonts[glyph_id.font_id.0];
|
let font = &self.fonts[glyph_id.font_id.0];
|
||||||
let scale = Transform2F::from_scale(glyph_id.scale_factor);
|
let scale = Transform2F::from_scale(glyph_id.scale_factor);
|
||||||
let glyph_bounds = font.raster_bounds(
|
let glyph_bounds = font.raster_bounds(
|
||||||
|
@ -252,18 +252,15 @@ impl MacTextSystemState {
|
||||||
glyph_id.subpixel_variant.x.min(1) as i32,
|
glyph_id.subpixel_variant.x.min(1) as i32,
|
||||||
glyph_id.subpixel_variant.y.min(1) as i32,
|
glyph_id.subpixel_variant.y.min(1) as i32,
|
||||||
);
|
);
|
||||||
let cx_bounds = RectI::new(
|
let bitmap_size = glyph_bounds.size() + subpixel_padding;
|
||||||
glyph_bounds.origin(),
|
|
||||||
glyph_bounds.size() + subpixel_padding,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut bytes = vec![0; cx_bounds.width() as usize * cx_bounds.height() as usize];
|
let mut bytes = vec![0; bitmap_size.x() as usize * bitmap_size.y() as usize];
|
||||||
let cx = CGContext::create_bitmap_context(
|
let cx = CGContext::create_bitmap_context(
|
||||||
Some(bytes.as_mut_ptr() as *mut _),
|
Some(bytes.as_mut_ptr() as *mut _),
|
||||||
cx_bounds.width() as usize,
|
bitmap_size.x() as usize,
|
||||||
cx_bounds.height() as usize,
|
bitmap_size.y() as usize,
|
||||||
8,
|
8,
|
||||||
cx_bounds.width() as usize,
|
bitmap_size.x() as usize,
|
||||||
&CGColorSpace::create_device_gray(),
|
&CGColorSpace::create_device_gray(),
|
||||||
kCGImageAlphaOnly,
|
kCGImageAlphaOnly,
|
||||||
);
|
);
|
||||||
|
@ -298,7 +295,7 @@ impl MacTextSystemState {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((cx_bounds.into(), bytes))
|
Ok((bitmap_size.into(), bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,14 +508,23 @@ impl From<RectF> for Bounds<f32> {
|
||||||
impl From<RectI> for Bounds<DevicePixels> {
|
impl From<RectI> for Bounds<DevicePixels> {
|
||||||
fn from(rect: RectI) -> Self {
|
fn from(rect: RectI) -> Self {
|
||||||
Bounds {
|
Bounds {
|
||||||
origin: point(
|
origin: point(DevicePixels(rect.origin_x()), DevicePixels(rect.origin_y())),
|
||||||
DevicePixels(rect.origin_x() as u32),
|
size: size(DevicePixels(rect.width()), DevicePixels(rect.height())),
|
||||||
DevicePixels(rect.origin_y() as u32),
|
}
|
||||||
),
|
}
|
||||||
size: size(
|
}
|
||||||
DevicePixels(rect.width() as u32),
|
|
||||||
DevicePixels(rect.height() as u32),
|
impl From<Vector2I> for Size<DevicePixels> {
|
||||||
),
|
fn from(value: Vector2I) -> Self {
|
||||||
|
size(value.x().into(), value.y().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RectI> for Bounds<i32> {
|
||||||
|
fn from(rect: RectI) -> Self {
|
||||||
|
Bounds {
|
||||||
|
origin: point(rect.origin_x(), rect.origin_y()),
|
||||||
|
size: size(rect.width(), rect.height()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use crate::{
|
||||||
point, px, size, AnyWindowHandle, Bounds, Event, KeyDownEvent, Keystroke, MacScreen, Modifiers,
|
point, px, size, AnyWindowHandle, Bounds, Event, KeyDownEvent, Keystroke, MacScreen, Modifiers,
|
||||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
|
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
|
||||||
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
|
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
|
||||||
PlatformWindow, Point, RasterizedGlyphId, Scene, Size, Timer, WindowAppearance, WindowBounds,
|
PlatformWindow, Point, RasterizeGlyphParams, Scene, Size, Timer, WindowAppearance,
|
||||||
WindowKind, WindowOptions, WindowPromptLevel,
|
WindowBounds, WindowKind, 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<RasterizedGlyphId>> {
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<RasterizeGlyphParams>> {
|
||||||
self.0.lock().renderer.glyph_atlas().clone()
|
self.0.lock().renderer.glyph_atlas().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{iter::Peekable, mem};
|
use std::{iter::Peekable, mem};
|
||||||
|
|
||||||
use super::{Bounds, Hsla, Pixels, Point};
|
use super::{Bounds, Hsla, Pixels, Point};
|
||||||
use crate::{AtlasTextureId, AtlasTile, Corners, Edges};
|
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledPixels};
|
||||||
use collections::BTreeMap;
|
use collections::BTreeMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ impl Scene {
|
||||||
let primitive = primitive.into();
|
let primitive = primitive.into();
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Quad(mut quad) => {
|
Primitive::Quad(mut quad) => {
|
||||||
quad.scale(self.scale_factor);
|
|
||||||
layer.quads.push(quad);
|
layer.quads.push(quad);
|
||||||
}
|
}
|
||||||
Primitive::Sprite(sprite) => {
|
Primitive::Sprite(sprite) => {
|
||||||
|
@ -187,17 +186,17 @@ pub(crate) enum PrimitiveBatch<'a> {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Quad {
|
pub struct Quad {
|
||||||
pub order: u32,
|
pub order: u32,
|
||||||
pub bounds: Bounds<Pixels>,
|
pub bounds: Bounds<ScaledPixels>,
|
||||||
pub clip_bounds: Bounds<Pixels>,
|
pub clip_bounds: Bounds<ScaledPixels>,
|
||||||
pub clip_corner_radii: Corners<Pixels>,
|
pub clip_corner_radii: Corners<ScaledPixels>,
|
||||||
pub background: Hsla,
|
pub background: Hsla,
|
||||||
pub border_color: Hsla,
|
pub border_color: Hsla,
|
||||||
pub corner_radii: Corners<Pixels>,
|
pub corner_radii: Corners<ScaledPixels>,
|
||||||
pub border_widths: Edges<Pixels>,
|
pub border_widths: Edges<ScaledPixels>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Quad {
|
impl Quad {
|
||||||
pub fn vertices(&self) -> impl Iterator<Item = Point<Pixels>> {
|
pub fn vertices(&self) -> impl Iterator<Item = Point<ScaledPixels>> {
|
||||||
let x1 = self.bounds.origin.x;
|
let x1 = self.bounds.origin.x;
|
||||||
let y1 = self.bounds.origin.y;
|
let y1 = self.bounds.origin.y;
|
||||||
let x2 = x1 + self.bounds.size.width;
|
let x2 = x1 + self.bounds.size.width;
|
||||||
|
@ -210,14 +209,6 @@ impl Quad {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(&mut self, factor: f32) {
|
|
||||||
self.bounds *= factor;
|
|
||||||
self.clip_bounds *= factor;
|
|
||||||
self.clip_corner_radii *= factor;
|
|
||||||
self.corner_radii *= factor;
|
|
||||||
self.border_widths *= factor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Quad {
|
impl Ord for Quad {
|
||||||
|
|
|
@ -182,6 +182,7 @@ impl Style {
|
||||||
/// Paints the background of an element styled with this style.
|
/// Paints the background of an element styled with this style.
|
||||||
pub fn paint<V: 'static>(&self, order: u32, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
|
pub fn paint<V: 'static>(&self, order: u32, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
|
||||||
let rem_size = cx.rem_size();
|
let rem_size = cx.rem_size();
|
||||||
|
let scale = cx.scale_factor();
|
||||||
|
|
||||||
let background_color = self.fill.as_ref().and_then(Fill::color);
|
let background_color = self.fill.as_ref().and_then(Fill::color);
|
||||||
if background_color.is_some() || self.is_border_visible() {
|
if background_color.is_some() || self.is_border_visible() {
|
||||||
|
@ -190,13 +191,19 @@ impl Style {
|
||||||
layer_id,
|
layer_id,
|
||||||
Quad {
|
Quad {
|
||||||
order,
|
order,
|
||||||
bounds,
|
bounds: bounds.scale(scale),
|
||||||
clip_bounds: bounds, // todo!
|
clip_bounds: bounds.scale(scale), // todo!
|
||||||
clip_corner_radii: self.corner_radii.map(|length| length.to_pixels(rem_size)),
|
clip_corner_radii: self
|
||||||
|
.corner_radii
|
||||||
|
.map(|length| length.to_pixels(rem_size).scale(scale)),
|
||||||
background: background_color.unwrap_or_default(),
|
background: background_color.unwrap_or_default(),
|
||||||
border_color: self.border_color.unwrap_or_default(),
|
border_color: self.border_color.unwrap_or_default(),
|
||||||
corner_radii: self.corner_radii.map(|length| length.to_pixels(rem_size)),
|
corner_radii: self
|
||||||
border_widths: self.border_widths.map(|length| length.to_pixels(rem_size)),
|
.corner_radii
|
||||||
|
.map(|length| length.to_pixels(rem_size).scale(scale)),
|
||||||
|
border_widths: self
|
||||||
|
.border_widths
|
||||||
|
.map(|length| length.to_pixels(rem_size).scale(scale)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,8 +217,8 @@ impl TextSystem {
|
||||||
|
|
||||||
pub fn rasterize_glyph(
|
pub fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizedGlyphId,
|
glyph_id: &RasterizeGlyphParams,
|
||||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
self.platform_text_system.rasterize_glyph(glyph_id)
|
self.platform_text_system.rasterize_glyph(glyph_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ pub struct ShapedGlyph {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct RasterizedGlyphId {
|
pub struct RasterizeGlyphParams {
|
||||||
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,
|
||||||
|
@ -388,9 +388,9 @@ pub struct RasterizedGlyphId {
|
||||||
pub(crate) scale_factor: f32,
|
pub(crate) scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for RasterizedGlyphId {}
|
impl Eq for RasterizeGlyphParams {}
|
||||||
|
|
||||||
impl Hash for RasterizedGlyphId {
|
impl Hash for RasterizeGlyphParams {
|
||||||
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);
|
||||||
|
|
|
@ -157,35 +157,29 @@ impl Line {
|
||||||
|
|
||||||
if let Some((_underline_origin, _underline_style)) = finished_underline {
|
if let Some((_underline_origin, _underline_style)) = finished_underline {
|
||||||
todo!()
|
todo!()
|
||||||
// cx.scene().insert(Underline {
|
|
||||||
// origin: underline_origin,
|
|
||||||
// width: glyph_origin.x - underline_origin.x,
|
|
||||||
// thickness: underline_style.thickness.into(),
|
|
||||||
// color: underline_style.color.unwrap(),
|
|
||||||
// squiggly: underline_style.squiggly,
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if glyph.is_emoji {
|
if glyph.is_emoji {
|
||||||
todo!()
|
todo!()
|
||||||
// cx.scene().push_image_glyph(scene::ImageGlyph {
|
|
||||||
// font_id: run.font_id,
|
|
||||||
// font_size: self.layout.font_size,
|
|
||||||
// id: glyph.id,
|
|
||||||
// origin: glyph_origin,
|
|
||||||
// });
|
|
||||||
} else {
|
} else {
|
||||||
if let Some((tile, bounds)) = cx
|
if let Some(tile) = cx
|
||||||
.rasterize_glyph(
|
.rasterize_glyph(
|
||||||
run.font_id,
|
run.font_id,
|
||||||
glyph.id,
|
glyph.id,
|
||||||
self.layout.font_size,
|
self.layout.font_size,
|
||||||
cx.scale_factor(),
|
|
||||||
glyph_origin,
|
glyph_origin,
|
||||||
|
cx.scale_factor(),
|
||||||
)
|
)
|
||||||
.log_err()
|
.log_err()
|
||||||
{
|
{
|
||||||
let layer_id = cx.current_layer_id();
|
let layer_id = cx.current_layer_id();
|
||||||
|
|
||||||
|
let bounds = Bounds {
|
||||||
|
origin: glyph_origin + todo!(),
|
||||||
|
size: todo!(),
|
||||||
|
};
|
||||||
|
// cx.text_system().raster_bounds()
|
||||||
|
|
||||||
cx.scene().insert(
|
cx.scene().insert(
|
||||||
layer_id,
|
layer_id,
|
||||||
MonochromeSprite {
|
MonochromeSprite {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AnyView, AppContext, AtlasTile, AvailableSpace, Bounds, Context, DevicePixels, Effect,
|
px, AnyView, AppContext, AtlasTile, AvailableSpace, Bounds, Context, Effect, Element, EntityId,
|
||||||
Element, EntityId, FontId, GlyphId, Handle, LayoutId, MainThread, MainThreadOnly,
|
FontId, GlyphId, Handle, LayoutId, MainThread, MainThreadOnly, Pixels, PlatformAtlas,
|
||||||
MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point, RasterizedGlyphId, Reference,
|
PlatformWindow, Point, RasterizeGlyphParams, Reference, Scene, Size, StackContext,
|
||||||
Scene, Size, StackContext, StackingOrder, Style, TaffyLayoutEngine, WeakHandle, WindowOptions,
|
StackingOrder, Style, TaffyLayoutEngine, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
||||||
SUBPIXEL_VARIANTS,
|
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
@ -16,7 +15,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<RasterizedGlyphId>>,
|
glyph_atlas: Arc<dyn PlatformAtlas<RasterizeGlyphParams>>,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
content_size: Size<Pixels>,
|
content_size: Size<Pixels>,
|
||||||
layout_engine: TaffyLayoutEngine,
|
layout_engine: TaffyLayoutEngine,
|
||||||
|
@ -171,39 +170,26 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
font_id: FontId,
|
font_id: FontId,
|
||||||
glyph_id: GlyphId,
|
glyph_id: GlyphId,
|
||||||
font_size: Pixels,
|
font_size: Pixels,
|
||||||
scale_factor: f32,
|
|
||||||
target_position: Point<Pixels>,
|
target_position: Point<Pixels>,
|
||||||
) -> Result<(AtlasTile, Bounds<Pixels>)> {
|
scale_factor: f32,
|
||||||
|
) -> Result<AtlasTile> {
|
||||||
let target_position = target_position * scale_factor;
|
let target_position = target_position * scale_factor;
|
||||||
let subpixel_variant = Point {
|
let subpixel_variant = Point {
|
||||||
x: (target_position.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
x: (target_position.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
y: (target_position.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
y: (target_position.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
};
|
};
|
||||||
let rasterized_glyph_id = RasterizedGlyphId {
|
let rasterized_glyph_id = RasterizeGlyphParams {
|
||||||
font_id,
|
font_id,
|
||||||
glyph_id,
|
glyph_id,
|
||||||
font_size,
|
font_size,
|
||||||
subpixel_variant,
|
subpixel_variant,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
};
|
};
|
||||||
let mut offset = Default::default();
|
self.window
|
||||||
let tile = self
|
|
||||||
.window
|
|
||||||
.glyph_atlas
|
.glyph_atlas
|
||||||
.get_or_insert_with(&rasterized_glyph_id, &mut || {
|
.get_or_insert_with(&rasterized_glyph_id, &mut || {
|
||||||
let (bounds, pixels) = self.text_system().rasterize_glyph(&rasterized_glyph_id)?;
|
self.text_system().rasterize_glyph(&rasterized_glyph_id)
|
||||||
offset = bounds.origin;
|
})
|
||||||
Ok((bounds.size, pixels))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Align bounding box surrounding glyph to pixel grid
|
|
||||||
let mut origin = (target_position * scale_factor).map(|p| p.floor());
|
|
||||||
// Position glyph within bounding box
|
|
||||||
origin += offset.map(|o| px(u32::from(o) as f32));
|
|
||||||
let size = tile.bounds.size.map(|b| px(b.0 as f32));
|
|
||||||
let bounds = Bounds { origin, size };
|
|
||||||
|
|
||||||
Ok((tile, bounds))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn draw(&mut self) -> Result<()> {
|
pub(crate) fn draw(&mut self) -> Result<()> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
themes::rose_pine_dawn,
|
themes::rose_pine_dawn,
|
||||||
};
|
};
|
||||||
use gpui3::{
|
use gpui3::{
|
||||||
div, img, svg, view, Context, Element, ParentElement, RootView, StyleHelpers, View,
|
black, div, img, svg, view, Context, Element, ParentElement, RootView, StyleHelpers, View,
|
||||||
ViewContext, WindowContext,
|
ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ impl Workspace {
|
||||||
let theme = rose_pine_dawn();
|
let theme = rose_pine_dawn();
|
||||||
div()
|
div()
|
||||||
.font("Helvetica")
|
.font("Helvetica")
|
||||||
|
.text_color(black())
|
||||||
.text_base()
|
.text_base()
|
||||||
.size_full()
|
.size_full()
|
||||||
.fill(theme.middle.positive.default.background)
|
.fill(theme.middle.positive.default.background)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue