Skip to content

Instantly share code, notes, and snippets.

@MatsPalmgren
Last active July 26, 2020 04:23
Show Gist options
  • Select an option

  • Save MatsPalmgren/8eb65464f08850597877ab155e856a0c to your computer and use it in GitHub Desktop.

Select an option

Save MatsPalmgren/8eb65464f08850597877ab155e856a0c to your computer and use it in GitHub Desktop.
General fallback mechanism for fragmentation bugs

Consider the following testcase:

<!DOCTYPE HTML>
<style>
body { font-size: 32pt; margin:0; }
</style>

<div style="color:blue">
<div style="position:absolute; top:calc(100% - 20px); border:1px solid">Hello</div>
  <div style="break-after:always">1</div>
  <div style="">2</div>
</div>

In Print Preview you would get something like:

image

because of bug 267029.

I have an idea of how to fix bugs like this where we don't fragment a frame for some reason and it instead overflows the page content area and we clip it with "dataloss". This can be fixed in a general way by building a DisplayList for the frames on the first page with a clip area that corresponds to the second page (i.e. that starts exactly at the end edge of the first page and has the size of the second page) and include that in the DisplayList for the second page. Then you get the desired result:

image

I hacked up a proof-of-concept for the above using the same technique as we use here: https://searchfox.org/mozilla-central/rev/446160560bf32ebf4cb7c4e25d7386ee22667255/layout/generic/nsPageFrame.cpp#515-543

My DisplayList-fu is weak though, so I'm hoping that someone on the Web Painting team can investigate this idea further...

@MatsPalmgren
Copy link
Author

MatsPalmgren commented May 12, 2020

BTW, this would also allow us to render scrollbars in print mode, compare for example:

<div style="height:70cm; overflow:scroll"></div>

when printed in Firefox and Chrome. We currently render such boxes as special non-scrollable blocks so that we can fragment them and avoid dataloss of their contents. (See NS_BLOCK_CLIP_PAGINATED_OVERFLOW and its uses.) But that also means we don't render scrollbars for most elements in print mode.

@MatsPalmgren
Copy link
Author

MatsPalmgren commented Jul 24, 2020

A variation on the Layout side would be to create continuations for all frames, even for "atomic" ones, if they overflow. The continuation would never have any children... instead we modify BuildDisplayList* so that they generate a clipped DL from its first-in-flow (or at least its first-in-flow's children) in a similar way as I suggested for the PageContentFrame above. This is a bit trickier and more work, but it has the advantage that we can fix the "reserve space" problem easily. This variation would still require support for multiple DL for the same frame on the Paint side though.

For the record, the "reserve space" problem is that the "overflow DL" of page 1 might paint on top of content on page 2, e.g. if we clip a line box then the line after it (in the next-in-flow) will start at the top of the next page - we should reserve some space there for the overflowed part of the clipped line.

(We could do this variation as a version 2 solution though, and do the whole page as suggested above as version 1 since that's faster to implement.)

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