module fortplot_spec_rendering_utils !! Shared utilities for spec rendering modules. !! !! Contains functions used across spec_rendering, mark_handlers, !! and field_rendering without pulling in heavy dependencies. use, intrinsic :: iso_fortran_env, only: wp => real64 use fortplot_constants, only: APPROX_EQUAL_TOLERANCE use fortplot_colors, only: parse_color use fortplot_spec_types, only: encoding_t, data_t implicit none private public :: get_label_from_encoding public :: approx_equal public :: ends_with contains function get_label_from_encoding(enc, data) result(label) type(encoding_t), intent(in) :: enc type(data_t), intent(in), optional :: data character(len=:), allocatable :: label integer :: value_length, i, j character(len=:), allocatable :: field_name if (.not. enc%color%defined) return if (allocated(enc%color%value)) then value_length = len(enc%color%value) if (value_length >= 2 .and. enc%color%value(1:1) == '"' .and. & enc%color%value(value_length:value_length) == '"') then label = enc%color%value(2:value_length - 1) else label = enc%color%value end if return end if if (.not. present(data)) return if (.not. allocated(enc%color%field)) return if (.not. allocated(data%columns)) return field_name = enc%color%field do i = 1, size(data%columns) if (data%columns(i)%field /= field_name) cycle if (.not. data%columns(i)%is_string) return if (.not. allocated(data%columns(i)%string_values)) return if (size(data%columns(i)%string_values) == 0) return label = trim(data%columns(i)%string_values(1)) if (len_trim(label) == 0) then return end if if (size(data%columns(i)%string_values) > 1) then do j = 2, size(data%columns(i)%string_values) if (trim(data%columns(i)%string_values(j)) /= label) then exit end if end do end if return end do end function get_label_from_encoding logical function approx_equal(a, b) result(equal) real(wp), intent(in) :: a, b equal = abs(a - b) < APPROX_EQUAL_TOLERANCE end function approx_equal logical function ends_with(text, suffix) result(matches) character(len=*), intent(in) :: text character(len=*), intent(in) :: suffix integer :: text_length integer :: suffix_length text_length = len_trim(text) suffix_length = len_trim(suffix) if (suffix_length == 0 .or. suffix_length > text_length) then matches = .false. return end if matches = text(text_length - suffix_length + 1:text_length) == & suffix(1:suffix_length) end function ends_with end module fortplot_spec_rendering_utils