Fork of Pixie for nimskull and with extra features
Go to file
2021-05-11 22:40:40 -05:00
.github/workflows
docs 1.1.2: Update deps and docs. 2021-03-26 14:10:11 -07:00
examples text examples 2021-05-11 22:40:40 -05:00
experiments runs 2021-03-03 15:18:20 -06:00
src f 2021-05-11 22:40:40 -05:00
tests f 2021-05-11 22:40:39 -05:00
tools text examples 2021-05-11 22:40:40 -05:00
.gitignore
LICENSE
pixie.nimble svg fonts + move stuff around 2021-05-11 22:40:24 -05:00
README.md text examples 2021-05-11 22:40:40 -05:00

Pixie - A full-featured 2D graphics library for Nim

Pixie is a 2D graphics library similar to Cairo and Skia written (almost) entirely in Nim.

This library is being actively developed and we'd be happy for you to use it.

nimble install pixie

Features:

  • Drawing paths, shapes and curves with even-odd and non-zero windings.
  • Pixel-perfect AA quality.
  • Supported file formats are PNG, BMP, JPG, SVG + more in development.
  • Strokes with joins and caps.
  • Shadows, glows and blurs.
  • Complex masking: Subtract, Intersect, Exclude.
  • Complex blends: Darken, Multiply, Color Dodge, Hue, Luminosity... etc.
  • Many operations are SIMD accelerated where possible.

Documentation

API reference: https://treeform.github.io/pixie/pixie.html

File formats

Format Read Write
PNG
JPEG
BMP
GIF
SVG

Joins and caps

Supported Caps:

  • Butt
  • Round
  • Square

Supported Joins:

  • Miter (with miter angle limit)
  • Bevel
  • Round

Blending & masking

Supported Blend Modes:

  • Normal
  • Darken
  • Multiply
  • ColorBurn
  • Lighten
  • Screen
  • Color Dodge
  • Overlay
  • Soft Light
  • Hard Light
  • Difference
  • Exclusion
  • Hue
  • Saturation
  • Color
  • Luminosity

Supported Mask Modes:

  • Mask
  • Overwrite
  • Subtract Mask
  • Intersect Mask
  • Exclude Mask

SVG style paths:

Format Supported Description
M,m move to
L,l line to
h,h horizontal line to
V,v vertical line to
C,c,S,s cublic to
Q,q,T,t quadratic to
A,a arc to
z close path

Testing

nimble test

Examples

Text

examples/text.nim

var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
font.size = 20

let text = "Typesetting is the arrangement and composition of text in graphic design and publishing in both digital and traditional medias."

image.fillText(font.typeset(text, bounds = vec2(180, 180)), vec2(10, 10))

example output

Text spans

examples/text_spans.nim

let font = readFont("tests/fonts/Ubuntu-Regular_1.ttf")

var style1 = font
style1.size = 12
style1.paint.color = rgba(200, 200, 200, 255)

var style2 = font
style2.size = 36
style2.paint.color = rgba(0, 0, 0, 255)

var style3 = font
style3.size = 13
style3.paint.color = rgba(0, 127, 244, 255)

var style4 = font
style4.size = 14
style4.paint.color = rgba(80, 80, 80, 255)

let spans = @[
  newSpan("verb [with object] ", style1),
  newSpan("strallow\n", style2),
  newSpan("\nstral·low\n", style3),
  newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ", style4)
]

image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))

example output

Square

examples/square.nim

let
  pos = vec2(50, 50)
  wh = vec2(100, 100)

image.fillRect(rect(pos, wh), rgba(255, 0, 0, 255))

example output

Line

examples/line.nim

let
  start = vec2(25, 25)
  stop = vec2(175, 175)
  color = parseHtmlColor("#FF5C00").rgba

image.strokeSegment(segment(start, stop), color, strokeWidth = 10)

example output

Rounded rectangle

examples/rounded_rectangle.nim

let
  pos = vec2(50, 50)
  wh = vec2(100, 100)
  r = 25.0

image.fillRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255))

example output

Heart

examples/heart.nim

image.fillPath(
  """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
  """,
  parseHtmlColor("#FC427B").rgba
)

example output

Masking

examples/masking.nim

lines.strokeSegment(
  segment(vec2(25, 25), vec2(175, 175)), color, strokeWidth = 30)
lines.strokeSegment(
  segment(vec2(25, 175), vec2(175, 25)), color, strokeWidth = 30)

mask.fillPath(
  """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
  """
)
lines.draw(mask)
image.draw(lines)

example output

Gradient

examples/gradient.nim

let paint = Paint(
  kind: pkGradientRadial,
  gradientHandlePositions: @[
    vec2(100, 100),
    vec2(200, 100),
    vec2(100, 200)
  ],
  gradientStops: @[
    ColorStop(color: rgba(255, 0, 0, 255), position: 0),
    ColorStop(color: rgba(255, 0, 0, 40), position: 1.0),
  ]
)

image.fillPath(
  """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
  """,
  paint
)

example output

Image tiled

examples/image_tiled.nim

var path: Path
path.polygon(
  vec2(100, 100),
  70,
  sides = 8
)
image.fillPath(
  path,
  Paint(
    kind: pkImageTiled,
    image: readImage("tests/images/png/baboon.png"),
    imageMat: scale(vec2(0.08, 0.08))
  )
)

example output

Shadow

examples/shadow.nim

let polygonImage = newImage(200, 200)
polygonImage.fillPolygon(
  vec2(100, 100),
  70,
  sides = 8,
  rgba(255, 255, 255, 255)
)

let shadow = polygonImage.shadow(
  offset = vec2(2, 2),
  spread = 2,
  blur = 10,
  color = rgba(0, 0, 0, 200)
)

image.draw(shadow)
image.draw(polygonImage)

example output

Blur

examples/blur.nim

let mask = newMask(200, 200)
mask.fillPolygon(vec2(100, 100), 70, sides = 6)

blur.blur(20)
blur.draw(mask, blendMode = bmMask)

image.draw(trees)
image.draw(blur)

example output

Tiger

examples/tiger.nim

let tiger = readImage("examples/data/tiger.svg")

image.draw(
  tiger,
  translate(vec2(100, 100)) *
  scale(vec2(0.2, 0.2)) *
  translate(vec2(-450, -450))
)

example output