/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/geom/Shape.h"

#include "include/core/SkPathBuilder.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/private/base/SkAlign.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkMalloc.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRRectPriv.h"

#include <cstring>

namespace {
// Keys for paths may be extracted from the path data for small paths, to maximize matches
// even when the genIDs may differ. The value is based on emperical experience, to trade off
// matches vs. key size.
constexpr int kMaxKeyFromDataVerbCnt = 10;
}

namespace skgpu::graphite {

Shape& Shape::operator=(const Shape& shape) {
    switch (shape.type()) {
        case Type::kEmpty: this->reset();                         break;
        case Type::kLine:  this->setLine(shape.p0(), shape.p1()); break;
        case Type::kRect:  this->setRect(shape.rect());           break;
        case Type::kRRect: this->setRRect(shape.rrect());         break;
        case Type::kArc:   this->setArc(shape.arc());             break;
        case Type::kPath:  this->setPath(shape.path());           break;
    }

    fInverted = shape.fInverted;
    return *this;
}

bool Shape::conservativeContains(const Rect& rect) const {
    switch (fType) {
        case Type::kEmpty: return false;
        case Type::kLine:  return false;
        case Type::kRect:  return fRect.contains(rect);
        case Type::kRRect: return fRRect.contains(rect.asSkRect());
        case Type::kPath:  // We need to ensure the path is non-inverted.
                           if (this->inverted()) {
                               SkPath nonInverted(fPath);
                               nonInverted.toggleInverseFillType();
                               return nonInverted.conservativelyContainsRect(rect.asSkRect());
                           } else {
                               return fPath.conservativelyContainsRect(rect.asSkRect());
                           }
        case Type::kArc:   if (fArc.fType == SkArc::Type::kWedge) {
                               SkPath arc = this->asPath();
                               if (this->inverted()) {
                                   arc.toggleInverseFillType();
                               }
                               return arc.conservativelyContainsRect(rect.asSkRect());
                           } else {
                               return false;
                           }
    }
    SkUNREACHABLE;
}

bool Shape::conservativeContains(skvx::float2 point) const {
    switch (fType) {
        case Type::kEmpty: return false;
        case Type::kLine:  return false;
        case Type::kRect:  return fRect.contains(Rect::Point(point));
        case Type::kRRect: return SkRRectPriv::ContainsPoint(fRRect, {point.x(), point.y()});
        case Type::kPath:  // We need to ensure the path is non-inverted.
                           if (this->inverted()) {
                               SkPath nonInverted(fPath);
                               nonInverted.toggleInverseFillType();
                               return nonInverted.contains(point.x(), point.y());
                           } else {
                               return fPath.contains(point.x(), point.y());
                           }
        case Type::kArc:   return false;
    }
    SkUNREACHABLE;
}

bool Shape::convex(bool simpleFill) const {
    if (this->isPath()) {
        // SkPath.isConvex() really means "is this path convex were it to be closed".
        return (simpleFill || fPath.isLastContourClosed()) && fPath.isConvex();
    } else if (this->isArc()) {
        return SkPathPriv::DrawArcIsConvex(fArc.sweepAngle(), fArc.fType, simpleFill);
    } else {
        // Every other shape type is convex by construction.
        return true;
    }
}

Rect Shape::bounds() const {
    switch (fType) {
        case Type::kEmpty: return Rect(0, 0, 0, 0);
        case Type::kLine:  return fRect.makeSorted(); // sorting corners computes bbox of segment
        case Type::kRect:  return fRect; // assuming it's sorted
        case Type::kRRect: return fRRect.getBounds();
        case Type::kArc:   return fArc.oval();
        case Type::kPath:  return fPath.getBounds();
    }
    SkUNREACHABLE;
}

SkPath Shape::asPath() const {
    if (fType == Type::kPath) {
        return fPath;
    }

    if (fType == Type::kArc) {
        // Filled ovals are already culled out so we assume no simple fills
        SkPath out = SkPathPriv::CreateDrawArcPath(fArc, /*isFillNoPathEffect=*/false);
        // CreateDrawArcPath resets the output path and configures its fill
        // type, so we just have to ensure invertedness is correct.
        if (fInverted) {
            out.toggleInverseFillType();
        }
        return out;
    }

    SkPathBuilder builder(this->fillType());
    switch (fType) {
        case Type::kEmpty: /* do nothing */                            break;
        case Type::kLine:  builder.moveTo(fRect.left(), fRect.top())
                                  .lineTo(fRect.right(), fRect.bot()); break;
        case Type::kRect:  builder.addRect(fRect.asSkRect());          break;
        case Type::kRRect: builder.addRRect(fRRect);                   break;
        case Type::kPath:
        case Type::kArc:   SkUNREACHABLE;
    }
    return builder.detach();
}

namespace {
int path_key_from_data_size(const SkPath& path) {
    const int verbCnt = path.countVerbs();
    if (verbCnt > kMaxKeyFromDataVerbCnt) {
        return -1;
    }
    const size_t pointCnt = path.points().size();
    const size_t conicWeightCnt = path.conicWeights().size();

    static_assert(sizeof(SkPoint) == 2 * sizeof(uint32_t));
    static_assert(sizeof(SkScalar) == sizeof(uint32_t));
    // 1 is for the verb count. Each verb is a byte but we'll pad the verb data out to
    // a uint32_t length.
    return 1 + (SkAlign4(verbCnt) >> 2) + 2 * pointCnt + conicWeightCnt;
}

// Writes the path data key into the passed pointer.
void write_path_key_from_data(const SkPath& path, uint32_t* origKey) {
    uint32_t* key = origKey;
    // The check below should take care of negative values casted positive.
    SkSpan<const SkPathVerb> verbs = path.verbs();
    SkSpan<const SkPoint> points = path.points();
    SkSpan<const float> conics = path.conicWeights();
    SkASSERT(verbs.size() <= kMaxKeyFromDataVerbCnt);
    SkASSERT(points.size() && verbs.size());
    *key++ = SkToInt(verbs.size());
    memcpy(key, verbs.data(), verbs.size_bytes());
    const size_t verbKeySize = SkAlign4(verbs.size());
    // pad out to uint32_t alignment using value that will stand out when debugging.
    uint8_t* pad = reinterpret_cast<uint8_t*>(key)+ verbs.size();
    memset(pad, 0xDE, verbKeySize - verbs.size());
    key += verbKeySize >> 2;

    memcpy(key, points.data(), points.size_bytes());
    static_assert(sizeof(SkPoint) == 2 * sizeof(uint32_t));
    key += 2 * points.size();
    sk_careful_memcpy(key, conics.data(), conics.size_bytes());
    static_assert(sizeof(SkScalar) == sizeof(uint32_t));
    SkDEBUGCODE(key += conics.size());
    SkASSERT(key - origKey == path_key_from_data_size(path));
}
} // anonymous namespace

int Shape::keySize() const {
    int count = 1; // Every key has the state flags from the Shape
    switch(this->type()) {
        case Type::kLine:
            static_assert(0 == sizeof(skvx::float4) % sizeof(uint32_t));
            count += sizeof(skvx::float4) / sizeof(uint32_t);
            break;
        case Type::kRect:
            static_assert(0 == sizeof(Rect) % sizeof(uint32_t));
            count += sizeof(Rect) / sizeof(uint32_t);
            break;
        case Type::kRRect:
            static_assert(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
            count += SkRRect::kSizeInMemory / sizeof(uint32_t);
            break;
        case Type::kArc:
            static_assert(0 == sizeof(SkArc) % sizeof(uint32_t));
            count += sizeof(SkArc) / sizeof(uint32_t);
            break;
        case Type::kPath: {
            // An empty path is the same as an empty shape -- only needs the state flags
            if (!this->path().isEmpty()) {
                int dataKeySize = path_key_from_data_size(this->path());
                if (dataKeySize >= 0) {
                    count += dataKeySize;
                } else {
                    count++; // Just adds the gen ID.
                }
            }
            break;
        }
        default:
            // else it's empty, which just needs the state flags for its key
            SkASSERT(this->isEmpty());
    }
    return count;
}

void Shape::writeKey(uint32_t* key, bool includeInverted) const {
    SkASSERT(this->keySize());
    SkDEBUGCODE(uint32_t* origKey = key;)

    // Every key starts with the state from the Shape (this includes path fill type,
    // and any tracked inversion, as well as the class of geometry).
    *key++ = this->stateKey(includeInverted);

    switch(this->type()) {
        case Type::kPath: {
            // An empty path is the same as an empty shape -- only needs the state flags
            if (!this->path().isEmpty()) {
                // The path's inversion must match our state in order for the path's key to suffice.
                SkASSERT(this->inverted() == this->path().isInverseFillType());

                int dataKeySize = path_key_from_data_size(this->path());
                if (dataKeySize >= 0) {
                    // We check the rest of the size in write_path_key_from_data
                    SkASSERT(key - origKey == 1);
                    write_path_key_from_data(this->path(), key);
                    return;
                } else {
                    *key++ = this->path().getGenerationID();
                }
            }
            break;
        }
        case Type::kRect:
            memcpy(key, &this->rect(), sizeof(Rect));
            key += sizeof(Rect) / sizeof(uint32_t);
            break;
        case Type::kRRect:
            this->rrect().writeToMemory(key);
            key += SkRRect::kSizeInMemory / sizeof(uint32_t);
            break;
        case Type::kArc: {
            // Write dense floats first
            memcpy(key, &fArc, sizeof(SkRect) + 2 * sizeof(float));
            key += (sizeof(SkArc) / sizeof(uint32_t) - 1);
            // Then write the final bool as an int, to make sure upper bits are set
            *key++ = fArc.isWedge() ? 1 : 0;
            break;
        }
        case Type::kLine: {
            skvx::float4 line = this->line();
            memcpy(key, &line, sizeof(skvx::float4));
            key += sizeof(skvx::float4) / sizeof(uint32_t);
            break;
        }
        default:
            // Nothing other than the flag state is needed in the key for an empty shape
            SkASSERT(this->isEmpty());
    }
    SkASSERT(key - origKey == this->keySize());
}

namespace {
SkPathFillType noninverted_fill_type(SkPathFillType fillType) {
    switch (fillType) {
        case SkPathFillType::kWinding:
        case SkPathFillType::kInverseWinding:
            return SkPathFillType::kWinding;
        case SkPathFillType::kEvenOdd:
        case SkPathFillType::kInverseEvenOdd:
            return SkPathFillType::kEvenOdd;
    }
    SkUNREACHABLE;
}
} // anonymous namespace

uint32_t Shape::stateKey(bool includeInverted) const {
    uint32_t key;
    if (includeInverted) {
        // Use the path's full fill type instead of just whether or not it's inverted.
        key = this->isPath() ? static_cast<uint32_t>(fPath.getFillType())
                             : (fInverted ? 1 : 0);
    } else {
        // Use the path's noninverted fill type.
        key = this->isPath() ? static_cast<uint32_t>(noninverted_fill_type(fPath.getFillType()))
                             : 0;
    }
    key |= ((uint32_t) fType) << 2; // fill type was 2 bits
    return key;
}

} // namespace skgpu::graphite
