summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/familytree/ft-marriage.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/familytree/ft-marriage.dtx')
-rw-r--r--macros/latex/contrib/familytree/ft-marriage.dtx374
1 files changed, 374 insertions, 0 deletions
diff --git a/macros/latex/contrib/familytree/ft-marriage.dtx b/macros/latex/contrib/familytree/ft-marriage.dtx
new file mode 100644
index 0000000000..138f8f06f9
--- /dev/null
+++ b/macros/latex/contrib/familytree/ft-marriage.dtx
@@ -0,0 +1,374 @@
+% \iffalse
+% Copyright 2022 Jiro Senju
+%
+% This package is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% any later version.
+%
+% This package is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this package. If not, see <http://www.gnu.org/licenses/>.
+% \fi
+%
+% \section{Marriage Box (\texttt{ft-marriage.dtx})}
+%
+% \DescribeMacro{\mrrgdef}
+% \cmd{\mrrgdef
+% \marg{new box name}
+% \marg{spouse list A}
+% \marg{oneself}
+% \marg{spouse list B}
+% \oarg{childline xlength}
+% }
+% \medskip
+%
+% Defines a marriage box with a specified name \meta{new box name}.
+% To support remarrying and the concubines, the spouses are specified by
+% a list. The element of the list is a box name defined by |\indvdldef|.
+% \meta{spouse list A} is placed upper side of \meta{oneself}, and
+% \meta{spouse list B} is lower side.
+% All box names are NOT \CS{} (no backslash).
+% \smallskip
+%
+% Aligns them in the same column, and connects them by a double line if the
+% marriage is official. If the marriage is not official (|\private|
+% attribute), uses a dashed double line.
+% Those double line is placed at the center of the length of the name of
+% \meta{oneself}.
+% \smallskip
+%
+% If a spouse has a child (|\haschild| attribute),
+% then the line to their child is drawn from the center of the
+% double line.
+% \smallskip
+%
+% Like |\sblngdef|, the interval box can be inserted if you want more
+% spaces.
+% \bigskip
+%
+% Like |\indvdldef|, some connection points are defined. Their origin
+% is left-bottom of the box and the unit is |pt|.
+%
+% \begin{itemize}
+% \item \meta{box name}|nameCY|
+%
+% the center of the height of the name of \meta{oneself}
+%
+% \item \meta{box name}\meta{individual box name}|nameCY|
+%
+% the center of the height of the name of who has any child-mark
+%
+% \item \meta{box name}\meta{individual box name}|mrrgCY|
+%
+% the center of the double line when any spouse has |\haschild| attribute
+% \end{itemize}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Customization}
+%
+% \DescribeMacro{\mrrgboxcfg}
+% \cmd{\mrrgboxcfg
+% \marg{space between two lines}
+% \marg{space between name and the line}
+% \marg{line length}
+% }
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \clearpage
+% \subsection{Example}
+%
+% \begin{enumerate}
+% \item
+% \srcfig{fig4Robert}
+%
+% \clearpage
+% \item
+% \srcfig{fig4HenryVIII}
+% \end{enumerate}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Layout and connecting in a same generation}
+%
+% It is not a good idea to put everything in a single family tree.
+%
+% For example, see King Henry VIII and his wives. Catherine of Aragon,
+% his first wife was actually a wife of Henry's brother, Arthur. If we
+% put King's siblings to this tree, how would it be looked? It's just
+% ugly and hard to understand in a glance. Let's think more using an
+% example from \refnm{sec:Lily1} again.
+%
+% How can we represent the Petunia -- Lily sisters tree including their husbands.
+% As a first step, define two marriage boxes, and then define the
+% sibling box.
+% \medskip
+%
+% \srcfig{fig4Lily1}
+% \medskip
+%
+% Why is this tree so ugly? There are three points to consider.
+% \begin{enumerate}
+% \item The position of two double lines differ from each other.
+% \item The length of a line to their child differs too. If we connected
+% the child, the ugliness would be improved.
+% \item James interrupts into between Petunia and Lily. It makes the
+% understandability worse.
+% \end{enumerate}
+%
+% On fixing the first point, the position of the double line, the second
+% point will be fixed automatically.
+% The solution is the one already suggested in \refnm{sec:Lily1}, set
+% the width of Lily box to Petunia's.
+% For the third point, the position of James, how about expanding the
+% space as a first step?
+% \medskip
+%
+% \srcfig{fig4Lily2}
+% \medskip
+%
+% Even spreading the space wider, James is still interrupting those two
+% sisters. Does it look better?
+% If we want more, the last way is to switch the position of James and Lily.
+% \medskip
+%
+% \srcfig{fig4Lily3}
+% \medskip
+%
+% Moreover spreading the blank is a good option.
+% \medskip
+%
+% \srcfig{fig4Lily4}
+% \medskip
+%
+% Is this best looking?
+% The easiness of looking is subject to one's opinion or taste.
+% Personally I feel resistance in the order of husband and wife. But also I
+% admit that as long as the main purpose of this tree is to represent those
+% sisters, this position of James is not bad.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsectImpl
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% \parag{Customization}
+%
+% \DescribeMacro{\ftmrrgboxcfg}
+% \DescribeMacro{\mrrgboxcfg}
+%
+% \begin{macrocode}
+\newlength{\ft@mrrgline@sep}
+\setlength{\ft@mrrgline@sep}{4pt}
+\newlength{\ft@mrrgline@sp}
+\setlength{\ft@mrrgline@sp}{.5\ft@unit}
+\newlength{\ft@mrrgline@length}
+\setlength{\ft@mrrgline@length}{1.5\ft@unit}
+\newcommand{\ftmrrgboxcfg}[3]{% sep space length
+ \ifx#1\empty\else%
+ \setlength{\ft@mrrgline@sep}{#1}%
+ \fi%
+ \ifx#2\empty\else%
+ \setlength{\ft@mrrgline@sp}{#2}%
+ \fi%
+ \ifx#3\empty\else%
+ \setlength{\ft@mrrgline@length}{#3}%
+ \fi%
+}
+\ft@alias{mrrgboxcfg}
+% \end{macrocode}
+%
+% \parag{Parsing}
+%
+% \begin{macrocode}
+\newcommand{\ft@mrrg@parse}[1]{% spouse-list
+ \global\ft@height=0pt%
+ \global\ft@width=0pt%
+ \global\ft@box@has@malelinefalse%
+ \@for\@temptokena:=#1\do{%
+ \ifx\@temptokena\empty\else%
+ \xdef\ft@spouse{\@temptokena}%
+ \@ifundefined{\@temptokena ival}{%
+ \@ifundefined{\ft@spouse haschild}{}{%
+ \global\ft@box@has@malelinetrue%
+ }%
+ \setlength{\ft@len}{\wd\@nameuse{\ft@spouse}}%
+ \ifdim\ft@width<\ft@len%
+ \global\ft@width=\ft@len%
+ \fi%
+ \ft@dbgmsg{\ft@spouse, W \the\wd\@nameuse{\ft@spouse},%
+ H \the\ht\@nameuse{\ft@spouse},%
+ D \the\dp\@nameuse{\ft@spouse}}%
+ \global\advance\ft@height \dimexpr\ft@mrrgline@length%
+ + 2\ft@mrrgline@sp\relax%
+ \ft@dbgmsg{\ft@spouse, H \the\ft@height}%
+ }{}%
+ \global\advance\ft@height \dimexpr\ht\@nameuse{\ft@spouse}%
+ + \dp\@nameuse{\ft@spouse}\relax%
+ \ft@dbgmsg{\ft@spouse, h H \the\ft@height}%
+ \fi%
+ }%
+ %
+ \ifft@box@has@maleline%
+ \global\advance\ft@width \ft@namebox@maleline@length%
+ \fi%
+ %
+ \global\ft@depth=\dp\@nameuse{\ft@spouse}%
+ \global\advance\ft@height \dimexpr -2\ft@mrrgline@sp%
+ - \ft@mrrgline@length - \ft@depth\relax%
+ \ft@dbgmsg{final H \the\ft@height, D \the\ft@depth}%
+}
+% \end{macrocode}
+%
+% \parag{The double line}
+%
+% \DescribeMacro{\ft@mrrg@line}
+%
+% \begin{macrocode}
+\newlength{\ft@mrrg@chlen}
+\newcommand{\ft@mrrg@line}[5]{% box-name spouse cx sp length
+ \ft@x=#3%
+ \global\advance\ft@height -#4%
+ \@tempskipb=\dimexpr\ft@mrrgline@sep/2\relax%
+ \edef\@y{\strip@pt\ft@height}%
+ \@ifundefined{#2private}{%
+ \ft@len=#5\relax%
+ \edef\@l{\strip@pt\ft@len}%
+ \put(\strip@pt\dimexpr\ft@x - \@tempskipb, \@y){\line(0,-1){\@l}}%
+ \put(\strip@pt\dimexpr\ft@x + \@tempskipb, \@y){\line(0,-1){\@l}}%
+ }{%
+ % this divisor should match the delta_y for multiput
+ \ft@len=#5\relax%
+ \ft@len=\dimexpr\ft@len/2 + .5pt\relax%
+ \@tempcnta=\dimexpr\ft@len/65536\relax%
+ \multiput(\strip@pt\dimexpr\ft@x - \@tempskipb, \@y)%
+ (0,-2){\@tempcnta}{\line(0,-1){.5}}%
+ \multiput(\strip@pt\dimexpr\ft@x + \@tempskipb, \@y)%
+ (0,-2){\@tempcnta}{\line(0,-1){.5}}%
+ }%
+ \@ifundefined{#2haschild}{}{%
+ \ft@len=#5\relax%
+ \ft@y=\dimexpr\ft@height - \ft@len/2\relax%
+ \put(\strip@pt\dimexpr\ft@x + \@tempskipb,\strip@pt\ft@y)%
+ {\line(1,0){\strip@pt\ft@mrrg@chlen}}%
+ \ft@dbgplot{\strip@pt\ft@x,\strip@pt\ft@y}%
+ \ft@namexdefstrip{#1#2mrrgCY}{\ft@y}%
+ }%
+ \ft@len=#5\relax%
+ \@tempskipa=#4\relax%
+ \global\advance\ft@height \dimexpr -\ft@len - \@tempskipa\relax%
+ \ft@dbgmsg{line #2 H \the\ft@height}%
+}
+% \end{macrocode}
+%
+% \parag{Layout the names}
+%
+% \DescribeMacro{\ft@mrrg@name}
+%
+% \begin{macrocode}
+\newcommand{\ft@mrrg@name}[2]{% box-name individual-name
+ \global\advance\ft@height -\ht\@nameuse{#2}%
+ \put(0,\strip@pt\ft@height){\usebox{\@nameuse{#2}}}%
+ \ft@dbgframe[0,\strip@pt\ft@height]%
+ {\strip@pt\wd\@nameuse{#2},\strip@pt\ht\@nameuse{#2}}%
+ %
+ \@ifundefined{#2hasmaleline}{}{%
+ \ft@x=\@nameuse{#2nameX}pt%
+ \ft@y=\dimexpr\ft@height + \@nameuse{#2nameCY}pt\relax%
+ \ft@len=\dimexpr\ft@width - \@nameuse{#2nameX}pt%
+ %- \ft@namebox@maleline@sp%
+ \relax%
+ \put(\strip@pt\ft@x,\strip@pt\ft@y){\line(1,0){\strip@pt\ft@len}}%
+ \ft@namexdefstrip{#1#2nameCY}{\ft@y}%
+ }%
+ %
+ \@ifundefined{#2hascmark}{}{%
+ \ft@len=\dimexpr\ft@height + \@nameuse{#2nameCY}pt\relax%
+ \ft@namexdefstrip{#1#2nameCY}{\ft@len}%
+ \ft@dbgplot{0,\strip@pt\ft@len}%
+ }%
+ \global\advance\ft@height -\dp\@nameuse{#2}%
+ \ft@dbgmsg{name #2 H \the\ft@height}%
+}
+% \end{macrocode}
+%
+% \subsubsection{Layout and connect the individuals --- core}
+%
+% \DescribeMacro{\ft@mrrg@spouse}
+%
+% \begin{macrocode}
+\newlength{\ft@mrrg@ival}
+\newcommand{\ft@mrrg@spouse}[2]{% box-name list
+ \global\ft@mrrg@ival=0pt%
+ \@for\@temptokena:=#2\do{%
+ \@ifundefined{\@temptokena ival}{%
+ \@tempskipa=\dimexpr\ft@mrrgline@length + \ft@mrrg@ival\relax%
+ \if@tempswa%
+ \ft@mrrg@name{#1}{\@temptokena}%
+ \ft@mrrg@line{#1}{\@temptokena}{\ft@xx}{\ft@mrrgline@sp}%
+ {\@tempskipa}%
+ \else%
+ \ft@mrrg@line{#1}{\@temptokena}{\ft@xx}{\ft@mrrgline@sp}%
+ {\@tempskipa}%
+ \ft@mrrg@name{#1}{\@temptokena}%
+ \fi%
+ \global\ft@mrrg@ival=0pt%
+ }{%
+ \global\advance\ft@mrrg@ival%
+ \dimexpr\ht\@nameuse{\@temptokena}%
+ + \dp\@nameuse{\@temptokena}\relax%
+ }%
+ }%
+}
+% \end{macrocode}
+%
+% \subsubsection{Marriage box --- interface}
+%
+% \DescribeMacro{\ftmrrgdef}
+% \DescribeMacro{\mrrgdef}
+%
+% \begin{macrocode}
+\NewDocumentCommand{\ftmrrgdef}{mmmmO{0pt}}{%
+ % box-name spouse-listA oneself spouse-listB [xline]
+ \ft@xx=\@nameuse{#3nameCX}pt\relax%
+ \ft@mrrg@parse{#2,#3,#4}%
+ %
+ \advance\ft@width #5%
+ \global\ft@mrrg@chlen=\dimexpr\ft@width - \ft@xx%
+ - \ft@mrrgline@sep/2\relax%
+ %
+ \ft@theight=\ft@height%
+ \ft@newnamebox{#1}{%
+ \edef\@w{\strip@pt\ft@width}%
+ \edef\@h{\strip@pt\ft@height}%
+ \begin{picture}(\@w,\@h)%
+ \ft@dbgframe{\@w,\@h}%
+ %
+ \ifx#2\@nil\else%
+ \@tempswatrue%
+ \ft@mrrg@spouse{#1}{#2}%
+ \fi%
+ %
+ \ft@mrrg@name{#1}{#3}%
+ \@ifundefined{#1#3nameCY}{}{%
+ \ft@len=\@nameuse{#1#3nameCY}pt\relax%
+ \ft@dbgplot{1,\strip@pt\ft@len}%
+ \ft@namexdefstrip{#1nameCY}{\ft@len}%
+ }%
+ \@ifundefined{#3hascmark}{}{%
+ \ft@namexdef{#1hascmark}{\@nameuse{#3hascmark}}%
+ }%
+ %
+ \ifx#4\empty\else%
+ \@tempswafalse%
+ \ft@mrrg@spouse{#1}{#4}%
+ \fi%
+ \end{picture}%
+ }%
+ \ft@nameboxsz{#1}{\ft@theight}{\ft@depth}%
+}
+\ft@alias{mrrgdef}
+% \end{macrocode}