% File: hawkdraw-arrows.code.tex
% Copyright 2026 Jasper Habicht (mail(at)jasperhabicht.de).
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License version 1.3c,
% available at http://www.latex-project.org/lppl/.
%
% This file is part of the `hawkdraw' package (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% This work has the LPPL maintenance status `maintained'.
%
% BOF

% v0.4.1 2026-07-08

\msg_new:nnn { hawkdraw } { arrow-unknown } {
    Arrow ~ tip ~ `#1` ~ unknown.
}

\prop_new:N \g_hawkdraw_arrow_default_keys_prop
\clist_new:N \l_hawkdraw_arrow_start_keys_clist
\clist_new:N \l_hawkdraw_arrow_end_keys_clist

\keys_define:nn { hawkdraw / path } {
    arrow ~ start           .code:n         = {
        \tl_put_right:Nn \l_hawkdraw_path_postactions_tl {
            \fp_if_nan:nF { \g_hawkdraw_path_slope_first_fp } {
                \hawkdraw_arrow:nnnV {#1}
                    { \g_hawkdraw_path_point_first_fp }
                    { \g_hawkdraw_path_slope_first_fp + 90 }
                    \l_hawkdraw_arrow_start_keys_clist
            }
        }
    } ,
    arrow ~ start           .default:n      = { default } ,
    arrow ~ end             .code:n         = {
        \tl_put_right:Nn \l_hawkdraw_path_postactions_tl {
            \fp_if_nan:nF { \g_hawkdraw_path_slope_last_fp } {
                \hawkdraw_arrow:nnnV {#1}
                    { \g_hawkdraw_path_point_last_fp }
                    { \g_hawkdraw_path_slope_last_fp - 90 }
                    \l_hawkdraw_arrow_end_keys_clist
            }
        }
    } ,
    arrow ~ end             .default:n      = { default } ,
    arrow ~ start ~ style ~ set
                            .clist_set:N    = \l_hawkdraw_arrow_start_keys_clist ,
    arrow ~ end ~ style ~ set
                            .clist_set:N    = \l_hawkdraw_arrow_end_keys_clist ,
    arrow ~ start ~ style ~ add
                            .code:n         = {
        \clist_put_right:Nn \l_hawkdraw_arrow_start_keys_clist {#1}
    } ,
    arrow ~ end ~ style ~ add
                            .code:n         = {
        \clist_put_right:Nn \l_hawkdraw_arrow_end_keys_clist {#1}
    } ,
    arrow ~ style ~ set     .code:n         = {
        \clist_set:Nn \l_hawkdraw_arrow_start_keys_clist {#1}
        \clist_set:Nn \l_hawkdraw_arrow_end_keys_clist {#1}
    } ,
    arrow ~ style ~ add     .code:n         = {
        \clist_put_right:Nn \l_hawkdraw_arrow_start_keys_clist {#1}
        \clist_put_right:Nn \l_hawkdraw_arrow_end_keys_clist {#1}
    } ,
}

\cs_new_protected:Npn \hawkdraw_arrow:nnnn #1#2#3#4 {
    \draw_scope_begin:
        \draw_transform_shift:n {#2}
        \draw_transform_rotate:n {#3}
        \clist_clear:N \l_hawkdraw_path_use_clist
        \keys_set:ne { hawkdraw / path } {
            \prop_item:Nn \g_hawkdraw_arrow_default_keys_prop {#1}
        }
        \keys_set:nn { hawkdraw / path } {#4}
        \hawkdraw_path_set_options:
        \cs_if_exist_use:cF { hawkdraw_arrow_tip_ #1 : } {
            \msg_warning:nnn { hawkdraw } { arrow-unknown } {#1}
        }
        \draw_path_use_clear:e { \clist_use:N \l_hawkdraw_path_use_clist }
    \draw_scope_end:
}
\cs_generate_variant:Nn \hawkdraw_arrow:nnnn { nnnV }

\cs_new_protected:Npn \hawkdraw_arrow_create:nnn #1#2#3 {
    \prop_gput:Nnn \g_hawkdraw_arrow_default_keys_prop {#1} {#2}
    \cs_new_protected:cpn { hawkdraw_arrow_tip_ #1 : } {
        #3
    }
}

% ===

\hawkdraw_operator_construct_arg:nN { tip } \hawkdraw_arrow_single:nn

\cs_new_protected:Npn \hawkdraw_arrow_single:nn #1#2 {
    \clist_clear:N \l__hawkdraw_keys_unprocessed_clist
    \keys_set_known:nnN { hawkdraw / path / tip } {#1}
        \l__hawkdraw_keys_unprocessed_clist
    \tl_put_right:Ne \l_hawkdraw_path_postactions_tl {
        \exp_not:N
        \hawkdraw_arrow:nnnn {#2} {
            \use:c { __hawkdraw_point_part_ \l__hawkdraw_path_type_tl :V }
                \l_hawkdraw_tip_at_part_fp
        } {
            \use:c { __hawkdraw_point_part_slope_ \l__hawkdraw_path_type_tl :V }
                \l_hawkdraw_tip_at_part_fp
            \bool_if:NTF \l_hawkdraw_tip_flipped_bool {
                + 90
            } {
                - 90
            }
        }
        { \clist_use:N \l__hawkdraw_keys_unprocessed_clist }
    }
}
\cs_generate_variant:Nn \hawkdraw_arrow_single:nn { en }

\fp_new:N \l_hawkdraw_tip_at_part_fp
\bool_new:N \l_hawkdraw_tip_flipped_bool

\keys_define:nn { hawkdraw / path / tip } {
    at ~ part               .fp_set:N       = \l_hawkdraw_tip_at_part_fp ,
    at ~ part               .initial:n      = { 1 } ,
    at ~ distance           .code:n         = {
        \hawkdraw_path_get_length:
        \fp_set:Nn \l_hawkdraw_tip_at_part_fp {
            #1 / \g_hawkdraw_path_length_fp
        }
    } ,
    flipped                 .bool_set:N     = \l_hawkdraw_tip_flipped_bool ,
    flipped                 .default:n      = { true } ,
}

\cs_new_protected:cpn { __hawkdraw_path_process_tip_ [ :w } [ #1 ] #2#3 \s__hawkdraw_stop {
    \hawkdraw_arrow_single:en { \clist_use:N \l__hawkdraw_keys_unprocessed_clist } {#2}
    \tl_trim_spaces_apply:nN {#3} \__hawkdraw_path_process_continue:n
}

% ===

\hawkdraw_arrow_create:nnn { none } { } { }

\hawkdraw_arrow_create:nnn { default } {
    fill
} {
    \draw_path_moveto:n { -2.5 , -5 }
    \draw_path_curveto:nn { -1 , -3 } { 0 , 0 }
    \draw_path_curveto:nn { 1 , -3 } { 2.5 , -5 }
    \draw_path_close:
}

\hawkdraw_arrow_create:nnn { stealth } {
    fill
} {
    \draw_path_moveto:n { 0 , 0 }
    \draw_path_lineto:n { -2.5 , -5 }
    \draw_path_lineto:n { 0 , -3.5 }
    \draw_path_lineto:n { 2.5 , -5 }
    \draw_path_close:
}

\hawkdraw_arrow_create:nnn { triangle } {
    fill
} {
    \draw_path_moveto:n { 0 , 0 }
    \draw_path_lineto:n { -2.5 , -5 }
    \draw_path_lineto:n { 2.5 , -5 }
    \draw_path_close:
}

\hawkdraw_arrow_create:nnn { kite } {
    fill
} {
    \draw_path_moveto:n { 0 , 0 }
    \draw_path_lineto:n { -2.5 , -5 }
    \draw_path_lineto:n { 0 , -7.5 }
    \draw_path_lineto:n { 2.5 , -5 }
    \draw_path_close:
}

\hawkdraw_arrow_create:nnn { circle } {
    fill
} {
    \draw_path_circle:nn { 0 , -2.5 } { 2.5 }
}

\hawkdraw_arrow_create:nnn { simple } {
    stroke ,
    line ~ cap = { round } ,
    line ~ join = { round }
} {
    \draw_path_moveto:n { -3 , -3 }
    \draw_path_curveto:nn { -0.5 , -1.25 } { 0 , 0 }
    \draw_path_curveto:nn { 0.5 , -1.25 } { 3 , -3 }
}

\hawkdraw_arrow_create:nnn { straight } {
    stroke
} {
    \draw_path_moveto:n { -3 , -3 }
    \draw_path_lineto:n { 0 , 0 }
    \draw_path_lineto:n { 3 , -3 }
}

\hawkdraw_arrow_create:nnn { bar } {
    stroke
} {
    \draw_path_moveto:n { -3 , 0 }
    \draw_path_lineto:n { 3 , 0 }
}

\hawkdraw_arrow_create:nnn { slash } {
    stroke
} {
    \draw_path_moveto:n { -3 , 3 }
    \draw_path_lineto:n { 3 , -3 }
}

\hawkdraw_arrow_create:nnn { barslash } {
    stroke
} {
    \draw_path_moveto:n { 0 , 0 }
    \draw_path_lineto:n { 0 , 3 }
    \draw_path_moveto:n { -3 , 0 }
    \draw_path_lineto:n { 3 , 0 }
    \draw_path_moveto:n { -2 , 2 }
    \draw_path_lineto:n { 2 , -2 }
}

\hawkdraw_arrow_create:nnn { tail } {
    fill
} {
    \draw_path_moveto:n { 0 , 0 }
    \draw_path_lineto:n { -2.5 , 2.5 }
    \draw_path_lineto:n { -2.5 , -2.5 }
    \draw_path_lineto:n { 0 , -5 }
    \draw_path_lineto:n { 2.5 , -2.5 }
    \draw_path_lineto:n { 2.5 , 2.5 }
    \draw_path_close:
}

% EOF
