Implement drawDRRect for GPU
BUG=skia:2259 R=jvanverth@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/220233011 git-svn-id: http://skia.googlecode.com/svn/trunk@14118 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
149e9a107c
commit
0a09d7195b
@ -59,3 +59,7 @@ canvas-layer-state
|
||||
# yunchao: https://codereview.chromium.org/204143004/
|
||||
# This change add some cases to bitmapshader to avoid potential drawing error for kA8_Config
|
||||
bitmapshaders
|
||||
|
||||
# bsalomon: This image will change on the GPU due to an accelerated drawDRRect() implementation.
|
||||
# https://codereview.chromium.org/220233011/
|
||||
drrect
|
@ -457,9 +457,19 @@ public:
|
||||
* @param rrect the roundrect to draw
|
||||
* @param stroke the stroke information (width, join, cap)
|
||||
*/
|
||||
void drawRRect(const GrPaint& paint,
|
||||
const SkRRect& rrect,
|
||||
const SkStrokeRec& stroke);
|
||||
void drawRRect(const GrPaint& paint, const SkRRect& rrect, const SkStrokeRec& stroke);
|
||||
|
||||
/**
|
||||
* Shortcut for drawing an SkPath consisting of nested rrects using a paint.
|
||||
* Does not support stroking. The result is undefined if outer does not contain
|
||||
* inner.
|
||||
*
|
||||
* @param paint describes how to color pixels.
|
||||
* @param outer the outer roundrect
|
||||
* @param inner the inner roundrect
|
||||
*/
|
||||
void drawDRRect(const GrPaint& paint, const SkRRect& outer, const SkRRect& inner);
|
||||
|
||||
|
||||
/**
|
||||
* Draws a path.
|
||||
|
@ -91,6 +91,8 @@ public:
|
||||
const SkPaint& paint) SK_OVERRIDE;
|
||||
virtual void drawRRect(const SkDraw&, const SkRRect& r,
|
||||
const SkPaint& paint) SK_OVERRIDE;
|
||||
virtual void drawDRRect(const SkDraw& draw, const SkRRect& outer,
|
||||
const SkRRect& inner, const SkPaint& paint) SK_OVERRIDE;
|
||||
virtual void drawOval(const SkDraw&, const SkRect& oval,
|
||||
const SkPaint& paint) SK_OVERRIDE;
|
||||
virtual void drawPath(const SkDraw&, const SkPath& path,
|
||||
|
@ -1002,9 +1002,9 @@ void GrContext::drawVertices(const GrPaint& paint,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::drawRRect(const GrPaint& paint,
|
||||
const SkRRect& rect,
|
||||
const SkRRect& rrect,
|
||||
const SkStrokeRec& stroke) {
|
||||
if (rect.isEmpty()) {
|
||||
if (rrect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1014,15 +1014,41 @@ void GrContext::drawRRect(const GrPaint& paint,
|
||||
|
||||
GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
|
||||
|
||||
if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
|
||||
if (!fOvalRenderer->drawRRect(target, this, paint.isAntiAlias(), rrect, stroke)) {
|
||||
SkPath path;
|
||||
path.addRRect(rect);
|
||||
path.addRRect(rrect);
|
||||
this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::drawDRRect(const GrPaint& paint,
|
||||
const SkRRect& outer,
|
||||
const SkRRect& inner) {
|
||||
if (outer.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoRestoreEffects are;
|
||||
AutoCheckFlush acf(this);
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
||||
|
||||
GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
|
||||
|
||||
if (!fOvalRenderer->drawDRRect(target, this, paint.isAntiAlias(), outer, inner)) {
|
||||
SkPath path;
|
||||
path.addRRect(inner);
|
||||
path.addRRect(outer);
|
||||
path.setFillType(SkPath::kEvenOdd_FillType);
|
||||
|
||||
SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
|
||||
this->internalDrawPath(target, paint.isAntiAlias(), path, fillRec);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrContext::drawOval(const GrPaint& paint,
|
||||
const SkRect& oval,
|
||||
const SkStrokeRec& stroke) {
|
||||
|
@ -19,8 +19,10 @@
|
||||
|
||||
#include "SkRRect.h"
|
||||
#include "SkStrokeRec.h"
|
||||
#include "SkTLazy.h"
|
||||
|
||||
#include "effects/GrVertexEffect.h"
|
||||
#include "effects/GrRRectEffect.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -519,12 +521,14 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
||||
CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = radius;
|
||||
SkScalar halfWidth = 0;
|
||||
if (style != SkStrokeRec::kFill_Style) {
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(strokeWidth)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
@ -532,12 +536,12 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
||||
}
|
||||
|
||||
outerRadius += halfWidth;
|
||||
if (isStroked) {
|
||||
if (isStrokeOnly) {
|
||||
innerRadius = radius - halfWidth;
|
||||
}
|
||||
}
|
||||
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStroked && innerRadius > 0);
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
@ -626,11 +630,13 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||
scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY]));
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
SkScalar innerXRadius = 0;
|
||||
SkScalar innerYRadius = 0;
|
||||
if (SkStrokeRec::kFill_Style != style) {
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.length())) {
|
||||
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
@ -650,7 +656,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (isStroked) {
|
||||
if (isStrokeOnly) {
|
||||
innerXRadius = xRadius - scaledStroke.fX;
|
||||
innerYRadius = yRadius - scaledStroke.fY;
|
||||
}
|
||||
@ -675,7 +681,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||
|
||||
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
|
||||
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked &&
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly &&
|
||||
innerXRadius > 0 && innerYRadius > 0);
|
||||
|
||||
static const int kEllipseCenterAttrIndex = 1;
|
||||
@ -877,9 +883,39 @@ GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) {
|
||||
return fRRectIndexBuffer;
|
||||
}
|
||||
|
||||
bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& rrect, const SkStrokeRec& stroke)
|
||||
{
|
||||
bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& outer, const SkRRect& origInner) {
|
||||
GrDrawState::AutoRestoreEffects are;
|
||||
if (!origInner.isEmpty()) {
|
||||
SkTCopyOnFirstWrite<SkRRect> inner(origInner);
|
||||
if (!context->getMatrix().isIdentity()) {
|
||||
if (!origInner.transform(context->getMatrix(), inner.writable())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool applyAA = useAA &&
|
||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
||||
!target->shouldDisableCoverageAAForBlend();
|
||||
GrEffectEdgeType edgeType = applyAA ? kInverseFillAA_GrEffectEdgeType :
|
||||
kInverseFillBW_GrEffectEdgeType;
|
||||
GrEffectRef* effect = GrRRectEffect::Create(edgeType, *inner);
|
||||
if (NULL == effect) {
|
||||
return false;
|
||||
}
|
||||
are.set(target->drawState());
|
||||
target->drawState()->addCoverageEffect(effect)->unref();
|
||||
}
|
||||
|
||||
SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
|
||||
return this->drawRRect(target, context, useAA, outer, fillRec);
|
||||
}
|
||||
|
||||
bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& rrect, const SkStrokeRec& stroke) {
|
||||
if (rrect.isOval()) {
|
||||
return this->drawOval(target, context, useAA, rrect.getBounds(), stroke);
|
||||
}
|
||||
|
||||
bool useCoverageAA = useAA &&
|
||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
||||
!target->shouldDisableCoverageAAForBlend();
|
||||
@ -890,12 +926,10 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
|
||||
const SkMatrix& vm = context->getMatrix();
|
||||
#ifdef SK_DEBUG
|
||||
{
|
||||
// we should have checked for this previously
|
||||
SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple());
|
||||
|
||||
if (!vm.rectStaysRect() || !rrect.isSimple()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// do any matrix crunching before we reset the draw state for device coords
|
||||
const SkRect& rrectBounds = rrect.getBounds();
|
||||
@ -908,21 +942,38 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX +
|
||||
vm[SkMatrix::kMScaleY]*radii.fY);
|
||||
|
||||
// if hairline stroke is greater than radius, we don't handle that right now
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
if (SkStrokeRec::kHairline_Style == style &&
|
||||
(SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// do (potentially) anisotropic mapping of stroke
|
||||
SkVector scaledStroke;
|
||||
SkScalar strokeWidth = stroke.getWidth();
|
||||
scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMatrix::kMSkewY]));
|
||||
scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY]));
|
||||
|
||||
// if half of strokewidth is greater than radius, we don't handle that right now
|
||||
if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) {
|
||||
bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
|
||||
SkStrokeRec::kHairline_Style == style;
|
||||
bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
|
||||
|
||||
if (hasStroke) {
|
||||
if (SkStrokeRec::kHairline_Style == style) {
|
||||
scaledStroke.set(1, 1);
|
||||
} else {
|
||||
scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] +
|
||||
vm[SkMatrix::kMSkewY]));
|
||||
scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] +
|
||||
vm[SkMatrix::kMScaleY]));
|
||||
}
|
||||
|
||||
// if half of strokewidth is greater than radius, we don't handle that right now
|
||||
if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The way the effect interpolates the offset-to-ellipse/circle-center attribute only works on
|
||||
// the interior of the rrect if the radii are >= 0.5. Otherwise, the inner rect of the nine-
|
||||
// patch will have fractional coverage. This only matters when the interior is actually filled.
|
||||
// We could consider falling back to rect rendering here, since a tiny radius is
|
||||
// indistinguishable from a square corner.
|
||||
if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -933,8 +984,6 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
|
||||
|
||||
GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu());
|
||||
if (NULL == indexBuffer) {
|
||||
GrPrintf("Failed to create index buffer!\n");
|
||||
@ -942,7 +991,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
|
||||
// if the corners are circles, use the circle renderer
|
||||
if ((!isStroked || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
|
||||
if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
|
||||
drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs));
|
||||
SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize());
|
||||
|
||||
@ -956,23 +1005,23 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = xRadius;
|
||||
SkScalar halfWidth = 0;
|
||||
if (style != SkStrokeRec::kFill_Style) {
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.fX)) {
|
||||
halfWidth = SK_ScalarHalf;
|
||||
} else {
|
||||
halfWidth = SkScalarHalf(scaledStroke.fX);
|
||||
}
|
||||
|
||||
if (isStroked) {
|
||||
if (isStrokeOnly) {
|
||||
innerRadius = xRadius - halfWidth;
|
||||
}
|
||||
outerRadius += halfWidth;
|
||||
bounds.outset(halfWidth, halfWidth);
|
||||
}
|
||||
|
||||
isStroked = (isStroked && innerRadius >= 0);
|
||||
isStrokeOnly = (isStrokeOnly && innerRadius >= 0);
|
||||
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
@ -1025,7 +1074,8 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
|
||||
// drop out the middle quad if we're stroked
|
||||
int indexCnt = isStroked ? SK_ARRAY_COUNT(gRRectIndices)-6 : SK_ARRAY_COUNT(gRRectIndices);
|
||||
int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
|
||||
SK_ARRAY_COUNT(gRRectIndices);
|
||||
target->setIndexSourceToBuffer(indexBuffer);
|
||||
target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
|
||||
|
||||
@ -1036,7 +1086,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
|
||||
SkScalar innerXRadius = 0.0f;
|
||||
SkScalar innerYRadius = 0.0f;
|
||||
if (SkStrokeRec::kFill_Style != style) {
|
||||
if (hasStroke) {
|
||||
if (SkScalarNearlyZero(scaledStroke.length())) {
|
||||
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
|
||||
} else {
|
||||
@ -1056,7 +1106,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
|
||||
// this is legit only if scale & translation (which should be the case at the moment)
|
||||
if (isStroked) {
|
||||
if (isStrokeOnly) {
|
||||
innerXRadius = xRadius - scaledStroke.fX;
|
||||
innerYRadius = yRadius - scaledStroke.fY;
|
||||
}
|
||||
@ -1066,7 +1116,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
bounds.outset(scaledStroke.fX, scaledStroke.fY);
|
||||
}
|
||||
|
||||
isStroked = (isStroked && innerXRadius >= 0 && innerYRadius >= 0);
|
||||
isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
|
||||
|
||||
GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
|
||||
if (!geo.succeeded()) {
|
||||
@ -1075,7 +1125,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
|
||||
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly);
|
||||
static const int kEllipseOffsetAttrIndex = 1;
|
||||
static const int kEllipseRadiiAttrIndex = 2;
|
||||
drawState->addCoverageEffect(effect,
|
||||
@ -1134,7 +1184,8 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
}
|
||||
|
||||
// drop out the middle quad if we're stroked
|
||||
int indexCnt = isStroked ? SK_ARRAY_COUNT(gRRectIndices)-6 : SK_ARRAY_COUNT(gRRectIndices);
|
||||
int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
|
||||
SK_ARRAY_COUNT(gRRectIndices);
|
||||
target->setIndexSourceToBuffer(indexBuffer);
|
||||
target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
|
||||
}
|
||||
|
@ -33,8 +33,10 @@ public:
|
||||
|
||||
bool drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
|
||||
const SkRect& oval, const SkStrokeRec& stroke);
|
||||
bool drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& rrect, const SkStrokeRec& stroke);
|
||||
bool drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& rrect, const SkStrokeRec& stroke);
|
||||
bool drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||
const SkRRect& outer, const SkRRect& inner);
|
||||
|
||||
private:
|
||||
bool drawEllipse(GrDrawTarget* target, bool useCoverageAA,
|
||||
|
@ -656,17 +656,7 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
|
||||
|
||||
}
|
||||
|
||||
bool usePath = !rect.isSimple();
|
||||
// another two reasons we might need to call drawPath...
|
||||
if (paint.getMaskFilter() || paint.getPathEffect()) {
|
||||
usePath = true;
|
||||
}
|
||||
// until we can rotate rrects...
|
||||
if (!usePath && !fContext->getMatrix().rectStaysRect()) {
|
||||
usePath = true;
|
||||
}
|
||||
|
||||
if (usePath) {
|
||||
SkPath path;
|
||||
path.addRRect(rect);
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
@ -676,6 +666,34 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
|
||||
fContext->drawRRect(grPaint, rect, stroke);
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
|
||||
const SkRRect& inner, const SkPaint& paint) {
|
||||
SkStrokeRec stroke(paint);
|
||||
if (stroke.isFillStyle()) {
|
||||
|
||||
CHECK_FOR_ANNOTATION(paint);
|
||||
CHECK_SHOULD_DRAW(draw, false);
|
||||
|
||||
GrPaint grPaint;
|
||||
if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
|
||||
fContext->drawDRRect(grPaint, outer, inner);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkPath path;
|
||||
path.addRRect(outer);
|
||||
path.addRRect(inner);
|
||||
path.setFillType(SkPath::kEvenOdd_FillType);
|
||||
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
|
||||
|
@ -137,7 +137,8 @@ void GLCircleEffect::emitCode(GrGLShaderBuilder* builder,
|
||||
const TextureSamplerArray& samplers) {
|
||||
const CircleEffect& ce = drawEffect.castEffect<CircleEffect>();
|
||||
const char *circleName;
|
||||
// The circle uniform is (center.x, center.y, radius + 0.5)
|
||||
// The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and
|
||||
// (... ,radius - 0.5) for inverse fills.
|
||||
fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
|
||||
kVec3f_GrSLType,
|
||||
"circle",
|
||||
@ -171,7 +172,13 @@ GrGLEffect::EffectKey GLCircleEffect::GenKey(const GrDrawEffect& drawEffect,
|
||||
void GLCircleEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
|
||||
const CircleEffect& ce = drawEffect.castEffect<CircleEffect>();
|
||||
if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
|
||||
uman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, ce.getRadius() + 0.5f);
|
||||
SkScalar radius = ce.getRadius();
|
||||
if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) {
|
||||
radius -= 0.5f;
|
||||
} else {
|
||||
radius += 0.5f;
|
||||
}
|
||||
uman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius);
|
||||
fPrevCenter = ce.getCenter();
|
||||
fPrevRadius = ce.getRadius();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user