ASCII terminal plotting backend - Basic Drawing Elements
This module contains core drawing functions for ASCII plotting including markers, arrows, heatmaps, and line drawing.
Author: fortplot contributors
Glyph table selecting the concrete characters the text backend paints for frames, axes, ticks, markers, and arrows. The Unicode table swaps in box-drawing and symbol glyphs; the ASCII default keeps the historical literal '+', '-', '|' output and does not need a table (issue #2060). UTF-8 byte sequences are built with achar() so the source stays pure ASCII, matching the existing convention in fortplot_unicode.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| character(len=:), | public, | allocatable | :: | hline | |||
| character(len=:), | public, | allocatable | :: | vline | |||
| character(len=:), | public, | allocatable | :: | corner_tl | |||
| character(len=:), | public, | allocatable | :: | corner_tr | |||
| character(len=:), | public, | allocatable | :: | corner_bl | |||
| character(len=:), | public, | allocatable | :: | corner_br | |||
| character(len=:), | public, | allocatable | :: | marker_square | |||
| character(len=:), | public, | allocatable | :: | marker_diamond | |||
| character(len=:), | public, | allocatable | :: | marker_star | |||
| character(len=:), | public, | allocatable | :: | arrow_right | |||
| character(len=:), | public, | allocatable | :: | arrow_left | |||
| character(len=:), | public, | allocatable | :: | arrow_up | |||
| character(len=:), | public, | allocatable | :: | arrow_ne | |||
| character(len=:), | public, | allocatable | :: | arrow_se |
Map a 1-based band index onto the ordered density ramp.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | band | |||
| integer, | intent(in) | :: | n_bands |
Unicode charset table: box-drawing frame glyphs plus Unicode markers and arrows. Only bytes that never occur in numeric tick labels or letters are remapped, so labels and annotations stay intact.
Canonicalize a user charset selection to 'ascii' or 'unicode'. 'auto' resolves through the environment; anything unrecognized falls back to the ASCII compatibility charset.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | name |
Resolve 'auto' deterministically from FORTPLOT_TEXT_CHARSET. Absent or unset, the file default stays ASCII so saved .txt bytes are stable and never depend on the host locale (issue #2060 non-goal).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | mode |
Build the top or bottom frame border for the given charset. In ASCII mode this reproduces the historical '+' // '-'*width // '+' border.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | width | |||
| type(text_charset_t), | intent(in) | :: | glyphs | |||
| logical, | intent(in) | :: | is_top |
Map a single canvas byte to its charset glyph. Only structural, marker, and arrow symbols are remapped; digits, letters, '.', '-', and '+' pass through so numeric tick labels and text annotations survive Unicode output unchanged.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(in) | :: | ch | |||
| type(text_charset_t), | intent(in) | :: | glyphs |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in) | :: | x | |||
| real(kind=wp), | intent(in) | :: | y | |||
| character(len=*), | intent(in) | :: | style | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height |
Fill ASCII canvas with heatmap representation of 2D data
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in), | contiguous | :: | x_grid(:) | ||
| real(kind=wp), | intent(in), | contiguous | :: | y_grid(:) | ||
| real(kind=wp), | intent(in), | contiguous | :: | z_grid(:,:) | ||
| real(kind=wp), | intent(in) | :: | z_min | |||
| real(kind=wp), | intent(in) | :: | z_max | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height | |||
| integer, | intent(inout), | optional | :: | canvas_color(:,:) | ||
| character(len=*), | intent(in), | optional | :: | colormap_name |
Draw arrow using Unicode directional characters for ASCII backend
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in) | :: | x | |||
| real(kind=wp), | intent(in) | :: | y | |||
| real(kind=wp), | intent(in) | :: | dx | |||
| real(kind=wp), | intent(in) | :: | dy | |||
| real(kind=wp), | intent(in) | :: | size | |||
| character(len=*), | intent(in) | :: | style | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | width | |||
| integer, | intent(in) | :: | height | |||
| logical, | intent(out) | :: | has_rendered_arrows | |||
| logical, | intent(out) | :: | uses_vector_arrows | |||
| logical, | intent(out) | :: | has_triangular_arrows |
Project a quiver vector to a text cell, clip it to the interior plot
area, and stamp an eight-direction ASCII glyph at data-layer priority
so it never overwrites axis spines, ticks, or label text (issue #2071).
u/v are the already scaled vector components in data units, so
the caller's scale factor still governs which arrows survive the
minimum-shaft cut. The interior clip drops vectors that would land on
the frame or in the tick/axis label margin.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in) | :: | x | |||
| real(kind=wp), | intent(in) | :: | y | |||
| real(kind=wp), | intent(in) | :: | u | |||
| real(kind=wp), | intent(in) | :: | v | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in) | :: | x1 | |||
| real(kind=wp), | intent(in) | :: | y1 | |||
| real(kind=wp), | intent(in) | :: | x2 | |||
| real(kind=wp), | intent(in) | :: | y2 | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height | |||
| character(len=1), | intent(in) | :: | line_char |
Rasterize a streamplot trajectory segment thinned to terminal-cell resolution (issue #2070). Flow cells are placed through the layer policy so they never overwrite axes, ticks, or labels, and a minimum horizontal gap keeps any single row from being flooded with flow glyphs. The result is a sparse dotted flow field instead of a dense run of hyphen fragments.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in) | :: | x1 | |||
| real(kind=wp), | intent(in) | :: | y1 | |||
| real(kind=wp), | intent(in) | :: | x2 | |||
| real(kind=wp), | intent(in) | :: | y2 | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| type(plot_area_t), | intent(in) | :: | plot_area | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height |
Draw the solid left and bottom axis spines plus the corner tick. Spines are filled cell-by-cell in screen space so they stay continuous regardless of the data range (issue #2069).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| integer, | intent(in) | :: | axis_col | |||
| integer, | intent(in) | :: | bottom_row | |||
| integer, | intent(in) | :: | top_row | |||
| integer, | intent(in) | :: | right_col |
Draw a single tick mark on a spine at a labeled tick position.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| integer, | intent(in) | :: | row | |||
| integer, | intent(in) | :: | col |
Fill interior grid glyphs aligned to major-tick columns and rows. Grid cells are drawn at LAYER_GRID, the lowest drawable layer, so put_cell leaves data, axis spines, tick marks, and labels intact and only paints otherwise-blank interior cells (issue #2074).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| integer, | intent(in) | :: | x_cols(:) | |||
| integer, | intent(in) | :: | num_x | |||
| integer, | intent(in) | :: | y_rows(:) | |||
| integer, | intent(in) | :: | num_y | |||
| integer, | intent(in) | :: | top_row | |||
| integer, | intent(in) | :: | bottom_row | |||
| integer, | intent(in) | :: | left_col | |||
| integer, | intent(in) | :: | right_col |
Paint filled-contour bands into the ASCII canvas with an ordered glyph ramp (issue #2077). Each interior character cell is mapped back to a data coordinate (same screen mapping as ascii_fill_quad_primitive), its scalar value is looked up on the grid, and the band index selects a ramp glyph. Cells are written through put_cell at LAYER_DATA so axis spines, ticks, and labels stay reserved.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=1), | intent(inout) | :: | canvas(:,:) | |||
| real(kind=wp), | intent(in), | contiguous | :: | x_grid(:) | ||
| real(kind=wp), | intent(in), | contiguous | :: | y_grid(:) | ||
| real(kind=wp), | intent(in), | contiguous | :: | z_grid(:,:) | ||
| real(kind=wp), | intent(in) | :: | levels(:) | |||
| real(kind=wp), | intent(in) | :: | x_min | |||
| real(kind=wp), | intent(in) | :: | x_max | |||
| real(kind=wp), | intent(in) | :: | y_min | |||
| real(kind=wp), | intent(in) | :: | y_max | |||
| integer, | intent(in) | :: | plot_width | |||
| integer, | intent(in) | :: | plot_height |