mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
[vello_encoding] Move the encoding module into its own crate
This change moves the vello encoding logic to a new crate under crates/encoding. Combined with the `vello_shaders` crate, this enables lightweight integration of the Vello pipelines into renderers that don't depend on wgpu (or perhaps written in languages other than Rust). The Scene/Fragment API currently remain the vello crate.
This commit is contained in:
parent
b8e1bcfac3
commit
db2fefdc8f
12
Cargo.toml
12
Cargo.toml
|
@ -2,6 +2,7 @@
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
"crates/encoding",
|
||||||
"crates/shaders",
|
"crates/shaders",
|
||||||
|
|
||||||
"integrations/vello_svg",
|
"integrations/vello_svg",
|
||||||
|
@ -40,17 +41,20 @@ hot_reload = []
|
||||||
buffer_labels = []
|
buffer_labels = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bytemuck = { workspace = true }
|
||||||
|
fello = { workspace = true }
|
||||||
|
peniko = { workspace = true }
|
||||||
wgpu = { workspace = true }
|
wgpu = { workspace = true }
|
||||||
raw-window-handle = "0.5"
|
raw-window-handle = "0.5"
|
||||||
futures-intrusive = "0.5.0"
|
futures-intrusive = "0.5.0"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
bytemuck = { version = "1.12.1", features = ["derive"] }
|
|
||||||
smallvec = "1.8.0"
|
smallvec = "1.8.0"
|
||||||
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
|
vello_encoding = { path = "crates/encoding" }
|
||||||
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
|
|
||||||
guillotiere = "0.6.2"
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
bytemuck = { version = "1.12.1", features = ["derive"] }
|
||||||
|
fello = { git = "https://github.com/dfrg/fount", rev = "58a284eaae67512fb61cf76177c5d33238d79cb1" }
|
||||||
|
peniko = { git = "https://github.com/linebender/peniko", rev = "cafdac9a211a0fb2fec5656bd663d1ac770bcc81" }
|
||||||
wgpu = "0.15"
|
wgpu = "0.15"
|
||||||
|
|
||||||
# Used for examples
|
# Used for examples
|
||||||
|
|
10
crates/encoding/Cargo.toml
Normal file
10
crates/encoding/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "vello_encoding"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytemuck = { workspace = true }
|
||||||
|
fello = { workspace = true }
|
||||||
|
peniko = { workspace = true }
|
||||||
|
guillotiere = "0.6.2"
|
|
@ -14,11 +14,9 @@
|
||||||
//
|
//
|
||||||
// Also licensed under MIT license, at your choice.
|
// Also licensed under MIT license, at your choice.
|
||||||
|
|
||||||
use crate::encoding::DrawImage;
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
resolve::Patch, DrawColor, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph, GlyphRun,
|
resolve::Patch, DrawColor, DrawImage, DrawLinearGradient, DrawRadialGradient, DrawTag, Glyph,
|
||||||
PathEncoder, PathTag, Transform,
|
GlyphRun, PathEncoder, PathTag, Transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
use fello::NormalizedCoord;
|
use fello::NormalizedCoord;
|
|
@ -59,11 +59,11 @@ impl GlyphCache {
|
||||||
Style::Fill(Fill::EvenOdd) => encoding_cache.encode_linewidth(-2.0),
|
Style::Fill(Fill::EvenOdd) => encoding_cache.encode_linewidth(-2.0),
|
||||||
Style::Stroke(stroke) => encoding_cache.encode_linewidth(stroke.width),
|
Style::Stroke(stroke) => encoding_cache.encode_linewidth(stroke.width),
|
||||||
}
|
}
|
||||||
let mut path = crate::glyph::PathEncoderPen(encoding_cache.encode_path(is_fill));
|
let mut path = encoding_cache.encode_path(is_fill);
|
||||||
scaler
|
scaler
|
||||||
.outline(GlyphId::new(key.glyph_id as u16), &mut path)
|
.outline(GlyphId::new(key.glyph_id as u16), &mut path)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
if path.0.finish(false) == 0 {
|
if path.finish(false) == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let end = encoding_cache.stream_offsets();
|
let end = encoding_cache.stream_offsets();
|
|
@ -381,3 +381,25 @@ impl<'a> PathEncoder<'a> {
|
||||||
self.n_encoded_segments
|
self.n_encoded_segments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fello::scale::Pen for PathEncoder<'_> {
|
||||||
|
fn move_to(&mut self, x: f32, y: f32) {
|
||||||
|
self.move_to(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_to(&mut self, x: f32, y: f32) {
|
||||||
|
self.line_to(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
|
||||||
|
self.quad_to(cx0, cy0, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
|
||||||
|
self.cubic_to(cx0, cy0, cx1, cy1, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self) {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,6 @@ use super::{
|
||||||
ramp_cache::{RampCache, Ramps},
|
ramp_cache::{RampCache, Ramps},
|
||||||
DrawTag, Encoding, PathTag, StreamOffsets, Transform,
|
DrawTag, Encoding, PathTag, StreamOffsets, Transform,
|
||||||
};
|
};
|
||||||
use crate::shaders;
|
|
||||||
|
|
||||||
/// Layout of a packed encoding.
|
/// Layout of a packed encoding.
|
||||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||||
|
@ -161,6 +160,7 @@ impl Resolver {
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
encoding: &Encoding,
|
encoding: &Encoding,
|
||||||
packed: &mut Vec<u8>,
|
packed: &mut Vec<u8>,
|
||||||
|
workgroup_size: u32,
|
||||||
) -> (Layout, Ramps<'a>, Images<'a>) {
|
) -> (Layout, Ramps<'a>, Images<'a>) {
|
||||||
let sizes = self.resolve_patches(encoding);
|
let sizes = self.resolve_patches(encoding);
|
||||||
self.resolve_pending_images();
|
self.resolve_pending_images();
|
||||||
|
@ -172,7 +172,7 @@ impl Resolver {
|
||||||
// Compute size of data buffer
|
// Compute size of data buffer
|
||||||
let n_path_tags =
|
let n_path_tags =
|
||||||
encoding.path_tags.len() + sizes.path_tags + encoding.n_open_clips as usize;
|
encoding.path_tags.len() + sizes.path_tags + encoding.n_open_clips as usize;
|
||||||
let path_tag_padded = align_up(n_path_tags, 4 * shaders::PATHTAG_REDUCE_WG);
|
let path_tag_padded = align_up(n_path_tags, 4 * workgroup_size);
|
||||||
let capacity = path_tag_padded
|
let capacity = path_tag_padded
|
||||||
+ slice_size_in_bytes(&encoding.path_data, sizes.path_data)
|
+ slice_size_in_bytes(&encoding.path_data, sizes.path_data)
|
||||||
+ slice_size_in_bytes(
|
+ slice_size_in_bytes(
|
|
@ -12,6 +12,7 @@ repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vello = { path = "../../" }
|
vello = { path = "../../" }
|
||||||
|
vello_encoding = { path = "../../crates/encoding" }
|
||||||
vello_svg = { path = "../../integrations/vello_svg" }
|
vello_svg = { path = "../../integrations/vello_svg" }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
clap = { workspace = true, features = ["derive"] }
|
clap = { workspace = true, features = ["derive"] }
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use vello::{
|
use vello::{
|
||||||
encoding::Glyph,
|
|
||||||
fello::meta::MetadataProvider,
|
fello::meta::MetadataProvider,
|
||||||
fello::raw::FontRef,
|
fello::raw::FontRef,
|
||||||
glyph::GlyphContext,
|
glyph::GlyphContext,
|
||||||
|
@ -25,6 +24,7 @@ use vello::{
|
||||||
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
|
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
|
||||||
SceneBuilder,
|
SceneBuilder,
|
||||||
};
|
};
|
||||||
|
use vello_encoding::Glyph;
|
||||||
|
|
||||||
// This is very much a hack to get things working.
|
// This is very much a hack to get things working.
|
||||||
// On Windows, can set this to "c:\\Windows\\Fonts\\seguiemj.ttf" to get color emoji
|
// On Windows, can set this to "c:\\Windows\\Fonts\\seguiemj.ttf" to get color emoji
|
||||||
|
|
43
src/glyph.rs
43
src/glyph.rs
|
@ -16,18 +16,17 @@
|
||||||
|
|
||||||
//! Support for glyph rendering.
|
//! Support for glyph rendering.
|
||||||
|
|
||||||
use fello::scale::Pen;
|
|
||||||
|
|
||||||
use crate::encoding::{Encoding, PathEncoder};
|
|
||||||
use crate::scene::{SceneBuilder, SceneFragment};
|
use crate::scene::{SceneBuilder, SceneFragment};
|
||||||
use peniko::kurbo::Affine;
|
use {
|
||||||
use peniko::{Brush, Color, Fill, Style};
|
fello::{
|
||||||
|
|
||||||
use fello::{
|
|
||||||
raw::types::GlyphId,
|
raw::types::GlyphId,
|
||||||
raw::FontRef,
|
raw::FontRef,
|
||||||
scale::{Context, Scaler},
|
scale::{Context, Pen, Scaler},
|
||||||
FontKey, Setting, Size,
|
FontKey, Setting, Size,
|
||||||
|
},
|
||||||
|
peniko::kurbo::Affine,
|
||||||
|
peniko::{Brush, Color, Fill, Style},
|
||||||
|
vello_encoding::Encoding,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// General context for creating scene fragments for glyph outlines.
|
/// General context for creating scene fragments for glyph outlines.
|
||||||
|
@ -105,9 +104,9 @@ impl<'a> GlyphProvider<'a> {
|
||||||
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
||||||
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
||||||
}
|
}
|
||||||
let mut path = PathEncoderPen(encoding.encode_path(matches!(style, Style::Fill(_))));
|
let mut path = encoding.encode_path(matches!(style, Style::Fill(_)));
|
||||||
self.scaler.outline(GlyphId::new(gid), &mut path).ok()?;
|
self.scaler.outline(GlyphId::new(gid), &mut path).ok()?;
|
||||||
if path.0.finish(false) != 0 {
|
if path.finish(false) != 0 {
|
||||||
Some(())
|
Some(())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -144,27 +143,3 @@ impl Pen for BezPathPen {
|
||||||
self.0.close_path()
|
self.0.close_path()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct PathEncoderPen<'a>(pub PathEncoder<'a>);
|
|
||||||
|
|
||||||
impl Pen for PathEncoderPen<'_> {
|
|
||||||
fn move_to(&mut self, x: f32, y: f32) {
|
|
||||||
self.0.move_to(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn line_to(&mut self, x: f32, y: f32) {
|
|
||||||
self.0.line_to(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
|
|
||||||
self.0.quad_to(cx0, cy0, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
|
|
||||||
self.0.cubic_to(cx0, cy0, cx1, cy1, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(&mut self) {
|
|
||||||
self.0.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
//! Take an encoded scene and create a graph to render it
|
//! Take an encoded scene and create a graph to render it
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
encoding::{Config, Encoding, Layout},
|
|
||||||
engine::{BufProxy, ImageFormat, ImageProxy, Recording, ResourceProxy},
|
engine::{BufProxy, ImageFormat, ImageProxy, Recording, ResourceProxy},
|
||||||
shaders::{self, FullShaders, Shaders},
|
shaders::{self, FullShaders, Shaders},
|
||||||
RenderParams, Scene,
|
RenderParams, Scene,
|
||||||
};
|
};
|
||||||
|
use {
|
||||||
|
bytemuck::{Pod, Zeroable},
|
||||||
|
vello_encoding::{Config, Encoding, Layout},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// State for a render in progress.
|
/// State for a render in progress.
|
||||||
pub struct Render {
|
pub struct Render {
|
||||||
|
@ -213,11 +215,11 @@ impl Render {
|
||||||
params: &RenderParams,
|
params: &RenderParams,
|
||||||
robust: bool,
|
robust: bool,
|
||||||
) -> Recording {
|
) -> Recording {
|
||||||
use crate::encoding::Resolver;
|
use vello_encoding::Resolver;
|
||||||
let mut recording = Recording::default();
|
let mut recording = Recording::default();
|
||||||
let mut resolver = Resolver::new();
|
let mut resolver = Resolver::new();
|
||||||
let mut packed = vec![];
|
let mut packed = vec![];
|
||||||
let (layout, ramps, images) = resolver.resolve(encoding, &mut packed);
|
let (layout, ramps, images) = resolver.resolve(encoding, &mut packed, shaders::PATHTAG_REDUCE_WG);
|
||||||
let gradient_image = if ramps.height == 0 {
|
let gradient_image = if ramps.height == 0 {
|
||||||
ResourceProxy::new_image(1, 1, ImageFormat::Rgba8)
|
ResourceProxy::new_image(1, 1, ImageFormat::Rgba8)
|
||||||
} else {
|
} else {
|
||||||
|
@ -245,7 +247,7 @@ impl Render {
|
||||||
let new_height = next_multiple_of(params.height, 16);
|
let new_height = next_multiple_of(params.height, 16);
|
||||||
|
|
||||||
let info_size = layout.bin_data_start;
|
let info_size = layout.bin_data_start;
|
||||||
let config = crate::encoding::Config {
|
let config = vello_encoding::Config {
|
||||||
width_in_tiles: new_width / 16,
|
width_in_tiles: new_width / 16,
|
||||||
height_in_tiles: new_height / 16,
|
height_in_tiles: new_height / 16,
|
||||||
target_width: params.width,
|
target_width: params.width,
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
use fello::NormalizedCoord;
|
use fello::NormalizedCoord;
|
||||||
use peniko::kurbo::{Affine, Rect, Shape};
|
use peniko::kurbo::{Affine, Rect, Shape};
|
||||||
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, Stroke, StyleRef};
|
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Image, Stroke, StyleRef};
|
||||||
|
use vello_encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
|
||||||
use crate::encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
|
|
||||||
|
|
||||||
/// Encoded definition of a scene and associated resources.
|
/// Encoded definition of a scene and associated resources.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
Loading…
Reference in a new issue