%% folarrow.sty
%% 軸に3本の斜線が入った矢印（葉層束の射影を表す）
%% amscd，xy-pic，tikz-cdの図式と本文の数式で使う．
%%
%% Author: Yuwsuke Kieda
%% Copyright (c) 2026 Yuwsuke Kieda
%% This file is part of the folarrow package, released under the MIT License
%% (see the file LICENSE). The arrow fonts of the package keep the licenses of
%% their original fonts (see licenses/FONTS.md).
%%
\NeedsTeXFormat{LaTeX2e}[2022-06-01]
\ProvidesPackage{folarrow}[2026/10/10 v20261010.0 foliated arrows for amscd, xy-pic and tikz-cd]
\RequirePackage{pict2e}
\RequirePackage{graphics}

%% ---------------------------------------------------------------
%% パラメータ
%%   span：斜線の長さ（矢頭の幅に対する比）
%%   lean：斜線の傾き（長さに対する，矢印方向へのずれの比）
%%   gap：斜線の間隔（矢頭の幅に対する比）
%%   shift：矢印の中央から根元側へずらす量（矢頭の幅に対する比）
%%   thickness：斜線の太さ（空なら矢印の軸の太さ．下の「矢頭の幅と線の太さ」を参照）
%%   glyphs：本文用の矢印（\folrightarrowなど）に，用意したフォントの字形を使うか
%%     （true／false．下の「本文用の矢印のフォント」を参照）
%%   lite：簡易版（パッケージの読み込み時だけ指定できる）．ほかのファイル（folarrow.lua，
%%     folarrow-fonts.def，folarrow-glyphs.def，folarrow-otf.def，矢印のフォントとマップファイル）
%%     を一切使わず，すべての矢印を描いて組む．
%%     矢頭の幅と線の太さは，XeTeX＋OpenTypeの数式フォントなら\XeTeXglyphboundsで読み，
%%     それ以外はフォントの寸法から推定する．3本線は矢印の箱の中央に置く（字面の中心との
%%     ずれは補正しない）．
%% ---------------------------------------------------------------
\def\fol@span{1.0}
\def\fol@lean{0.25}
\def\fol@gap{0.35}
\def\fol@shift{0}
\def\fol@thickness{}
\newif\iffol@glyphs \fol@glyphstrue
\newif\iffol@lite
% 形のキーがすべて既定値か（本文用の矢印にフォントの字形を使えるか）．キーを設定するたびに判定する
\newif\iffol@defaultshape \fol@defaultshapetrue
% キーの値は設定のときに確かめる．数でないもの，範囲の外の値はエラーにして，前の値のままにする．
%   \fol@setnum{キー}{マクロ}{値}{範囲の条件（fpの式．##1が値）}{範囲の説明}
\ExplSyntaxOn
\cs_new_protected:Npn \fol@setnum #1#2#3#4#5
  {
    \regex_match:nnTF { \A\s*[+\-]?(\d+\.?\d*|\.\d+)([eE][+\-]?\d+)?\s*\Z } {#3}
      {
        \fp_compare:nTF {#4}
          { \tl_set:Nx #2 { \fp_eval:n {#3} } }
          { \msg_error:nnnnn { folarrow } { range } {#1} {#3} {#5} }
      }
      { \msg_error:nnnnn { folarrow } { number } {#1} {#3} {#5} }
    \fol@checkdefault
  }
\cs_new_protected:Npn \fol@setthickness #1
  {
    \tl_if_blank:nTF {#1}
      { \tl_clear:N \fol@thickness }
      {
        \regex_match:nnTF
          { \A\s*(([+\-]?(\d+\.?\d*|\.\d+)\s*(pt|bp|mm|cm|in|pc|dd|cc|sp|em|ex|px|nd|nc))|\\[A-Za-z@]+)\s*\Z } {#1}
          {
            \dim_compare:nNnTF {#1} < { 0pt }
              { \msg_error:nnnnn { folarrow } { range } { thickness } {#1} { a~non-negative~length } }
              { \tl_set:Nn \fol@thickness {#1} }
          }
          { \msg_error:nnnnn { folarrow } { number } { thickness } {#1} { a~length~such~as~0.4pt } }
      }
    \fol@checkdefault
  }
\cs_new_protected:Npn \fol@checkdefault
  {
    \bool_lazy_and:nnTF
      { \tl_if_empty_p:N \fol@thickness }
      { \fp_compare_p:n { abs(\fol@span-1) + abs(\fol@lean-0.25) + abs(\fol@gap-0.35) + abs(\fol@shift) < 0.0001 } }
      { \fol@defaultshapetrue } { \fol@defaultshapefalse }
  }
\msg_new:nnnn { folarrow } { number }
  { Invalid~value~'#2'~for~the~key~'#1'. }
  { The~value~must~be~#3.~The~previous~value~is~kept. }
\msg_new:nnnn { folarrow } { range }
  { The~value~'#2'~for~the~key~'#1'~is~out~of~range. }
  { The~value~must~be~#3.~The~previous~value~is~kept. }
\ExplSyntaxOff
\DeclareKeys[folarrow]{
  span.code       = \fol@setnum{span}\fol@span{#1}{#1>0 && #1<=10}{a number greater than 0 and at most 10},
  lean.code       = \fol@setnum{lean}\fol@lean{#1}{abs(#1)<=5}{a number between -5 and 5},
  gap.code        = \fol@setnum{gap}\fol@gap{#1}{#1>=0 && #1<=10}{a number between 0 and 10},
  shift.code      = \fol@setnum{shift}\fol@shift{#1}{abs(#1)<=10}{a number between -10 and 10},
  thickness.code  = \fol@setthickness{#1},
  glyphs.if       = fol@glyphs,
  lite.if         = fol@lite,
  lite.usage      = load,
}
\ProcessKeyOptions[folarrow]
% 簡易版では，ほかのファイルを使わない（フォントの字形も使わない）
\iffol@lite \fol@glyphsfalse \fi
% LuaTeXのグリフ情報（folarrow.lua）を使うか
\ifdefined\directlua \iffol@lite\else \def\fol@uselua{}\fi \fi
\NewDocumentCommand\folarrowsetup{m}{\SetKeys[folarrow]{#1}}

%% ---------------------------------------------------------------
%% 描画の核
%%   \fol@strokes{cx}{cy}{ux}{uy}{b}{t}
%%   (cx,cy)：3本の中心（pt単位の数），(ux,uy)：矢印の向きの単位ベクトル，
%%   b：矢頭の幅（pt），t：線の太さ（pt）．
%%   斜線の向きは ±lean×u＋n（nはuを左に90°回した法線）で，右上がりに
%%   なるほうの符号を選ぶ．横向きなら「///」，縦向きなら右上がりの
%%   ほぼ水平な3本になる．
%%   現在位置を原点とする幅0の箱に描く．
%%   線の端は\fol@capに従う：r（丸）なら丸い端，b（切りっぱなし）なら切りっぱなし．
%%   矢印の尻（軸の端）の形に合わせる．丸い端は線の太さの半分だけ外にはみ出すので，
%%   見た目の長さがそろうよう，そのぶん短く引く．
%% ---------------------------------------------------------------
\def\fol@cap{b}
\def\fol@cap@r{r}
\def\fol@off{0}
\def\fol@acr{0}
\def\fol@strokes#1#2#3#4#5#6{%
  \begingroup
  \edef\fol@s{\fpeval{\fol@span*(#5)}}%
  \ifx\fol@cap\fol@cap@r
    \edef\fol@k{\fpeval{max(0,\fol@s-(#6))/\fol@s}}%
  \else
    \def\fol@k{1}%
  \fi
  \edef\fol@sg{\fpeval{
      ((\fol@lean*(#3)-(#4))*(\fol@lean*(#4)+(#3)) >= 0) ? 1 : -1}}%
  % 斜線の半分のベクトル
  \edef\fol@vx{\fpeval{0.5*\fol@k*\fol@s*(\fol@sg*\fol@lean*(#3)-(#4))}}%
  \edef\fol@vy{\fpeval{0.5*\fol@k*\fol@s*(\fol@sg*\fol@lean*(#4)+(#3))}}%
  % 斜線どうしの間隔のベクトル
  \edef\fol@dx{\fpeval{\fol@gap*(#5)*(#3)}}%
  \edef\fol@dy{\fpeval{\fol@gap*(#5)*(#4)}}%
  \unitlength=1pt
  % タグ付けしたPDF（\DocumentMetadata{tagging=on}など）では，3本線は図ではなく飾り（artifact）にする
  \expandafter\ifx\csname l_tag_graphic_mode_tl\endcsname\relax\else
    \@namedef{l_tag_graphic_mode_tl}{artifact}%
  \fi
  \hbox to\z@{%
    \fol@tatebegin
    \begin{picture}(0,0)%
      \linethickness{#6pt}%
      \ifx\fol@cap\fol@cap@r\roundcap\else\buttcap\fi
      \fol@oneline{#1}{#2}{-1}%
      \fol@oneline{#1}{#2}{0}%
      \fol@oneline{#1}{#2}{1}%
    \end{picture}\fol@tateend\hss}%
  \endgroup}
% pTeX／upTeXの縦組み（dvipdfmx）では，pict2eのPDFの描画命令が縦組みに合わせて回らないので，
% -90°回して描く．\iftdirはpTeX系にしかないので，\csnameで呼ぶ（ほかのエンジンで\ifと\fiの
% 対応が崩れないように）．LuaTeX-jaの縦組みでは回さなくても正しい．
% （定義の本体に\fiを含むので，条件分岐の中には書かず，\@gobbleか\@firstofoneで選ぶ）
\let\fol@tatebegin\relax \let\fol@tateend\relax
\ifdefined\directlua\expandafter\@gobble\else\expandafter\@firstofone\fi
  {\@ifundefined{iftdir}{}{%
    \def\fol@tatebegin{\csname iftdir\endcsname\special{pdf:btrans rotate -90}\fi}%
    \def\fol@tateend{\csname iftdir\endcsname\special{pdf:etrans}\fi}}}
\def\fol@oneline#1#2#3{%
  \Line(\fpeval{(#1)+(#3)*\fol@dx-\fol@vx},\fpeval{(#2)+(#3)*\fol@dy-\fol@vy})%
       (\fpeval{(#1)+(#3)*\fol@dx+\fol@vx},\fpeval{(#2)+(#3)*\fol@dy+\fol@vy})}

%% ---------------------------------------------------------------
%% 矢頭の幅と線の太さ：\fol@b（矢頭の幅）と\fol@t（線の太さ）をpt単位の数で決める
%%   \fol@hmetrics{style}：横向きの矢印（\rightarrow系の文字）
%%   \fol@vmetrics{style}{box}{kind}：縦向きの矢印の箱．kindはbig（\Big\downarrowなど）
%%                                  またはinl（\foldownarrowの土台）
%% 次の順に試す．
%%   1. LuaTeXでOpenTypeの数式フォントなら，グリフの外接矩形から直接求める（folarrow.lua）．
%%   2. 矢印の文字を持つフォントの名前が実測データ（folarrow-fonts.def）にあれば，
%%      そのquadに実測の比を掛ける．\rightarrowは数式文字コードから，縦向きの矢印は
%%      \downarrowの区切り記号コードから，実際に使われるフォントを求める．
%%   3. どちらもなければ，箱の寸法とフォントのパラメーターから推定する．
%% thicknessキーが空でなければ，線の太さはその値にする．
%% ---------------------------------------------------------------
\def\fol@setff#1{% #1が\displaystyleなどのとき，\fol@ffを\textfontなどにする
  \ifx#1\scriptscriptstyle\let\fol@ff\scriptscriptfont
  \else\ifx#1\scriptstyle\let\fol@ff\scriptfont
  \else\let\fol@ff\textfont\fi\fi}
\newbox\fol@refbox

% 1. LuaTeX：グリフの外接矩形から（簡易版では使わない）
\ifdefined\fol@uselua
  \directlua{require('folarrow')}
  \def\fol@luaextent#1#2{% #1：箱の番号，#2：true（縦向き）かfalse
    \edef\fol@lua{\directlua{folarrow.extent(\number#1, #2)}}}
\else
  \def\fol@luaextent#1#2{\let\fol@lua\@empty}
\fi
\def\fol@splitlua#1 #2 #3 #4\@nil{\def\fol@b{#1}\def\fol@t{#2}\def\fol@otfkey{#3}\def\fol@glyphmid{#4}}
% 矢頭の上下の中心（ベースラインからの高さ，pt）．グリフから読めたときだけ設定する
\let\fol@glyphmid\@empty

% 1'. XeTeX：OpenTypeの数式フォントなら\XeTeXglyphboundsでグリフの外接矩形を読む
% \fol@xeextent{家族番号}{文字コード}{hかv}（フォントは\fol@ffで選んだスタイルのもの）：矢頭の幅（横向きは→の高さ＋深さ，縦向きは↓の
% 字面の幅）と，マイナス記号の高さ＋深さ（線の太さ）を\fol@luaに「幅 太さ」で入れる．
% 添字用の字形（ssty）や\Bigの大きい字形は読めないので，元の字形の値になる．
\ifdefined\XeTeXglyphbounds
  \def\fol@xeextent#1#2#3{%
    \ifnum\XeTeXfonttype\fol@ff#1 =\tw@
      \setbox\@tempboxa\hbox{\the\fol@ff#1\relax
        \count@=\XeTeXcharglyph#2\relax
        \if#3v%
          \setbox\@tempboxa\hbox{\XeTeXglyph\count@}%
          \@tempdima=\wd\@tempboxa
          \advance\@tempdima-\XeTeXglyphbounds1 \count@
          \advance\@tempdima-\XeTeXglyphbounds3 \count@
          \@tempdimc=\z@
        \else
          \@tempdima=\XeTeXglyphbounds2 \count@
          \advance\@tempdima\XeTeXglyphbounds4 \count@
          % 矢頭の上下の中心：（上端の高さ－下端の深さ）／2
          \@tempdimc=\XeTeXglyphbounds2 \count@
          \advance\@tempdimc-\XeTeXglyphbounds4 \count@
          \divide\@tempdimc\tw@
        \fi
        \count@=\XeTeXcharglyph"2212\relax
        \@tempdimb=\XeTeXglyphbounds2 \count@
        \advance\@tempdimb\XeTeXglyphbounds4 \count@
        \xdef\fol@xe@tmp{\strip@pt\@tempdima\space\strip@pt\@tempdimb}%
        \xdef\fol@xe@mid{\strip@pt\@tempdimc}}%
      \ifx\fol@xe@tmp\fol@xe@zero\else
        \fol@xecorrect{\fol@ff#1}{#3}%
        \let\fol@lua\fol@xe@tmp
      \fi
    \fi}
  \def\fol@xe@zero{0.0 0.0}
  % フォントごとの補正（folarrow.luaの表と同じ実測値．XeTeXでは\Bigの大きい字形を
  % 読めないので，KpMathは\Bigの矢頭の幅も補正する）
  \ExplSyntaxOn
  \cs_new_protected:Npn \fol@xecorrect #1#2
    {
      \str_set:Nx \l__fol_str { \str_lowercase:f { \fontname #1 } }
      \regex_replace_all:nnN { [^a-z0-9] } { } \l__fol_str
      \tl_set:Nn \l_tmpa_tl { 1 } % 太さ
      \tl_set:Nn \l_tmpb_tl { 1 } % 幅
      \str_if_in:NnT \l__fol_str { asanamath } { \tl_set:Nn \l_tmpa_tl { 1.058 } }
      \str_if_in:NnT \l__fol_str { gfsneohellenicmath } { \tl_set:Nn \l_tmpa_tl { 0.815 } }
      \str_if_eq:nnT {#2} { v }
        {
          \str_if_in:NnT \l__fol_str { minionmath } { \tl_set:Nn \l_tmpa_tl { 1.16 } }
          \str_if_in:NnT \l__fol_str { gfsneohellenicmath } { \tl_set:Nn \l_tmpa_tl { 0.79 } }
          \str_if_in:NnT \l__fol_str { kpmath }
            { \tl_set:Nn \l_tmpa_tl { 1.087 } \tl_set:Nn \l_tmpb_tl { 0.917 } }
        }
      \exp_after:wN \__fol_xe_apply:w \fol@xe@tmp \q_stop
    }
  \cs_new_protected:Npn \__fol_xe_apply:w #1~#2 \q_stop
    {
      \tl_gset:Nx \fol@xe@tmp
        { \fp_eval:n { #1 * \l_tmpb_tl } ~ \fp_eval:n { #2 * \l_tmpa_tl } ~ \l__fol_str \c_space_tl \fol@xe@mid }
    }
  \ExplSyntaxOff
\else
  \def\fol@xeextent#1#2#3{}
\fi

% 2. 実測データ
% \fol@hdata{フォント名}{矢頭の幅/quad}{軸の太さ/quad}{\longrightarrowの尻}{伸びる矢印の尻}
%           {中心のずれ：\longrightarrow,伸びる矢印,（直交方向）\longrightarrow,伸びる矢印,
%           （左向き）\longleftarrow,伸びる矢印,（左向きの直交方向）\longleftarrow,伸びる矢印}
% \fol@vdata{フォント名}{\Bigの矢頭の幅/quad}{\Bigの軸の太さ/quad}{土台の矢頭の幅/quad}{土台の軸の太さ/quad}
%           {\Bigの尻}{土台の尻}{中心のずれ：\Bigの下向き,\Bigの上向き,土台の下向き,土台の上向き,
%           （直交方向）同じ4つ}
% \fol@otfcap{鍵}{\longrightarrowの尻}{伸びる矢印の尻}{\Bigの尻}{土台の尻}
%           {中心のずれ：\longrightarrow,伸びる矢印,\Bigの下向き,\Bigの上向き,土台の下向き,土台の上向き,
%           （直交方向）同じ6つ,（左向き）\longleftarrow,伸びる矢印,（左向きの直交方向）同じ2つ}
%           ：OpenTypeのフォント
% 尻の形はr（丸）かb（切りっぱなし）．3本線の端をこれに合わせる．
% 中心のずれは，箱の中心に置いた3本線の中心が矢印の字面の中心から矢頭の側へずれる量と，
% 軸に直交する方向（横向きは下，縦向きは右が正）にずれる量（quadに対する比）．
% 3本線をこの量だけ戻して，字面の中心（軸の上）に置く．
\def\fol@hdata#1#2#3#4#5#6{\@namedef{fol@H@#1}{{#2}{#3}{#4}{#5}{#6}}}
\def\fol@vdata#1#2#3#4#5#6#7#8{\@namedef{fol@V@#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}}}
\def\fol@otfcaps{}
\def\fol@otfcap#1#2#3#4#5#6{\g@addto@macro\fol@otfcaps{\fol@oc{#1}{#2}{#3}{#4}{#5}{#6}}}
% \fol@otfcapxe：XeTeXで測った値（形式は\fol@otfcapと同じ）．XeTeXでは\Bigなどに選ばれる
% 字形がLuaTeXと違うことがあるので，XeTeXのときだけ使う（あとから足すので優先される）．
\ifdefined\XeTeXrevision
  \let\fol@otfcapxe\fol@otfcap
\else
  \def\fol@otfcapxe#1#2#3#4#5#6{}
\fi
\iffol@lite\else \InputIfFileExists{folarrow-fonts.def}{}{}\fi

\ExplSyntaxOn
\str_new:N \l__fol_str
\seq_new:N \l__fol_seq
% \fol@hfamily〈マクロ〉：\rightarrowの数式文字コード（\mathchar"…）から家族番号を取り出す．
% \fol@vfamily〈マクロ〉：\downarrowの区切り記号コード（\delimiter"…）から，大きい字形の
% 家族番号を取り出す．取り出せなければ既定値（2または3）にする．
\regex_const:Nn \c__fol_mathchar_regex { \\mathchar\s*\"([0-9A-Fa-f]+) }
\regex_const:Nn \c__fol_delimiter_regex { \\delimiter\s*\"([0-9A-Fa-f]+) }
% unicode-math（LuaTeX，XeTeX）：\Umathchar"類"家族"文字，\Udelimiter"類"家族"文字
\regex_const:Nn \c__fol_umath_regex
  { \\U(?:mathchar|delimiter)\s*\"([0-9A-Fa-f]+)\"([0-9A-Fa-f]+)\" }
\cs_new_protected:Npn \__fol_family:NNnN #1#2#3#4
  {
    \cs_if_exist:cTF { fol@FAM@ \token_to_meaning:N #1 }
      { \tl_set_eq:Nc #4 { fol@FAM@ \token_to_meaning:N #1 } }
      {
        \__fol_family_compute:NNnN #1#2{#3}#4
        \tl_gset_eq:cN { fol@FAM@ \token_to_meaning:N #1 } #4
      }
  }
\cs_new_protected:Npn \__fol_family_compute:NNnN #1#2#3#4
  {
    \str_set:Nx \l__fol_str { \token_to_meaning:N #1 }
    \regex_extract_once:NVNTF \c__fol_umath_regex \l__fol_str \l__fol_seq
      { \tl_set:Nx #4 { \int_from_hex:e { \seq_item:Nn \l__fol_seq { 3 } } } }
      {
        \regex_extract_once:NVNTF #2 \l__fol_str \l__fol_seq
          {
            \tl_set:Nx #4
              { \int_eval:n { \int_mod:nn { \int_div_truncate:nn
                  { \int_from_hex:e { \seq_item:Nn \l__fol_seq { 2 } } } { 256 } } { 16 } } }
          }
          { \tl_set:Nn #4 {#3} }
      }
  }
\cs_generate_variant:Nn \regex_extract_once:NnNTF { NV }
\cs_generate_variant:Nn \int_from_hex:n { e }
\cs_new_protected:Npn \fol@hfamily #1
  { \__fol_family:NNnN \rightarrow \c__fol_mathchar_regex { 2 } #1 }
\cs_new_protected:Npn \fol@vfamily #1
  { \__fol_family:NNnN \downarrow \c__fol_delimiter_regex { 3 } #1 }
% フォント名の基本部分（「 at 10.95pt」を除く）と，末尾の数字を除いたもの
\cs_new_protected:Npn \fol@basename #1
  {
    \str_set:Nx \l__fol_str { \fontname #1 }
    \regex_replace_once:nnN { [\s\\].* } { } \l__fol_str
    \tl_set:Nx \fol@fname { \l__fol_str }
    \regex_replace_once:nnN { [0-9]+\Z } { } \l__fol_str
    \tl_set:Nx \fol@fnamestem { \l__fol_str }
  }
\ExplSyntaxOff
% データを引く．#1：HかV，#2：フォント．見つかれば\fol@dataに値を入れる．
\def\fol@lookup#1#2{%
  \fol@basename{#2}%
  \expandafter\let\expandafter\fol@data\csname fol@#1@\fol@fname\endcsname
  \ifx\fol@data\relax
    \expandafter\let\expandafter\fol@data\csname fol@#1@\fol@fnamestem\endcsname
  \fi}
% 表の値の取り出し：\fol@ra（幅），\fol@rb（太さ），\fol@rc（尻の形）
% \fol@rd：中心のずれ（quadに対する比）
% \fol@re：直交方向のずれ（quadに対する比）
\def\fol@hvals#1#2#3#4#5#6\@nil{\def\fol@ra{#1}\def\fol@rb{#2}%
  \ifnum\fol@hkindnum=\z@\def\fol@rc{#3}\else\def\fol@rc{#4}\fi
  \edef\fol@rd{\fol@clistitem{#5}{\ifnum\fol@hdir<\z@\ifnum\fol@hkindnum=\z@ 5\else 6\fi
    \else\ifnum\fol@hkindnum=\z@ 1\else 2\fi\fi}}%
  \edef\fol@re{\fol@clistitem{#5}{\ifnum\fol@hdir<\z@\ifnum\fol@hkindnum=\z@ 7\else 8\fi
    \else\ifnum\fol@hkindnum=\z@ 3\else 4\fi\fi}}}
% 横向きの矢印の向き（1で右向き，-1で左向き）
\def\fol@hdir{1}
\def\fol@bigvals#1#2#3#4#5#6#7\@nil{\def\fol@ra{#1}\def\fol@rb{#2}\def\fol@rc{#5}%
  \edef\fol@rd{\fol@clistitem{#7}{\ifnum\fol@vdir<\z@ 1\else 2\fi}}%
  \edef\fol@re{\fol@clistitem{#7}{\ifnum\fol@vdir<\z@ 5\else 6\fi}}}
\def\fol@inlvals#1#2#3#4#5#6#7\@nil{\def\fol@ra{#3}\def\fol@rb{#4}\def\fol@rc{#6}%
  \edef\fol@rd{\fol@clistitem{#7}{\ifnum\fol@vdir<\z@ 3\else 4\fi}}%
  \edef\fol@re{\fol@clistitem{#7}{\ifnum\fol@vdir<\z@ 7\else 8\fi}}}
% 縦向きの矢印の向き（-1で下向き，1で上向き）
\def\fol@vdir{-1}
% 横向きの矢印の組み方：0は\longrightarrow（本文の数式），1は伸びる矢印（amscd，\xfolrightarrow）
\chardef\fol@hkindnum=\z@
% OpenTypeのフォントの尻の形と中心のずれ：#1は小文字の英数字だけにしたフォント名，
% #2は尻の形の何番目（1～4），#3は中心のずれの何番目（1～6）か．
% 結果は\fol@cap（尻の形）と\fol@rd（中心のずれ，quadに対する比）．
\ExplSyntaxOn
% コンマ区切りの並びの#2番目．なければ0
\cs_new:Npn \fol@clistitem #1#2
  { \exp_args:Ne \tl_if_blank:nTF { \clist_item:nn {#1} {#2} } { 0 } { \clist_item:nn {#1} {#2} } }
\cs_new_protected:Npn \fol@otfcaplookup #1#2#3
  {
    \def\fol@cap{b}
    \def\fol@rd{0}
    \def\fol@re{0}
    \cs_set:Npn \fol@oc ##1##2##3##4##5##6
      {
        \str_if_in:nnT {#1} {##1}
          {
            \tl_set:Nx \fol@cap { \int_case:nn {#2} { {1}{##2} {2}{##3} {3}{##4} {4}{##5} } }
            \tl_set:Nx \fol@rd { \fol@clistitem {##6} {#3} }
            \tl_set:Nx \fol@re { \fol@clistitem {##6}
              { \int_eval:n { \int_compare:nNnTF {#3} > {12} { #3 + 2 } { #3 + 6 } } } }
          }
      }
    \fol@otfcaps
    \tl_if_blank:VT \fol@rd { \def\fol@rd{0} }
    \tl_if_blank:VT \fol@re { \def\fol@re{0} }
  }
\ExplSyntaxOff

% 3. 推定（データがないとき）
% 矢頭の幅：\rightarrowの箱の高さと数式の軸から2×（高さ－軸の高さ）．これが0.35 quad
% 未満なら，箱の高さが矢頭より低く設定されたフォントとみなして0.5 quadにする．
% 線の太さ：数式拡張フォントの罫線の太さ．Computer Modernでexscaleを使わない
% ときのように拡張フォントが拡大されていなければ，記号フォントの大きさに合わせる．
% いずれも極端な値にならないよう，quadに対する比を制限する．
\def\fol@guess#1{%
  \fol@setff#1%
  \setbox\@tempboxa\hbox{$\m@th#1\rightarrow$}%
  \@tempdima=\ht\@tempboxa \advance\@tempdima-\fontdimen22\fol@ff\tw@
  \multiply\@tempdima\tw@
  \@tempdimb=.35\fontdimen6\fol@ff\tw@
  \ifdim\@tempdima<\@tempdimb \@tempdima=.5\fontdimen6\fol@ff\tw@ \fi
  \@tempdimb=\fontdimen6\fol@ff\tw@
  \edef\fol@b{\fpeval{min(max(\the\@tempdima,0.25*\the\@tempdimb),0.8*\the\@tempdimb)}}%
  \@tempdima\fontdimen8\textfont3
  \@tempdimc\fontdimen6\textfont3
  \ifdim\@tempdimc=\z@ \@tempdimc=\fontdimen6\textfont\tw@ \fi
  \edef\fol@t{\fpeval{\the\@tempdima*\the\@tempdimb/\the\@tempdimc}}%
  \edef\fol@t{\fpeval{min(max(\fol@t,0.02*\the\@tempdimb),0.12*\the\@tempdimb)}}}

% 横向き
\def\fol@hmetrics@calc#1{%
  \let\fol@glyphmid\@empty
  \setbox\fol@refbox\hbox{$\m@th#1\rightarrow$}%
  \fol@luaextent\fol@refbox{false}%
  \fol@setff#1\fol@hfamily\fol@fam
  \ifx\fol@lua\@empty
    \fol@xeextent\fol@fam{"2192}h%
  \fi
  \ifx\fol@lua\@empty
    \fol@lookup H{\fol@ff\fol@fam\relax}%
    \ifx\fol@data\relax
      \fol@guess#1\def\fol@cap{b}\def\fol@off{0}\def\fol@acr{0}%
    \else
      \expandafter\fol@hvals\fol@data\@nil
      \@tempdimb=\fontdimen6\fol@ff\fol@fam\relax
      \edef\fol@b{\fpeval{\fol@ra*\the\@tempdimb}}%
      \edef\fol@t{\fpeval{\fol@rb*\the\@tempdimb}}%
      \edef\fol@off{\fpeval{\fol@rd*\the\@tempdimb}}%
      \edef\fol@acr{\fpeval{\fol@re*\the\@tempdimb}}%
      \let\fol@cap\fol@rc
    \fi
  \else
    \expandafter\fol@splitlua\fol@lua\@nil
    \expandafter\fol@otfcaplookup\expandafter{\fol@otfkey}%
      {\ifnum\fol@hkindnum=\z@ 1\else 2\fi}%
      {\ifnum\fol@hdir<\z@\ifnum\fol@hkindnum=\z@ 13\else 14\fi\else\ifnum\fol@hkindnum=\z@ 1\else 2\fi\fi}%
    \@tempdimb=\fontdimen6\fol@ff\fol@fam\relax
    \edef\fol@off{\fpeval{\fol@rd*\the\@tempdimb}}%
      \edef\fol@acr{\fpeval{\fol@re*\the\@tempdimb}}%
  \fi
  \fol@usethickness}
% 縦向き
\def\fol@vmetrics@calc#1#2#3{%
  \fol@luaextent#2{true}%
  \fol@setff#1\fol@vfamily\fol@fam
  \ifx\fol@lua\@empty
    \fol@xeextent\fol@fam{"2193}v%
  \fi
  \def\@tempa{#3}%
  \ifx\fol@lua\@empty
    \fol@lookup V{\fol@ff\fol@fam\relax}%
    \ifx\fol@data\relax
      % データがなければ横向きと同じ値を，拡張フォントの大きさに合わせて使う
      \fol@hmetrics#1\fol@getrthree
      \edef\fol@b{\fpeval{\fol@b*\fol@rthree}}%
      \edef\fol@t{\fpeval{\fol@t*\fol@rthree}}%
      \def\fol@cap{b}\def\fol@off{0}\def\fol@acr{0}%
    \else
      \ifx\@tempa\fol@kind@inl
        \expandafter\fol@inlvals\fol@data\@nil
      \else
        \expandafter\fol@bigvals\fol@data\@nil
      \fi
      \@tempdimb=\fontdimen6\fol@ff\fol@fam\relax
      \edef\fol@b{\fpeval{\fol@ra*\the\@tempdimb}}%
      \edef\fol@t{\fpeval{\fol@rb*\the\@tempdimb}}%
      \edef\fol@off{\fpeval{\fol@rd*\the\@tempdimb}}%
      \edef\fol@acr{\fpeval{\fol@re*\the\@tempdimb}}%
      \let\fol@cap\fol@rc
    \fi
  \else
    \expandafter\fol@splitlua\fol@lua\@nil
    \expandafter\fol@otfcaplookup\expandafter{\fol@otfkey}%
      {\ifx\@tempa\fol@kind@inl 4\else 3\fi}%
      {\ifx\@tempa\fol@kind@inl\ifnum\fol@vdir<\z@ 5\else 6\fi\else\ifnum\fol@vdir<\z@ 3\else 4\fi\fi}%
    \@tempdimb=\fontdimen6\fol@ff\fol@fam\relax
    \edef\fol@off{\fpeval{\fol@rd*\the\@tempdimb}}%
      \edef\fol@acr{\fpeval{\fol@re*\the\@tempdimb}}%
  \fi
  \fol@usethickness}
\def\fol@kind@inl{inl}
% 計算した寸法（\fol@b，\fol@t，\fol@cap，\fol@off，\fol@acr，\fol@glyphmid）は，フォント名，矢印の種類，
% 向き，thicknessの値ごとに覚えておき，2回目からは計算しない（描く矢印が多い文書で時間がかかるため）
\def\fol@hmetrics#1{%
  \fol@setff#1\fol@hfamily\fol@fam
  \edef\fol@mkey{H\fol@fnm\fol@ff\fol@fam\relax|\number\fol@hkindnum|\fol@hdir|\detokenize\expandafter{\fol@thickness}}%
  \fol@metricscache{\fol@hmetrics@calc#1}}
\def\fol@vmetrics#1#2#3{%
  \fol@setff#1\fol@vfamily\fol@fam
  \edef\fol@mkey{V\fol@fnm\fol@ff\fol@fam\relax|\fol@fnm\fol@ff\tw@\relax|#3|\fol@vdir|\detokenize\expandafter{\fol@thickness}}%
  \fol@metricscache{\fol@vmetrics@calc#1#2{#3}}}
\def\fol@metricscache#1{%
  \ifcsname fol@MC@\fol@mkey\endcsname
    \csname fol@MC@\fol@mkey\endcsname
  \else
    #1%
    \expandafter\xdef\csname fol@MC@\fol@mkey\endcsname{%
      \def\noexpand\fol@b{\fol@b}\def\noexpand\fol@t{\fol@t}\def\noexpand\fol@cap{\fol@cap}%
      \def\noexpand\fol@off{\fol@off}\def\noexpand\fol@acr{\fol@acr}%
      \def\noexpand\fol@glyphmid{\fol@glyphmid}}%
  \fi}
\def\fol@usethickness{%
  \ifx\fol@thickness\@empty\else
    \@tempdima=\fol@thickness\relax
    \edef\fol@t{\fpeval{\the\@tempdima}}%
  \fi}
% 拡張フォント（family 3）が拡大されていなければ（family 3のquad）／（family 2のquad），
% 拡大されていれば1
\def\fol@getrthree{%
  \@tempdima\fontdimen6\textfont3
  \@tempdimb\fontdimen6\textfont\tw@
  \edef\fol@rthree{\fpeval{(\the\@tempdima>0pt) ? \the\@tempdima/\the\@tempdimb : 1}}%
  \edef\fol@rthree{\fpeval{abs(\fol@rthree-1)>0.2 ? \fol@rthree : 1}}}
% 数式の軸の高さ
\def\fol@getaxis#1{%
  \fol@setff#1\@tempdima\fontdimen22\fol@ff\tw@
  \edef\fol@axis{\fpeval{\the\@tempdima}}}
% 箱の寸法
\def\fol@getbox#1{%
  \edef\fol@wd{\fpeval{\the\wd#1}}%
  \edef\fol@ht{\fpeval{\the\ht#1}}%
  \edef\fol@dp{\fpeval{\the\dp#1}}}

%% ---------------------------------------------------------------
%% 箱に斜線を重ねる
%%   \fol@overh{style}{box}{dir}：横向きの矢印の箱（dir＝1で右向き，-1で左向き）
%%   \fol@overv{style}{box}{dir}{kind}：縦向きの矢印の箱（dir＝-1で下向き，1で上向き）
%% ---------------------------------------------------------------
\def\fol@overh#1#2#3{%
  \def\fol@hdir{#3}%
  \fol@hmetrics#1\fol@getaxis#1\fol@getbox#2%
  % 3本線の高さ：グリフから矢頭の上下の中心が読めればそれ，読めなければ数式の軸
  \ifx\fol@glyphmid\@empty\else\let\fol@axis\fol@glyphmid\fi
  \edef\fol@axis{\fpeval{\fol@axis+\fol@acr}}%
  \hbox{\fol@strokes
    {\fpeval{\fol@wd/2-(#3)*(\fol@shift*\fol@b+\fol@off)}}{\fol@axis}{#3}{0}{\fol@b}{\fol@t}%
    % 斜線の上下の広がりを箱の高さ・深さに入れ，上下のラベルと重ならないようにする
    \vrule\@width\z@
      \@height\fpeval{\fol@axis+(0.5*\fol@span*\fol@b+0.5*\fol@t)}pt
      \@depth\fpeval{max(0,(0.5*\fol@span*\fol@b+0.5*\fol@t)-\fol@axis)}pt
    \box#2}}
\def\fol@overv#1#2#3#4{%
  \def\fol@vdir{#3}%
  \fol@vmetrics#1#2{#4}\fol@getbox#2%
  \hbox{\fol@strokes
    {\fpeval{\fol@wd/2-\fol@acr}}%
    {\fpeval{(\fol@ht-\fol@dp)/2-(#3)*(\fol@shift*\fol@b+\fol@off)}}%
    {0}{#3}{\fol@b}{\fol@t}%
    \box#2}}

%% ---------------------------------------------------------------
%% 本文の数式用
%% ---------------------------------------------------------------
% 長い矢印：unicode-mathで数式フォントにU+27F6，U+27F5がなければ（XITS Math Bold），\LaTeX{}の
% 元の定義と同じく\relbar\joinrel\rightarrow（\leftarrow\joinrel\relbar）で組む
\def\fol@longright{\fol@iflongchar{"27F6}\longrightarrow{\relbar\joinrel\rightarrow}}
\def\fol@longleft{\fol@iflongchar{"27F5}\longleftarrow{\leftarrow\joinrel\relbar}}
\def\fol@iflongchar#1#2#3{%
  \ifdefined\Umathcode
    \fol@hfamily\fol@lfam
    \iffontchar\textfont\numexpr\fol@lfam\relax#1 \def\fol@tmp{#2}\else\def\fol@tmp{#3}\fi
  \else
    \def\fol@tmp{#2}%
  \fi
  \fol@tmp}
\DeclareRobustCommand*\folrightarrow{\mathrel{\mathpalette\fol@rightarrow\relax}}
\DeclareRobustCommand*\folleftarrow{\mathrel{\mathpalette\fol@leftarrow\relax}}
\DeclareRobustCommand*\foldownarrow{\mathrel{\mathpalette\fol@downarrow\relax}}
\DeclareRobustCommand*\foluparrow{\mathrel{\mathpalette\fol@uparrow\relax}}
\def\fol@rightarrow#1#2{\fol@tryglyph#1\z@{%
  \setbox\z@\hbox{$\m@th#1\fol@longright$}\fol@overh#1\z@{1}}}
\def\fol@leftarrow#1#2{\fol@tryglyph#1\@ne{%
  \setbox\z@\hbox{$\m@th#1\fol@longleft$}\fol@overh#1\z@{-1}}}
% 縦向きの土台：\right.が空の区切り記号の幅（\nulldelimiterspace）を右に足すと箱の中心が
% 軸からずれるので，\Bigと同じく0にして組む．高さは記号フォントのquadの1.25倍とする
% （本文のフォントによらず，数式フォントだけで形が決まるようにするため）．
% \fol@vbase{style}{\downarrowか\uparrow}：土台を\box\z@に組む．区切り記号の字形の選び方が
% 文字の大きさによらないよう，\delimiterfactorを1000，\delimitershortfallを0にする．
\def\fol@vbase#1#2{%
  \fol@setff#1\@tempdima=1.25\fontdimen6\fol@ff\tw@
  \setbox\z@\hbox{$\m@th\nulldelimiterspace\z@\delimiterfactor\@m\delimitershortfall\z@
    #1\left#2\vcenter to\@tempdima{}\right.$}}
\def\fol@downarrow#1#2{\fol@tryglyph#1\tw@{%
  \fol@tryrotv#1{-1}{}{%
    \fol@vbase#1\downarrow
    \fol@overv#1\z@{-1}{inl}}}}
\def\fol@uparrow#1#2{\fol@tryglyph#1\thr@@{%
  \fol@tryrotv#1{1}{}{%
    \fol@vbase#1\uparrow
    \fol@overv#1\z@{1}{inl}}}}

%% ---------------------------------------------------------------
%% 横向きの矢印を回した縦向きの矢印
%%   ↓↑の伸縮の部品がずれているOpenTypeの数式フォント（Pennstander Math）では，大きな
%%   区切り記号として組んだ↓↑が崩れる（軸の部品と矢頭の部品の軸の位置が合わない）．
%%   そのようなフォント（folarrow-otf.defの\fol@otfrotv）では，描いて組む縦向きの矢印の土台を，
%%   横向きの矢印を90°回したものにする（OTFの字形と同じ作り方）．
%%   \fol@tryrotv{style}{dir}{長さ}{そうでない場合の処理}：dirは-1で下向き，1で上向き．
%%   長さが空なら\longrightarrow，空でなければその長さの伸びる矢印（amscd用）を回す．
%%   3本線は，横向きの矢印の実測値（矢頭の幅，軸の太さ，中心のずれ）を回した位置に描く．
%% ---------------------------------------------------------------
\def\fol@tryrotv#1#2#3#4{%
  \fol@setff#1\fol@vfamily\fol@fam
  \fol@ifrotv{\fol@ff\fol@fam\relax}{\fol@rotv#1{#2}{#3}}{#4}}
% \fol@hink{style}{box}：横向きの矢印の箱の字面の左端と右端（pt）を\fol@inkl，\fol@inkrに入れる．
% 読めなければ\fol@inklを空にする．LuaTeXはfolarrow.hink，XeTeXは\XeTeXglyphboundsで，
% 最初の字形（\longrightarrowならU+27F6，伸びる矢印ならマイナス記号）の左の余白と，
% 最後の字形（U+27F6か→）の右の余白から求める．
\def\fol@hink#1#2#3{\let\fol@inkl\@empty
  \ifdefined\fol@uselua
    \edef\@tempa{\directlua{folarrow.hink(\number#2)}}%
    \ifx\@tempa\@empty\else\expandafter\fol@hink@split\@tempa\@nil\fi
  \else\ifdefined\XeTeXglyphbounds
    \fol@setff#1\fol@hfamily\fol@fam
    \ifnum\XeTeXfonttype\fol@ff\fol@fam=\tw@
      \begingroup
        \the\fol@ff\fol@fam\relax
        \ifx\@empty#3\@empty
          \count@=\XeTeXcharglyph"27F6 \count@ii=\count@
        \else
          \count@=\XeTeXcharglyph"2212 \count@ii=\XeTeXcharglyph"2192
        \fi
        \@tempdima=\XeTeXglyphbounds1 \count@
        \@tempdimb=\wd#2\advance\@tempdimb-\XeTeXglyphbounds3 \count@ii
        \xdef\fol@hink@tmp{\strip@pt\@tempdima\space\strip@pt\@tempdimb}%
      \endgroup
      \expandafter\fol@hink@split\fol@hink@tmp\@nil
    \fi
  \fi\fi}
\def\fol@hink@split#1 #2\@nil{\def\fol@inkl{#1}\def\fol@inkr{#2}}
\newcount\count@ii
\def\fol@rotv#1#2#3{%
  \def\@tempa{#3}%
  \ifx\@tempa\@empty
    \setbox\z@\hbox{$\m@th#1\fol@longright$}%
    \chardef\fol@hkindnum=\z@
  \else
    \setbox\z@\hbox to#3{\rightarrowfill@#1}%
    \chardef\fol@hkindnum=\@ne
  \fi
  \def\fol@hdir{1}%
  \fol@hmetrics#1\fol@getaxis#1\fol@getbox\z@
  \let\fol@vaxis\fol@axis
  \ifx\fol@glyphmid\@empty\else\let\fol@axis\fol@glyphmid\fi
  % 横向きの矢印の字面の中心（箱の基準点から）．字面の左右の端が読めればその中央，
  % 読めなければ箱の中央から実測の中心のずれを引いたもの
  \fol@hink#1\z@{#3}%
  \ifx\fol@inkl\@empty
    \edef\fol@cx{\fpeval{\fol@wd/2-\fol@off}}%
  \else
    \edef\fol@cx{\fpeval{(\fol@inkl+\fol@inkr)/2}}%
  \fi
  \edef\fol@cy{\fpeval{\fol@axis+\fol@acr}}%
  % 回したあと（\rotateboxは回した外接矩形の左端を基準点に置く）の字面の中心の横位置と，
  % 字面の中心を数式の軸に合わせるための上げ幅
  \ifnum#2<\z@
    \edef\fol@x{\fpeval{\fol@cy+\fol@dp}}%
    \edef\fol@r{\fpeval{\fol@vaxis+\fol@cx}}%
    \setbox\z@\hbox{\rotatebox{-90}{\box\z@}}%
  \else
    \edef\fol@x{\fpeval{\fol@ht-\fol@cy}}%
    \edef\fol@r{\fpeval{\fol@vaxis-\fol@cx}}%
    \setbox\z@\hbox{\rotatebox{90}{\box\z@}}%
  \fi
  \hbox{\fol@strokes{\fol@x}{\fol@vaxis}{0}{#2}{\fol@b}{\fol@t}%
    \raise\fol@r\p@\box\z@}}

%% ---------------------------------------------------------------
%% 本文用の矢印のフォント
%%   主な数式フォント（CM，Latin Modern，newtx，txfonts，newpx，pxfonts）には，
%%   記号フォントの→（またはマイナス記号と→）の字形に3本線を加えたType 1フォントを
%%   用意してある（元のフォントから作成した．文字0から順に→←↓↑）．
%%   \rightarrowを持つ記号フォントの名前がfolarrow-glyphs.defにあり，形のキーが既定値
%%   のままなら，本文用の矢印はそのフォントの字形で組む．フォントは記号フォントと同じ
%%   大きさで読む．そうでなければ（unicode-mathのOpenTypeフォントなど）これまでどおり
%%   描く．テキストとしては→←↓↑（U+2192，U+2190，U+2193，U+2191）になる．
%% ---------------------------------------------------------------
\def\fol@glyphfont#1#2{\@namedef{fol@G@#1}{#2}}
\iffol@lite\else \InputIfFileExists{folarrow-glyphs.def}{}{}\fi
% OpenTypeの数式フォント（unicode-math）用のOTF：\fol@otfglyphfont{見分ける文字列}{ファイル名}．
% 見分ける文字列は，元のフォントのファイル名，PostScript名，フルネーム，ファミリー名を小文字に
% して英数字だけ残したもの．\fontnameからフォント名の部分（「name:」や「[…]」の中，
% 「:」や「/OT」の前）を取り出して同じようにしたものと，完全に一致すれば使う．
% 文字はUnicodeの位置（→U+2192，←U+2190，↓U+2193，↑U+2191）にある．
\ifdefined\XeTeXrevision\def\fol@otfok{}\fi
\ifdefined\directlua\def\fol@otfok{}\fi
\iffol@lite \let\fol@otfok\@undefined \fi
\ifdefined\fol@otfok
  \def\fol@otfglyphfont#1#2{\@namedef{fol@O@#1}{#2}}
  \def\fol@otfrotv#1{\@namedef{fol@RV@#1}{}\def\fol@hasrotv{}}
  \ifdefined\XeTeXrevision
    \let\fol@otfrotvxe\fol@otfrotv
  \else
    \def\fol@otfrotvxe#1{}
  \fi
  \InputIfFileExists{folarrow-otf.def}{}{}
\fi
% 番兵：「フォントがない」ことを表す．\protectedなので，見出しなどを書き出すときにも展開されない
\protected\def\fol@nofont{}
% \fol@tryglyph{style}{文字の番号}{描く場合の処理}
\def\fol@tryglyph#1#2#3{%
  \let\fol@gf\fol@nofont
  \iffol@glyphs\iffol@defaultshape
    \fol@setff#1\fol@hfamily\fol@fam
    \fol@getglyphfont{\fol@ff\fol@fam\relax}%
  \fi\fi
  % LuaTeX-jaは水平モードのU+2190〜U+2193を和文文字として和文フォントで組むので，
  % \ltjalcharで欧文の文字として組む
  \ifx\fol@gf\fol@nofont #3\else
    \hbox{\fol@gf\ifdefined\ltjalchar\ltjalchar\else\char\fi\ifx\fol@gkind\fol@gkind@o
      \ifcase\numexpr#2\relax"2192\or"2190\or"2193\else"2191\fi\else#2\fi}%
  \fi}
\def\fol@gkind@o{o}
\ExplSyntaxOn
\tl_new:N \l__fol_tl
\tl_new:N \l__fol_at_tl
\str_new:N \l__fol_key_str
% \fol@getglyphfont{フォント}：対応するフォントを（まだなら読んで）\fol@gfにする．
% 読んだフォントは「fol@F@〈\fontnameの文字列〉」に覚えておく（ないことも覚える）．
% フォント（TFM）はfolarrow-glyphs.defと一緒に配布するので，あるものとする．
\def\fol@fnm#1\relax{\fontname#1}
\cs_new_protected:Npn \fol@getglyphfont #1
  {
    \cs_if_exist:cTF { fol@GC@ \fol@fnm #1 }
      {
        \cs_set_eq:Nc \fol@gf { fol@GC@ \fol@fnm #1 }
        \cs_set_eq:Nc \fol@gkind { fol@GK@ \fol@fnm #1 }
      }
      {
        \__fol_getglyphfont:n {#1}
        \cs_gset_eq:cN { fol@GC@ \fol@fnm #1 } \fol@gf
        \cs_gset_eq:cN { fol@GK@ \fol@fnm #1 } \fol@gkind
      }
  }
\cs_new_protected:Npn \__fol_getglyphfont:n #1
  {
    \str_set:Nx \l__fol_key_str { \fontname #1 }
    \regex_replace_once:nnN { \\relax.* } { } \l__fol_key_str
    \cs_if_exist:cF { fol@F@ \l__fol_key_str }
      {
        \cs_gset_eq:cN { fol@F@ \l__fol_key_str } \fol@nofont
        \cs_gset_eq:cN { fol@K@ \l__fol_key_str } \fol@gkind@t
        \fol@basename {#1}
        \cs_if_exist:cF { fol@G@ \fol@fname } { \__fol_otfglyphfont: }
        \cs_if_exist:cT { fol@G@ \fol@fname }
          {
            \tl_set:Nx \l__fol_tl { \use:c { fol@G@ \fol@fname } }
            \regex_extract_once:nVNTF { \sat\s*(\S+) } \l__fol_key_str \l__fol_seq
              {
                \tl_set:Nx \l__fol_at_tl
                  { \c_space_tl at \c_space_tl \seq_item:Nn \l__fol_seq { 2 } }
              }
              { \tl_clear:N \l__fol_at_tl }
            \use:x
              {
                \global \font \exp_not:c { fol@F@ \l__fol_key_str }
                  = \l__fol_tl \l__fol_at_tl \scan_stop:
              }
          }
      }
    \cs_set_eq:Nc \fol@gf { fol@F@ \l__fol_key_str }
    \cs_set_eq:Nc \fol@gkind { fol@K@ \l__fol_key_str }
  }
\def\fol@gkind@t{t}
% OpenTypeの数式フォントなら，対応するOTFを元のフォントと同じ大きさ，同じ添字用字形の
% 指定（+ssty=0など）で読む．
\cs_new_protected:Npn \__fol_otfglyphfont:
  {
    \__fol_namekey:
    \tl_clear:N \l__fol_tl
    \cs_if_exist:cT { fol@O@ \l__fol_str }
      { \tl_set:Nx \l__fol_tl { \use:c { fol@O@ \l__fol_str } } }
    \tl_if_empty:NF \l__fol_tl
      {
        \regex_extract_once:nVNTF { \sat\s*(\S+) } \l__fol_key_str \l__fol_seq
          { \tl_set:Nx \l__fol_at_tl { \c_space_tl at \c_space_tl \seq_item:Nn \l__fol_seq { 2 } } }
          { \tl_clear:N \l__fol_at_tl }
        \regex_extract_once:nVNTF { \+ssty=(\d+) } \l__fol_key_str \l__fol_seq
          { \tl_set:Nx \l__fol_ssty_tl { \seq_item:Nn \l__fol_seq { 2 } } }
          { \tl_clear:N \l__fol_ssty_tl }
        \ifdefined\XeTeXrevision
          \tl_set:Nx \l__fol_tl
            { "[\l__fol_tl]\tl_if_empty:NF \l__fol_ssty_tl { /OT:+ssty=\l__fol_ssty_tl ; }" }
        \else
          \tl_set:Nx \l__fol_tl
            { "[\l__fol_tl]:mode=base\tl_if_empty:NF \l__fol_ssty_tl { ;+ssty=\l__fol_ssty_tl }" }
        \fi
        \use:x
          {
            \global \font \exp_not:c { fol@F@ \l__fol_key_str }
              = \l__fol_tl \l__fol_at_tl \scan_stop:
          }
        \cs_gset_eq:cN { fol@K@ \l__fol_key_str } \fol@gkind@o
      }
  }
\cs_generate_variant:Nn \regex_match:nnTF { nV }
% \l__fol_key_str（\fontnameの文字列）から，フォント名の部分（「name:」や「[…]」の中，「:」や
% 「/OT」の前）を取り出し，小文字にして英数字だけ残したものを\l__fol_strに入れる．
\cs_new_protected:Npn \__fol_namekey:
  {
    \str_set_eq:NN \l__fol_str \l__fol_key_str
    \regex_replace_once:nnN { \A\"? } { } \l__fol_str
    \regex_replace_once:nnN { \A(name|file): } { } \l__fol_str
    \regex_match:nVTF { \A\[ } \l__fol_str
      {
        \regex_replace_once:nnN { \A\[([^\]]*)\].* } { \1 } \l__fol_str
        \regex_replace_once:nnN { .*/ } { } \l__fol_str
      }
      { \regex_replace_once:nnN { [:/\"].* } { } \l__fol_str }
    \str_set:Nx \l__fol_str { \str_lowercase:f { \l__fol_str } }
    \regex_replace_all:nnN { [^a-z0-9] } { } \l__fol_str
  }
% \fol@ifrotv{フォント}{真}{偽}：縦向きの矢印を横向きの矢印を回して組むフォントか
% （folarrow-otf.defの\fol@otfrotv．↓↑の伸縮の部品がずれていて，大きな区切り記号が崩れるもの）
\cs_new_protected:Npn \fol@ifrotv #1#2#3
  {
    \cs_if_exist:NTF \fol@hasrotv
      {
        \cs_if_exist:cF { fol@RVC@ \fol@fnm #1 }
          {
            \str_set:Nx \l__fol_key_str { \fontname #1 }
            \__fol_namekey:
            \cs_if_exist:cTF { fol@RV@ \l__fol_str }
              { \cs_gset_eq:cN { fol@RVC@ \fol@fnm #1 } \use_i:nn }
              { \cs_gset_eq:cN { fol@RVC@ \fol@fnm #1 } \use_ii:nn }
          }
        \use:c { fol@RVC@ \fol@fnm #1 } {#2} {#3}
      }
      {#3}
  }
\tl_new:N \l__fol_ssty_tl
\cs_generate_variant:Nn \regex_extract_once:nnNTF { nV }
\ExplSyntaxOff
% マップファイルと，テキストとしての値（ToUnicode）
\iffol@glyphs
  \ifdefined\pdfextension % LuaTeX
    \ifnum\outputmode>\z@
      \pdfextension mapfile{+folarrow.map}%
      \pdfvariable gentounicode=\@ne
      \pdfextension glyphtounicode{arrowright}{2192}%
      \pdfextension glyphtounicode{arrowleft}{2190}%
      \pdfextension glyphtounicode{arrowdown}{2193}%
      \pdfextension glyphtounicode{arrowup}{2191}%
    \fi
  \else\ifdefined\pdfoutput % pdfTeX（XeTeXには\pdfoutputがない）
    \ifnum\pdfoutput>\z@
      \pdfmapfile{+folarrow.map}%
      \pdfgentounicode=\@ne
      \pdfglyphtounicode{arrowright}{2192}%
      \pdfglyphtounicode{arrowleft}{2190}%
      \pdfglyphtounicode{arrowdown}{2193}%
      \pdfglyphtounicode{arrowup}{2191}%
    \fi
  \fi\fi
  % dvipdfmx，xdvipdfmx：字形の名前（arrowrightなど）からToUnicodeを作るので，
  % マップファイルだけ読ませる．dvipsではupdmapでfolarrow.mapを登録しておく．
  \AtBeginDocument{%
    \def\fol@tempa{dvipdfmx.def}\def\fol@tempb{xetex.def}%
    \ifdefined\Gin@driver
      \ifx\Gin@driver\fol@tempa\fol@dvipdfmxmap\fi
      \ifx\Gin@driver\fol@tempb\fol@dvipdfmxmap\fi
      % dvipsはパッケージからマップファイルを読ませられないので，登録が要ることを知らせる
      \def\fol@tempa{dvips.def}%
      \ifx\Gin@driver\fol@tempa
        \PackageWarningNoLine{folarrow}{%
          With dvips, the map file folarrow.map must be\MessageBreak
          enabled (updmap-user --enable Map=folarrow.map,\MessageBreak
          or dvips -u +folarrow.map). Otherwise the inline\MessageBreak
          arrows are replaced by other glyphs.\MessageBreak
          The option glyphs=false avoids the arrow fonts}%
      \fi
    \fi}
  \def\fol@dvipdfmxmap{\AddToHook{shipout/firstpage}{\special{pdf:mapfile folarrow.map}}}
\fi

%% 伸びる矢印：\xfolrightarrow[下]{上}，\xfolleftarrow[下]{上}
%% （amsmathの\xrightarrowと同じ組み方で，できた矢印に斜線を重ねる）
\providecommand\rightarrowfill@{\arrowfill@\relbar\relbar\rightarrow}
\providecommand\leftarrowfill@{\arrowfill@\leftarrow\relbar\relbar}
\providecommand\arrowfill@[4]{%
  $\m@th\thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
   \relax#4#1\mkern-7mu%
   \cleaders\hbox{$#4\mkern-2mu#2\mkern-2mu$}\hfill
   \mkern-7mu#3$}
% hyperrefのしおりでは，矢印は→←↓↑の文字にし，伸びる矢印のラベルは捨てる
% （引数を取る定義は外に置き，\letで置き換える．フックの中に#を書くと二重に処理されるため）
\def\fol@pdfstr@xr#1#{\textrightarrow\@gobble}
\def\fol@pdfstr@xl#1#{\textleftarrow\@gobble}
\AtBeginDocument{%
  \ifdefined\pdfstringdefDisableCommands
    \pdfstringdefDisableCommands{%
      \def\folrightarrow{\textrightarrow}\def\folleftarrow{\textleftarrow}%
      \def\foldownarrow{\textdownarrow}\def\foluparrow{\textuparrow}%
      \let\xfolrightarrow\fol@pdfstr@xr \let\xfolleftarrow\fol@pdfstr@xl}%
  \fi}
\newcommand*\xfolrightarrow[2][]{\fol@extarrow 0359\rightarrowfill@{1}{#1}{#2}}
\newcommand*\xfolleftarrow[2][]{\fol@extarrow 3095\leftarrowfill@{-1}{#1}{#2}}
\def\fol@extarrow#1#2#3#4#5#6#7#8{%
  \mathrel{\mathop{%
    \setbox\z@\hbox{#5\displaystyle}%
    \setbox\tw@\vbox{\m@th
      \hbox{$\scriptstyle\mkern#3mu{#7}\mkern#4mu$}%
      \hbox{$\scriptstyle\mkern#3mu{#8}\mkern#4mu$}%
      \copy\z@}%
    % 短すぎると斜線が窮屈になるので，\longrightarrowの長さを最小とする
    \setbox\@ne\hbox{$\m@th\displaystyle\fol@longright$}%
    \ifdim\wd\tw@<\wd\@ne \setbox\tw@\hbox to\wd\@ne{}\fi
    \setbox\z@\hbox to\wd\tw@{\unhbox\z@}%
    \chardef\fol@hkindnum=\@ne
    \fol@overh\displaystyle\z@{#6}}%
  \limits
    \@ifnotempty{#8}{^{\if0#1\else\mkern#1mu\fi
                       #8\if0#2\else\mkern#2mu\fi}}%
    \@ifnotempty{#7}{_{\if0#2\else\mkern#2mu\fi
                       #7\if0#1\else\mkern#1mu\fi}}}}

%% ---------------------------------------------------------------
%% amscd：@F>>>，@F<<<，@FVVV，@FAAA
%%   通常の@>>>などの@の直後にFを付けると斜線入りになる．
%% ---------------------------------------------------------------
\def\fol@amscd{%
  % unicode-mathは\begin{document}で@の数式コードを上書きし，amscdの@>>>などが
  % 使えなくなる．amscdの設定（数式中で@を特別な意味にする）に戻す．unicode-mathを
  % folarrowより後に読むと，unicode-mathの上書きがこの後になるので，CD環境の始めでも戻す．
  \mathcode`\@="8000
  \AddToHook{env/CD/begin}{\mathcode`\@="8000 }%
  \atdef@ F##1{%
    \@ifundefined{fol@CD\string##1}%
      {\PackageError{folarrow}{@F must be followed by >, <, V or A}\@eha}%
      {\csname fol@CD\string##1\endcsname}}%
}
\@namedef{fol@CD>}#1>#2>{\ampersand@
  \ifCD@ \global\bigaw@\minCDarrowwidth \else \global\bigaw@\minaw@ \fi
  % 大きな文字では\minCDarrowwidth（既定2.5pc）が短すぎて3本線が矢頭にかかるので，
  % \longrightarrowの長さより短くしない
  \setboxz@h{$\m@th\displaystyle\fol@longright$}%
  \ifdim\wdz@>\bigaw@\global\bigaw@\wdz@\fi
  \setboxz@h{$\m@th\scriptstyle\;{#1}\;\;$}%
  \ifdim\wdz@>\bigaw@\global\bigaw@\wdz@\fi
  \@ifnotempty{#2}{\setbox\@ne\hbox{$\m@th\scriptstyle\;{#2}\;\;$}%
    \ifdim\wd\@ne>\bigaw@\global\bigaw@\wd\@ne\fi}%
  \ifCD@\enskip\fi
  \mathrel{\mathop{%
      \setbox\z@\hbox to\bigaw@{\rightarrowfill@\displaystyle}%
      \chardef\fol@hkindnum=\@ne
      \fol@overh\displaystyle\z@{1}}%
    \limits^{#1}\@ifnotempty{#2}{_{#2}}}%
  \ifCD@\enskip\fi \ampersand@}
\@namedef{fol@CD<}#1<#2<{\ampersand@
  \ifCD@ \global\bigaw@\minCDarrowwidth \else \global\bigaw@\minaw@ \fi
  % 大きな文字では\minCDarrowwidth（既定2.5pc）が短すぎて3本線が矢頭にかかるので，
  % \longrightarrowの長さより短くしない
  \setboxz@h{$\m@th\displaystyle\fol@longright$}%
  \ifdim\wdz@>\bigaw@\global\bigaw@\wdz@\fi
  \setboxz@h{$\m@th\scriptstyle\;\;{#1}\;$}%
  \ifdim\wdz@>\bigaw@ \global\bigaw@\wdz@ \fi
  \@ifnotempty{#2}{\setbox\@ne\hbox{$\m@th\scriptstyle\;\;{#2}\;$}%
    \ifdim\wd\@ne>\bigaw@ \global\bigaw@\wd\@ne \fi}%
  \ifCD@\enskip\fi
  \mathrel{\mathop{%
      \setbox\z@\hbox to\bigaw@{\leftarrowfill@\displaystyle}%
      \chardef\fol@hkindnum=\@ne
      \fol@overh\displaystyle\z@{-1}}%
    \limits^{#1}\@ifnotempty{#2}{_{#2}}}%
  \ifCD@\enskip\fi \ampersand@}
\@namedef{fol@CDV}#1V#2V{\CD@check{FV..V..V}{\llap{$\m@th\vcenter{\hbox
  {$\scriptstyle#1$}}$}\fol@Bigv\downarrow{-1}%
  \rlap{$\m@th\vcenter{\hbox{$\scriptstyle#2$}}$}&&}}
\@namedef{fol@CDA}#1A#2A{\CD@check{FA..A..A}{\llap{$\m@th\vcenter{\hbox
  {$\scriptstyle#1$}}$}\fol@Bigv\uparrow{1}%
  \rlap{$\m@th\vcenter{\hbox{$\scriptstyle#2$}}$}&&}}
% 回して組むときの長さは，\Bigの区切り記号に求める高さ（空の区切り記号の\Big.の箱の高さ＋深さ）
\newdimen\fol@Blen
\def\fol@Bigv#1#2{%
  \setbox\z@\hbox{$\m@th\Big.$}\fol@Blen=\dimexpr\ht\z@+\dp\z@\relax
  \mathord{\fol@tryrotv\textstyle{#2}{\fol@Blen}{%
    \setbox\z@\hbox{$\m@th\Big#1$}\fol@overv\textstyle\z@{#2}{big}}}}

%% ---------------------------------------------------------------
%% xy-pic：\ar[d]|@{fol}
%%   矢印の途中に置く大きさ0の方向付き物体（\newdir）．矢印は切れない．
%%   斜線の向きはその矢印の向きから決まる．
%% ---------------------------------------------------------------
\def\fol@xy{\newdir{fol}{*=0{\fol@xymark}}}
% \folpad{ラベル}：ラベルの四方に斜線の半分の長さの余白を付ける．xy-picの矢印のラベルが
% 斜線にかからないようにするときに\ar[r]|@{fol}^{\folpad{f}}のように使う．
\newcommand*\folpad[1]{\mathpalette\fol@pad{#1}}
\def\fol@pad#1#2{%
  \fol@hmetrics#1%
  \@tempdima=\fpeval{0.5*\fol@span*\fol@b}pt
  \setbox\z@\hbox{$\m@th#1#2$}%
  \hbox{\kern\@tempdima
    \vrule\@width\z@\@height\dimexpr\ht\z@+\@tempdima\relax
      \@depth\dimexpr\dp\z@+\@tempdima\relax
    \box\z@\kern\@tempdima}}
\def\fol@xymark{%
  \fol@hmetrics\textstyle
  \def\fol@cap{r}% xy-picの線の端は丸い
  \fol@strokes
    {\fpeval{-\fol@shift*\fol@b*(\cosDirection)}}%
    {\fpeval{-\fol@shift*\fol@b*(\sinDirection)}}%
    {\cosDirection}{\sinDirection}{\fol@b}{\fol@t}}

%% ---------------------------------------------------------------
%% tikz-cd：\arrow[d, foliated]
%% ---------------------------------------------------------------
\def\fol@tikz{%
  \usetikzlibrary{decorations.markings}%
  \tikzset{
    foliated/.style={
      postaction={decorate,
        decoration={markings,
          mark=at position 0.5 with {\fol@tikzmark}}},
      % ラベルが斜線にかからないよう，この矢印のラベルだけ余白を斜線の半分の長さだけ増やす
      % （tikz-cdの既定は0.5ex．矢頭の幅はおよそ0.4～0.55 em）
      /tikz/commutative diagrams/every label/.append style={
        inner sep={0.5ex+0.28em*\fol@span}}},
    commutative diagrams/foliated/.style={/tikz/foliated}}%
}
\def\fol@tikzmark{%
  % マーキングの座標系は矢印の向きに回っている（x軸が矢印の向き）．
  \fol@hmetrics\textstyle
  \edef\fol@c{\fpeval{cosd(\pgfdecoratedangle)}}%
  \edef\fol@si{\fpeval{sind(\pgfdecoratedangle)}}%
  % 右上がりになる符号（\fol@strokesと同じ判定）
  \edef\fol@sg{\fpeval{
      ((\fol@lean*\fol@c-\fol@si)*(\fol@lean*\fol@si+\fol@c) >= 0) ? 1 : -1}}%
  \edef\fol@s{\fpeval{\fol@span*\fol@b}}%
  \edef\fol@x{\fpeval{-\fol@shift*\fol@b}}%
  \ifx\fol@thickness\@empty\else\pgfsetlinewidth{\fol@thickness}\fi
  % 線の端は矢印の線の設定（line cap）をそのまま使う（tikz-cdの既定は切りっぱなし）
  \pgfsetarrows{-}%
  % 破線・点線（dashed，dotted）の模様は3本線には付けない
  \pgfsetdash{}{0pt}%
  \foreach \fol@k in {-1,0,1}{%
    \pgfpathmoveto{\pgfpoint
      {(\fol@x+\fol@k*\fol@gap*\fol@b-0.5*\fol@sg*\fol@lean*\fol@s)*1pt}
      {-0.5*\fol@s*1pt}}%
    \pgfpathlineto{\pgfpoint
      {(\fol@x+\fol@k*\fol@gap*\fol@b+0.5*\fol@sg*\fol@lean*\fol@s)*1pt}
      {0.5*\fol@s*1pt}}}%
  \pgfusepath{stroke}}

\AtBeginDocument{%
  \@ifpackageloaded{amscd}{\fol@amscd}{}%
  \@ifpackageloaded{tikz-cd}{\fol@tikz}{}%
  \@ifpackageloaded{xy}{\fol@xy}{}%
}
\endinput
