| Index: src/gpu/SkGpuDevice.cpp | 
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp | 
| index 10bcecf2ba350c3b08e002f22815835d166288bd..20afada017dd0170b9a2184f683da6ef75b5e04c 100644 | 
| --- a/src/gpu/SkGpuDevice.cpp | 
| +++ b/src/gpu/SkGpuDevice.cpp | 
| @@ -692,12 +692,78 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint | 
| #include "SkMaskFilter.h" | 
|  | 
| /////////////////////////////////////////////////////////////////////////////// | 
| +void SkGpuDevice::drawStrokedLine(const SkPoint points[2], | 
| +                                  const SkDraw& draw, | 
| +                                  const SkPaint& origPaint) { | 
| +    ASSERT_SINGLE_OWNER | 
| +    GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawStrokedLine", fContext); | 
| +    CHECK_SHOULD_DRAW(draw); | 
| + | 
| +    // Adding support for round capping would require a GrDrawContext::fillRRectWithLocalMatrix | 
| +    // entry point | 
| +    SkASSERT(SkPaint::kRound_Cap != origPaint.getStrokeCap()); | 
| +    SkASSERT(SkPaint::kStroke_Style == origPaint.getStyle()); | 
| +    SkASSERT(!origPaint.getPathEffect()); | 
| +    SkASSERT(!origPaint.getMaskFilter()); | 
| + | 
| +    const SkScalar halfWidth = 0.5f * origPaint.getStrokeWidth(); | 
| +    SkASSERT(halfWidth > 0); | 
| + | 
| +    SkVector v = points[1] - points[0]; | 
| + | 
| +    SkScalar length = SkPoint::Normalize(&v); | 
| +    if (!length) { | 
| +        v.fX = 1.0f; | 
| +        v.fY = 0.0f; | 
| +    } | 
| + | 
| +    SkPaint newPaint(origPaint); | 
| +    newPaint.setStyle(SkPaint::kFill_Style); | 
| + | 
| +    SkScalar xtraLength = 0.0f; | 
| +    if (SkPaint::kButt_Cap != origPaint.getStrokeCap()) { | 
| +        xtraLength = halfWidth; | 
| +    } | 
| + | 
| +    SkPoint mid = points[0] + points[1]; | 
| +    mid.scale(0.5f); | 
| + | 
| +    SkRect rect = SkRect::MakeLTRB(mid.fX-halfWidth, mid.fY - 0.5f*length - xtraLength, | 
| +                                   mid.fX+halfWidth, mid.fY + 0.5f*length + xtraLength); | 
| +    SkMatrix m; | 
| +    m.setSinCos(v.fX, -v.fY, mid.fX, mid.fY); | 
| + | 
| +    SkMatrix local = m; | 
| + | 
| +    m.postConcat(*draw.fMatrix); | 
| + | 
| +    GrPaint grPaint; | 
| +    if (!SkPaintToGrPaint(this->context(), newPaint, m, | 
| +                          this->surfaceProps().isGammaCorrect(), &grPaint)) { | 
| +        return; | 
| +    } | 
| + | 
| +    fDrawContext->fillRectWithLocalMatrix(fClip, grPaint, m, rect, local); | 
| +} | 
|  | 
| void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, | 
| const SkPaint& paint, const SkMatrix* prePathMatrix, | 
| bool pathIsMutable) { | 
| ASSERT_SINGLE_OWNER | 
| if (!origSrcPath.isInverseFillType() && !paint.getPathEffect() && !prePathMatrix) { | 
| +        SkPoint points[2]; | 
| +        if (SkPaint::kStroke_Style == paint.getStyle() && paint.getStrokeWidth() > 0 && | 
| +            !paint.getMaskFilter() && SkPaint::kRound_Cap != paint.getStrokeCap() && | 
| +            draw.fMatrix->preservesRightAngles() && origSrcPath.isLine(points)) { | 
| +            // Path-based stroking looks better for thin rects | 
| +            SkScalar strokeWidth = draw.fMatrix->getMaxScale() * paint.getStrokeWidth(); | 
| +            if (strokeWidth > 0.9f) { | 
| +                // Round capping support is currently disabled b.c. it would require | 
| +                // a RRect batch that takes a localMatrix. | 
| +                this->drawStrokedLine(points, draw, paint); | 
| +                return; | 
| +            } | 
| +        } | 
| bool isClosed; | 
| SkRect rect; | 
| if (origSrcPath.isRect(&rect, &isClosed) && isClosed) { | 
|  |