diff --git a/content/src/clip.rs b/content/src/clip.rs index d74d3960..b92abe52 100644 --- a/content/src/clip.rs +++ b/content/src/clip.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Clips polygons. + +#![allow(deprecated)] + use crate::outline::{Contour, ContourIterFlags, PointFlags, PushSegmentFlags}; use crate::segment::{CubicSegment, Segment}; use arrayvec::ArrayVec; @@ -310,16 +314,25 @@ enum EdgeRelativeLocation { // 3D quad clipping +/// Clips polygons in 3D homogeneous coordinates against the (-1, 1) normalized device coordinate +/// cube. +#[deprecated] pub struct PolygonClipper3D { subject: Vec, } impl PolygonClipper3D { + /// Creates a new polygon clipper with the vertices of the given polygon-to-be-clipped, in 3D + /// homogeneous coordinates. + #[deprecated] #[inline] pub fn new(subject: Vec) -> PolygonClipper3D { PolygonClipper3D { subject } } + /// Clips the subject polygon against the (-1, 1) normalized device coordinate cube and returns + /// the resulting vertices, in 3D homogeneous coordinates. + #[deprecated] pub fn clip(mut self) -> Vec { // TODO(pcwalton): Fast path for completely contained polygon? diff --git a/content/src/dash.rs b/content/src/dash.rs index 9c820a97..2a183dff 100644 --- a/content/src/dash.rs +++ b/content/src/dash.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Line dashing support. +//! Transforms a stroke into a dashed stroke. use crate::outline::{Contour, ContourIterFlags, Outline, PushSegmentFlags}; use std::mem; const EPSILON: f32 = 0.0001; +/// Transforms a stroke into a dashed stroke. pub struct OutlineDash<'a> { input: &'a Outline, output: Outline, @@ -22,17 +23,34 @@ pub struct OutlineDash<'a> { } impl<'a> OutlineDash<'a> { + /// Creates a new outline dasher for the given stroke. + /// + /// Arguments: + /// + /// * `input`: The input stroke to be dashed. This must not yet been converted to a fill; i.e. + /// it is assumed that the stroke-to-fill conversion happens *after* this dashing process. + /// + /// * `dashes`: The list of dashes, specified as alternating pixel lengths of lines and gaps + /// that describe the pattern. See + /// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash. + /// + /// * `offset`: The line dash offset, or "phase". See + /// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset. #[inline] pub fn new(input: &'a Outline, dashes: &'a [f32], offset: f32) -> OutlineDash<'a> { OutlineDash { input, output: Outline::new(), state: DashState::new(dashes, offset) } } + /// Performs the dashing operation. + /// + /// The results can be retrieved with the `into_outline()` method. pub fn dash(&mut self) { for contour in &self.input.contours { ContourDash::new(contour, &mut self.output, &mut self.state).dash() } } + /// Returns the resulting dashed outline. pub fn into_outline(mut self) -> Outline { if self.state.is_on() { self.output.push_contour(self.state.output); diff --git a/content/src/effects.rs b/content/src/effects.rs index e5db8f43..990b9f20 100644 --- a/content/src/effects.rs +++ b/content/src/effects.rs @@ -15,20 +15,28 @@ use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_geometry::vector::Vector2F; use pathfinder_simd::default::F32x2; -/// This intentionally does not precisely match what Core Graphics does (a -/// Lanczos function), because we don't want any ringing artefacts. +/// A defringing kernel for LCD screens that approximates the macOS/iOS look. +/// +/// This intentionally does not precisely match what Core Graphics does (a Lanczos function), +/// because we don't want any ringing artefacts. pub static DEFRINGING_KERNEL_CORE_GRAPHICS: DefringingKernel = DefringingKernel([0.033165660, 0.102074051, 0.221434336, 0.286651906]); + +/// A defringing kernel for LCD screens that approximates the FreeType look. pub static DEFRINGING_KERNEL_FREETYPE: DefringingKernel = DefringingKernel([0.0, 0.031372549, 0.301960784, 0.337254902]); +/// Stem darkening factors that approximate the macOS look. +/// /// Should match macOS 10.13 High Sierra. pub static STEM_DARKENING_FACTORS: [f32; 2] = [0.0121, 0.0121 * 1.25]; +/// The maximum number of pixels we are willing to expand outlines by to match the macOS look. +/// /// Should match macOS 10.13 High Sierra. 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. +/// A subjective cutoff. Above this ppem value, no stem darkening is performed. pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0; /// The shader that should be used when compositing this layer onto its destination. diff --git a/content/src/fill.rs b/content/src/fill.rs index e2941f17..f26f302e 100644 --- a/content/src/fill.rs +++ b/content/src/fill.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Fill rules. +//! The fill rule, which determines how self-intersecting paths are filled. +/// The fill rule, which determines how self-intersecting paths are filled. +/// +/// Paths that don't intersect themselves (and have no holes) are unaffected by the choice of fill +/// rule. #[derive(Clone, Copy, PartialEq, Debug)] pub enum FillRule { + /// The nonzero rule: https://en.wikipedia.org/wiki/Nonzero-rule Winding, + /// The even-odd rule: https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule EvenOdd, } diff --git a/content/src/gradient.rs b/content/src/gradient.rs index 05392e13..e475a16c 100644 --- a/content/src/gradient.rs +++ b/content/src/gradient.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Gradient effects that paths can be filled with. + use crate::util; use pathfinder_color::ColorU; use pathfinder_geometry::line_segment::LineSegment2F; diff --git a/content/src/pattern.rs b/content/src/pattern.rs index 43f88a8c..783a46fa 100644 --- a/content/src/pattern.rs +++ b/content/src/pattern.rs @@ -33,6 +33,7 @@ pub struct Pattern { flags: PatternFlags, } +/// Where a raster image pattern comes from. #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum PatternSource { Image(Image), @@ -42,9 +43,10 @@ pub enum PatternSource { } } -/// RGBA, non-premultiplied. +/// A raster image, in 32-bit RGBA (8 bits per channel), non-premultiplied form. // FIXME(pcwalton): Hash the pixel contents so that we don't have to compare every pixel! // TODO(pcwalton): Should the pixels be premultiplied? +// TODO(pcwalton): Color spaces. #[derive(Clone, PartialEq, Eq)] pub struct Image { size: Vector2I, @@ -58,9 +60,15 @@ pub struct Image { pub struct ImageHash(pub u64); bitflags! { + /// Various flags that determine behavior of a pattern. pub struct PatternFlags: u8 { + /// If set, the pattern repeats in the X direction. If unset, the base color is used. const REPEAT_X = 0x01; + /// If set, the pattern repeats in the Y direction. If unset, the base color is used. const REPEAT_Y = 0x02; + /// If set, nearest-neighbor interpolation is used when compositing this pattern (i.e. the + /// image will be pixelated). If unset, bilinear interpolation is used when compositing + /// this pattern (i.e. the image will be smooth). const NO_SMOOTHING = 0x04; } } @@ -76,26 +84,37 @@ impl Pattern { } } + /// Creates a new pattern from the given image. + /// + /// The transform is initialized to the identity transform. There is no filter. #[inline] pub fn from_image(image: Image) -> Pattern { Pattern::from_source(PatternSource::Image(image)) } + /// Creates a new pattern from the given render target with the given size. + /// + /// The transform is initialized to the identity transform. There is no filter. #[inline] pub fn from_render_target(id: RenderTargetId, size: Vector2I) -> Pattern { Pattern::from_source(PatternSource::RenderTarget { id, size }) } + /// Returns the affine transform applied to this pattern. #[inline] pub fn transform(&self) -> Transform2F { self.transform } + /// Applies the given transform to this pattern. + /// + /// The transform is applied after any existing transform. #[inline] pub fn apply_transform(&mut self, transform: Transform2F) { self.transform = transform * self.transform; } + /// Returns the underlying pixel size of this pattern, not taking transforms into account. #[inline] pub fn size(&self) -> Vector2I { match self.source { @@ -104,51 +123,72 @@ impl Pattern { } } + /// Returns the filter attached to this pattern, if any. #[inline] pub fn filter(&self) -> Option { self.filter } + /// Applies a filter to this pattern, replacing any previous filter if any. #[inline] pub fn set_filter(&mut self, filter: Option) { self.filter = filter; } + /// Returns true if this pattern repeats in the X direction or false if the base color will be + /// used when sampling beyond the coordinates of the image. #[inline] pub fn repeat_x(&self) -> bool { self.flags.contains(PatternFlags::REPEAT_X) } + /// Set to true if the pattern should repeat in the X direction or false if the base color + /// should be used when sampling beyond the coordinates of the image. #[inline] pub fn set_repeat_x(&mut self, repeat_x: bool) { self.flags.set(PatternFlags::REPEAT_X, repeat_x); } + /// Returns true if this pattern repeats in the Y direction or false if the base color will be + /// used when sampling beyond the coordinates of the image. #[inline] pub fn repeat_y(&self) -> bool { self.flags.contains(PatternFlags::REPEAT_Y) } + /// Set to true if the pattern should repeat in the Y direction or false if the base color + /// should be used when sampling beyond the coordinates of the image. #[inline] pub fn set_repeat_y(&mut self, repeat_y: bool) { self.flags.set(PatternFlags::REPEAT_Y, repeat_y); } + /// Returns true if this pattern should use bilinear interpolation (i.e. the image will be + /// smooth) when scaled or false if this pattern should use nearest-neighbor interpolation + /// (i.e. the image will be pixelated). #[inline] pub fn smoothing_enabled(&self) -> bool { !self.flags.contains(PatternFlags::NO_SMOOTHING) } + /// Set to true if the pattern should use bilinear interpolation (i.e. should be smooth) when + /// scaled or false if this pattern should use nearest-neighbor interpolation (i.e. should be + /// pixelated). #[inline] pub fn set_smoothing_enabled(&mut self, enable: bool) { self.flags.set(PatternFlags::NO_SMOOTHING, !enable); } + /// Returns true if this pattern is obviously fully opaque. + /// + /// This is a best-effort quick check, so it might return false even if the image is actually + /// opaque. #[inline] pub fn is_opaque(&self) -> bool { self.source.is_opaque() } + /// Returns the underlying source of the pattern. #[inline] pub fn source(&self) -> &PatternSource { &self.source @@ -156,6 +196,8 @@ impl Pattern { } impl Image { + /// Creates a new image with the given device pixel size and pixel store, as 32-bit RGBA (8 + /// bits per channel), RGBA, linear color space, nonpremultiplied. #[inline] pub fn new(size: Vector2I, pixels: Arc>) -> Image { assert_eq!(size.x() as usize * size.y() as usize, pixels.len()); @@ -168,6 +210,7 @@ impl Image { Image { size, pixels, pixels_hash, is_opaque } } + /// A convenience function to create a new image with the given image from the `image` crate. #[cfg(feature = "pf-image")] pub fn from_image_buffer(image_buffer: RgbaImage) -> Image { let (width, height) = image_buffer.dimensions(); @@ -175,21 +218,29 @@ impl Image { Image::new(vec2i(width as i32, height as i32), Arc::new(pixels)) } + /// Returns the device pixel size of the image. #[inline] pub fn size(&self) -> Vector2I { self.size } + /// Returns the pixel buffer of this image as 32-bit RGBA (8 bits per channel), RGBA, linear + /// color space, nonpremultiplied. #[inline] pub fn pixels(&self) -> &Arc> { &self.pixels } + /// Returns true if this image is obviously opaque. + /// + /// This is a best-guess quick check, and as such it might return false even if the image is + /// fully opaque. #[inline] pub fn is_opaque(&self) -> bool { self.is_opaque } + /// Returns a non-cryptographic hash of the image, which should be globally unique. #[inline] pub fn get_hash(&self) -> ImageHash { let mut hasher = DefaultHasher::new(); @@ -199,6 +250,10 @@ impl Image { } impl PatternSource { + /// Returns true if this pattern is obviously opaque. + /// + /// This is a best-guess quick check, and as such it might return false even if the pattern is + /// fully opaque. #[inline] pub fn is_opaque(&self) -> bool { match *self { diff --git a/content/src/segment.rs b/content/src/segment.rs index 1c2b1c1b..a5023a05 100644 --- a/content/src/segment.rs +++ b/content/src/segment.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Line or curve segments, optimized with SIMD. +//! Single line or Bézier curve segments, optimized with SIMD. use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_geometry::transform2d::Transform2F; @@ -17,15 +17,26 @@ use pathfinder_geometry::vector::{Vector2F, vec2f}; use pathfinder_simd::default::F32x4; use std::f32::consts::SQRT_2; +/// A single line or Bézier curve segment, with explicit start and end points. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Segment { + /// The start and end points of the curve. pub baseline: LineSegment2F, + /// The control point or points. + /// + /// If this is a line (which can be determined by examining the segment kind), this field is + /// ignored. If this is a quadratic Bézier curve, the start point of this line represents the + /// control point, and the endpoint of this line is ignored. Otherwise, if this is a cubic + /// Bézier curve, both the start and endpoints are used. pub ctrl: LineSegment2F, + /// The type of segment this is: invalid, line, quadratic, or cubic Bézier curve. pub kind: SegmentKind, + /// Various flags that describe information about this segment in a path. pub flags: SegmentFlags, } impl Segment { + /// Returns an invalid segment. #[inline] pub fn none() -> Segment { Segment { @@ -36,6 +47,7 @@ impl Segment { } } + /// Returns a segment representing a straight line. #[inline] pub fn line(line: LineSegment2F) -> Segment { Segment { @@ -226,12 +238,17 @@ impl Segment { } } +/// The type of line segment this is. #[derive(Clone, Copy, Debug, PartialEq)] #[repr(u8)] pub enum SegmentKind { + /// An invalid segment. None, + /// A line segment. Line, + /// A quadratic Bézier curve. Quadratic, + /// A cubic Bézier curve. Cubic, } diff --git a/renderer/src/options.rs b/renderer/src/options.rs index cc739cad..0b2bfc17 100644 --- a/renderer/src/options.rs +++ b/renderer/src/options.rs @@ -16,6 +16,8 @@ use pathfinder_geometry::rect::RectF; use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform3d::Perspective; use pathfinder_geometry::vector::{Vector2F, Vector4F}; + +#[allow(deprecated)] use pathfinder_content::clip::PolygonClipper3D; /// A sink for the render commands that scenes build. @@ -85,6 +87,7 @@ impl Default for RenderTransform { } impl RenderTransform { + #[allow(deprecated)] fn prepare(&self, bounds: RectF) -> PreparedRenderTransform { let perspective = match self { RenderTransform::Transform2D(ref transform) => {