This is a lightweight self-contained package that attempts to provide efficient drawing methods for some simple shapes. So far, in this package, all the shapes and drawing algorithms are integer-based, and all the drawing algorithms are single-threaded.
Background
Point
Line
ThickLine
Triangle
FilledTriangle
Rectangle
FilledRectangle
ThickRectangle
Circle
FilledCircle
ThickCircle
Bitmap
Image
Character
TextLine
import SimpleDraw as SD
# create a canvas (could be any AbstractMatrix)
image = falses(32, 32) # (height, width)
# create the shape
shape = SD.Line(SD.Point(9, 5), SD.Point(14, 19))
# we will draw on the boolean image with the "color" true
color = true
# draw the shape on image
SD.draw!(image, shape, color)
# print the boolean image using Unicode block characters
SD.visualize(image)
The following types are part of the API.
- All types in List of shapes
- The abstract type
AbstractShape
- The font constants
TERMINUS_16_8
,TERMINUS_BOLD_16_8
,TERMINUS_24_12
,TERMINUS_BOLD_24_12
,TERMINUS_32_16
,TERMINUS_BOLD_32_16
.
The following functions are part of the API:
draw!
is_valid
get_i_min
get_i_max
get_j_min
get_j_max
get_i_extrema
get_j_extrema
get_height
get_width
get_position
move_i
move_j
move
visualize
Everything else should be considered internal for now.
Being able to draw broadly requires three things:
image
: A canvas to draw on. It could be anyAbstractMatrix
.shape
: The geometric shape to be drawn. Note that primitiveshape
s can easily be composed to create more complexshape
s. For example,struct MyComplexShape{I <: Integer} <: SD.AbstractShape line::SD.Line{I} circle::SD.Circle{I} end
color
: The color to draw the shape with. This is what fills up the entries of theimage
matrix at appropriate positions, thereby drawing the geometric shape.
With this in mind, this package provides the draw!
function, which is commonly invoked as follows:
SD.draw!(image, shape, color)
Under the hood, it calls internal _draw!
methods that automatically take care of some basic optimizations (see Drawing optimizations). Then there are _draw!
methods of the form SD._draw!(f, image, shape, color)
that are heavily used internally. Here, f
can roughly be thought of as a drawing function applied to every pixel of the shape. This offers a lot of flexibility with the "brush-stroke" and significantly decreases code duplication. At the same time, it does not adversely affect performance. Most users will not need to use these methods directly, but in case you do, please look up the source code as their usage is not very well documented as of now.
By default, the draw!
function is safe, that is, it draws only those pixels of the shape that lie within the bounds of the image. So you don't have to worry about your program breaking even if it tries to draw something outside the bounds of the image
. That being said, certain basic optimizations are already enabled for drawing most shapes. See Drawing optimizations.
DrawingOptimizationStyle
is trait whose subtypes are used to define generic draw!
methods with different levels of optimization for drawing shapes:
PUT_PIXEL
: Iterate through all the positions needed to draw the shape. For each position, if it lies within the bounds of the image, put a pixel at that position else don't do anything.CHECK_BOUNDS
: If the shape lies completely outside the bounds of the image, simply returnnothing
. If it lies completely inside the bounds of the image, then draw each pixel of the shape without any further bounds checking. If it is neither of the previous cases, fall back to the slow but safe method of drawing each pixel of the shape only if it lies within the bounds of the image.CLIP
: Some shapes likeVerticalLine
,HorizontalLine
,FilledRectangle
can be direcly clipped into shapes that completely lie within the bounds of the image. In such cases, perform the clipping and draw the clipped shape without any further bounds checking.PUT_PIXEL_INBOUNDS
: Iterate through all the positions needed to draw the shape. For each position, put a pixel at that position assuming without any bounds checking image.
Use get_drawing_optimization_style(shape)
to get the default drawing optimization style for a shape. Shapes which do not fall within the above will implement custom draw!
methods with relevant optimizations.
The visualize
function helps in visualizing a boolean image directly inside the terminal. This is a quick and effective tool to verify whether a shape is being drawn as expected. This is extremely handy when you want to know about the exact coordinates of the pixels that are being drawn for a shape.
It uses Unicode block characters to represent a pixel. This works well for low resolution images. To visualize slightly higher resolution images, you can maximize your terminal window and reduce its font size.
Below are the benchmarks for v0.5.0
of this package:
julia> versioninfo()
Julia Version 1.8.5
Commit 17cfb8e65ea (2023-01-08 06:45 UTC)
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 12 × AMD Ryzen 5 6600H with Radeon Graphics
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, znver3)
Threads: 1 on 12 virtual cores
julia>
Timestamp: 2023_01_11_03_20_28 (yyyy_mm_dd_HH_MM_SS)
Shapes are drawn on an image of type Matrix{UInt32}
with a color of type UInt32
shape type | image height | image width | median time | memory | shape |
---|---|---|---|---|---|
Background | 64 | 64 | 121.069 ns | 0 bytes | SimpleDraw.Background() |
Background | 256 | 256 | 2.140 μs | 0 bytes | SimpleDraw.Background() |
Background | 1024 | 1024 | 59.781 μs | 0 bytes | SimpleDraw.Background() |
Point | 64 | 64 | 2.585 ns | 0 bytes | SimpleDraw.Point{Int64}(33, 33) |
Point | 256 | 256 | 2.334 ns | 0 bytes | SimpleDraw.Point{Int64}(129, 129) |
Point | 1024 | 1024 | 2.585 ns | 0 bytes | SimpleDraw.Point{Int64}(513, 513) |
Line | 64 | 64 | 70.601 ns | 0 bytes | SimpleDraw.Line{Int64}(SimpleDraw.Point{Int64}(9, 2), SimpleDraw.Point{Int64}(56, 63)) |
Line | 256 | 256 | 342.824 ns | 0 bytes | SimpleDraw.Line{Int64}(SimpleDraw.Point{Int64}(33, 2), SimpleDraw.Point{Int64}(224, 255)) |
Line | 1024 | 1024 | 1.470 μs | 0 bytes | SimpleDraw.Line{Int64}(SimpleDraw.Point{Int64}(129, 2), SimpleDraw.Point{Int64}(896, 1023)) |
ThickLine | 64 | 64 | 834.514 ns | 0 bytes | SimpleDraw.ThickLine{Int64}(SimpleDraw.Point{Int64}(9, 9), SimpleDraw.Point{Int64}(56, 56), 7) |
ThickLine | 256 | 256 | 49.472 μs | 0 bytes | SimpleDraw.ThickLine{Int64}(SimpleDraw.Point{Int64}(33, 33), SimpleDraw.Point{Int64}(224, 224), 31) |
ThickLine | 1024 | 1024 | 1.273 ms | 0 bytes | SimpleDraw.ThickLine{Int64}(SimpleDraw.Point{Int64}(129, 129), SimpleDraw.Point{Int64}(896, 896), 127) |
Triangle | 64 | 64 | 185.163 ns | 0 bytes | SimpleDraw.Triangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(63, 32), SimpleDraw.Point{Int64}(32, 63)) |
Triangle | 256 | 256 | 749.029 ns | 0 bytes | SimpleDraw.Triangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(255, 128), SimpleDraw.Point{Int64}(128, 255)) |
Triangle | 1024 | 1024 | 4.349 μs | 0 bytes | SimpleDraw.Triangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(1023, 512), SimpleDraw.Point{Int64}(512, 1023)) |
FilledTriangle | 64 | 64 | 433.065 ns | 0 bytes | SimpleDraw.FilledTriangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(63, 32), SimpleDraw.Point{Int64}(32, 63)) |
FilledTriangle | 256 | 256 | 2.377 μs | 0 bytes | SimpleDraw.FilledTriangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(255, 128), SimpleDraw.Point{Int64}(128, 255)) |
FilledTriangle | 1024 | 1024 | 28.884 μs | 0 bytes | SimpleDraw.FilledTriangle{Int64}(SimpleDraw.Point{Int64}(2, 2), SimpleDraw.Point{Int64}(1023, 512), SimpleDraw.Point{Int64}(512, 1023)) |
Rectangle | 64 | 64 | 56.104 ns | 0 bytes | SimpleDraw.Rectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 63, 63) |
Rectangle | 256 | 256 | 908.600 ns | 0 bytes | SimpleDraw.Rectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 255, 255) |
Rectangle | 1024 | 1024 | 9.859 μs | 0 bytes | SimpleDraw.Rectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1023, 1023) |
FilledRectangle | 64 | 64 | 518.203 ns | 0 bytes | SimpleDraw.FilledRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 63, 63) |
FilledRectangle | 256 | 256 | 3.588 μs | 0 bytes | SimpleDraw.FilledRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 255, 255) |
FilledRectangle | 1024 | 1024 | 49.322 μs | 0 bytes | SimpleDraw.FilledRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1023, 1023) |
ThickRectangle | 64 | 64 | 841.000 ns | 0 bytes | SimpleDraw.ThickRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 63, 63, 16) |
ThickRectangle | 256 | 256 | 3.241 μs | 0 bytes | SimpleDraw.ThickRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 255, 255, 64) |
ThickRectangle | 1024 | 1024 | 53.329 μs | 0 bytes | SimpleDraw.ThickRectangle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1023, 1023, 256) |
Circle | 64 | 64 | 95.229 ns | 0 bytes | SimpleDraw.Circle{Int64}(SimpleDraw.Point{Int64}(2, 2), 62) |
Circle | 256 | 256 | 366.939 ns | 0 bytes | SimpleDraw.Circle{Int64}(SimpleDraw.Point{Int64}(2, 2), 254) |
Circle | 1024 | 1024 | 3.228 μs | 0 bytes | SimpleDraw.Circle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1022) |
FilledCircle | 64 | 64 | 608.218 ns | 0 bytes | SimpleDraw.FilledCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 62) |
FilledCircle | 256 | 256 | 3.966 μs | 0 bytes | SimpleDraw.FilledCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 254) |
FilledCircle | 1024 | 1024 | 52.016 μs | 0 bytes | SimpleDraw.FilledCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1022) |
ThickCircle | 64 | 64 | 923.326 ns | 0 bytes | SimpleDraw.ThickCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 62, 16) |
ThickCircle | 256 | 256 | 24.506 μs | 0 bytes | SimpleDraw.ThickCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 254, 64) |
ThickCircle | 1024 | 1024 | 1.730 ms | 0 bytes | SimpleDraw.ThickCircle{Int64}(SimpleDraw.Point{Int64}(2, 2), 1022, 256) |
Bitmap | 64 | 64 | 4.490 μs | 0 bytes | SimpleDraw.Bitmap{Int64, BitMatrix}(SimpleDraw.Point{Int64}(2, 2), Bool[1 0 … 1 0; 0 1 … 0 1; … ; 1 0 … 1 0; 0 1 … 0 1]) |
Bitmap | 256 | 256 | 71.583 μs | 0 bytes | SimpleDraw.Bitmap{Int64, BitMatrix}(SimpleDraw.Point{Int64}(2, 2), Bool[1 0 … 1 0; 0 1 … 0 1; … ; 1 0 … 1 0; 0 1 … 0 1]) |
Bitmap | 1024 | 1024 | 1.181 ms | 0 bytes | SimpleDraw.Bitmap{Int64, BitMatrix}(SimpleDraw.Point{Int64}(2, 2), Bool[1 0 … 1 0; 0 1 … 0 1; … ; 1 0 … 1 0; 0 1 … 0 1]) |
Image | 64 | 64 | 2.285 μs | 0 bytes | SimpleDraw.Image{Int64, Matrix{UInt32}}(SimpleDraw.Point{Int64}(2, 2), UInt32[0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001; … ; 0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001]) |
Image | 256 | 256 | 38.742 μs | 0 bytes | SimpleDraw.Image{Int64, Matrix{UInt32}}(SimpleDraw.Point{Int64}(2, 2), UInt32[0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001; … ; 0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001]) |
Image | 1024 | 1024 | 814.004 μs | 0 bytes | SimpleDraw.Image{Int64, Matrix{UInt32}}(SimpleDraw.Point{Int64}(2, 2), UInt32[0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001; … ; 0x00000001 0x00000000 … 0x00000001 0x00000000; 0x00000000 0x00000001 … 0x00000000 0x00000001]) |
Character | 64 | 64 | 873.814 ns | 0 bytes | SimpleDraw.Character{Int64, Char, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(2, 2), 'A', SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
Character | 256 | 256 | 874.355 ns | 0 bytes | SimpleDraw.Character{Int64, Char, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(2, 2), 'A', SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
Character | 1024 | 1024 | 881.478 ns | 0 bytes | SimpleDraw.Character{Int64, Char, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(2, 2), 'A', SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
TextLine | 64 | 64 | 3.548 μs | 0 bytes | SimpleDraw.TextLine{Int64, String, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(1, 1), "BUDB", SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
TextLine | 256 | 256 | 14.377 μs | 0 bytes | SimpleDraw.TextLine{Int64, String, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(1, 1), "ZZPEKEEOUGIIHKGY", SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
TextLine | 1024 | 1024 | 58.398 μs | 0 bytes | SimpleDraw.TextLine{Int64, String, SimpleDraw.MonospaceBitmapASCIIFont}(SimpleDraw.Point{Int64}(1, 1), "ZBXMZBNLSOTGROCLZJTOONNIEIFUOLCSLIUTYUGDMIEWKIWMYJLOPHGYPLTWBIDF", SimpleDraw.MonospaceBitmapASCIIFont([0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; … ;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0;;; 0 0 … 0 0; 0 0 … 0 0; … ; 0 0 … 0 0; 0 0 … 0 0])) |
Follow these steps to generate benchmarks. Take care to double-check the version of the package you are benchmarking:
-
Clone the project
$ git clone https://github.com/Sid-Bhatia-0/SimpleDraw.jl.git
-
Start the julia REPL inside the
/benchmark
directorybenchmark $ julia
-
Activate and instantiate the project
julia> import Pkg; Pkg.activate("."); Pkg.instantiate()
-
Exit the REP and run
generate_benchmarks.jl
with theProject.toml
andManifest.toml
files in this directorybenchmark $ julia --project=. generate_benchmarks.jl
This will print a bunch of outputs and produce a markdown file named with a timestamp containing the final benchmarks. Using a timestamp in the name helps ensure that running generate_benchmarks.jl
multiple times does not overwrite the same file.
-
struct Background <: AbstractShape end
-
struct Point{I <: Integer} <: AbstractShape i::I j::I end
-
struct Line{I <: Integer} <: AbstractLine point1::Point{I} point2::Point{I} end
Line(point1, point2)
will draw the same thing asLine(point2, point1)
as they are always sorted internally. But note that the visual representation of the line may not symmetric with respect to the end points in general. -
struct ThickLine{I <: Integer} <: AbstractLine point1::Point{I} point2::Point{I} thickness::I end
An instance of
ThickLine
is considered valid only if the following conditions hold true:thickness > 0
-
struct Triangle{I <: Integer} <: AbstractTriangle point1::Point{I} point2::Point{I} point3::Point{I} end
-
struct FilledTriangle{I <: Integer} <: AbstractTriangle point1::Point{I} point2::Point{I} point3::Point{I} end
-
struct Rectangle{I <: Integer} <: AbstractRectangle position::Point{I} height::I width::I end
An instance of
Rectangle
is considered valid only if the following conditions hold true:height > 0
width > 0
-
struct FilledRectangle{I <: Integer} <: AbstractRectangle position::Point{I} height::I width::I end
An instance of
FilledRectangle
is considered valid only if the following conditions hold true:height > 0
width > 0
-
struct ThickRectangle{I <: Integer} <: AbstractRectangle position::Point{I} height::I width::I thickness::I end
An instance of
ThickRectangle
is considered valid only if the following conditions hold true:height > 0
width > 0
thickness > 0
thickness <= min(height, width)
-
struct Circle{I <: Integer} <: AbstractCircle position::Point{I} diameter::I end
An instance of
Circle
is considered valid only if the following conditions hold true:diameter > 0
-
struct FilledCircle{I <: Integer} <: AbstractCircle position::Point{I} diameter::I end
An instance of
FilledCircle
is considered valid only if the following conditions hold true:diameter > 0
-
struct ThickCircle{I <: Integer} <: AbstractCircle position::Point{I} diameter::I thickness::I end
An instance of
ThickCircle
is considered valid only if the following conditions hold true:diameter > 0
thickness > 0
- if
diameter
is odd, then2 * thickness <= diameter + 1
- if
diameter
is even, then2 * thickness <= diameter
-
struct Bitmap{I <: Integer, B <: AbstractMatrix{Bool}} <: AbstractShape position::Point{I} bitmap::B end
Can be used to draw a 1-bit image using some color on an image. For example, it is used for drawing character glyphs in
Character
orTextLine
. -
struct Image{I <: Integer, A} <: AbstractShape position::Point{I} image::A end
Can be used to draw an existing image on top of an image at some position. No need to pass color explicitly, the sub-image should already be colored. Whereas in
Bitmap
, one needs to pass color explicitly and it can only be of a single color. -
struct Character{I <: Integer, C <: AbstractChar, F <: AbstractFont} <: AbstractShape position::Point{I} character::C font::F end
There are 6 monospace ASCII fonts are available at this point:
TERMINUS_16_8
(height 16 pixels, width 8 pixels)TERMINUS_BOLD_16_8
(height 16 pixels, width 8 pixels)TERMINUS_24_12
(height 24 pixels, width 12 pixels)TERMINUS_BOLD_24_12
(height 24 pixels, width 12 pixels)TERMINUS_32_16
(height 32 pixels, width 16 pixels)TERMINUS_BOLD_32_16
(height 32 pixels, width 16 pixels)
Only glyphs for ASCII characters are available as of now.
-
struct TextLine{I <: Integer, S, F <: AbstractFont} <: AbstractShape position::Point{I} text::S font::F end
There are 6 monospace ASCII fonts are available at this point:
TERMINUS_16_8
(height 16 pixels, width 8 pixels)TERMINUS_BOLD_16_8
(height 16 pixels, width 8 pixels)TERMINUS_24_12
(height 24 pixels, width 12 pixels)TERMINUS_BOLD_24_12
(height 24 pixels, width 12 pixels)TERMINUS_32_16
(height 32 pixels, width 16 pixels)TERMINUS_BOLD_32_16
(height 32 pixels, width 16 pixels)
Only glyphs for ASCII characters are available as of now.
- Octant drawing: https://en.wikipedia.org/w/index.php?title=Midpoint_circle_algorithm&oldid=1073593456
- Line drawing: https://en.wikipedia.org/w/index.php?title=Bresenham%27s_line_algorithm&oldid=1073834153
- Fonts: This package supports bitmap fonts for ASCII characters at this point. We use a subset of Terminus Font for drawing the glyphs. Terminus Font is licensed under the SIL Open Font License, Version 1.1. The license is included as OFL.TXT in the
/src/fonts
directory in this repository, and is also available with a FAQ at http://scripts.sil.org/OFL. - Everything else is under LICENSE.