scany

package module
v0.0.0-...-69e1887 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 17, 2022 License: MIT Imports: 6 Imported by: 0

README

scany

About

The scany package is a denovo implementation the CL-AA antigrain algorithm in both a single thread or multi-threaded structure by ScanS and ScanT, respectivly. Both implement the rasterx.Scanner interface, and therefore they can be used with the rasterx and oksvg. The single threaded ScanS is vitually as fast as the ScanFT structure implemented in github.com/swiley/scanFT. Benchmarks vary a bit from run to run but ScanS appears to be within 1 or 2 percent as fast as ScanFT. The difference is that ScanFT is under the Freetype license, since it is a direct port from the C implementation of Freetype. while ScanS and ScanT are under the less restrictive MIT3 license, so they can be freely incoporated in commercial as well as open source projects.

If ScanT is run using a thread count of one it is around 10% slower than ScanFT or ScanS. However, as additional threads are added it will exceed the speed of the single thread implementations. At what point this occurs, depends on the image being rendered. SVG's with gradients, for example, particularly benefit from using multiple threads. Also note that number of threads specified may exceed the number of available CPU cores and still increase speed on some machines, while on others it may max out, so experimentation to determine the optimal thread number is advised.

Instead of the Painter interface used by Freetype to translate x y coordinates and alpha values to various image formats, scanY uses the scany.Collector interface. A Collector for the image.RGBA format is provided in the scany package. Collectors for additional formats may be provided by the user.

How to use

To use the ScanS single threaded antialiaser with oksvg do the following:

img := image.NewRGBA(image.Rect(0, 0, width, height))
collector := &scany.RGBACollector{Image: img}
scanner := scany.NewScanS(width, height, collector)
raster := rasterx.NewDasher(w, h, scanner)
icon.Draw(raster, 1.0) // icon is an oksvg.Icon

Similarly to use the ScanT multi-threaded antialiaser do:

threadCount := 6
img := image.NewRGBA(image.Rect(0, 0, width, height))
collector := &scany.RGBACollector{Image: img}
scanner := scany.NewScanT(threadCount, width, height, collector)
raster := rasterx.NewDasher(w, h, scanner)
icon.Draw(raster, 1.0) // icon is an oksvg.Icon

All threads are started when the NewScanT method is called. There are three types of threads handling various steps of the CL-AA algorithm. One type breaks lines into cell sized segments, one calculates the cover and area, and places them into a linked list. Once these complete, the last type of thread sweeps the linked list scan lines, and adds the x, y alpha values to the target image format using the Collector. When a thread count of one is specified, one of each thread type is created. Similarly if a thead count of six is used, six of each type of thread are created. The threads can be shut down by executing:

scanner.Close()

For an explanation of the CL-AA algorithm, see the cl-vectors file in the docs folder taken from projects.tuxee.net. See the test files for additional examples and benchmarks.

example

Thanks to Freepik from Flaticon Licensed by Creative Commons 3.0 for the test icons used in the testdata/svg/landscapeIcons folder.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cell

type Cell struct {
	// contains filtered or unexported fields
}

Used as entries in the scanLinks linked list

type CellM

type CellM struct {
	AreaOvCov int
	// contains filtered or unexported fields
}

Used to message cells via the channels

type CellWorker

type CellWorker struct {
	// contains filtered or unexported fields
}

CellWorker listends to cellChan to store cell cover and area values into the scanLines linked list of cells

type Collector

type Collector interface {
	Sweeper(lastX, scanLine, len int, cover int16)
	SetColor(clr interface{})
}

Collector translates the line seweep data to the target format. For example a 16 bit alpha only image would use a different collector than an RGBA image.

type Line

type Line struct {
	// contains filtered or unexported fields
}

Fixed point line

type RGBACollector

type RGBACollector struct {
	Color     color.RGBA
	ColorFunc rasterx.ColorFunc
	Image     *image.RGBA
}

RGBA collector implements the collector interface for image.RGBA images.

func (*RGBACollector) SetColor

func (r *RGBACollector) SetColor(clr interface{})

SetColor accepts either a color.Color or a rastserx.ColorFunc

func (*RGBACollector) Sweeper

func (r *RGBACollector) Sweeper(x, y, len int, alpha int16)

Sweeper sweeps the accumulated alpha value into the collector's RGBA image using Duff-Porter color composition equations. If the collector's ColorFunc is not nil it uses that otherwise it uses the collectors color. len is the number of steps in the y direction the sweep extends.

type ScannerS

type ScannerS struct {
	// contains filtered or unexported fields
}

ScannerS is a single threaded version of the cl-aa antialiasing algorithm. ScannerS implements the rasterx.Scanner interface, so it can be used with the rasterx and oksvg packages. There is considerable repeat code between ScannerS and ScannerT which, while not desirable, is done to optimize performance.

func NewScanS

func NewScanS(width, height int, collector Collector) (s *ScannerS)

NewScanS returns a single-threaded implementation of the cl-aa antialiasing algorithm ScannerS implements the rasterx.Scannner interface for use with the rasterx and oksvg packages. An object implementing the Collector interface must be provided, which will convert x,y, and alpha values to the target format such as an image.RGBA. A collector for image.RGBA, RGBACollector, is defined in this package.

func (*ScannerS) Clear

func (s *ScannerS) Clear()

Clear reinitializes the cell linked lists and the path extents to make it ready for new paths

func (*ScannerS) Draw

func (s *ScannerS) Draw()

Draw finishes the path if it is open and then sweeps the accumulated area and cover cell values to the collector

func (*ScannerS) GetPathExtent

func (s *ScannerS) GetPathExtent() fixed.Rectangle26_6

GetPathExtent returns the bounaries of the current path

func (*ScannerS) Line

func (s *ScannerS) Line(b fixed.Point26_6)

Line adds a straight line segment to the path

func (*ScannerS) SetBounds

func (s *ScannerS) SetBounds(height, width int)

SetBounds set the boundaries in which the scanner is allowed to draw. Negative values are excluded

func (*ScannerS) SetClip

func (s *ScannerS) SetClip(rect image.Rectangle)

SetClip does nothing for now

func (*ScannerS) SetColor

func (s *ScannerS) SetColor(color interface{})

SetColor sends either a rasterx.ColorFunc or color.Color value to the collector

func (*ScannerS) SetWinding

func (s *ScannerS) SetWinding(useNonZeroWinding bool)

SetWinding does nothing for now

func (*ScannerS) Start

func (s *ScannerS) Start(a fixed.Point26_6)

Start initiates a new path. If a path is already in progress it will automatically close.

type ScannerT

type ScannerT struct {
	// contains filtered or unexported fields
}

ScannerT is a multi-threaded version of the cl-aa antialiasing algorithm. ScannerT implements the rasterx.Scanner interface, so it can be used with the rasterx and oksvg packages.

func NewScanT

func NewScanT(threads, width, height int, collector Collector) (s *ScannerT)

NewScanT returns a multi-threaded implementation of the cl-aa antialiasing algorithm ScannerT implements the rasterx.Scannner interface for use with the rasterx and oksvg packages. An object implementing the Collector interface must be provided, which will convert x,y, and alpha values to the target format such as an image.RGBA. A collector for image.RGBA, RGBACollector, is defined in this package.

func (*ScannerT) Clear

func (s *ScannerT) Clear()

Clear reinitializes the cell linked lists and the path extents to make it ready for new paths

func (*ScannerT) Close

func (s *ScannerT) Close()

Close shuts down the channels associated with the ScannerT

func (*ScannerT) Draw

func (s *ScannerT) Draw()

Draw finishes the path if it is open and then sweeps the accumulated area and cover cell values to the collector

func (*ScannerT) GetPathExtent

func (s *ScannerT) GetPathExtent() fixed.Rectangle26_6

GetPathExtent returns the bounaries of the current path

func (*ScannerT) Line

func (s *ScannerT) Line(b fixed.Point26_6)

Line adds a straight line segment to the path

func (*ScannerT) SetBounds

func (s *ScannerT) SetBounds(height, width int)

SetBounds set the boundaries in which the scanner is allowed to draw. Negative values are excluded

func (*ScannerT) SetClip

func (s *ScannerT) SetClip(rect image.Rectangle)

SetClip does nothing for now

func (*ScannerT) SetColor

func (s *ScannerT) SetColor(color interface{})

SetColor sends either a rasterx.ColorFunc or color.Color value to the collector

func (*ScannerT) SetWinding

func (s *ScannerT) SetWinding(useNonZeroWinding bool)

SetWinding does nothing for now

func (*ScannerT) Start

func (s *ScannerT) Start(a fixed.Point26_6)

Start initiates a new path. If a path is already in progress it will automatically close.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL