Closed
Bug 371434
Opened 18 years ago
Closed 18 years ago
background images are sometimes scaled
Categories
(Core :: Graphics, defect, P1)
Core
Graphics
Tracking
()
RESOLVED
FIXED
mozilla1.9alpha3
People
(Reporter: dbaron, Assigned: dbaron)
References
Details
(Whiteboard: [patch])
Attachments
(1 file, 3 obsolete files)
(deleted),
patch
|
vlad
:
review+
|
Details | Diff | Splinter Review |
Some of the reftests for background images (ones where only a single image is needed for the tile, so we use DrawImage rather than tiling) in layout/reftests/pixel-rounding/ are failing with symptoms of bug 371316. I think this means that the images are being scaled (for some cases of non-pixel-alignment), which they should never be.
Assignee | ||
Comment 1•18 years ago
|
||
So in the case I'm looking at (the last test in background-image-height-5.html), things look fine near the end of nsCSSRendering::PaintBackgroundWithSC where it is about to make the calls into GFX:
p2a=60
sourceRect=900,870,600,630
drawRect=10200,4200,600,630
which is correct. So the problem seems to be in GFX.
Assignee: roc → nobody
Component: Layout: View Rendering → GFX: Thebes
QA Contact: ian → thebes
Assignee | ||
Comment 2•18 years ago
|
||
Oh, I remember this problem. This is the fun case where we have to transform the stuff that's in image coordinates based on where it's going to be placed (for cases where we're placing a non-round number of pixels of width/height of the image), at least for the cases where we're not scaling. (So my patch yesterday in bug 371225 was partly wrong (for the source rect transformation.)
Assignee | ||
Comment 3•18 years ago
|
||
In other words, this is bug 326158 all over again.
Assignee | ||
Comment 4•18 years ago
|
||
Of course, now that we're doing scaling of images that involves averaging pixels, it's even harder to fix correctly. To get that right, we really need to change the DrawImage API so it doesn't conflate scaling and clipping, since we want to scale the image fitting within a region snapped to pixels and then clip the result.
Assignee | ||
Comment 5•18 years ago
|
||
I think nsIRenderingContext::DrawImage needs to take three rects:
const nsIntRect &aSourceRect, /* region of image, pixels */
const nsRect &aDestRect, /* place where aSourceRect is drawn, coords */
const nsRect &aClipRect, /* part of aDestRect that we are currently drawing */
and callers need to stop reducing aSourceRect and aDestRect based on clipping. Then, pretty much the same thing for nsIImage::Draw, except they're all in pixels.
Assignee | ||
Comment 6•18 years ago
|
||
(And note that the only case I can think of in such a proposal where aSourceRect would not be the complete image dimensions would be when -moz-image-region is used to select a subregion of the image. But there might be some other analogous feature I've forgotten about.)
Assignee | ||
Comment 7•18 years ago
|
||
Actually, -moz-image-region takes <length>s, so the region of the image actually has to be in app units as well.
Assignee | ||
Comment 8•18 years ago
|
||
Assignee: nobody → dbaron
Status: NEW → ASSIGNED
Assignee | ||
Comment 9•18 years ago
|
||
Attachment #256574 -
Attachment is obsolete: true
Assignee | ||
Comment 10•18 years ago
|
||
The above patch seems to work, and fixes the background image reftest failures that are marked in the reftest.list, at least on Linux/GTK2. I have low confidence in the nsTreeBodyFrame.cpp changes, though -- I need to test them more, and perhaps refactor that code a little more.
Assignee | ||
Updated•18 years ago
|
Priority: -- → P1
Whiteboard: [patch]
Target Milestone: --- → mozilla1.9alpha3
Assignee | ||
Comment 11•18 years ago
|
||
So I reread the nsTreeBodyFrame changes and tested them a bit, and I'm comfortable with them.
I'd like to test breaking images when printing, but I can't seem to get images to break at all. I was sort of expecting either http://www.flickr.com/photo_zoom.gne?id=401336414&size=o or the image inside of it (in a standalone image document) to break, but it didn't -- in a trunk build without my changes.
In any case, stuart, could you review the gfx changes and the nsLayoutUtils.cpp changes, and roc could you review the rest and sr the whole thing?
Note that I moved nsRenderingContextThebes::DrawImage to nsLayoutUtils, but left the code in nsThebesImage where it is. Stuart suggested entirely using thebes, but nsThebesImage encapsulates all the solid color stuff for single pixel images. Perhaps at some point in the future nsThebesImage should move into thebes, and have an interface other than nsIImage to get at it. But for now I'm just passing gfxRects through nsIImage, which was a bit ugly, but seems the least ugly simple solution I could think of.
Attachment #256579 -
Attachment is obsolete: true
Attachment #256589 -
Flags: superreview?(roc)
Attachment #256589 -
Flags: review?(pavlov)
Assignee | ||
Updated•18 years ago
|
Attachment #256589 -
Flags: review?(roc)
+ destRect.size.width = (srcRect.size.width)*xscale + 1 - xscale;
+ destRect.size.height = (srcRect.size.height)*yscale + 1 - yscale;
Now that we're not rounding, do we need this 1 - scale term? I'm not actually sure why it's there.
+ * @param aDirtyRect The region that was invalidated.
Don't you really mean "draw only this area"? This is more general than invalidation.
I need to think more about what you're doing here, but I'm suspicious of this claim:
+ // And likewise for the dirty rect. (Is should be OK to round to
+ // nearest rather than outwards, since any dirty rects coming from the
+ // OS should be on pixel boundaries; the rest is other things it's
+ // been intersected with, and we should be rounding those consistently.)
E.g. if we're clipping to the bounds of a frame that's not on pixel boundaries, we could have any dirty rect.
Assignee | ||
Comment 13•18 years ago
|
||
(In reply to comment #12)
> + * @param aDirtyRect The region that was invalidated.
>
> Don't you really mean "draw only this area"? This is more general than
> invalidation.
Right, it's the intersection of invalidation and clipping. I'll fix the comment to reflect that.
> I need to think more about what you're doing here, but I'm suspicious of this
> claim:
> + // And likewise for the dirty rect. (Is should be OK to round to
> + // nearest rather than outwards, since any dirty rects coming from the
> + // OS should be on pixel boundaries; the rest is other things it's
> + // been intersected with, and we should be rounding those consistently.)
>
> E.g. if we're clipping to the bounds of a frame that's not on pixel boundaries,
> we could have any dirty rect.
I still think this is ok -- the frame's border, background, and background image are all rounded in the same manner, so it seems like we should round its clipping rect the same way. (I actually originally was going to do expansion, but decided that was unnecessary and wrote the comment above.)
I still need to look into the first comment.
It seems safer to me to round out the dirty rect (and clip it to the image rect). That way we're not relying on any assumptions about how it's being used.
Assignee | ||
Comment 15•18 years ago
|
||
(In reply to comment #14)
> It seems safer to me to round out the dirty rect (and clip it to the image
> rect). That way we're not relying on any assumptions about how it's being used.
We have to be consistent in the way we snap things to pixel boundaries or we'll break lots of things (cause gaps, misalignment, etc.). So I think it really should be safe to assume that we're consistent. (I'm testing that consistency in layout/reftests/pixel-rounding/ too.)
OK
Assignee | ||
Comment 17•18 years ago
|
||
(In reply to comment #12)
> + destRect.size.width = (srcRect.size.width)*xscale + 1 - xscale;
> + destRect.size.height = (srcRect.size.height)*yscale + 1 - yscale;
>
> Now that we're not rounding, do we need this 1 - scale term? I'm not actually
> sure why it's there.
I don't understand what that code is trying to do, so I'd rather not change it.
Comment on attachment 256589 [details] [diff] [review]
patch
- nscoord y = GetContinuationOffset(&aMetrics.width);
- aMetrics.height -= y + mBorderPadding.top;
+ aMetrics.width = GetPrevInFlow()->GetSize().width;
This is odd (the original code I mean). How about just not setting aMetrics.width here?
I think we should remove that not-understood 1-scale factor --- preferably as a separately checked-in patch so we can pinpoint regressions more easily.
Attachment #256589 -
Flags: superreview?(roc)
Attachment #256589 -
Flags: superreview+
Attachment #256589 -
Flags: review?(roc)
Attachment #256589 -
Flags: review+
Assignee | ||
Comment 19•18 years ago
|
||
This is slightly revised in nsImageFrame to fix asserts that it was triggering (by splitting UpdateIntrinsicSize and RecalculateTransform). And switching review request from stuart to vlad per IRC discussion
Attachment #256589 -
Attachment is obsolete: true
Attachment #259047 -
Flags: review?(vladimir)
Attachment #256589 -
Flags: review?(pavlov)
Comment on attachment 259047 [details] [diff] [review]
patch
Looks fine to me..
For posterity, if someone wants to tweak this code, it may be possible to simplify it by clipping to pxDirty and always drawing pxSrc to pxDest, though you'd have to munge all of them for the imgFrame-wants-to-start-at-different-position issue.
Attachment #259047 -
Flags: review?(vladimir) → review+
Assignee | ||
Comment 21•18 years ago
|
||
(In reply to comment #18)
> (From update of attachment 256589 [details] [diff] [review])
> - nscoord y = GetContinuationOffset(&aMetrics.width);
> - aMetrics.height -= y + mBorderPadding.top;
> + aMetrics.width = GetPrevInFlow()->GetSize().width;
>
> This is odd (the original code I mean). How about just not setting
> aMetrics.width here?
I think we should actually keep this, at least for now, since things would be pretty broken if an image were split and it was at different widths (which it could be given different paper sizes and CSS @page). That said, we should fix those things (it doesn't look too hard, at least if we have a way of testing it). I'll file a followup bug.
> I think we should remove that not-understood 1-scale factor --- preferably as a
> separately checked-in patch so we can pinpoint regressions more easily.
OK, I'll try to remember to do that tomorrow...
> things would be pretty broken if an image were split and it was at different
> widths (which it could be given different paper sizes and CSS @page).
Why?
Assignee | ||
Comment 23•18 years ago
|
||
We figure out what part of the image to draw based on the assumption that it's all drawn at the same scale. So we'd end up double-drawing some pieces or leaving gaps.
Assignee | ||
Comment 24•18 years ago
|
||
Anyway, patch checked in to trunk about an hour ago.
SeaMonkey sea-linux-tbox: Zdiff:-1632 (+7208/-8840)
Firefox argo-vm Linux nightly: Zdiff:-924 (+5944/-6868)
still need to file the followup bugs.
Assignee | ||
Comment 25•18 years ago
|
||
Filed bug 376178 and bug 376181 as followup; marking this bug as fixed.
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Updated•18 years ago
|
You need to log in
before you can comment on or make changes to this bug.
Description
•