/*
 * 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/SkFixed.h"
#include "src/core/SkBlitter_A8.h"
#include "src/core/SkFloatBits.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
