Bug 78647 - Switch drawLineForBoxSide to use integers
Summary: Switch drawLineForBoxSide to use integers
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Levi Weintraub
URL:
Keywords:
Depends on:
Blocks: 60318
  Show dependency treegraph
 
Reported: 2012-02-14 15:54 PST by Levi Weintraub
Modified: 2012-02-23 19:55 PST (History)
5 users (show)

See Also:


Attachments
Patch (14.12 KB, patch)
2012-02-14 18:02 PST, Levi Weintraub
no flags Details | Formatted Diff | Diff
Patch (22.40 KB, patch)
2012-02-15 15:41 PST, Levi Weintraub
no flags Details | Formatted Diff | Diff
Patch (22.62 KB, patch)
2012-02-23 11:58 PST, Levi Weintraub
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Levi Weintraub 2012-02-14 15:54:39 PST
drawLineForBoxSide handles painting lines for boxes which it's important to be done on pixel boundaries. Its interface doesn't make it possible to pixel snap properly within the function itself -- it draws one side of the box at a time, and the logical right and bottom lines can only be properly determined using the logical top and left positions -- so it needs to be treated like a graphics context function, whereby the caller handles the proper pixel snapping before passing the values in.
Comment 1 Levi Weintraub 2012-02-14 18:02:07 PST
Created attachment 127094 [details]
Patch
Comment 2 Darin Adler 2012-02-14 18:36:48 PST
Comment on attachment 127094 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=127094&action=review

> Source/WebCore/rendering/RenderBlock.cpp:2506
> +                // FIXME: These values will be pixel snapped before being passed to drawLineForBoxSide.

Why does this code have to wait? Can’t we add some pixel-snaping inline functions now that do nothing when fractional positioning is off?
Comment 3 Levi Weintraub 2012-02-15 09:40:09 PST
Comment on attachment 127094 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=127094&action=review

>> Source/WebCore/rendering/RenderBlock.cpp:2506
>> +                // FIXME: These values will be pixel snapped before being passed to drawLineForBoxSide.
> 
> Why does this code have to wait? Can’t we add some pixel-snaping inline functions now that do nothing when fractional positioning is off?

Here is the code being left out: http://trac.webkit.org/changeset/107640/branches/subpixellayout/Source/WebCore/rendering/RenderBlock.cpp

There are a few reasons why I've chosen to not use entirely inline functions to get trunk looking like our subpixel branch:
- There are places where pixel snapping involves calling additional non-inline functions, the results of which will just be thrown out.
- We'll need to use explicit wrapping on constants (think zero mostly) used in places like ternary operators.
- I'm partial to putting methods like round() directly on the FractionalLayoutUnit class, which we obviously can't do for integral types.

The last point was my rationale here. If you disagree, I'll happily go the inline route.
Comment 4 Darin Adler 2012-02-15 09:58:52 PST
Comment on attachment 127094 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=127094&action=review

Please consider my comments.

>>> Source/WebCore/rendering/RenderBlock.cpp:2506
>>> +                // FIXME: These values will be pixel snapped before being passed to drawLineForBoxSide.
>> 
>> Why does this code have to wait? Can’t we add some pixel-snaping inline functions now that do nothing when fractional positioning is off?
> 
> Here is the code being left out: http://trac.webkit.org/changeset/107640/branches/subpixellayout/Source/WebCore/rendering/RenderBlock.cpp
> 
> There are a few reasons why I've chosen to not use entirely inline functions to get trunk looking like our subpixel branch:
> - There are places where pixel snapping involves calling additional non-inline functions, the results of which will just be thrown out.
> - We'll need to use explicit wrapping on constants (think zero mostly) used in places like ternary operators.
> - I'm partial to putting methods like round() directly on the FractionalLayoutUnit class, which we obviously can't do for integral types.
> 
> The last point was my rationale here. If you disagree, I'll happily go the inline route.

> There are places where pixel snapping involves calling additional functions, the results of which will just be thrown out.

I’d like to raise the level of abstraction a bit and use a well named function rather than four lines of code in cases like this:

    int pixelSnappedRuleLeft = ruleLeft.round(); 
    int pixelSnappedRuleRight = snapSizeToPixel(ruleRight - ruleLeft, ruleLeft) + pixelSnappedRuleLeft; 
    int pixelSnappedRuleTop = ruleTop.round(); 
    int pixelSnappedRuleBottom = snapSizeToPixel(ruleBottom - ruleTop, ruleTop) + pixelSnappedRuleTop; 

I think this should be a function that takes a rectangle or other struct and returns one rather than code written out like this. The name of the function can be the best documentation for something like this.

I also think that drawLineForBoxSide should take a struct, not four separate layout unit arguments.

> We'll need to use explicit wrapping on constants (think zero mostly) used in places like ternary operators.

I think that best for this is a named constant zeroLayoutUnit or something like that. Actual explicit wrapping is far inferior.

> I'm partial to putting methods like round() directly on the FractionalLayoutUnit class, which we obviously can't do for integral types.

I don’t think that member functions are better than non-member functions for this sort of thing. I’d like to see us add these functions and start using them in TOT instead of having adding them be a part of flipping the switch. I’d like to see almost no code changes at all required when flipping the switch.
Comment 5 Levi Weintraub 2012-02-15 10:30:54 PST
(In reply to comment #4)
> (From update of attachment 127094 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=127094&action=review
> 
> Please consider my comments.
> 
> >>> Source/WebCore/rendering/RenderBlock.cpp:2506
> >>> +                // FIXME: These values will be pixel snapped before being passed to drawLineForBoxSide.
> >> 
> >> Why does this code have to wait? Can’t we add some pixel-snaping inline functions now that do nothing when fractional positioning is off?
> > 
> > Here is the code being left out: http://trac.webkit.org/changeset/107640/branches/subpixellayout/Source/WebCore/rendering/RenderBlock.cpp
> > 
> > There are a few reasons why I've chosen to not use entirely inline functions to get trunk looking like our subpixel branch:
> > - There are places where pixel snapping involves calling additional non-inline functions, the results of which will just be thrown out.
> > - We'll need to use explicit wrapping on constants (think zero mostly) used in places like ternary operators.
> > - I'm partial to putting methods like round() directly on the FractionalLayoutUnit class, which we obviously can't do for integral types.
> > 
> > The last point was my rationale here. If you disagree, I'll happily go the inline route.
> 
> > There are places where pixel snapping involves calling additional functions, the results of which will just be thrown out.
> 
> I’d like to raise the level of abstraction a bit and use a well named function rather than four lines of code in cases like this:
> 
>     int pixelSnappedRuleLeft = ruleLeft.round(); 
>     int pixelSnappedRuleRight = snapSizeToPixel(ruleRight - ruleLeft, ruleLeft) + pixelSnappedRuleLeft; 
>     int pixelSnappedRuleTop = ruleTop.round(); 
>     int pixelSnappedRuleBottom = snapSizeToPixel(ruleBottom - ruleTop, ruleTop) + pixelSnappedRuleTop; 
> 
> I think this should be a function that takes a rectangle or other struct and returns one rather than code written out like this. The name of the function can be the best documentation for something like this.

Good point.

> 
> I also think that drawLineForBoxSide should take a struct, not four separate layout unit arguments.

Agreed. It only ends up being really ugly in RenderInline::paintOutlineForLine.

> 
> > We'll need to use explicit wrapping on constants (think zero mostly) used in places like ternary operators.
> 
> I think that best for this is a named constant zeroLayoutUnit or something like that. Actual explicit wrapping is far inferior.

We've been trying to avoid explicit wrapping wherever possible, but there are quite a few un-named constants that seem to come from nowhere. Just adding a zero constant would solve many of these... I'll create that one.

> 
> > I'm partial to putting methods like round() directly on the FractionalLayoutUnit class, which we obviously can't do for integral types.
> 
> I don’t think that member functions are better than non-member functions for this sort of thing. I’d like to see us add these functions and start using them in TOT instead of having adding them be a part of flipping the switch. I’d like to see almost no code changes at all required when flipping the switch.

Thanks for sharing your thoughts. I'll work to make that happen.
Comment 6 Levi Weintraub 2012-02-15 15:41:49 PST
Created attachment 127253 [details]
Patch
Comment 7 Levi Weintraub 2012-02-15 15:42:14 PST
(In reply to comment #6)
> Created an attachment (id=127253) [details]
> Patch

Hey Darin, I think this is a better patch (nothing is left out :)

Mind taking another look?
Comment 8 Levi Weintraub 2012-02-17 10:37:11 PST
Darin? Eric? Take a look?
Comment 9 Levi Weintraub 2012-02-22 14:11:38 PST
One more friendly ping :)
Comment 10 Eric Seidel (no email) 2012-02-22 20:00:49 PST
Comment on attachment 127253 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=127253&action=review

> Source/WebCore/rendering/RenderBlock.cpp:2537
> +            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
>              drawLineForBoxSide(paintInfo.context, ruleRect.x(), ruleRect.y(), ruleRect.maxX(), ruleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);

Um...
Comment 11 Levi Weintraub 2012-02-23 11:58:21 PST
Created attachment 128525 [details]
Patch
Comment 12 Levi Weintraub 2012-02-23 13:24:26 PST
(In reply to comment #10)
> (From update of attachment 127253 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=127253&action=review
> 
> > Source/WebCore/rendering/RenderBlock.cpp:2537
> > +            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
> >              drawLineForBoxSide(paintInfo.context, ruleRect.x(), ruleRect.y(), ruleRect.maxX(), ruleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
> 
> Um...

Good catch... take another look?
Comment 13 Eric Seidel (no email) 2012-02-23 13:57:56 PST
Comment on attachment 128525 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=128525&action=review

> Source/WebCore/rendering/RenderBlock.cpp:2597
> +                drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);

Seems we should have a version of this method which takes a rect?  Possibly a LayoutRect event...

> Source/WebCore/rendering/RenderInline.cpp:1459
> +    IntRect pixelSnappedBox = pixelSnappedIntRect(box);

I would have used "snappedBox" or something shorter.  pixelBox?  intBox?

> Source/WebCore/rendering/RenderInline.cpp:1534
> +            pixelSnappedBox.maxY(),
> +            pixelSnappedBox.maxX() + outlineWidth,
> +            pixelSnappedBox.maxY() + outlineWidth,

This seems like a theme... seems like we should have a helper method to help with this theme...

> Source/WebCore/rendering/RenderObject.cpp:1184
> +    int leftOuter = outer.x();
> +    int leftInner = inner.x();
> +    int rightOuter = outer.maxX();
> +    int rightInner = inner.maxX();

Oh, split coords, you are so error prone. :(
Comment 14 Levi Weintraub 2012-02-23 14:17:20 PST
Comment on attachment 128525 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=128525&action=review

>> Source/WebCore/rendering/RenderBlock.cpp:2597
>> +                drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
> 
> Seems we should have a version of this method which takes a rect?  Possibly a LayoutRect event...

We could turn the current contract into an inline version that builds an IntRect for the real implementation. We wouldn't want to use a LayoutRect though... we don't have enough information by the time we get into this function to do pixel snapping in the RenderInline case.
Comment 15 WebKit Review Bot 2012-02-23 19:55:33 PST
Comment on attachment 128525 [details]
Patch

Clearing flags on attachment: 128525

Committed r108719: <http://trac.webkit.org/changeset/108719>
Comment 16 WebKit Review Bot 2012-02-23 19:55:39 PST
All reviewed patches have been landed.  Closing bug.