Bug 131561

Summary: Subpixel rendering: Content with ::before leaves bits behind while animating its position.
Product: WebKit Reporter: zalan <zalan>
Component: Layout and RenderingAssignee: zalan <zalan>
Status: ASSIGNED ---    
Severity: Normal CC: joepeck, simon.fraser
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Test reduction
none
Patch none

Description zalan 2014-04-11 13:51:55 PDT
it's the combination of ::before + (non-compositing)layer + starting position being off screen + moving the content by 0.05 (has to be less than 0.1)

div:before {
 position: absolute;
  top: 0px;
  left: -1px;
  width: 100px;
  height: 100px;
  background-color: red;
  content: "";
}

div {
  position: absolute;
  -webkit-transform: translateX(0px);
}

setInterval(function() { document.getElementById("foo").style.left = pos + "px"; pos += 0.05; }, 10);
Comment 1 zalan 2014-04-11 13:52:26 PDT
Created attachment 229159 [details]
Test reduction
Comment 2 zalan 2014-04-13 12:28:38 PDT
Created attachment 229240 [details]
Patch
Comment 3 zalan 2014-04-13 12:29:10 PDT
Comment on attachment 229240 [details]
Patch

EWS first.
Comment 4 Darin Adler 2014-04-13 23:35:11 PDT
Comment on attachment 229240 [details]
Patch

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

> Source/WebCore/platform/LayoutUnit.h:948
> -    return roundf((value.rawValue() * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor;
> +    int rawValue = value.rawValue();
> +    if (rawValue >= 0)
> +        return roundf((rawValue * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor;
> +
> +    // We need to ceil negative halfway values to maintain rounding direction.
> +    float halfwayRoundingValue = kEffectiveFixedPointDenominator / pixelSnappingFactor / 2;
> +    if (!fmodf(rawValue, halfwayRoundingValue))
> +        return ceilf((rawValue * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor;
> +    return roundf((rawValue * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor;

There is a simpler way of doing this without all the branching. Should just do floorf(x + 0.5f).