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

sile-typesetter / sile / 14384044172

10 Apr 2025 03:07PM UTC coverage: 40.142% (+10.8%) from 29.317%
14384044172

push

github

alerque
Merge branch 'cairo-is-still-in-egypt'

3 of 51 new or added lines in 3 files covered. (5.88%)

302 existing lines in 20 files now uncovered.

6876 of 17129 relevant lines covered (40.14%)

2601.39 hits per line

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

0.0
/outputters/cairo.lua
1
local base = require("outputters.base")
×
2

3
-- This output package is deprecated and should only be used as an
4
-- example of how to create alternative output backends, in comparison
5
-- with the libtexpdf and debug backends.
6
local lgi = require("lgi")
×
NEW
7
local cairo = lgi.cairo
×
8
-- local pango = lgi.Pango
9
-- local fm = lgi.PangoCairo.FontMap.get_default()
10
-- local pango_context = lgi.Pango.FontMap.create_context(fm)
11
local imagesize = require("imagesize")
×
12

13
local cursorX = 0
×
14
local cursorY = 0
×
15

16
local cr
17
local move -- See https://github.com/pavouk/lgi/issues/48
18
local sgs
19

20
local outputter = pl.class(base)
×
21
outputter._name = "cairo"
×
22
outputter.extension = "pdf"
×
23

NEW
24
local started = false
×
25
local surface
26

27
function outputter:_init ()
×
28
   base._init(self)
×
29
end
30

NEW
31
function outputter:_ensureInit ()
×
32
   local fname = self:getOutputFilename()
×
NEW
33
   if not started then
×
NEW
34
      surface = cairo.PdfSurface.create(
×
35
         fname == "-" and "/dev/stdout" or fname,
NEW
36
         SILE.documentState.paperSize[1],
×
NEW
37
         SILE.documentState.paperSize[2]
×
38
      )
NEW
39
      cr = cairo.Context.create(surface)
×
NEW
40
      move = cr.move_to
×
NEW
41
      sgs = cr.show_glyph_string
×
42
   end
43
end
44

45
function outputter:newPage ()
×
NEW
46
   self:_ensureInit()
×
NEW
47
   cr:show_page()
×
48
end
49

NEW
50
function outputter:abort ()
×
NEW
51
   if started then
×
NEW
52
      surface:finish()
×
53
   end
54
end
55

NEW
56
function outputter:finish()
×
57
   -- allows generation of empty PDFs
NEW
58
   self:_ensureInit()
×
NEW
59
   self:runHooks("prefinish")
×
UNCOV
60
   cr:show_page()
×
NEW
61
   surface:finish()
×
62
end
63

64
function outputter:getCursor ()
×
65
   return cursorX, cursorY
×
66
end
67

68
function outputter:setCursor (x, y, relative)
×
NEW
69
   self:_ensureInit()
×
70
   local offset = relative and { x = cursorX, y = cursorY } or { x = 0, y = 0 }
×
71
   cursorX = offset.x + x
×
72
   cursorY = offset.y - y
×
73
   move(cr, cursorX, cursorY)
×
74
end
75

76
function outputter:setColor (color)
×
NEW
77
   self:_ensureInit()
×
UNCOV
78
   cr:set_source_rgb(color.r, color.g, color.b)
×
79
end
80

81
function outputter:drawHbox (value, _)
×
NEW
82
   self:_ensureInit()
×
83
   if not value then
×
84
      return
×
85
   end
86
   if value.pgs then
×
87
      sgs(cr, value.font, value.pgs)
×
88
   elseif value.text then
×
89
      cr:show_text(value.text)
×
90
   end
91
end
92

93
function outputter:setFont (options)
×
NEW
94
   self:_ensureInit()
×
95
   cr:select_font_face(options.font, options.style:lower() == "italic" and 1 or 0, options.weight > 100 and 0 or 1)
×
96
   cr:set_font_size(options.size)
×
97
end
98

99
function outputter:drawImage (src, x, y, width, height)
×
NEW
100
   self:_ensureInit()
×
NEW
101
   local image = cairo.ImageSurface.create_from_png(src)
×
102
   if not image then
×
103
      SU.error("Could not load image " .. src)
×
104
   end
105
   local src_width = image:get_width()
×
106
   local src_height = image:get_height()
×
107
   if not (src_width > 0) then
×
108
      SU.error("Something went wrong loading image " .. src)
×
109
   end
110
   cr:save()
×
111
   cr:set_source_surface(image, 0, 0)
×
112
   local p = cr:get_source()
×
113
   local matrix, sx, sy
114
   if width or height then
×
115
      if width > 0 then
×
116
         sx = src_width / width
×
117
      end
118
      if height > 0 then
×
119
         sy = src_height / height
×
120
      end
NEW
121
      matrix = cairo.Matrix.create_scale(sx or sy, sy or sx)
×
122
   else
NEW
123
      matrix = cairo.Matrix.create_identity()
×
124
   end
125
   matrix:translate(-x, -y)
×
126
   p:set_matrix(matrix)
×
127
   cr:paint()
×
128
   cr:restore()
×
129
end
130

131
function outputter:getImageSize (src)
×
132
   local box_width, box_height, err = imagesize.imgsize(src)
×
133
   if not box_width then
×
134
      SU.error(err .. " loading image")
×
135
   end
136
   return box_width, box_height
×
137
end
138

139
function outputter:drawRule (x, y, width, depth)
×
NEW
140
   self:_ensureInit()
×
141
   cr:rectangle(x, y, width, depth)
×
142
   cr:fill()
×
143
end
144

145
function outputter:debugFrame (frame)
×
NEW
146
   self:_ensureInit()
×
147
   cr:set_source_rgb(0.8, 0, 0)
×
148
   cr:set_line_width(0.5)
×
149
   cr:rectangle(frame:left(), frame:top(), frame:width(), frame:height())
×
150
   cr:stroke()
×
151
   cr:move_to(frame:left() - 10, frame:top() - 2)
×
152
   cr:show_text(frame.id)
×
153
   cr:set_source_rgb(0, 0, 0)
×
154
end
155

156
function outputter:debugHbox (hbox, scaledWidth)
×
NEW
157
   self:_ensureInit()
×
158
   cr:set_source_rgb(0.9, 0.9, 0.9)
×
159
   cr:set_line_width(0.5)
×
160
   local x, y = self:getCursor()
×
161
   cr:rectangle(x, y - hbox.height, scaledWidth, hbox.height + hbox.depth)
×
162
   if hbox.depth then
×
163
      cr:rectangle(x, y - hbox.height, scaledWidth, hbox.height)
×
164
   end
165
   cr:stroke()
×
166
   cr:set_source_rgb(0, 0, 0)
×
167
   cr:move_to(x, y)
×
168
end
169

170
-- untested
171
function outputter:drawRaw (literal)
×
NEW
172
   self:_ensureInit()
×
UNCOV
173
   cr:show_text(literal)
×
174
end
175

176
return outputter
×
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