Document the remainder of the `pathfinder_renderer` API
This commit is contained in:
parent
3d9b5509ba
commit
26bf6cce4e
|
@ -11,7 +11,7 @@
|
|||
use pathfinder_content::outline::ContourIterFlags;
|
||||
use pathfinder_content::segment::SegmentKind;
|
||||
use pathfinder_geometry::vector::{Vector2F, vec2f};
|
||||
use pathfinder_renderer::scene::{DrawPath, Scene};
|
||||
use pathfinder_renderer::scene::{DrawPathId, Scene};
|
||||
use std::fmt;
|
||||
use std::io::{self, Write};
|
||||
|
||||
|
@ -53,13 +53,15 @@ fn export_svg<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
|||
view_box.size().x(),
|
||||
view_box.size().y()
|
||||
)?;
|
||||
for &DrawPath { paint: paint_id, ref outline, ref name, .. } in scene.draw_paths() {
|
||||
let paint = scene.get_paint(paint_id);
|
||||
for draw_path_index in 0..scene.draw_path_count() {
|
||||
let draw_path_id = DrawPathId(draw_path_index);
|
||||
let draw_path = scene.get_draw_path(draw_path_id);
|
||||
let paint = scene.get_paint(draw_path.paint);
|
||||
write!(writer, " <path")?;
|
||||
if !name.is_empty() {
|
||||
write!(writer, " id=\"{}\"", name)?;
|
||||
if !draw_path.name.is_empty() {
|
||||
write!(writer, " id=\"{}\"", draw_path.name)?;
|
||||
}
|
||||
writeln!(writer, " fill=\"{:?}\" d=\"{:?}\" />", paint, outline)?;
|
||||
writeln!(writer, " fill=\"{:?}\" d=\"{:?}\" />", draw_path.paint, draw_path.outline)?;
|
||||
}
|
||||
writeln!(writer, "</svg>")?;
|
||||
Ok(())
|
||||
|
@ -76,14 +78,17 @@ fn export_pdf<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
|||
vec2f(r.x(), height - r.y())
|
||||
};
|
||||
|
||||
for &DrawPath { paint: paint_id, ref outline, .. } in scene.draw_paths() {
|
||||
for draw_path_index in 0..scene.draw_path_count() {
|
||||
let draw_path_id = DrawPathId(draw_path_index);
|
||||
let draw_path = scene.get_draw_path(draw_path_id);
|
||||
|
||||
// TODO(pcwalton): Gradients and patterns.
|
||||
let paint = scene.get_paint(paint_id);
|
||||
let paint = scene.get_paint(draw_path.paint);
|
||||
if paint.is_color() {
|
||||
pdf.set_fill_color(paint.base_color());
|
||||
}
|
||||
|
||||
for contour in outline.contours() {
|
||||
for contour in draw_path.outline.contours() {
|
||||
for (segment_index, segment) in contour.iter(ContourIterFlags::empty()).enumerate() {
|
||||
if segment_index == 0 {
|
||||
pdf.move_to(tr(segment.baseline.from()));
|
||||
|
@ -140,14 +145,16 @@ fn export_ps<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
|||
writeln!(writer, "0 {} translate", view_box.size().y())?;
|
||||
writeln!(writer, "1 -1 scale")?;
|
||||
|
||||
for &DrawPath { paint: paint_id, ref outline, ref name, .. } in scene.draw_paths() {
|
||||
if !name.is_empty() {
|
||||
writeln!(writer, "newpath % {}", name)?;
|
||||
for draw_path_index in 0..scene.draw_path_count() {
|
||||
let draw_path_id = DrawPathId(draw_path_index);
|
||||
let draw_path = scene.get_draw_path(draw_path_id);
|
||||
if !draw_path.name.is_empty() {
|
||||
writeln!(writer, "newpath % {}", draw_path.name)?;
|
||||
} else {
|
||||
writeln!(writer, "newpath")?;
|
||||
}
|
||||
|
||||
for contour in outline.contours() {
|
||||
for contour in draw_path.outline.contours() {
|
||||
for (segment_index, segment) in contour.iter(ContourIterFlags::empty()).enumerate() {
|
||||
if segment_index == 0 {
|
||||
writeln!(writer, "{} moveto", P(segment.baseline.from()))?;
|
||||
|
@ -182,7 +189,7 @@ fn export_ps<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
|
|||
}
|
||||
|
||||
// TODO(pcwalton): Gradients and patterns.
|
||||
let paint = scene.get_paint(paint_id);
|
||||
let paint = scene.get_paint(draw_path.paint);
|
||||
if paint.is_color() {
|
||||
let color = paint.base_color();
|
||||
writeln!(writer, "{} {} {} setrgbcolor", color.r, color.g, color.b)?;
|
||||
|
|
|
@ -32,6 +32,11 @@ pub struct RendererOptions<D> where D: Device {
|
|||
pub show_debug_ui: bool,
|
||||
}
|
||||
|
||||
/// The GPU API level that Pathfinder will use.
|
||||
///
|
||||
/// Note that this is a *level*, not a *backend*. Levels describe rough GPU feature requirements
|
||||
/// instead of specific APIs. "D3D9" doesn't mean "Direct3D 9" specifically: rather, it's a more
|
||||
/// convenient way to write something like "Direct3D 9/OpenGL 3.0/Metal/WebGL 2.0".
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum RendererLevel {
|
||||
/// Direct3D 9/OpenGL 3.0/WebGL 2.0 compatibility. Bin on CPU, fill and composite on GPU.
|
||||
|
@ -41,6 +46,7 @@ pub enum RendererLevel {
|
|||
}
|
||||
|
||||
impl RendererMode {
|
||||
/// Creates a new `RendererMode` with a suitable API level for the given GPU device.
|
||||
#[inline]
|
||||
pub fn default_for_device<D>(device: &D) -> RendererMode where D: Device {
|
||||
RendererMode { level: RendererLevel::default_for_device(device) }
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! The GPU renderer that processes commands necessary to render a scene.
|
||||
|
||||
use crate::gpu::blend::{ToBlendState, ToCompositeCtrl};
|
||||
use crate::gpu::d3d9::renderer::RendererD3D9;
|
||||
use crate::gpu::d3d11::renderer::RendererD3D11;
|
||||
|
@ -66,6 +68,7 @@ const COMBINER_CTRL_COLOR_FILTER_SHIFT: i32 = 4;
|
|||
const COMBINER_CTRL_COLOR_COMBINE_SHIFT: i32 = 6;
|
||||
const COMBINER_CTRL_COMPOSITE_SHIFT: i32 = 8;
|
||||
|
||||
/// The GPU renderer that processes commands necessary to render a scene.
|
||||
pub struct Renderer<D> where D: Device {
|
||||
// Basic data
|
||||
pub(crate) core: RendererCore<D>,
|
||||
|
|
|
@ -242,7 +242,7 @@ pub struct DrawTileBatchD3D11 {
|
|||
pub struct TileBatchTexture {
|
||||
pub page: TexturePageId,
|
||||
pub sampling_flags: TextureSamplingFlags,
|
||||
pub composite_op: PaintCompositeOp,
|
||||
pub(crate) composite_op: PaintCompositeOp,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! The CPU portion of Pathfinder's renderer.
|
||||
//! Pathfinder's renderer and associated objects.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Defines how a path is to be filled.
|
||||
|
||||
use crate::allocator::{AllocationMode, TextureAllocator};
|
||||
use crate::gpu_data::{ColorCombineMode, RenderCommand, TextureLocation, TextureMetadataEntry};
|
||||
use crate::gpu_data::{TexturePageDescriptor, TexturePageId, TileBatchTexture};
|
||||
|
@ -48,34 +50,46 @@ struct RenderTargetData {
|
|||
metadata: RenderTargetMetadata,
|
||||
}
|
||||
|
||||
/// Defines how a path is to be filled: with a solid color, gradient, or pattern.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct Paint {
|
||||
base_color: ColorU,
|
||||
overlay: Option<PaintOverlay>,
|
||||
}
|
||||
|
||||
/// What is to be overlaid on top of a base color.
|
||||
///
|
||||
/// An overlay is a gradient or a pattern, plus a composite operation which determines how the
|
||||
/// gradient or pattern is to be combined with the base color.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct PaintOverlay {
|
||||
composite_op: PaintCompositeOp,
|
||||
contents: PaintContents,
|
||||
}
|
||||
|
||||
/// The contents of an overlay: either a gradient or a pattern.
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum PaintContents {
|
||||
pub(crate) enum PaintContents {
|
||||
/// A gradient, either linear or radial.
|
||||
Gradient(Gradient),
|
||||
/// A raster image pattern.
|
||||
Pattern(Pattern),
|
||||
}
|
||||
|
||||
/// The ID of a paint, unique to a scene.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct PaintId(pub u16);
|
||||
|
||||
/// The ID of a gradient, unique to a scene.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct GradientId(pub u32);
|
||||
|
||||
/// How a paint is to be composited over a base color, or vice versa.
|
||||
/// How an overlay is to be composited over a base color.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum PaintCompositeOp {
|
||||
/// The source that overlaps the destination, replaces the destination.
|
||||
SrcIn,
|
||||
/// Destination which overlaps the source, replaces the source.
|
||||
DestIn,
|
||||
}
|
||||
|
||||
|
@ -102,11 +116,13 @@ impl Palette {
|
|||
}
|
||||
|
||||
impl Paint {
|
||||
/// Creates a simple paint from a single base color.
|
||||
#[inline]
|
||||
pub fn from_color(color: ColorU) -> Paint {
|
||||
Paint { base_color: color, overlay: None }
|
||||
}
|
||||
|
||||
/// Creates a paint from a gradient.
|
||||
#[inline]
|
||||
pub fn from_gradient(gradient: Gradient) -> Paint {
|
||||
Paint {
|
||||
|
@ -118,6 +134,7 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a paint from a raster pattern.
|
||||
#[inline]
|
||||
pub fn from_pattern(pattern: Pattern) -> Paint {
|
||||
Paint {
|
||||
|
@ -129,16 +146,21 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// A convenience function to create a solid black paint.
|
||||
#[inline]
|
||||
pub fn black() -> Paint {
|
||||
Paint::from_color(ColorU::black())
|
||||
}
|
||||
|
||||
/// A convenience function to create a transparent paint with all channels set to zero.
|
||||
#[inline]
|
||||
pub fn transparent_black() -> Paint {
|
||||
Paint::from_color(ColorU::transparent_black())
|
||||
}
|
||||
|
||||
/// Returns true if this paint is obviously opaque, via a quick check.
|
||||
///
|
||||
/// Even if the paint is opaque, this function might return false.
|
||||
pub fn is_opaque(&self) -> bool {
|
||||
if !self.base_color.is_opaque() {
|
||||
return false;
|
||||
|
@ -155,6 +177,9 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this paint is fully transparent, via a quick check.
|
||||
///
|
||||
/// Even if the paint is fully transparent, this function might return false.
|
||||
pub fn is_fully_transparent(&self) -> bool {
|
||||
if !self.base_color.is_fully_transparent() {
|
||||
return false;
|
||||
|
@ -171,11 +196,15 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this paint represents a solid color.
|
||||
#[inline]
|
||||
pub fn is_color(&self) -> bool {
|
||||
self.overlay.is_none()
|
||||
}
|
||||
|
||||
/// Applies an affine transform to this paint.
|
||||
///
|
||||
/// This has no effect if this paint is a solid color.
|
||||
pub fn apply_transform(&mut self, transform: &Transform2F) {
|
||||
if transform.is_identity() {
|
||||
return;
|
||||
|
@ -189,26 +218,36 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the *base color* of this paint.
|
||||
///
|
||||
/// The base color is the color that goes underneath the gradient or pattern, if there is one.
|
||||
#[inline]
|
||||
pub fn base_color(&self) -> ColorU {
|
||||
self.base_color
|
||||
}
|
||||
|
||||
/// Changes the *base color* of this paint.
|
||||
///
|
||||
/// The base color is the color that goes underneath the gradient or pattern, if there is one.
|
||||
#[inline]
|
||||
pub fn set_base_color(&mut self, new_base_color: ColorU) {
|
||||
self.base_color = new_base_color;
|
||||
}
|
||||
|
||||
/// Returns the paint overlay, which is the portion of the paint on top of the base color.
|
||||
#[inline]
|
||||
pub fn overlay(&self) -> &Option<PaintOverlay> {
|
||||
&self.overlay
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the paint overlay, which is the portion of the paint on top
|
||||
/// of the base color.
|
||||
#[inline]
|
||||
pub fn overlay_mut(&mut self) -> &mut Option<PaintOverlay> {
|
||||
&mut self.overlay
|
||||
}
|
||||
|
||||
/// Returns the pattern, if this paint represents one.
|
||||
#[inline]
|
||||
pub fn pattern(&self) -> Option<&Pattern> {
|
||||
match self.overlay {
|
||||
|
@ -222,6 +261,7 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the pattern, if this paint represents one.
|
||||
#[inline]
|
||||
pub fn pattern_mut(&mut self) -> Option<&mut Pattern> {
|
||||
match self.overlay {
|
||||
|
@ -235,6 +275,7 @@ impl Paint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the gradient, if this paint represents one.
|
||||
#[inline]
|
||||
pub fn gradient(&self) -> Option<&Gradient> {
|
||||
match self.overlay {
|
||||
|
@ -251,18 +292,22 @@ impl Paint {
|
|||
|
||||
impl PaintOverlay {
|
||||
#[inline]
|
||||
pub fn contents(&self) -> &PaintContents {
|
||||
pub(crate) fn contents(&self) -> &PaintContents {
|
||||
&self.contents
|
||||
}
|
||||
|
||||
/// Returns the composite operation, which defines how the overlay is to be composited on top
|
||||
/// of the base color.
|
||||
#[inline]
|
||||
pub fn composite_op(&self) -> PaintCompositeOp {
|
||||
self.composite_op
|
||||
}
|
||||
|
||||
/// Changes the composite operation, which defines how the overlay is to be composited on top
|
||||
/// of the base color.
|
||||
#[inline]
|
||||
pub fn set_composite_op(&mut self, new_composite_op: PaintCompositeOp) {
|
||||
self.composite_op = new_composite_op
|
||||
self.composite_op = new_composite_op;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,10 +47,12 @@ pub struct Scene {
|
|||
epoch: SceneEpoch,
|
||||
}
|
||||
|
||||
/// A globally-unique identifier for the scene.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct SceneId(pub u32);
|
||||
|
||||
impl Scene {
|
||||
/// Creates a new empty scene.
|
||||
#[inline]
|
||||
pub fn new() -> Scene {
|
||||
let scene_id = SceneId(NEXT_SCENE_ID.fetch_add(1, Ordering::Relaxed) as u32);
|
||||
|
@ -66,10 +68,17 @@ impl Scene {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn push_draw_path(&mut self, draw_path: DrawPath) {
|
||||
/// Adds a path to the scene, to be drawn on top of all previously-added paths.
|
||||
///
|
||||
/// If a render target is on the stack (see `push_render_target()`), the path goes to the
|
||||
/// render target. Otherwise, it goes to the main output.
|
||||
///
|
||||
/// Returns an ID which can later be used to retrieve the path via `get_draw_path()`.
|
||||
pub fn push_draw_path(&mut self, draw_path: DrawPath) -> DrawPathId {
|
||||
let draw_path_index = DrawPathId(self.draw_paths.len() as u32);
|
||||
self.draw_paths.push(draw_path);
|
||||
self.push_draw_path_with_index(draw_path_index);
|
||||
draw_path_index
|
||||
}
|
||||
|
||||
fn push_draw_path_with_index(&mut self, draw_path_id: DrawPathId) {
|
||||
|
@ -85,6 +94,7 @@ impl Scene {
|
|||
self.epoch.next();
|
||||
}
|
||||
|
||||
/// Defines a clip path. Returns an ID that can be used to later clip draw paths.
|
||||
pub fn push_clip_path(&mut self, clip_path: ClipPath) -> ClipPathId {
|
||||
self.bounds = self.bounds.union_rect(clip_path.outline.bounds());
|
||||
let clip_path_id = ClipPathId(self.clip_paths.len() as u32);
|
||||
|
@ -93,6 +103,10 @@ impl Scene {
|
|||
clip_path_id
|
||||
}
|
||||
|
||||
/// Directs subsequent draw paths to draw to the given render target instead of the output.
|
||||
///
|
||||
/// Render targets form a stack. All `push_draw_path()` commands go to the render target at the
|
||||
/// top of the stack.
|
||||
pub fn push_render_target(&mut self, render_target: RenderTarget) -> RenderTargetId {
|
||||
let render_target_id = self.palette.push_render_target(render_target);
|
||||
self.display_list.push(DisplayItem::PushRenderTarget(render_target_id));
|
||||
|
@ -100,10 +114,17 @@ impl Scene {
|
|||
render_target_id
|
||||
}
|
||||
|
||||
/// Removes the most-recently-pushed render target from the top of the stack.
|
||||
///
|
||||
/// After calling this method, drawing will go to the previous render target. If no render
|
||||
/// targets remain on the stack, drawing goes to the main output.
|
||||
pub fn pop_render_target(&mut self) {
|
||||
self.display_list.push(DisplayItem::PopRenderTarget);
|
||||
}
|
||||
|
||||
/// Adds all elements in a scene to this one.
|
||||
///
|
||||
/// This includes draw paths, clip paths, render targets, and paints.
|
||||
pub fn append_scene(&mut self, scene: Scene) {
|
||||
let MergedPaletteInfo {
|
||||
render_target_mapping,
|
||||
|
@ -161,6 +182,8 @@ impl Scene {
|
|||
self.palette.build_paint_info(render_transform)
|
||||
}
|
||||
|
||||
/// Defines a new paint, which specifies how paths are to be filled or stroked. Returns a paint
|
||||
/// ID that can be later specified alongside draw paths.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn push_paint(&mut self, paint: &Paint) -> PaintId {
|
||||
let paint_id = self.palette.push_paint(paint);
|
||||
|
@ -168,22 +191,30 @@ impl Scene {
|
|||
paint_id
|
||||
}
|
||||
|
||||
/// Returns a rectangle that should enclose all objects in the scene.
|
||||
///
|
||||
/// FIXME(pcwalton): Is this really needed?
|
||||
#[inline]
|
||||
pub fn bounds(&self) -> RectF {
|
||||
self.bounds
|
||||
}
|
||||
|
||||
/// Sets a rectangle that should enclose all objects in the scene.
|
||||
///
|
||||
/// FIXME(pcwalton): Is this really needed?
|
||||
#[inline]
|
||||
pub fn set_bounds(&mut self, new_bounds: RectF) {
|
||||
self.bounds = new_bounds;
|
||||
self.epoch.next();
|
||||
}
|
||||
|
||||
/// Returns the view box, which defines the visible portion of the scene.
|
||||
#[inline]
|
||||
pub fn view_box(&self) -> RectF {
|
||||
self.view_box
|
||||
}
|
||||
|
||||
/// Changes the view box, which defines the visible portion of the scene.
|
||||
#[inline]
|
||||
pub fn set_view_box(&mut self, new_view_box: RectF) {
|
||||
self.view_box = new_view_box;
|
||||
|
@ -246,6 +277,11 @@ impl Scene {
|
|||
}
|
||||
}
|
||||
|
||||
/// Builds render commands necessary to render the scene and sends them to the `SceneSink`.
|
||||
///
|
||||
/// The given executor will be used to prepare these commands. Typically, this will be a
|
||||
/// `SequentialExecutor` to prepare commands on a single thread or `RayonExecutor` to prepare
|
||||
/// commands in parallel across multiple threads.
|
||||
#[inline]
|
||||
pub fn build<'a, 'b, E>(&mut self,
|
||||
options: BuildOptions,
|
||||
|
@ -257,42 +293,52 @@ impl Scene {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn display_list(&self) -> &[DisplayItem] {
|
||||
pub(crate) fn display_list(&self) -> &[DisplayItem] {
|
||||
&self.display_list
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn draw_paths(&self) -> &[DrawPath] {
|
||||
pub(crate) fn draw_paths(&self) -> &[DrawPath] {
|
||||
&self.draw_paths
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clip_paths(&self) -> &[ClipPath] {
|
||||
pub(crate) fn clip_paths(&self) -> &[ClipPath] {
|
||||
&self.clip_paths
|
||||
}
|
||||
|
||||
/// Returns the number of draw paths in this scene.
|
||||
#[inline]
|
||||
pub fn draw_path_count(&self) -> u32 {
|
||||
self.draw_paths.len() as u32
|
||||
}
|
||||
|
||||
/// Returns the draw path with the given ID.
|
||||
#[inline]
|
||||
pub fn get_draw_path(&self, draw_path_id: DrawPathId) -> &DrawPath {
|
||||
&self.draw_paths[draw_path_id.0 as usize]
|
||||
}
|
||||
|
||||
/// Returns the clip path with the given ID.
|
||||
#[inline]
|
||||
pub fn get_clip_path(&self, clip_path_id: ClipPathId) -> &ClipPath {
|
||||
&self.clip_paths[clip_path_id.0 as usize]
|
||||
}
|
||||
|
||||
/// Returns the paint with the given ID.
|
||||
#[inline]
|
||||
pub fn get_paint(&self, paint_id: PaintId) -> &Paint {
|
||||
self.palette.paints.get(paint_id.0 as usize).expect("No paint with that ID!")
|
||||
}
|
||||
|
||||
/// Returns the globally-unique ID of the scene.
|
||||
#[inline]
|
||||
pub fn id(&self) -> SceneId {
|
||||
self.id
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn epoch(&self) -> SceneEpoch {
|
||||
pub(crate) fn epoch(&self) -> SceneEpoch {
|
||||
self.epoch
|
||||
}
|
||||
|
||||
|
@ -328,6 +374,9 @@ impl Scene {
|
|||
}
|
||||
}
|
||||
|
||||
/// Receives render commands and delivers them to a `RenderCommandListener`.
|
||||
///
|
||||
/// Scene sinks wrap render command listeners with cached information about the previous scene.
|
||||
pub struct SceneSink<'a> {
|
||||
pub(crate) listener: RenderCommandListener<'a>,
|
||||
pub(crate) renderer_level: RendererLevel,
|
||||
|
@ -342,9 +391,9 @@ pub(crate) struct LastSceneInfo {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct SceneEpoch {
|
||||
pub hi: u64,
|
||||
pub lo: u64,
|
||||
pub(crate) struct SceneEpoch {
|
||||
pub(crate) hi: u64,
|
||||
pub(crate) lo: u64,
|
||||
}
|
||||
|
||||
impl SceneEpoch {
|
||||
|
@ -369,6 +418,7 @@ impl SceneEpoch {
|
|||
}
|
||||
|
||||
impl<'a> SceneSink<'a> {
|
||||
/// Creates a new scene sink from the given render command listener and level.
|
||||
#[inline]
|
||||
pub fn new(listener: RenderCommandListener<'a>, renderer_level: RendererLevel)
|
||||
-> SceneSink<'a> {
|
||||
|
@ -376,27 +426,47 @@ impl<'a> SceneSink<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A path drawn to the output or to a render target.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DrawPath {
|
||||
/// The actual vector path outline.
|
||||
pub outline: Outline,
|
||||
/// The ID of the paint that specifies how to fill the interior of this outline.
|
||||
pub paint: PaintId,
|
||||
/// The ID of an optional clip path that will be used to clip this path.
|
||||
pub clip_path: Option<ClipPathId>,
|
||||
/// How to fill this path (winding or even-odd).
|
||||
pub fill_rule: FillRule,
|
||||
/// How to blend this path with everything below it.
|
||||
pub blend_mode: BlendMode,
|
||||
/// The name of this path, for debugging.
|
||||
///
|
||||
/// Pass the empty string (which does not allocate) if debugging is not needed.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Describes a path that can be used to clip other paths.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClipPath {
|
||||
/// The actual vector path outline.
|
||||
pub outline: Outline,
|
||||
/// The ID of another, previously-defined, clip path that clips this one.
|
||||
///
|
||||
/// Nested clips can be achieved by clipping clip paths with other clip paths.
|
||||
pub clip_path: Option<ClipPathId>,
|
||||
/// How to fill this path (winding or even-odd).
|
||||
pub fill_rule: FillRule,
|
||||
/// The name of this clip path, for debugging.
|
||||
///
|
||||
/// Pass the empty string (which does not allocate) if debugging is not needed.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// The ID of a draw path, unique to a single scene.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct DrawPathId(pub u32);
|
||||
|
||||
/// The ID of a clip path, unique to a single scene.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct ClipPathId(pub u32);
|
||||
|
||||
|
@ -404,13 +474,18 @@ pub struct ClipPathId(pub u32);
|
|||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct PathId(pub u32);
|
||||
|
||||
/// A raster image target that can be rendered to and later reused as a pattern.
|
||||
///
|
||||
/// This can be useful for creating "stamps" or "symbols" that are rendered once and reused. It can
|
||||
/// also be useful for image effects that require many paths to be processed at once; e.g. opacity
|
||||
/// applied to a group of paths.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RenderTarget {
|
||||
size: Vector2I,
|
||||
name: String,
|
||||
}
|
||||
|
||||
/// Drawing commands.
|
||||
/// High-level drawing commands.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum DisplayItem {
|
||||
/// Draws paths to the render target on top of the stack.
|
||||
|
@ -424,6 +499,10 @@ pub enum DisplayItem {
|
|||
}
|
||||
|
||||
impl DrawPath {
|
||||
/// Creates a new draw path with the given outline and paint.
|
||||
///
|
||||
/// Initially, there is no clip path, the fill rule is set to winding, the blend mode is set to
|
||||
/// source-over, and the path has no name.
|
||||
#[inline]
|
||||
pub fn new(outline: Outline, paint: PaintId) -> DrawPath {
|
||||
DrawPath {
|
||||
|
@ -436,6 +515,7 @@ impl DrawPath {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the outline of this path, which defines its vector commands.
|
||||
#[inline]
|
||||
pub fn outline(&self) -> &Outline {
|
||||
&self.outline
|
||||
|
@ -446,6 +526,10 @@ impl DrawPath {
|
|||
self.clip_path
|
||||
}
|
||||
|
||||
/// Sets a previously-defined clip path that will be used to limit the filled region of this
|
||||
/// path.
|
||||
///
|
||||
/// Clip paths are defined in world space, not relative to the bounds of this path.
|
||||
#[inline]
|
||||
pub fn set_clip_path(&mut self, new_clip_path: Option<ClipPathId>) {
|
||||
self.clip_path = new_clip_path
|
||||
|
@ -461,6 +545,7 @@ impl DrawPath {
|
|||
self.fill_rule
|
||||
}
|
||||
|
||||
/// Sets the fill rule: even-odd or winding.
|
||||
#[inline]
|
||||
pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) {
|
||||
self.fill_rule = new_fill_rule
|
||||
|
@ -471,11 +556,14 @@ impl DrawPath {
|
|||
self.blend_mode
|
||||
}
|
||||
|
||||
/// Sets the blend mode, which specifies how this path will be composited with content
|
||||
/// underneath it.
|
||||
#[inline]
|
||||
pub fn set_blend_mode(&mut self, new_blend_mode: BlendMode) {
|
||||
self.blend_mode = new_blend_mode
|
||||
}
|
||||
|
||||
/// Assigns a name to this path, for debugging.
|
||||
#[inline]
|
||||
pub fn set_name(&mut self, new_name: String) {
|
||||
self.name = new_name
|
||||
|
@ -483,11 +571,16 @@ impl DrawPath {
|
|||
}
|
||||
|
||||
impl ClipPath {
|
||||
/// Creates a new clip path with the given outline.
|
||||
///
|
||||
/// Initially, there is no nested clip path, the fill rule is set to winding, and the clip path
|
||||
/// has no name.
|
||||
#[inline]
|
||||
pub fn new(outline: Outline) -> ClipPath {
|
||||
ClipPath { outline, clip_path: None, fill_rule: FillRule::Winding, name: String::new() }
|
||||
}
|
||||
|
||||
/// Returns the outline of this clip path, which defines its vector commands.
|
||||
#[inline]
|
||||
pub fn outline(&self) -> &Outline {
|
||||
&self.outline
|
||||
|
@ -498,6 +591,10 @@ impl ClipPath {
|
|||
self.clip_path
|
||||
}
|
||||
|
||||
/// Sets a nested clip path for this one by ID.
|
||||
///
|
||||
/// Draw paths can effectively be clipped by multiple paths by clipping one of the clip paths
|
||||
/// with the other, forming a chain of clips.
|
||||
#[inline]
|
||||
pub fn set_clip_path(&mut self, new_clip_path: Option<ClipPathId>) {
|
||||
self.clip_path = new_clip_path
|
||||
|
@ -508,11 +605,13 @@ impl ClipPath {
|
|||
self.fill_rule
|
||||
}
|
||||
|
||||
/// Sets the fill rule for this clip path: even-odd or winding.
|
||||
#[inline]
|
||||
pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) {
|
||||
self.fill_rule = new_fill_rule
|
||||
}
|
||||
|
||||
/// Assigns a name to this clip path, for debugging.
|
||||
#[inline]
|
||||
pub fn set_name(&mut self, new_name: String) {
|
||||
self.name = new_name
|
||||
|
@ -520,11 +619,16 @@ impl ClipPath {
|
|||
}
|
||||
|
||||
impl RenderTarget {
|
||||
/// Declares a new render target of the given device pixel size and with the given name for
|
||||
/// debugging.
|
||||
///
|
||||
/// Pass the empty string (which does not allocate) if a name is not needed.
|
||||
#[inline]
|
||||
pub fn new(size: Vector2I, name: String) -> RenderTarget {
|
||||
RenderTarget { size, name }
|
||||
}
|
||||
|
||||
/// Returns the device pixel size of this render target.
|
||||
#[inline]
|
||||
pub fn size(&self) -> Vector2I {
|
||||
self.size
|
||||
|
|
Loading…
Reference in New Issue