aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/SkGpuDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/SkGpuDevice.cpp')
-rw-r--r--src/gpu/SkGpuDevice.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 10bcecf2ba..20afada017 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) {