% File: hawkdraw-patterns.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.0 2026-07-01

\msg_new:nnn { hawkdraw } { pattern-unknown } {
    Pattern ~ `#1` ~ unknown.
}

\prop_new:N \g_hawkdraw_pattern_default_keys_prop
\clist_new:N \l_hawkdraw_pattern_keys_clist
\box_new:N \l_hawkdraw_pattern_box
\dim_new:N \l__hawkdraw_pattern_width_dim
\dim_new:N \l__hawkdraw_pattern_height_dim
\fp_new:N \l_hawkdraw_pattern_tile_size_fp

\keys_define:nn { hawkdraw / path } {
    fill ~ pattern          .code:n         = {
        \tl_put_right:Nn \l_hawkdraw_path_postactions_tl {
            \draw_scope_begin:
                \tl_trim_spaces_apply:nN { \g_hawkdraw_softpath_original_tl } \__hawkdraw_path_process:o
                \tl_use:N \g_hawkdraw_softpath_original_tl
                \draw_path_use_clear:n { clip }
                \hawkdraw_pattern_fill:nV {#1} \l_hawkdraw_pattern_keys_clist
                \bool_gset_false:N \g__hawkdraw_path_use_clip_bool
            \draw_scope_end:
        }
    } ,
    pattern ~ style ~ set   .clist_set:N    = \l_hawkdraw_pattern_keys_clist ,
    pattern ~ style ~ add   .code:n         = {
        \clist_put_right:Nn \l_hawkdraw_pattern_keys_clist {#1}
    } ,
    pattern ~ tile ~ size   .fp_set:N      = \l_hawkdraw_pattern_tile_size_fp ,
    pattern ~ tile ~ size   .initial:n     = { ( 10pt , 10pt ) } ,
}

\cs_new_protected:Npn \hawkdraw_pattern_fill:nn #1#2 {
    \prop_if_in:NnF \g_hawkdraw_pattern_default_keys_prop {#1} {
        \msg_warning:nnn { hawkdraw } { pattern-unknown } {#1}
    }
    \pdfxform_if_exist:nF {
        hawkdraw_pattern_
        #1 . \str_mdfive_hash:n {#2}
    } {
        \hawkdraw_pattern_set:nn {#1} {#2}
    }
    \hbox_set:Nn \l_hawkdraw_pattern_box {
        \pdfxform_use:n {
            hawkdraw_pattern_
            #1 . \str_mdfive_hash:n {#2}
        }
    }
    \dim_set:Nn \l__hawkdraw_pattern_width_dim {
        \box_wd:N \l_hawkdraw_pattern_box
    }
    \dim_set:Nn \l__hawkdraw_pattern_height_dim {
        \box_ht_plus_dp:N \l_hawkdraw_pattern_box
    }
    \bool_set_false:N \l_draw_bb_update_bool
    \int_step_inline:nnn {
        \fp_to_int:n {
            floor( \g_draw_bb_xmin_dim / \l__hawkdraw_pattern_width_dim )
        }
    } {
        \fp_to_int:n {
            floor( \g_draw_bb_xmax_dim / \l__hawkdraw_pattern_width_dim )
        }
    } {
        \int_step_inline:nnn {
            \fp_to_int:n {
                floor( \g_draw_bb_ymin_dim / \l__hawkdraw_pattern_height_dim )
            }
        } {
            \fp_to_int:n {
                floor( \g_draw_bb_ymax_dim / \l__hawkdraw_pattern_height_dim )
            }
        } {
            \draw_box_use:Nn \l_hawkdraw_pattern_box {
                ##1 * \l__hawkdraw_pattern_width_dim
                ,
                ####1 * \l__hawkdraw_pattern_height_dim
            }
        }
    }
    \bool_set_true:N \l_draw_bb_update_bool
}
\cs_generate_variant:Nn \hawkdraw_pattern_fill:nn { nV }

\cs_new_protected:Npn \hawkdraw_pattern_set:nn #1#2 {
    \pdfxform_new:nnn {
        hawkdraw_pattern_
        #1 . \str_mdfive_hash:n {#2}
    } { } {
        \draw_suspend_begin:
            \draw_begin:
                \draw_set_baseline:n { 0pt }
                \clist_clear:N \l_hawkdraw_path_use_clist
                \keys_set:ne { hawkdraw / path } {
                    \prop_item:Nn \g_hawkdraw_pattern_default_keys_prop {#1}
                }
                \keys_set:nn { hawkdraw / path } {#2}
                \hawkdraw_path_set_options:
                \draw_path_rectangle:nn { 0pt , 0pt } { \l_hawkdraw_pattern_tile_size_fp }
                \draw_path_use_clear:n { }
                \bool_set_false:N \l_draw_bb_update_bool
                \use:c { hawkdraw_pattern_ #1 : }
            \draw_end:
        \draw_suspend_end:
    }
}

\cs_new_protected:Npn \hawkdraw_pattern_create:nnn #1#2#3 {
    \prop_gput:Nnn \g_hawkdraw_pattern_default_keys_prop {#1} {#2}
    \cs_new_protected:cpn { hawkdraw_pattern_ #1 : } {
        #3
    }
}

% ===

\hawkdraw_pattern_create:nnn { lines } { } {
    \draw_path_moveto:n { 0pt , 5pt }
    \draw_path_lineto:n { 10pt , 5pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { waves } { } {
    \draw_path_moveto:n { 0pt , 2.5pt }
    \draw_path_curveto:nnn { 2.5pt , 2.5pt } { 2.5pt , 7.5pt } { 5pt , 7.5pt }
    \draw_path_curveto:nnn { 7.5pt , 7.5pt } { 7.5pt , 2.5pt } { 10pt , 2.5pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { hatch } { } {
    \draw_path_moveto:n { 0pt , 5pt }
    \draw_path_lineto:n { 10pt , 5pt }
    \draw_path_moveto:n { 5pt , 0pt }
    \draw_path_lineto:n { 5pt , 10pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { dots } { } {
    \draw_path_circle:nn { 5pt , 5pt } { 2.5pt }
    \draw_path_use_clear:n { fill }
}

\hawkdraw_pattern_create:nnn { circles } { } {
    \draw_path_circle:nn { 5pt , 5pt } { 2.5pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { plus } { } {
    \draw_path_moveto:n { 5pt , 2.5pt }
    \draw_path_lineto:n { 5pt , 7.5pt }
    \draw_path_moveto:n { 2.5pt , 5pt }
    \draw_path_lineto:n { 7.5pt , 5pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { minus } { } {
    \draw_path_moveto:n { 2.5pt , 5pt }
    \draw_path_lineto:n { 7.5pt , 5pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { check } { } {
    \draw_path_rectangle:nn { 0pt , 0pt } { 5pt , 5pt }
    \draw_path_rectangle:nn { 5pt , 5pt } { 10pt , 10pt }
    \draw_path_use_clear:n { fill }
}

\hawkdraw_pattern_create:nnn { masonry } { } {
    \draw_path_moveto:n { 0pt , 2.5pt }
    \draw_path_lineto:n { 10pt , 2.5pt }
    \draw_path_moveto:n { 0pt , 7.5pt }
    \draw_path_lineto:n { 10pt , 7.5pt }
    \draw_path_moveto:n { 2.5pt , 10pt }
    \draw_path_lineto:n { 2.5pt , 7.5pt }
    \draw_path_moveto:n { 7.5pt , 7.5pt }
    \draw_path_lineto:n { 7.5pt , 2.5pt }
    \draw_path_moveto:n { 2.5pt , 2.5pt }
    \draw_path_lineto:n { 2.5pt , 0pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { herringbone } { } {
    \draw_path_moveto:n { 0pt , 0pt }
    \draw_path_lineto:n { 5pt , 5pt }
    \draw_path_lineto:n { 10pt , 0pt }
    \draw_path_moveto:n { 2.5pt , 2.5pt }
    \draw_path_lineto:n { 5pt , 0pt }
    \draw_path_moveto:n { 7.5pt , 2.5pt }
    \draw_path_lineto:n { 10pt , 5pt }
    \draw_path_moveto:n { 0pt , 5pt }
    \draw_path_lineto:n { 5pt , 10pt }
    \draw_path_lineto:n { 10pt , 5pt }
    \draw_path_moveto:n { 2.5pt , 7.5pt }
    \draw_path_lineto:n { 5pt , 5pt }
    \draw_path_moveto:n { 7.5pt , 7.5pt }
    \draw_path_lineto:n { 10pt , 10pt }
    \draw_path_use_clear:n { stroke }
}

\hawkdraw_pattern_create:nnn { hexagonal } {
    pattern ~ tile ~ size = {
        \fp_to_dim:n { cosd( 30 ) * 20/3pt } ,
        10pt
    }
} {
    \draw_path_moveto:n { 0pt , 0pt }
    \draw_path_lineto:n { 0pt , 5/3pt }
    \draw_path_lineto:n {
        ( 0pt , 5/3pt ) + 
        ( \draw_point_polar:nn { 10/3pt } { 30 } )
    }
    \draw_path_lineto:n {
        ( 0pt , 15/3pt ) +
        ( \draw_point_polar:nn { 10/3pt } { 30 } )
    }
    \draw_path_lineto:n { 0pt , 25/3pt }
    \draw_path_lineto:n { 0pt , 10pt }
    \draw_path_moveto:n {
        ( 0pt , 15/3pt ) +
        ( \draw_point_polar:nn { 10/3pt } { 30 } )
    }
    \draw_path_lineto:n {
        ( 0pt , 15/3pt ) +
        ( \draw_point_polar:nn { 20/3pt } { 30 } )
    }
    \draw_path_lineto:n {
        ( 0pt , 25/3pt ) +
        ( \draw_point_polar:nn { 20/3pt } { 30 } )
    }
    \draw_path_moveto:n {
        ( 0pt , 5/3pt ) +
        ( \draw_point_polar:nn { 10/3pt } { 30 } )
    }
    \draw_path_lineto:n {
        ( 0pt , 15/3pt ) +
        ( \draw_point_polar:nn { 20/3pt } { -30 } )
    }
    \draw_path_lineto:n {
        ( 0pt , 10/3pt ) +
        ( \draw_point_polar:nn { 20/3pt } { -30 } )
    }
    \draw_path_use_clear:n { stroke }
}

%EOF