• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 6934957716

20 Nov 2023 07:35PM UTC coverage: 57.468% (-3.2%) from 60.703%
6934957716

push

github

web-flow
Merge c91d9a7d4 into 34e2e5335

60 of 79 new or added lines in 1 file covered. (75.95%)

717 existing lines in 27 files now uncovered.

8957 of 15586 relevant lines covered (57.47%)

5715.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/rotate/init.lua
UNCOV
1
local base = require("packages.base")
×
2

UNCOV
3
local package = pl.class(base)
×
UNCOV
4
package._name = "rotate"
×
5

UNCOV
6
local pdf = require("justenoughlibtexpdf")
×
7

8
local enter = function (self, _)
UNCOV
9
  if not self.rotate then return end
×
UNCOV
10
  local x = -math.rad(self.rotate)
×
11
  -- Keep center point the same
UNCOV
12
  pdf:gsave()
×
UNCOV
13
  local cx = self:left():tonumber()
×
UNCOV
14
  local cy = -self:bottom():tonumber()
×
UNCOV
15
  pdf.setmatrix(1, 0, 0, 1, cx + math.sin(x) * self:height():tonumber(), cy)
×
UNCOV
16
  pdf.setmatrix(math.cos(x), math.sin(x), -math.sin(x), math.cos(x), 0, 0)
×
UNCOV
17
  pdf.setmatrix(1, 0, 0, 1, -cx, -cy)
×
18
end
19

20
local leave =   function(self, _)
UNCOV
21
  if not self.rotate then return end
×
UNCOV
22
  pdf:grestore()
×
23
end
24

25
-- What is the width, depth and height of a rectangle width w and height h rotated by angle theta?
26
-- rect1 = Rectangle[{0, 0}, {w, h}]
27
-- {{xmin, xmax}, {ymin, ymax}} = Refine[RegionBounds[TransformedRegion[rect1,
28
--                                                     RotationTransform[theta, {w/2,h/2}]]],
29
--                                      w > 0 && h > 0 && theta > 0 && theta < 2 Pi ]
30
-- PiecewiseExpand[xmax - xmin]
31
    -- \[Piecewise]  -w Cos[theta]-h Sin[theta]  Sin[theta]<=0&&Cos[theta]<=0
32
    --                w Cos[theta]-h Sin[theta]  Sin[theta]<=0&&Cos[theta]>0
33
    --               -w Cos[theta]+h Sin[theta]  Sin[theta]>0&&Cos[theta]<=0
34
    --                w Cos[theta]+h Sin[theta]  True
35

36
local outputRotatedHbox = function (self, typesetter, line)
UNCOV
37
  local origbox = self.value.orig
×
UNCOV
38
  local x = self.value.theta
×
39
  -- Find origin of untransformed hbox
UNCOV
40
  local save = typesetter.frame.state.cursorX
×
UNCOV
41
  typesetter.frame.state.cursorX = typesetter.frame.state.cursorX - (origbox.width.length-self.width)/2
×
42

UNCOV
43
  local horigin = (typesetter.frame.state.cursorX + origbox.width.length / 2):tonumber()
×
UNCOV
44
  local vorigin = -(typesetter.frame.state.cursorY - (origbox.height - origbox.depth) / 2):tonumber()
×
UNCOV
45
  pdf:gsave()
×
UNCOV
46
  pdf.setmatrix(1, 0, 0, 1, horigin, vorigin)
×
UNCOV
47
  pdf.setmatrix(math.cos(x), math.sin(x), -math.sin(x), math.cos(x), 0, 0)
×
UNCOV
48
  pdf.setmatrix(1, 0, 0, 1, -horigin, -vorigin)
×
UNCOV
49
  origbox:outputYourself(typesetter, line)
×
UNCOV
50
  pdf:grestore()
×
UNCOV
51
  typesetter.frame.state.cursorX = save
×
UNCOV
52
  typesetter.frame:advanceWritingDirection(self.width)
×
53
end
54

UNCOV
55
function package:_init ()
×
UNCOV
56
  base._init(self)
×
UNCOV
57
  if SILE.typesetter and SILE.typesetter.frame then
×
UNCOV
58
    enter(SILE.typesetter.frame, SILE.typesetter)
×
UNCOV
59
    table.insert(SILE.typesetter.frame.leaveHooks, leave)
×
60
  end
UNCOV
61
  table.insert(SILE.framePrototype.enterHooks, enter)
×
UNCOV
62
  table.insert(SILE.framePrototype.leaveHooks, leave)
×
63
end
64

UNCOV
65
function package:registerCommands ()
×
66

UNCOV
67
  self:registerCommand("rotate", function(options, content)
×
UNCOV
68
    local angle = SU.required(options, "angle", "rotate command")
×
UNCOV
69
    local theta = -math.rad(angle)
×
UNCOV
70
    local origbox, hlist = SILE.typesetter:makeHbox(content)
×
UNCOV
71
    local h = origbox.height + origbox.depth
×
UNCOV
72
    local w = origbox.width.length
×
UNCOV
73
    local st = math.sin(theta)
×
UNCOV
74
    local ct = math.cos(theta)
×
75
    local height, width, depth
UNCOV
76
    if st <= 0 and ct <= 0    then
×
77
      width  = -w * ct - h * st
×
78
      height = 0.5*(h-h*ct-w*st)
×
79
      depth  = 0.5*(h+h*ct+w*st)
×
UNCOV
80
    elseif st <=0 and ct > 0  then
×
UNCOV
81
      width  =  w * ct - h * st
×
UNCOV
82
      height = 0.5*(h+h*ct-w*st)
×
UNCOV
83
      depth  = 0.5*(h-h*ct+w*st)
×
84
    elseif st > 0 and ct <= 0 then
×
85
      width  = -w * ct + h * st
×
86
      height = 0.5*(h-h*ct+w*st)
×
87
      depth  = 0.5*(h+h*ct-w*st)
×
88
    else
89
      width  =  w * ct + h * st
×
90
      height = 0.5*(h+h*ct+w*st)
×
91
      depth  = 0.5*(h-h*ct-w*st)
×
92
    end
UNCOV
93
    depth = -depth
×
UNCOV
94
    if depth < SILE.length(0) then depth = SILE.length(0) end
×
UNCOV
95
    SILE.outputter:_ensureInit()
×
UNCOV
96
    SILE.typesetter:pushHbox({
×
97
      value = { orig = origbox, theta = theta},
98
      height = height,
99
      width = width,
100
      depth = depth,
UNCOV
101
      outputYourself = outputRotatedHbox
×
102
    })
UNCOV
103
    SILE.typesetter:pushHlist(hlist)
×
104
  end)
105

106
end
107

108
package.documentation = [[
109
\begin{document}
110
\use[module=packages.rotate]
111
The \autodoc:package{rotate} package allows you to rotate things. You can rotate entire
112
frames, by adding the \autodoc:parameter{rotate=<angle>} declaration to your frame declaration,
113
and you can rotate any content by issuing the command \autodoc:command{\rotate[angle=<angle>]{<content>}},
114
where the angle is measured in degrees.
115

116
Content which is rotated is placed in a box and rotated. The height and width of
117
the rotated box is measured, and then put into the normal horizontal list for
118
typesetting. The effect is that space is reserved around the rotated content.
119
The best way to understand this is by example: here is some text rotated by
120
\rotate[angle=10]{ten}, \rotate[angle=20]{twenty}, and \rotate[angle=40]{forty} degrees.
121

122
The previous line was produced by the following code:
123

124
\begin[type=autodoc:codeblock]{raw}
125
here is some text rotated by
126
\rotate[angle=10]{ten}, \rotate[angle=20]{twenty}, and \rotate[angle=40]{forty} degrees.
127
\end{raw}
128
\end{document}
UNCOV
129
]]
×
130

UNCOV
131
return package
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc