% pgfornament.sty (utf8 encoding)
% Copyright 2012-2026  Alain Matthes
% SPDX-License-Identifier: LPPL-1.3c
% Maintainer: Alain Matthes
%---------%---------%---------%---------%---------%---------%---------%---------
%  First version created by Alain Matthes le 2012-02-22.
%---------%---------%---------%---------%---------%---------%---------%---------
% Inspired from psvectorian P Fradin H Voss
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{tikz,pgfopts}
\ProvidesPackage{pgfornament}[2026/10/17 v1.4 vector ornaments]
%---------%---------%---------%---------%---------%---------%---------%---------
%    family of ornaments (option object, default vectorian)
%---------%---------%---------%---------%---------%---------%---------%---------
% v1.4 : the runtime files share the prefix pgfornament- (TeX Live rule):
%   library  pgfornament-lib-<family>.code.tex
%   ornament pgfornament-<family><n>.pgf
% The old names (pgflibrary<family>.code.tex, <family><n>.pgf) are still
% accepted, for the families created by users with the previous versions.
\gdef\OrnamentsFamily{vectorian}%
\pgfkeys{%
  /pgfOrnaments/object/.code = {\gdef\OrnamentsFamily{#1}}%
}%
\ProcessPgfOptions{/pgfOrnaments}%
\usetikzlibrary{calc}% v1.4 : needed by \pgfornamenthline and \pgfornamentvline
%---------%---------%---------%---------%---------%---------%---------%---------
%    tools
%---------%---------%---------%---------%---------%---------%---------%---------
% loading of a family. The library files only define \@pgfornamentDim.
\def\pgfornament@loadfamily#1{%
  \edef\OrnamentsFamily{#1}%
  \IfFileExists{pgfornament-lib-\OrnamentsFamily.code.tex}{%
    \xdef\pgfOrnamentsObject{pgfornament-lib-\OrnamentsFamily.code.tex}%
    \def\pgfornament@prefix{pgfornament-}%
  }{% family made with a version < 1.4
    \xdef\pgfOrnamentsObject{pgflibrary\OrnamentsFamily.code.tex}%
    \def\pgfornament@prefix{}%
  }%
  \input{\pgfOrnamentsObject}%
}%
\pgfornament@loadfamily{\OrnamentsFamily}%
\def\newpgfornamentfamily#1{\pgfornament@loadfamily{#1}}%
% the environment is a group : the previous family is restored at the end
\newenvironment{newfamily}[1][vectorian]{%
  \newpgfornamentfamily{#1}%
  \ignorespaces
}{%
  \ignorespacesafterend
}%

% v1.4 : common definitions of the short macros used in the .pgf files
\def\pgfornament@shortcuts{%
  \def\ubb{\pgfusepath{use as bounding box}}%
  \def\i{\pgfusepath{clip}}%
  \def\k{\pgfusepath{stroke}}%
  \let\o\pgfpathclose
  \let\s\pgfusepathqfillstroke
  \def\p ##1##2{\pgfqpoint{##1bp}{##2bp}}%
  \def\m ##1 ##2 {\pgfpathmoveto{\p{##1}{##2}}}%
  \def\l ##1 ##2 {\pgfpathlineto{\p{##1}{##2}}}%
  \def\r ##1 ##2 ##3 ##4 {\pgfpathrectangle{\p{##1}{##2}}{\p{##3}{##4}}}%
  \def\c ##1 ##2 ##3 ##4 ##5 ##6 {%
    \pgfpathcurveto{\p{##1}{##2}}{\p{##3}{##4}}{\p{##5}{##6}}}%
}%

\def\pgf@@ornament#1{%
  \begingroup
  \pgfornament@shortcuts
  \@@input \pgfornament@prefix\OrnamentsFamily#1.pgf\relax
  \endgroup
}%

\newcommand{\callornament}[1]{%
  \begingroup
  \pgfornament@shortcuts
  \IfFileExists{pgfornament-#1}% v1.4 : \callornament{vectorian1.pgf} still works
    {\@@input pgfornament-#1\relax}%
    {\@@input #1\relax}%
  \endgroup
}%
%---------%---------%---------%---------%---------%---------%---------%---------
% Les options de \pgfornament sont:
%
% scale        : nombre (échelle, 1 par défaut)
% width        : nombre + unité (largeur, naturelle par défaut)
% height       : nombre + unité (hauteur, naturelle par défaut)
% color        : couleur ( par défaut couleur courante )
% symmetry=h   : true/false (symétrie horizontale, false par défaut)
% symmetry=v   : true/false (symétrie verticale,   false par défaut)
% symmetry=c   : true/false (symétrie centrale h+v,false par défaut)
%---------%---------%---------%---------%---------%---------%---------%--------
\tikzset{pgfornamentstyle/.style={}}%
\pgfkeys{%
  /ornament/.cd,
  scale/.code         =  {\def\pgfornamentscale{#1}},
  width/.code         =  {\def\pgfornamentwidth{#1}},
  height/.code        =  {\def\pgfornamentheight{#1}},
  color/.code         =  {\def\pgfornamentcolor{#1}},
  opacity/.code       =  {\def\pgfornamentopacity{#1}},
  anchor/.code        =  {\def\pgfornamentanchor{#1}},
  ydelta/.code        =  {\def\pgfornamentydelta{#1}},
  symmetry/.is choice,
  symmetry/v/.code     = {\tikzset{pgfornamentstyle/.append
     style={cm={-1,0,0,1,(0,0)}}}},
  symmetry/c/.code     = {\tikzset{pgfornamentstyle/.append
     style={cm={-1,0,0,-1,(0,0)}}}},
  symmetry/h/.code     = {\tikzset{pgfornamentstyle/.append
     style={cm={1,0,0,-1,(0,0)}}}},
  symmetry/none/.code  = {\tikzset{pgfornamentstyle/.append style={cm={1,0,0,1,(0,0)}}}}%
}%
%---------%---------%---------%---------%---------%---------%---------%---------
\def\pgfornament{\pgfutil@ifnextchar[{\pgf@ornament}{\pgf@ornament[]}}%
\def\pgf@ornament[#1]#2{%
\pgfkeys{%
  /ornament/.cd,
   scale    =  1,
   opacity  =  {},
   width    =  {},
   height   =  {},
   color    =  {},
   ydelta   =  0 pt,
   symmetry =  none ,
   anchor   =  center
   }%
\pgfqkeys{/ornament}{#1}%
\ifx\pgfornamentcolor\empty\else
    \tikzset{pgfornamentstyle/.append style={color=\pgfornamentcolor}}%
\fi
\ifx\pgfornamentopacity\empty\else
    \tikzset{pgfornamentstyle/.append style={opacity=\pgfornamentopacity}}%
\fi
\ifx\pgfornamentwidth\empty
   \else
   \@pgfornamentDim{#2}% bug correction LianTze
   \pgfmathsetmacro{\pgfornamentscale}{\pgfornamentwidth/\@pgfornamentX bp}%
\fi
\ifx\pgfornamentheight\empty
   \else
    \@pgfornamentDim{#2}% bug correction LianTze
    \pgfmathsetmacro{\pgfornamentscale}{\pgfornamentheight/\@pgfornamentY bp}%
\fi
\begin{tikzpicture}[%
baseline={([yshift=\pgfornamentydelta]current bounding box.\pgfornamentanchor)},
   pgfornamentstyle]
   \pgftransformscale{\pgfornamentscale}%
   \pgf@@ornament{#2}%
\end{tikzpicture}%
\tikzset{pgfornamentstyle/.style={cm={1,0,0,1,(0,0)}}}%
}% end pgfornament

\gdef\ornamenttopos{.5}
\gdef\ornamenttoanchor{center}
\gdef\ornamenttosymmetry{none}
\tikzset{options default/.style={anchor=center,
                                 sloped,
                                 allow upside down,
                                 inner sep=0pt}}
\tikzset{ornament/at/.code={\def\ornamenttopos{#1}},
         options/.style={options default,#1},
         ornament symmetry/.code={\def\ornamenttosymmetry{#1}},
         node anchor/.code={\def\ornamenttoanchor{#1}},
         ornament/.style={%
         to path={%
\pgfextra{%
      \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
         \pgf@xa=\pgf@x
         \pgf@ya=\pgf@y
      \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
         \pgf@xb=\pgf@x
         \pgf@yb=\pgf@y
         \advance\pgf@xa by-\pgf@xb
         \advance\pgf@ya by-\pgf@yb
      \pgfmathveclen{\pgf@xa}{\pgf@ya}%
      \global\let\ornamentlen\pgfmathresult}
       --  node [pos=\ornamenttopos,options,
              anchor=\ornamenttoanchor]{%
        \pgfornament[width    = \ornamentlen,
                 symmetry=\ornamenttosymmetry]{#1}}
            (\tikztotarget)\tikztonodes %end pgfextra
    }% end to path
  }% end style
}% end \tikzset

\def\pgfornamenthline#1#2#3#4{%
  \pgfextractx{\pgf@x}{\pgfpointanchor{#1}{#3 east}}%
  \pgf@xa=\pgf@x
  \pgfextractx{\pgf@x}{\pgfpointanchor{#2}{#3 west}}%
  \pgf@xb=\pgf@x
  \advance\pgf@xb by -\pgf@xa
  \node[inner sep=0pt] at ($(#1.#3 east)!.5!(#2.#3 west)$)
     {\pgfornament[width=\pgf@xb]{#4}};%
}%
\def\pgfornamentvline#1#2#3#4{%
  \pgfextracty{\pgf@y}{\pgfpointanchor{#1}{south #3}}%
  \pgf@ya=\pgf@y
  \pgfextracty{\pgf@y}{\pgfpointanchor{#2}{north #3}}%
  \pgf@yb=\pgf@y
  \advance\pgf@yb by -\pgf@ya
  \node[inner sep=0pt,rotate=90] at ($(#1.south #3)!.5!(#2.north #3)$)
     {\pgfornament[width=\pgf@yb]{#4}};%
}%
\def\getornamentlength#1#2#3#4{%
  \pgfpointdiff{\pgfpointanchor{#1}{#2}}%
               {\pgfpointanchor{#3}{#4}}%
  \pgf@xa=\pgf@x
  \pgf@ya=\pgf@y
  \pgfmathveclen{\pgf@xa}{\pgf@ya}%
  \global\let\ornamentlen\pgfmathresult
}%
\def\getornamentangle#1#2#3{%
  \pgfpointdiff{\pgfpointanchor{#2}{center}}{\pgfpointanchor{#3}{center}}%
  \pgfmathsetmacro{#1}{atan2(\pgf@x,\pgf@y)}%
}%
\newcommand{\resetpgfornamentstyle}{\tikzset{pgfornamentstyle/.style={}}}%
%---------%---------%---------%---------%---------%---------%---------%---------
%    \pgfornamentline[options]{A}{B}{n}{ornament}
%---------%---------%---------%---------%---------%---------%---------%---------
\pgfkeys{/ornamentline/.cd,
         color/.store in = \ornamentcolor,
         color           = black,
         /ornamentline/.search also = {/tikz}}%
\def\pgfornamentline{\pgfutil@ifnextchar[{\pgf@ornamentline}{\pgf@ornamentline[]}}%
\def\pgf@ornamentline[#1]#2#3#4#5{%
  \begingroup
  \pgfqkeys{/ornamentline}{color=black,#1}%  v1.4 : color reset at each call
  \pgfmathtruncatemacro\pgfornament@nb{#4}%  v1.4 : integer
  \pgfmathtruncatemacro\pgfornament@nbm{\pgfornament@nb-1}%
  \path (#2) -- (#3) foreach \i in {0,...,\pgfornament@nb}
       {coordinate[pos=\i/\pgfornament@nb] (p\i)}
       [color=\ornamentcolor] foreach \i [count=\j] in {0,...,\pgfornament@nbm}
       {(p\i) to [ornament=#5] (p\j)};%
  \endgroup
}%
\endinput
