/*
 * Copyright 2024 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/RasterPathUtils.h"

#include "include/core/SkStrokeRec.h"
#include "include/private/base/SkFixed.h"
#include "src/base/SkFloatBits.h"
#include "src/core/SkBlitter_A8.h"
#include "src/gpu/graphite/geom/Shape.h"
#include "src/gpu/graphite/geom/Transform.h"

namespace skgpu::graphite {

std::tuple<SkBitmap, RasterMaskHelper> RasterMaskHelper::Allocate(SkISize size,
                                                                  SkIVector translation,
                                                                  int padding,
                                                                  SkAlpha initialAlpha) {
    SkASSERT(padding >= 0);
    SkASSERT(!size.isEmpty());

    SkISize paddedSize{size.width() + 2 * padding, size.height() + 2 * padding};
    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::MakeA8(paddedSize));
    memset(bitmap.getAddr(0, 0), initialAlpha, bitmap.computeByteSize());

    const SkPixmap outerPM = bitmap.pixmap();
    SkPixmap innerPM;
    SkAssertResult(outerPM.extractSubset(&innerPM, SkIRect::MakePtSize({padding, padding}, size)));

    return std::make_tuple(std::move(bitmap), RasterMaskHelper{innerPM, translation});
}

RasterMaskHelper::RasterMaskHelper(SkPixmap pixmap, SkIVector translation)
        : fPixels{pixmap}
        , fRasterClip{SkIRect::MakeSize(pixmap.dimensions())} {
    SkASSERT(fPixels.addr());
    SkASSERT(!fPixels.info().dimensions().isEmpty());
    SkASSERT(pixmap.colorType() == kAlpha_8_SkColorType);

    fTranslate.fX = translation.fX;
    fTranslate.fY = translation.fY;
}

skcpu::Draw make_draw(const SkPixmap& pm, const SkRasterClip& rc, const SkMatrix& m) {
    skcpu::Draw draw;
    draw.fDst = pm;
    draw.fBlitterChooser = SkA8Blitter_Choose;
    draw.fCTM = &m;
    draw.fRC = &rc;
    return draw;
}

void RasterMaskHelper::drawShape(const Shape& shape,
                                 const Transform& localToDevice,
                                 const SkStrokeRec& strokeRec) {
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);  // "Replace" mode
    paint.setAntiAlias(true);
    // SkPaint's color is unpremul so this will produce alpha in every channel.
    paint.setColor(SK_ColorWHITE);
    strokeRec.applyToPaint(&paint);

    SkMatrix translatedMatrix = SkMatrix(localToDevice);
    translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);

    // TODO: use drawRect, drawRRect, drawArc
    SkPath path = shape.asPath();
    if (path.isInverseFillType()) {
        // The shader will handle the inverse fill in this case
        path.toggleInverseFillType();
    }
    make_draw(fPixels, fRasterClip, translatedMatrix).drawPathCoverage(path, paint);
}

void RasterMaskHelper::drawClip(const Shape& shape, const Transform& localToDevice, uint8_t alpha) {
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);  // "Replace" mode
    paint.setAntiAlias(true);
    // SkPaint's color is unpremul so this will produce alpha in every channel.
    paint.setColor(SkColorSetARGB(alpha, 0xFF, 0xFF, 0xFF));

    SkMatrix translatedMatrix = SkMatrix(localToDevice);
    translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);

    // TODO: use drawRect, drawRRect, drawArc
    SkPath path = shape.asPath();
    skcpu::Draw draw = make_draw(fPixels, fRasterClip, translatedMatrix);
    // Because we could be combining multiple paths into one entry we don't touch
    // the inverse fill in this case.
    if (0xFF == alpha) {
        SkASSERT(0xFF == paint.getAlpha());
        draw.drawPathCoverage(path, paint);
    } else {
        draw.drawPath(path, paint, nullptr);
    }
}

uint32_t add_transform_key(skgpu::UniqueKey::Builder* builder,
                           int startIndex,
                           const Transform& transform) {
    // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
    SkMatrix mat = transform.matrix().asM33();
    SkScalar sx = mat.get(SkMatrix::kMScaleX);
    SkScalar sy = mat.get(SkMatrix::kMScaleY);
    SkScalar kx = mat.get(SkMatrix::kMSkewX);
    SkScalar ky = mat.get(SkMatrix::kMSkewY);
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    // Fractional translate does not affect caching on Android. This is done for better cache
    // hit ratio and speed and is matching HWUI behavior, which didn't consider the matrix
    // at all when caching paths.
    SkFixed fracX = 0;
    SkFixed fracY = 0;
#else
    SkScalar tx = mat.get(SkMatrix::kMTransX);
    SkScalar ty = mat.get(SkMatrix::kMTransY);
    // Allow 8 bits each in x and y of subpixel positioning.
    SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
    SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
#endif
    (*builder)[startIndex + 0] = SkFloat2Bits(sx);
    (*builder)[startIndex + 1] = SkFloat2Bits(sy);
    (*builder)[startIndex + 2] = SkFloat2Bits(kx);
    (*builder)[startIndex + 3] = SkFloat2Bits(ky);
    // FracX and fracY are &ed with 0x0000ff00, so need to shift one down to fill 16 bits.
    uint32_t fracBits = fracX | (fracY >> 8);

    return fracBits;
}

skgpu::UniqueKey GeneratePathMaskKey(const Shape& shape,
                                     const Transform& transform,
                                     const SkStrokeRec& strokeRec,
                                     skvx::half2 maskOrigin,
                                     skvx::half2 maskSize) {
    skgpu::UniqueKey maskKey;
    {
        static const skgpu::UniqueKey::Domain kDomain = skgpu::UniqueKey::GenerateDomain();
        uint16_t styleKeySize = 7;
        if (!strokeRec.isHairlineStyle() && !strokeRec.isFillStyle()) {
            // Add space for width and miter if needed
            styleKeySize += 2;
        }
        skgpu::UniqueKey::Builder builder(&maskKey, kDomain, styleKeySize + shape.keySize(),
                                          "Raster Path Mask");
        builder[0] = maskOrigin.x() | (maskOrigin.y() << 16);
        builder[1] = maskSize.x() | (maskSize.y() << 16);

        // Add transform key and get packed fractional translation bits
        uint32_t fracBits = add_transform_key(&builder, 2, transform);
        // Distinguish between path styles. For anything but fill, we also need to include
        // the cap. (SW grows hairlines by 0.5 pixel with round and square caps). For stroke
        // or fill-and-stroke we need to include the join, width, and miter.
        static_assert(SkStrokeRec::kStyleCount <= (1 << 2));
        static_assert(SkPaint::kCapCount <= (1 << 2));
        static_assert(SkPaint::kJoinCount <= (1 << 2));
        uint32_t styleBits = strokeRec.getStyle();
        if (!strokeRec.isFillStyle()) {
            styleBits |= (strokeRec.getCap() << 2);
        }
        if (!strokeRec.isHairlineStyle() && !strokeRec.isFillStyle()) {
            styleBits |= (strokeRec.getJoin() << 4);
            builder[6] = SkFloat2Bits(strokeRec.getWidth());
            builder[7] = SkFloat2Bits(strokeRec.getMiter());
        }
        builder[styleKeySize-1] = fracBits | (styleBits << 16);
        shape.writeKey(&builder[styleKeySize], /*includeInverted=*/false);
    }
    return maskKey;
}

skgpu::UniqueKey GenerateClipMaskKey(uint32_t stackRecordID,
                                     const ClipStack::ElementList* elementsForMask,
                                     SkIRect maskDeviceBounds,
                                     bool includeBounds,
                                     SkIRect* keyBounds,
                                     bool* usesPathKey) {
    static constexpr int kMaxShapeCountForKey = 2;
    static const skgpu::UniqueKey::Domain kDomain = skgpu::UniqueKey::GenerateDomain();

    skgpu::UniqueKey maskKey;
    // if the element list is too large we just use the stackRecordID
    if (elementsForMask->size() <= kMaxShapeCountForKey) {
        static constexpr int kXformKeySize = 5;
        uint16_t keySize = includeBounds ? 2 : 0;
        // Iterate through to get key size; given kMaxShapeCountForKey and Shape's own key size
        // limitations, this should always fit safely within a 16-bit number
        for (int i = 0; i < elementsForMask->size(); ++i) {
            keySize += kXformKeySize + (*elementsForMask)[i]->fShape.keySize();
        }

        skgpu::UniqueKey::Builder builder(&maskKey, kDomain, keySize, "Clip Path Mask");
        int elementKeyIndex = 0;
        Rect unclippedBounds = Rect::InfiniteInverted();
        for (int i = 0; i < elementsForMask->size(); ++i) {
            const ClipStack::Element* element = (*elementsForMask)[i];

            // Add transform key and get packed fractional translation bits
            uint32_t fracBits = add_transform_key(&builder,
                                                    elementKeyIndex,
                                                    element->fLocalToDevice);
            uint32_t opBits = static_cast<uint32_t>(element->fOp);
            builder[elementKeyIndex + 4] = fracBits | (opBits << 16);

            const Shape& shape = element->fShape;
            shape.writeKey(&builder[elementKeyIndex + kXformKeySize],
                            /*includeInverted=*/true);

            elementKeyIndex += kXformKeySize + shape.keySize();

            Rect transformedBounds = element->fLocalToDevice.mapRect(element->fShape.bounds());
            unclippedBounds.join(transformedBounds);
        }

        // The keyBounds are the maskDeviceBounds relative to the full transformed mask. We use
        // this to ensure we capture the situation where the maskDeviceBounds are equal in two
        // cases but actually enclose different regions of the full mask due to an integer
        // translation (which is not captured in the key) in the element transforms.
        *keyBounds = maskDeviceBounds.makeOffset(-unclippedBounds.left(),
                                                    -unclippedBounds.top());

        if (includeBounds) {
            SkASSERT(SkTFitsIn<int16_t>(keyBounds->left()));
            SkASSERT(SkTFitsIn<int16_t>(keyBounds->top()));
            SkASSERT(SkTFitsIn<int16_t>(keyBounds->right()));
            SkASSERT(SkTFitsIn<int16_t>(keyBounds->bottom()));

            builder[elementKeyIndex] = keyBounds->left() | (keyBounds->top() << 16);
            builder[elementKeyIndex+1] = keyBounds->right() | (keyBounds->bottom() << 16);
        }

        *usesPathKey = true;
        return maskKey;
    }

    // Either we have too many elements or at least one shape can't create a key
    skgpu::UniqueKey::Builder builder(&maskKey, kDomain, 1, "Clip SaveRecord Mask");
    builder[0] = stackRecordID;

    *usesPathKey = false;
    // It doesn't matter what the keyBounds are in this case --
    // the stackRecordID is enough to distinguish between clips.
    *keyBounds = {};
    return maskKey;
}

}  // namespace skgpu::graphite
