View Source Scenic.Script (Scenic v0.11.2)

overview

Overview

Scenic.Script is the fundamental "rendering" data structure for Scenic.

Prior to v0.11, drivers received Graphs from the ViewPort and were responsible for transforming them into a list of drawing commands that would ultimately draw the actual picture that is displayed as the Scenic UI.

After some experience, it became apparent that this was a common task for almost all drivers and has been moved into the ViewPort and formalized in Scenic.Script.

Simply put, Scenic.Script produces a list of static drawing commands that are sent, unmodified, to the drivers through the ViewPort. These scripts are generated for you when you use Scenic.Scene.push_graph/3, or you can create them yourself by using this api.

If you use Scenic.Script directly, you can create more complicated and/or reusable graphics than you could by using Graphs alone.

update-isolation

Update Isolation

Another way to use scripts is to separate large static bits of a graph from that which changes frequently. When a graph is pushed to the ViewPort, the entire thing is compiled into a script, which is sent as a whole to the Drivers.

However if that graph references a script, only the reference to the script is sent, not the contents of the script. This means you can modify the graph frequently without sending the contents of the scripts.

The opposite is also true. You can generate and push the scripts frequently without causing the graphs that reference them to be recompiled or resent.

An example of this might be a graph that implements a chart of some sort. The contents of the chart could be a script that is updated as new data comes in without needing all the chrome around it to be recompiled or sent for every update.

api-patterns

API Patterns

This is a large module with many functions. Most of them are very small, however and simply add individual commands to the script.

The general pattern is that you start by calling Scenic.Script.start(). This simply returns an empty list. Each drawing api adds an element to the head of the list. Then you end with Scenic.Script.finsh(), which reverses the list and performs some optimizations on it.

alias Scenic.Script

my_script =
  Script.start()
  |> Script.text( "A very simple script" )
  |> Script.finish()

After the script is generated, you publish it to the ViewPort through either your scene's helper api Scenic.Scene.push_script/4 or directly throught the ViewPort api Scenic.ViewPort.put_script/4

Finally, to get the script to draw, you need to reference it from a graph.

my_graph =
  Graph.build()
    |> script( "my_script_name" )

It doesn't matter if you push the script before or after you push the graph that references it.

scene =
  scene
  |> push_script( my_script, "my_script_name" )
  |> push_graph( my_graph )

example-the-checkbox-check-mark

Example: the Checkbox check mark

The canonical example is the checkmark symbol used in the Checkbox component. This is two lines, with rounded endpoints and rounded joint between them. It could be described using a Path primitive, but there is no need to send its instructions every time it is shown or hidden since its shape doesn't actually change.

The Checkbox component creates and publishes this script using something very similar to the following example.

alias Scenic.Script

# build the checkmark script
chx_script =
  Script.start()
  |> Script.push_state()
  |> Script.join(:round)
  |> Script.stroke_width(@border_width + 1)
  |> Script.stroke_color(theme.thumb)
  |> Script.begin_path()
  |> Script.move_to(0, 8)
  |> Script.line_to(5, 13)
  |> Script.line_to(12, 1)
  |> Script.stroke_path()
  |> Script.pop_state()
  |> Script.finish()

chx_id = scene.id <> "_chk"
scene = push_script(scene, chx_script, chx_id)

Building and using a custom script happens in three parts. First, the script itself is created using the Scenic.Script api.

Then the script is published to the ViewPort using Scenic.Scene.push_script/4 with a unique name.

Later, the graph for the checkbox references this script, which is what triggers it to be drawn.

graph =
  Graph.build()
    |> script(chx_id, id: :chx, hidden: !checked?)

script-state

Script State

The underlying rendering engine that consumes these scripts and draws the actual pictures maintains a set of current drawing state, which can be pushed and popped from a stack via the push_state/1, pop_state/1, and pop_push_state/1 apis.

These functions are analogous to the state save/restore APIs in Canvas.

transforms

Transforms

Transforms are applied to the running script by multiplying matrices together. This is very similar to how games position elements of UI. It takes a little getting used to, but is very powerful.

If you want to unroll the most recent applied transform, you should push then pop the state to get back to the previous transform stack.

binary-format

Binary Format

The serialize/3 and deserialize/1 go back and forth from the list format to a binary representation of the script. The serialize/3 function produces an IO list, and deserialize goes back into a list of instructions.

There is a standard format to the binary, but that needs to be independently documented. You can dig into the code behind serialize/3 to see it in action.

Drivers, which normally do the serialization call, can intercept/override any command if they need something specific.

Link to this section Summary

Functions

Add an arc segment to the path using the control points and radius.

Begin a new path.

Add a bezier curve segment to the path using the control points.

Set the current end cap style.

Add a circle to the current path.

Erase the entire drawing field output.

Close the current path.

Transform a binary or io list into a readable script list.

Draw an arc defined by radius and an angle. Can be filled or stroked.

Draw a circle defined by a radius. Can be filled or stroked.

Draw an ellipse defined by two radii. Can be filled or stroked.

draw_flag is a helper function to choose the appropriate fill and/or stroke flag given a map of styles.

Draw a line from a start point to a finish point. Can only be stroked.

Draw a quad defined by four points. Can be filled or stroked.

Draw a rectangle defined by height and width. Can be filled or stroked.

Draw a rounded rectangle defined by height, width, and radius. Can be filled or stroked.

Draw a sector defined by radius and an angle. Can be filled or stroked.

Draw a collection of sprites.

Draw a a block of text. Can be filled.

Draw a a block of text with automatic new lines. Can be filled.

Draw a triangle defined by three points. Can be filled or stroked.

Add an ellipse to the current path.

Set the current fill to an single color.

Set the current fill to an image from the Static asset library.

Set the current fill to linear gradient that goes between two colors.

Fill the current path with the currently selected fill paint.

Set the current fill to radial gradient that goes between two colors.

Set the current fill to an image from an asset stream.

Finish a script, preparing it to be sent to the ViewPort.

Set the current font. Must be a valid reference into your static assets library.

Set the current font size.

Set the current line joint style.

Add a new line segment from the current position to a specified location.

Extract a map of all the media (both static assets and streams) used in a script.

Set the current miter limit for joints.

Move the current draw position without adding a line segment.

Reverts the style/transform state of the script then immediately pushes it again.

Reverts the style/transform state of the script to the most recently pushed state.

Saves the current style/transform state of the script as it is running.

Add a quad to the current path.

Add a quadratic curve segment to the path using the control points.

Add a rectangle to the current path.

Recursively draw a script by reference.

Apply a rotation transform to the current transform stack.

Add a rounded rectangle to the current path.

Apply a scale transform to the current transform stack.

Set the current scissor rect.

Add a sector to the current path.

Transform a script list into a binary IO list.

Transform a script list into a binary IO list with a map like interceptor function.

Transform a script list into a binary IO list with a map_reduce like interceptor function.

Create a new Script.

Set the current stroke to an single color.

Set the current stroke to an image from the Static asset library.

Set the current stroke to linear gradient that goes between two colors.

Stroke the current path with the currently selected stroke width/paint.

Set the current stroke to radial gradient that goes between two colors.

Set the current stroke to an image from an asset stream.

Set the current stroke width.

Set the current horizontal text alignment.

Set the current vertical text alignment.

Apply an arbitrary transform to the current transform stack.

Apply a translation transform to the current transform stack.

Add a triangle to the current path.

Link to this section Types

@type fill_stroke() :: :fill | :stroke | :fill_stroke
@type id() :: atom() | String.t() | reference() | pid()
@type script_op() ::
  :push_state
  | :pop_state
  | :pop_push_state
  | {:clear, color :: Scenic.Color.t()}
  | {:draw_line,
     {x0 :: number(), y0 :: number(), x1 :: number(), y1 :: number(), :stroke}}
  | {:draw_quad,
     {x0 :: number(), y0 :: number(), x1 :: number(), y1 :: number(),
      x2 :: number(), y2 :: number(), x3 :: number(), y3 :: number(),
      fill_stroke()}}
  | {:draw_rect, {width :: number(), height :: number(), fill_stroke()}}
  | {:draw_rrect,
     {width :: number(), height :: number(), radius :: number(), fill_stroke()}}
  | {:draw_sector, {radius :: number(), radians :: number(), fill_stroke()}}
  | {:draw_arc, {radius :: number(), radians :: number(), fill_stroke()}}
  | {:draw_circle, {radius :: number(), fill_stroke()}}
  | {:draw_ellipse, {radius0 :: number(), radius1 :: number(), fill_stroke()}}
  | {:draw_sprites,
     {src_id :: Scenic.Assets.Static.id(),
      cmds :: Scenic.Primitive.Sprites.draw_cmds()}}
  | {:draw_text, utf8_string :: String.t()}
  | {:draw_triangle,
     {x0 :: number(), y0 :: number(), x1 :: number(), y1 :: number(),
      x2 :: number(), y2 :: number(), fill_stroke()}}
  | {:script, id :: pos_integer()}
  | :begin_path
  | :close_path
  | :fill_path
  | :stroke_path
  | {:move_to, {x :: number(), y :: number()}}
  | {:line_to, {x :: number(), y :: number()}}
  | {:arc_to,
     {x1 :: number(), y1 :: number(), x2 :: number(), y2 :: number(),
      radius :: number()}}
  | {:bezier_to,
     {cp1x :: number(), cp1y :: number(), cp2x :: number(), cp2y :: number(),
      x :: number(), y :: number()}}
  | {:quadratic_to,
     {cpx :: number(), cpy :: number(), x :: number(), y :: number()}}
  | {:quad,
     {x0 :: number(), y0 :: number(), x1 :: number(), y1 :: number(),
      x2 :: number(), y2 :: number(), x3 :: number(), y3 :: number()}}
  | {:rect, {width :: number(), height :: number()}}
  | {:rrect, {width :: number(), height :: number(), radius :: number()}}
  | {:sector, {radius :: number(), radians :: number()}}
  | {:circle, {radius :: number()}}
  | {:ellipse, {radius0 :: number(), radius1 :: number()}}
  | {:triangle,
     {x0 :: number(), y0 :: number(), x1 :: number(), y1 :: number(),
      x2 :: number(), y2 :: number()}}
  | {:scale, {x :: number(), y :: number()}}
  | {:rotate, radians :: number()}
  | {:translate, {x :: number(), y :: number()}}
  | {:transform,
     {a :: number(), b :: number(), c :: number(), d :: number(), e :: number(),
      f :: number()}}
  | {:fill_color, color :: Scenic.Color.t()}
  | {:fill_linear,
     {start_x :: number(), start_y :: number(), end_x :: number(),
      end_y :: number(), color_start :: Scenic.Color.t(),
      color_end :: Scenic.Color.t()}}
  | {:fill_radial,
     {center_x :: number(), center_y :: number(), inner_radius :: number(),
      outer_radius :: number(), color_start :: Scenic.Color.t(),
      color_end :: Scenic.Color.t()}}
  | {:fill_image, image :: Scenic.Assets.Static.id()}
  | {:fill_stream, id :: Scenic.Assets.Stream.id()}
  | {:stroke_color, color :: Scenic.Color.t()}
  | {:stroke_linear,
     {start_x :: number(), start_y :: number(), end_x :: number(),
      end_y :: number(), color_start :: Scenic.Color.t(),
      color_end :: Scenic.Color.t()}}
  | {:stroke_radial,
     {center_x :: number(), center_y :: number(), inner_radius :: number(),
      outer_radius :: number(), color_start :: Scenic.Color.t(),
      color_end :: Scenic.Color.t()}}
  | {:stroke_image, image :: Scenic.Assets.Static.id()}
  | {:stroke_stream, id :: Scenic.Assets.Stream.id()}
  | {:stroke_width, width :: number()}
  | {:cap, :butt}
  | {:cap, :round}
  | {:cap, :square}
  | {:join, :bevel}
  | {:join, :round}
  | {:join, :miter}
  | {:miter_limit, limit :: number()}
  | {:scissor, {width :: number(), height :: number()}}
  | {:font, id :: Scenic.Assets.Static.id()}
  | {:font_size, size :: number()}
  | {:text_align, :left}
  | {:text_align, :center}
  | {:text_align, :right}
  | {:text_base, :top}
  | {:text_base, :middle}
  | {:text_base, :alphabetic}
  | {:text_base, :bottom}
@type t() :: [script_op()]

Link to this section Functions

Link to this function

arc_to(ops, x1, y1, x2, y2, radius)

View Source
@spec arc_to(
  ops :: t(),
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  radius :: number()
) :: ops :: t()

Add an arc segment to the path using the control points and radius.

This adds to the current path. It does not fill or stroke anything.

@spec begin_path(ops :: t()) :: ops :: t()

Begin a new path.

Link to this function

bezier_to(ops, cp1x, cp1y, cp2x, cp2y, x, y)

View Source
@spec bezier_to(
  ops :: t(),
  cp1x :: number(),
  cp1y :: number(),
  cp2x :: number(),
  cp2y :: number(),
  x :: number(),
  y :: number()
) :: ops :: t()

Add a bezier curve segment to the path using the control points.

This adds to the current path. It does not fill or stroke anything.

@spec cap(ops :: t(), type :: :butt | :round | :square) :: ops :: t()

Set the current end cap style.

Can be any one of :butt, :round, or :square

@spec circle(ops :: t(), radius :: number()) :: ops :: t()

Add a circle to the current path.

This adds to the current path. It does not fill or stroke anything.

@spec clear(ops :: t(), color :: Scenic.Color.t()) :: ops :: t()

Erase the entire drawing field output.

The clear/1 function is equivalent to setting a color, creating a new rect path that covers the entire draw field, then filling it. clear/1 does all this in a single, compact script command.

@spec close_path(ops :: t()) :: ops :: t()

Close the current path.

This effectively adds a line segment from the current draw position back to where the path was started.

@spec deserialize(bin :: binary()) :: script :: t()

Transform a binary or io list into a readable script list.

This is intended to help with debugging.

Deserialization will only work for scripts serialized using the standard, un-hooked format.

Link to this function

draw_arc(ops, radius, radians, flag)

View Source
@spec draw_arc(
  ops :: t(),
  radius :: number(),
  radians :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw an arc defined by radius and an angle. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_circle(ops, radius, flag)

View Source
@spec draw_circle(
  ops :: t(),
  radius :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a circle defined by a radius. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_ellipse(ops, radius0, radius1, flag)

View Source
@spec draw_ellipse(
  ops :: t(),
  radius0 :: number(),
  radius1 :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw an ellipse defined by two radii. Can be filled or stroked.

Creates a new path and draws it.

@spec draw_flag(styles :: map()) :: :fill_stroke | :fill | :stroke | nil

draw_flag is a helper function to choose the appropriate fill and/or stroke flag given a map of styles.

Link to this function

draw_line(ops, x0, y0, x1, y1, atom)

View Source
@spec draw_line(
  ops :: t(),
  x0 :: number(),
  y0 :: number(),
  x1 :: number(),
  y1 :: number(),
  :stroke
) ::
  ops :: t()

Draw a line from a start point to a finish point. Can only be stroked.

Creates a new path and draws it.

Link to this function

draw_quad(ops, x0, y0, x1, y1, x2, y2, x3, y3, flag)

View Source
@spec draw_quad(
  ops :: t(),
  x0 :: number(),
  y0 :: number(),
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  x3 :: number(),
  y3 :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a quad defined by four points. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_rectangle(ops, width, height, flag)

View Source
@spec draw_rectangle(
  ops :: t(),
  width :: number(),
  height :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a rectangle defined by height and width. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_rounded_rectangle(ops, width, height, radius, flag)

View Source
@spec draw_rounded_rectangle(
  ops :: t(),
  width :: number(),
  height :: number(),
  radius :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a rounded rectangle defined by height, width, and radius. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_sector(ops, radius, radians, flag)

View Source
@spec draw_sector(
  ops :: t(),
  radius :: number(),
  radians :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a sector defined by radius and an angle. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

draw_sprites(ops, src_id, cmds)

View Source
@spec draw_sprites(
  ops :: t(),
  image_source :: Scenic.Assets.Static.id(),
  draw_commands :: Scenic.Primitive.Sprites.draw_cmds()
) :: ops :: t()

Draw a collection of sprites.

Draws one or more subsection from a single source image.

Link to this function

draw_text(ops, utf8_string)

View Source
@spec draw_text(ops :: t(), text :: String.t()) :: ops :: t()

Draw a a block of text. Can be filled.

Creates a new path and draws it.

Link to this function

draw_text(ops, utf8_text, line_height)

View Source
@spec draw_text(ops :: t(), text :: String.t(), line_height :: number()) :: ops :: t()

Draw a a block of text with automatic new lines. Can be filled.

Creates a new path and draws it.

Link to this function

draw_triangle(ops, x0, y0, x1, y1, x2, y2, flag)

View Source
@spec draw_triangle(
  ops :: t(),
  x0 :: number(),
  y0 :: number(),
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  fill_stroke_flags :: fill_stroke()
) :: ops :: t()

Draw a triangle defined by three points. Can be filled or stroked.

Creates a new path and draws it.

Link to this function

ellipse(ops, radius0, radius1)

View Source
@spec ellipse(ops :: t(), radius0 :: number(), radius1 :: number()) :: ops :: t()

Add an ellipse to the current path.

This adds to the current path. It does not fill or stroke anything.

@spec fill_color(ops :: t(), color :: Scenic.Color.t()) :: ops :: t()

Set the current fill to an single color.

This only sets the fill paint type. You still need to call fill_path/1 or one of the draw_* apis to actually draw something.

@spec fill_image(ops :: t(), image :: Scenic.Assets.Static.id()) :: ops :: t()

Set the current fill to an image from the Static asset library.

This image will be automatically repeated both horizontally and vertically.

This only sets the fill paint type. You still need to call fill_path/1 or one of the draw_* apis to actually draw something.

Link to this function

fill_linear(ops, start_x, start_y, end_x, end_y, color_start, color_end)

View Source
@spec fill_linear(
  ops :: t(),
  start_x :: number(),
  start_y :: number(),
  end_x :: number(),
  end_y :: number(),
  color_start :: Scenic.Color.t(),
  color_end :: Scenic.Color.t()
) :: ops :: t()

Set the current fill to linear gradient that goes between two colors.

This only sets the fill paint type. You still need to call fill_path/1 or one of the draw_* apis to actually draw something.

@spec fill_path(ops :: t()) :: ops :: t()

Fill the current path with the currently selected fill paint.

Link to this function

fill_radial(ops, center_x, center_y, inner_radius, outer_radius, color_start, color_end)

View Source
@spec fill_radial(
  ops :: t(),
  center_x :: number(),
  center_y :: number(),
  inner_radius :: number(),
  outer_radius :: number(),
  color_start :: Scenic.Color.t(),
  color_end :: Scenic.Color.t()
) :: ops :: t()

Set the current fill to radial gradient that goes between two colors.

This only sets the fill paint type. You still need to call fill_path/1 or one of the draw_* apis to actually draw something.

@spec fill_stream(ops :: t(), id :: Scenic.Assets.Stream.id()) :: ops :: t()

Set the current fill to an image from an asset stream.

This image will be automatically repeated both horizontally and vertically.

This only sets the fill paint type. You still need to call fill_path/1 or one of the draw_* apis to actually draw something.

@spec finish(ops :: t()) :: final_script :: t()

Finish a script, preparing it to be sent to the ViewPort.

This function cleans up the script, which should have been created by first calling start/0 then and series of calls to Scenic.Script functions that add commands to the script.

finish/1 cleans up the script, reverses it, and runs an optimization pass.

The resulting script is ready to be stored in the ViewPort.

@spec font(ops :: t(), id :: Scenic.Assets.Static.id()) :: ops :: t()

Set the current font. Must be a valid reference into your static assets library.

@spec font_size(ops :: t(), size :: number()) :: ops :: t()

Set the current font size.

@spec join(ops :: t(), type :: :bevel | :round | :miter) :: ops :: t()

Set the current line joint style.

Can be any one of :bevel, :round, or :miter

@spec line_to(ops :: t(), x :: number(), y :: number()) :: ops :: t()

Add a new line segment from the current position to a specified location.

This adds to the current path. It does not fill or stroke anything.

Extract a map of all the media (both static assets and streams) used in a script.

@spec miter_limit(ops :: t(), limit :: number()) :: ops :: t()

Set the current miter limit for joints.

@spec move_to(ops :: t(), x :: number(), y :: number()) :: ops :: t()

Move the current draw position without adding a line segment.

@spec pop_push_state(ops :: t()) :: ops :: t()

Reverts the style/transform state of the script then immediately pushes it again.

pop_push_state/1 is for when you have made changes that you want to revert, but then know you are going to make more changes that you revert again. This is functionally equivalent to calling pop_state/1 followed immediately by push_state/1, except that it is done as a single operation in the script instead of two. This saves drawtime compute and makes the script smaller. Any adjacent pop/push pairs in the script will be converted to pop_push in the optimization phase of the finish/1 function.

pop_push_state/1 must be preceded with either push_state/1 and followed by either pop_state/1 or another pop_push_state/1

@spec pop_state(ops :: t()) :: ops :: t()

Reverts the style/transform state of the script to the most recently pushed state.

This function restores the style and transform states from a stack of states. The idea is that you can make changes, then "pop" back to where the state was before.

push_state/1 must be preceded with either push_state/1 or pop_push_state/1

@spec push_state(ops :: t()) :: ops :: t()

Saves the current style/transform state of the script as it is running.

This function saves the current style and transform states in a stack of states. The idea is that you can make changes, then "pop" back to where the state was before.

push_state/1 must be paired with an eventual pop_state/1 or pop_push_state/1

Link to this function

quad(ops, x0, y0, x1, y1, x2, y2, x3, y3)

View Source
@spec quad(
  ops :: t(),
  x0 :: number(),
  y0 :: number(),
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  x3 :: number(),
  y3 :: number()
) :: ops :: t()

Add a quad to the current path.

This adds to the current path. It does not fill or stroke anything.

Link to this function

quadratic_to(ops, cpx, cpy, x, y)

View Source
@spec quadratic_to(
  ops :: t(),
  cpx :: number(),
  cpy :: number(),
  x :: number(),
  y :: number()
) ::
  ops :: t()

Add a quadratic curve segment to the path using the control points.

This adds to the current path. It does not fill or stroke anything.

Link to this function

rectangle(ops, width, height)

View Source
@spec rectangle(ops :: t(), width :: number(), height :: number()) :: ops :: t()

Add a rectangle to the current path.

This adds to the current path. It does not fill or stroke anything.

@spec render_script(ops :: t(), id :: String.t()) :: ops :: t()

Recursively draw a script by reference.

This adds a command that pauses the current script being rendered and recursively draws another script that is referenced by id.

The new script being drawn starts with the currently set draw state and the current state is automatically restored with the script is completed. Then the current script continues drawing.

@spec rotate(ops :: t(), radians :: number()) :: ops :: t()

Apply a rotation transform to the current transform stack.

Link to this function

rounded_rectangle(ops, width, height, radius)

View Source
@spec rounded_rectangle(
  ops :: t(),
  width :: number(),
  height :: number(),
  radius :: number()
) ::
  ops :: t()

Add a rounded rectangle to the current path.

This adds to the current path. It does not fill or stroke anything.

@spec scale(ops :: t(), x :: number(), y :: number()) :: ops :: t()

Apply a scale transform to the current transform stack.

@spec scissor(ops :: t(), width :: number(), height :: number()) :: ops :: t()

Set the current scissor rect.

To remove the scissor rect, push the state before you use the scissor, then pop it afterwards.

Link to this function

sector(ops, radius, radians)

View Source
@spec sector(ops :: t(), radius :: number(), radians :: number()) :: ops :: t()

Add a sector to the current path.

This adds to the current path. It does not fill or stroke anything.

@spec serialize(script :: t()) :: iolist()

Transform a script list into a binary IO list.

Usually called from a driver.

Returns an IO list.

with {:ok, script} <- ViewPort.get_script_by_id(vp, "my_script_id") do
  Scenic.Script.serialize(script)
  |> my_render_function()
end

There are times when a driver will want to customize the serialization. For example, GLFW driver wants fixed width names for the streams. So it hooks the serialization of certain commands.

  io_list = Script.serialize(script, fn
    {:font, id} -> my_serialize_font(id)
    {:fill_stream, id} -> my_serialize_fill_stream(id)
    {:stroke_stream, id} -> my_serialize_stroke_stream(id)
    other -> other
end
Link to this function

serialize(script, intercept_fn)

View Source
@spec serialize(
  script :: t(),
  op_fn :: (op_fn :: script_op() -> nil | binary() | iolist() | script_op())
) :: iolist()

Transform a script list into a binary IO list with a map like interceptor function.

Usually called from a driver.

Returns an IO list.

with {:ok, script} <- ViewPort.get_script(vp, id) do
  io_list = Script.serialize(script, fn
    {:font, id} -> my_serialize_font(id)
    {:fill_stream, id} -> my_serialize_fill_stream(id)
    {:stroke_stream, id} -> my_serialize_stroke_stream(id)
    other -> other
  end)
end
Link to this function

serialize(script, acc, intercept_fn)

View Source
@spec serialize(
  script :: t(),
  accumulator :: Enum.acc(),
  (op_fn :: script_op(), state :: any() ->
     {nil, any()} | {binary(), any()} | {iolist(), any()} | {script_op(), any()})
) :: {iolist(), Enum.acc()}

Transform a script list into a binary IO list with a map_reduce like interceptor function.

Usually called from a driver.

Returns an IO list.

  {io_list, count} = Script.serialize(script, 0, fn
    {:font, id}, c -> {my_serialize_font(id), c+1}
    {:fill_stream, id}, c -> {my_serialize_fill_stream(id), c+1}
    {:stroke_stream, id}, c -> {my_serialize_stroke_stream(id), c+1}
    other, c -> {other, c+1}
  end)
@spec start() :: ops :: t()

Create a new Script.

Link to this function

stroke_color(ops, color)

View Source
@spec stroke_color(ops :: t(), color :: Scenic.Color.t()) :: ops :: t()

Set the current stroke to an single color.

This only sets the stroke paint type. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

@spec stroke_image(ops :: t(), image :: Scenic.Assets.Static.id()) :: ops :: t()

Set the current stroke to an image from the Static asset library.

This image will be automatically repeated both horizontally and vertically.

This only sets the stroke paint type. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

Link to this function

stroke_linear(ops, start_x, start_y, end_x, end_y, color_start, color_end)

View Source
@spec stroke_linear(
  ops :: t(),
  start_x :: number(),
  start_y :: number(),
  end_x :: number(),
  end_y :: number(),
  color_start :: Scenic.Color.t(),
  color_end :: Scenic.Color.t()
) :: ops :: t()

Set the current stroke to linear gradient that goes between two colors.

This only sets the stroke paint type. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

@spec stroke_path(ops :: t()) :: ops :: t()

Stroke the current path with the currently selected stroke width/paint.

Link to this function

stroke_radial(ops, center_x, center_y, inner_radius, outer_radius, color_start, color_end)

View Source
@spec stroke_radial(
  ops :: t(),
  center_x :: number(),
  center_y :: number(),
  inner_radius :: number(),
  outer_radius :: number(),
  color_start :: Scenic.Color.t(),
  color_end :: Scenic.Color.t()
) :: ops :: t()

Set the current stroke to radial gradient that goes between two colors.

This only sets the stroke paint type. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

@spec stroke_stream(ops :: t(), id :: Scenic.Assets.Stream.id()) :: ops :: t()

Set the current stroke to an image from an asset stream.

This image will be automatically repeated both horizontally and vertically.

This only sets the stroke paint type. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

Link to this function

stroke_width(ops, width)

View Source
@spec stroke_width(ops :: t(), width :: number()) :: ops :: t()

Set the current stroke width.

This only sets the stroke sidth. You still need to call stroke_path/1 or one of the draw_* apis to actually draw something.

@spec text_align(ops :: t(), type :: :left | :center | :right) :: ops :: t()

Set the current horizontal text alignment.

Can be any one of :left, :right, or :center

@spec text_base(ops :: t(), type :: :top | :middle | :alphabetic | :bottom) ::
  ops :: t()

Set the current vertical text alignment.

Can be any one of :top, :middle, :alphabetic, or :bottom

Link to this function

transform(ops, a, b, c, d, e, f)

View Source
@spec transform(
  ops :: t(),
  a :: number(),
  b :: number(),
  c :: number(),
  d :: number(),
  e :: number(),
  f :: number()
) :: ops :: t()

Apply an arbitrary transform to the current transform stack.

@spec translate(ops :: t(), x :: number(), y :: number()) :: ops :: t()

Apply a translation transform to the current transform stack.

Link to this function

triangle(ops, x0, y0, x1, y1, x2, y2)

View Source
@spec triangle(
  ops :: t(),
  x0 :: number(),
  y0 :: number(),
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number()
) :: ops :: t()

Add a triangle to the current path.

This adds to the current path. It does not fill or stroke anything.