Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

simoncozens / sile / 724

8 Dec 2015 - 7:09 coverage: 90.117%. Remained the same
724

push

travis-ci

97f68b9e757f8150fc0b4c9aed1ee6db?size=18&default=identiconsimoncozens
The warnings moved to stderr.

7723 of 8570 relevant lines covered (90.12%)

7176.22 hits per line

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

76.36
/core/break.lua
1

2
SILE.settings.declare({ name="linebreak.parShape", type = "string or nil", default = nil}) -- unimplemented
252×
3
SILE.settings.declare({ name="linebreak.tolerance", type = "integer or nil", default = 500})
252×
4
SILE.settings.declare({ name="linebreak.pretolerance", type = "integer or nil", default = 100})
252×
5
SILE.settings.declare({ name="linebreak.hangIndent", type = "nil", default = nil}) -- unimplemented
252×
6
SILE.settings.declare({ name="linebreak.adjdemerits", type = "integer", default = 10000,
504×
7
  help = "Additional demerits which are accumulated in the course of paragraph building when two consecutive lines are visually incompatible. In these cases, one line is built with much space for justification, and the other one with little space."})
252×
8
SILE.settings.declare({ name="linebreak.looseness", type = "integer", default = 0})
252×
9
SILE.settings.declare({ name="linebreak.prevGraf", type = "integer", default = 0})
252×
10
SILE.settings.declare({ name="linebreak.emergencyStretch", type = "Length or nil", default = SILE.length.new()})
252×
11
SILE.settings.declare({ name="linebreak.doLastLineFit", type = "boolean", default = false}) -- unimplemented
252×
12
SILE.settings.declare({ name="linebreak.linePenalty", type = "integer", default = 10})
252×
13
SILE.settings.declare({ name="linebreak.hyphenPenalty", type = "integer", default = 50})
252×
14
SILE.settings.declare({ name="linebreak.doubleHyphenDemerits", type = "integer", default = 10000})
252×
15
SILE.settings.declare({ name="linebreak.finalHyphenDemerits", type = "integer", default = 5000})
252×
16

17
-- doubleHyphenDemerits
18
-- hyphenPenalty
19

20
local classes = {"tight"; "decent"; "loose"; "veryLoose"}
252×
21
local passSerial = 0
252×
22
local awful_bad = 1073741823
252×
23
local inf_bad = 10000
252×
24
local ejectPenalty = -inf_bad
252×
25
lineBreak = {}
252×
26

27
--[[
28
  Basic control flow:
29
  doBreak:
30
    init
31
    for each node:
32
      checkForLegalBreak
33
        tryBreak
34
          createNewActiveNodes
35
          considerDemerits
36
            deactivateR (or) recordFeasible
37
    tryFinalBreak
38
    postLineBreak
39
]]
40

41
local param = function(x) return SILE.settings.get("linebreak."..x) end
73,206×
42

43
-- Routines here will be called thousands of times; we micro-optimize
44
-- to avoid debugging and concat calls.
45
local debugging = false
252×
46

47
function lineBreak:init()
504×
48
  self:trimGlue() -- 842
1,338×
49
  -- 849
50
  self.activeWidth = SILE.length.new()
1,338×
51
  self.curActiveWidth = SILE.length.new()
1,338×
52
  self.breakWidth = SILE.length.new()
1,338×
53
  -- 853
54
  local rskip = SILE.settings.get("document.rskip")
1,338×
55
  if type(rskip) == "table" then rskip = rskip.width else rskip = 0 end
1,338×
56
  local lskip = SILE.settings.get("document.lskip")
1,338×
57
  if type(lskip) == "table" then lskip = lskip.width else lskip = 0 end
1,338×
58
  self.background = SILE.length.new() + rskip + lskip
1,338×
59
  -- 860
60
  self.bestInClass = {}
1,338×
61
  for i = 1,#classes do
6,690×
62
    self.bestInClass[classes[i]] = {
5,352×
63
      minimalDemerits = awful_bad
5,352×
64
    }
5,352×
65
  end
66
  self.minimumDemerits = awful_bad
1,338×
67
  self:setupLineLengths(params)
1,338×
68
end
69

70
function lineBreak:trimGlue() -- 842
504×
71
  local nodes = self.nodes
1,338×
72
  if nodes[#nodes]:isGlue() then nodes[#nodes] = nil end
1,338×
73
  nodes[#nodes+1] = SILE.nodefactory.newPenalty({penalty = inf_bad})
1,338×
74
end
75

76
function lineBreak:setupLineLengths(params) -- 874
504×
77
  self.parShape = param("parShape")
1,338×
78
  if not self.parShape then
1,338×
79
    if not param("hangIndent") then
1,338×
80
      self.lastSpecialLine = 0
1,338×
81
      self.secondWidth = self.hsize or SU.error("No hsize")
1,338×
82
    else
83
      SU.error("Hanging indents not supported yet. Implement node 875 from TeX!", 1)
!
84
    end
85
  else
86
    self.lastSpecialLine = #param("parShape")
!
87
    self.secondWidth = SU.error("Oops")
!
88
  end
89
  if param("looseness") == 0 then self.easy_line = self.lastSpecialLine else self.easy_line = awful_bad end
1,338×
90
  -- self.easy_line = awful_bad
91

92
end
93

94
function lineBreak:tryBreak() -- 855
504×
95
  local pi,breakType
96
 
97
  local n = self.nodes[self.cur_p]
50,442×
98
  if not n then pi = ejectPenalty; breakType = "hyphenated"
50,442×
99
  elseif n:isDiscretionary() then breakType = "hyphenated"; pi = param("hyphenPenalty")
50,442×
100
  else breakType = "unhyphenated"; pi = n.penalty or 0 end
38,406×
101

102
  if debugging then SU.debug("break", "Trying a "..breakType.." break p="..pi) end
50,442×
103
  self.no_break_yet = true -- We have to store all this state crap in the object, or it's global variables all the way
50,442×
104
  self.prev_prev_r = nil
50,442×
105
  self.prev_r = self.activeListHead
50,442×
106
  self.old_l = 0
50,442×
107
  self.r = nil
50,442×
108
  self.curActiveWidth = std.tree.clone(self.activeWidth)
50,442×
109

110
  while true do
111
    while true do -- allows "break" to function as "continue"
112
      self.r = self.prev_r.next
305,760×
113
      if debugging then SU.debug("break","We have moved the link  forward, ln is now "..(self.r.type == "delta" and "XX" or self.r.lineNumber)) end
305,760×
114

115
      if self.r.type == "delta" then -- 858
305,760×
116
        if debugging then SU.debug("break", " Adding delta node width of ".. tostring(self.r.width)) end
93,060×
117

118
        self.curActiveWidth = self.curActiveWidth + self.r.width
93,060×
119
        self.prev_prev_r = self.prev_r
93,060×
120
        self.prev_r = self.r
93,060×
121
        break
only LUA=lua5.1 and LUA=lua5.1 GRAPHITE=false - 31,020×
122
      end
123

124
      -- 861
125
      if self.r.lineNumber > self.old_l then
212,700×
126
        if debugging then SU.debug("break","Mimimum demerits = " .. self.minimumDemerits) end
100,884×
127
        if self.minimumDemerits < awful_bad and (self.old_l ~= self.easy_line or self.r == self.activeListHead) then
100,884×
128
          self:createNewActiveNodes(breakType)
12,006×
129
        end
130
        if self.r == self.activeListHead then
100,884×
131
          if debugging then SU.debug("break", "<- tryBreak") end
50,442×
132
          return
50,442×
133
        end
134
        -- 876
135
        if self.r.lineNumber > self.easy_line then
50,442×
136
          self.lineWidth = self.secondWidth
50,442×
137
          self.old_l = awful_bad -1
50,442×
138
        else
139
          self.old_l = self.r.lineNumber
!
140
          if self.r.lineNumber > self.lastSpecialLine then self.lineWidth = self.secondWidth
!
141
          elseif not self.parShape then self.lineWidth = self.firstWidth else self.lineWidth = self.parShape[self.r.lineNumber]
!
142
          end
143
        end
144
        if debugging then SU.debug("break", "line width = "..self.lineWidth) end
50,442×
145
      end
146
      if debugging then
162,258×
147
        SU.debug("break", " ---> (2) cuaw is ".. self.curActiveWidth.length)
!
148
        SU.debug("break", " ---> aw is ".. self.activeWidth.length)
!
149
      end
150
      self:considerDemerits(pi, breakType)
162,258×
151
      if debugging then
162,258×
152
        SU.debug("break", " <--- cuaw is ".. self.curActiveWidth.length)
!
153
        SU.debug("break", " <--- aw is ".. self.activeWidth.length)
!
154
      end
155
    end
156
  end
157
 
158
end
159

160
local function fitclass(self, s) -- s =shortfall
161
  local badness, class
162
  local stretch = self.curActiveWidth.stretch
162,258×
163
  local shrink = self.curActiveWidth.shrink
162,258×
164
  if s > 0 then
162,258×
165
    if s > 110 and stretch < 25 then
150,690×
166
      badness = inf_bad
71,940×
167
    else
168
      badness = lineBreak:badness(s, stretch)
78,750×
169
    end
170
    if     badness > 99 then class = "veryLoose"
150,690×
171
    elseif badness > 12 then class = "loose"
44,742×
172
    else                     class = "decent"
43,050×
173
    end
174
  else
175
    s = -s
11,568×
176
    if s > shrink then
11,568×
177
      badness = inf_bad + 1
8,784×
178
    else
179
      badness = lineBreak:badness(s, shrink)
2,784×
180
    end
181
    if badness > 12 then class = "tight"
11,568×
182
    else                 class = "decent"
1,422×
183
    end
184
  end
185
  return badness, class
162,258×
186
end
187

188
function lineBreak:tryAlternatives(from, to)
504×
189
  local altSizes = {}
!
190
  local alternates = {}
!
191
  for i = from, to do
!
192
    if self.nodes[i] and self.nodes[i]:isAlternative() then
!
193
      alternates[#alternates+1] = self.nodes[i]
!
194
      altSizes[#altSizes+1] = #(self.nodes[i].options)
!
195
    end
196
  end
197
  if #alternates == 0 then return end
!
198
  local localMinimum = awful_bad
!
199
  local selectedShortfall = 0
!
200
  local shortfall = self.lineWidth - self.curActiveWidth.length
!
201
  if debugging then SU.debug("break", "Shortfall was ", shortfall) end
!
202
  for combination in SU.allCombinations(altSizes) do
!
203
    local addWidth = 0
!
204
    for i = 1,#(alternates) do local alt = alternates[i]
!
205
      addWidth = (addWidth + alt.options[combination[i]].width - alt:minWidth()).length
!
206
      if debugging then SU.debug("break", alt.options[combination[i]], " width", addWidth) end
!
207
    end
208
    local ss = shortfall - addWidth
!
209
    local b = ss > 0 and lineBreak:badness(ss, self.curActiveWidth.stretch) or lineBreak:badness(math.abs(ss), self.curActiveWidth.shrink)
!
210
    if debugging then SU.debug("break", "  badness of "..ss.." ("..self.curActiveWidth.stretch..") is ".. b) end
!
211
    if b < localMinimum then
!
212
      self.r.alternates = alternates
!
213
      self.r.altSelections = combination
!
214
      selectedShortfall = addWidth
!
215
      localMinimum = b
!
216
    end
217
  end
218
  if debugging then SU.debug("break", "Choosing ", alternates[1].options[self.r.altSelections[1]]) end
!
219
  -- self.curActiveWidth = self.curActiveWidth + selectedShortfall
220
  shortfall = self.lineWidth - self.curActiveWidth.length
!
221
  if debugging then SU.debug("break", "Is now ", shortfall) end
!
222
end
223

224
function lineBreak:considerDemerits(pi, breakType) -- 877
504×
225
  self.artificialDemerits = false
162,258×
226
  local nodeStaysActive = false
162,258×
227
  -- self:dumpActiveRing()
228
  local shortfall = self.lineWidth - self.curActiveWidth.length
162,258×
229
  if self.seenAlternatives then
162,258×
230
    self:tryAlternatives(self.r.prevBreak and self.r.prevBreak.curBreak or 1, self.r.curBreak and self.r.curBreak or 1, shortfall)
!
231
  end
232
  shortfall = self.lineWidth - self.curActiveWidth.length
162,258×
233
  self.b, self.fitClass = fitclass(self, shortfall)
162,258×
234
  if debugging then SU.debug("break", self.b .. " " .. self.fitClass) end
162,258×
235
  if (self.b > inf_bad or pi == ejectPenalty) then
162,258×
236
    if self.finalpass and self.minimumDemerits == awful_bad and self.r.next == self.activeListHead and self.prev_r == self.activeListHead then
12,336×
237
      self.artificialDemerits = true
264×
238
    else
239
      if self.b > self.threshold then
12,072×
240
        self:deactivateR()
8,616×
241
        return
8,616×
242
      end
243
    end
244
  else
245
    self.prev_r = self.r
149,922×
246
    if self.b > self.threshold then return end
149,922×
247
    nodeStaysActive = true
46,260×
248
  end
249

250
  self.lastRatio = shortfall > 0 and shortfall/(self.curActiveWidth.stretch or awful_bad) or shortfall/(self.curActiveWidth.shrink or awful_bad)
49,980×
251
  self:recordFeasible(pi, breakType)
49,980×
252
  if not nodeStaysActive then self:deactivateR() end
49,980×
253
end
254

255
function lineBreak:badness(t,s)
504×
256
  local bad = 100 * (t/s)^3
81,534×
257
  bad = math.floor(bad) -- TeX uses integer math for this stuff, so for compatibility...
81,534×
258

259
  if bad > inf_bad then return inf_bad else return bad end
81,534×
260
end
261

262
function lineBreak:deactivateR() -- 886
504×
263
  if debugging then SU.debug("break"," Deactivating r ("..self.r.type..")") end
12,336×
264
  self.prev_r.next = self.r.next
12,336×
265
  if self.prev_r == self.activeListHead then
12,336×
266
    -- 887
267
    self.r = self.activeListHead.next
12,336×
268
    if self.r.type == "delta" then
12,336×
269
      self.activeWidth = self.activeWidth + self.r.width
10,038×
270
      self.curActiveWidth = std.tree.clone(self.activeWidth)
10,038×
271
      self.activeListHead.next = self.r.next
10,038×
272
    end
273
    if debugging then SU.debug("break","  Deactivate, branch 1"); end
12,336×
274
  else
275
    if self.prev_r.type == "delta" then
!
276
      self.r = self.prev_r.next
!
277
      if self.r == self.activeListHead then
!
278
        self.curActiveWidth = self.curActiveWidth - self.r.width
!
279
        self.prev_prev_r.next = self.activeListHead
!
280
        self.prev_r = self.prev_prev_r
!
281
      elseif self.r.type == "delta" then
!
282
        self.curActiveWidth = self.curActiveWidth + self.r.width
!
283
        self.prev_r.width = self.prev_r.width + self.r.width
!
284
        self.prev_r.next = self.r.next
!
285
      end
286
    end
287
    if debugging then SU.debug("break","  Deactivate, branch 2"); end
!
288
  end
289
end
290

291
function lineBreak:computeDemerits(pi, breakType)
504×
292
  if self.artificialDemerits then return 0 end
49,980×
293
  local d = param("linePenalty") + self.b
49,716×
294
  if math.abs(d) >= 10000 then d = 100000000 else d = d * d end
49,716×
295
  if pi > 0 then d = d + pi * pi
49,716×
296
  elseif pi == 0 then -- do nothing
46,158×
297
  elseif pi > ejectPenalty then d = d - pi * pi end
3,456×
298
  if breakType == "hyphenated" and self.r.type == "hyphenated" then
49,716×
299
    if self.nodes[self.cur_p] then
1,236×
300
      d = d + param("doubleHyphenDemerits")
1,236×
301
    else d = d + param("finalHyphenDemerits") end
!
302
  end
303
  -- XXX adjDemerits not added here
304
  return d
49,716×
305
end
306

307
function lineBreak:recordFeasible(pi, breakType) -- 881
504×
308
  local d = lineBreak:computeDemerits(pi, breakType)
49,980×
309
  if debugging then
49,980×
310
    if self.nodes[self.cur_p] then
!
311
      SU.debug("break", "@" .. self.nodes[self.cur_p] .. " via @@" .. (self.r.serial or "0")  .. " b=" .. self.b .. " d=".. d) -- 882
!
312
    else
313
      SU.debug("break", "@ \\par via @@");
!
314
    end
315
    SU.debug("break"," fit class = "..self.fitClass);
!
316
  end
317
  d = d + self.r.totalDemerits
49,980×
318
  if d <= self.bestInClass[self.fitClass].minimalDemerits then
49,980×
319
    self.bestInClass[self.fitClass] = {
30,354×
320
      minimalDemerits = d,
30,354×
321
      node = self.r.serial and self.r,
30,354×
322
      line = self.r.lineNumber
30,354×
323
    }
30,354×
324
    -- XXX do last line fit
325
    if d < self.minimumDemerits then self.minimumDemerits = d end
30,354×
326
  end
327
end
328

329

330
function lineBreak:createNewActiveNodes(breakType) -- 862
504×
331
  if self.no_break_yet then
12,006×
332
    -- 863
333
    self.no_break_yet = false
12,006×
334
    self.breakWidth = std.tree.clone(self.background)
12,006×
335
    local s = self.cur_p
12,006×
336
    local n = self.nodes[s]
12,006×
337
    if n and n:isDiscretionary() then -- 866
12,006×
338
      self.breakWidth = self.breakWidth + n:prebreakWidth() + n:postbreakWidth() - n:replacementWidth()
1,974×
339
    end
340
    while self.nodes[s] and not self.nodes[s]:isBox() do
26,286×
341
      if self.sideways and self.nodes[s].height then
14,280×
342
        self.breakWidth = self.breakWidth - (self.nodes[s].height + self.nodes[s].depth)
!
343
      elseif self.nodes[s].width then -- We use the fact that (a) nodes know if they have width and (b) width subtraction is polymorphic
14,280×
344
        self.breakWidth = self.breakWidth - self.nodes[s]:lineContribution()
14,280×
345
      end
346
      s = s + 1
14,280×
347
    end
348
    if debugging then SU.debug("break", "Value of breakWidth = " .. tostring(self.breakWidth)) end
12,006×
349
  end
350
  -- 869 (Add a new delta node)
351
  if self.prev_r.type == "delta" then self.prev_r.width = self.prev_r.width - self.curActiveWidth + self.breakWidth
12,006×
352
  elseif self.prev_r == self.activeListHead then self.activeWidth = std.tree.clone(self.breakWidth)
12,006×
353
  else
354
    local newDelta = { next = self.r, type = "delta", width = self.breakWidth - self.curActiveWidth}
10,446×
355
    if debugging then SU.debug("break", "Added new delta node = " .. tostring(newDelta.width)) end
10,446×
356
    self.prev_r.next = newDelta
10,446×
357
    self.prev_prev_r = self.prev_r
10,446×
358
    self.prev_r = newDelta
10,446×
359
  end
360
  if (math.abs(self.adjdemerits) >= awful_bad - self.minimumDemerits) then
12,006×
361
    self.minimumDemerits = awful_bad - 1
!
362
  else self.minimumDemerits = self.minimumDemerits + math.abs(self.adjdemerits)
12,006×
363
  end
364

365
  for i = 1,#classes do
60,030×
366
    local class = classes[i]
48,024×
367
    local best = self.bestInClass[class]
48,024×
368
    local value = best.minimalDemerits
48,024×
369
    if debugging then SU.debug("break","Class is "..class.." Best value here is " .. value) end
48,024×
370

371
    if value <= self.minimumDemerits then
48,024×
372
      -- 871: this is what creates new active notes
373
      passSerial = passSerial + 1
12,444×
374

375
      local newActive = { next = self.r,
12,444×
376
        curBreak = self.cur_p,
12,444×
377
        prevBreak = best.node,
12,444×
378
        serial = passSerial,
12,444×
379
        ratio = self.lastRatio,
12,444×
380
        lineNumber = best.line + 1,
12,444×
381
        type = breakType,
12,444×
382
        fitness = class,
12,444×
383
        totalDemerits = value
12,444×
384
      }
385
      -- DoLastLineFit? 1636 XXX
386
      self.prev_r.next = newActive
12,444×
387
      self.prev_r = newActive
12,444×
388
      self:dumpBreakNode(newActive)
12,444×
389

390
    end
391
    self.bestInClass[class] = { minimalDemerits = awful_bad }
48,024×
392
  end
393

394
  self.minimumDemerits = awful_bad
12,006×
395
  -- 870
396
  if self.r ~= self.activeListHead then
12,006×
397
    local newDelta = { next = self.r, type = "delta", width = self.curActiveWidth - self.breakWidth }
!
398
    self.prev_r.next = newDelta
!
399
    self.prev_prev_r = self.prev_r
!
400
    self.prev_r = newDelta
!
401
  end
402
end
403

404
function lineBreak:dumpBreakNode(b)
504×
405
  if not SU.debugging("break") then return end
12,444×
406
  print(lineBreak:describeBreakNode(b))
!
407
end
408

409
function lineBreak:describeBreakNode(b)
504×
410
  --print("@@" .. b.serial .. ": line " .. (b.lineNumber -1) .. "." .. b.fitness .. " " .. b.type .. " t=".. b.totalDemerits .. " -> @@ " .. (b.prevBreak and b.prevBreak.serial or "0") )
411
  if b.sentinel then return b.sentinel end
!
412
  if b.type == "delta" then return "delta "..b.width.length.."pt" end
!
413
  local before = self.nodes[b.curBreak-1]
!
414
  local after = self.nodes[b.curBreak+1]
!
415
  local from = b.prevBreak and b.prevBreak.curBreak or 1
!
416
  local to = b.curBreak
!
417
  return "b "..from.."-"..to.." \""..(before and before:toText()).." | "..(after and after:toText()).."\" [".. b.totalDemerits..", "..b.fitness.."]"
!
418
end
419

420
function lineBreak:checkForLegalBreak(n) -- 892
504×
421
  if debugging then SU.debug("break", "considering node "..n); end
99,288×
422
  local previous = self.nodes[self.cur_p - 1]
99,288×
423
  if n:isAlternative() then self.seenAlternatives = true end
99,288×
424
  if self.sideways and n:isBox() then
99,288×
425
    self.activeWidth = self.activeWidth + n.height + n.depth
!
426
  elseif self.sideways and n:isVglue() then
99,288×
427
    if previous and (previous:isBox()) then
!
428
      self:tryBreak()
!
429
    end
430
    self.activeWidth = self.activeWidth + n.height + n.depth
!
431
  elseif n:isAlternative() then
99,288×
432
    self.activeWidth = self.activeWidth + n:minWidth()
!
433
  elseif n:isBox() then
99,288×
434
    self.activeWidth = self.activeWidth + n:lineContribution()
48,816×
435
  elseif n:isGlue() then
50,472×
436
    -- 894 (We removed the auto_breaking parameter)
437
    if previous and previous:isBox() then self:tryBreak() end
35,748×
438
    self.activeWidth = self.activeWidth + n.width
35,748×
439
  elseif n:isDiscretionary() then -- 895
14,724×
440
    self.activeWidth = self.activeWidth + n:prebreakWidth()
12,036×
441
    self:tryBreak()
12,036×
442
    self.activeWidth = self.activeWidth - n:prebreakWidth()
12,036×
443
    self.activeWidth = self.activeWidth + n:replacementWidth()
12,036×
444
  elseif n:isPenalty() then
2,688×
445
    self:tryBreak()
2,682×
446
  end
447
end
448

449
function lineBreak:tryFinalBreak()      -- 899
504×
450
  -- XXX TeX has self:tryBreak() here. But this doesn't seem to work
451
  -- for us. If we call tryBreak(), we end up demoting all break points
452
  -- to veryLoose (possibly because the active width gets reset - why?).
453
  -- This means we end up doing unnecessary passes.
454
  -- However, there doesn't seem to be any downside to not calling it
455
  -- (how scary is that?) so I have removed it for now. With this
456
  -- "fix", we only perform hyphenation and emergency passes when necessary
457
  -- instead of every single time. If things go strange with the break
458
  -- algorithm in the future, this should be the first place to look!
459
  -- self:tryBreak()
460
  if self.activeListHead.next == self.activeListHead then return end
1,338×
461
  self.r = self.activeListHead.next
1,338×
462
  local fewestDemerits = awful_bad
1,338×
463
  repeat
464
    if not(self.r.type == "delta") then
2,154×
465
      if (self.r.totalDemerits < fewestDemerits) then
1,746×
466
        fewestDemerits = self.r.totalDemerits
1,338×
467
        self.bestBet = self.r
1,338×
468
      end
469
    end
470
    self.r = self.r.next
2,154×
471
  until self.r == self.activeListHead
2,154×
472
  if param("looseness") == 0 then return "done" end
1,338×
473
  -- XXX node 901 not implemented
474
  if (self.actualLooseness == param("looseness")) or self.finalpass then return "done" end
!
475
end
476

477
function lineBreak:doBreak (nodes, hsize, sideways)
504×
478
  passSerial = 1
1,338×
479
  debugging = SILE.debugFlags["break"]
1,338×
480
  self.seenAlternatives = false
1,338×
481
  self.nodes = nodes
1,338×
482
  self.hsize = hsize
1,338×
483
  self.sideways = sideways
1,338×
484
  self:init()
1,338×
485
  self.adjdemerits = param("adjdemerits")
1,338×
486
  self.threshold = param("pretolerance")
1,338×
487
  if self.threshold >= 0 then
1,338×
488
    self.pass = "first"
1,338×
489
    self.finalpass = false
1,338×
490
  else
491
    self.threshold = param("tolerance")
!
492
    self.pass = "second"
!
493
    self.finalpass = (param("emergencyStretch") <= 0)
!
494
  end
495
  -- 889
496
  while 1 do
!
497
    if debugging then SU.debug("break", "@" .. self.pass .. "pass") end
1,638×
498
    if self.threshold > inf_bad then self.threshold = inf_bad end
1,638×
499
    if self.pass == "second" then
1,638×
500
      self.nodes = SILE.hyphenate(self.nodes)
240×
501
      SILE.typesetter.state.nodes = self.nodes -- Horrible breaking of separation of concerns here. :-(
240×
502
    end
503
    -- 890
504
    self.activeListHead = { sentinel="START", type = "hyphenated", lineNumber = awful_bad, subtype = 0 } -- 846
1,638×
505
    self.activeListHead.next = { sentinel="END", type = "unhyphenated", fitness = "decent", next = self.activeListHead, lineNumber = param("prevGraf") + 1, totalDemerits = 0}
1,638×
506

507
    -- Not doing 1630
508
    self.activeWidth = std.tree.clone(self.background)
1,638×
509

510
    self.cur_p = 1
1,638×
511
    while self.nodes[self.cur_p] and self.activeListHead.next ~= self.activeListHead do
100,926×
512
      self:checkForLegalBreak(self.nodes[self.cur_p])
99,288×
513
      self.cur_p = self.cur_p + 1
99,288×
514
    end
515
    if self.cur_p > #(self.nodes) then
1,638×
516
      if self:tryFinalBreak() == "done" then break end
1,338×
517
    end
518
    -- (Not doing 891)
519
    if self.pass ~= "second" then
300×
520
      self.pass = "second"
240×
521
      self.threshold = param("tolerance")
240×
522
    else
523
      self.pass = "emergency"
60×
524
      self.background.stretch = self.background.stretch + param("emergencyStretch").length
60×
525
      self.finalpass = true
60×
526
    end
527
  end
528
  -- Not doing 1638
529
  return self:postLineBreak()
1,338×
530
end
531

532
function lineBreak:postLineBreak() -- 903
504×
533
  local p = self.bestBet
1,338×
534
  local breaks = {}
1,338×
535
  local line  = 1
1,338×
536
  repeat
537
    table.insert(breaks, 1,  { position = p.curBreak, width = self.parShape and self.parShape[line] or self.hsize } )
3,726×
538
    if p.alternates then
3,726×
539
      for i = 1,#p.alternates do
!
540
        p.alternates[i].selected = p.altSelections[i]
!
541
        p.alternates[i].width = p.alternates[i].options[p.altSelections[i]].width
!
542
      end
543
    end
544
    p = p.prevBreak
3,726×
545
    line = line + 1
3,726×
546
  until not p
3,726×
547
  return breaks
1,338×
548
end
549

550
function lineBreak:dumpActiveRing()
504×
551
  local p = self.activeListHead
!
552
  io.write("\n")
!
553
  repeat
554
    if p == self.r then io.write("-> ") else io.write("   ") end
!
555
    print(lineBreak:describeBreakNode(p))
!
556
    p = p.next
!
557
  until p == self.activeListHead
!
558
end
559

560
return lineBreak
252×
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2023 Coveralls, Inc