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

sile-typesetter / sile / 9507147410

13 Jun 2024 09:40PM UTC coverage: 50.521% (-18.7%) from 69.177%
9507147410

push

github

web-flow
Merge pull request #2062 from alerque/plug-fluent-leak

Link document.language setting more closely with Fluent locale

15 of 15 new or added lines in 3 files covered. (100.0%)

3244 existing lines in 65 files now uncovered.

8586 of 16995 relevant lines covered (50.52%)

4659.09 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

6
local enter = function (self, _)
7
   -- Probably broken, see:
8
   -- https://github.com/sile-typesetter/sile/issues/427
UNCOV
9
   if not self.rotate then
×
UNCOV
10
      return
×
11
   end
UNCOV
12
   if not SILE.outputter.enterFrameRotate then
×
13
      return SU.warn(
×
14
         "Frame '"
15
            .. self.id("' will not be rotated: backend '")
×
16
            .. SILE.outputter._name
×
17
            .. "' does not support rotation"
×
18
      )
19
   end
UNCOV
20
   local theta = -math.rad(self.rotate)
×
21
   -- Keep center point the same
UNCOV
22
   local x0 = self:left():tonumber()
×
UNCOV
23
   local x1 = x0 + math.sin(theta) * self:height():tonumber()
×
UNCOV
24
   local y0 = self:bottom():tonumber()
×
UNCOV
25
   SILE.outputter:enterFrameRotate(x0, x1, y0, theta) -- Unstable API
×
26
end
27

28
local leave = function (self, _)
UNCOV
29
   if not self.rotate then
×
UNCOV
30
      return
×
31
   end
UNCOV
32
   if not SILE.outputter.enterFrameRotate then
×
33
      return
×
34
   end -- no enter no leave.
UNCOV
35
   SILE.outputter:leaveFrameRotate()
×
36
end
37

38
-- What is the width, depth and height of a rectangle width w and height h rotated by angle theta?
39
-- rect1 = Rectangle[{0, 0}, {w, h}]
40
-- {{xmin, xmax}, {ymin, ymax}} = Refine[RegionBounds[TransformedRegion[rect1,
41
--                                                     RotationTransform[theta, {w/2,h/2}]]],
42
--                                      w > 0 && h > 0 && theta > 0 && theta < 2 Pi ]
43
-- PiecewiseExpand[xmax - xmin]
44
-- \[Piecewise]  -w Cos[theta]-h Sin[theta]  Sin[theta]<=0&&Cos[theta]<=0
45
--                w Cos[theta]-h Sin[theta]  Sin[theta]<=0&&Cos[theta]>0
46
--               -w Cos[theta]+h Sin[theta]  Sin[theta]>0&&Cos[theta]<=0
47
--                w Cos[theta]+h Sin[theta]  True
48

49
local outputRotatedHbox = function (self, typesetter, line)
UNCOV
50
   local origbox = self.value.orig
×
UNCOV
51
   local theta = self.value.theta
×
52

53
   -- Find origin of untransformed hbox
UNCOV
54
   local X = typesetter.frame.state.cursorX
×
UNCOV
55
   local Y = typesetter.frame.state.cursorY
×
UNCOV
56
   typesetter.frame.state.cursorX = X - (origbox.width.length - self.width) / 2
×
UNCOV
57
   local horigin = X + origbox.width.length / 2
×
UNCOV
58
   local vorigin = Y - (origbox.height - origbox.depth) / 2
×
59

UNCOV
60
   SILE.outputter:rotateFn(horigin, vorigin, theta, function ()
×
UNCOV
61
      origbox:outputYourself(typesetter, line)
×
62
   end)
UNCOV
63
   typesetter.frame.state.cursorX = X
×
UNCOV
64
   typesetter.frame.state.cursorY = Y
×
UNCOV
65
   typesetter.frame:advanceWritingDirection(self.width)
×
66
end
67

UNCOV
68
function package:_init ()
×
UNCOV
69
   base._init(self)
×
UNCOV
70
   if SILE.typesetter and SILE.typesetter.frame then
×
UNCOV
71
      enter(SILE.typesetter.frame, SILE.typesetter)
×
UNCOV
72
      table.insert(SILE.typesetter.frame.leaveHooks, leave)
×
73
   end
UNCOV
74
   table.insert(SILE.framePrototype.enterHooks, enter)
×
UNCOV
75
   table.insert(SILE.framePrototype.leaveHooks, leave)
×
76
end
77

UNCOV
78
function package:registerCommands ()
×
UNCOV
79
   self:registerCommand("rotate", function (options, content)
×
UNCOV
80
      if not SILE.outputter.rotateFn then
×
81
         SU.warn("Output will not be rotated: backend '" .. SILE.outputter._name .. "' does not support rotation")
×
82
         return SILE.process(content)
×
83
      end
UNCOV
84
      local angle = SU.required(options, "angle", "rotate command")
×
UNCOV
85
      local theta = -math.rad(angle)
×
UNCOV
86
      local origbox, hlist = SILE.typesetter:makeHbox(content)
×
UNCOV
87
      local h = origbox.height + origbox.depth
×
UNCOV
88
      local w = origbox.width.length
×
UNCOV
89
      local st = math.sin(theta)
×
UNCOV
90
      local ct = math.cos(theta)
×
91
      local height, width, depth
UNCOV
92
      if st <= 0 and ct <= 0 then
×
93
         width = -w * ct - h * st
×
94
         height = 0.5 * (h - h * ct - w * st)
×
95
         depth = 0.5 * (h + h * ct + w * st)
×
UNCOV
96
      elseif st <= 0 and ct > 0 then
×
UNCOV
97
         width = w * ct - h * st
×
UNCOV
98
         height = 0.5 * (h + h * ct - w * st)
×
UNCOV
99
         depth = 0.5 * (h - h * ct + w * st)
×
100
      elseif st > 0 and ct <= 0 then
×
101
         width = -w * ct + h * st
×
102
         height = 0.5 * (h - h * ct + w * st)
×
103
         depth = 0.5 * (h + h * ct - w * st)
×
104
      else
105
         width = w * ct + h * st
×
106
         height = 0.5 * (h + h * ct + w * st)
×
107
         depth = 0.5 * (h - h * ct - w * st)
×
108
      end
UNCOV
109
      depth = -depth
×
UNCOV
110
      if depth < SILE.types.length(0) then
×
111
         depth = SILE.types.length(0)
×
112
      end
UNCOV
113
      SILE.typesetter:pushHbox({
×
114
         value = { orig = origbox, theta = theta },
115
         height = height,
116
         width = width,
117
         depth = depth,
118
         outputYourself = outputRotatedHbox,
119
      })
UNCOV
120
      SILE.typesetter:pushHlist(hlist)
×
121
   end)
122
end
123

124
package.documentation = [[
125
\begin{document}
126
\use[module=packages.rotate]
127
The \autodoc:package{rotate} package allows you to rotate things. You can rotate entire
128
frames, by adding the \autodoc:parameter{rotate=<angle>} declaration to your frame declaration,
129
and you can rotate any content by issuing the command \autodoc:command{\rotate[angle=<angle>]{<content>}},
130
where the angle is measured in degrees.
131

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

138
The previous line was produced by the following code:
139

140
\begin[type=autodoc:codeblock]{raw}
141
here is some text rotated by
142
\rotate[angle=10]{ten}, \rotate[angle=20]{twenty}, and \rotate[angle=40]{forty} degrees.
143
\end{raw}
144
\end{document}
UNCOV
145
]]
×
146

UNCOV
147
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