Remove `draw_render_target()` in favor of the standard tile-based rendering
path
This commit is contained in:
parent
cd37791d72
commit
eb2b622615
|
@ -12,18 +12,18 @@
|
||||||
|
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_content::dash::OutlineDash;
|
use pathfinder_content::dash::OutlineDash;
|
||||||
use pathfinder_content::effects::{BlendMode, BlurDirection, Effects, Filter};
|
use pathfinder_content::effects::{BlendMode, BlurDirection, PatternFilter};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::gradient::Gradient;
|
use pathfinder_content::gradient::Gradient;
|
||||||
use pathfinder_content::outline::{ArcDirection, Contour, Outline};
|
use pathfinder_content::outline::{ArcDirection, Contour, Outline};
|
||||||
use pathfinder_content::pattern::{Pattern, PatternFlags, PatternSource};
|
use pathfinder_content::pattern::Pattern;
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin};
|
use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin};
|
||||||
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
|
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::transform2d::Transform2F;
|
use pathfinder_geometry::transform2d::Transform2F;
|
||||||
use pathfinder_geometry::vector::{IntoVector2F, Vector2F, vec2f};
|
use pathfinder_geometry::vector::{IntoVector2F, Vector2F, Vector2I, vec2f, vec2i};
|
||||||
use pathfinder_renderer::paint::{Paint, PaintId};
|
use pathfinder_renderer::paint::{Paint, PaintId};
|
||||||
use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, RenderTarget, Scene};
|
use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, RenderTarget, Scene};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -101,6 +101,11 @@ impl Canvas {
|
||||||
font_context,
|
font_context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn size(&self) -> Vector2I {
|
||||||
|
self.scene.view_box().size().ceil().to_i32()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CanvasRenderingContext2D {
|
pub struct CanvasRenderingContext2D {
|
||||||
|
@ -340,7 +345,7 @@ impl CanvasRenderingContext2D {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_target_size = self.canvas.scene.view_box().size().ceil().to_i32();
|
let render_target_size = self.canvas.size();
|
||||||
let render_target_a = RenderTarget::new(render_target_size, String::new());
|
let render_target_a = RenderTarget::new(render_target_size, String::new());
|
||||||
let render_target_id_a = self.canvas.scene.push_render_target(render_target_a);
|
let render_target_id_a = self.canvas.scene.push_render_target(render_target_a);
|
||||||
let render_target_b = RenderTarget::new(render_target_size, String::new());
|
let render_target_b = RenderTarget::new(render_target_size, String::new());
|
||||||
|
@ -357,16 +362,24 @@ impl CanvasRenderingContext2D {
|
||||||
};
|
};
|
||||||
|
|
||||||
let sigma = self.current_state.shadow_blur * 0.5;
|
let sigma = self.current_state.shadow_blur * 0.5;
|
||||||
|
|
||||||
|
let mut paint_x = Pattern::from_render_target(render_target_ids[1], self.canvas.size());
|
||||||
|
let mut paint_y = Pattern::from_render_target(render_target_ids[0], self.canvas.size());
|
||||||
|
paint_x.set_filter(Some(PatternFilter::Blur { direction: BlurDirection::X, sigma }));
|
||||||
|
paint_y.set_filter(Some(PatternFilter::Blur { direction: BlurDirection::Y, sigma }));
|
||||||
|
|
||||||
|
let paint_id_x = self.canvas.scene.push_paint(&Paint::Pattern(paint_x));
|
||||||
|
let paint_id_y = self.canvas.scene.push_paint(&Paint::Pattern(paint_y));
|
||||||
|
|
||||||
|
// TODO(pcwalton): Apply clip as necessary.
|
||||||
|
let outline = Outline::from_rect(RectI::new(vec2i(0, 0), self.canvas.size()).to_f32());
|
||||||
|
let path_x = DrawPath::new(outline.clone(), paint_id_x);
|
||||||
|
let path_y = DrawPath::new(outline.clone(), paint_id_y);
|
||||||
|
|
||||||
self.canvas.scene.pop_render_target();
|
self.canvas.scene.pop_render_target();
|
||||||
self.canvas.scene.draw_render_target(render_target_ids[1], Effects::new(Filter::Blur {
|
self.canvas.scene.push_path(path_x);
|
||||||
direction: BlurDirection::X,
|
|
||||||
sigma,
|
|
||||||
}));
|
|
||||||
self.canvas.scene.pop_render_target();
|
self.canvas.scene.pop_render_target();
|
||||||
self.canvas.scene.draw_render_target(render_target_ids[0], Effects::new(Filter::Blur {
|
self.canvas.scene.push_path(path_y);
|
||||||
direction: BlurDirection::Y,
|
|
||||||
sigma,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transformations
|
// Transformations
|
||||||
|
@ -487,17 +500,16 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
pub fn create_pattern_from_canvas(&mut self, canvas: Canvas, transform: Transform2F)
|
pub fn create_pattern_from_canvas(&mut self, canvas: Canvas, transform: Transform2F)
|
||||||
-> Pattern {
|
-> Pattern {
|
||||||
|
let subscene_size = canvas.size();
|
||||||
let subscene = canvas.into_scene();
|
let subscene = canvas.into_scene();
|
||||||
let subscene_size = subscene.view_box().size().ceil().to_i32();
|
|
||||||
let render_target = RenderTarget::new(subscene_size, String::new());
|
let render_target = RenderTarget::new(subscene_size, String::new());
|
||||||
let render_target_id = self.canvas.scene.push_render_target(render_target);
|
let render_target_id = self.canvas.scene.push_render_target(render_target);
|
||||||
self.canvas.scene.append_scene(subscene);
|
self.canvas.scene.append_scene(subscene);
|
||||||
self.canvas.scene.pop_render_target();
|
self.canvas.scene.pop_render_target();
|
||||||
let pattern_source = PatternSource::RenderTarget {
|
|
||||||
id: render_target_id,
|
let mut pattern = Pattern::from_render_target(render_target_id, subscene_size);
|
||||||
size: subscene_size,
|
pattern.apply_transform(transform);
|
||||||
};
|
pattern
|
||||||
Pattern::new(pattern_source, transform, PatternFlags::empty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,8 +569,7 @@ impl State {
|
||||||
let mut must_copy = !self.transform.is_identity();
|
let mut must_copy = !self.transform.is_identity();
|
||||||
if !must_copy {
|
if !must_copy {
|
||||||
if let Paint::Pattern(ref pattern) = *paint {
|
if let Paint::Pattern(ref pattern) = *paint {
|
||||||
must_copy = !self.image_smoothing_enabled !=
|
must_copy = self.image_smoothing_enabled != pattern.smoothing_enabled()
|
||||||
pattern.flags.contains(PatternFlags::NO_SMOOTHING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +580,7 @@ impl State {
|
||||||
let mut paint = (*paint).clone();
|
let mut paint = (*paint).clone();
|
||||||
paint.apply_transform(&self.transform);
|
paint.apply_transform(&self.transform);
|
||||||
if let Paint::Pattern(ref mut pattern) = paint {
|
if let Paint::Pattern(ref mut pattern) = paint {
|
||||||
pattern.flags.set(PatternFlags::NO_SMOOTHING, !self.image_smoothing_enabled);
|
pattern.set_smoothing_enabled(self.image_smoothing_enabled);
|
||||||
}
|
}
|
||||||
Cow::Owned(paint)
|
Cow::Owned(paint)
|
||||||
}
|
}
|
||||||
|
@ -833,7 +844,7 @@ pub trait CanvasImageDestLocation {
|
||||||
impl CanvasImageSource for Pattern {
|
impl CanvasImageSource for Pattern {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_pattern(mut self, _: &mut CanvasRenderingContext2D, transform: Transform2F) -> Pattern {
|
fn to_pattern(mut self, _: &mut CanvasRenderingContext2D, transform: Transform2F) -> Pattern {
|
||||||
self.transform(transform);
|
self.apply_transform(transform);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,13 +31,6 @@ pub const MAX_STEM_DARKENING_AMOUNT: [f32; 2] = [0.3, 0.3];
|
||||||
/// This value is a subjective cutoff. Above this ppem value, no stem darkening is performed.
|
/// This value is a subjective cutoff. Above this ppem value, no stem darkening is performed.
|
||||||
pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;
|
pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;
|
||||||
|
|
||||||
/// Effects that can be applied to a layer.
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
|
||||||
pub struct Effects {
|
|
||||||
/// The shader that should be used when compositing this layer onto its destination.
|
|
||||||
pub filter: Filter,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The shader that should be used when compositing this layer onto its destination.
|
/// The shader that should be used when compositing this layer onto its destination.
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
pub enum Filter {
|
pub enum Filter {
|
||||||
|
@ -54,6 +47,12 @@ pub enum Filter {
|
||||||
uv_origin: Vector2F,
|
uv_origin: Vector2F,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
PatternFilter(PatternFilter),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shaders applicable to patterns.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
|
pub enum PatternFilter {
|
||||||
/// Performs postprocessing operations useful for monochrome text.
|
/// Performs postprocessing operations useful for monochrome text.
|
||||||
Text {
|
Text {
|
||||||
/// The foreground color of the text.
|
/// The foreground color of the text.
|
||||||
|
@ -136,13 +135,6 @@ impl Default for Filter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Effects {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(filter: Filter) -> Effects {
|
|
||||||
Effects { filter }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BlendMode {
|
impl BlendMode {
|
||||||
/// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend
|
/// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend
|
||||||
/// factor is zero when source alpha is one).
|
/// factor is zero when source alpha is one).
|
||||||
|
|
|
@ -110,6 +110,13 @@ impl Outline {
|
||||||
outline
|
outline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_rect(rect: RectF) -> Outline {
|
||||||
|
let mut outline = Outline::new();
|
||||||
|
outline.push_contour(Contour::from_rect(rect));
|
||||||
|
outline
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bounds(&self) -> RectF {
|
pub fn bounds(&self) -> RectF {
|
||||||
self.bounds
|
self.bounds
|
||||||
|
@ -266,6 +273,18 @@ impl Contour {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_rect(rect: RectF) -> Contour {
|
||||||
|
let mut contour = Contour::new();
|
||||||
|
contour.push_point(rect.origin(), PointFlags::empty(), false);
|
||||||
|
contour.push_point(rect.upper_right(), PointFlags::empty(), false);
|
||||||
|
contour.push_point(rect.lower_right(), PointFlags::empty(), false);
|
||||||
|
contour.push_point(rect.lower_left(), PointFlags::empty(), false);
|
||||||
|
contour.close();
|
||||||
|
contour.bounds = rect;
|
||||||
|
contour
|
||||||
|
}
|
||||||
|
|
||||||
// Replaces this contour with a new one, with arrays preallocated to match `self`.
|
// Replaces this contour with a new one, with arrays preallocated to match `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn take(&mut self) -> Contour {
|
pub(crate) fn take(&mut self) -> Contour {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
//! Raster image patterns.
|
//! Raster image patterns.
|
||||||
|
|
||||||
|
use crate::effects::PatternFilter;
|
||||||
use crate::render_target::RenderTargetId;
|
use crate::render_target::RenderTargetId;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use pathfinder_color::{self as color, ColorU};
|
use pathfinder_color::{self as color, ColorU};
|
||||||
|
@ -26,9 +27,10 @@ use image::RgbaImage;
|
||||||
/// A raster image pattern.
|
/// A raster image pattern.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub struct Pattern {
|
pub struct Pattern {
|
||||||
pub source: PatternSource,
|
source: PatternSource,
|
||||||
pub transform: Transform2F,
|
transform: Transform2F,
|
||||||
pub flags: PatternFlags,
|
filter: Option<PatternFilter>,
|
||||||
|
flags: PatternFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -61,13 +63,33 @@ bitflags! {
|
||||||
|
|
||||||
impl Pattern {
|
impl Pattern {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(source: PatternSource, transform: Transform2F, flags: PatternFlags) -> Pattern {
|
fn from_source(source: PatternSource) -> Pattern {
|
||||||
Pattern { source, transform, flags }
|
Pattern {
|
||||||
|
source,
|
||||||
|
transform: Transform2F::default(),
|
||||||
|
filter: None,
|
||||||
|
flags: PatternFlags::empty(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform(&mut self, transform: Transform2F) {
|
pub fn from_image(image: Image) -> Pattern {
|
||||||
self.transform *= transform
|
Pattern::from_source(PatternSource::Image(image))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_render_target(id: RenderTargetId, size: Vector2I) -> Pattern {
|
||||||
|
Pattern::from_source(PatternSource::RenderTarget { id, size })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn transform(&self) -> Transform2F {
|
||||||
|
self.transform
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn apply_transform(&mut self, transform: Transform2F) {
|
||||||
|
self.transform = transform * self.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -77,6 +99,56 @@ impl Pattern {
|
||||||
PatternSource::RenderTarget { size, .. } => size,
|
PatternSource::RenderTarget { size, .. } => size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn filter(&self) -> Option<PatternFilter> {
|
||||||
|
self.filter
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_filter(&mut self, filter: Option<PatternFilter>) {
|
||||||
|
self.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn repeat_x(&self) -> bool {
|
||||||
|
self.flags.contains(PatternFlags::REPEAT_X)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_repeat_x(&mut self, repeat_x: bool) {
|
||||||
|
self.flags.set(PatternFlags::REPEAT_X, repeat_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn repeat_y(&self) -> bool {
|
||||||
|
self.flags.contains(PatternFlags::REPEAT_Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_repeat_y(&mut self, repeat_y: bool) {
|
||||||
|
self.flags.set(PatternFlags::REPEAT_Y, repeat_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn smoothing_enabled(&self) -> bool {
|
||||||
|
!self.flags.contains(PatternFlags::NO_SMOOTHING)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_smoothing_enabled(&mut self, enable: bool) {
|
||||||
|
self.flags.set(PatternFlags::NO_SMOOTHING, !enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_opaque(&self) -> bool {
|
||||||
|
self.source.is_opaque()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn source(&self) -> &PatternSource {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
|
|
|
@ -22,10 +22,14 @@ use crate::device::{GroundProgram, GroundVertexArray};
|
||||||
use crate::ui::{DemoUIModel, DemoUIPresenter, ScreenshotInfo, ScreenshotType, UIAction};
|
use crate::ui::{DemoUIModel, DemoUIPresenter, ScreenshotInfo, ScreenshotType, UIAction};
|
||||||
use crate::window::{Event, Keycode, SVGPath, Window, WindowSize};
|
use crate::window::{Event, Keycode, SVGPath, Window, WindowSize};
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use pathfinder_content::effects::{DEFRINGING_KERNEL_CORE_GRAPHICS, Effects};
|
use pathfinder_content::effects::DEFRINGING_KERNEL_CORE_GRAPHICS;
|
||||||
use pathfinder_content::effects::{Filter, STEM_DARKENING_FACTORS};
|
use pathfinder_content::effects::PatternFilter;
|
||||||
|
use pathfinder_content::effects::STEM_DARKENING_FACTORS;
|
||||||
|
use pathfinder_content::outline::Outline;
|
||||||
|
use pathfinder_content::pattern::Pattern;
|
||||||
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_export::{Export, FileFormat};
|
use pathfinder_export::{Export, FileFormat};
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
use pathfinder_geometry::transform2d::Transform2F;
|
use pathfinder_geometry::transform2d::Transform2F;
|
||||||
use pathfinder_geometry::transform3d::Transform4F;
|
use pathfinder_geometry::transform3d::Transform4F;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, Vector4F, vec2f, vec2i};
|
||||||
|
@ -34,7 +38,8 @@ use pathfinder_renderer::concurrent::scene_proxy::{RenderCommandStream, ScenePro
|
||||||
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
|
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
|
||||||
use pathfinder_renderer::gpu::renderer::{RenderStats, RenderTime, Renderer};
|
use pathfinder_renderer::gpu::renderer::{RenderStats, RenderTime, Renderer};
|
||||||
use pathfinder_renderer::options::{BuildOptions, RenderTransform};
|
use pathfinder_renderer::options::{BuildOptions, RenderTransform};
|
||||||
use pathfinder_renderer::scene::{RenderTarget, Scene};
|
use pathfinder_renderer::paint::Paint;
|
||||||
|
use pathfinder_renderer::scene::{DrawPath, RenderTarget, Scene};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_svg::BuiltSVG;
|
use pathfinder_svg::BuiltSVG;
|
||||||
use pathfinder_ui::{MousePosition, UIEvent};
|
use pathfinder_ui::{MousePosition, UIEvent};
|
||||||
|
@ -136,13 +141,13 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
let mut ui_model = DemoUIModel::new(&options);
|
let mut ui_model = DemoUIModel::new(&options);
|
||||||
let render_options = RendererOptions { background_color: None };
|
let render_options = RendererOptions { background_color: None };
|
||||||
|
|
||||||
let effects = build_effects(&ui_model);
|
let filter = build_filter(&ui_model);
|
||||||
|
|
||||||
let viewport = window.viewport(options.mode.view(0));
|
let viewport = window.viewport(options.mode.view(0));
|
||||||
let (mut built_svg, svg_tree) = load_scene(resources,
|
let (mut built_svg, svg_tree) = load_scene(resources,
|
||||||
&options.input_path,
|
&options.input_path,
|
||||||
viewport.size(),
|
viewport.size(),
|
||||||
effects);
|
filter);
|
||||||
|
|
||||||
let message = get_svg_building_message(&built_svg);
|
let message = get_svg_building_message(&built_svg);
|
||||||
|
|
||||||
|
@ -420,11 +425,11 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
|
|
||||||
Event::OpenSVG(ref svg_path) => {
|
Event::OpenSVG(ref svg_path) => {
|
||||||
let viewport = self.window.viewport(self.ui_model.mode.view(0));
|
let viewport = self.window.viewport(self.ui_model.mode.view(0));
|
||||||
let effects = build_effects(&self.ui_model);
|
let filter = build_filter(&self.ui_model);
|
||||||
let (mut built_svg, svg_tree) = load_scene(self.window.resource_loader(),
|
let (mut built_svg, svg_tree) = load_scene(self.window.resource_loader(),
|
||||||
svg_path,
|
svg_path,
|
||||||
viewport.size(),
|
viewport.size(),
|
||||||
effects);
|
filter);
|
||||||
|
|
||||||
self.ui_model.message = get_svg_building_message(&built_svg);
|
self.ui_model.message = get_svg_building_message(&built_svg);
|
||||||
|
|
||||||
|
@ -578,8 +583,8 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
UIAction::ModelChanged => self.dirty = true,
|
UIAction::ModelChanged => self.dirty = true,
|
||||||
UIAction::EffectsChanged => {
|
UIAction::EffectsChanged => {
|
||||||
let viewport_size = self.window.viewport(self.ui_model.mode.view(0)).size();
|
let viewport_size = self.window.viewport(self.ui_model.mode.view(0)).size();
|
||||||
let effects = build_effects(&self.ui_model);
|
let filter = build_filter(&self.ui_model);
|
||||||
let mut built_svg = build_svg_tree(&self.svg_tree, viewport_size, effects);
|
let mut built_svg = build_svg_tree(&self.svg_tree, viewport_size, filter);
|
||||||
self.scene_metadata =
|
self.scene_metadata =
|
||||||
SceneMetadata::new_clipping_view_box(&mut built_svg.scene, viewport_size);
|
SceneMetadata::new_clipping_view_box(&mut built_svg.scene, viewport_size);
|
||||||
self.scene_proxy.replace_scene(built_svg.scene);
|
self.scene_proxy.replace_scene(built_svg.scene);
|
||||||
|
@ -737,7 +742,7 @@ pub enum UIVisibility {
|
||||||
fn load_scene(resource_loader: &dyn ResourceLoader,
|
fn load_scene(resource_loader: &dyn ResourceLoader,
|
||||||
input_path: &SVGPath,
|
input_path: &SVGPath,
|
||||||
viewport_size: Vector2I,
|
viewport_size: Vector2I,
|
||||||
effects: Option<Effects>)
|
filter: Option<PatternFilter>)
|
||||||
-> (BuiltSVG, Tree) {
|
-> (BuiltSVG, Tree) {
|
||||||
let mut data;
|
let mut data;
|
||||||
match *input_path {
|
match *input_path {
|
||||||
|
@ -750,33 +755,47 @@ fn load_scene(resource_loader: &dyn ResourceLoader,
|
||||||
};
|
};
|
||||||
|
|
||||||
let tree = Tree::from_data(&data, &UsvgOptions::default()).expect("Failed to parse the SVG!");
|
let tree = Tree::from_data(&data, &UsvgOptions::default()).expect("Failed to parse the SVG!");
|
||||||
let built_svg = build_svg_tree(&tree, viewport_size, effects);
|
let built_svg = build_svg_tree(&tree, viewport_size, filter);
|
||||||
(built_svg, tree)
|
(built_svg, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, effects: Option<Effects>) -> BuiltSVG {
|
// FIXME(pcwalton): Rework how transforms work in the demo. The transform affects the final
|
||||||
|
// composite steps, breaking this approach.
|
||||||
|
fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, filter: Option<PatternFilter>)
|
||||||
|
-> BuiltSVG {
|
||||||
let mut scene = Scene::new();
|
let mut scene = Scene::new();
|
||||||
|
let filter_info = filter.map(|filter| {
|
||||||
let render_target_id = match effects {
|
let scale = match filter {
|
||||||
None => None,
|
PatternFilter::Text { defringing_kernel: Some(_), .. } => vec2i(3, 1),
|
||||||
Some(effects) => {
|
_ => vec2i(1, 1),
|
||||||
let scale = match effects.filter {
|
};
|
||||||
Filter::Text { defringing_kernel: Some(_), .. } => vec2i(3, 1),
|
let name = "Text".to_owned();
|
||||||
_ => vec2i(1, 1),
|
let render_target_size = viewport_size * scale;
|
||||||
};
|
let render_target = RenderTarget::new(render_target_size, name);
|
||||||
let name = "Text".to_owned();
|
let render_target_id = scene.push_render_target(render_target);
|
||||||
let render_target = RenderTarget::new(viewport_size * scale, name);
|
FilterInfo { filter, render_target_id, render_target_size }
|
||||||
Some(scene.push_render_target(render_target))
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut built_svg = BuiltSVG::from_tree_and_scene(&tree, scene);
|
let mut built_svg = BuiltSVG::from_tree_and_scene(&tree, scene);
|
||||||
|
if let Some(FilterInfo { filter, render_target_id, render_target_size }) = filter_info {
|
||||||
|
let mut paint = Pattern::from_render_target(render_target_id, render_target_size);
|
||||||
|
paint.set_filter(Some(filter));
|
||||||
|
let paint_id = built_svg.scene.push_paint(&Paint::Pattern(paint));
|
||||||
|
|
||||||
|
let outline = Outline::from_rect(RectI::new(vec2i(0, 0), viewport_size).to_f32());
|
||||||
|
let path = DrawPath::new(outline, paint_id);
|
||||||
|
|
||||||
if let (Some(render_target_id), Some(effects)) = (render_target_id, effects) {
|
|
||||||
built_svg.scene.pop_render_target();
|
built_svg.scene.pop_render_target();
|
||||||
built_svg.scene.draw_render_target(render_target_id, effects);
|
built_svg.scene.push_path(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return built_svg;
|
||||||
|
|
||||||
|
struct FilterInfo {
|
||||||
|
filter: PatternFilter,
|
||||||
|
render_target_id: RenderTargetId,
|
||||||
|
render_target_size: Vector2I,
|
||||||
}
|
}
|
||||||
built_svg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn center_of_window(window_size: &WindowSize) -> Vector2F {
|
fn center_of_window(window_size: &WindowSize) -> Vector2F {
|
||||||
|
@ -863,22 +882,20 @@ impl SceneMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_effects(ui_model: &DemoUIModel) -> Option<Effects> {
|
fn build_filter(ui_model: &DemoUIModel) -> Option<PatternFilter> {
|
||||||
if !ui_model.gamma_correction_effect_enabled && !ui_model.subpixel_aa_effect_enabled {
|
if !ui_model.gamma_correction_effect_enabled && !ui_model.subpixel_aa_effect_enabled {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Effects {
|
Some(PatternFilter::Text {
|
||||||
filter: Filter::Text {
|
fg_color: ui_model.foreground_color().to_f32(),
|
||||||
fg_color: ui_model.foreground_color().to_f32(),
|
bg_color: ui_model.background_color().to_f32(),
|
||||||
bg_color: ui_model.background_color().to_f32(),
|
gamma_correction: ui_model.gamma_correction_effect_enabled,
|
||||||
gamma_correction: ui_model.gamma_correction_effect_enabled,
|
defringing_kernel: if ui_model.subpixel_aa_effect_enabled {
|
||||||
defringing_kernel: if ui_model.subpixel_aa_effect_enabled {
|
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
||||||
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
} else {
|
||||||
} else {
|
None
|
||||||
None
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use pathfinder_color::{ColorF, ColorU, rgbau, rgbf, rgbu};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::gradient::Gradient;
|
use pathfinder_content::gradient::Gradient;
|
||||||
use pathfinder_content::outline::ArcDirection;
|
use pathfinder_content::outline::ArcDirection;
|
||||||
use pathfinder_content::pattern::{Image, Pattern, PatternFlags, PatternSource};
|
use pathfinder_content::pattern::{Image, Pattern};
|
||||||
use pathfinder_content::stroke::LineCap;
|
use pathfinder_content::stroke::LineCap;
|
||||||
use pathfinder_geometry::angle;
|
use pathfinder_geometry::angle;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
|
@ -537,21 +537,11 @@ fn draw_window(context: &mut CanvasRenderingContext2D, title: &str, rect: RectF)
|
||||||
|
|
||||||
// Draw window with shadow.
|
// Draw window with shadow.
|
||||||
context.set_fill_style(rgbau(28, 30, 34, 192));
|
context.set_fill_style(rgbau(28, 30, 34, 192));
|
||||||
|
context.set_shadow_blur(10.0);
|
||||||
|
context.set_shadow_offset(vec2f(0.0, 2.0));
|
||||||
|
context.set_shadow_color(rgbau(0, 0, 0, 128));
|
||||||
context.fill_path(create_rounded_rect_path(rect, CORNER_RADIUS), FillRule::Winding);
|
context.fill_path(create_rounded_rect_path(rect, CORNER_RADIUS), FillRule::Winding);
|
||||||
|
context.set_shadow_color(rgbau(0, 0, 0, 0));
|
||||||
// Draw window drop shadow.
|
|
||||||
let mut path =
|
|
||||||
create_rounded_rect_path(RectF::new(rect.origin() - 10.0, rect.size() + vec2f(20.0, 30.0)),
|
|
||||||
CORNER_RADIUS);
|
|
||||||
path.rect(rect);
|
|
||||||
fill_path_with_box_gradient(context,
|
|
||||||
path,
|
|
||||||
FillRule::EvenOdd,
|
|
||||||
rect + vec2f(0.0, 2.0),
|
|
||||||
CORNER_RADIUS * 2.0,
|
|
||||||
10.0,
|
|
||||||
rgbau(0, 0, 0, 128),
|
|
||||||
rgbau(0, 0, 0, 0));
|
|
||||||
|
|
||||||
// Header.
|
// Header.
|
||||||
let mut header_gradient =
|
let mut header_gradient =
|
||||||
|
@ -585,21 +575,22 @@ fn draw_window(context: &mut CanvasRenderingContext2D, title: &str, rect: RectF)
|
||||||
fn draw_search_box(context: &mut CanvasRenderingContext2D, text: &str, rect: RectF) {
|
fn draw_search_box(context: &mut CanvasRenderingContext2D, text: &str, rect: RectF) {
|
||||||
let corner_radius = rect.height() * 0.5 - 1.0;
|
let corner_radius = rect.height() * 0.5 - 1.0;
|
||||||
|
|
||||||
fill_path_with_box_gradient(context,
|
let path = create_rounded_rect_path(rect, corner_radius);
|
||||||
create_rounded_rect_path(rect, corner_radius),
|
context.save();
|
||||||
FillRule::Winding,
|
context.clip_path(path.clone(), FillRule::Winding);
|
||||||
rect + vec2f(0.0, 1.5),
|
context.set_shadow_offset(vec2f(0.0, 1.5));
|
||||||
rect.height() * 0.5,
|
context.set_shadow_blur(5.0);
|
||||||
5.0,
|
context.set_shadow_color(rgbau(0, 0, 0, 92));
|
||||||
rgbau(0, 0, 0, 16),
|
context.set_fill_style(rgbau(0, 0, 0, 16));
|
||||||
rgbau(0, 0, 0, 92));
|
context.fill_path(path, FillRule::Winding);
|
||||||
|
context.restore();
|
||||||
|
|
||||||
context.set_font_size(rect.height() * 0.5);
|
context.set_font_size(rect.height() * 0.5);
|
||||||
context.set_font(FONT_NAME_EMOJI);
|
context.set_font(FONT_NAME_EMOJI);
|
||||||
context.set_fill_style(rgbau(255, 255, 255, 64));
|
context.set_fill_style(rgbau(255, 255, 255, 64));
|
||||||
context.set_text_align(TextAlign::Center);
|
context.set_text_align(TextAlign::Center);
|
||||||
context.set_text_baseline(TextBaseline::Middle);
|
context.set_text_baseline(TextBaseline::Middle);
|
||||||
context.fill_text("🔍", rect.origin() + (rect.height() * 0.55));
|
context.fill_text("🔍", rect.origin() + Vector2F::splat(rect.height() * 0.55));
|
||||||
|
|
||||||
context.set_font(FONT_NAME_REGULAR);
|
context.set_font(FONT_NAME_REGULAR);
|
||||||
context.set_font_size(17.0);
|
context.set_font_size(17.0);
|
||||||
|
@ -908,9 +899,8 @@ fn draw_thumbnails(context: &mut CanvasRenderingContext2D,
|
||||||
(image_index % IMAGES_ACROSS) as i32,
|
(image_index % IMAGES_ACROSS) as i32,
|
||||||
(image_index / IMAGES_ACROSS) as i32).to_f32() * THUMB_HEIGHT) *
|
(image_index / IMAGES_ACROSS) as i32).to_f32() * THUMB_HEIGHT) *
|
||||||
Transform2F::from_scale(0.5);
|
Transform2F::from_scale(0.5);
|
||||||
let pattern = Pattern::new(PatternSource::Image((*image).clone()),
|
let mut pattern = Pattern::from_image((*image).clone());
|
||||||
pattern_transform,
|
pattern.apply_transform(pattern_transform);
|
||||||
PatternFlags::empty());
|
|
||||||
context.set_fill_style(pattern);
|
context.set_fill_style(pattern);
|
||||||
context.set_global_alpha(alpha);
|
context.set_global_alpha(alpha);
|
||||||
context.fill_path(image_path, FillRule::Winding);
|
context.fill_path(image_path, FillRule::Winding);
|
||||||
|
|
|
@ -15,13 +15,13 @@ use crate::gpu::renderer::{BlendModeExt, MASK_TILES_ACROSS, MASK_TILES_DOWN};
|
||||||
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TexturePageId, Tile, TileBatch};
|
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TexturePageId, Tile, TileBatch};
|
||||||
use crate::gpu_data::{TileBatchTexture, TileObjectPrimitive, TileVertex};
|
use crate::gpu_data::{TileBatchTexture, TileObjectPrimitive, TileVertex};
|
||||||
use crate::options::{PreparedBuildOptions, PreparedRenderTransform, RenderCommandListener};
|
use crate::options::{PreparedBuildOptions, PreparedRenderTransform, RenderCommandListener};
|
||||||
use crate::paint::{PaintInfo, PaintMetadata, RenderTargetMetadata};
|
use crate::paint::{PaintInfo, PaintMetadata};
|
||||||
use crate::scene::{DisplayItem, Scene};
|
use crate::scene::{DisplayItem, Scene};
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles::{self, DrawTilingPathInfo, PackedTile, TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{self, DrawTilingPathInfo, PackedTile, TILE_HEIGHT, TILE_WIDTH};
|
||||||
use crate::tiles::{Tiler, TilingPathInfo};
|
use crate::tiles::{Tiler, TilingPathInfo};
|
||||||
use crate::z_buffer::{DepthMetadata, ZBuffer};
|
use crate::z_buffer::{DepthMetadata, ZBuffer};
|
||||||
use pathfinder_content::effects::{BlendMode, Effects};
|
use pathfinder_content::effects::{BlendMode, Filter};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
||||||
|
@ -38,9 +38,7 @@ use std::u16;
|
||||||
pub(crate) struct SceneBuilder<'a> {
|
pub(crate) struct SceneBuilder<'a> {
|
||||||
scene: &'a Scene,
|
scene: &'a Scene,
|
||||||
built_options: &'a PreparedBuildOptions,
|
built_options: &'a PreparedBuildOptions,
|
||||||
|
|
||||||
next_alpha_tile_index: AtomicUsize,
|
next_alpha_tile_index: AtomicUsize,
|
||||||
|
|
||||||
pub(crate) listener: Box<dyn RenderCommandListener>,
|
pub(crate) listener: Box<dyn RenderCommandListener>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +53,7 @@ pub(crate) struct ObjectBuilder {
|
||||||
struct BuiltDrawPath {
|
struct BuiltDrawPath {
|
||||||
path: BuiltPath,
|
path: BuiltPath,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
effects: Effects,
|
filter: Filter,
|
||||||
color_texture_page_0: TexturePageId,
|
color_texture_page_0: TexturePageId,
|
||||||
color_texture_page_1: TexturePageId,
|
color_texture_page_1: TexturePageId,
|
||||||
sampling_flags_0: TextureSamplingFlags,
|
sampling_flags_0: TextureSamplingFlags,
|
||||||
|
@ -126,9 +124,9 @@ impl<'a> SceneBuilder<'a> {
|
||||||
let PaintInfo {
|
let PaintInfo {
|
||||||
render_commands,
|
render_commands,
|
||||||
paint_metadata,
|
paint_metadata,
|
||||||
render_target_metadata,
|
|
||||||
opacity_tile_page,
|
opacity_tile_page,
|
||||||
opacity_tile_transform,
|
opacity_tile_transform,
|
||||||
|
render_target_metadata: _
|
||||||
} = self.scene.build_paint_info(render_transform);
|
} = self.scene.build_paint_info(render_transform);
|
||||||
for render_command in render_commands {
|
for render_command in render_commands {
|
||||||
self.listener.send(render_command);
|
self.listener.send(render_command);
|
||||||
|
@ -160,7 +158,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
self.finish_building(&paint_metadata, &render_target_metadata, built_draw_paths);
|
self.finish_building(&paint_metadata, built_draw_paths);
|
||||||
|
|
||||||
let build_time = Instant::now() - start_time;
|
let build_time = Instant::now() - start_time;
|
||||||
self.listener.send(RenderCommand::Finish { build_time });
|
self.listener.send(RenderCommand::Finish { build_time });
|
||||||
|
@ -220,7 +218,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
BuiltDrawPath {
|
BuiltDrawPath {
|
||||||
path: tiler.object_builder.built_path,
|
path: tiler.object_builder.built_path,
|
||||||
blend_mode: path_object.blend_mode(),
|
blend_mode: path_object.blend_mode(),
|
||||||
effects: paint_metadata.effects(),
|
filter: paint_metadata.filter(),
|
||||||
color_texture_page_0: paint_metadata.location.page,
|
color_texture_page_0: paint_metadata.location.page,
|
||||||
sampling_flags_0: paint_metadata.sampling_flags,
|
sampling_flags_0: paint_metadata.sampling_flags,
|
||||||
color_texture_page_1: opacity_tile_page,
|
color_texture_page_1: opacity_tile_page,
|
||||||
|
@ -230,10 +228,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cull_tiles(&self,
|
fn cull_tiles(&self, paint_metadata: &[PaintMetadata], built_draw_paths: Vec<BuiltDrawPath>)
|
||||||
paint_metadata: &[PaintMetadata],
|
|
||||||
render_target_metadata: &[RenderTargetMetadata],
|
|
||||||
built_draw_paths: Vec<BuiltDrawPath>)
|
|
||||||
-> CulledTiles {
|
-> CulledTiles {
|
||||||
let mut culled_tiles = CulledTiles { display_list: vec![] };
|
let mut culled_tiles = CulledTiles { display_list: vec![] };
|
||||||
|
|
||||||
|
@ -269,40 +264,6 @@ impl<'a> SceneBuilder<'a> {
|
||||||
layer_z_buffers_stack.pop();
|
layer_z_buffers_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayItem::DrawRenderTarget { render_target, effects } => {
|
|
||||||
let effective_view_box = self.scene.effective_view_box(self.built_options);
|
|
||||||
let tile_rect = tiles::round_rect_out_to_tile_bounds(effective_view_box);
|
|
||||||
let layer_z_buffer = layer_z_buffers_stack.last().unwrap();
|
|
||||||
let mut tiles = vec![];
|
|
||||||
let uv_scale = vec2f(1.0, 1.0) / tile_rect.lower_right().to_f32();
|
|
||||||
let metadata = &render_target_metadata[render_target.0 as usize];
|
|
||||||
for tile_y in tile_rect.min_y()..tile_rect.max_y() {
|
|
||||||
for tile_x in tile_rect.min_x()..tile_rect.max_x() {
|
|
||||||
let tile_coords = vec2i(tile_x, tile_y);
|
|
||||||
if !layer_z_buffer.test(tile_coords, current_depth) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uv_rect = RectI::new(tile_coords, vec2i(1, 1)).to_f32() * uv_scale;
|
|
||||||
tiles.push(Tile::new_solid_from_texture_rect(tile_coords, uv_rect));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let batch = TileBatch {
|
|
||||||
tiles,
|
|
||||||
color_texture_0: Some(TileBatchTexture {
|
|
||||||
page: metadata.location.page,
|
|
||||||
sampling_flags: TextureSamplingFlags::empty(),
|
|
||||||
}),
|
|
||||||
color_texture_1: None,
|
|
||||||
effects,
|
|
||||||
blend_mode: BlendMode::SrcOver,
|
|
||||||
mask_0_fill_rule: None,
|
|
||||||
mask_1_fill_rule: None,
|
|
||||||
};
|
|
||||||
culled_tiles.display_list.push(CulledDisplayItem::DrawTiles(batch));
|
|
||||||
current_depth += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayItem::DrawPaths {
|
DisplayItem::DrawPaths {
|
||||||
start_index: start_draw_path_index,
|
start_index: start_draw_path_index,
|
||||||
end_index: end_draw_path_index,
|
end_index: end_draw_path_index,
|
||||||
|
@ -328,7 +289,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
built_draw_path.blend_mode,
|
built_draw_path.blend_mode,
|
||||||
built_draw_path.effects,
|
built_draw_path.filter,
|
||||||
None,
|
None,
|
||||||
None);
|
None);
|
||||||
|
|
||||||
|
@ -339,7 +300,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0,
|
color_texture_0,
|
||||||
color_texture_1,
|
color_texture_1,
|
||||||
built_draw_path.blend_mode,
|
built_draw_path.blend_mode,
|
||||||
built_draw_path.effects,
|
built_draw_path.filter,
|
||||||
Some(built_draw_path.mask_0_fill_rule),
|
Some(built_draw_path.mask_0_fill_rule),
|
||||||
None);
|
None);
|
||||||
|
|
||||||
|
@ -351,7 +312,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0,
|
color_texture_0,
|
||||||
color_texture_1,
|
color_texture_1,
|
||||||
built_draw_path.blend_mode,
|
built_draw_path.blend_mode,
|
||||||
built_draw_path.effects,
|
built_draw_path.filter,
|
||||||
Some(built_draw_path.mask_0_fill_rule),
|
Some(built_draw_path.mask_0_fill_rule),
|
||||||
Some(mask_1_fill_rule));
|
Some(mask_1_fill_rule));
|
||||||
}
|
}
|
||||||
|
@ -365,7 +326,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0,
|
color_texture_0,
|
||||||
color_texture_1,
|
color_texture_1,
|
||||||
built_draw_path.blend_mode,
|
built_draw_path.blend_mode,
|
||||||
built_draw_path.effects,
|
built_draw_path.filter,
|
||||||
None,
|
None,
|
||||||
None);
|
None);
|
||||||
}
|
}
|
||||||
|
@ -416,10 +377,6 @@ impl<'a> SceneBuilder<'a> {
|
||||||
current_depth += 1;
|
current_depth += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DisplayItem::DrawRenderTarget { .. } => {
|
|
||||||
// FIXME(pcwalton): Not great that this doesn't participate in Z-buffering!
|
|
||||||
current_depth += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug_assert_eq!(z_buffer_index_stack.len(), 1);
|
debug_assert_eq!(z_buffer_index_stack.len(), 1);
|
||||||
|
@ -435,7 +392,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0: Option<TileBatchTexture>,
|
color_texture_0: Option<TileBatchTexture>,
|
||||||
color_texture_1: Option<TileBatchTexture>,
|
color_texture_1: Option<TileBatchTexture>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
effects: Effects,
|
filter: Filter,
|
||||||
mask_0_fill_rule: Option<FillRule>,
|
mask_0_fill_rule: Option<FillRule>,
|
||||||
mask_1_fill_rule: Option<FillRule>) {
|
mask_1_fill_rule: Option<FillRule>) {
|
||||||
if alpha_tiles.is_empty() {
|
if alpha_tiles.is_empty() {
|
||||||
|
@ -454,13 +411,13 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0: ref batch_color_texture_0,
|
color_texture_0: ref batch_color_texture_0,
|
||||||
color_texture_1: ref batch_color_texture_1,
|
color_texture_1: ref batch_color_texture_1,
|
||||||
blend_mode: batch_blend_mode,
|
blend_mode: batch_blend_mode,
|
||||||
effects: batch_effects,
|
filter: batch_filter,
|
||||||
mask_0_fill_rule: batch_mask_0_fill_rule,
|
mask_0_fill_rule: batch_mask_0_fill_rule,
|
||||||
mask_1_fill_rule: batch_mask_1_fill_rule,
|
mask_1_fill_rule: batch_mask_1_fill_rule,
|
||||||
})) if *batch_color_texture_0 == color_texture_0 &&
|
})) if *batch_color_texture_0 == color_texture_0 &&
|
||||||
*batch_color_texture_1 == color_texture_1 &&
|
*batch_color_texture_1 == color_texture_1 &&
|
||||||
batch_blend_mode == blend_mode &&
|
batch_blend_mode == blend_mode &&
|
||||||
batch_effects == effects &&
|
batch_filter == filter &&
|
||||||
batch_mask_0_fill_rule == mask_0_fill_rule &&
|
batch_mask_0_fill_rule == mask_0_fill_rule &&
|
||||||
batch_mask_1_fill_rule == mask_1_fill_rule &&
|
batch_mask_1_fill_rule == mask_1_fill_rule &&
|
||||||
!batch_blend_mode.needs_readable_framebuffer() => {}
|
!batch_blend_mode.needs_readable_framebuffer() => {}
|
||||||
|
@ -470,7 +427,7 @@ impl<'a> SceneBuilder<'a> {
|
||||||
color_texture_0,
|
color_texture_0,
|
||||||
color_texture_1,
|
color_texture_1,
|
||||||
blend_mode,
|
blend_mode,
|
||||||
effects,
|
filter,
|
||||||
mask_0_fill_rule,
|
mask_0_fill_rule,
|
||||||
mask_1_fill_rule,
|
mask_1_fill_rule,
|
||||||
};
|
};
|
||||||
|
@ -512,12 +469,9 @@ impl<'a> SceneBuilder<'a> {
|
||||||
|
|
||||||
fn finish_building(&mut self,
|
fn finish_building(&mut self,
|
||||||
paint_metadata: &[PaintMetadata],
|
paint_metadata: &[PaintMetadata],
|
||||||
render_target_metadata: &[RenderTargetMetadata],
|
|
||||||
built_draw_paths: Vec<BuiltDrawPath>) {
|
built_draw_paths: Vec<BuiltDrawPath>) {
|
||||||
self.listener.send(RenderCommand::FlushFills);
|
self.listener.send(RenderCommand::FlushFills);
|
||||||
let culled_tiles = self.cull_tiles(paint_metadata,
|
let culled_tiles = self.cull_tiles(paint_metadata, built_draw_paths);
|
||||||
render_target_metadata,
|
|
||||||
built_draw_paths);
|
|
||||||
self.pack_tiles(culled_tiles);
|
self.pack_tiles(culled_tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +479,6 @@ impl<'a> SceneBuilder<'a> {
|
||||||
let mut framebuffer_nesting = 0;
|
let mut framebuffer_nesting = 0;
|
||||||
for display_item in &self.scene.display_list {
|
for display_item in &self.scene.display_list {
|
||||||
match *display_item {
|
match *display_item {
|
||||||
DisplayItem::DrawRenderTarget { .. } => {}
|
|
||||||
DisplayItem::PushRenderTarget(_) => framebuffer_nesting += 1,
|
DisplayItem::PushRenderTarget(_) => framebuffer_nesting += 1,
|
||||||
DisplayItem::PopRenderTarget => framebuffer_nesting -= 1,
|
DisplayItem::PopRenderTarget => framebuffer_nesting -= 1,
|
||||||
DisplayItem::DrawPaths { start_index, end_index } => {
|
DisplayItem::DrawPaths { start_index, end_index } => {
|
||||||
|
|
|
@ -19,7 +19,8 @@ use crate::gpu_data::{TexturePageId, Tile, TileBatchTexture};
|
||||||
use crate::options::BoundingQuad;
|
use crate::options::BoundingQuad;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use pathfinder_color::{self as color, ColorF, ColorU};
|
use pathfinder_color::{self as color, ColorF, ColorU};
|
||||||
use pathfinder_content::effects::{BlendMode, BlurDirection, DefringingKernel, Effects, Filter};
|
use pathfinder_content::effects::{BlendMode, BlurDirection, DefringingKernel};
|
||||||
|
use pathfinder_content::effects::{Filter, PatternFilter};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
|
@ -313,7 +314,7 @@ where
|
||||||
batch.mask_0_fill_rule,
|
batch.mask_0_fill_rule,
|
||||||
batch.mask_1_fill_rule,
|
batch.mask_1_fill_rule,
|
||||||
batch.blend_mode,
|
batch.blend_mode,
|
||||||
batch.effects)
|
batch.filter)
|
||||||
}
|
}
|
||||||
RenderCommand::Finish { .. } => {}
|
RenderCommand::Finish { .. } => {}
|
||||||
}
|
}
|
||||||
|
@ -583,7 +584,7 @@ where
|
||||||
mask_0_fill_rule: Option<FillRule>,
|
mask_0_fill_rule: Option<FillRule>,
|
||||||
mask_1_fill_rule: Option<FillRule>,
|
mask_1_fill_rule: Option<FillRule>,
|
||||||
blend_mode: BlendMode,
|
blend_mode: BlendMode,
|
||||||
effects: Effects) {
|
filter: Filter) {
|
||||||
// TODO(pcwalton): Disable blend for solid tiles.
|
// TODO(pcwalton): Disable blend for solid tiles.
|
||||||
|
|
||||||
let needs_readable_framebuffer = blend_mode.needs_readable_framebuffer();
|
let needs_readable_framebuffer = blend_mode.needs_readable_framebuffer();
|
||||||
|
@ -658,13 +659,18 @@ where
|
||||||
|
|
||||||
ctrl |= blend_mode.to_composite_ctrl() << COMBINER_CTRL_COMPOSITE_SHIFT;
|
ctrl |= blend_mode.to_composite_ctrl() << COMBINER_CTRL_COMPOSITE_SHIFT;
|
||||||
|
|
||||||
match effects.filter {
|
match filter {
|
||||||
Filter::None => {}
|
Filter::None => {}
|
||||||
Filter::RadialGradient { line, radii, uv_origin } => {
|
Filter::RadialGradient { line, radii, uv_origin } => {
|
||||||
ctrl |= COMBINER_CTRL_FILTER_RADIAL_GRADIENT << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
ctrl |= COMBINER_CTRL_FILTER_RADIAL_GRADIENT << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
||||||
self.set_uniforms_for_radial_gradient_filter(&mut uniforms, line, radii, uv_origin)
|
self.set_uniforms_for_radial_gradient_filter(&mut uniforms, line, radii, uv_origin)
|
||||||
}
|
}
|
||||||
Filter::Text { fg_color, bg_color, defringing_kernel, gamma_correction } => {
|
Filter::PatternFilter(PatternFilter::Text {
|
||||||
|
fg_color,
|
||||||
|
bg_color,
|
||||||
|
defringing_kernel,
|
||||||
|
gamma_correction,
|
||||||
|
}) => {
|
||||||
ctrl |= COMBINER_CTRL_FILTER_TEXT << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
ctrl |= COMBINER_CTRL_FILTER_TEXT << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
||||||
self.set_uniforms_for_text_filter(&mut textures,
|
self.set_uniforms_for_text_filter(&mut textures,
|
||||||
&mut uniforms,
|
&mut uniforms,
|
||||||
|
@ -673,7 +679,7 @@ where
|
||||||
defringing_kernel,
|
defringing_kernel,
|
||||||
gamma_correction);
|
gamma_correction);
|
||||||
}
|
}
|
||||||
Filter::Blur { direction, sigma } => {
|
Filter::PatternFilter(PatternFilter::Blur { direction, sigma }) => {
|
||||||
ctrl |= COMBINER_CTRL_FILTER_BLUR << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
ctrl |= COMBINER_CTRL_FILTER_BLUR << COMBINER_CTRL_COLOR_0_FILTER_SHIFT;
|
||||||
self.set_uniforms_for_blur_filter(&mut uniforms, direction, sigma);
|
self.set_uniforms_for_blur_filter(&mut uniforms, direction, sigma);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
use crate::options::BoundingQuad;
|
use crate::options::BoundingQuad;
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_content::effects::{BlendMode, Effects};
|
use pathfinder_content::effects::{BlendMode, Filter};
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8};
|
use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8};
|
||||||
|
@ -91,8 +91,8 @@ pub struct TileBatch {
|
||||||
pub color_texture_1: Option<TileBatchTexture>,
|
pub color_texture_1: Option<TileBatchTexture>,
|
||||||
pub mask_0_fill_rule: Option<FillRule>,
|
pub mask_0_fill_rule: Option<FillRule>,
|
||||||
pub mask_1_fill_rule: Option<FillRule>,
|
pub mask_1_fill_rule: Option<FillRule>,
|
||||||
|
pub filter: Filter,
|
||||||
pub blend_mode: BlendMode,
|
pub blend_mode: BlendMode,
|
||||||
pub effects: Effects,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
|
|
@ -14,9 +14,9 @@ use crate::scene::RenderTarget;
|
||||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pathfinder_color::ColorU;
|
use pathfinder_color::ColorU;
|
||||||
use pathfinder_content::effects::{Effects, Filter};
|
use pathfinder_content::effects::{Filter, PatternFilter};
|
||||||
use pathfinder_content::gradient::Gradient;
|
use pathfinder_content::gradient::Gradient;
|
||||||
use pathfinder_content::pattern::{Pattern, PatternFlags, PatternSource};
|
use pathfinder_content::pattern::{Pattern, PatternSource};
|
||||||
use pathfinder_content::render_target::RenderTargetId;
|
use pathfinder_content::render_target::RenderTargetId;
|
||||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||||
use pathfinder_geometry::rect::{RectF, RectI};
|
use pathfinder_geometry::rect::{RectF, RectI};
|
||||||
|
@ -93,7 +93,7 @@ impl Paint {
|
||||||
Paint::Gradient(ref gradient) => {
|
Paint::Gradient(ref gradient) => {
|
||||||
gradient.stops().iter().all(|stop| stop.color.is_opaque())
|
gradient.stops().iter().all(|stop| stop.color.is_opaque())
|
||||||
}
|
}
|
||||||
Paint::Pattern(ref pattern) => pattern.source.is_opaque(),
|
Paint::Pattern(ref pattern) => pattern.is_opaque(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ impl Paint {
|
||||||
0.5))));
|
0.5))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Paint::Pattern(ref mut pattern) => pattern.transform = *transform * pattern.transform,
|
Paint::Pattern(ref mut pattern) => pattern.apply_transform(*transform),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,8 +165,8 @@ pub struct PaintMetadata {
|
||||||
pub sampling_flags: TextureSamplingFlags,
|
pub sampling_flags: TextureSamplingFlags,
|
||||||
/// True if this paint is fully opaque.
|
/// True if this paint is fully opaque.
|
||||||
pub is_opaque: bool,
|
pub is_opaque: bool,
|
||||||
/// The radial gradient for this paint, if applicable.
|
/// The filter to be applied to this paint.
|
||||||
pub radial_gradient: Option<RadialGradientMetadata>,
|
pub filter: PaintFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -183,6 +183,18 @@ pub struct RenderTargetMetadata {
|
||||||
pub location: TextureLocation,
|
pub location: TextureLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PaintFilter {
|
||||||
|
None,
|
||||||
|
RadialGradient {
|
||||||
|
/// The line segment that connects the two circles.
|
||||||
|
line: LineSegment2F,
|
||||||
|
/// The radii of the two circles.
|
||||||
|
radii: F32x2,
|
||||||
|
},
|
||||||
|
PatternFilter(PatternFilter),
|
||||||
|
}
|
||||||
|
|
||||||
impl Palette {
|
impl Palette {
|
||||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
pub fn push_paint(&mut self, paint: &Paint) -> PaintId {
|
pub fn push_paint(&mut self, paint: &Paint) -> PaintId {
|
||||||
|
@ -219,23 +231,26 @@ impl Palette {
|
||||||
let mut gradient_tile_builder = GradientTileBuilder::new();
|
let mut gradient_tile_builder = GradientTileBuilder::new();
|
||||||
let mut image_texel_info = vec![];
|
let mut image_texel_info = vec![];
|
||||||
for paint in &self.paints {
|
for paint in &self.paints {
|
||||||
let (texture_location, mut sampling_flags, radial_gradient);
|
let (texture_location, mut sampling_flags, filter);
|
||||||
match paint {
|
match paint {
|
||||||
Paint::Color(color) => {
|
Paint::Color(color) => {
|
||||||
texture_location = solid_color_tile_builder.allocate(&mut allocator, *color);
|
texture_location = solid_color_tile_builder.allocate(&mut allocator, *color);
|
||||||
sampling_flags = TextureSamplingFlags::empty();
|
sampling_flags = TextureSamplingFlags::empty();
|
||||||
radial_gradient = None;
|
filter = PaintFilter::None;
|
||||||
}
|
}
|
||||||
Paint::Gradient(ref gradient) => {
|
Paint::Gradient(ref gradient) => {
|
||||||
// FIXME(pcwalton): The gradient size might not be big enough. Detect this.
|
// FIXME(pcwalton): The gradient size might not be big enough. Detect this.
|
||||||
texture_location = gradient_tile_builder.allocate(&mut allocator, gradient);
|
texture_location = gradient_tile_builder.allocate(&mut allocator, gradient);
|
||||||
sampling_flags = TextureSamplingFlags::empty();
|
sampling_flags = TextureSamplingFlags::empty();
|
||||||
radial_gradient = gradient.radii().map(|radii| {
|
filter = match gradient.radii() {
|
||||||
RadialGradientMetadata { line: gradient.line(), radii }
|
None => PaintFilter::None,
|
||||||
});
|
Some(radii) => {
|
||||||
|
PaintFilter::RadialGradient { line: gradient.line(), radii }
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Paint::Pattern(ref pattern) => {
|
Paint::Pattern(ref pattern) => {
|
||||||
match pattern.source {
|
match *pattern.source() {
|
||||||
PatternSource::RenderTarget { id: render_target_id, .. } => {
|
PatternSource::RenderTarget { id: render_target_id, .. } => {
|
||||||
texture_location =
|
texture_location =
|
||||||
render_target_metadata[render_target_id.0 as usize].location;
|
render_target_metadata[render_target_id.0 as usize].location;
|
||||||
|
@ -253,18 +268,21 @@ impl Palette {
|
||||||
}
|
}
|
||||||
|
|
||||||
sampling_flags = TextureSamplingFlags::empty();
|
sampling_flags = TextureSamplingFlags::empty();
|
||||||
if pattern.flags.contains(PatternFlags::REPEAT_X) {
|
if pattern.repeat_x() {
|
||||||
sampling_flags.insert(TextureSamplingFlags::REPEAT_U);
|
sampling_flags.insert(TextureSamplingFlags::REPEAT_U);
|
||||||
}
|
}
|
||||||
if pattern.flags.contains(PatternFlags::REPEAT_Y) {
|
if pattern.repeat_y() {
|
||||||
sampling_flags.insert(TextureSamplingFlags::REPEAT_V);
|
sampling_flags.insert(TextureSamplingFlags::REPEAT_V);
|
||||||
}
|
}
|
||||||
if pattern.flags.contains(PatternFlags::NO_SMOOTHING) {
|
if !pattern.smoothing_enabled() {
|
||||||
sampling_flags.insert(TextureSamplingFlags::NEAREST_MIN |
|
sampling_flags.insert(TextureSamplingFlags::NEAREST_MIN |
|
||||||
TextureSamplingFlags::NEAREST_MAG);
|
TextureSamplingFlags::NEAREST_MAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
radial_gradient = None;
|
filter = match pattern.filter() {
|
||||||
|
None => PaintFilter::None,
|
||||||
|
Some(pattern_filter) => PaintFilter::PatternFilter(pattern_filter),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,7 +291,7 @@ impl Palette {
|
||||||
texture_transform: Transform2F::default(),
|
texture_transform: Transform2F::default(),
|
||||||
sampling_flags,
|
sampling_flags,
|
||||||
is_opaque: paint.is_opaque(),
|
is_opaque: paint.is_opaque(),
|
||||||
radial_gradient,
|
filter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,24 +321,24 @@ impl Palette {
|
||||||
vector: texture_origin_uv,
|
vector: texture_origin_uv,
|
||||||
} * render_transform
|
} * render_transform
|
||||||
}
|
}
|
||||||
Paint::Pattern(Pattern { source: PatternSource::Image(_), transform, .. }) => {
|
Paint::Pattern(pattern) => {
|
||||||
let texture_origin_uv =
|
match pattern.source() {
|
||||||
rect_to_uv(metadata.location.rect, texture_scale).origin();
|
PatternSource::Image(_) => {
|
||||||
Transform2F::from_translation(texture_origin_uv) *
|
let texture_origin_uv =
|
||||||
Transform2F::from_scale(texture_scale) *
|
rect_to_uv(metadata.location.rect, texture_scale).origin();
|
||||||
transform.inverse() * render_transform
|
Transform2F::from_translation(texture_origin_uv) *
|
||||||
}
|
Transform2F::from_scale(texture_scale) *
|
||||||
Paint::Pattern(Pattern {
|
pattern.transform().inverse() * render_transform
|
||||||
source: PatternSource::RenderTarget { .. },
|
}
|
||||||
transform,
|
PatternSource::RenderTarget { .. } => {
|
||||||
..
|
// FIXME(pcwalton): Only do this in GL, not Metal!
|
||||||
}) => {
|
let texture_origin_uv = rect_to_uv(metadata.location.rect,
|
||||||
// FIXME(pcwalton): Only do this in GL, not Metal!
|
texture_scale).lower_left();
|
||||||
let texture_origin_uv = rect_to_uv(metadata.location.rect,
|
Transform2F::from_translation(texture_origin_uv) *
|
||||||
texture_scale).lower_left();
|
Transform2F::from_scale(texture_scale * vec2f(1.0, -1.0)) *
|
||||||
Transform2F::from_translation(texture_origin_uv) *
|
pattern.transform().inverse() * render_transform
|
||||||
Transform2F::from_scale(texture_scale * vec2f(1.0, -1.0)) *
|
}
|
||||||
transform.inverse() * render_transform
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,18 +394,14 @@ impl PaintMetadata {
|
||||||
tex_coords
|
tex_coords
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn effects(&self) -> Effects {
|
pub(crate) fn filter(&self) -> Filter {
|
||||||
Effects {
|
match self.filter {
|
||||||
filter: match self.radial_gradient {
|
PaintFilter::None => Filter::None,
|
||||||
None => Filter::None,
|
PaintFilter::RadialGradient { line, radii } => {
|
||||||
Some(gradient) => {
|
let uv_origin = self.texture_transform.vector;
|
||||||
Filter::RadialGradient {
|
Filter::RadialGradient { line, radii, uv_origin }
|
||||||
line: gradient.line,
|
}
|
||||||
radii: gradient.radii,
|
PaintFilter::PatternFilter(pattern_filter) => Filter::PatternFilter(pattern_filter),
|
||||||
uv_origin: self.texture_transform.vector,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::concurrent::executor::Executor;
|
||||||
use crate::options::{BuildOptions, PreparedBuildOptions};
|
use crate::options::{BuildOptions, PreparedBuildOptions};
|
||||||
use crate::options::{PreparedRenderTransform, RenderCommandListener};
|
use crate::options::{PreparedRenderTransform, RenderCommandListener};
|
||||||
use crate::paint::{Paint, PaintId, PaintInfo, Palette};
|
use crate::paint::{Paint, PaintId, PaintInfo, Palette};
|
||||||
use pathfinder_content::effects::{BlendMode, Effects};
|
use pathfinder_content::effects::BlendMode;
|
||||||
use pathfinder_content::fill::FillRule;
|
use pathfinder_content::fill::FillRule;
|
||||||
use pathfinder_content::outline::Outline;
|
use pathfinder_content::outline::Outline;
|
||||||
use pathfinder_content::pattern::{Pattern, PatternSource};
|
use pathfinder_content::pattern::{Pattern, PatternSource};
|
||||||
|
@ -87,10 +87,6 @@ impl Scene {
|
||||||
self.display_list.push(DisplayItem::PopRenderTarget);
|
self.display_list.push(DisplayItem::PopRenderTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_render_target(&mut self, render_target: RenderTargetId, effects: Effects) {
|
|
||||||
self.display_list.push(DisplayItem::DrawRenderTarget { render_target, effects });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_scene(&mut self, scene: Scene) {
|
pub fn append_scene(&mut self, scene: Scene) {
|
||||||
// Merge render targets.
|
// Merge render targets.
|
||||||
let mut render_target_mapping = HashMap::new();
|
let mut render_target_mapping = HashMap::new();
|
||||||
|
@ -108,19 +104,20 @@ impl Scene {
|
||||||
for (old_paint_index, old_paint) in scene.palette.paints.iter().enumerate() {
|
for (old_paint_index, old_paint) in scene.palette.paints.iter().enumerate() {
|
||||||
let old_paint_id = PaintId(old_paint_index as u16);
|
let old_paint_id = PaintId(old_paint_index as u16);
|
||||||
let new_paint_id = match old_paint {
|
let new_paint_id = match old_paint {
|
||||||
Paint::Pattern(Pattern {
|
Paint::Pattern(pattern) => {
|
||||||
source: PatternSource::RenderTarget { id: old_render_target_id, size },
|
match pattern.source() {
|
||||||
transform,
|
PatternSource::RenderTarget { id: old_render_target_id, size } => {
|
||||||
flags
|
let mut new_pattern =
|
||||||
}) => {
|
Pattern::from_render_target(*old_render_target_id, *size);
|
||||||
self.palette.push_paint(&Paint::Pattern(Pattern {
|
new_pattern.set_filter(pattern.filter());
|
||||||
source: PatternSource::RenderTarget {
|
new_pattern.apply_transform(pattern.transform());
|
||||||
id: render_target_mapping[old_render_target_id],
|
new_pattern.set_repeat_x(pattern.repeat_x());
|
||||||
size: *size,
|
new_pattern.set_repeat_y(pattern.repeat_y());
|
||||||
},
|
new_pattern.set_smoothing_enabled(pattern.smoothing_enabled());
|
||||||
transform: *transform,
|
self.palette.push_paint(&Paint::Pattern(new_pattern))
|
||||||
flags: *flags,
|
}
|
||||||
}))
|
_ => self.palette.push_paint(old_paint),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
paint => self.palette.push_paint(paint),
|
paint => self.palette.push_paint(paint),
|
||||||
};
|
};
|
||||||
|
@ -154,13 +151,6 @@ impl Scene {
|
||||||
// Merge display items.
|
// Merge display items.
|
||||||
for display_item in scene.display_list {
|
for display_item in scene.display_list {
|
||||||
match display_item {
|
match display_item {
|
||||||
DisplayItem::DrawRenderTarget {
|
|
||||||
render_target: old_render_target_id,
|
|
||||||
effects,
|
|
||||||
} => {
|
|
||||||
let new_render_target_id = render_target_mapping[&old_render_target_id];
|
|
||||||
self.draw_render_target(new_render_target_id, effects)
|
|
||||||
}
|
|
||||||
DisplayItem::PushRenderTarget(old_render_target_id) => {
|
DisplayItem::PushRenderTarget(old_render_target_id) => {
|
||||||
let new_render_target_id = render_target_mapping[&old_render_target_id];
|
let new_render_target_id = render_target_mapping[&old_render_target_id];
|
||||||
self.display_list.push(DisplayItem::PushRenderTarget(new_render_target_id));
|
self.display_list.push(DisplayItem::PushRenderTarget(new_render_target_id));
|
||||||
|
@ -349,13 +339,6 @@ pub enum DisplayItem {
|
||||||
/// Draws paths to the render target on top of the stack.
|
/// Draws paths to the render target on top of the stack.
|
||||||
DrawPaths { start_index: u32, end_index: u32 },
|
DrawPaths { start_index: u32, end_index: u32 },
|
||||||
|
|
||||||
/// Draws an entire render target to the render target on top of the stack.
|
|
||||||
///
|
|
||||||
/// FIXME(pcwalton): This draws the entire render target, so it's inefficient. We should get
|
|
||||||
/// rid of this command and transition all uses to `DrawPaths`. The reason it exists is that we
|
|
||||||
/// don't have logic to create tiles for blur bounding regions yet.
|
|
||||||
DrawRenderTarget { render_target: RenderTargetId, effects: Effects },
|
|
||||||
|
|
||||||
/// Pushes a render target onto the top of the stack.
|
/// Pushes a render target onto the top of the stack.
|
||||||
PushRenderTarget(RenderTargetId),
|
PushRenderTarget(RenderTargetId),
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::gpu_data::{Tile, TileBatch, TileBatchTexture, TileVertex};
|
||||||
use crate::paint::{PaintId, PaintMetadata};
|
use crate::paint::{PaintId, PaintMetadata};
|
||||||
use crate::tile_map::DenseTileMap;
|
use crate::tile_map::DenseTileMap;
|
||||||
use crate::tiles;
|
use crate::tiles;
|
||||||
use pathfinder_content::effects::{BlendMode, Effects};
|
use pathfinder_content::effects::{BlendMode, Filter};
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2i};
|
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2i};
|
||||||
use vec_map::VecMap;
|
use vec_map::VecMap;
|
||||||
|
@ -94,7 +94,7 @@ impl ZBuffer {
|
||||||
}),
|
}),
|
||||||
color_texture_1: None,
|
color_texture_1: None,
|
||||||
tiles: vec![],
|
tiles: vec![],
|
||||||
effects: Effects::default(),
|
filter: Filter::None,
|
||||||
blend_mode: BlendMode::default(),
|
blend_mode: BlendMode::default(),
|
||||||
mask_0_fill_rule: None,
|
mask_0_fill_rule: None,
|
||||||
mask_1_fill_rule: None,
|
mask_1_fill_rule: None,
|
||||||
|
@ -124,19 +124,6 @@ impl Tile {
|
||||||
paint_metadata),
|
paint_metadata),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_solid_from_texture_rect(tile_position: Vector2I, texture_rect: RectF)
|
|
||||||
-> Tile {
|
|
||||||
Tile {
|
|
||||||
upper_left: TileVertex::new_solid_from_uv(tile_position, texture_rect.origin()),
|
|
||||||
upper_right: TileVertex::new_solid_from_uv(tile_position + vec2i(1, 0),
|
|
||||||
texture_rect.upper_right()),
|
|
||||||
lower_left: TileVertex::new_solid_from_uv(tile_position + vec2i(0, 1),
|
|
||||||
texture_rect.lower_left()),
|
|
||||||
lower_right: TileVertex::new_solid_from_uv(tile_position + vec2i(1, 1),
|
|
||||||
texture_rect.lower_right()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TileVertex {
|
impl TileVertex {
|
||||||
|
|
Loading…
Reference in New Issue