Checkpoint

This commit is contained in:
Nathan Sobo
2023-10-03 13:52:10 -06:00
parent a8c1958c75
commit 3b27d41c72
9 changed files with 234 additions and 93 deletions
@@ -1,6 +1,6 @@
use crate::{
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad,
RasterizeGlyphParams, Scene, Size,
point, size, AtlasTextureId, DevicePixels, GlyphRasterizationParams, MetalAtlas,
MonochromeSprite, Quad, Scene, Size,
};
use cocoa::{
base::{NO, YES},
@@ -22,7 +22,7 @@ pub struct MetalRenderer {
sprites_pipeline_state: metal::RenderPipelineState,
unit_vertices: metal::Buffer,
instances: metal::Buffer,
glyph_atlas: Arc<MetalAtlas<RasterizeGlyphParams>>,
glyph_atlas: Arc<MetalAtlas<GlyphRasterizationParams>>,
}
impl MetalRenderer {
@@ -126,7 +126,7 @@ impl MetalRenderer {
&*self.layer
}
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizeGlyphParams>> {
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<GlyphRasterizationParams>> {
&self.glyph_atlas
}
+57 -32
View File
@@ -1,6 +1,6 @@
use crate::{
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,
};
use anyhow::anyhow;
@@ -134,9 +134,16 @@ impl PlatformTextSystem for MacTextSystem {
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(
&self,
glyph_id: &RasterizeGlyphParams,
glyph_id: &GlyphRasterizationParams,
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
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(
&self,
glyph_id: &RasterizeGlyphParams,
params: &GlyphRasterizationParams,
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
let font = &self.fonts[glyph_id.font_id.0];
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,
)?;
let glyph_bounds = self.raster_bounds(params)?;
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"))
} else {
// Make room for subpixel variants.
let subpixel_padding = Vector2I::new(
glyph_id.subpixel_variant.x.min(1) as i32,
glyph_id.subpixel_variant.y.min(1) as i32,
);
let bitmap_size = glyph_bounds.size() + subpixel_padding;
// Add an extra pixel when the subpixel variant isn't zero to make room for anti-aliasing.
let mut bitmap_size = glyph_bounds.size;
if params.subpixel_variant.x > 0 {
bitmap_size.width += DevicePixels(1);
}
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(
Some(bytes.as_mut_ptr() as *mut _),
bitmap_size.x() as usize,
bitmap_size.y() as usize,
bitmap_size.width.0 as usize,
bitmap_size.height.0 as usize,
8,
bitmap_size.x() as usize,
bitmap_size.width.0 as usize,
&CGColorSpace::create_device_gray(),
kCGImageAlphaOnly,
);
@@ -268,26 +292,27 @@ impl MacTextSystemState {
// Move the origin to bottom left and account for scaling, this
// makes drawing text consistent with the font-kit's raster_bounds.
cx.translate(
-glyph_bounds.origin_x() as CGFloat,
(glyph_bounds.origin_y() + glyph_bounds.height()) as CGFloat,
-glyph_bounds.origin.x.0 as CGFloat,
(glyph_bounds.origin.y.0 + glyph_bounds.size.height.0) as CGFloat,
);
cx.scale(
glyph_id.scale_factor as CGFloat,
glyph_id.scale_factor as CGFloat,
params.scale_factor as CGFloat,
params.scale_factor as CGFloat,
);
let subpixel_shift = glyph_id
let subpixel_shift = params
.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_should_subpixel_position_fonts(true);
cx.set_allows_font_subpixel_quantization(false);
cx.set_should_subpixel_quantize_fonts(false);
font.native_font()
.clone_with_font_size(f32::from(glyph_id.font_size) as CGFloat)
self.fonts[params.font_id.0]
.native_font()
.clone_with_font_size(f32::from(params.font_size) as CGFloat)
.draw_glyphs(
&[u32::from(glyph_id.glyph_id) as CGGlyph],
&[u32::from(params.glyph_id) as CGGlyph],
&[CGPoint::new(
subpixel_shift.x as CGFloat,
subpixel_shift.y as CGFloat,
+6 -6
View File
@@ -1,10 +1,10 @@
use super::{ns_string, MetalRenderer, NSRange};
use crate::{
point, px, size, AnyWindowHandle, Bounds, Event, KeyDownEvent, Keystroke, MacScreen, Modifiers,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
PlatformWindow, Point, RasterizeGlyphParams, Scene, Size, Timer, WindowAppearance,
WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
point, px, size, AnyWindowHandle, Bounds, Event, GlyphRasterizationParams, KeyDownEvent,
Keystroke, MacScreen, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent,
MouseMovedEvent, MouseUpEvent, NSRectExt, Pixels, Platform, PlatformAtlas, PlatformDispatcher,
PlatformInputHandler, PlatformScreen, PlatformWindow, Point, Scene, Size, Timer,
WindowAppearance, WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
};
use block::ConcreteBlock;
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()
}
}