'<(skia_src_path)/gpu/GrClipMaskManager.cpp',
'<(skia_src_path)/gpu/GrContext.cpp',
'<(skia_src_path)/gpu/GrCoordTransform.cpp',
+ '<(skia_src_path)/gpu/GrDashLinePathRenderer.cpp',
+ '<(skia_src_path)/gpu/GrDashLinePathRenderer.h',
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.cpp',
'<(skia_src_path)/gpu/GrDefaultGeoProcFactory.h',
'<(skia_src_path)/gpu/GrDefaultPathRenderer.cpp',
'<(skia_src_path)/gpu/GrStencilAndCoverTextContext.h',
'<(skia_src_path)/gpu/GrStencilAttachment.cpp',
'<(skia_src_path)/gpu/GrStencilAttachment.h',
+ '<(skia_src_path)/gpu/GrStrokeInfo.cpp',
'<(skia_src_path)/gpu/GrStrokeInfo.h',
'<(skia_src_path)/gpu/GrTargetCommands.cpp',
'<(skia_src_path)/gpu/GrTargetCommands.h',
class GrStrokeInfo;
class GrSoftwarePathRenderer;
class SkGpuDevice;
-class SkStrokeRec;
class SK_API GrContext : public SkRefCnt {
public:
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool allowSW,
GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType,
GrPathRendererChain::StencilSupport* stencilSupport = NULL);
class GrDrawTarget;
class GrPathRenderer;
class GrPipelineBuilder;
+class GrStrokeInfo;
class SkMatrix;
class SkPath;
-class SkStrokeRec;
/**
* Keeps track of an ordered list of path renderers. When a path needs to be
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& rec,
+ const GrStrokeInfo& stroke,
DrawType drawType,
StencilSupport* stencilSupport);
#include "GrPathUtils.h"
#include "GrProcessor.h"
#include "GrPipelineBuilder.h"
+#include "GrStrokeInfo.h"
#include "SkGeometry.h"
#include "SkString.h"
-#include "SkStrokeRec.h"
#include "SkTraceEvent.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
return (target->caps()->shaderDerivativeSupport() && antiAlias &&
stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
GrColor color,
const SkMatrix& vm,
const SkPath& path,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) {
if (path.isEmpty()) {
return true;
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
protected:
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
};
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
// TODO: Support inverse fill
// TODO: Support strokes
if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInverseFillType()
- || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) {
+ || path.isVolatile() || !stroke.isFillStyle()) {
return false;
}
GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const {
+ const GrStrokeInfo&) const {
return GrPathRenderer::kNoSupport_StencilSupport;
}
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) {
// we've already bailed on inverse filled paths, so this is safe
if (path.isEmpty()) {
(void*)this);
}
- AADistanceFieldPathBatch::Geometry geometry(stroke);
+ AADistanceFieldPathBatch::Geometry geometry(stroke.getStrokeRec());
geometry.fPath = path;
geometry.fAntiAlias = antiAlias;
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
protected:
virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const override;
+ const GrStrokeInfo&) const override;
virtual bool onDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
private:
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
if (!antiAlias) {
return false;
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool) {
if (!fLinesIndexBuffer || !fQuadsIndexBuffer) {
SkDebugf("unable to allocate indices\n");
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
typedef SkTArray<SkPoint, true> PtArray;
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
private:
#include "GrAAHairLinePathRenderer.h"
#include "GrAAConvexPathRenderer.h"
#include "GrAADistanceFieldPathRenderer.h"
+#include "GrDashLinePathRenderer.h"
#include "GrTessellatingPathRenderer.h"
#if GR_STROKE_PATH_RENDERING
#include "../../experimental/StrokePathRenderer/GrStrokePathRenderer.h"
#endif
void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
+ chain->addPathRenderer(SkNEW_ARGS(GrDashLinePathRenderer, (ctx)))->unref();
+
#if GR_STROKE_PATH_RENDERING
chain->addPathRenderer(SkNEW(GrStrokePathRenderer))->unref();
#endif
#include "GrStencilAttachment.h"
#include "GrSWMaskHelper.h"
#include "SkRasterClip.h"
-#include "SkStrokeRec.h"
#include "SkTLazy.h"
#include "effects/GrConvexPolyEffect.h"
#include "effects/GrPorterDuffXferProcessor.h"
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& origPath,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool doAA) {
// the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
SkTCopyOnFirstWrite<SkPath> path(origPath);
// TODO: generalize this function so that when
// a clip gets complex enough it can just be done in SW regardless
// of whether it would invoke the GrSoftwarePathRenderer.
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
if (path.isInverseFillType()) {
path.toggleInverseFillType();
}
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
if (NULL == pr) {
GrPathRendererChain::DrawType type;
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
if (path.isInverseFillType()) {
path.toggleInverseFillType();
}
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
GrPathRendererChain::DrawType type = element->isAA() ?
GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
GrPathRendererChain::kStencilAndColor_DrawType;
// stencil with arbitrary stencil settings.
GrPathRenderer::StencilSupport stencilSupport;
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
SkRegion::Op op = element->getOp();
GrPathRenderer* pr = NULL;
}
GrColor color = paint.getColor();
- if (strokeInfo.isDashed()) {
- SkPoint pts[2];
- if (path.isLine(pts)) {
- AutoCheckFlush acf(this);
- GrPipelineBuilder pipelineBuilder;
- GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
- if (NULL == target) {
- return;
- }
-
- if (GrDashingEffect::DrawDashLine(fGpu, target, &pipelineBuilder, color, viewMatrix,
- pts, paint, strokeInfo)) {
- return;
- }
- }
-
- // Filter dashed path into new path with the dashing applied
- const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
- SkTLazy<SkPath> effectPath;
- GrStrokeInfo newStrokeInfo(strokeInfo, false);
- SkStrokeRec* stroke = newStrokeInfo.getStrokeRecPtr();
- if (SkDashPath::FilterDashPath(effectPath.init(), path, stroke, NULL, info)) {
- this->drawPath(rt, clip, paint, viewMatrix, *effectPath.get(), newStrokeInfo);
- return;
- }
-
- this->drawPath(rt, clip, paint, viewMatrix, path, newStrokeInfo);
- return;
- }
// Note that internalDrawPath may sw-rasterize the path into a scratch texture.
// Scratch textures can be recycled after they are returned to the texture
GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex());
- const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
-
- bool useCoverageAA = paint.isAntiAlias() &&
- !pipelineBuilder.getRenderTarget()->isMultisampled();
+ if (!strokeInfo.isDashed()) {
+ const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+ bool useCoverageAA = paint.isAntiAlias() &&
+ !pipelineBuilder.getRenderTarget()->isMultisampled();
- if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
- // Concave AA paths are expensive - try to avoid them for special cases
- SkRect rects[2];
+ if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
+ // Concave AA paths are expensive - try to avoid them for special cases
+ SkRect rects[2];
- if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeRec, rects)) {
- fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix, rects);
- return;
+ if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeRec,
+ rects)) {
+ fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix,
+ rects);
+ return;
+ }
}
- }
+ SkRect ovalRect;
+ bool isOval = path.isOval(&ovalRect);
- SkRect ovalRect;
- bool isOval = path.isOval(&ovalRect);
-
- if (!isOval || path.isInverseFillType() ||
- !fOvalRenderer->drawOval(target,
- &pipelineBuilder,
- color,
- viewMatrix,
- paint.isAntiAlias(),
- ovalRect,
- strokeRec)) {
- this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
- path, strokeInfo);
+ if (isOval && !path.isInverseFillType()) {
+ if (fOvalRenderer->drawOval(target,
+ &pipelineBuilder,
+ color,
+ viewMatrix,
+ paint.isAntiAlias(),
+ ovalRect,
+ strokeRec)) {
+ return;
+ }
+ }
}
+ this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
+ path, strokeInfo);
}
void GrContext::internalDrawPath(GrDrawTarget* target,
const SkPath* pathPtr = &path;
SkTLazy<SkPath> tmpPath;
- SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec());
+ const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
// Try a 1st time without stroking the path and without allowing the SW renderer
GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr,
- *stroke, false, type);
+ *strokeInfoPtr, false, type);
+
+ GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
+ if (NULL == pr && strokeInfo.isDashed()) {
+ // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
+ if (strokeInfo.applyDash(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
+ pathPtr = tmpPath.get();
+ if (pathPtr->isEmpty()) {
+ return;
+ }
+ strokeInfoPtr = &dashlessStrokeInfo;
+ }
+ pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
+ false, type);
+ }
if (NULL == pr) {
- if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, NULL)) {
- // It didn't work the 1st time, so try again with the stroked path
- stroke.writable()->setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
- if (stroke->applyToPath(tmpPath.init(), *pathPtr)) {
+ if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, NULL)) {
+ // It didn't work above, so try again with stroke converted to a fill.
+ if (!tmpPath.isValid()) {
+ tmpPath.init();
+ }
+ SkStrokeRec* strokeRec = dashlessStrokeInfo.getStrokeRecPtr();
+ strokeRec->setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
+ if (strokeRec->applyToPath(tmpPath.get(), *pathPtr)) {
pathPtr = tmpPath.get();
- stroke.writable()->setFillStyle();
if (pathPtr->isEmpty()) {
return;
}
+ strokeRec->setFillStyle();
+ strokeInfoPtr = &dashlessStrokeInfo;
}
}
// This time, allow SW renderer
- pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *stroke, true,
- type);
+ pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
+ true, type);
}
if (NULL == pr) {
return;
}
- pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *stroke, useCoverageAA);
+ pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA);
}
////////////////////////////////////////////////////////////////////////////////
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool allowSW,
GrPathRendererChain::DrawType drawType,
GrPathRendererChain::StencilSupport* stencilSupport) {
--- /dev/null
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDashLinePathRenderer.h"
+
+#include "GrGpu.h"
+#include "effects/GrDashingEffect.h"
+
+GrDashLinePathRenderer::GrDashLinePathRenderer(GrContext* context)
+ : fGpu(SkRef(context->getGpu())) {
+}
+
+GrDashLinePathRenderer::~GrDashLinePathRenderer() {
+}
+
+bool GrDashLinePathRenderer::canDrawPath(const GrDrawTarget* target,
+ const GrPipelineBuilder* pipelineBuilder,
+ const SkMatrix& viewMatrix,
+ const SkPath& path,
+ const GrStrokeInfo& stroke,
+ bool antiAlias) const {
+ SkPoint pts[2];
+ if (stroke.isDashed() && path.isLine(pts)) {
+ return GrDashingEffect::CanDrawDashLine(pts, stroke, viewMatrix);
+ }
+ return false;
+}
+
+bool GrDashLinePathRenderer::onDrawPath(GrDrawTarget* target,
+ GrPipelineBuilder* pipelineBuilder,
+ GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkPath& path,
+ const GrStrokeInfo& stroke,
+ bool useAA) {
+ SkPoint pts[2];
+ SkAssertResult(path.isLine(pts));
+ return GrDashingEffect::DrawDashLine(fGpu, target, pipelineBuilder, color,
+ viewMatrix, pts, useAA, stroke);
+}
--- /dev/null
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDashLinePathRenderer_DEFINED
+#define GrDashLinePathRenderer_DEFINED
+
+#include "GrPathRenderer.h"
+
+class GrDashLinePathRenderer : public GrPathRenderer {
+public:
+ GrDashLinePathRenderer(GrContext*);
+ ~GrDashLinePathRenderer();
+
+ bool canDrawPath(const GrDrawTarget*,
+ const GrPipelineBuilder*,
+ const SkMatrix& viewMatrix,
+ const SkPath&,
+ const GrStrokeInfo&,
+ bool antiAlias) const override;
+
+protected:
+ StencilSupport onGetStencilSupport(const GrDrawTarget*,
+ const GrPipelineBuilder*,
+ const SkPath&,
+ const GrStrokeInfo&) const override {
+ return kNoSupport_StencilSupport;
+ }
+
+ bool onDrawPath(GrDrawTarget*,
+ GrPipelineBuilder*,
+ GrColor,
+ const SkMatrix& viewMatrix,
+ const SkPath&,
+ const GrStrokeInfo&,
+ bool antiAlias) override;
+ SkAutoTUnref<GrGpu> fGpu;
+ typedef GrPathRenderer INHERITED;
+};
+
+
+#endif
GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath& path,
- const SkStrokeRec& stroke) const {
- if (single_pass_path(path, stroke)) {
+ const GrStrokeInfo& stroke) const {
+ if (single_pass_path(path, stroke.getStrokeRec())) {
return GrPathRenderer::kNoRestriction_StencilSupport;
} else {
return GrPathRenderer::kStencilOnly_StencilSupport;
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& origStroke,
+ const GrStrokeInfo& origStroke,
bool stencilOnly) {
- SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
+ SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
SkScalar hairlineCoverage;
uint8_t newCoverage = 0xff;
if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) {
newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
- if (!stroke->isHairlineStyle()) {
- stroke.writable()->setHairlineStyle();
+ if (!stroke->getStrokeRec().isHairlineStyle()) {
+ stroke.writable()->getStrokeRecPtr()->setHairlineStyle();
}
}
- const bool isHairline = stroke->isHairlineStyle();
+ const bool isHairline = stroke->getStrokeRec().isHairlineStyle();
// Save the current xp on the draw state so we can reset it if needed
SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXPFactory()));
lastPassIsBounds = false;
drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
} else {
- if (single_pass_path(path, *stroke)) {
+ if (single_pass_path(path, stroke->getStrokeRec())) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
// this class can draw any path with any fill but doesn't do any anti-aliasing.
return !antiAlias && (stroke.isFillStyle() || IsStrokeHairlineOrEquivalent(stroke,
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) {
return this->internalDrawPath(target,
pipelineBuilder,
GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& stroke) {
SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType());
SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType());
this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, path, stroke, true);
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
private:
virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const override;
+ const GrStrokeInfo&) const override;
virtual bool onDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
virtual void onStencilPath(GrDrawTarget*,
GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&) override;
+ const GrStrokeInfo&) override;
bool internalDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool stencilOnly);
bool fSeparateStencil;
#include "GrDrawTarget.h"
#include "GrPathRendererChain.h"
#include "GrStencil.h"
+#include "GrStrokeInfo.h"
#include "SkDrawProcs.h"
-#include "SkStrokeRec.h"
#include "SkTArray.h"
class SkPath;
StencilSupport getStencilSupport(const GrDrawTarget* target,
const GrPipelineBuilder* pipelineBuilder,
const SkPath& path,
- const SkStrokeRec& stroke) const {
+ const GrStrokeInfo& stroke) const {
SkASSERT(!path.isInverseFillType());
return this->onGetStencilSupport(target, pipelineBuilder, path, stroke);
}
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& rec,
+ const GrStrokeInfo& rec,
bool antiAlias) const = 0;
/**
* Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) {
SkASSERT(!path.isEmpty());
SkASSERT(this->canDrawPath(target, ds, viewMatrix, path, stroke, antiAlias));
GrPipelineBuilder* ds,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& stroke) {
SkASSERT(!path.isEmpty());
SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(target, ds, path, stroke));
this->onStencilPath(target, ds, viewMatrix, path, stroke);
// Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
// If we can, we draw lots faster (raster device does this same test).
- static bool IsStrokeHairlineOrEquivalent(const SkStrokeRec& stroke, const SkMatrix& matrix,
+ static bool IsStrokeHairlineOrEquivalent(const GrStrokeInfo& stroke, const SkMatrix& matrix,
SkScalar* outCoverage) {
- if (stroke.isHairlineStyle()) {
+ if (stroke.isDashed()) {
+ return false;
+ }
+ if (stroke.getStrokeRec().isHairlineStyle()) {
if (outCoverage) {
*outCoverage = SK_Scalar1;
}
return true;
}
- return stroke.getStyle() == SkStrokeRec::kStroke_Style &&
- SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage);
+ return stroke.getStrokeRec().getStyle() == SkStrokeRec::kStroke_Style &&
+ SkDrawTreatAAStrokeAsHairline(stroke.getStrokeRec().getWidth(), matrix, outCoverage);
}
protected:
virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const {
+ const GrStrokeInfo&) const {
return kNoRestriction_StencilSupport;
}
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) = 0;
/**
GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& stroke) {
GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,
kReplace_StencilOp,
kReplace_StencilOp,
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
DrawType drawType,
StencilSupport* stencilSupport) {
if (!fInit) {
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
if (NULL == fContext) {
return false;
}
-
+ if (stroke.isDashed()) {
+ return false;
+ }
return true;
}
GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const {
+ const GrStrokeInfo&) const {
return GrPathRenderer::kNoSupport_StencilSupport;
}
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) {
-
if (NULL == fContext) {
return false;
}
}
SkAutoTUnref<GrTexture> texture(
- GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
+ GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke.getStrokeRec(),
devPathBounds,
antiAlias, &viewMatrix));
if (NULL == texture) {
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
protected:
virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const override;
+ const GrStrokeInfo&) const override;
virtual bool onDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
private:
#include "GrPath.h"
#include "GrRenderTarget.h"
#include "GrRenderTargetPriv.h"
-#include "SkStrokeRec.h"
+#include "GrStrokeInfo.h"
/*
* For now paths only natively support winding and even odd fill types
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
- return !stroke.isHairlineStyle() &&
- !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
- pipelineBuilder->getStencil().isDisabled();
+ return !stroke.getStrokeRec().isHairlineStyle() &&
+ !stroke.isDashed() &&
+ !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
+ pipelineBuilder->getStencil().isDisabled();
}
GrPathRenderer::StencilSupport
GrStencilAndCoverPathRenderer::onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const {
+ const GrStrokeInfo&) const {
return GrPathRenderer::kStencilOnly_StencilSupport;
}
GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& stroke) {
SkASSERT(!path.isInverseFillType());
SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(GrColor_WHITE, viewMatrix));
- SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
+ SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke.getStrokeRec()));
target->stencilPath(pipelineBuilder, pp, p, convert_skpath_filltype(path.getFillType()));
}
GrColor color,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) {
SkASSERT(!antiAlias);
- SkASSERT(!stroke.isHairlineStyle());
-
+ SkASSERT(!stroke.getStrokeRec().isHairlineStyle());
+ SkASSERT(!stroke.isDashed());
SkASSERT(pipelineBuilder->getStencil().isDisabled());
- SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
+ SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke.getStrokeRec()));
if (path.isInverseFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
const GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
protected:
virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const override;
+ const GrStrokeInfo&) const override;
virtual bool onDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
virtual void onStencilPath(GrDrawTarget*,
GrPipelineBuilder*,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&) override;
+ const GrStrokeInfo&) override;
private:
GrStencilAndCoverPathRenderer(GrGpu*);
--- /dev/null
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrStrokeInfo.h"
+
+#include "SkDashPathPriv.h"
+
+bool GrStrokeInfo::applyDash(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const {
+ if (this->isDashed()) {
+ const SkPathEffect::DashInfo& info = this->getDashInfo();
+ SkStrokeRec strokeRec = fStroke;
+ if (SkDashPath::FilterDashPath(dst, src, &strokeRec, NULL, info)) {
+ dstStrokeInfo->fStroke = strokeRec;
+ dstStrokeInfo->removeDash();
+ return true;
+ }
+ }
+ return false;
+}
this->init(paint);
}
+ GrStrokeInfo& operator=(const GrStrokeInfo& other) {
+ fStroke = other.fStroke;
+ fDashInfo = other.fDashInfo;
+ fDashType = other.fDashType;
+ fIntervals.reset(other.dashCount());
+ memcpy(fIntervals.get(), other.fIntervals.get(), other.dashCount() * sizeof(SkScalar));
+ return *this;
+ }
+
const SkStrokeRec& getStrokeRec() const { return fStroke; }
SkStrokeRec* getStrokeRecPtr() { return &fStroke; }
return (!fStroke.isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
}
+ bool isFillStyle() const { return fStroke.isFillStyle(); }
+
int32_t dashCount() const {
return fDashInfo.fCount;
}
const SkPathEffect::DashInfo& getDashInfo() const { return fDashInfo; }
+ /** Applies the dash to a path, if the stroke info has dashing.
+ * @return true if the dash ingwas applied (dst and dstStrokeInfo will be modified).
+ * false if the stroke info did not have dashing. The dst and dstStrokeInfo
+ * will be unmodified. The stroking in the SkStrokeRec might still
+ * be applicable.
+ */
+ bool applyDash(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const;
+
private:
void init(const SkPaint& paint) {
const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const {
+ const GrStrokeInfo&) const {
return GrPathRenderer::kNoSupport_StencilSupport;
}
const GrPipelineBuilder* pipelineBuilder,
const SkMatrix& viewMatrix,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& stroke,
bool antiAlias) const {
// This path renderer can draw all fill styles, but does not do antialiasing. It can do convex
// and concave paths, but we'll leave the convex ones to simpler algorithms.
GrColor color,
const SkMatrix& viewM,
const SkPath& path,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo&,
bool antiAlias) {
SkASSERT(!antiAlias);
const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
const GrPipelineBuilder*,
const SkMatrix&,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) const override;
protected:
StencilSupport onGetStencilSupport(const GrDrawTarget*,
const GrPipelineBuilder*,
const SkPath&,
- const SkStrokeRec&) const override;
+ const GrStrokeInfo&) const override;
bool onDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
const SkPath&,
- const SkStrokeRec&,
+ const GrStrokeInfo&,
bool antiAlias) override;
typedef GrPathRenderer INHERITED;
///////////////////////////////////////////////////////////////////////////////
// Returns whether or not the gpu can fast path the dash line effect.
-static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
- const GrDrawTarget& target, const GrPipelineBuilder& pipelineBuilder,
- const SkMatrix& viewMatrix) {
+bool GrDashingEffect::CanDrawDashLine(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
+ const SkMatrix& viewMatrix) {
// Pts must be either horizontal or vertical in src space
if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) {
return false;
bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
GrPipelineBuilder* pipelineBuilder, GrColor color,
const SkMatrix& viewMatrix, const SkPoint pts[2],
- const GrPaint& paint, const GrStrokeInfo& strokeInfo) {
- if (!can_fast_path_dash(pts, strokeInfo, *target, *pipelineBuilder, viewMatrix)) {
- return false;
- }
-
+ bool useAA, const GrStrokeInfo& strokeInfo) {
const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
}
DashAAMode aaMode = pipelineBuilder->getRenderTarget()->isMultisampled() ? kMSAA_DashAAMode :
- paint.isAntiAlias() ? kEdgeAA_DashAAMode :
- kBW_DashAAMode;
+ useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode;
// TODO we can do a real rect call if not using fulldash(ie no off interval, not using AA)
bool fullDash = offInterval > 0.f || aaMode != kBW_DashAAMode;
namespace GrDashingEffect {
bool DrawDashLine(GrGpu*, GrDrawTarget*, GrPipelineBuilder*, GrColor,
- const SkMatrix& viewMatrix, const SkPoint pts[2], const GrPaint& paint,
+ const SkMatrix& viewMatrix, const SkPoint pts[2], bool useAA,
const GrStrokeInfo& strokeInfo);
+ bool CanDrawDashLine(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
+ const SkMatrix& viewMatrix);
}
#endif
GrTessellatingPathRenderer tess;
GrPipelineBuilder pipelineBuilder;
pipelineBuilder.setRenderTarget(rt);
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
tess.drawPath(dt, &pipelineBuilder, SK_ColorWHITE, SkMatrix::I(), path, stroke, false);
}