sile-typesetter / sile

The SILE Typesetter — Simon’s Improved Layout Engine
https://sile-typesetter.org
MIT License
1.63k stars 96 forks source link

Floating frames eat insertions for lunch #420

Open alerque opened 7 years ago

alerque commented 7 years ago

According to by experiments with drop caps (see #394) the current best way to handle them is using the \float command to break up the frames. It's touchy and requires some care to come out right, but it can work.

That is until I introduced the concept of footnotes. An that point my pages started looking like they took a trip through a meat grinder. Here's a sample.

screenshot from 2016-12-20 10-49-13

If I eliminate the drop-cap, the footnote frame behaves just fine:

screenshot from 2016-12-20 10-52-12

This is using a pretty simple version of outputting a drop cap. A flag SILE.scratch.startOfChapterContent is getting set to true at the very end of the chapter header code, then the drop cap is inserted like this:

SILE.scratch.startOfChapterContent = false

local push = SILE.typesetter.pushHorizontal
SILE.typesetter.pushHorizontal = function (self, node)
  if SILE.scratch.startOfChapterContent then
    SILE.call("output-chaptercap")
  end
  return push(self, node)
end

SILE.registerCommand("output-chaptercap", function (options, content)
  SILE.scratch.startOfChapterContent = false
  SILE.call("float", { bottomboundary = "1.3ex", rightboundary = "2spc" }, function ()
    SILE.call("font", { family = "Symbola", size = "3em" } , { "✛" })
  end)
end)

Obviously something isn't wired up right here. Whatever happens to frames when introducing a float doesn't get connected up to the insertion frame that can steal space.

alerque commented 7 years ago

I added an MWE for this is #421.

alerque commented 7 years ago

It looks like the \float command in renaming the frames by appending _ to the current id. This breaks the insertion things which knows which frame to steal from by name. Either the naming needs to happen the other direction (rename the original and keep the new name going forward) or there needs to be some sort of callback that specifies the insertion handling that could be moved to the new frame object.

alerque commented 7 years ago

I made several attempts to fix this. The most promising attempt was to rename the old frame and keep the id with the new frame when creating a break. However this didn't actually work.

Desperate to meet a publishing deadline I came up with a dirty hack instead. That works by adding ALL the broken frame id's to the insertion steal from list and iterating over ones that exist on a given page when processing insertions. I know this isn't the right fix, but I had to get words on the page.