mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
small fixes
* make SimpleText::add_run accept glyph_transform and style parameters so it doesn't unconditionally do oblique strokes * replace fill/stroke methods on DrawGlyphs with a single draw method that accepts either fill or stroke styles * update peniko rev to access the new style types used above * for now, change glyph cache to only cache non-zero fills. Prior to this, style was ignored in the key which could lead to incorrect rendering.
This commit is contained in:
parent
39e35ceba9
commit
82391534c0
|
@ -45,7 +45,7 @@ parking_lot = "0.12"
|
|||
bytemuck = { version = "1.12.1", features = ["derive"] }
|
||||
smallvec = "1.8.0"
|
||||
moscato = { git = "https://github.com/dfrg/pinot", rev = "59db153" }
|
||||
peniko = { git = "https://github.com/linebender/peniko", rev = "8cb710f" }
|
||||
peniko = { git = "https://github.com/linebender/peniko", rev = "882882c" }
|
||||
|
||||
[workspace.dependencies]
|
||||
wgpu = "0.15"
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use vello::{
|
||||
encoding::{Glyph, Transform},
|
||||
encoding::Glyph,
|
||||
glyph::{
|
||||
pinot,
|
||||
pinot::{FontRef, TableProvider},
|
||||
GlyphContext,
|
||||
},
|
||||
kurbo::Affine,
|
||||
peniko::{Blob, Brush, BrushRef, Color, Fill, Font, Stroke},
|
||||
peniko::{Blob, Brush, BrushRef, Font, StyleRef},
|
||||
SceneBuilder,
|
||||
};
|
||||
|
||||
|
@ -45,12 +45,14 @@ impl SimpleText {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_run<'b>(
|
||||
pub fn add_run<'a>(
|
||||
&mut self,
|
||||
builder: &mut SceneBuilder,
|
||||
size: f32,
|
||||
brush: impl Into<BrushRef<'b>>,
|
||||
brush: impl Into<BrushRef<'a>>,
|
||||
transform: Affine,
|
||||
glyph_transform: Option<Affine>,
|
||||
style: impl Into<StyleRef<'a>>,
|
||||
text: &str,
|
||||
) {
|
||||
let font = FontRef {
|
||||
|
@ -58,6 +60,7 @@ impl SimpleText {
|
|||
offset: 0,
|
||||
};
|
||||
let brush = brush.into();
|
||||
let style = style.into();
|
||||
if let Some(cmap) = font.cmap() {
|
||||
if let Some(hmtx) = font.hmtx() {
|
||||
let upem = font.head().map(|head| head.units_per_em()).unwrap_or(1000) as f64;
|
||||
|
@ -69,22 +72,13 @@ impl SimpleText {
|
|||
.unwrap_or(0);
|
||||
let mut pen_x = 0f64;
|
||||
builder
|
||||
.draw_glyphs(&self)
|
||||
.draw_glyphs(&self.font)
|
||||
.font_size(size)
|
||||
.transform(transform)
|
||||
.glyph_transform(Some(Affine::new([
|
||||
1.,
|
||||
0.,
|
||||
20f64.to_radians().tan(),
|
||||
1.,
|
||||
0.,
|
||||
0.,
|
||||
])))
|
||||
.glyph_transform(glyph_transform)
|
||||
.brush(brush)
|
||||
.stroke(
|
||||
Stroke::new(1.),
|
||||
// .fill(
|
||||
// Fill::NonZero,
|
||||
.draw(
|
||||
style,
|
||||
text.chars().map(|ch| {
|
||||
let gid = cmap.map(ch as u32).unwrap_or(0);
|
||||
let advance = hmetrics
|
||||
|
|
|
@ -128,6 +128,9 @@ fn animated_text(sb: &mut SceneBuilder, params: &mut SceneParams) {
|
|||
text_size,
|
||||
Color::WHITE,
|
||||
Affine::translate((110.0, 700.0)),
|
||||
// Add a skew to simulate an oblique font.
|
||||
Some(Affine::new([1., 0., 20f64.to_radians().tan(), 1., 0., 0.])),
|
||||
&Stroke::new(1.0),
|
||||
s,
|
||||
);
|
||||
let th = params.time as f64;
|
||||
|
|
|
@ -28,7 +28,7 @@ mod resolve;
|
|||
|
||||
pub use draw::{
|
||||
DrawBeginClip, DrawColor, DrawImage, DrawLinearGradient, DrawMonoid, DrawRadialGradient,
|
||||
DrawStyle, DrawTag,
|
||||
DrawTag,
|
||||
};
|
||||
pub use encoding::{Encoding, StreamOffsets};
|
||||
pub use glyph::{Glyph, GlyphRun};
|
||||
|
|
|
@ -19,13 +19,6 @@ use peniko::{BlendMode, Color, Fill, Stroke};
|
|||
|
||||
use super::Monoid;
|
||||
|
||||
/// Fill or stroke style.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DrawStyle {
|
||||
Fill(Fill),
|
||||
Stroke(Stroke),
|
||||
}
|
||||
|
||||
/// Draw tag representation.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
use std::ops::Range;
|
||||
|
||||
use peniko::Font;
|
||||
use peniko::{Font, Style};
|
||||
|
||||
use super::{DrawStyle, StreamOffsets, Transform};
|
||||
use super::{StreamOffsets, Transform};
|
||||
|
||||
/// Positioned glyph.
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
|
@ -47,7 +47,7 @@ pub struct GlyphRun {
|
|||
/// Range of normalized coordinates in the parent encoding.
|
||||
pub normalized_coords: Range<usize>,
|
||||
/// Fill or stroke style.
|
||||
pub style: DrawStyle,
|
||||
pub style: Style,
|
||||
/// Range of glyphs in the parent encoding.
|
||||
pub glyphs: Range<usize>,
|
||||
/// Stream offsets where this glyph run should be inserted.
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{DrawStyle, Encoding, StreamOffsets};
|
||||
use super::{Encoding, StreamOffsets};
|
||||
use crate::glyph::GlyphProvider;
|
||||
|
||||
use peniko::{Fill, Style};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)]
|
||||
pub struct GlyphKey {
|
||||
pub font_id: u64,
|
||||
|
@ -43,17 +45,24 @@ impl GlyphCache {
|
|||
pub fn get_or_insert(
|
||||
&mut self,
|
||||
key: GlyphKey,
|
||||
style: &DrawStyle,
|
||||
style: &Style,
|
||||
scaler: &mut GlyphProvider,
|
||||
) -> Option<CachedRange> {
|
||||
if let Some(range) = self.glyphs.get(&key) {
|
||||
return Some(*range);
|
||||
// For now, only cache non-zero filled glyphs so we don't need to keep style
|
||||
// as part of the key.
|
||||
let is_nz_fill = matches!(style, Style::Fill(Fill::NonZero));
|
||||
if is_nz_fill {
|
||||
if let Some(range) = self.glyphs.get(&key) {
|
||||
return Some(*range);
|
||||
}
|
||||
}
|
||||
let start = self.encoding.stream_offsets();
|
||||
scaler.encode_glyph(key.glyph_id as u16, style, &mut self.encoding)?;
|
||||
let end = self.encoding.stream_offsets();
|
||||
let range = CachedRange { start, end };
|
||||
self.glyphs.insert(key, range);
|
||||
if is_nz_fill {
|
||||
self.glyphs.insert(key, range);
|
||||
}
|
||||
Some(range)
|
||||
}
|
||||
}
|
||||
|
|
19
src/glyph.rs
19
src/glyph.rs
|
@ -18,10 +18,10 @@
|
|||
|
||||
pub use moscato::pinot;
|
||||
|
||||
use crate::encoding::{DrawStyle, Encoding};
|
||||
use crate::encoding::Encoding;
|
||||
use crate::scene::{SceneBuilder, SceneFragment};
|
||||
use peniko::kurbo::{Affine, Rect};
|
||||
use peniko::{Brush, Color, Fill, Mix};
|
||||
use peniko::{Brush, Color, Fill, Mix, Style};
|
||||
|
||||
use moscato::{Context, Scaler};
|
||||
use pinot::{types::Tag, FontRef};
|
||||
|
@ -104,20 +104,15 @@ impl<'a> GlyphProvider<'a> {
|
|||
Some(fragment)
|
||||
}
|
||||
|
||||
pub fn encode_glyph(
|
||||
&mut self,
|
||||
gid: u16,
|
||||
style: &DrawStyle,
|
||||
encoding: &mut Encoding,
|
||||
) -> Option<()> {
|
||||
pub fn encode_glyph(&mut self, gid: u16, style: &Style, encoding: &mut Encoding) -> Option<()> {
|
||||
let glyph = self.scaler.glyph(gid)?;
|
||||
let path = glyph.path(0)?;
|
||||
match style {
|
||||
DrawStyle::Fill(Fill::NonZero) => encoding.encode_linewidth(-1.0),
|
||||
DrawStyle::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
||||
DrawStyle::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
||||
Style::Fill(Fill::NonZero) => encoding.encode_linewidth(-1.0),
|
||||
Style::Fill(Fill::EvenOdd) => encoding.encode_linewidth(-2.0),
|
||||
Style::Stroke(stroke) => encoding.encode_linewidth(stroke.width),
|
||||
}
|
||||
let mut path_encoder = encoding.encode_path(matches!(style, DrawStyle::Fill(_)));
|
||||
let mut path_encoder = encoding.encode_path(matches!(style, Style::Fill(_)));
|
||||
for el in path.elements() {
|
||||
use moscato::Element::*;
|
||||
match el {
|
||||
|
|
25
src/scene.rs
25
src/scene.rs
|
@ -15,9 +15,9 @@
|
|||
// Also licensed under MIT license, at your choice.
|
||||
|
||||
use peniko::kurbo::{Affine, Rect, Shape};
|
||||
use peniko::{BlendMode, Brush, BrushRef, Color, Fill, Font, Stroke};
|
||||
use peniko::{BlendMode, BrushRef, Color, Fill, Font, Stroke, StyleRef};
|
||||
|
||||
use crate::encoding::{DrawStyle, Encoding, Glyph, GlyphRun, Patch, Transform};
|
||||
use crate::encoding::{Encoding, Glyph, GlyphRun, Patch, Transform};
|
||||
|
||||
/// Encoded definition of a scene and associated resources.
|
||||
#[derive(Default)]
|
||||
|
@ -206,7 +206,7 @@ impl<'a> DrawGlyphs<'a> {
|
|||
font_size: 16.0,
|
||||
hint: false,
|
||||
normalized_coords: coords_start..coords_start,
|
||||
style: DrawStyle::Fill(Fill::NonZero),
|
||||
style: Fill::NonZero.into(),
|
||||
glyphs: glyphs_start..glyphs_start,
|
||||
stream_offsets,
|
||||
},
|
||||
|
@ -276,19 +276,12 @@ impl<'a> DrawGlyphs<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Encodes a fill for the given sequence of glyphs and consumes the builder.
|
||||
pub fn fill(mut self, style: Fill, glyphs: impl Iterator<Item = Glyph>) {
|
||||
self.run.style = DrawStyle::Fill(style);
|
||||
self.finish(glyphs);
|
||||
}
|
||||
|
||||
/// Encodes a stroke for the given sequence of glyphs and consumes the builder.
|
||||
pub fn stroke(mut self, style: Stroke, glyphs: impl Iterator<Item = Glyph>) {
|
||||
self.run.style = DrawStyle::Stroke(style);
|
||||
self.finish(glyphs);
|
||||
}
|
||||
|
||||
fn finish(mut self, glyphs: impl Iterator<Item = Glyph>) {
|
||||
/// Encodes a fill or stroke for for the given sequence of glyphs and consumes
|
||||
/// the builder.
|
||||
///
|
||||
/// The `style` parameter accepts either `Fill` or `&Stroke` types.
|
||||
pub fn draw(mut self, style: impl Into<StyleRef<'a>>, glyphs: impl Iterator<Item = Glyph>) {
|
||||
self.run.style = style.into().to_owned();
|
||||
self.encoding.glyphs.extend(glyphs);
|
||||
self.run.glyphs.end = self.encoding.glyphs.len();
|
||||
if self.run.glyphs.is_empty() {
|
||||
|
|
Loading…
Reference in a new issue