crengine icon indicating copy to clipboard operation
crengine copied to clipboard

Inner borders on table cells missing

Open johnbeard opened this issue 5 years ago • 6 comments

The following HTML:

<table style="margin:auto; border:1px solid red; border-collapse:collapse;">
    <tbody>
    <tr style="border:1px solid black;">
        <td style="border:1px solid pink;">Foo</td>
        <td>Bar</td>
        <td>Quux</td>
    </tr>
    <tr style="">
        <td>Foo</td>
        <td>Bar</td>
        <td>Quux</td>
    </tr>
    </tbody>
</table>

In Koreader, the result is something like this: 2020-12-28_134623_253x118_screenshot The expected output is more like this (Firefox): 2020-12-28_134700_127x64_screenshot

Table border.epub.zip

johnbeard avatar Dec 28 '20 13:12 johnbeard

Yes, not easy to get right.

We take some shortcuts around there to keep the (already tedious) work low: https://github.com/koreader/crengine/blob/8254cef9d99238f92ebe0a534f41a66d2e631b7c/crengine/src/lvrend.cpp#L935-L947

For your expected output, we'd have to report some borders from some cells to some other cells - which feels quite more complicated.

poire-z avatar Dec 30 '20 22:12 poire-z

Interesting. For my own future reference, the border-collapsing model is described here: https://www.w3.org/TR/CSS2/tables.html#borders Specifically, the section 17.6.2.1 Border conflict resolution is what would be needed to deal with this (and as you say, it's not trivial)

However, what's the thinking behind this bit?

                     // Now, we should disable some borders for this cell,
                    // at inter-cell boundaries.

Since I suppose "most" tables that set borders on rows/cols/cells individually default to no borders and turn them on selectively, it's seems likely that the current "top and left only" method is falsely turning borders off than falsely turning then on (or overriding with the wrong style)?

For example, a border-bottom on a "header row" is pretty common (it's now I found this behaviour).

In the EPUB above, just commenting lines 948 to 951

https://github.com/koreader/crengine/blob/8254cef9d99238f92ebe0a534f41a66d2e631b7c/crengine/src/lvrend.cpp#L948-L951

produces this: 2021-01-01_231518_167x81_screenshot which, while it won't quite get it right for very complex cases with multiple different borders competing for a single edge, is at least closer to the mark than not having any right or bottom borders at all?

johnbeard avatar Jan 01 '21 23:01 johnbeard

what's the thinking behind this bit?

It's the way crengine does its drawing: it doesn't do: draw borders, and then, between the borders, the cell content. What it does (for every block element): each block/cell carries its own borders, get the own top/left x/y, and it draws them (border + content) at x/y+w/h. For non-collapsed borders, that's just fine.

But, for drawing a 1px collapsed/shared border, if each cell would draw its own, we'll have 2px borders. So, the solution for collapsing was to kill 2 borders (nearly arbitrary, but see my comment) on each cell, so each cells draws fully 2 borders, and get the other 2 from adjacent cells. So, yes, we can falsely turn off some borders - and don't get any if they are not set on the adjacent cells.

Doing differently would need another (tedious) algorithm to decide what to cancel and what not, and possibly shift a bit cells' x/y/h/w so they align correctly whether some provide some borders and others not...

poire-z avatar Jan 01 '21 23:01 poire-z

Oh, I seeeeeee. Makes much more sense now. Certainly sounds painful. I think the worst part might actually be that figuring out a edge's neighbors is tricky due to rowspan and colspans. Once you have a list on "contenders" for an edge, doing the priority part is tedious but it basically a big chain of if's.

johnbeard avatar Jan 01 '21 23:01 johnbeard

What it does (for every block element): each block/cell carries its own borders, get the own top/left x/y, and it draws them (border + content) at x/y+w/h.

Technically, it's supposed to offset by half the border width, I think, so the top corner is (x-b/2, y-b/2) and the total size, measured from outer edges of the border, is (w+b, h+b).

For example, from the CSS spec example: tbl-border-conflict

vs (with the lines above commented to show all borders, ignore the missing black line, that's because COL doesn't work): 2021-01-02_003052_224x382_screenshot

so the blue and green borders start a little too far down and to the right.

BTW, here's with stock crengine, lines un-commented: 2021-01-02_003559_226x372_screenshot

johnbeard avatar Jan 02 '21 00:01 johnbeard

To not lose it, some related discussion on gitter around https://gitter.im/koreader/koreader?at=5ff4d73dacd1e516f8d637f9

poire-z avatar Jan 06 '21 21:01 poire-z