Make text respect clip, blend mode, and opacity

This commit is contained in:
Patrick Walton 2020-04-03 15:37:59 -07:00
parent b38f75a38d
commit 9d5dd7fd6a
2 changed files with 54 additions and 3 deletions

View File

@ -42,11 +42,19 @@ impl CanvasRenderingContext2D {
pub fn fill_layout(&mut self, layout: &Layout, transform: Transform2F) { pub fn fill_layout(&mut self, layout: &Layout, transform: Transform2F) {
let paint_id = self.canvas.scene.push_paint(&self.current_state.fill_paint); let paint_id = self.canvas.scene.push_paint(&self.current_state.fill_paint);
let clip_path = self.current_state.clip_path;
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
let opacity = (self.current_state.global_alpha * 255.0) as u8;
drop(self.canvas.scene.push_layout(&layout, drop(self.canvas.scene.push_layout(&layout,
&TextStyle { size: self.current_state.font_size }, &TextStyle { size: self.current_state.font_size },
&(transform * self.current_state.transform), &(transform * self.current_state.transform),
TextRenderMode::Fill, TextRenderMode::Fill,
HintingOptions::None, HintingOptions::None,
clip_path,
blend_mode,
opacity,
paint_id)); paint_id));
} }
@ -57,6 +65,10 @@ impl CanvasRenderingContext2D {
render_mode: TextRenderMode) { render_mode: TextRenderMode) {
let layout = self.layout_text(string); let layout = self.layout_text(string);
let clip_path = self.current_state.clip_path;
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
let opacity = (self.current_state.global_alpha * 255.0) as u8;
match self.current_state.text_align { match self.current_state.text_align {
TextAlign::Left => {}, TextAlign::Left => {},
TextAlign::Right => position.set_x(position.x() - layout.width()), TextAlign::Right => position.set_x(position.x() - layout.width()),
@ -82,6 +94,9 @@ impl CanvasRenderingContext2D {
&transform, &transform,
render_mode, render_mode,
HintingOptions::None, HintingOptions::None,
clip_path,
blend_mode,
opacity,
paint_id)); paint_id));
} }

View File

@ -14,15 +14,17 @@ use font_kit::error::GlyphLoadingError;
use font_kit::hinting::HintingOptions; use font_kit::hinting::HintingOptions;
use font_kit::loader::Loader; use font_kit::loader::Loader;
use lyon_path::builder::{FlatPathBuilder, PathBuilder, Build}; use lyon_path::builder::{FlatPathBuilder, PathBuilder, Build};
use pathfinder_content::effects::BlendMode;
use pathfinder_content::outline::{Contour, Outline}; use pathfinder_content::outline::{Contour, Outline};
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::Vector2F; use pathfinder_geometry::vector::Vector2F;
use pathfinder_renderer::paint::PaintId; use pathfinder_renderer::paint::PaintId;
use pathfinder_renderer::scene::{DrawPath, Scene}; use pathfinder_renderer::scene::{ClipPathId, DrawPath, Scene};
use skribo::{FontCollection, Layout, TextStyle}; use skribo::{FontCollection, Layout, TextStyle};
use std::mem; use std::mem;
// FIXME(pcwalton): Too many parameters!
pub trait SceneExt { pub trait SceneExt {
// TODO(pcwalton): Support stroked glyphs. // TODO(pcwalton): Support stroked glyphs.
fn push_glyph<F>(&mut self, fn push_glyph<F>(&mut self,
@ -31,6 +33,9 @@ pub trait SceneExt {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError> -> Result<(), GlyphLoadingError>
where F: Loader; where F: Loader;
@ -41,6 +46,9 @@ pub trait SceneExt {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError>; -> Result<(), GlyphLoadingError>;
@ -51,6 +59,9 @@ pub trait SceneExt {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError>; -> Result<(), GlyphLoadingError>;
} }
@ -63,6 +74,9 @@ impl SceneExt for Scene {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError> -> Result<(), GlyphLoadingError>
where F: Loader { where F: Loader {
@ -76,7 +90,12 @@ impl SceneExt for Scene {
outline = stroke_to_fill.into_outline(); outline = stroke_to_fill.into_outline();
} }
self.push_path(DrawPath::new(outline, paint_id)); let mut path = DrawPath::new(outline, paint_id);
path.set_clip_path(clip_path);
path.set_blend_mode(blend_mode);
path.set_opacity(opacity);
self.push_path(path);
Ok(()) Ok(())
} }
@ -86,6 +105,9 @@ impl SceneExt for Scene {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError> { -> Result<(), GlyphLoadingError> {
for glyph in &layout.glyphs { for glyph in &layout.glyphs {
@ -100,6 +122,9 @@ impl SceneExt for Scene {
&transform, &transform,
render_mode, render_mode,
hinting_options, hinting_options,
clip_path,
blend_mode,
opacity,
paint_id)?; paint_id)?;
} }
Ok(()) Ok(())
@ -113,10 +138,21 @@ impl SceneExt for Scene {
transform: &Transform2F, transform: &Transform2F,
render_mode: TextRenderMode, render_mode: TextRenderMode,
hinting_options: HintingOptions, hinting_options: HintingOptions,
clip_path: Option<ClipPathId>,
blend_mode: BlendMode,
opacity: u8,
paint_id: PaintId) paint_id: PaintId)
-> Result<(), GlyphLoadingError> { -> Result<(), GlyphLoadingError> {
let layout = skribo::layout(style, collection, text); let layout = skribo::layout(style, collection, text);
self.push_layout(&layout, style, &transform, render_mode, hinting_options, paint_id) self.push_layout(&layout,
style,
&transform,
render_mode,
hinting_options,
clip_path,
blend_mode,
opacity,
paint_id)
} }
} }