Checkpoint
This commit is contained in:
parent
a8c1958c75
commit
3b27d41c72
9 changed files with 234 additions and 93 deletions
|
@ -618,6 +618,12 @@ impl From<ScaledPixels> for DevicePixels {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<DevicePixels> for ScaledPixels {
|
||||||
|
fn from(device: DevicePixels) -> Self {
|
||||||
|
ScaledPixels(device.0 as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)]
|
#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)]
|
||||||
pub struct Rems(f32);
|
pub struct Rems(f32);
|
||||||
|
|
||||||
|
@ -802,3 +808,76 @@ impl From<()> for Length {
|
||||||
Self::Definite(DefiniteLength::default())
|
Self::Definite(DefiniteLength::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IsZero {
|
||||||
|
fn is_zero(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for DevicePixels {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for ScaledPixels {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0 == 0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for Pixels {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0 == 0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for Rems {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0 == 0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for AbsoluteLength {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
AbsoluteLength::Pixels(pixels) => pixels.is_zero(),
|
||||||
|
AbsoluteLength::Rems(rems) => rems.is_zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for DefiniteLength {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
DefiniteLength::Absolute(length) => length.is_zero(),
|
||||||
|
DefiniteLength::Fraction(fraction) => *fraction == 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsZero for Length {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Length::Definite(length) => length.is_zero(),
|
||||||
|
Length::Auto => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IsZero + Debug + Clone> IsZero for Point<T> {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.x.is_zero() && self.y.is_zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IsZero + Debug + Clone> IsZero for Size<T> {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.width.is_zero() && self.height.is_zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IsZero + Debug + Clone> IsZero for Bounds<T> {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.origin.is_zero() && self.size.is_zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ mod mac;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId, Pixels, Point,
|
AnyWindowHandle, Bounds, DevicePixels, Font, FontId, FontMetrics, GlyphId,
|
||||||
RasterizeGlyphParams, Result, Scene, ShapedLine, SharedString, Size,
|
GlyphRasterizationParams, Pixels, Point, 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<RasterizeGlyphParams>>;
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<GlyphRasterizationParams>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformDispatcher: Send + Sync {
|
pub trait PlatformDispatcher: Send + Sync {
|
||||||
|
@ -163,9 +163,13 @@ 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: &GlyphRasterizationParams,
|
||||||
|
) -> Result<Bounds<DevicePixels>>;
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizeGlyphParams,
|
params: &GlyphRasterizationParams,
|
||||||
) -> Result<(Size<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(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad,
|
point, size, AtlasTextureId, DevicePixels, GlyphRasterizationParams, MetalAtlas,
|
||||||
RasterizeGlyphParams, Scene, Size,
|
MonochromeSprite, Quad, Scene, Size,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
base::{NO, YES},
|
base::{NO, YES},
|
||||||
|
@ -22,7 +22,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<RasterizeGlyphParams>>,
|
glyph_atlas: Arc<MetalAtlas<GlyphRasterizationParams>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalRenderer {
|
impl MetalRenderer {
|
||||||
|
@ -126,7 +126,7 @@ impl MetalRenderer {
|
||||||
&*self.layer
|
&*self.layer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizeGlyphParams>> {
|
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<GlyphRasterizationParams>> {
|
||||||
&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, Pixels, PlatformTextSystem, Point, RasterizeGlyphParams, Result,
|
FontWeight, GlyphId, GlyphRasterizationParams, Pixels, PlatformTextSystem, Point, Result,
|
||||||
ShapedGlyph, ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
ShapedGlyph, ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
@ -134,9 +134,16 @@ 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: &GlyphRasterizationParams,
|
||||||
|
) -> Result<Bounds<DevicePixels>> {
|
||||||
|
self.0.read().raster_bounds(params)
|
||||||
|
}
|
||||||
|
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizeGlyphParams,
|
glyph_id: &GlyphRasterizationParams,
|
||||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
self.0.read().rasterize_glyph(glyph_id)
|
self.0.read().rasterize_glyph(glyph_id)
|
||||||
}
|
}
|
||||||
|
@ -230,37 +237,54 @@ impl MacTextSystemState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn raster_bounds(&self, params: &GlyphRasterizationParams) -> Result<Bounds<DevicePixels>> {
|
||||||
|
let font = &self.fonts[params.font_id.0];
|
||||||
|
let scale = Transform2F::from_scale(params.scale_factor);
|
||||||
|
Ok(font
|
||||||
|
.raster_bounds(
|
||||||
|
params.glyph_id.into(),
|
||||||
|
params.font_size.into(),
|
||||||
|
scale,
|
||||||
|
HintingOptions::None,
|
||||||
|
font_kit::canvas::RasterizationOptions::GrayscaleAa,
|
||||||
|
)?
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
|
||||||
fn rasterize_glyph(
|
fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizeGlyphParams,
|
params: &GlyphRasterizationParams,
|
||||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
let font = &self.fonts[glyph_id.font_id.0];
|
let glyph_bounds = self.raster_bounds(params)?;
|
||||||
let scale = Transform2F::from_scale(glyph_id.scale_factor);
|
|
||||||
let glyph_bounds = font.raster_bounds(
|
|
||||||
glyph_id.glyph_id.into(),
|
|
||||||
glyph_id.font_size.into(),
|
|
||||||
scale,
|
|
||||||
HintingOptions::None,
|
|
||||||
font_kit::canvas::RasterizationOptions::GrayscaleAa,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if glyph_bounds.width() == 0 || glyph_bounds.height() == 0 {
|
// let scale = Transform2F::from_scale(params.scale_factor);
|
||||||
|
// let glyph_bounds = font.raster_bounds(
|
||||||
|
// params.glyph_id.into(),
|
||||||
|
// params.font_size.into(),
|
||||||
|
// scale,
|
||||||
|
// HintingOptions::None,
|
||||||
|
// font_kit::canvas::RasterizationOptions::GrayscaleAa,
|
||||||
|
// )?;
|
||||||
|
|
||||||
|
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"))
|
||||||
} else {
|
} else {
|
||||||
// Make room for subpixel variants.
|
// Add an extra pixel when the subpixel variant isn't zero to make room for anti-aliasing.
|
||||||
let subpixel_padding = Vector2I::new(
|
let mut bitmap_size = glyph_bounds.size;
|
||||||
glyph_id.subpixel_variant.x.min(1) as i32,
|
if params.subpixel_variant.x > 0 {
|
||||||
glyph_id.subpixel_variant.y.min(1) as i32,
|
bitmap_size.width += DevicePixels(1);
|
||||||
);
|
}
|
||||||
let bitmap_size = glyph_bounds.size() + subpixel_padding;
|
if params.subpixel_variant.y > 0 {
|
||||||
|
bitmap_size.height += DevicePixels(1);
|
||||||
|
}
|
||||||
|
|
||||||
let mut bytes = vec![0; bitmap_size.x() as usize * bitmap_size.y() as usize];
|
let mut bytes = vec![0; bitmap_size.width.0 as usize * bitmap_size.height.0 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 _),
|
||||||
bitmap_size.x() as usize,
|
bitmap_size.width.0 as usize,
|
||||||
bitmap_size.y() as usize,
|
bitmap_size.height.0 as usize,
|
||||||
8,
|
8,
|
||||||
bitmap_size.x() as usize,
|
bitmap_size.width.0 as usize,
|
||||||
&CGColorSpace::create_device_gray(),
|
&CGColorSpace::create_device_gray(),
|
||||||
kCGImageAlphaOnly,
|
kCGImageAlphaOnly,
|
||||||
);
|
);
|
||||||
|
@ -268,26 +292,27 @@ impl MacTextSystemState {
|
||||||
// Move the origin to bottom left and account for scaling, this
|
// Move the origin to bottom left and account for scaling, this
|
||||||
// makes drawing text consistent with the font-kit's raster_bounds.
|
// makes drawing text consistent with the font-kit's raster_bounds.
|
||||||
cx.translate(
|
cx.translate(
|
||||||
-glyph_bounds.origin_x() as CGFloat,
|
-glyph_bounds.origin.x.0 as CGFloat,
|
||||||
(glyph_bounds.origin_y() + glyph_bounds.height()) as CGFloat,
|
(glyph_bounds.origin.y.0 + glyph_bounds.size.height.0) as CGFloat,
|
||||||
);
|
);
|
||||||
cx.scale(
|
cx.scale(
|
||||||
glyph_id.scale_factor as CGFloat,
|
params.scale_factor as CGFloat,
|
||||||
glyph_id.scale_factor as CGFloat,
|
params.scale_factor as CGFloat,
|
||||||
);
|
);
|
||||||
|
|
||||||
let subpixel_shift = glyph_id
|
let subpixel_shift = params
|
||||||
.subpixel_variant
|
.subpixel_variant
|
||||||
.map(|v| v as f32 / SUBPIXEL_VARIANTS as f32 / glyph_id.scale_factor);
|
.map(|v| v as f32 / SUBPIXEL_VARIANTS as f32 / params.scale_factor);
|
||||||
|
|
||||||
cx.set_allows_font_subpixel_positioning(true);
|
cx.set_allows_font_subpixel_positioning(true);
|
||||||
cx.set_should_subpixel_position_fonts(true);
|
cx.set_should_subpixel_position_fonts(true);
|
||||||
cx.set_allows_font_subpixel_quantization(false);
|
cx.set_allows_font_subpixel_quantization(false);
|
||||||
cx.set_should_subpixel_quantize_fonts(false);
|
cx.set_should_subpixel_quantize_fonts(false);
|
||||||
font.native_font()
|
self.fonts[params.font_id.0]
|
||||||
.clone_with_font_size(f32::from(glyph_id.font_size) as CGFloat)
|
.native_font()
|
||||||
|
.clone_with_font_size(f32::from(params.font_size) as CGFloat)
|
||||||
.draw_glyphs(
|
.draw_glyphs(
|
||||||
&[u32::from(glyph_id.glyph_id) as CGGlyph],
|
&[u32::from(params.glyph_id) as CGGlyph],
|
||||||
&[CGPoint::new(
|
&[CGPoint::new(
|
||||||
subpixel_shift.x as CGFloat,
|
subpixel_shift.x as CGFloat,
|
||||||
subpixel_shift.y as CGFloat,
|
subpixel_shift.y as CGFloat,
|
||||||
|
|
|
@ -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, KeyDownEvent, Keystroke, MacScreen, Modifiers,
|
point, px, size, AnyWindowHandle, Bounds, Event, GlyphRasterizationParams, KeyDownEvent,
|
||||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
|
Keystroke, MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
|
||||||
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
|
MouseMovedEvent, MouseUpEvent, NSRectExt, Pixels, Platform, PlatformAtlas, PlatformDispatcher,
|
||||||
PlatformWindow, Point, RasterizeGlyphParams, Scene, Size, Timer, WindowAppearance,
|
PlatformInputHandler, PlatformScreen, PlatformWindow, Point, Scene, Size, Timer,
|
||||||
WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
|
WindowAppearance, 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<RasterizeGlyphParams>> {
|
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<GlyphRasterizationParams>> {
|
||||||
self.0.lock().renderer.glyph_atlas().clone()
|
self.0.lock().renderer.glyph_atlas().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{iter::Peekable, mem};
|
use std::{iter::Peekable, mem};
|
||||||
|
|
||||||
use super::{Bounds, Hsla, Pixels, Point};
|
use super::{Bounds, Hsla, Point};
|
||||||
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledPixels};
|
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledPixels};
|
||||||
use collections::BTreeMap;
|
use collections::BTreeMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -35,7 +35,7 @@ impl Scene {
|
||||||
|
|
||||||
let primitive = primitive.into();
|
let primitive = primitive.into();
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Quad(mut quad) => {
|
Primitive::Quad(quad) => {
|
||||||
layer.quads.push(quad);
|
layer.quads.push(quad);
|
||||||
}
|
}
|
||||||
Primitive::Sprite(sprite) => {
|
Primitive::Sprite(sprite) => {
|
||||||
|
@ -233,9 +233,9 @@ impl From<Quad> for Primitive {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct MonochromeSprite {
|
pub struct MonochromeSprite {
|
||||||
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 color: Hsla,
|
pub color: Hsla,
|
||||||
pub tile: AtlasTile,
|
pub tile: AtlasTile,
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,9 +215,13 @@ impl TextSystem {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn raster_bounds(&self, params: &GlyphRasterizationParams) -> Result<Bounds<DevicePixels>> {
|
||||||
|
self.platform_text_system.glyph_raster_bounds(params)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rasterize_glyph(
|
pub fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
glyph_id: &RasterizeGlyphParams,
|
glyph_id: &GlyphRasterizationParams,
|
||||||
) -> 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)
|
||||||
}
|
}
|
||||||
|
@ -380,7 +384,7 @@ pub struct ShapedGlyph {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct RasterizeGlyphParams {
|
pub struct GlyphRasterizationParams {
|
||||||
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 +392,9 @@ pub struct RasterizeGlyphParams {
|
||||||
pub(crate) scale_factor: f32,
|
pub(crate) scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for RasterizeGlyphParams {}
|
impl Eq for GlyphRasterizationParams {}
|
||||||
|
|
||||||
impl Hash for RasterizeGlyphParams {
|
impl Hash for GlyphRasterizationParams {
|
||||||
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,11 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
black, point, px, Bounds, Corners, FontId, Hsla, Layout, MonochromeSprite, Pixels, Point,
|
black, point, px, Bounds, FontId, Hsla, Layout, Pixels, Point, RunStyle, ShapedBoundary,
|
||||||
RunStyle, ShapedBoundary, ShapedLine, ShapedRun, UnderlineStyle, WindowContext,
|
ShapedLine, ShapedRun, UnderlineStyle, WindowContext,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use util::ResultExt;
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
|
@ -162,36 +161,14 @@ impl Line {
|
||||||
if glyph.is_emoji {
|
if glyph.is_emoji {
|
||||||
todo!()
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
if let Some(tile) = cx
|
cx.paint_glyph(
|
||||||
.rasterize_glyph(
|
glyph_origin,
|
||||||
run.font_id,
|
layout.order,
|
||||||
glyph.id,
|
run.font_id,
|
||||||
self.layout.font_size,
|
glyph.id,
|
||||||
glyph_origin,
|
self.layout.font_size,
|
||||||
cx.scale_factor(),
|
color,
|
||||||
)
|
)?;
|
||||||
.log_err()
|
|
||||||
{
|
|
||||||
let layer_id = cx.current_layer_id();
|
|
||||||
|
|
||||||
let bounds = Bounds {
|
|
||||||
origin: glyph_origin + todo!(),
|
|
||||||
size: todo!(),
|
|
||||||
};
|
|
||||||
// cx.text_system().raster_bounds()
|
|
||||||
|
|
||||||
cx.scene().insert(
|
|
||||||
layer_id,
|
|
||||||
MonochromeSprite {
|
|
||||||
order: layout.order,
|
|
||||||
bounds,
|
|
||||||
clip_bounds: bounds,
|
|
||||||
clip_corner_radii: Corners::default(),
|
|
||||||
color,
|
|
||||||
tile,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AnyView, AppContext, AtlasTile, AvailableSpace, Bounds, Context, Effect, Element, EntityId,
|
px, AnyView, AppContext, AtlasTile, AvailableSpace, Bounds, Context, Effect, Element, EntityId,
|
||||||
FontId, GlyphId, Handle, LayoutId, MainThread, MainThreadOnly, Pixels, PlatformAtlas,
|
FontId, GlyphId, GlyphRasterizationParams, Handle, Hsla, IsZero, LayoutId, MainThread,
|
||||||
PlatformWindow, Point, RasterizeGlyphParams, Reference, Scene, Size, StackContext,
|
MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point, Reference,
|
||||||
StackingOrder, Style, TaffyLayoutEngine, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
Scene, Size, StackContext, StackingOrder, Style, TaffyLayoutEngine, WeakHandle, WindowOptions,
|
||||||
|
SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
@ -15,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<RasterizeGlyphParams>>,
|
glyph_atlas: Arc<dyn PlatformAtlas<GlyphRasterizationParams>>,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
content_size: Size<Pixels>,
|
content_size: Size<Pixels>,
|
||||||
layout_engine: TaffyLayoutEngine,
|
layout_engine: TaffyLayoutEngine,
|
||||||
|
@ -165,6 +166,57 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn paint_glyph(
|
||||||
|
&mut self,
|
||||||
|
origin: Point<Pixels>,
|
||||||
|
order: u32,
|
||||||
|
font_id: FontId,
|
||||||
|
glyph_id: GlyphId,
|
||||||
|
font_size: Pixels,
|
||||||
|
color: Hsla,
|
||||||
|
) -> Result<()> {
|
||||||
|
let scale_factor = self.scale_factor();
|
||||||
|
let origin = origin.scale(scale_factor);
|
||||||
|
let subpixel_variant = Point {
|
||||||
|
x: (origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
|
y: (origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
|
||||||
|
};
|
||||||
|
let params = GlyphRasterizationParams {
|
||||||
|
font_id,
|
||||||
|
glyph_id,
|
||||||
|
font_size,
|
||||||
|
subpixel_variant,
|
||||||
|
scale_factor,
|
||||||
|
};
|
||||||
|
|
||||||
|
let raster_bounds = self.text_system().raster_bounds(¶ms)?;
|
||||||
|
|
||||||
|
if !raster_bounds.is_zero() {
|
||||||
|
let layer_id = self.current_layer_id();
|
||||||
|
let bounds = Bounds {
|
||||||
|
origin: origin + raster_bounds.origin.map(Into::into),
|
||||||
|
size: raster_bounds.size.map(Into::into),
|
||||||
|
};
|
||||||
|
let tile = self
|
||||||
|
.window
|
||||||
|
.glyph_atlas
|
||||||
|
.get_or_insert_with(¶ms, &mut || self.text_system().rasterize_glyph(¶ms))?;
|
||||||
|
|
||||||
|
self.window.scene.insert(
|
||||||
|
layer_id,
|
||||||
|
MonochromeSprite {
|
||||||
|
order,
|
||||||
|
bounds,
|
||||||
|
clip_bounds: bounds,
|
||||||
|
clip_corner_radii: Default::default(),
|
||||||
|
color,
|
||||||
|
tile,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rasterize_glyph(
|
pub fn rasterize_glyph(
|
||||||
&self,
|
&self,
|
||||||
font_id: FontId,
|
font_id: FontId,
|
||||||
|
@ -178,7 +230,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
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 = RasterizeGlyphParams {
|
let rasterized_glyph_id = GlyphRasterizationParams {
|
||||||
font_id,
|
font_id,
|
||||||
glyph_id,
|
glyph_id,
|
||||||
font_size,
|
font_size,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue