1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
// Copyright (c) 2026 Innovation Trigger B.V.
//
// PDFluent is available under two licences, at your option: the GNU AGPLv3, or
// the PDFluent Commercial Licence. See the LICENSE file in this repository --
// that file travels with the copy you received, which a URL does not.
//! Running headers, footers and page numbers (#571).
//!
//! A page's furniture is the matter the document repeats at the top and the
//! bottom of every page: the chapter it is in, the form's revision, `Page 4 of
//! 12`. It is set in the text frame like everything else, so extraction reads
//! it as body -- and it lands in the middle of the flow, between the last
//! paragraph of one page and the first of the next, where it breaks a sentence
//! in two for anything that chunks, cites or embeds the document.
//!
//! THE EVIDENCE IS REPETITION, AND AT THE FOOT OF A PAGE A FIGURE IS ENOUGH. A
//! line at the top of a page is a title as often as it is a running head, and
//! neither its type nor its position separates them: what separates them is
//! that the document says the running head again on the next page, and the
//! page after that. So this reads the whole document, groups the lines at the
//! two ends of each page by what they say and where they stand, and calls a
//! group furniture once THREE pages carry it. Two is a coincidence a two-page
//! document cannot rule out; three is the smallest run that is a decision by
//! the typesetter.
//!
//! That rule needs a document, and a document is what a corpus of loose pages
//! does not have (#579). So there is a second reading, for ONE page: a band at
//! the FOOT of a page, set off from the body by white, whose line carries a
//! figure is a page number, and a page number is furniture on the evidence of
//! the page it stands on. The repetition rule is left exactly as it is and
//! still decides everything else, which is what makes this an addition rather
//! than a replacement: on a document the two agree, and on a single page the
//! foot is the only end that can be read alone.
//!
//! THE HEAD CANNOT BE READ THAT WAY, and it was measured rather than assumed.
//! Over the 200 annotated pages of run `structured-doclaynet-20260921T000905Z`
//! the same signal at the top of the page marks 26 blocks the ground truth
//! calls body -- section headings standing over their own white -- and takes
//! the heading axis from 0.465 to 0.404. Two further guards on the foot were
//! tried and refused: a band no taller than the page's median block loses four
//! running feet and saves no body block, and a forty-character limit loses
//! twenty-seven and saves one.
//!
//! * THE SAME TEXT, OR THE SAME PATTERN. A page number changes on every page,
//! which is the whole of its job, so the comparison is made on a normalised
//! reading in which every run of digits is one `#` and a lone roman numeral
//! is the same `#`: `Page 4 of 12` and `Page 5 of 12` are one group, and so
//! are `ii` and `iii` on the front matter of a report.
//! * AT THE SAME PLACE. Position is measured as a FRACTION of the page's own
//! text extent rather than in points, so a landscape page in a portrait
//! document is judged against its own measure instead of against the
//! portrait pages' -- the failure this would otherwise have on every report
//! that turns a wide table sideways.
//! * SET OFF FROM THE BODY. A band at the end of a page is furniture only when
//! white stands between it and the rest of the page. Without that rail the
//! first paragraph of a page whose text happens to repeat -- a form's
//! standing clause, a table's caption -- is read as a running head. The
//! white is measured against what stands OVER the band and not against
//! everything else on the page: a page number in the outer corner has a
//! whole margin around it and a caption in the middle of the same strip
//! beside it, and measuring against the caption reads that margin as a
//! NEGATIVE gap. It cost 66 of the 128 running heads this rule missed on the
//! annotated sample of #579, most of them the folio of an annual report set
//! alternately left and right.
//!
//! WHAT IT LEAVES ALONE. The first page of a report carries no running head,
//! and nothing here asks it to: a group is decided over the pages that have
//! one. A footnote is at the bottom of its page and is not furniture, because
//! its text is its own and no other page repeats it. A list item and a table
//! cell are refused before anything else is measured: both are a statement
//! about a region of one page (#569, #570), and a cell that reads `1` in the
//! same corner of three pages is not a page number.
//!
//! What this does NOT do is drop the blocks. They keep their text, their box
//! and their page, and take the kind [`BlockKind::Header`] or
//! [`BlockKind::Footer`]; `crate::reading_order` then keeps them out of the
//! flow by putting them after the body. A caller reading the JSON still has
//! them, which is the point of marking rather than deleting.
use BTreeMap;
use Ordering;
use crate;
/// How many pages have to carry the same line in the same place before it is
/// furniture.
///
/// Three. Two lines that agree are a pair, and a pair happens: two pages of a
/// contract that both open `Schedule 2`, two slides with the same footer under
/// a title that is not repeated. Three is the shortest run in which the
/// typesetter rather than the text is speaking, and it is what the ticket asks
/// for.
const MIN_PAGES: usize = 3;
/// How far the next line may stand from the band and still belong to it, in
/// lines of its own type (#584).
///
/// A running head set over two lines -- the company on one, what the
/// statements are on the next -- is set at its own leading, and a band of one
/// line left the second half in the body: on `NASDAQ_SHEN_2003.pdf` the
/// document repeats such a head on twelve pages and we called both halves a
/// heading on every one of them.
const BAND_LINE_REACH: f64 = 1.25;
/// How far short of the page's own measure a line must stop to be taken into
/// the band beneath the outermost one (#584).
///
/// This is what tells the second line of a running head from the first line of
/// the body: a running head does not run to the measure and a body line does.
/// Without it the band grows into the text, which is the case
/// `a_line_too_near_the_body_is_not_furniture` has held since #571.
const BAND_SHORT_FRACTION: f64 = 0.9;
/// The most lines a band may hold (#584). A head of two lines happens, three
/// is a title block, and beyond that a page is being read as its own margin.
const BAND_MAX_LINES: usize = 4;
/// The longest a running head may be, in characters.
///
/// A running head is a line; a paragraph that happens to sit at the top of
/// three pages is not one. Generous, because a legal footer runs long.
const MAX_CHARS: usize = 160;
/// How much white has to stand between the band and the body, as a fraction of
/// the band's own height.
///
/// Three quarters of a line. A running head is set off by at least a line of
/// white in every manual of style; the body's own paragraphs are set at their
/// leading, which is less than a line of white between the boxes.
const BAND_GAP_FRACTION: f64 = 0.75;
/// How far the band may move between pages, as a fraction of the page's own
/// text height.
const POSITION_TOLERANCE: f64 = 0.06;
/// How far the band may move across the page between pages, as a fraction of
/// the page's own text width.
///
/// Wider than the vertical tolerance on purpose: a running head is often set
/// on alternating sides, and a centred page number moves with the width of the
/// number it holds.
const SIDE_TOLERANCE: f64 = 0.12;
/// How near the body's own left edge a band has to start before it is read as
/// being set in the body's measure, as a fraction of the page's text width.
///
/// A hundredth: the rounding a text matrix arrives through, and nothing else.
/// A footnote is set to the body's edge and a folio is not, and the two are
/// either at the same edge or points apart.
const BODY_MEASURE_TOLERANCE: f64 = 0.01;
/// How many of a group's candidates are tried as the centre of a cluster.
///
/// The search is quadratic in the group, and a group is as long as the
/// document. Sixty-four is far past what a running head needs: it stands in
/// one place on every page that carries it, so the first candidates of the
/// group find it.
const MAX_SEEDS: usize = 64;
/// One line at one end of one page, reduced to what the grouping decides on.
/// Mark every running header and footer in `blocks` (#571).
///
/// Runs over the WHOLE document, before the headings are classified: a running
/// head is often set in a face of its own, and a classifier that sees it as
/// body first would spend a heading level on it.
pub
/// Whether one page on its own says this band is a page number.
///
/// The foot of the page, and a figure in what it says. [`normalise`] has
/// already written every run of digits -- and a line that is nothing but a
/// roman numeral -- as `#`, so the question is whether the key carries one:
/// `Page 4 of 12`, `iv`, `SHENANDOAH TELECOMMUNICATIONS COMPANY 22`, and the
/// bare `41` in the corner of an annual report.
///
/// AND NOT A FOOTNOTE, which is the one thing at the foot of a page that opens
/// with a figure of its own. What separates them is where the line starts: a
/// footnote is set in the body's measure and a folio stands clear of it. The
/// discriminator was chosen against the annotated sample and against the
/// footnote case this suite already had; on the sample it costs two running
/// feet and saves one body block, and without it the footnote goes.
///
/// EVERYTHING ELSE IS LEFT TO THE REPETITION RULE, and the head above all. A
/// heading standing over its own white at the top of a page is what the same
/// signal marks there, and the sample of #579 says how often: 26 body blocks
/// on 200 pages, and the heading axis from 0.465 to 0.404. A rule that takes a
/// section heading out of the body to save a running head has made the
/// document worse.
/// The candidates at one end of one page, or nothing where that end holds no
/// band that is set off from the body.
/// Whether a block may be furniture at all.
/// The box every block on a page stands in.
/// What a line says, with everything that changes from page to page taken out.
///
/// Lower case, one space between words, every run of digits one `#`, and a
/// line that is nothing but a roman numeral the same `#` -- which is what
/// makes `ii`, `iii` and `iv` at the foot of three pages one group. The roman
/// rule is deliberately the WHOLE line and not a token inside it: `Chapter V`
/// is the name of a chapter and stays what it says.
/// Whether the whole line is a roman numeral as a typesetter writes one.
///
/// THE SYNTAX AND NOT THE ALPHABET. `Civil`, `Mild` and `Livid` are spelt out
/// of nothing but the seven letters, and a membership test called each of them
/// a page number -- so three pages that open with three such words at the same
/// place lost all three out of the body (codex, round 2). This reads the
/// numeral instead: thousands, then hundreds, tens and units, each of them the
/// subtractive pair, or the five, or up to three of the one, and the line has
/// to end where the numeral does.
/// One power of ten of a roman numeral: `one`, the `five` above it and the
/// `ten` above that. Returns where the numeral has got to.
/// The groups of candidates that say the same thing in the same place on at
/// least [`MIN_PAGES`] pages.
///
/// Grouped by what they say first, and then clustered by position inside that
/// group -- EVERY cluster that reaches the count, not the biggest one. A book
/// sets its running head at the OUTER margin, so one line of text stands on
/// the left of every verso and the right of every recto: two clusters of one
/// text, and keeping the larger would leave half the pages' heads in the body
/// (codex, round 1). The clusters are taken one at a time, biggest first, and
/// each one's members are out of the running for the next -- so a candidate is
/// in one cluster and a document that repeats one line at the top of every
/// page AND again in a box halfway down still gets two answers rather than one
/// smeared over both places.
/// The largest cluster of `members` that sit within tolerance of one of them,
/// with the number of PAGES it covers -- which is what the count is about, a
/// head and a page number on one page being one page and not two.
///
/// Only the first [`MAX_SEEDS`] members are tried as the centre. The work is
/// quadratic in the size of the group, and the group is as long as the
/// document: a thousand pages of one running head is a million comparisons,
/// which is nothing, and a hundred thousand is not. A running head stands in
/// the same place on every page that carries it, so a cluster that the first
/// few dozen candidates cannot find is not a running head.