/*
 * 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/SkAttributes.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));
    SK_UNSAFE_TODO(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
