Picture

Picture is an imitation of a function whose input is an implicit parameter (which in Scala 3 is a context function), and whose output type depends on the input type (which in Scala 3 is a dependent function type). It has two type parameters. They are, in order:

In Scala 3 notation, a Picture is conceptually equivalent to a function with type [Alg <: Algebra, A] => (a: Alg) ?=> a.Drawing[A].

Pictures Are Values

Algebras do not work directly with Picture. Instead they work with the Drawing[A] type that is the output of a Picture. However, all the syntax that makes the algebras easier to use, and which we have used in our previous examples, create and consume Picture. The reason for this is that working with raw algebras requires we wrap everything in methods. Methods are not values; we cannot pass a method to a method nor return a method from a method. Functions are values, but in Scala 2 their input parameters cannot also be implicit parameters. Picture is like a function with an implicit input parameter. It also provides a bit more structure than using functions directly. When we see a Picture we know exactly what we're dealing with.

Drawing Pictures

We can draw a picture to the screen using the draw method. This is RendererSyntax that depends on a having a Renderer in scope. There are other methods provided by the Renderer effect, as explained in its documentation.

Writing and Converting Pictures

In addition to drawing a picture to the screen we can write it to a file or convert it to some other type. The write method saves a picture to a file. When we call write we must pass two parameters: a normal parameter that is the file name to use and a type parameter that gives the format of the file. In the example below we save a file as a PNG.

import doodle.core.*
import doodle.syntax.all.*
import doodle.java2d.*
import doodle.core.format.*
import cats.effect.unsafe.implicits.global

val picture = circle(100)

picture.write[Png]("circle.png")

The write method is WriterSyntax that comes from the Writer. There are other methods that allow, for example, specifying a Frame to use when saving the file.

We can convert a Picture to a Base64 value using the base64 method. As with write, this method is Base64Syntax for the Base64. The parameters are similar to write: we must specify a format to encode the picture in but we don't specify a filename. Instead we get back the result of evaluating the Picture (the A in F[A] which is usually ()) and a Base64 value.

import doodle.core.*
import doodle.syntax.all.*
import doodle.java2d.*
import doodle.core.format.*
import cats.effect.unsafe.implicits.global

val picture = circle(100)

val (result, b64) = picture.base64[Png]()

Converting Other Types to a Picture

The ToPicture algebra provides a single method that converts some type (fixed for each instance of ToPicture) to a F[Unit]. The ToPictureSyntax wraps the result in a Picture, as is standard for syntax, and therefore gives a way to convert the input type to a Picture.

The available instances vary depending on the backend. For the Java2D backend, Base64 and BufferedImage values can be converted to Picture. For SVG only Base64 is currently supported.

Here is quick example of use. First we create a Base64 value from a Picture.

import doodle.core.*
import doodle.syntax.all.*
import doodle.java2d.*
import doodle.core.format.*
import cats.effect.unsafe.implicits.global
// The value we throw away is the result of evaluating the
// `Picture`, which is `Unit`.
val (_, base64) = circle(100).base64[Png]()

We can convert it right back to a Picture using the toPicture method.

val picture = base64.toPicture

Type Class Instances for Picture

There some type class instances defined for Picture.

Picture[Alg,*] always has an Monad instance.

Picture[Alg,*] has a Monoid instance if:

In this case the combine is on, with identity empty.

Available Algebras→