我想知道是否可以rotatebox
在普通的旧 TeX 中进行定义(无需导入eplain
、pstricks
或miniltx
其他,或使用pdfrotate
或其他特定于 pdf 的命令)。
“rotate”这个词似乎没有出现在TeXbook中,它仅指vbox
和hbox
。
用例:
- 把练习的答案倒过来写,
- 创建新的数学符号(例如,
\newcommand{\diamondplus}{\rotatebox[origin=c]{45}{$\boxtimes$}}
在纯 TeX 中重复打出 \diamond 和加号?)
如果有一个用于原点中心的宏、另一个用于原点左上角的宏(或使用不同参数的相同宏)等等,那就太好了,但只有一个宏才是有效的答案,可以帮助我理解如何做这样的事情。
答案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
但其他引擎可以非常简单地定义这些命令,例如,参见文件\pdfrestore
。pdftex
opmac-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
如果您发现更直接的东西,请展示出来。