/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkPaint.h"
#include "SkPathEffect.h"
#include "SkPictureContentInfo.h"
bool SkPictureContentInfo::suitableForGpuRasterization(GrContext* context, const char **reason,
int sampleCount) const {
// TODO: the heuristic used here needs to be refined
static const int kNumPaintWithPathEffectUsesTol = 1;
static const int kNumAAConcavePaths = 5;
SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
int numNonDashedPathEffects = fNumPaintWithPathEffectUses -
fNumFastPathDashEffects;
bool suitableForDash = (0 == fNumPaintWithPathEffectUses) ||
(numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
&& 0 == sampleCount);
bool ret = suitableForDash &&
(fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths)
< kNumAAConcavePaths;
if (!ret && reason) {
if (!suitableForDash) {
if (0 != sampleCount) {
*reason = "Can't use multisample on dash effect.";
} else {
*reason = "Too many non dashed path effects.";
}
} else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths - fNumAADFEligibleConcavePaths)
>= kNumAAConcavePaths) {
*reason = "Too many anti-aliased concave paths.";
} else {
*reason = "Unknown reason for GPU unsuitability.";
}
}
return ret;
}
void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) {
if (paint.getPathEffect() != nullptr) {
SkPathEffect::DashInfo info;
SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
++fNumFastPathDashEffects;
}
}
}
void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) {
if (paint.isAntiAlias() && !path.isConvex()) {
++fNumAAConcavePaths;
SkPaint::Style paintStyle = paint.getStyle();
const SkRect& pathBounds = path.getBounds();
if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
++fNumAAHairlineConcavePaths;
} else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f &&
pathBounds.height() < 64.f && !path.isVolatile()) {
++fNumAADFEligibleConcavePaths;
}
}
}
void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) {
if (paint && paint->getPathEffect()) {
++fNumPaintWithPathEffectUses;
}
}
void SkPictureContentInfo::onSaveLayer() {
*fSaveStack.append() = kSaveLayer_Flag;
}
void SkPictureContentInfo::onSave() {
*fSaveStack.append() = kSave_Flag;
}
void SkPictureContentInfo::onRestore() {
SkASSERT(fSaveStack.count() > 0);
bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
if (fSaveStack.top() & kSaveLayer_Flag) {
++fNumLayers;
if (containedSaveLayer) {
++fNumInteriorLayers;
} else {
++fNumLeafLayers;
}
containedSaveLayer = true;
}
fSaveStack.pop();
if (containedSaveLayer && fSaveStack.count() > 0) {
fSaveStack.top() |= kContainedSaveLayer_Flag;
}
}
void SkPictureContentInfo::rescindLastSave() {
SkASSERT(fSaveStack.count() > 0);
SkASSERT(fSaveStack.top() & kSave_Flag);
bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
fSaveStack.pop();
if (containedSaveLayer && fSaveStack.count() > 0) {
fSaveStack.top() |= kContainedSaveLayer_Flag;
}
}
void SkPictureContentInfo::rescindLastSaveLayer() {
SkASSERT(fSaveStack.count() > 0);
SkASSERT(fSaveStack.top() & kSaveLayer_Flag);
bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag;
fSaveStack.pop();
if (containedSaveLayer && fSaveStack.count() > 0) {
fSaveStack.top() |= kContainedSaveLayer_Flag;
}
}
void SkPictureContentInfo::set(const SkPictureContentInfo& src) {
fNumOperations = src.fNumOperations;
fNumTexts = src.fNumTexts;
fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
fNumFastPathDashEffects = src.fNumFastPathDashEffects;
fNumAAConcavePaths = src.fNumAAConcavePaths;
fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
fNumAADFEligibleConcavePaths = src.fNumAADFEligibleConcavePaths;
fNumLayers = src.fNumLayers;
fNumInteriorLayers = src.fNumInteriorLayers;
fNumLeafLayers = src.fNumLeafLayers;
fSaveStack = src.fSaveStack;
}
void SkPictureContentInfo::reset() {
fNumOperations = 0;
fNumTexts = 0;
fNumPaintWithPathEffectUses = 0;
fNumFastPathDashEffects = 0;
fNumAAConcavePaths = 0;
fNumAAHairlineConcavePaths = 0;
fNumAADFEligibleConcavePaths = 0;
fNumLayers = 0;
fNumInteriorLayers = 0;
fNumLeafLayers = 0;
fSaveStack.rewind();
}
void SkPictureContentInfo::swap(SkPictureContentInfo* other) {
SkTSwap(fNumOperations, other->fNumOperations);
SkTSwap(fNumTexts, other->fNumTexts);
SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
SkTSwap(fNumAADFEligibleConcavePaths, other->fNumAADFEligibleConcavePaths);
SkTSwap(fNumLayers, other->fNumLayers);
SkTSwap(fNumInteriorLayers, other->fNumInteriorLayers);
SkTSwap(fNumLeafLayers, other->fNumLeafLayers);
fSaveStack.swap(other->fSaveStack);
}