/*
 * 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);
}
