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) { |