Сила Postscript заключается в его безжалостном стремлении к идеалу «отложенного связывания».Реализация поворотов не является исключением.Он работает с использованием более общего инструмента, аффинной матрицы преобразования.
Вы можете вращать как текст, так и графику (потому что текст IS графика), потому что все указанные пользователем координаты сначала умножаются черезэта матрица для получения координат устройства .
Чтобы выполнить все необходимые трюки (масштабирование, вращение, сдвиг, сдвиг), нам сначала нужно расширить 2d точки до 3d точек на плоскости z= 1 (не спрашивайте меня, почему; прочитайте Математические иллюстрации Билла Кассельмана или Adobe Blue Book для получения дополнительной информации).
[ x [ a b 0
y * c d 0 = [ x' y' 1 ] = [ ax+cy+e bx+dy+f 1 ]
1 ] e f 1 ]
Поскольку в 3-м столбце матрицы всегда [00 1] он исключен из внешнего представления, а матрица описана в постскриптуме как:
[ a b c d e f ]
Поэтому, когда вы используете пару координат, скажем, для оператора moveto
, сначала moveto
преобразует его в координаты устройства, x '= ax + by + e, y' = cx + dy + f, перед добавлением элемента <</move [x' y']>>
к текущему пути.Измените матрицу: измените «значение» пользовательских координат.
Идентификационная матрица такова:
[ 1 0 0 1 0 0 ] % x' = x, y' = y
Для масштабирования замените 1 с коэффициентами масштабирования x и y:
[ Sx 0 0 Sy 0 0 ] % x' = Sx*x, y' = Sy*y
Чтобы перевести, замените e и f смещениями перевода x и y:
[ 1 0 0 1 Tx Ty ] % x' = x+Tx, y' = y+Ty
Чтобы повернуть, замените a, b, c, d на sin и cos, коэффициенты масштабирования и сдвига:
[ cosW sinW -sinW cosW 0 0 ] % x' = x*cosW-y*sinW, y' = x*sinW+y*cosW, where W is angle(degrees) from x-axis
Вы «устанавливаете» эту матрицу с помощью concat
, которая принимает текущую матрицу преобразования (CTM), умножает ее на новую матрицу и использует продукт в качестве нового CTM.Так что translate
, rotate
и scale
- это просто «вспомогательные функции», которые можно реализовать следующим образом:
/translate { [ 1 0 0 1 7 -2 roll ] concat } def
/scale { [ 3 1 roll 0 0 3 -1 roll 0 0 ] concat } def
/rotate { [ exch dup cos exch sin dup neg 2 index 0 0 ] concat } def
Поскольку CTM является частью графического состояния, вы можете использовать графикустек состояний для иерархического управления вашими преобразованиями:
/box { % x y w h %create a path in the shape of a box w*h with lower left corner at x,y
4 2 roll moveto
exch dup 3 1 roll
0 rlineto
0 exch rlineto
neg 0 rlineto
closepath
} def
/Courier 10 selectfont
100 100 100 100 box stroke % draw an oriented box
120 120 moveto (inside) show
gsave
150 150 translate % make the center of the box the new 0,0 point
45 rotate % rotate CCW 45 degrees
0 0 100 100 box stroke % a rotated, shifted box
20 20 moveto (inside) show
grestore
100 200 100 100 box stroke % another box, just north of the first, in the original coordinte system
120 220 moveto (inside) show
Создается следующее изображение:
Вращающиеся поля и текст http://xpost.googlecode.com/files/rotbox.png