如何在纯 TeX 中定义“rotatebox”?

如何在纯 TeX 中定义“rotatebox”?

我想知道是否可以rotatebox在普通的旧 TeX 中进行定义(无需导入eplainpstricksminiltx其他,或使用pdfrotate或其他特定于 pdf 的命令)。

“rotate”这个词似乎没有出现在TeXbook中,它仅指vboxhbox

用例:

如果有一个用于原点中心的宏、另一个用于原点左上角的宏(或使用不同参数的相同宏)等等,那就太好了,但只有一个宏才是有效的答案,可以帮助我理解如何做这样的事情。

答案1

我只填写了后端代码,因为pdftex最后的条件的其他分支将需要合适的\Grot@start定义(来自graphics-def/luatex.def等)

但这适用于pdftex

在此处输入图片描述

%package
\catcode`@=11

%latex.ltx
\def\zap@space#1 #2{%
  #1%
  \ifx#2\@empty\else\expandafter\zap@space\fi
  #2}
\def\@car#1#2\@nil{#1}
\def\@cdr#1#2\@nil{#2}
\def\@empty{}
\long\def\@gobble#1{}
\long\def\@firstofone#1{#1}

%trig.sty
\chardef\nin@ty=90
\chardef\@clxxx=180
\chardef\@lxxi=71
\mathchardef\@mmmmlxviii=4068
\chardef\@coeffz=72
\chardef\@coefb=42
\mathchardef\@coefc=840
\mathchardef\@coefd=5040
{\catcode`t=12\catcode`p=12\gdef\noPT#1pt{#1}}
\def\TG@rem@pt#1{\expandafter\noPT\the#1\space}
\def\TG@term#1{%
 \dimen@\@tempb\dimen@
 \advance\dimen@ #1\p@}
\def\TG@series{%
 \dimen@\@lxxi\dimen@
 \divide \dimen@ \@mmmmlxviii
 \edef\@tempa{\TG@rem@pt\dimen@}%
 \dimen@\@tempa\dimen@
 \edef\@tempb{\TG@rem@pt\dimen@}%
 \divide\dimen@\@coeffz
 \advance\dimen@\m@ne\p@
 \TG@term\@coefb
 \TG@term{-\@coefc}%
 \TG@term\@coefd
 \dimen@\@tempa\dimen@
 \divide\dimen@ \@coefd}
\def\CalculateSin#1{{%
  \expandafter\ifx\csname sin(\number#1)\endcsname\relax
    \dimen@=#1\p@\TG@@sin
    \expandafter\xdef\csname sin(\number#1)\endcsname
                                    {\TG@rem@pt\dimen@}%
  \fi}}
\def\CalculateCos#1{{%
  \expandafter\ifx\csname cos(\number#1)\endcsname\relax
    \dimen@=\nin@ty\p@
    \advance\dimen@-#1\p@
    \TG@@sin
    \expandafter\xdef\csname cos(\number#1)\endcsname
                                     {\TG@rem@pt\dimen@}%
  \fi}}
\def\TG@reduce#1#2{%
\dimen@#1#2\nin@ty\p@
  \advance\dimen@#2-\@clxxx\p@
  \dimen@-\dimen@
  \TG@@sin}
\def\TG@@sin{%
  \ifdim\TG@reduce>+%
  \else\ifdim\TG@reduce<-%
  \else\TG@series\fi\fi}%
\def\UseSin#1{\csname sin(\number#1)\endcsname}
\def\UseCos#1{\csname cos(\number#1)\endcsname}
\def\z@num{0 }
\def\@tempa{1 }
\def\@tempb{-1 }
\expandafter\let\csname sin(0)\endcsname\z@num
\expandafter\let\csname cos(0)\endcsname\@tempa
\expandafter\let\csname sin(90)\endcsname\@tempa
\expandafter\let\csname cos(90)\endcsname\z@num
\expandafter\let\csname sin(-90)\endcsname\@tempb
\expandafter\let\csname cos(-90)\endcsname\z@num


%graphics.sty
\newdimen\Grot@height
\newdimen\Grot@left
\newdimen\Grot@right
\newdimen\Grot@depth
\newdimen\Grot@l
\newdimen\Grot@r
\newdimen\Grot@h
\newdimen\Grot@d
\newdimen\Grot@x
\newdimen\Grot@y
\long\def\rotatebox#1#2{%
  \leavevmode
  \Grot@setangle{#1}%
  \setbox\z@\hbox{{#2}}%
  \Grot@x\z@
  \Grot@y\z@
  \Grot@box}
\def\Grot@setangle#1{\edef\Grot@angle{#1}}
\def\Grot@Px#1#2#3{%
        #1\Grot@cos#2%
        \advance#1-\Grot@sin#3}
\def\Grot@Py#1#2#3{%
        #1\Grot@sin#2%
        \advance#1\Grot@cos#3}
\def\Grot@box{%
  \begingroup
  \CalculateSin\Grot@angle
  \CalculateCos\Grot@angle
  \edef\Grot@sin{\UseSin\Grot@angle}%
  \edef\Grot@cos{\UseCos\Grot@angle}%
  \Grot@r\wd\z@  \advance\Grot@r-\Grot@x
  \Grot@l\z@     \advance\Grot@l-\Grot@x
  \Grot@h\ht\z@  \advance\Grot@h-\Grot@y
  \Grot@d-\dp\z@ \advance\Grot@d-\Grot@y
  \ifdim\Grot@sin\p@>\z@
    \ifdim\Grot@cos\p@>\z@
      \Grot@Py\Grot@height \Grot@r\Grot@h%B
      \Grot@Px\Grot@right  \Grot@r\Grot@d%E
      \Grot@Px\Grot@left   \Grot@l\Grot@h%C
      \Grot@Py\Grot@depth  \Grot@l\Grot@d%D
    \else
      \Grot@Py\Grot@height \Grot@r\Grot@d%E
      \Grot@Px\Grot@right  \Grot@l\Grot@d%D
      \Grot@Px\Grot@left   \Grot@r\Grot@h%B
      \Grot@Py\Grot@depth  \Grot@l\Grot@h%C
    \fi
  \else
    \ifdim\Grot@cos\p@<\z@
      \Grot@Py\Grot@height \Grot@l\Grot@d%D
      \Grot@Px\Grot@right  \Grot@l\Grot@h%C
      \Grot@Px\Grot@left   \Grot@r\Grot@d%E
      \Grot@Py\Grot@depth  \Grot@r\Grot@h%B
    \else
      \Grot@Py\Grot@height \Grot@l\Grot@h%C
      \Grot@Px\Grot@right  \Grot@r\Grot@h%B
      \Grot@Px\Grot@left   \Grot@l\Grot@d%D
      \Grot@Py\Grot@depth  \Grot@r\Grot@d%E
    \fi
  \fi
  \advance\Grot@height\Grot@y
  \advance\Grot@depth\Grot@y
  \Grot@Px\dimen@  \Grot@x\Grot@y
  \Grot@Py\dimen@ii \Grot@x\Grot@y
  \dimen@-\dimen@     \advance\dimen@-\Grot@left
  \dimen@ii-\dimen@ii \advance\dimen@ii\Grot@y
  \setbox\z@\hbox{%
    \kern\dimen@
    \raise\dimen@ii\hbox{\Grot@start\box\z@\Grot@end}}%
  \ht\z@\Grot@height
  \dp\z@-\Grot@depth
  \advance\Grot@right-\Grot@left\wd\z@\Grot@right
  \leavevmode\box\z@
  \endgroup}




\ifx\pdfoutput\undefined
\else
\ifnum\pdfoutput=1
%pdftex.def
\def\GPT@space{ }
\def\GPT@MatrixIdentity{1 0 0 1}
\def\GPT@Zero{0}
\def\GPT@Minus{-}
\def\GPT@NormalizeNumber#1{%
  \edef#1{#1}%
  \edef#1{\expandafter\zap@space#1 \@empty}%
  \edef#1{\expandafter\GPT@ZapPlus#1+\@nil}%
  \edef#1{\expandafter\GPT@ZapMinusMinus#1--\@nil}%
  \expandafter\GPT@Split#1..\@nil
  \ifx\GPT@frac\@empty
  \else
    \edef\GPT@frac{%
      \expandafter\GPT@Reverse\expandafter{\expandafter}\GPT@frac\@nil
    }%
    \edef\GPT@frac{%
      \expandafter\GPT@ZapLeadingZeros\GPT@frac\@empty
    }%
    \ifx\GPT@frac\@empty
    \else
      \edef\GPT@frac{%
        \expandafter\GPT@Reverse\expandafter{\expandafter}\GPT@frac\@nil
      }%
    \fi
  \fi
  \edef\GPT@sign{\expandafter\@car\GPT@int\@empty\@nil}%
  \ifx\GPT@sign\GPT@Minus
    \edef\GPT@int{\expandafter\@cdr\GPT@int\@nil}%
  \else
    \def\GPT@sign{}%
  \fi
  \edef\GPT@int{%
    \expandafter\GPT@ZapLeadingZeros\GPT@int\@empty
  }%
  \edef\GPT@temp{\GPT@int\GPT@frac}%
  \ifx\GPT@temp\@empty
    \def#1{0}%
  \else
    \edef#1{%
      \GPT@sign
      \GPT@int
      \ifx\GPT@frac\@empty
      \else
        .\GPT@frac
      \fi
    }%
  \fi
}
\def\GPT@ZapPlus#1+#2\@nil{%
  #1%
  \ifx\@empty#2\@empty
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {%
    \GPT@ZapPlus#2\@nil
  }%
}
\def\GPT@ZapMinusMinus#1--#2\@nil{%
  #1%
  \ifx\@empty#2\@empty
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {%
    \GPT@ZapMinusMinus#2\@nil
  }%
}
\def\GPT@Split#1.#2.#3\@nil{%
  \def\GPT@int{#1}%
  \ifx\@empty#2\@empty
    \let\GPT@frac\@empty
  \else
    \def\GPT@frac{#2}%
  \fi
}
\def\GPT@Reverse#1#2#3\@nil{%
  \ifx\@empty#3\@empty
    #2#1%
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {%
    \GPT@Reverse{#2#1}#3\@nil
  }%
}
\def\GPT@ZapLeadingZeros#1{%
  \ifx0#1%
    \expandafter\GPT@ZapLeadingZeros
  \else
    #1%
  \fi
}
\def\Grot@start{%
  \GPT@NormalizeNumber\Grot@sin
  \GPT@NormalizeNumber\Grot@cos
  \edef\GPT@temp{%
    \Grot@cos\GPT@space\Grot@sin\GPT@space
    \if-\Grot@sin
    \else
      \ifx\Grot@sin\GPT@Zero
        \GPT@Zero
      \else
        -\Grot@sin
      \fi
    \fi
    \GPT@space\Grot@cos
  }%
  \ifx\GPT@temp\GPT@MatrixIdentity
    \def\Grot@end{}%
  \else
    \pdfsave
    \pdfsetmatrix{\GPT@temp}%
    \wd\z@\z@
  \fi
}
\def\Grot@end{\pdfrestore}

\else
\fi
\fi


%end package
\catcode`@=12

% a plain tex document

aaa \rotatebox{45}{use La\TeX} bbb

\bye

答案2

我认为,大多数基本的旋转实现都可以在 OPmac 宏中找到。它基于\pdfsetmatrix、,\pdfsave但其他引擎可以非常简单地定义这些命令,例如,参见文件\pdfrestorepdftexopmac-xetex.tex

主要问题是,ta 我们必须使用\pdfsetmatrix{cos\alpha sin\alpha -sin\alpha cos\alpha},这意味着我们必须实现一个简单的 cos、sin 计算,而这在经典 TeX 中是不存在的。以下 OPmac 宏中的实现使用值表对这些函数的值进行插值。

\newdimen\tmpdim \newcount\tmpnum

\def\pdfscale#1#2{\pdfsetmatrix{#1 0 0 #2}}

\def\pdfrotate#1{\tmpdim=#1pt
   \ifdim\tmpdim=0pt
   \else \ifdim\tmpdim=90pt \pdfsetmatrix{0 1 -1 0}%
         \else \edef\tmp{#1}\expandafter\pdfrotateA\tmp..\relax
   \fi   \fi
}
\def\pdfrotateA #1.#2.#3\relax{%
   \def\tmp##1.##2\relax {##1}%
   \tmpnum=\expandafter \tmp \the\tmpdim \relax % round
   \ifdim\tmpdim>0pt \def\tmpa{}\else\def\tmpa{-}\fi % save -
   \loop \ifnum\tmpnum<0 \advance\tmpnum by360 \repeat
   \loop \ifnum\tmpnum>360 \advance\tmpnum by-360 \repeat
   \loop \ifnum\tmpnum>90 \pdfrotate{90}\advance\tmpnum by-90 \repeat
   \ifnum\tmpnum=90 \pdfrotate{90}\else
      \ifnum\tmpnum>44 \pdfsetmatrix{.7071 .7071 -.7071 .7071}%
                       \advance\tmpnum by-45 \fi
      \ifnum\tmpnum>22 \pdfsetmatrix{.9272 .3746 -.3746 .9272}%
                       \advance\tmpnum by-22 \fi
      \ifnum\tmpnum>0
         \pdfsetmatrix{\smallcos \smallsin -\smallsin \smallcos}%
   \fi\fi
   \if$#2$\else % fraction part
      \tmpdim=.01745329pt % \pi/180
      \tmpdim=.#2\tmpdim  %
      \edef\tmp{\expandafter\ignorept\the\tmpdim\space}%
      \ifx\tmpa\empty \pdfsetmatrix{1 \tmp -\tmp 1}%
      \else           \pdfsetmatrix{1 -\tmp \tmp 1}%
   \fi\fi
}
\def\smallcos{.\ifcase\tmpnum \or9998\or9994\or9986\or9976\or9962\or9945\or
  9925\or9903\or9877\or9848\or9816\or9781\or9744\or9703\or9659\or9613\or
  9563\or9511\or9455\or9397\or9336\or9272\fi\space}
\def\smallsin{.\ifcase\tmpnum 0\or0175\or0359\or0523\or0698\or0872\or1045\or
  1219\or1391\or1564\or1736\or1908\or2079\or2250\or2419\or2588\or2756\or
  2924\or309\or3256\or342\or3584\or3746\fi\space}

Test: \pdfsave\pdfrotate{35}\rlap{don't use La\TeX}\pdfrestore

\bye

如果您发现更直接的东西,请展示出来。

相关内容