Scenic.Script (Scenic v0.11.0-beta.0) View Source

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 push_graph, 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

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.

If that graph references a script tho, only the reference 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.

And 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 needed all the chrome around it to be recompiled or sent.

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

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 it's instructions ever time it is shown or hidden since it's 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 the push_script (part of Scenic.Scene) 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

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 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

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 at 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

Specs

fill_stroke() :: :fill | :stroke | :fill_stroke

Specs

id() :: atom() | String.t() | reference() | pid()

Specs

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}

Specs

t() :: [script_op()]

Link to this section Functions

Link to this function

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

View Source

Specs

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.

Specs

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

Specs

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.

Specs

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

Set the current end cap style.

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

Specs

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.

Specs

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.

Specs

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.

Specs

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

Specs

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

Specs

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

Specs

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.

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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.

Specs

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.

Specs

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

Specs

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.

Specs

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

Specs

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.

Specs

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.

Specs

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.

Specs

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

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

Specs

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

Set the current font size.

Specs

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

Set the current line joint style.

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

Specs

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.

Specs

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

Set the current miter limit for joints.

Specs

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

Move the current draw position without adding a line segment.

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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

Specs

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.

Specs

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.

Specs

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

Specs

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.

Specs

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

Apply a scale transform to the current transform stack.

Specs

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

Specs

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.

Specs

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

Specs

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

Specs

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)

Specs

start() :: ops :: t()

Create a new Script.

Link to this function

stroke_color(ops, color)

View Source

Specs

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.

Specs

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

Specs

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.

Specs

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

Specs

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.

Specs

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

Specs

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.

Specs

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

Specs

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

Specs

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.

Specs

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

Specs

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.