PrawnEx (prawn_ex v0.4.0)

Copy Markdown View Source

Prawn-style declarative PDF generation for Elixir.

Pure Elixir, no Chrome or HTML. Build a document spec and emit PDF 1.4 binary.

Image / asset path

When using this library as a dependency, set in your application config:

config :prawn_ex, image_dir: "priv/images"

Relative paths passed to image/3 (e.g. "photo.jpg", "logo.png") are then resolved from that directory. Absolute paths and raw JPEG or PNG binaries are used as-is.

Example

PrawnEx.build("out.pdf", fn doc ->
  doc
  |> PrawnEx.set_font("Helvetica", 12)
  |> PrawnEx.text("Hello, PDF!")
  |> PrawnEx.rectangle(100, 400, 200, 50)
  |> PrawnEx.stroke()
end)

See module docs for PrawnEx.Document, PrawnEx.Units, PrawnEx.Layout (flow, stacks, region, markup), and PrawnEx.Layout.Markup.

Summary

Functions

Adds a new page. The new page becomes current.

Draws a bar chart. data is a list of {label, value} or [label, value]. Options: :at, :width, :height, :bar_color (gray 0–1), :axis, :labels, :label_font_size, :padding.

Builds a PDF by running the function on a new document, then writes to the given path.

Closes the current path back to its starting point.

Appends a cubic Bézier curve from the current point to {x, y} with control points c1 and c2. Draw with stroke/1 or fill/1.

Fills the current path.

Fills and strokes the current path in one operation — a shape with both a background and a border.

Embeds an image at the given position. path_or_binary is a file path or image binary.

Draws a line from {x1, y1} to {x2, y2}. Call stroke/1 to draw it.

Draws a line chart. data is a list of y-values (x = index) or [{x, y}, ...]. Options: :at, :width, :height, :stroke_color, :axis, :padding.

Draws a line from the current path point to {x, y}. Call stroke/1 after the path is complete.

Adds an external link annotation on the current page. Clicking the rectangle opens the URL. x, y are bottom-left in pt; width and height define the clickable area.

Moves the path to {x, y} without drawing. Use with line_to/2 and then stroke/1 for polylines.

Draws several lines in one chart box on a shared scale. See PrawnEx.Chart.multi_line_chart/3 for series shape and options.

Adds a rectangle at (x, y) with width and height. Call stroke/1 or fill/1 to draw it.

Registers a TrueType font for embedding, under name.

Appends a rounded-rectangle path (Bézier corners). Like rectangle/5 it only builds the path — follow with fill/1, stroke/1, or fill_stroke/1.

Sets the current font (e.g. "Helvetica") and size in points.

Sets the stroke (line) width in points for subsequent stroked paths.

Sets the non-stroking (fill and text) color to gray. g in 0..1 (0=black, 1=white).

Sets the non-stroking (fill and text) color to RGB. r, g, b in 0..1.

Sets fill and stroke opacity (0.0 transparent .. 1.0 opaque) for subsequent drawing. Set it back to 1.0 when done — like colors, it stays in effect.

Sets the stroking (lines, borders) color to gray. g in 0..1.

Sets the stroking (lines, borders) color to RGB. r, g, b in 0..1.

Strokes the current path (e.g. after rectangle/5 or line/3).

Draws a table at the given position. rows is a list of rows (list of cell values). First row can be styled as header with header: true (default).

Appends text at the current position (single line).

Draws text at the given position {x, y} (PDF coordinates: origin bottom-left).

Draws text wrapped to fit within a width. First line baseline at {x, y}; subsequent lines below (smaller y).

Converts the document to PDF binary.

Writes the document to a file at path.

Functions

add_page(doc)

@spec add_page(PrawnEx.Document.t()) :: PrawnEx.Document.t()

Adds a new page. The new page becomes current.

bar_chart(doc, data, opts \\ [])

@spec bar_chart(PrawnEx.Document.t(), [{String.t(), number()} | [term()]], keyword()) ::
  PrawnEx.Document.t()

Draws a bar chart. data is a list of {label, value} or [label, value]. Options: :at, :width, :height, :bar_color (gray 0–1), :axis, :labels, :label_font_size, :padding.

build(path, fun)

@spec build(String.t(), (PrawnEx.Document.t() -> PrawnEx.Document.t())) ::
  :ok | {:error, term()}

build(path, opts, fun)

@spec build(String.t(), keyword(), (PrawnEx.Document.t() -> PrawnEx.Document.t())) ::
  :ok | {:error, term()}

Builds a PDF by running the function on a new document, then writes to the given path.

Options (when passing a keyword list as second argument):

  • :header - fn(doc, page_number) -> doc — add ops at top of each page (e.g. title, line)
  • :footer - fn(doc, page_number) -> doc — add ops at bottom of each page (e.g. "Page N")

Returns :ok or {:error, reason}.

close_path(doc)

Closes the current path back to its starting point.

curve_to(doc, c1, c2, point)

Appends a cubic Bézier curve from the current point to {x, y} with control points c1 and c2. Draw with stroke/1 or fill/1.

fill(doc)

Fills the current path.

fill_stroke(doc)

Fills and strokes the current path in one operation — a shape with both a background and a border.

image(doc, path_or_binary, opts)

@spec image(PrawnEx.Document.t(), String.t() | binary(), keyword()) ::
  PrawnEx.Document.t() | {:error, term()}

Embeds an image at the given position. path_or_binary is a file path or image binary.

Supported formats: JPEG (embedded as DCT) and PNG (8-bit RGB or RGBA, non-interlaced; RGBA is composited on white). Other formats return {:error, :unsupported_image_format}.

If path_or_binary is a relative path, it is resolved against the configured image directory (see "Image / asset path" in the module docs). Set config :prawn_ex, image_dir: "priv/images" in your app to define where to look for image files.

Options: :at (required) {x, y} bottom-left of image, :width and :height in pt (default: intrinsic size).

line(doc, from, to)

@spec line(PrawnEx.Document.t(), {number(), number()}, {number(), number()}) ::
  PrawnEx.Document.t()

Draws a line from {x1, y1} to {x2, y2}. Call stroke/1 to draw it.

line_chart(doc, data, opts \\ [])

@spec line_chart(PrawnEx.Document.t(), [number()] | [{number(), number()}], keyword()) ::
  PrawnEx.Document.t()

Draws a line chart. data is a list of y-values (x = index) or [{x, y}, ...]. Options: :at, :width, :height, :stroke_color, :axis, :padding.

line_to(doc, pos)

@spec line_to(
  PrawnEx.Document.t(),
  {number(), number()}
) :: PrawnEx.Document.t()

Draws a line from the current path point to {x, y}. Call stroke/1 after the path is complete.

link(doc, x, y, width, height, url)

Adds an external link annotation on the current page. Clicking the rectangle opens the URL. x, y are bottom-left in pt; width and height define the clickable area.

move_to(doc, pos)

@spec move_to(
  PrawnEx.Document.t(),
  {number(), number()}
) :: PrawnEx.Document.t()

Moves the path to {x, y} without drawing. Use with line_to/2 and then stroke/1 for polylines.

multi_line_chart(doc, series, opts \\ [])

@spec multi_line_chart(PrawnEx.Document.t(), [map() | keyword()], keyword()) ::
  PrawnEx.Document.t()

Draws several lines in one chart box on a shared scale. See PrawnEx.Chart.multi_line_chart/3 for series shape and options.

rectangle(doc, x, y, width, height)

@spec rectangle(PrawnEx.Document.t(), number(), number(), number(), number()) ::
  PrawnEx.Document.t()

Adds a rectangle at (x, y) with width and height. Call stroke/1 or fill/1 to draw it.

register_font(doc, name, source)

Registers a TrueType font for embedding, under name.

source is a path to a .ttf file or the font binary itself. After registering, pass name to set_font/3 like any built-in font — the writer embeds the font program (flate-compressed) and real glyph widths, so text renders in the actual typeface instead of a base-14 stand-in. Text keeps flowing through the same WinAnsi transliteration.

Raises ArgumentError when the data is not a usable TrueType font (CFF-flavoured OpenType included — that needs /FontFile3).

doc
|> PrawnEx.register_font("HankenGrotesk", "priv/fonts/HankenGrotesk-Regular.ttf")
|> PrawnEx.set_font("HankenGrotesk", 12)

rounded_rectangle(doc, x, y, w, h, radius)

Appends a rounded-rectangle path (Bézier corners). Like rectangle/5 it only builds the path — follow with fill/1, stroke/1, or fill_stroke/1.

set_font(doc, font_name, size)

@spec set_font(PrawnEx.Document.t(), String.t(), number()) :: PrawnEx.Document.t()

Sets the current font (e.g. "Helvetica") and size in points.

set_line_width(doc, width)

@spec set_line_width(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()

Sets the stroke (line) width in points for subsequent stroked paths.

set_non_stroking_gray(doc, g)

@spec set_non_stroking_gray(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()

Sets the non-stroking (fill and text) color to gray. g in 0..1 (0=black, 1=white).

set_non_stroking_rgb(doc, r, g, b)

@spec set_non_stroking_rgb(PrawnEx.Document.t(), number(), number(), number()) ::
  PrawnEx.Document.t()

Sets the non-stroking (fill and text) color to RGB. r, g, b in 0..1.

set_opacity(doc, alpha)

Sets fill and stroke opacity (0.0 transparent .. 1.0 opaque) for subsequent drawing. Set it back to 1.0 when done — like colors, it stays in effect.

set_stroking_gray(doc, g)

@spec set_stroking_gray(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()

Sets the stroking (lines, borders) color to gray. g in 0..1.

set_stroking_rgb(doc, r, g, b)

@spec set_stroking_rgb(PrawnEx.Document.t(), number(), number(), number()) ::
  PrawnEx.Document.t()

Sets the stroking (lines, borders) color to RGB. r, g, b in 0..1.

stroke(doc)

@spec stroke(PrawnEx.Document.t()) :: PrawnEx.Document.t()

Strokes the current path (e.g. after rectangle/5 or line/3).

table(doc, rows, opts \\ [])

@spec table(PrawnEx.Document.t(), [list()], keyword()) :: PrawnEx.Document.t()

Draws a table at the given position. rows is a list of rows (list of cell values). First row can be styled as header with header: true (default).

Options

  • :at - {x, y} top-left of table (default {50, 750})
  • :column_widths - list of pt widths or :auto
  • :row_height, :cell_padding, :header, :border, :font_size, :header_font_size

Example

PrawnEx.table(doc, [["Name", "Score"], ["Alice", "95"], ["Bob", "87"]],
  at: {50, 650}, column_widths: [200, 80])

text(doc, s)

Appends text at the current position (single line).

text_at(doc, pos, s)

@spec text_at(PrawnEx.Document.t(), {number(), number()}, String.t()) ::
  PrawnEx.Document.t()

Draws text at the given position {x, y} (PDF coordinates: origin bottom-left).

text_box(doc, text, opts)

@spec text_box(PrawnEx.Document.t(), String.t(), keyword()) :: PrawnEx.Document.t()

Draws text wrapped to fit within a width. First line baseline at {x, y}; subsequent lines below (smaller y).

Options:

  • :at - {x, y} (required) — position of first line baseline
  • :width - max width in pt (required)
  • :font_name - default "Helvetica"
  • :font_size - default 12
  • :line_height - default 1.2 * font_size

to_binary(doc)

@spec to_binary(PrawnEx.Document.t()) :: binary()

Converts the document to PDF binary.

write_to_file(doc, path)

@spec write_to_file(PrawnEx.Document.t(), String.t()) :: :ok | {:error, term()}

Writes the document to a file at path.