Closed Bug 421438 Opened 13 years ago Closed 12 years ago

single-tile and multi-tile CSS background images are drawn inconsistently


(Core :: Layout, defect)

Not set





(Reporter: roc, Assigned: roc)



See bug 403181 where I ran into problems with the 368020-2 reftest. Basically if you have

  <div style="background:url(foo.png)">...</div>

where foo.png is at least as big as the <div>, we draw the image using nsLayoutUtils::DrawImage. But if you add a border to the <div> (e.g., "border:1px solid black;"), we take the DrawTile path. This is correct because by default CSS background images repeat, their origin is the top-left of the padding-box, and they extend to cover the border-box, so there is actually a tile whose right edge is under the left border.

But nsLayoutUtils::DrawImage snaps images to pixels, while DrawTile doesn't, so this means that adding a border to the <div> actually changes the rasterization of the background image. That violates the principle of least surprise (and test 368020-2).

Actually, the problem is worse than that, because nsCSSRendering::PaintBackgroundWithSC will take the DrawImage path if the dirty rect happens to fit inside one tile, so you could get rasterization differences if you get unlucky with the dirty rect. But that can be fixed relatively easily by taking the dirty rect out of the decision. I'll assume we will at least do that; the question is what to do about the rest of the problem.
As far as I can tell, there is no ideal solution here. Here are the options:

1) Use the tile path less, by detecting when we have a solid border and adjusting the bgClipArea to exclude the border so we don't try to paint under it. Might be good for performance and would solve the surprising example above. OTOH, surprising scenarios involving dotted/dashed borders and translucent borders would still exist ... although since the tiling would probably be visible in this case, maybe it would be less surprising.

2) Use the tile path more, by making all background-image painting use it. Would probably be bad for both performance and appearance.

3) Make DrawTile paint each tile consistently with DrawImage. That doesn't really work; for example, if we have an image that's nominally 4.5x4.5 pixels and we want to paint an area that's 45x45, snapping each tile to pixels will give us 9 tiles in each direction instead of 10 --- a major change in appearance.

4) Make DrawImage paint consistently with DrawTile. That means no snapping of CSS background images, which sounds awful.

Any other ideas? I'm leaning towards 1, anyone else got an opinion on that?
FWIW, #2 is what we used to do, in Fx2 and until a few months ago on trunk.  #1 sounds fine.
Are you sure it changed that late on trunk? I thought behaviour would have been different by bug 371434 if not earlier.
I just fixed bug 449324 on trunk, which implements suggestion #1.

However, there's still a problem, which is that an image that's normally tiled might take the non-tiled path for a dirty area that fits in a single tile. I filed bug 450350 (with patch) for that.
Depends on: 449324, 450350
Bug 450350 was fixed.
Assignee: nobody → roc
Closed: 12 years ago
Resolution: --- → FIXED
Enabled 368020-2.html:
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.