fortplot_ascii_drawing Module

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.



Derived Types

type, public ::  text_charset_t

Components

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

Functions

public pure function ascii_contour_glyph(band, n_bands) result(glyph)

Map a 1-based band index onto the ordered density ramp.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: band
integer, intent(in) :: n_bands

Return Value character(len=1)

public function unicode_glyphs() result(glyphs)

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.

Arguments

None

Return Value type(text_charset_t)

public function normalize_text_charset(name) result(mode)

Canonicalize a user charset selection to 'ascii' or 'unicode'. 'auto' resolves through the environment; anything unrecognized falls back to the ASCII compatibility charset.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

Return Value character(len=:), allocatable

public function resolve_text_charset_from_environment() result(mode)

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

Arguments

None

Return Value character(len=:), allocatable

public pure function charset_is_unicode(mode) result(is_unicode)

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: mode

Return Value logical

public function text_frame_line(width, glyphs, is_top) result(line)

Build the top or bottom frame border for the given charset. In ASCII mode this reproduces the historical '+' // '-'*width // '+' border.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: width
type(text_charset_t), intent(in) :: glyphs
logical, intent(in) :: is_top

Return Value character(len=:), allocatable

public function translate_text_cell(ch, glyphs) result(token)

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.

Arguments

Type IntentOptional Attributes Name
character(len=1), intent(in) :: ch
type(text_charset_t), intent(in) :: glyphs

Return Value character(len=:), allocatable


Subroutines

public subroutine draw_ascii_marker(canvas, x, y, style, x_min, x_max, y_min, y_max, plot_area, plot_width, plot_height)

Arguments

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

public subroutine fill_ascii_heatmap(canvas, x_grid, y_grid, z_grid, z_min, z_max, x_min, x_max, y_min, y_max, plot_area, plot_width, plot_height, canvas_color, colormap_name)

Fill ASCII canvas with heatmap representation of 2D data

Arguments

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

public subroutine draw_ascii_arrow(canvas, x, y, dx, dy, size, style, x_min, x_max, y_min, y_max, plot_area, width, height, has_rendered_arrows, uses_vector_arrows, has_triangular_arrows)

Draw arrow using Unicode directional characters for ASCII backend

Arguments

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

public subroutine draw_ascii_vector_arrow(canvas, x, y, u, v, x_min, x_max, y_min, y_max, plot_area, plot_width, plot_height)

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.

Arguments

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

public subroutine draw_line_on_canvas(canvas, x1, y1, x2, y2, x_min, x_max, y_min, y_max, plot_area, plot_width, plot_height, line_char)

Arguments

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

public subroutine draw_ascii_stream_segment(canvas, x1, y1, x2, y2, x_min, x_max, y_min, y_max, plot_area, plot_width, plot_height)

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.

Arguments

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

public subroutine draw_text_axis_frame(canvas, axis_col, bottom_row, top_row, right_col)

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

Arguments

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

public subroutine draw_text_axis_tick(canvas, row, col)

Draw a single tick mark on a spine at a labeled tick position.

Arguments

Type IntentOptional Attributes Name
character(len=1), intent(inout) :: canvas(:,:)
integer, intent(in) :: row
integer, intent(in) :: col

public subroutine draw_text_grid_lines(canvas, x_cols, num_x, y_rows, num_y, top_row, bottom_row, left_col, right_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).

Arguments

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

public subroutine fill_ascii_contour(canvas, x_grid, y_grid, z_grid, levels, x_min, x_max, y_min, y_max, plot_width, plot_height)

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.

Arguments

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