/*
 * 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 SkPictureCommon_DEFINED
#define SkPictureCommon_DEFINED

// Some shared code used by both SkBigPicture and SkMiniPicture.
//   SkTextHunter   -- SkRecord visitor that returns true when the op draws text.
//   SkBitmapHunter -- SkRecord visitor that returns true when the op draws a bitmap or image.
//   SkPathCounter  -- SkRecord visitor that counts paths that draw slowly on the GPU.

#include "SkPathEffect.h"
#include "SkRecords.h"
#include "SkTLogic.h"

// N.B. This name is slightly historical: hunting season is now open for SkImages too.
struct SkBitmapHunter {
    // Some ops have a paint, some have an optional paint.  Either way, get back a pointer.
    static const SkPaint* AsPtr(const SkPaint& p) { return &p; }
    static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; }

    // Main entry for visitor:
    // If the op is a DrawPicture, recurse.
    // If the op has a bitmap or image directly, return true.
    // If the op has a paint and the paint has a bitmap, return true.
    // Otherwise, return false.
    bool operator()(const SkRecords::DrawPicture& op) { return op.picture->willPlayBackBitmaps(); }
    bool operator()(const SkRecords::DrawDrawable&) { /*TODO*/ return false; }

    template <typename T>
    bool operator()(const T& op) { return CheckBitmap(op); }

    // If the op is tagged as having an image, return true.
    template <typename T>
    static SK_WHEN(T::kTags & SkRecords::kHasImage_Tag, bool) CheckBitmap(const T&) {
        return true;
    }

    // If not, look for one in its paint (if it has a paint).
    template <typename T>
    static SK_WHEN(!(T::kTags & SkRecords::kHasImage_Tag), bool) CheckBitmap(const T& op) {
        return CheckPaint(op);
    }

    // Most draws-type ops have paints.
    template <typename T>
    static SK_WHEN(T::kTags & SkRecords::kHasPaint_Tag, bool) CheckPaint(const T& op) {
        return PaintHasBitmap(AsPtr(op.paint));
    }

    template <typename T>
    static SK_WHEN(!(T::kTags & SkRecords::kHasPaint_Tag), bool) CheckPaint(const T&) {
        return false;
    }

private:
    static bool PaintHasBitmap(const SkPaint* paint) {
        if (paint) {
            const SkShader* shader = paint->getShader();
            if (shader && shader->isAImage()) {
                return true;
            }
        }
        return false;
    }
};

// TODO: might be nicer to have operator() return an int (the number of slow paths) ?
struct SkPathCounter {
    // Some ops have a paint, some have an optional paint.  Either way, get back a pointer.
    static const SkPaint* AsPtr(const SkPaint& p) { return &p; }
    static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; }

    SkPathCounter() : fNumSlowPathsAndDashEffects(0) {}

    // Recurse into nested pictures.
    void operator()(const SkRecords::DrawPicture& op) {
        fNumSlowPathsAndDashEffects += op.picture->numSlowPaths();
    }
    void operator()(const SkRecords::DrawDrawable&) { /* TODO */ }

    void checkPaint(const SkPaint* paint) {
        if (paint && paint->getPathEffect()) {
            // Initially assume it's slow.
            fNumSlowPathsAndDashEffects++;
        }
    }

    void operator()(const SkRecords::DrawPoints& op) {
        this->checkPaint(&op.paint);
        const SkPathEffect* effect = op.paint.getPathEffect();
        if (effect) {
            SkPathEffect::DashInfo info;
            SkPathEffect::DashType dashType = effect->asADash(&info);
            if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap() &&
                SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
                fNumSlowPathsAndDashEffects--;
            }
        }
    }

    void operator()(const SkRecords::DrawPath& op) {
        this->checkPaint(&op.paint);
        if (op.paint.isAntiAlias() && !op.path.isConvex()) {
            SkPaint::Style paintStyle = op.paint.getStyle();
            const SkRect& pathBounds = op.path.getBounds();
            if (SkPaint::kStroke_Style == paintStyle &&
                0 == op.paint.getStrokeWidth()) {
                // AA hairline concave path is not slow.
            } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f &&
                       pathBounds.height() < 64.f && !op.path.isVolatile()) {
                // AADF eligible concave path is not slow.
            } else {
                fNumSlowPathsAndDashEffects++;
            }
        }
    }

    void operator()(const SkRecords::ClipPath& op) {
        // TODO: does the SkRegion op matter?
        if (op.opAA.aa() && !op.path.isConvex()) {
            fNumSlowPathsAndDashEffects++;
        }
    }

    void operator()(const SkRecords::SaveLayer& op) {
        this->checkPaint(AsPtr(op.paint));
    }

    template <typename T>
    SK_WHEN(T::kTags & SkRecords::kDraw_Tag, void) operator()(const T& op) {
        this->checkPaint(AsPtr(op.paint));
    }

    template <typename T>
    SK_WHEN(!(T::kTags & SkRecords::kDraw_Tag), void) operator()(const T& op) { /* do nothing */ }

    int fNumSlowPathsAndDashEffects;
};
#endif  // SkPictureCommon_DEFINED
