Follow up on the previous patch :

- Moved the SkStrokeRec class in its own file
- Replaced SkStroke by SkStrokeRec in Ganesh
- Moved path stroking to the Ganesh level in some cases (everytime it isn't required to do it directly in SkGpuDevice). PathEffect and MaskFilter still require path stroking at the SkGpuDevice for now.
- Renamed static functions in SkPath with proper names

* No functionality shold have changed with this patch. This is a step towards enabling Ganesh Path Renderers to decide whether or not to stroke the path rather than always receiving the stroked path as an input argument.

BUG=chromium:135111
TEST=Try path rendering tests from the gm
Review URL: https://codereview.appspot.com/6946072

git-svn-id: http://skia.googlecode.com/svn/trunk@6861 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
sugoi@google.com 2012-12-17 21:16:45 +00:00
parent 9f6a557548
commit 5f74cf8c49
35 changed files with 369 additions and 328 deletions

View File

@ -158,6 +158,7 @@
'<(skia_src_path)/core/SkString.cpp',
'<(skia_src_path)/core/SkStroke.h',
'<(skia_src_path)/core/SkStroke.cpp',
'<(skia_src_path)/core/SkStrokeRec.cpp',
'<(skia_src_path)/core/SkStrokerPriv.cpp',
'<(skia_src_path)/core/SkStrokerPriv.h',
'<(skia_src_path)/core/SkTemplatesPriv.h',
@ -251,6 +252,7 @@
'<(skia_include_path)/core/SkShader.h',
'<(skia_include_path)/core/SkStream.h',
'<(skia_include_path)/core/SkString.h',
'<(skia_include_path)/core/SkStrokeRec.h',
'<(skia_include_path)/core/SkTArray.h',
'<(skia_include_path)/core/SkTDArray.h',
'<(skia_include_path)/core/SkTDStack.h',

View File

@ -89,7 +89,7 @@ public:
}
/** Returns true if the filltype is one of the Inverse variants */
bool isInverseFillType() const { return IsInverseFill((FillType)fFillType); }
bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
/**
* Toggle between inverse and normal filltypes. This reverse the return
@ -524,8 +524,13 @@ public:
/**
* Returns whether or not a fill type is inverted
*
* kWinding_FillType -> false
* kEvenOdd_FillType -> false
* kInverseWinding_FillType -> true
* kInverseEvenOdd_FillType -> true
*/
static bool IsInverseFill(FillType fill) {
static bool IsInverseFillType(FillType fill) {
SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
@ -535,8 +540,13 @@ public:
/**
* Returns the equivalent non-inverted fill type to the given fill type
*
* kWinding_FillType -> kWinding_FillType
* kEvenOdd_FillType -> kEvenOdd_FillType
* kInverseWinding_FillType -> kWinding_FillType
* kInverseEvenOdd_FillType -> kEvenOdd_FillType
*/
static FillType NonInverseFill(FillType fill) {
static FillType ConvertToNonInverseFillType(FillType fill) {
SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);

View File

@ -11,91 +11,14 @@
#define SkPathEffect_DEFINED
#include "SkFlattenable.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkStrokeRec.h"
#include "SkTDArray.h"
class SkPath;
class SkStrokeRec {
public:
enum InitStyle {
kHairline_InitStyle,
kFill_InitStyle
};
SkStrokeRec(InitStyle style);
SkStrokeRec(const SkStrokeRec&);
explicit SkStrokeRec(const SkPaint&);
enum Style {
kHairline_Style,
kFill_Style,
kStroke_Style,
kStrokeAndFill_Style
};
Style getStyle() const;
SkScalar getWidth() const { return fWidth; }
SkScalar getMiter() const { return fMiterLimit; }
SkPaint::Cap getCap() const { return fCap; }
SkPaint::Join getJoin() const { return fJoin; }
bool isHairlineStyle() const {
return kHairline_Style == this->getStyle();
}
bool isFillStyle() const {
return kFill_Style == this->getStyle();
}
void setFillStyle();
void setHairlineStyle();
/**
* Specify the strokewidth, and optionally if you want stroke + fill.
* Note, if width==0, then this request is taken to mean:
* strokeAndFill==true -> new style will be Fill
* strokeAndFill==false -> new style will be Hairline
*/
void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
fCap = cap;
fJoin = join;
fMiterLimit = miterLimit;
}
/**
* Returns true if this specifes any thick stroking, i.e. applyToPath()
* will return true.
*/
bool needToApply() const {
Style style = this->getStyle();
return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
}
/**
* Apply these stroke parameters to the src path, returning the result
* in dst.
*
* If there was no change (i.e. style == hairline or fill) this returns
* false and dst is unchanged. Otherwise returns true and the result is
* stored in dst.
*
* src and dst may be the same path.
*/
bool applyToPath(SkPath* dst, const SkPath& src) const;
private:
SkScalar fWidth;
SkScalar fMiterLimit;
SkPaint::Cap fCap;
SkPaint::Join fJoin;
bool fStrokeAndFill;
};
/** \class SkPathEffect
SkPathEffect is the base class for objects in the SkPaint that affect

View File

@ -0,0 +1,92 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkStrokeRec_DEFINED
#define SkStrokeRec_DEFINED
#include "SkPaint.h"
class SkPath;
class SkStrokeRec {
public:
enum InitStyle {
kHairline_InitStyle,
kFill_InitStyle
};
SkStrokeRec(InitStyle style);
SkStrokeRec(const SkStrokeRec&);
explicit SkStrokeRec(const SkPaint&);
enum Style {
kHairline_Style,
kFill_Style,
kStroke_Style,
kStrokeAndFill_Style
};
Style getStyle() const;
SkScalar getWidth() const { return fWidth; }
SkScalar getMiter() const { return fMiterLimit; }
SkPaint::Cap getCap() const { return fCap; }
SkPaint::Join getJoin() const { return fJoin; }
bool isHairlineStyle() const {
return kHairline_Style == this->getStyle();
}
bool isFillStyle() const {
return kFill_Style == this->getStyle();
}
void setFillStyle();
void setHairlineStyle();
/**
* Specify the strokewidth, and optionally if you want stroke + fill.
* Note, if width==0, then this request is taken to mean:
* strokeAndFill==true -> new style will be Fill
* strokeAndFill==false -> new style will be Hairline
*/
void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
fCap = cap;
fJoin = join;
fMiterLimit = miterLimit;
}
/**
* Returns true if this specifes any thick stroking, i.e. applyToPath()
* will return true.
*/
bool needToApply() const {
Style style = this->getStyle();
return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
}
/**
* Apply these stroke parameters to the src path, returning the result
* in dst.
*
* If there was no change (i.e. style == hairline or fill) this returns
* false and dst is unchanged. Otherwise returns true and the result is
* stored in dst.
*
* src and dst may be the same path.
*/
bool applyToPath(SkPath* dst, const SkPath& src) const;
private:
SkScalar fWidth;
SkScalar fMiterLimit;
SkPaint::Cap fCap;
SkPaint::Join fJoin;
bool fStrokeAndFill;
};
#endif

View File

@ -39,7 +39,7 @@ class GrTextureParams;
class GrVertexBuffer;
class GrVertexBufferAllocPool;
class GrSoftwarePathRenderer;
class SkStroke;
class SkStrokeRec;
class GR_API GrContext : public GrRefCnt {
public:
@ -411,9 +411,9 @@ public:
*
* @param paint describes how to color pixels.
* @param path the path to draw
* @param doHairLine whether the stroke can be optimized as a hairline
* @param stroke the stroke information (width, join, cap)
*/
void drawPath(const GrPaint& paint, const SkPath& path, bool doHairLine);
void drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke);
/**
* Draws vertices with a paint.
@ -846,7 +846,7 @@ public:
GrPathRenderer* getPathRenderer(
const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool allowSW,
GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType,
@ -910,7 +910,7 @@ private:
/// draw state is left unmodified.
GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw);
void internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStroke& stroke);
void internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke);
GrTexture* createResizedTexture(const GrTextureDesc& desc,
const GrCacheData& cacheData,

View File

@ -17,7 +17,7 @@ class GrContext;
class GrDrawTarget;
class GrPathRenderer;
class SkPath;
class SkStroke;
class SkStrokeRec;
/**
* Keeps track of an ordered list of path renderers. When a path needs to be
@ -58,7 +58,7 @@ public:
whether the path can be rendered with arbitrary stencil rules or not. See comments on
StencilSupport in GrPathRenderer.h. */
GrPathRenderer* getPathRenderer(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& rec,
const GrDrawTarget* target,
DrawType drawType,
StencilSupport* stencilSupport);

View File

@ -6,107 +6,9 @@
* found in the LICENSE file.
*/
#include "SkPathEffect.h"
#include "SkPath.h"
#include "SkFlattenableBuffers.h"
#include "SkPaintDefaults.h"
// must be < 0, since ==0 means hairline, and >0 means normal stroke
#define kStrokeRec_FillStyleWidth (-SK_Scalar1)
SkStrokeRec::SkStrokeRec(InitStyle s) {
fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
fMiterLimit = SkPaintDefaults_MiterLimit;
fCap = SkPaint::kDefault_Cap;
fJoin = SkPaint::kDefault_Join;
fStrokeAndFill = false;
}
SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
memcpy(this, &src, sizeof(src));
}
SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
switch (paint.getStyle()) {
case SkPaint::kFill_Style:
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
break;
case SkPaint::kStroke_Style:
fWidth = paint.getStrokeWidth();
fStrokeAndFill = false;
break;
case SkPaint::kStrokeAndFill_Style:
if (0 == paint.getStrokeWidth()) {
// hairline+fill == fill
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
} else {
fWidth = paint.getStrokeWidth();
fStrokeAndFill = true;
}
break;
default:
SkASSERT(!"unknown paint style");
// fall back on just fill
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
break;
}
// copy these from the paint, regardless of our "style"
fMiterLimit = paint.getStrokeMiter();
fCap = paint.getStrokeCap();
fJoin = paint.getStrokeJoin();
}
SkStrokeRec::Style SkStrokeRec::getStyle() const {
if (fWidth < 0) {
return kFill_Style;
} else if (0 == fWidth) {
return kHairline_Style;
} else {
return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
}
}
void SkStrokeRec::setFillStyle() {
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
}
void SkStrokeRec::setHairlineStyle() {
fWidth = 0;
fStrokeAndFill = false;
}
void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
if (strokeAndFill && (0 == width)) {
// hairline+fill == fill
this->setFillStyle();
} else {
fWidth = width;
fStrokeAndFill = strokeAndFill;
}
}
#include "SkStroke.h"
bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
if (fWidth <= 0) { // hairline or fill
return false;
}
SkStroke stroker;
stroker.setCap(fCap);
stroker.setJoin(fJoin);
stroker.setMiterLimit(fMiterLimit);
stroker.setWidth(fWidth);
stroker.setDoFill(fStrokeAndFill);
stroker.strokePath(src, dst);
return true;
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -643,7 +643,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
// kDrawComplete will be the signal that we have reached the end of
// the command stream
static const int kDrawComplete = SK_MaxU32;
static const uint32_t kDrawComplete = SK_MaxU32;
SkReader32 reader(fOpData->bytes(), fOpData->size());
TextContainer text;

View File

@ -32,7 +32,6 @@ public:
void setMiterLimit(SkScalar);
void setWidth(SkScalar);
SkScalar getWidthIfStroked() const { return fDoFill ? -SK_Scalar1 : fWidth; }
bool getDoFill() const { return SkToBool(fDoFill); }
void setDoFill(bool doFill) { fDoFill = SkToU8(doFill); }

106
src/core/SkStrokeRec.cpp Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkStrokeRec.h"
#include "SkPaintDefaults.h"
// must be < 0, since ==0 means hairline, and >0 means normal stroke
#define kStrokeRec_FillStyleWidth (-SK_Scalar1)
SkStrokeRec::SkStrokeRec(InitStyle s) {
fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
fMiterLimit = SkPaintDefaults_MiterLimit;
fCap = SkPaint::kDefault_Cap;
fJoin = SkPaint::kDefault_Join;
fStrokeAndFill = false;
}
SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
memcpy(this, &src, sizeof(src));
}
SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
switch (paint.getStyle()) {
case SkPaint::kFill_Style:
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
break;
case SkPaint::kStroke_Style:
fWidth = paint.getStrokeWidth();
fStrokeAndFill = false;
break;
case SkPaint::kStrokeAndFill_Style:
if (0 == paint.getStrokeWidth()) {
// hairline+fill == fill
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
} else {
fWidth = paint.getStrokeWidth();
fStrokeAndFill = true;
}
break;
default:
SkASSERT(!"unknown paint style");
// fall back on just fill
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
break;
}
// copy these from the paint, regardless of our "style"
fMiterLimit = paint.getStrokeMiter();
fCap = paint.getStrokeCap();
fJoin = paint.getStrokeJoin();
}
SkStrokeRec::Style SkStrokeRec::getStyle() const {
if (fWidth < 0) {
return kFill_Style;
} else if (0 == fWidth) {
return kHairline_Style;
} else {
return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
}
}
void SkStrokeRec::setFillStyle() {
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
}
void SkStrokeRec::setHairlineStyle() {
fWidth = 0;
fStrokeAndFill = false;
}
void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
if (strokeAndFill && (0 == width)) {
// hairline+fill == fill
this->setFillStyle();
} else {
fWidth = width;
fStrokeAndFill = strokeAndFill;
}
}
#include "SkStroke.h"
bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
if (fWidth <= 0) { // hairline or fill
return false;
}
SkStroke stroker;
stroker.setCap(fCap);
stroker.setJoin(fJoin);
stroker.setMiterLimit(fMiterLimit);
stroker.setWidth(fWidth);
stroker.setDoFill(fStrokeAndFill);
stroker.strokePath(src, dst);
return true;
}

View File

@ -12,7 +12,7 @@
#include "GrDrawState.h"
#include "GrPathUtils.h"
#include "SkString.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
#include "SkTrace.h"
GrAAConvexPathRenderer::GrAAConvexPathRenderer() {
@ -429,15 +429,15 @@ void create_vertices(const SegmentArray& segments,
}
bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const {
return (target->getCaps().shaderDerivativeSupport() && antiAlias &&
stroke.getDoFill() && !path.isInverseFillType() && path.isConvex());
stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
}
bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget* target,
bool antiAlias) {

View File

@ -14,13 +14,13 @@ public:
GrAAConvexPathRenderer();
virtual bool canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const SK_OVERRIDE;
protected:
virtual bool onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) SK_OVERRIDE;
};

View File

@ -547,10 +547,10 @@ bool GrAAHairLinePathRenderer::createGeom(
}
bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const {
if ((0 != stroke.getWidthIfStroked()) || !antiAlias) {
if (!stroke.isHairlineStyle() || !antiAlias) {
return false;
}
@ -564,7 +564,7 @@ bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
}
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget* target,
bool antiAlias) {

View File

@ -18,13 +18,13 @@ public:
static GrPathRenderer* Create(GrContext* context);
virtual bool canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const SK_OVERRIDE;
protected:
virtual bool onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) SK_OVERRIDE;

View File

@ -10,7 +10,6 @@
#include "GrStencilAndCoverPathRenderer.h"
#include "GrAAHairLinePathRenderer.h"
#include "GrAAConvexPathRenderer.h"
#include "GrSoftwarePathRenderer.h"
void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) {

View File

@ -14,7 +14,7 @@
#include "GrPathRenderer.h"
#include "GrPaint.h"
#include "SkRasterClip.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
#include "GrAAConvexPathRenderer.h"
#include "GrAAHairLinePathRenderer.h"
#include "GrSWMaskHelper.h"
@ -62,7 +62,7 @@ void setup_drawstate_aaclip(GrGpu* gpu,
bool path_needs_SW_renderer(GrContext* context,
GrGpu* gpu,
const SkPath& origPath,
const SkStroke& stroke,
const SkStrokeRec& stroke,
bool doAA) {
// the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
SkTCopyOnFirstWrite<SkPath> path(origPath);
@ -89,8 +89,7 @@ bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
// 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.
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
const Element* element = iter.get();
@ -270,12 +269,11 @@ bool draw_path_in_software(GrContext* context,
const SkPath& path,
bool doAA,
const GrIRect& resultBounds) {
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
SkAutoTUnref<GrTexture> texture(
GrSWMaskHelper::DrawPathMaskToTexture(context, path,
stroke,
rec,
resultBounds,
doAA, NULL));
if (NULL == texture) {
@ -318,8 +316,7 @@ bool GrClipMaskManager::drawElement(GrTexture* target,
if (path->isInverseFillType()) {
path.writable()->toggleInverseFillType();
}
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
if (NULL == pr) {
GrPathRendererChain::DrawType type;
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
@ -354,8 +351,7 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target,
if (path->isInverseFillType()) {
path.writable()->toggleInverseFillType();
}
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
GrPathRendererChain::DrawType type = element->isAA() ?
GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
GrPathRendererChain::kStencilAndColor_DrawType;
@ -660,8 +656,7 @@ bool GrClipMaskManager::createStencilClipMask(InitialState initialState,
// stencil with arbitrary stencil settings.
GrPathRenderer::StencilSupport stencilSupport;
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
SkRegion::Op op = element->getOp();
@ -975,8 +970,7 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t clipStackGenID,
helper.clear(kAllIn_InitialState == initialState ? 0xFF : 0x00);
SkStroke stroke;
stroke.setDoFill(true);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
for (ElementList::Iter iter(elements.headIter()) ; NULL != iter.get(); iter.next()) {

View File

@ -23,10 +23,10 @@
#include "GrSoftwarePathRenderer.h"
#include "GrStencilBuffer.h"
#include "GrTextStrike.h"
#include "SkStrokeRec.h"
#include "SkTLazy.h"
#include "SkTLS.h"
#include "SkTrace.h"
#include "SkStroke.h"
SK_DEFINE_INST_COUNT(GrContext)
SK_DEFINE_INST_COUNT(GrDrawState)
@ -720,7 +720,7 @@ void GrContext::drawRect(const GrPaint& paint,
return;
}
if (width >= 0) {
GrVec strokeSize;;
GrVec strokeSize;
if (width > 0) {
strokeSize.set(width, width);
combinedMatrix.mapVectors(&strokeSize, 1);
@ -982,11 +982,10 @@ void GrContext::drawOval(const GrPaint& paint,
SkPath path;
path.addOval(rect);
path.setFillType(SkPath::kWinding_FillType);
SkStroke stroke;
if (strokeWidth < 0) {
stroke.setDoFill(true);
} else {
stroke.setWidth(strokeWidth);
SkStrokeRec stroke(0 == strokeWidth ? SkStrokeRec::kHairline_InitStyle :
SkStrokeRec::kFill_InitStyle);
if (strokeWidth > 0) {
stroke.setStrokeStyle(strokeWidth, true);
}
this->internalDrawPath(paint, path, stroke);
return;
@ -1058,7 +1057,7 @@ void GrContext::drawOval(const GrPaint& paint,
target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
}
void GrContext::drawPath(const GrPaint& paint, const SkPath& path, bool doHairLine) {
void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
if (path.isEmpty()) {
if (path.isInverseFillType()) {
@ -1067,24 +1066,27 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, bool doHairLi
return;
}
const SkPath* pathPtr = &path;
SkPath tmpPath;
SkStrokeRec strokeRec(stroke);
if (!strokeRec.isHairlineStyle()) {
if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
pathPtr = &tmpPath;
strokeRec.setFillStyle();
}
}
SkRect ovalRect;
if (!path.isInverseFillType() && path.isOval(&ovalRect)) {
SkScalar width = doHairLine ? 0 : -SK_Scalar1;
if (!pathPtr->isInverseFillType() && pathPtr->isOval(&ovalRect)) {
SkScalar width = strokeRec.isHairlineStyle() ? 0 : -SK_Scalar1;
this->drawOval(paint, ovalRect, width);
return;
}
SkStroke stroke;
if (doHairLine) {
stroke.setWidth(0);
} else {
stroke.setDoFill(true);
}
this->internalDrawPath(paint, path, stroke);
this->internalDrawPath(paint, *pathPtr, strokeRec);
}
void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStroke& stroke) {
void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
// Note that below we may sw-rasterize the path into a scratch texture.
// Scratch textures can be recycled after they are returned to the texture
@ -1616,7 +1618,7 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffer
* can be individually allowed/disallowed via the "allowSW" boolean.
*/
GrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool allowSW,
GrPathRendererChain::DrawType drawType,

View File

@ -12,7 +12,7 @@
#include "GrDrawState.h"
#include "GrPathUtils.h"
#include "SkString.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
#include "SkTrace.h"
@ -151,11 +151,11 @@ GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
#define STENCIL_OFF 0 // Always disable stencil (even when needed)
static inline bool single_pass_path(const SkPath& path, const SkStroke& stroke) {
static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) {
#if STENCIL_OFF
return true;
#else
if ((0 != stroke.getWidthIfStroked()) && !path.isInverseFillType()) {
if (!stroke.isHairlineStyle() && !path.isInverseFillType()) {
return path.isConvex();
}
return false;
@ -164,7 +164,7 @@ static inline bool single_pass_path(const SkPath& path, const SkStroke& stroke)
GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport(
const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget*) const {
if (single_pass_path(path, stroke)) {
return GrPathRenderer::kNoRestriction_StencilSupport;
@ -188,7 +188,7 @@ static inline void append_countour_edge_indices(bool hairLine,
}
bool GrDefaultPathRenderer::createGeom(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
SkScalar srcSpaceTol,
GrDrawTarget* target,
GrPrimitiveType* primType,
@ -214,7 +214,7 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path,
GrVertexLayout layout = 0;
bool indexed = contourCnt > 1;
const bool isHairline = 0 == stroke.getWidthIfStroked();
const bool isHairline = stroke.isHairlineStyle();
int maxIdxs = 0;
if (isHairline) {
@ -238,7 +238,7 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path,
return false;
}
uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());;
uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());
uint16_t* idx = idxBase;
uint16_t subpathIdxStart = 0;
@ -324,7 +324,7 @@ FINISHED:
}
bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool stencilOnly) {
@ -360,7 +360,7 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
bool reverse = false;
bool lastPassIsBounds;
if (0 == stroke.getWidthIfStroked()) {
if (stroke.isHairlineStyle()) {
passCount = 1;
if (stencilOnly) {
passes[0] = &gDirectToStencil;
@ -495,16 +495,15 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
}
bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const {
// this class can draw any path with any fill but doesn't do any
// anti-aliasing.
return (stroke.getWidthIfStroked() <= 0) && !antiAlias;
// this class can draw any path with any fill but doesn't do any anti-aliasing.
return (stroke.isFillStyle() || stroke.isHairlineStyle()) && !antiAlias;
}
bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {
return this->internalDrawPath(path,
@ -514,7 +513,7 @@ bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
}
void GrDefaultPathRenderer::onStencilPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target) {
GrAssert(SkPath::kInverseEvenOdd_FillType != path.getFillType());
GrAssert(SkPath::kInverseWinding_FillType != path.getFillType());

View File

@ -20,32 +20,32 @@ public:
GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport);
virtual bool canDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*,
bool antiAlias) const SK_OVERRIDE;
private:
virtual StencilSupport onGetStencilSupport(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*) const SK_OVERRIDE;
virtual bool onDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*,
bool antiAlias) SK_OVERRIDE;
virtual void onStencilPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*) SK_OVERRIDE;
bool internalDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*,
bool stencilOnly);
bool createGeom(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
SkScalar srcSpaceTol,
GrDrawTarget*,
GrPrimitiveType*,

View File

@ -10,12 +10,11 @@
#include "GrDrawTarget.h"
#include "GrGpuVertex.h"
#include "GrIndexBuffer.h"
#include "GrRenderTarget.h"
#include "GrTexture.h"
#include "GrVertexBuffer.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
SK_DEFINE_INST_COUNT(GrDrawTarget)
@ -785,12 +784,12 @@ void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
}
}
void GrDrawTarget::stencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
// TODO: extract portions of checkDraw that are relevant to path stenciling.
GrAssert(NULL != path);
GrAssert(fCaps.pathStencilingSupport());
GrAssert(0 != stroke.getWidthIfStroked());
GrAssert(!SkPath::IsInverseFill(fill));
GrAssert(!stroke.isHairlineStyle());
GrAssert(!SkPath::IsInverseFillType(fill));
this->onStencilPath(path, stroke, fill);
}

View File

@ -28,7 +28,7 @@ class GrClipData;
class GrPath;
class GrVertexBuffer;
class SkStroke;
class SkStrokeRec;
class GrDrawTarget : public GrRefCnt {
protected:
@ -457,7 +457,7 @@ public:
* winding (not inverse or hairline). It will respect the HW antialias flag
* on the draw state (if possible in the 3D API).
*/
void stencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType fill);
void stencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType fill);
/**
* Helper function for drawing rects. This does not use the current index
@ -992,7 +992,7 @@ protected:
virtual void onDrawNonIndexed(GrPrimitiveType type,
int startVertex,
int vertexCount) = 0;
virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType fill) = 0;
virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType fill) = 0;
// subclass overrides to be notified when clip is set. Must call
// INHERITED::clipwillBeSet

View File

@ -410,7 +410,7 @@ void GrGpu::onDrawNonIndexed(GrPrimitiveType type,
this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
}
void GrGpu::onStencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
void GrGpu::onStencilPath(const GrPath* path, const SkStrokeRec&, SkPath::FillType fill) {
this->handleDirtyContext();
// TODO: make this more effecient (don't copy and copy back)

View File

@ -570,7 +570,7 @@ private:
virtual void onDrawNonIndexed(GrPrimitiveType type,
int startVertex,
int vertexCount) SK_OVERRIDE;
virtual void onStencilPath(const GrPath* path, const SkStroke& stroke,
virtual void onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
SkPath::FillType) SK_OVERRIDE;
// readies the pools to provide vertex/index data.

View File

@ -487,7 +487,9 @@ void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
draw->fIndexBuffer = NULL;
}
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStroke& stroke,
GrInOrderDrawBuffer::StencilPath::StencilPath() : fStroke(SkStrokeRec::kFill_InitStyle) {}
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
SkPath::FillType fill) {
if (this->needsNewClip()) {
this->recordClip();

View File

@ -17,7 +17,7 @@
#include "GrPath.h"
#include "SkClipStack.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
#include "SkTemplates.h"
class GrGpu;
@ -158,8 +158,10 @@ private:
};
struct StencilPath {
StencilPath();
SkAutoTUnref<const GrPath> fPath;
SkStroke fStroke;
SkStrokeRec fStroke;
SkPath::FillType fFill;
};
@ -181,7 +183,7 @@ private:
virtual void onDrawNonIndexed(GrPrimitiveType primitiveType,
int startVertex,
int vertexCount) SK_OVERRIDE;
virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType) SK_OVERRIDE;
virtual void onStencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType) SK_OVERRIDE;
virtual bool onReserveVertexSpace(GrVertexLayout layout,
int vertexCount,
void** vertices) SK_OVERRIDE;

View File

@ -14,7 +14,7 @@
#include "GrPathRendererChain.h"
#include "GrStencil.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
#include "SkTArray.h"
class SkPath;
@ -82,7 +82,7 @@ public:
* @param stroke the stroke information (width, join, cap).
*/
StencilSupport getStencilSupport(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target) const {
GrAssert(!path.isInverseFillType());
return this->onGetStencilSupport(path, stroke, target);
@ -101,7 +101,7 @@ public:
* @return true if the path can be drawn by this object, false otherwise.
*/
virtual bool canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& rec,
const GrDrawTarget* target,
bool antiAlias) const = 0;
/**
@ -114,7 +114,7 @@ public:
* @param antiAlias true if anti-aliasing is required.
*/
bool drawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {
GrAssert(this->canDrawPath(path, stroke, target, antiAlias));
@ -131,7 +131,7 @@ public:
* @param stroke the stroke information (width, join, cap)
* @param target target that the path will be rendered to
*/
void stencilPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target) {
void stencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) {
GrAssert(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target));
this->onStencilPath(path, stroke, target);
}
@ -141,7 +141,7 @@ protected:
* Subclass overrides if it has any limitations of stenciling support.
*/
virtual StencilSupport onGetStencilSupport(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*) const {
return kNoRestriction_StencilSupport;
}
@ -150,7 +150,7 @@ protected:
* Subclass implementation of drawPath()
*/
virtual bool onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) = 0;
@ -158,7 +158,7 @@ protected:
* Subclass implementation of stencilPath(). Subclass must override iff it ever returns
* kStencilOnly in onGetStencilSupport().
*/
virtual void onStencilPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target) {
virtual void onStencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) {
GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
GrDrawState* drawState = target->drawState();
GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,

View File

@ -33,7 +33,7 @@ GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) {
}
GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
DrawType drawType,
StencilSupport* stencilSupport) {

View File

@ -9,7 +9,7 @@
#include "GrDrawState.h"
#include "GrGpu.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
// TODO: try to remove this #include
#include "GrContext.h"
@ -55,24 +55,24 @@ void GrSWMaskHelper::draw(const GrRect& rect, SkRegion::Op op,
/**
* Draw a single path element of the clip stack into the accumulation bitmap
*/
void GrSWMaskHelper::draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
void GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
bool antiAlias, uint8_t alpha) {
SkPaint paint;
SkScalar width = stroke.getWidthIfStroked();
if (0 == width) {
if (stroke.isHairlineStyle()) {
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SK_Scalar1);
} else {
if (stroke.getDoFill()) {
if (stroke.isFillStyle()) {
paint.setStyle(SkPaint::kFill_Style);
} else {
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeJoin(stroke.getJoin());
paint.setStrokeCap(stroke.getCap());
paint.setStrokeWidth(width);
paint.setStrokeWidth(stroke.getWidth());
}
}
SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
paint.setXfermode(mode);
@ -159,7 +159,7 @@ void GrSWMaskHelper::toTexture(GrTexture *texture, uint8_t alpha) {
*/
GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrIRect& resultBounds,
bool antiAlias,
SkMatrix* matrix) {

View File

@ -21,7 +21,7 @@ class GrAutoScratchTexture;
class GrContext;
class GrTexture;
class SkPath;
class SkStroke;
class SkStrokeRec;
class GrDrawTarget;
/**
@ -55,7 +55,7 @@ public:
bool antiAlias, uint8_t alpha);
// Draw a single path into the accumuation bitmap using the specified op
void draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
void draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
bool antiAlias, uint8_t alpha);
// Helper function to get a scratch texture suitable for capturing the
@ -75,7 +75,7 @@ public:
// to the GPU. The result is returned in "result".
static GrTexture* DrawPathMaskToTexture(GrContext* context,
const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrIRect& resultBounds,
bool antiAlias,
SkMatrix* matrix);

View File

@ -11,9 +11,9 @@
#include "GrSWMaskHelper.h"
////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
const SkStroke& stroke,
const GrDrawTarget* target,
bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
const SkStrokeRec&,
const GrDrawTarget*,
bool antiAlias) const {
if (!antiAlias || NULL == fContext) {
// TODO: We could allow the SW path to also handle non-AA paths but
@ -30,7 +30,7 @@ bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*) const {
return GrPathRenderer::kNoSupport_StencilSupport;
}
@ -114,7 +114,7 @@ void draw_around_inv_path(GrDrawTarget* target,
////////////////////////////////////////////////////////////////////////////////
// return true on success; false on failure
bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {

View File

@ -25,16 +25,16 @@ public:
}
virtual bool canDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*,
bool antiAlias) const SK_OVERRIDE;
protected:
virtual StencilSupport onGetStencilSupport(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*) const SK_OVERRIDE;
virtual bool onDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*,
bool antiAlias) SK_OVERRIDE;

View File

@ -11,7 +11,7 @@
#include "GrContext.h"
#include "GrGpu.h"
#include "GrPath.h"
#include "SkStroke.h"
#include "SkStrokeRec.h"
GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
GrAssert(NULL != context);
@ -34,23 +34,23 @@ GrStencilAndCoverPathRenderer::~GrStencilAndCoverPathRenderer() {
}
bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const {
return stroke.getDoFill() &&
return stroke.isFillStyle() &&
!antiAlias && // doesn't do per-path AA, relies on the target having MSAA
target->getDrawState().getStencil().isDisabled();
}
GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
const SkPath&,
const SkStroke& ,
const SkStrokeRec& ,
const GrDrawTarget*) const {
return GrPathRenderer::kStencilOnly_StencilSupport;
}
void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target) {
GrAssert(!path.isInverseFillType());
SkAutoTUnref<GrPath> p(fGpu->createPath(path));
@ -58,18 +58,18 @@ void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
}
bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
const SkStroke& stroke,
const SkStrokeRec& stroke,
GrDrawTarget* target,
bool antiAlias) {
GrAssert(!antiAlias);
GrAssert(0 != stroke.getWidthIfStroked());
GrAssert(!stroke.isHairlineStyle());
GrDrawState* drawState = target->drawState();
GrAssert(drawState->getStencil().isDisabled());
SkAutoTUnref<GrPath> p(fGpu->createPath(path));
SkPath::FillType nonInvertedFill = SkPath::NonInverseFill(path.getFillType());
SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType());
target->stencilPath(p, stroke, nonInvertedFill);
// TODO: Use built in cover operation rather than a rect draw. This will require making our

View File

@ -26,22 +26,22 @@ public:
virtual ~GrStencilAndCoverPathRenderer();
virtual bool canDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*,
bool antiAlias) const SK_OVERRIDE;
protected:
virtual StencilSupport onGetStencilSupport(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
const GrDrawTarget*) const SK_OVERRIDE;
virtual bool onDrawPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*,
bool antiAlias) SK_OVERRIDE;
virtual void onStencilPath(const SkPath&,
const SkStroke&,
const SkStrokeRec&,
GrDrawTarget*) SK_OVERRIDE;
private:

View File

@ -17,6 +17,7 @@
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
#include "SkPath.h"
#include "SkStrokeRec.h"
enum {
kGlyphMaskStage = GrPaint::kTotalStages,
@ -179,7 +180,8 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
GrPaint tmpPaint(fPaint);
am.setPreConcat(fContext, translate, &tmpPaint);
fContext->drawPath(tmpPaint, *glyph->fPath, false);
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
return;
}

View File

@ -19,6 +19,8 @@
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkImageFilter.h"
#include "SkPathEffect.h"
#include "SkStroke.h"
#include "SkUtils.h"
#define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
@ -753,7 +755,7 @@ inline bool shouldDrawBlurWithCPU(const SkRect& rect, SkScalar radius) {
return false;
}
bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, bool doHairLine,
bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, const SkStrokeRec& stroke,
SkMaskFilter* filter, const SkRegion& clip,
SkBounder* bounder, GrPaint* grp) {
SkMaskFilter::BlurInfo info;
@ -838,7 +840,7 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, bool doHai
SkMatrix translate;
translate.setTranslate(offset.fX, offset.fY);
am.set(context, translate);
context->drawPath(tempPaint, devPath, doHairLine);
context->drawPath(tempPaint, devPath, stroke);
// If we're doing a normal blur, we can clobber the pathTexture in the
// gaussianBlur. Otherwise, we need to save it for later compositing.
@ -964,8 +966,6 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
CHECK_FOR_NODRAW_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw, false);
bool doHairLine = false;
GrPaint grPaint;
SkAutoCachedTexture textures[GrPaint::kMaxColorStages];
if (!skPaint2GrPaintShader(this,
@ -979,8 +979,8 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
// can we cheat, and threat a thin stroke as a hairline w/ coverage
// if we can, we draw lots faster (raster device does this same test)
SkScalar hairlineCoverage;
if (SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage)) {
doHairLine = true;
bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage);
if (doHairLine) {
grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
}
@ -988,7 +988,7 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
// where the original path can in fact be modified in place (even though
// its parameter type is const).
SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
SkPath tmpPath;
SkPath tmpPath, effectPath;
if (prePathMatrix) {
SkPath* result = pathPtr;
@ -1005,32 +1005,40 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
// at this point we're done with prePathMatrix
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
if (paint.getPathEffect() ||
(!doHairLine && paint.getStyle() != SkPaint::kFill_Style)) {
// it is safe to use tmpPath here, even if we already used it for the
// prepathmatrix, since getFillPath can take the same object for its
// input and output safely.
doHairLine = !paint.getFillPath(*pathPtr, &tmpPath);
pathPtr = &tmpPath;
SkStrokeRec stroke(paint);
SkPathEffect* pathEffect = paint.getPathEffect();
if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke)) {
pathPtr = &effectPath;
}
if (!pathEffect && doHairLine) {
stroke.setHairlineStyle();
}
if (paint.getMaskFilter()) {
if (!stroke.isHairlineStyle()) {
if (stroke.applyToPath(&tmpPath, *pathPtr)) {
pathPtr = &tmpPath;
stroke.setFillStyle();
}
}
// avoid possibly allocating a new path in transform if we can
SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
// transform the path into device space
pathPtr->transform(fContext->getMatrix(), devPathPtr);
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, doHairLine, paint.getMaskFilter(),
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, stroke, paint.getMaskFilter(),
*draw.fClip, draw.fBounder, &grPaint)) {
SkPaint::Style style = doHairLine ? SkPaint::kStroke_Style :
SkPaint::kFill_Style;
SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
SkPaint::kFill_Style;
drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
*draw.fClip, draw.fBounder, &grPaint, style);
}
return;
}
fContext->drawPath(grPaint, *pathPtr, doHairLine);
fContext->drawPath(grPaint, *pathPtr, stroke);
}
namespace {