<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>85532</bug_id>
          
          <creation_ts>2012-05-03 12:34:35 -0700</creation_ts>
          <short_desc>[meta] Enable sub-pixel layout on all platforms</short_desc>
          <delta_ts>2013-03-25 07:33:16 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>Layout and Rendering</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          <dependson>60318</dependson>
    
    <dependson>85555</dependson>
    
    <dependson>85671</dependson>
    
    <dependson>86665</dependson>
    
    <dependson>89458</dependson>
    
    <dependson>94792</dependson>
    
    <dependson>102622</dependson>
    
    <dependson>113199</dependson>
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Levi Weintraub">leviw</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>allan.jensen</cc>
    
    <cc>drackett</cc>
    
    <cc>d-r</cc>
    
    <cc>eae</cc>
    
    <cc>jdaggett</cc>
    
    <cc>pdr</cc>
    
    <cc>simon.fraser</cc>
    
    <cc>zimmermann</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>615498</commentid>
    <comment_count>0</comment_count>
    <who name="Levi Weintraub">leviw</who>
    <bug_when>2012-05-03 12:34:35 -0700</bug_when>
    <thetext>bug to track enabling the SUBPIXEL_LAYOUT feature flag on all platforms.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>646832</commentid>
    <comment_count>1</comment_count>
    <who name="Nikolas Zimmermann">zimmermann</who>
    <bug_when>2012-06-12 04:52:36 -0700</bug_when>
    <thetext>What&apos;s the status of sub pixel support? Can you give us an update Levi?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>647028</commentid>
    <comment_count>2</comment_count>
    <who name="Levi Weintraub">leviw</who>
    <bug_when>2012-06-12 10:05:06 -0700</bug_when>
    <thetext>(In reply to comment #1)
&gt; What&apos;s the status of sub pixel support? Can you give us an update Levi?

Sure.

Sub-pixel support is in but defaulted to off, behind the ENABLE_SUBPIXEL_LAYOUT flag. Chromium has turned this feature on (you can try it in the Dev channel), and all other ports are encouraged to do so.

I plan to follow up with encouraging other ports on webkit-dev when we&apos;ve promoted this functionality to Chromium&apos;s beta or stable channel as that&apos;ll mean a lot more eyes have verified this functionality.

Do you have any specific questions?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>648762</commentid>
    <comment_count>3</comment_count>
    <who name="Levi Weintraub">leviw</who>
    <bug_when>2012-06-13 21:01:02 -0700</bug_when>
    <thetext>(In reply to comment #2)
&gt; (In reply to comment #1)
&gt; &gt; What&apos;s the status of sub pixel support? Can you give us an update Levi?
&gt; 
&gt; Sure.
&gt; 
&gt; Sub-pixel support is in but defaulted to off, behind the ENABLE_SUBPIXEL_LAYOUT flag. Chromium has turned this feature on (you can try it in the Dev channel), and all other ports are encouraged to do so.
&gt; 
&gt; I plan to follow up with encouraging other ports on webkit-dev when we&apos;ve promoted this functionality to Chromium&apos;s beta or stable channel as that&apos;ll mean a lot more eyes have verified this functionality.
&gt; 
&gt; Do you have any specific questions?

I&apos;d love an update on plans for enabling it in the KDE project ;)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>649054</commentid>
    <comment_count>4</comment_count>
    <who name="Nikolas Zimmermann">zimmermann</who>
    <bug_when>2012-06-14 03:45:01 -0700</bug_when>
    <thetext>(In reply to comment #2)
&gt; (In reply to comment #1)
&gt; &gt; What&apos;s the status of sub pixel support? Can you give us an update Levi?
&gt; 
&gt; Sure.
&gt; 
&gt; Sub-pixel support is in but defaulted to off, behind the ENABLE_SUBPIXEL_LAYOUT flag. Chromium has turned this feature on (you can try it in the Dev channel), and all other ports are encouraged to do so.
Excellent, I&apos;ll try this on Mac for a while.
 
&gt; I plan to follow up with encouraging other ports on webkit-dev when we&apos;ve promoted this functionality to Chromium&apos;s beta or stable channel as that&apos;ll mean a lot more eyes have verified this functionality.
&gt; 
&gt; Do you have any specific questions?
Not really, if it can be enabled I&apos;m happy -- we can remove SVG specific FloatPoint/FloatRects in several places, if we could use the frameRect/borderBoxRect for this as example. I&apos;m working on it.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>654334</commentid>
    <comment_count>5</comment_count>
    <who name="Allan Sandfeld Jensen">allan.jensen</who>
    <bug_when>2012-06-21 02:25:45 -0700</bug_when>
    <thetext>For your information. I have been testing sub-pixel layout on the Qt platform (to ensure my work on rect-based hit-testing was compatible with sub-pixel types), and it works perfectly with no regression I have noticed.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>657603</commentid>
    <comment_count>6</comment_count>
    <who name="Nikolas Zimmermann">zimmermann</who>
    <bug_when>2012-06-26 07:48:01 -0700</bug_when>
    <thetext>(In reply to comment #3)
&gt; I&apos;d love an update on plans for enabling it in the KDE project ;)
I&apos;m not working on KDE stuff since half a decade btw, historical reasons for my bugzilla account :-)

Anyhow, I&apos;ve experimented lots with SUBPIXEL_LAYOUT turned on, on Mac. You&apos;ve done a great job, it&apos;s working as-expected for most parts.

I&apos;ve ran into an issue with transforming an absolute positioned &lt;div&gt;, which is aligned on sub-pixel boundaries, like this:

&lt;html&gt;
&lt;body&gt;
&lt;div style=&quot;-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

If you run this in trunk, you won&apos;t see anything, unless you zoom in or out at least once.
I&apos;ve nailed down the problem, but I&apos;m yet unsure on how to fix it properly, so I&apos;d like to share it with you to get your insight:
void RenderBlock::paint(PaintInfo&amp; paintInfo, const LayoutPoint&amp; paintOffset)
{
    LayoutPoint adjustedPaintOffset = paintOffset + location();

    PaintPhase phase = paintInfo.phase;

    // Check if we need to do anything at all.
    // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
    // paints the root&apos;s background.
    if (!isRoot()) {
        LayoutRect overflowBox = visualOverflowRect();
        flipForWritingMode(overflowBox);
        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
        overflowBox.moveBy(adjustedPaintOffset);
        if (!overflowBox.intersects(paintInfo.rect))
            return;
    ....

Break on RenderBlock::paint(), at some point:
Breakpoint 1, WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2626
2626	    LayoutPoint adjustedPaintOffset = paintOffset + location();
(gdb) p showRenderTreeForThis()
RenderView 0x109124108                 	#document	0x10882a600
  RenderBlock 0x109125b78              	HTML	0x109120380
    RenderBody 0x1091266d8             	BODY	0x109125ca0
*     RenderBlock (positioned) 0x1091271e8	DIV	0x109126400 STYLE=-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;

is reached.

2638	        if (!overflowBox.intersects(paintInfo.rect))
(gdb) p overflowBox
$39 = {
  m_location = {
    m_x = {
      m_value = 0
    }, 
    m_y = {
      m_value = 0
    }
  }, 
  m_size = {
    m_width = {
      m_value = 60
    }, 
    m_height = {
      m_value = 60
    }
  }
}

p paintInfo.rect
$40 = {
  m_location = {
    m_x = 1, 
    m_y = 1
  }, 
  m_size = {
    m_width = 8, 
    m_height = 6
  }
}

0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
2638	        if (!overflowBox.intersects(paintInfo.rect))
Value returned is $41 = false

And here&apos;s the problem. The paintInfo.rect has a location of 1x1, and a size of 8x6.
So let&apos;s examine where the incorrect paintInfo.rect is coming from:

(gdb) bt
#0  0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
#1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149

Looking at frame #1:
#1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
3147	            // Paint the background.
3148	            PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
3149	            renderer()-&gt;paint(paintInfo, paintOffset);

(gdb) p damageRect.rect()
$51 = (const LayoutRect &amp;) @0x7fff5fbf9908: {
  m_location = {
    m_x = {
      m_value = 30
    }, 
    m_y = {
      m_value = 30
    }
  }, 
  m_size = {
    m_width = {
      m_value = 480
    }, 
    m_height = {
      m_value = 360
    }
  }
}

The pixelSnappedIntRect() produces the x/y=1, width=8, height=6 IntRect.

Some more background info:
The RenderLayer associated with the &lt;div&gt; has a transform, scale(100).
#3  0x000000010279c370 in WebCore::RenderLayer::paintLayer (this=0x1091272b8, rootLayer=0x1091244c8, context=0x7fff5fbfb4c0, paintDirtyRect=@0x7fff5fbfa2d0, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3006

3001	        {
3002	            GraphicsContextStateSaver stateSaver(*context);
3003	            context-&gt;concatCTM(transform.toAffineTransform());
3004	
3005	            // Now do a paint with the root layer shifted to be us.
3006	            paintLayerContentsAndReflection(this, context, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
3007	        }        
3008	
3009	        // Restore the clip.
3010	        if (parent())

(gdb) p transform
$56 = {
  m_matrix = {{100, 0, 0, 0}, {0, 100, 0, 0}, {0, 0, 1, 0}, {-50, -50, 0, 1}}
}

(gdb) p paintDirtyRect
$58 = (const LayoutRect &amp;) @0x7fff5fbfa2d0: {
  m_location = {
    m_x = {
      m_value = 0
    }, 
    m_y = {
      m_value = 0
    }
  }, 
  m_size = {
    m_width = {
      m_value = 48000
    }, 
    m_height = {
      m_value = 36000
    }
  }
}

The mapping of the paintDirtyRect through the inverse of the transform, produces x/y=30 (aka. 0.5).
Now that we know the root of the problem, if you change left/top to 0.4999px, it&apos;ll show up as expected, as the paintInfo.rect is now at 0x0, as 0.4999px is pixel-snapped to 0, instead of 1.

I&apos;m unsure on how to fix this properly: the intersection between the pixel-snapped paint info rect and the overflow box is lossy, as the overflow box is sub-pixel aware.

(gdb) p toRenderBox(renderer())-&gt;m_frameRect
$61 = {
  m_location = {
    m_x = {
      m_value = -30
    }, 
    m_y = {
      m_value = -30
    }
  }, 
  m_size = {
    m_width = {
      m_value = 60
    }, 
    m_height = {
      m_value = 60
    }
  }
}

As no overflow is involved in my example, visualOverflowRect() == borderBoxRect(), aka. LayoutRect(0, 0, m_frameRect-&gt;width(), m_frameRect-&gt;height()) (in this example).

Sorry for the long post, but I thought I&apos;d give as much information as possible, so we can discuss this easier. Levi, any idea?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>663071</commentid>
    <comment_count>7</comment_count>
    <who name="Philip Rogers">pdr</who>
    <bug_when>2012-07-04 11:06:49 -0700</bug_when>
    <thetext>(In reply to comment #6)
&gt; (In reply to comment #3)
&gt; &gt; I&apos;d love an update on plans for enabling it in the KDE project ;)
&gt; I&apos;m not working on KDE stuff since half a decade btw, historical reasons for my bugzilla account :-)
&gt; 
&gt; Anyhow, I&apos;ve experimented lots with SUBPIXEL_LAYOUT turned on, on Mac. You&apos;ve done a great job, it&apos;s working as-expected for most parts.
&gt; 
&gt; I&apos;ve ran into an issue with transforming an absolute positioned &lt;div&gt;, which is aligned on sub-pixel boundaries, like this:
&gt; 
&gt; &lt;html&gt;
&gt; &lt;body&gt;
&gt; &lt;div style=&quot;-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;&quot;&gt;&lt;/div&gt;
&gt; &lt;/body&gt;
&gt; &lt;/html&gt;
&gt; 
&gt; If you run this in trunk, you won&apos;t see anything, unless you zoom in or out at least once.
&gt; I&apos;ve nailed down the problem, but I&apos;m yet unsure on how to fix it properly, so I&apos;d like to share it with you to get your insight:
&gt; void RenderBlock::paint(PaintInfo&amp; paintInfo, const LayoutPoint&amp; paintOffset)
&gt; {
&gt;     LayoutPoint adjustedPaintOffset = paintOffset + location();
&gt; 
&gt;     PaintPhase phase = paintInfo.phase;
&gt; 
&gt;     // Check if we need to do anything at all.
&gt;     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
&gt;     // paints the root&apos;s background.
&gt;     if (!isRoot()) {
&gt;         LayoutRect overflowBox = visualOverflowRect();
&gt;         flipForWritingMode(overflowBox);
&gt;         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
&gt;         overflowBox.moveBy(adjustedPaintOffset);
&gt;         if (!overflowBox.intersects(paintInfo.rect))
&gt;             return;
&gt;     ....
&gt; 
&gt; Break on RenderBlock::paint(), at some point:
&gt; Breakpoint 1, WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2626
&gt; 2626        LayoutPoint adjustedPaintOffset = paintOffset + location();
&gt; (gdb) p showRenderTreeForThis()
&gt; RenderView 0x109124108                     #document    0x10882a600
&gt;   RenderBlock 0x109125b78                  HTML    0x109120380
&gt;     RenderBody 0x1091266d8                 BODY    0x109125ca0
&gt; *     RenderBlock (positioned) 0x1091271e8    DIV    0x109126400 STYLE=-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;
&gt; 
&gt; is reached.
&gt; 
&gt; 2638            if (!overflowBox.intersects(paintInfo.rect))
&gt; (gdb) p overflowBox
&gt; $39 = {
&gt;   m_location = {
&gt;     m_x = {
&gt;       m_value = 0
&gt;     }, 
&gt;     m_y = {
&gt;       m_value = 0
&gt;     }
&gt;   }, 
&gt;   m_size = {
&gt;     m_width = {
&gt;       m_value = 60
&gt;     }, 
&gt;     m_height = {
&gt;       m_value = 60
&gt;     }
&gt;   }
&gt; }
&gt; 
&gt; p paintInfo.rect
&gt; $40 = {
&gt;   m_location = {
&gt;     m_x = 1, 
&gt;     m_y = 1
&gt;   }, 
&gt;   m_size = {
&gt;     m_width = 8, 
&gt;     m_height = 6
&gt;   }
&gt; }
&gt; 
&gt; 0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
&gt; 2638            if (!overflowBox.intersects(paintInfo.rect))
&gt; Value returned is $41 = false
&gt; 
&gt; And here&apos;s the problem. The paintInfo.rect has a location of 1x1, and a size of 8x6.
&gt; So let&apos;s examine where the incorrect paintInfo.rect is coming from:
&gt; 
&gt; (gdb) bt
&gt; #0  0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
&gt; #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
&gt; 
&gt; Looking at frame #1:
&gt; #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
&gt; 3147                // Paint the background.
&gt; 3148                PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
&gt; 3149                renderer()-&gt;paint(paintInfo, paintOffset);
&gt; 
&gt; (gdb) p damageRect.rect()
&gt; $51 = (const LayoutRect &amp;) @0x7fff5fbf9908: {
&gt;   m_location = {
&gt;     m_x = {
&gt;       m_value = 30
&gt;     }, 
&gt;     m_y = {
&gt;       m_value = 30
&gt;     }
&gt;   }, 
&gt;   m_size = {
&gt;     m_width = {
&gt;       m_value = 480
&gt;     }, 
&gt;     m_height = {
&gt;       m_value = 360
&gt;     }
&gt;   }
&gt; }
&gt; 
&gt; The pixelSnappedIntRect() produces the x/y=1, width=8, height=6 IntRect.
&gt; 
&gt; Some more background info:
&gt; The RenderLayer associated with the &lt;div&gt; has a transform, scale(100).
&gt; #3  0x000000010279c370 in WebCore::RenderLayer::paintLayer (this=0x1091272b8, rootLayer=0x1091244c8, context=0x7fff5fbfb4c0, paintDirtyRect=@0x7fff5fbfa2d0, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3006
&gt; 
&gt; 3001            {
&gt; 3002                GraphicsContextStateSaver stateSaver(*context);
&gt; 3003                context-&gt;concatCTM(transform.toAffineTransform());
&gt; 3004    
&gt; 3005                // Now do a paint with the root layer shifted to be us.
&gt; 3006                paintLayerContentsAndReflection(this, context, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
&gt; 3007            }        
&gt; 3008    
&gt; 3009            // Restore the clip.
&gt; 3010            if (parent())
&gt; 
&gt; (gdb) p transform
&gt; $56 = {
&gt;   m_matrix = {{100, 0, 0, 0}, {0, 100, 0, 0}, {0, 0, 1, 0}, {-50, -50, 0, 1}}
&gt; }
&gt; 
&gt; (gdb) p paintDirtyRect
&gt; $58 = (const LayoutRect &amp;) @0x7fff5fbfa2d0: {
&gt;   m_location = {
&gt;     m_x = {
&gt;       m_value = 0
&gt;     }, 
&gt;     m_y = {
&gt;       m_value = 0
&gt;     }
&gt;   }, 
&gt;   m_size = {
&gt;     m_width = {
&gt;       m_value = 48000
&gt;     }, 
&gt;     m_height = {
&gt;       m_value = 36000
&gt;     }
&gt;   }
&gt; }
&gt; 
&gt; The mapping of the paintDirtyRect through the inverse of the transform, produces x/y=30 (aka. 0.5).
&gt; Now that we know the root of the problem, if you change left/top to 0.4999px, it&apos;ll show up as expected, as the paintInfo.rect is now at 0x0, as 0.4999px is pixel-snapped to 0, instead of 1.
&gt; 
&gt; I&apos;m unsure on how to fix this properly: the intersection between the pixel-snapped paint info rect and the overflow box is lossy, as the overflow box is sub-pixel aware.
&gt; 
&gt; (gdb) p toRenderBox(renderer())-&gt;m_frameRect
&gt; $61 = {
&gt;   m_location = {
&gt;     m_x = {
&gt;       m_value = -30
&gt;     }, 
&gt;     m_y = {
&gt;       m_value = -30
&gt;     }
&gt;   }, 
&gt;   m_size = {
&gt;     m_width = {
&gt;       m_value = 60
&gt;     }, 
&gt;     m_height = {
&gt;       m_value = 60
&gt;     }
&gt;   }
&gt; }
&gt; 
&gt; As no overflow is involved in my example, visualOverflowRect() == borderBoxRect(), aka. LayoutRect(0, 0, m_frameRect-&gt;width(), m_frameRect-&gt;height()) (in this example).
&gt; 
&gt; Sorry for the long post, but I thought I&apos;d give as much information as possible, so we can discuss this easier. Levi, any idea?


Levi, eae: ping? This is somewhat of a blocker for the SVG2.0 work.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>663094</commentid>
    <comment_count>8</comment_count>
    <who name="Emil A Eklund">eae</who>
    <bug_when>2012-07-04 12:19:28 -0700</bug_when>
    <thetext>I&apos;ll try to get to this later today or tomorrow, been a busy week. Sorry about the delay.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>678508</commentid>
    <comment_count>9</comment_count>
    <who name="Levi Weintraub">leviw</who>
    <bug_when>2012-07-25 14:55:37 -0700</bug_when>
    <thetext>(In reply to comment #7)
&gt; (In reply to comment #6)
&gt; &gt; (In reply to comment #3)
&gt; &gt; &gt; I&apos;d love an update on plans for enabling it in the KDE project ;)
&gt; &gt; I&apos;m not working on KDE stuff since half a decade btw, historical reasons for my bugzilla account :-)
&gt; &gt; 
&gt; &gt; Anyhow, I&apos;ve experimented lots with SUBPIXEL_LAYOUT turned on, on Mac. You&apos;ve done a great job, it&apos;s working as-expected for most parts.
&gt; &gt; 
&gt; &gt; I&apos;ve ran into an issue with transforming an absolute positioned &lt;div&gt;, which is aligned on sub-pixel boundaries, like this:
&gt; &gt; 
&gt; &gt; &lt;html&gt;
&gt; &gt; &lt;body&gt;
&gt; &gt; &lt;div style=&quot;-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;&quot;&gt;&lt;/div&gt;
&gt; &gt; &lt;/body&gt;
&gt; &gt; &lt;/html&gt;
&gt; &gt; 
&gt; &gt; If you run this in trunk, you won&apos;t see anything, unless you zoom in or out at least once.
&gt; &gt; I&apos;ve nailed down the problem, but I&apos;m yet unsure on how to fix it properly, so I&apos;d like to share it with you to get your insight:
&gt; &gt; void RenderBlock::paint(PaintInfo&amp; paintInfo, const LayoutPoint&amp; paintOffset)
&gt; &gt; {
&gt; &gt;     LayoutPoint adjustedPaintOffset = paintOffset + location();
&gt; &gt; 
&gt; &gt;     PaintPhase phase = paintInfo.phase;
&gt; &gt; 
&gt; &gt;     // Check if we need to do anything at all.
&gt; &gt;     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
&gt; &gt;     // paints the root&apos;s background.
&gt; &gt;     if (!isRoot()) {
&gt; &gt;         LayoutRect overflowBox = visualOverflowRect();
&gt; &gt;         flipForWritingMode(overflowBox);
&gt; &gt;         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
&gt; &gt;         overflowBox.moveBy(adjustedPaintOffset);
&gt; &gt;         if (!overflowBox.intersects(paintInfo.rect))
&gt; &gt;             return;
&gt; &gt;     ....
&gt; &gt; 
&gt; &gt; Break on RenderBlock::paint(), at some point:
&gt; &gt; Breakpoint 1, WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2626
&gt; &gt; 2626        LayoutPoint adjustedPaintOffset = paintOffset + location();
&gt; &gt; (gdb) p showRenderTreeForThis()
&gt; &gt; RenderView 0x109124108                     #document    0x10882a600
&gt; &gt;   RenderBlock 0x109125b78                  HTML    0x109120380
&gt; &gt;     RenderBody 0x1091266d8                 BODY    0x109125ca0
&gt; &gt; *     RenderBlock (positioned) 0x1091271e8    DIV    0x109126400 STYLE=-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;
&gt; &gt; 
&gt; &gt; is reached.
&gt; &gt; 
&gt; &gt; 2638            if (!overflowBox.intersects(paintInfo.rect))
&gt; &gt; (gdb) p overflowBox
&gt; &gt; $39 = {
&gt; &gt;   m_location = {
&gt; &gt;     m_x = {
&gt; &gt;       m_value = 0
&gt; &gt;     }, 
&gt; &gt;     m_y = {
&gt; &gt;       m_value = 0
&gt; &gt;     }
&gt; &gt;   }, 
&gt; &gt;   m_size = {
&gt; &gt;     m_width = {
&gt; &gt;       m_value = 60
&gt; &gt;     }, 
&gt; &gt;     m_height = {
&gt; &gt;       m_value = 60
&gt; &gt;     }
&gt; &gt;   }
&gt; &gt; }
&gt; &gt; 
&gt; &gt; p paintInfo.rect
&gt; &gt; $40 = {
&gt; &gt;   m_location = {
&gt; &gt;     m_x = 1, 
&gt; &gt;     m_y = 1
&gt; &gt;   }, 
&gt; &gt;   m_size = {
&gt; &gt;     m_width = 8, 
&gt; &gt;     m_height = 6
&gt; &gt;   }
&gt; &gt; }
&gt; &gt; 
&gt; &gt; 0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
&gt; &gt; 2638            if (!overflowBox.intersects(paintInfo.rect))
&gt; &gt; Value returned is $41 = false
&gt; &gt; 
&gt; &gt; And here&apos;s the problem. The paintInfo.rect has a location of 1x1, and a size of 8x6.
&gt; &gt; So let&apos;s examine where the incorrect paintInfo.rect is coming from:
&gt; &gt; 
&gt; &gt; (gdb) bt
&gt; &gt; #0  0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
&gt; &gt; #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
&gt; &gt; 
&gt; &gt; Looking at frame #1:
&gt; &gt; #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
&gt; &gt; 3147                // Paint the background.
&gt; &gt; 3148                PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
&gt; &gt; 3149                renderer()-&gt;paint(paintInfo, paintOffset);
&gt; &gt; 
&gt; &gt; (gdb) p damageRect.rect()
&gt; &gt; $51 = (const LayoutRect &amp;) @0x7fff5fbf9908: {
&gt; &gt;   m_location = {
&gt; &gt;     m_x = {
&gt; &gt;       m_value = 30
&gt; &gt;     }, 
&gt; &gt;     m_y = {
&gt; &gt;       m_value = 30
&gt; &gt;     }
&gt; &gt;   }, 
&gt; &gt;   m_size = {
&gt; &gt;     m_width = {
&gt; &gt;       m_value = 480
&gt; &gt;     }, 
&gt; &gt;     m_height = {
&gt; &gt;       m_value = 360
&gt; &gt;     }
&gt; &gt;   }
&gt; &gt; }
&gt; &gt; 
&gt; &gt; The pixelSnappedIntRect() produces the x/y=1, width=8, height=6 IntRect.
&gt; &gt; 
&gt; &gt; Some more background info:
&gt; &gt; The RenderLayer associated with the &lt;div&gt; has a transform, scale(100).
&gt; &gt; #3  0x000000010279c370 in WebCore::RenderLayer::paintLayer (this=0x1091272b8, rootLayer=0x1091244c8, context=0x7fff5fbfb4c0, paintDirtyRect=@0x7fff5fbfa2d0, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3006
&gt; &gt; 
&gt; &gt; 3001            {
&gt; &gt; 3002                GraphicsContextStateSaver stateSaver(*context);
&gt; &gt; 3003                context-&gt;concatCTM(transform.toAffineTransform());
&gt; &gt; 3004    
&gt; &gt; 3005                // Now do a paint with the root layer shifted to be us.
&gt; &gt; 3006                paintLayerContentsAndReflection(this, context, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
&gt; &gt; 3007            }        
&gt; &gt; 3008    
&gt; &gt; 3009            // Restore the clip.
&gt; &gt; 3010            if (parent())
&gt; &gt; 
&gt; &gt; (gdb) p transform
&gt; &gt; $56 = {
&gt; &gt;   m_matrix = {{100, 0, 0, 0}, {0, 100, 0, 0}, {0, 0, 1, 0}, {-50, -50, 0, 1}}
&gt; &gt; }
&gt; &gt; 
&gt; &gt; (gdb) p paintDirtyRect
&gt; &gt; $58 = (const LayoutRect &amp;) @0x7fff5fbfa2d0: {
&gt; &gt;   m_location = {
&gt; &gt;     m_x = {
&gt; &gt;       m_value = 0
&gt; &gt;     }, 
&gt; &gt;     m_y = {
&gt; &gt;       m_value = 0
&gt; &gt;     }
&gt; &gt;   }, 
&gt; &gt;   m_size = {
&gt; &gt;     m_width = {
&gt; &gt;       m_value = 48000
&gt; &gt;     }, 
&gt; &gt;     m_height = {
&gt; &gt;       m_value = 36000
&gt; &gt;     }
&gt; &gt;   }
&gt; &gt; }
&gt; &gt; 
&gt; &gt; The mapping of the paintDirtyRect through the inverse of the transform, produces x/y=30 (aka. 0.5).
&gt; &gt; Now that we know the root of the problem, if you change left/top to 0.4999px, it&apos;ll show up as expected, as the paintInfo.rect is now at 0x0, as 0.4999px is pixel-snapped to 0, instead of 1.
&gt; &gt; 
&gt; &gt; I&apos;m unsure on how to fix this properly: the intersection between the pixel-snapped paint info rect and the overflow box is lossy, as the overflow box is sub-pixel aware.
&gt; &gt; 
&gt; &gt; (gdb) p toRenderBox(renderer())-&gt;m_frameRect
&gt; &gt; $61 = {
&gt; &gt;   m_location = {
&gt; &gt;     m_x = {
&gt; &gt;       m_value = -30
&gt; &gt;     }, 
&gt; &gt;     m_y = {
&gt; &gt;       m_value = -30
&gt; &gt;     }
&gt; &gt;   }, 
&gt; &gt;   m_size = {
&gt; &gt;     m_width = {
&gt; &gt;       m_value = 60
&gt; &gt;     }, 
&gt; &gt;     m_height = {
&gt; &gt;       m_value = 60
&gt; &gt;     }
&gt; &gt;   }
&gt; &gt; }
&gt; &gt; 
&gt; &gt; As no overflow is involved in my example, visualOverflowRect() == borderBoxRect(), aka. LayoutRect(0, 0, m_frameRect-&gt;width(), m_frameRect-&gt;height()) (in this example).
&gt; &gt; 
&gt; &gt; Sorry for the long post, but I thought I&apos;d give as much information as possible, so we can discuss this easier. Levi, any idea?
&gt; 
&gt; 
&gt; Levi, eae: ping? This is somewhat of a blocker for the SVG2.0 work.

Apologies for the slow response -- I&apos;ve been away on vacation. This is yet another issue that is solved by the patch on https://bugs.webkit.org/show_bug.cgi?id=89238. I&apos;ve been trying rather unsuccessfully to get a review (and have been out of town) if one of you have a chance to take a look.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>683748</commentid>
    <comment_count>10</comment_count>
    <who name="Chris Drackett">drackett</who>
    <bug_when>2012-07-31 19:01:55 -0700</bug_when>
    <thetext>does this ticket cover adding subpixel support to &quot;normal&quot; css properties (border-size, box-shadow, margin, etc.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>684725</commentid>
    <comment_count>11</comment_count>
    <who name="Emil A Eklund">eae</who>
    <bug_when>2012-08-01 16:11:52 -0700</bug_when>
    <thetext>(In reply to comment #10)
&gt; does this ticket cover adding subpixel support to &quot;normal&quot; css properties (border-size, box-shadow, margin, etc.)

This bug is about enabling the subpixel support for platforms other than chromium.
See https://trac.webkit.org/wiki/LayoutUnit for details about what that entails.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>701855</commentid>
    <comment_count>12</comment_count>
    <who name="Nikolas Zimmermann">zimmermann</who>
    <bug_when>2012-08-22 06:40:25 -0700</bug_when>
    <thetext>(In reply to comment #9)
&gt; Apologies for the slow response -- I&apos;ve been away on vacation. This is yet another issue that is solved by the patch on https://bugs.webkit.org/show_bug.cgi?id=89238. I&apos;ve been trying rather unsuccessfully to get a review (and have been out of town) if one of you have a chance to take a look.
Oh, does that mean it&apos;s fixed now? Going to retry w/o my workarounds then.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>701887</commentid>
    <comment_count>13</comment_count>
    <who name="Levi Weintraub">leviw</who>
    <bug_when>2012-08-22 07:37:37 -0700</bug_when>
    <thetext>(In reply to comment #12)
&gt; Oh, does that mean it&apos;s fixed now? Going to retry w/o my workarounds then.

Let me know if there continues to be an issue.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>