Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #364 Implement footnotes at bottom of page #711

Merged
merged 56 commits into from
Sep 6, 2021

Conversation

danfickle
Copy link
Owner

@danfickle danfickle commented May 29, 2021

Now documented on the wiki under footnotes.

Fixes #364.

Finally ready!

Need tests and fixes for:

Performance:

  • Many footnotes.
  • Footnotes in amongst many lines of text.
  • Footnotes nested at great depth.

Blockers:

  • Don't break Java2D single page output. - Footnotes inside single page output will place them between virtual pages (ie. nonsensical but should not crash).
  • Java2D multi-page output. - Works correctly.
  • Make sure PDF/UA content is not broken. - Footnotes are NOT supported in PDF/UA.

More:

  • Counter reset on page-break - Not supported for this PR.
  • Links in documents with footnotes are not targeting correctly.
  • Footnotes called from positioned content (absolute, relative, fixed) - Absolute and relative works but physical ordering of footnotes may be different to counter order. Banned from fixed area.
  • Footnotes called from page margins - Banned (treated as normal content) and warning logged.

Inside footnotes:

  • Inline content
  • Block content
  • Inline-block content
  • Table content - paginated - unsupported (incorrect output) but does not crash, OOM, etc.
  • Table content not paginated
  • Replaced content (images)
  • Floated content - is contained by each footnote body.
  • Absolute positioned content - will be contained by footnote area (positioned relative to).
  • Fixed positioned content - will escape footnote area and be positioned as normal fixed boxes.
  • Transformed content
  • Footnotes inside footnotes - Warning emitted and treated as normal content.

As footnote element:

  • Inline content - will be displayed as block box regardless.
  • Block content
  • Inline-block content - Not supported, treated as normal content.
  • Table content - paginated - Not supported, treated as normal content.
  • Table content not paginated - Not supported, treated as normal content.
  • Replaced content (images) - Images may not be used as footnote element but can be wrapped in another element such as div. Images can be used as the pseudo footnote-call or footnote-marker via the content property.
  • Floated content - Footnotes can only be float: bottom.
  • Absolute positioned content - will be contained by footnote area (positioned relative to) with footnote mark.
  • Fixed positioned content - will escape footnote area and be positioned as normal fixed boxes, but without footnote mark.
  • Transformed content

In normal flow meeting footnotes:

  • Inline content - Line boxes will avoid footnote area.
  • Block content - Background will intersect footnote area unless page-break-inside: avoid is set. However, footnote area is on top.
  • Inline-block content
  • Table content - paginated - tfoot is placed above footnote area.
  • Table content not paginated
  • Replaced content (images)
  • Floated content - Footnote areas clear floated content.
  • Absolute positioned content - will be positioned as normal so may intersect with footnote areas, z-index works.
  • Fixed positioned content - will be positioned above footnote areas except for footnote overflow pages on which it is positioned as normal (page relative), z-index works.
  • Transformed content

Also

  • Implement max-height support for footnote at-rule.
  • When blocks (rather than line boxes) in normal flow meet footnote area.
  • Footnote calls may be floated for example to line-up on right margin.
  • Similar for replaced elements such as images/SVG.
  • Similar for floats.
  • Similar for table content.
  • Similar for inline-blocks.
  • Implement multi-page footnotes.
  • Tests for when a single line of text with a single line of footnotes is too large for a page.
  • Tests for when a single line contains many large multi-page footnotes.
  • Linking footnote call to footnote body.
  • Images in footnotes.
  • Block boxes in footnotes.

This markup:

<html>
<head>
<style>
@page {
    size: 300px 300px;
}
@page {
    @footnote {
        float: bottom;  /* The only supported position */
        box-sizing: border-box;
        width: 100%;    /* Same width as body */
        border: 1px solid green;
    }
}
body {
  margin: 0px;
  padding: 0px;
  font-size: 16px;
}
::footnote-call {
  counter-increment: footnote 3;
}
div.footnote {
  float: footnote;
  color: orange;
}
.footnote::footnote-call {
  font-family: sans-serif;
  font-size: 14px;
  padding: 2px;
  color: red;
  background-color: black;
  content: "[" counter(footnote) "]";
}
.footnote::footnote-marker {
  color: blue;
  content: counter(footnote) ". ";
}
</style>
</head>
<body>
<p style="margin-top: 0;">
  This text needs some footnotes. <div id="1" class="footnote">This is a footnote.</div>
  Also a footnote for this sentence. <div id="2" class="footnote">Another <strong>footnote</strong>!</div>
</p>

<p style="page-break-before: always;">
  Footnote numbers should be 3, 6 and 9. <div id="3" class="footnote">Just to be silly this is a really long footnote that will need wrapping and such.</div>
</p>

<p style="page-break-before: always; margin-bottom: 0;">
  One two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen
  seventeen eighteen nineteen twenty
  <div id="4" class="footnote">
    This is a very long footnote that will need wrapping. Someone once said
    about footnotes that they are hard to implement!
  </div>
  thirty fourty fifty sixty seventy eighty ninety hundred
  thousand million billion trillion
</p>
</body>
</html>

will result in something like this:
footnotes-openhtmltopdf-poc

We are now using a normal layer rather than painting footnotes separately as that approach did not work when the footnote area went over multiple pages.
This is to deal with multi-page footnote areas, which are now mostly working. We now reserve entire pages when footnotes flow over multiple pages.
Plus:
+ Overhauled BlockBoxing while trying to fix issue. Now better performance and cleaner code.
+ Added benchmarks for BlockBoxing.
…tes.

Also cleanup and documentation around styling code.
It is sitting above the footnotes.
…eracting with footnotes.

Minor fix to prevent anchor element being stripped from footnote calls which are floated.
With more work on correct boxing, so that images may now be used as footnote calls and footnote markers.
Since we wrap generated content correctly now, one can use a border on the generated content box (such as before or after) and get Chrome matching results, rather than a border on each item in the content property list.

With test proof:
+ Test for pseudo elements with different display values.
+ Test for using an image as footnote-call.
+ Test for using an image as footnote-marker.
Tests non-paginated table content works inside footnote body as well as footnotes being called from inside an in-flow table.
Also tests use of before and after pseudo elements in the footnote element.
Footnotes seem to cause problems with the destination of in-flow targets.
…ved.

Problem was that when a pending box was added, then removed from a line, it link target was not being removed.

Also some documentation and cleanup.
By processing them as non-footnote content.
Footnotes should be display: block, position: static, float: none and non-replaced.

Treat invalid elements as normal content. With test proof.
Unsupported but does not cause infinite loop, OOM, etc.
So it picks up orphans and widows. Also proof for footnotes basic test.
Multi-page output is correct.

Single page output produces footnotes in between content which is nonsensical but we are primarily a paged renderer.
@danfickle danfickle marked this pull request as ready for review September 6, 2021 13:02
@danfickle danfickle merged commit b87ef1f into open-dev-v1 Sep 6, 2021
@danfickle danfickle deleted the issue_364_footnotes branch September 6, 2021 13:05
@danfickle
Copy link
Owner Author

Footnote terminology

Footnote terminology

Image Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang). This software or document includes material copied from or derived from CSS Generated Content for Paged Media Module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Footnotes not supported
1 participant