All Projects → DougLau → footile

DougLau / footile

Licence: Apache-2.0, MIT licenses found Licenses found Apache-2.0 LICENSE-APACHE MIT LICENSE-MIT
A 2D vector graphics library written in Rust

Programming Languages

rust
11053 projects

Projects that are alternatives of or similar to footile

vector2d
2D Vector Library. Operates using Objects, Array or Float32Array types to allow flexible performance.
Stars: ✭ 28 (-12.5%)
Mutual labels:  vector, 2d
Synfig
This is the Official source code repository of the Synfig project
Stars: ✭ 1,056 (+3200%)
Mutual labels:  vector, 2d
vecti
A tiny TypeScript library for 2D vector math.
Stars: ✭ 14 (-56.25%)
Mutual labels:  vector, 2d
Svg.skia
An SVG rendering library.
Stars: ✭ 122 (+281.25%)
Mutual labels:  vector, 2d
Vkvg
Vulkan 2D graphics library
Stars: ✭ 394 (+1131.25%)
Mutual labels:  vector, 2d
Plutovg
Tiny 2D vector graphics library in C
Stars: ✭ 141 (+340.63%)
Mutual labels:  vector, 2d
Gdal
GDAL is an open source X/MIT licensed translator library for raster and vector geospatial data formats.
Stars: ✭ 2,797 (+8640.63%)
Mutual labels:  vector
Blasjs
Pure Javascript manually written 👌 implementation of BLAS, Many numerical software applications use BLAS computations, including Armadillo, LAPACK, LINPACK, GNU Octave, Mathematica, MATLAB, NumPy, R, and Julia.
Stars: ✭ 241 (+653.13%)
Mutual labels:  vector
Earthenterprise
Google Earth Enterprise - Open Source
Stars: ✭ 2,425 (+7478.13%)
Mutual labels:  vector
Pymilvus
Python SDK for Milvus.
Stars: ✭ 199 (+521.88%)
Mutual labels:  vector
elm-3d-camera
Camera type for doing 3D rendering in Elm
Stars: ✭ 12 (-62.5%)
Mutual labels:  vector
PyGLM
Fast OpenGL Mathematics (GLM) for Python
Stars: ✭ 167 (+421.88%)
Mutual labels:  vector
Earthpy
A package built to support working with spatial data using open source python
Stars: ✭ 236 (+637.5%)
Mutual labels:  vector
Twitterlaunchanimation
The library with Twitter-like launch animation
Stars: ✭ 221 (+590.63%)
Mutual labels:  vector
Flutter Icons
Customizable Icons for Flutter 💥
Stars: ✭ 241 (+653.13%)
Mutual labels:  vector
Android Animation Set
📚 Android 所有动画系列详尽教程。 Explain all animations in Android.
Stars: ✭ 2,452 (+7562.5%)
Mutual labels:  vector
cogj-spec
Cloud Optimized GeoJSON spec
Stars: ✭ 36 (+12.5%)
Mutual labels:  vector
Gophers
Free gophers
Stars: ✭ 2,542 (+7843.75%)
Mutual labels:  vector
Staticvec
Implements a fixed-capacity stack-allocated Vec alternative backed by an array, using const generics.
Stars: ✭ 236 (+637.5%)
Mutual labels:  vector
powerpaint
Kreative PowerPaint - Library and Application for Bitmap and Vector Image Editing
Stars: ✭ 27 (-15.62%)
Mutual labels:  vector

footile

A 2D vector graphics library written in Rust. It uses pix for the underlying raster images.

See the documentation for examples and API usage.

Rasterizing: Bird's Eye View

There is nothing novel here — this is merely a guide to the code.

We have a 2D path made up of lines, bézier splines, arcs, etc., and we want to make a high-quality raster image out of it. But how?

Modules

  • path: Defines path operations and Path2Ds
  • plotter: Defines Plotter struct and flattens curves
  • stroker: Creates stroked paths for plotter
  • fixed: Defines Fixed struct used by fig module
  • fig: Rasterizes paths

Curve Flattening

Flattening refers to approximating a curve with a series of line segments.

We use the recursive algorithm described by De Casteljau. There might be opportunities for optimization here if we ever determine this is a bottleneck. One other thing to note: this method could cause a stack overflow with the wrong input data.

Once complete, we have a series of line segments forming one or more closed polygons.

Sorting Vertices

For the next step, we create a sorted list of the vertices in (Y, X) order. This is needed because we will scan the polygon onto a grid one row at a time.

Every path has a winding order: either clockwise or the other direction, typically called counter- or anti-clockwise. Let's avoid that debate by calling it widdershins, since clocks rarely go backwards.

The first vertex must be on the outside of the path, so we can check the angle between its neighbors to determine the winding order.

Active Edges

As rows are scanned from top to bottom, we keep track of a list of active edges. If an edge crosses the current row, it is added to the list, otherwise, it is removed. Since horizontal edges cannot cross a row, they can safely be ignored.

For each row, vertices from the list are compared to its top and bottom. If the new vertex is above the bottom, one or more edges are added. When the new vertex is above the top, existing edges are removed.

           v0
           /\
          /  \ (a)
         /    \      v2
    (b) /      +-----+
       /      v1      \
      /                \ (c)
     /                  \
    +--------------------+
     v3                  v4

Example:

  • Starting with v0, add edges (a) and (b)
  • Scan until the bottom of the current row is below v1 / v2
  • Add edge (c)
  • Scan until the row top is below v1
  • Remove edge (a)
  • Scan until the row top is below v3 / v4
  • Remove edges (b) and (c)

Signed Area

The active edges are used to find the signed area at any point. Count the number of edge crossings needed to reach the exterior of the path. For example:

    +------+
    |      |
    |  +1  |
    |      |
    +------+

A self-intersecting polygon looks like this:

    +-----------------+
    |                 |
    |      +------+   |
    |      |       \ /
    |  +1  |  +2    X
    |      |       / \
    |      +------+   |
    |                 |
    +-----------------+

What about sub-paths with opposite winding order? In that case, subtract instead of adding:

    +----------------+
    |      +-----+   |
    |      |     |   |
    |  +1  |  0  |   |
    |      |     |   |
    |      +-----+   |
    |        <--     |
    |                |
    +----------------+
          -->

Scanning Rows

When scanning a row, the signed area is sampled for each pixel. The direction of each edge from top to bottom determines whether it adds to or subtracts from the area. In the normal winding order, it adds to the area; otherwise, it subtracts.

This row is 4 pixels wide:

      -  -  - | -  -  -   -  -  - | -  -  -
    |         |         |         |         |
              | +1                | -1
    |         |         |         |         |
              |                   |      
    | -  -  - | -  -  - | -  -  - | -  -  - |
          0         1         1         0

The cumulative sum of these values is the signed area of each pixel.

Anti-Aliasing

Sometimes edges don't fall on pixel boundaries. In this case, the trick is to use fractional numbers for anti-aliasing.

      -  -  - | -  |  -   -  -  -   -  -  -
    |         |    |    |         |         |
              | +1 | -½   -½
    |         |    |    |         |         |
              |    |                     
    | -  -  - | -  |  - | -  -  - | -  -  - |
          0         ½         0         0

Notice how the remainder of the second edge coverage is added to the pixel to the right (third pixel). This is necessary to keep the cumulative sum correct.

      -  -  - | -  \  -   -  -  -   -  -  -
    |         |     \   |         |         |
              | +1   \-¼  -¾
    |         |       \ |         |         |
              |        \
    | -  -  - | -  -  - \ -  -  - | -  -  - |
          0         ¾         0         0

Compositing

The signed area buffer can be composited with a raster, using a source color.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].