| Index: Source/WebCore/platform/graphics/cg/PathCG.cpp | 
| =================================================================== | 
| --- Source/WebCore/platform/graphics/cg/PathCG.cpp	(revision 104173) | 
| +++ Source/WebCore/platform/graphics/cg/PathCG.cpp	(working copy) | 
| @@ -41,6 +41,59 @@ | 
|  | 
| namespace WebCore { | 
|  | 
| +// A class to provide an isEmpty test that considers a one-element path with only a MoveTo element | 
| +// to be empty. This behavior is consistent with other platforms in WebKit, and is needed to prevent | 
| +// incorrect (according to the spec) linecap stroking for zero length paths in SVG. | 
| +class PathIsEmptyOrSingleMoveTester { | 
| +public: | 
| +    PathIsEmptyOrSingleMoveTester() : m_moveCount(0) { } | 
| + | 
| +    bool isEmpty() const | 
| +    { | 
| +        return m_moveCount <= 1; | 
| +    } | 
| + | 
| +    static void testPathElement(void* info, const CGPathElement* element) | 
| +    { | 
| +        PathIsEmptyOrSingleMoveTester* tester = static_cast<PathIsEmptyOrSingleMoveTester*>(info); | 
| +        if (element->type == kCGPathElementMoveToPoint) | 
| +            ++tester->m_moveCount; | 
| +        else { | 
| +            // Any non move element implies a non-empty path; set the count to 2 to force | 
| +            // isEmpty to return false. | 
| +            tester->m_moveCount = 2; | 
| +        } | 
| +    } | 
| + | 
| +private: | 
| +    // Any non-move-to element, or more than one move-to element, will make the count >= 2. | 
| +    unsigned m_moveCount; | 
| +}; | 
| + | 
| +// Paths with only move-to elements do not draw under any circumstances, so their bound should | 
| +// be empty. Currently, CoreGraphics returns non-empty bounds for such paths. Radar 10450621 | 
| +// tracks this. This class reports paths that have only move-to elements, allowing the | 
| +// bounding box code to work around the CoreGraphics problem. | 
| +class PathHasOnlyMoveToTester { | 
| +public: | 
| +    PathHasOnlyMoveToTester() : m_hasSeenOnlyMoveTo(true) { } | 
| + | 
| +    bool hasOnlyMoveTo() const | 
| +    { | 
| +        return m_hasSeenOnlyMoveTo; | 
| +    } | 
| + | 
| +    static void testPathElement(void* info, const CGPathElement* element) | 
| +    { | 
| +        PathHasOnlyMoveToTester* tester = static_cast<PathHasOnlyMoveToTester*>(info); | 
| +        if (tester->m_hasSeenOnlyMoveTo && element->type != kCGPathElementMoveToPoint) | 
| +            tester->m_hasSeenOnlyMoveTo = false; | 
| +    } | 
| + | 
| +private: | 
| +    bool m_hasSeenOnlyMoveTo; | 
| +}; | 
| + | 
| static size_t putBytesNowhere(void*, const void*, size_t count) | 
| { | 
| return count; | 
| @@ -165,6 +218,14 @@ | 
| { | 
| // CGPathGetBoundingBox includes the path's control points, CGPathGetPathBoundingBox | 
| // does not, but only exists on 10.6 and above. | 
| +    // A bug in CoreGraphics leads to an incorrect bound on paths containing only move-to elements | 
| +    // with a linecap style that is non-butt. All paths with only move-to elements (regardless of | 
| +    // linecap) are effectively empty for bounding purposes and here we make it so. | 
| +    PathHasOnlyMoveToTester tester; | 
| +    CGPathApply(m_path, &tester, PathHasOnlyMoveToTester::testPathElement); | 
| +    if (tester.hasOnlyMoveTo()) | 
| +        return FloatRect(0, 0, 0, 0); | 
| + | 
| #if !defined(BUILDING_ON_LEOPARD) | 
| return CGPathGetPathBoundingBox(m_path); | 
| #else | 
| @@ -174,6 +235,14 @@ | 
|  | 
| FloatRect Path::fastBoundingRect() const | 
| { | 
| +    // A bug in CoreGraphics leads to an incorrect bound on paths containing only move-to elements | 
| +    // with a linecap style that is non-butt. All paths with only move-to elements (regardless of | 
| +    // linecap) are effectively empty for bounding purposes and here we make it so. | 
| +    PathHasOnlyMoveToTester tester; | 
| +    CGPathApply(m_path, &tester, PathHasOnlyMoveToTester::testPathElement); | 
| +    if (tester.hasOnlyMoveTo()) | 
| +        return FloatRect(0, 0, 0, 0); | 
| + | 
| return CGPathGetBoundingBox(m_path); | 
| } | 
|  | 
| @@ -252,12 +321,18 @@ | 
|  | 
| bool Path::isEmpty() const | 
| { | 
| -    return CGPathIsEmpty(m_path); | 
| +    // The SVG rendering code that uses this method relies on paths with a single move-to | 
| +    // element, and nothing else, as being empty. Until that code is refactored to avoid | 
| +    // the dependence on isEmpty, we match the behavior of other platforms. | 
| +    // When the SVG code is refactored, we could use CGPathIsEmpty(m_path); | 
| +    PathIsEmptyOrSingleMoveTester tester; | 
| +    CGPathApply(m_path, &tester, PathIsEmptyOrSingleMoveTester::testPathElement); | 
| +    return tester.isEmpty(); | 
| } | 
|  | 
| bool Path::hasCurrentPoint() const | 
| { | 
| -    return !isEmpty(); | 
| +    return !CGPathIsEmpty(m_path); | 
| } | 
|  | 
| FloatPoint Path::currentPoint() const | 
| @@ -311,7 +386,7 @@ | 
|  | 
| void Path::transform(const AffineTransform& transform) | 
| { | 
| -    if (transform.isIdentity() || isEmpty()) | 
| +    if (transform.isIdentity() || CGPathIsEmpty(m_path)) | 
| return; | 
|  | 
| CGMutablePathRef path = CGPathCreateMutable(); | 
|  |