2009-07-27 Stephen White <senorblanco@chromium.org>
authorlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jul 2009 00:50:15 +0000 (00:50 +0000)
committerlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Jul 2009 00:50:15 +0000 (00:50 +0000)
        Reviewed by Eric Seidel and David Levin.

        Re-apply chromium/skia border fix (originally landed in r46157,
        reverted in r46363), since it was not the cause of the reliability
        failures in Chromium.

        http://bugs.webkit.org/show_bug.cgi?id=27388

        * platform/graphics/skia/GraphicsContextSkia.cpp:
        (WebCore::GraphicsContext::drawLine):
        * platform/graphics/skia/PlatformContextSkia.cpp:
        (PlatformContextSkia::setupPaintForStroking):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@46447 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
WebCore/platform/graphics/skia/PlatformContextSkia.cpp

index 27b3e16..46cc3bf 100644 (file)
@@ -1,3 +1,18 @@
+2009-07-27  Stephen White  <senorblanco@chromium.org>
+
+        Reviewed by Eric Seidel and David Levin.
+
+        Re-apply chromium/skia border fix (originally landed in r46157,
+        reverted in r46363), since it was not the cause of the reliability
+        failures in Chromium.
+
+        http://bugs.webkit.org/show_bug.cgi?id=27388
+
+        * platform/graphics/skia/GraphicsContextSkia.cpp:
+        (WebCore::GraphicsContext::drawLine):
+        * platform/graphics/skia/PlatformContextSkia.cpp:
+        (PlatformContextSkia::setupPaintForStroking):
+
 2009-07-27  Ryosuke Niwa  <rniwa@webkit.org>
 
         Reviewed by Justin Garcia.
index 18bedff..bbb42c9 100644 (file)
@@ -530,16 +530,48 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
     // probably worth the speed up of no square root, which also won't be exact.
     SkPoint disp = pts[1] - pts[0];
     int length = SkScalarRound(disp.fX + disp.fY);
-    int width = roundf(
-        platformContext()->setupPaintForStroking(&paint, 0, length));
+    platformContext()->setupPaintForStroking(&paint, 0, length);
+    int width = roundf(strokeThickness());
+    bool isVerticalLine = pts[0].fX == pts[1].fX;
+
+    if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
+        // Do a rect fill of our endpoints.  This ensures we always have the
+        // appearance of being a border.  We then draw the actual dotted/dashed line.
+
+        SkRect r1, r2;
+        r1.set(pts[0].fX, pts[0].fY, pts[0].fX + width, pts[0].fY + width);
+        r2.set(pts[1].fX, pts[1].fY, pts[1].fX + width, pts[1].fY + width);
+
+        if (isVerticalLine) {
+            r1.offset(-width / 2, 0);
+            r2.offset(-width / 2, -width);
+        } else {
+            r1.offset(0, -width / 2);
+            r2.offset(-width, -width / 2);
+        }
+        SkPaint fillPaint;
+        fillPaint.setColor(paint.getColor());
+        platformContext()->canvas()->drawRect(r1, fillPaint);
+        platformContext()->canvas()->drawRect(r2, fillPaint);
+
+        // Since we've already rendered the endcaps, adjust the endpoints to
+        // exclude them from the line itself.
+        if (isVerticalLine) {
+            pts[0].fY += width;
+            pts[1].fY -= width;
+        } else {
+            pts[0].fX += width;
+            pts[1].fX -= width;
+        }
+    }
 
     // "Borrowed" this comment and idea from GraphicsContextCG.cpp
+    //
     // For odd widths, we add in 0.5 to the appropriate x/y so that the float
     // arithmetic works out.  For example, with a border width of 3, KHTML will
     // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5.  It is
     // always true that an even width gave us a perfect position, but an odd
     // width gave us a position that is off by exactly 0.5.
-    bool isVerticalLine = pts[0].fX == pts[1].fX;
 
     if (width & 1) {  // Odd.
         if (isVerticalLine) {
index 4f13c3d..e0a292c 100644 (file)
@@ -338,20 +338,27 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i
             width = m_state->m_dashRatio * width;
             // Fall through.
         case WebCore::DottedStroke:
-            SkScalar dashLength;
-            if (length) {
-                // Determine about how many dashes or dots we should have.
-                float roundedWidth = roundf(width);
-                int numDashes = roundedWidth ? (length / roundedWidth) : length;
-                if (!(numDashes & 1))
-                    numDashes++;    // Make it odd so we end on a dash/dot.
-                // Use the number of dashes to determine the length of a
-                // dash/dot, which will be approximately width
-                dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
-            } else
-                dashLength = SkFloatToScalar(width);
-            SkScalar intervals[2] = { dashLength, dashLength };
-            paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
+            // Truncate the width, since we don't want fuzzy dots or dashes.
+            int dashLength = static_cast<int>(width);
+            // Subtract off the endcaps, since they're rendered separately.
+            int distance = length - 2 * static_cast<int>(m_state->m_strokeThickness);
+            int phase = 1;
+            if (dashLength > 1) {
+                // Determine how many dashes or dots we should have.
+                int numDashes = distance / dashLength;
+                int remainder = distance % dashLength;
+                // Adjust the phase to center the dashes within the line.
+                if (numDashes % 2 == 0) {
+                    // Even:  shift right half a dash, minus half the remainder
+                    phase = (dashLength - remainder) / 2;
+                } else {
+                    // Odd:  shift right a full dash, minus half the remainder
+                    phase = dashLength - remainder / 2;
+                }
+            }
+            SkScalar dashLengthSk = SkIntToScalar(dashLength);
+            SkScalar intervals[2] = { dashLengthSk, dashLengthSk };
+            paint->setPathEffect(new SkDashPathEffect(intervals, 2, SkIntToScalar(phase)))->unref();
         }
     }