/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkBitmap_DEFINED
#define SkBitmap_DEFINED

#include "include/core/SkAlphaType.h"
#include "include/core/SkColor.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkCPUTypes.h"
#include "include/private/base/SkDebug.h"

#include <cstddef>
#include <cstdint>

class SkColorSpace;
class SkImage;
class SkMatrix;
class SkMipmap;
class SkPaint;
class SkPixelRef;
class SkShader;
enum SkColorType : int;
enum class SkTileMode;
struct SkMaskBuilder;

/** \class SkBitmap
    SkBitmap describes a two-dimensional raster pixel array. SkBitmap is built on
    SkImageInfo, containing integer width and height, SkColorType and SkAlphaType
    describing the pixel format, and SkColorSpace describing the range of colors.
    SkBitmap points to SkPixelRef, which describes the physical array of pixels.
    SkImageInfo bounds may be located anywhere fully inside SkPixelRef bounds.

    SkBitmap can be drawn using SkCanvas. SkBitmap can be a drawing destination for SkCanvas
    draw member functions. SkBitmap flexibility as a pixel container limits some
    optimizations available to the target platform.

    If pixel array is primarily read-only, use SkImage for better performance.
    If pixel array is primarily written to, use SkSurface for better performance.

    Declaring SkBitmap const prevents altering SkImageInfo: the SkBitmap height, width,
    and so on cannot change. It does not affect SkPixelRef: a caller may write its
    pixels. Declaring SkBitmap const affects SkBitmap configuration, not its contents.

    SkBitmap is not thread safe. Each thread must have its own copy of SkBitmap fields,
    although threads may share the underlying pixel array.
*/
class SK_API SkBitmap {
public:
    class SK_API Allocator;

    /** Creates an empty SkBitmap without pixels, with kUnknown_SkColorType,
        kUnknown_SkAlphaType, and with a width and height of zero. SkPixelRef origin is
        set to (0, 0).

        Use setInfo() to associate SkColorType, SkAlphaType, width, and height
        after SkBitmap has been created.

        @return  empty SkBitmap

        example: https://fiddle.skia.org/c/@Bitmap_empty_constructor
    */
    SkBitmap();

    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
        allocated, so both bitmaps reference the same pixels.

        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef
        @return     copy of src

        example: https://fiddle.skia.org/c/@Bitmap_copy_const_SkBitmap
    */
    SkBitmap(const SkBitmap& src);

    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
        SkBitmap.

        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef
        @return     copy of src

        example: https://fiddle.skia.org/c/@Bitmap_move_SkBitmap
    */
    SkBitmap(SkBitmap&& src);

    /** Decrements SkPixelRef reference count, if SkPixelRef is not nullptr.
    */
    ~SkBitmap();

    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
        allocated, so both bitmaps reference the same pixels.

        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef
        @return     copy of src

        example: https://fiddle.skia.org/c/@Bitmap_copy_operator
    */
    SkBitmap& operator=(const SkBitmap& src);

    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
        SkBitmap.

        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef
        @return     copy of src

        example: https://fiddle.skia.org/c/@Bitmap_move_operator
    */
    SkBitmap& operator=(SkBitmap&& src);

    /** Swaps the fields of the two bitmaps.

        @param other  SkBitmap exchanged with original

        example: https://fiddle.skia.org/c/@Bitmap_swap
    */
    void swap(SkBitmap& other);

    /** Returns a constant reference to the SkPixmap holding the SkBitmap pixel
        address, row bytes, and SkImageInfo.

        @return  reference to SkPixmap describing this SkBitmap
    */
    const SkPixmap& pixmap() const { return fPixmap; }

    /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.

        @return  reference to SkImageInfo
    */
    const SkImageInfo& info() const { return fPixmap.info(); }

    /** Returns pixel count in each row. Should be equal or less than
        rowBytes() / info().bytesPerPixel().

        May be less than pixelRef().width(). Will not exceed pixelRef().width() less
        pixelRefOrigin().fX.

        @return  pixel width in SkImageInfo
    */
    int width() const { return fPixmap.width(); }

    /** Returns pixel row count.

        Maybe be less than pixelRef().height(). Will not exceed pixelRef().height() less
        pixelRefOrigin().fY.

        @return  pixel height in SkImageInfo
    */
    int height() const { return fPixmap.height(); }

    SkColorType colorType() const { return fPixmap.colorType(); }

    SkAlphaType alphaType() const { return fPixmap.alphaType(); }

    /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
        reference count of SkColorSpace is unchanged. The returned SkColorSpace is
        immutable.

        @return  SkColorSpace in SkImageInfo, or nullptr
    */
    SkColorSpace* colorSpace() const;

    /** Returns smart pointer to SkColorSpace, the range of colors, associated with
        SkImageInfo. The smart pointer tracks the number of objects sharing this
        SkColorSpace reference so the memory is released when the owners destruct.

        The returned SkColorSpace is immutable.

        @return  SkColorSpace in SkImageInfo wrapped in a smart pointer
    */
    sk_sp<SkColorSpace> refColorSpace() const;

    /** Returns number of bytes per pixel required by SkColorType.
        Returns zero if colorType( is kUnknown_SkColorType.

        @return  bytes in pixel
    */
    int bytesPerPixel() const { return fPixmap.info().bytesPerPixel(); }

    /** Returns number of pixels that fit on row. Should be greater than or equal to
        width().

        @return  maximum pixels per row
    */
    int rowBytesAsPixels() const { return fPixmap.rowBytesAsPixels(); }

    /** Returns bit shift converting row bytes to row pixels.
        Returns zero for kUnknown_SkColorType.

        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes
    */
    int shiftPerPixel() const { return fPixmap.shiftPerPixel(); }

    /** Returns true if either width() or height() are zero.

        Does not check if SkPixelRef is nullptr; call drawsNothing() to check width(),
        height(), and SkPixelRef.

        @return  true if dimensions do not enclose area
    */
    bool empty() const { return fPixmap.info().isEmpty(); }

    /** Returns true if SkPixelRef is nullptr.

        Does not check if width() or height() are zero; call drawsNothing() to check
        width(), height(), and SkPixelRef.

        @return  true if no SkPixelRef is associated
    */
    bool isNull() const { return nullptr == fPixelRef; }

    /** Returns true if width() or height() are zero, or if SkPixelRef is nullptr.
        If true, SkBitmap has no effect when drawn or drawn into.

        @return  true if drawing has no effect
    */
    bool drawsNothing() const {
        return this->empty() || this->isNull();
    }

    /** Returns row bytes, the interval from one pixel row to the next. Row bytes
        is at least as large as: width() * info().bytesPerPixel().

        Returns zero if colorType() is kUnknown_SkColorType, or if row bytes supplied to
        setInfo() is not large enough to hold a row of pixels.

        @return  byte length of pixel row
    */
    size_t rowBytes() const { return fPixmap.rowBytes(); }

    /** Sets SkAlphaType, if alphaType is compatible with SkColorType.
        Returns true unless alphaType is kUnknown_SkAlphaType and current SkAlphaType
        is not kUnknown_SkAlphaType.

        Returns true if SkColorType is kUnknown_SkColorType. alphaType is ignored, and
        SkAlphaType remains kUnknown_SkAlphaType.

        Returns true if SkColorType is kRGB_565_SkColorType or kGray_8_SkColorType.
        alphaType is ignored, and SkAlphaType remains kOpaque_SkAlphaType.

        If SkColorType is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: returns true unless
        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored.

        If SkColorType is kAlpha_8_SkColorType, returns true unless
        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored. If alphaType is
        kUnpremul_SkAlphaType, it is treated as kPremul_SkAlphaType.

        This changes SkAlphaType in SkPixelRef; all bitmaps sharing SkPixelRef
        are affected.

        @return           true if SkAlphaType is set

        example: https://fiddle.skia.org/c/@Bitmap_setAlphaType
    */
    bool setAlphaType(SkAlphaType alphaType);

    /** Returns pixel address, the base address corresponding to the pixel origin.

        @return  pixel address
    */
    void* getPixels() const { return fPixmap.writable_addr(); }

    /** Returns minimum memory required for pixel storage.
        Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
        Returns SIZE_MAX if result does not fit in size_t.
        Returns zero if height() or width() is 0.
        Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.

        @return  size in bytes of image buffer
    */
    size_t computeByteSize() const { return fPixmap.computeByteSize(); }

    /** Returns true if pixels can not change.

        Most immutable SkBitmap checks trigger an assert only on debug builds.

        @return  true if pixels are immutable

        example: https://fiddle.skia.org/c/@Bitmap_isImmutable
    */
    bool isImmutable() const;

    /** Sets internal flag to mark SkBitmap as immutable. Once set, pixels can not change.
        Any other bitmap sharing the same SkPixelRef are also marked as immutable.
        Once SkPixelRef is marked immutable, the setting cannot be cleared.

        Writing to immutable SkBitmap pixels triggers an assert on debug builds.

        example: https://fiddle.skia.org/c/@Bitmap_setImmutable
    */
    void setImmutable();

    /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
        alpha value is implicitly or explicitly 1.0. If true, and all pixels are
        not opaque, Skia may draw incorrectly.

        Does not check if SkColorType allows alpha, or if any pixel value has
        transparency.

        @return  true if SkImageInfo SkAlphaType is kOpaque_SkAlphaType
    */
    bool isOpaque() const {
        return SkAlphaTypeIsOpaque(this->alphaType());
    }

    /** Resets to its initial state; all fields are set to zero, as if SkBitmap had
        been initialized by SkBitmap().

        Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
        kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.

        If SkPixelRef is allocated, its reference count is decreased by one, releasing
        its memory if SkBitmap is the sole owner.

        example: https://fiddle.skia.org/c/@Bitmap_reset
    */
    void reset();

    /** Returns true if all pixels are opaque. SkColorType determines how pixels
        are encoded, and whether pixel describes alpha. Returns true for SkColorType
        without alpha in each pixel; for other SkColorType, returns true if all
        pixels have alpha values equivalent to 1.0 or greater.

        For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
        returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
        kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
        For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
        For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
        greater.

        Returns false for kUnknown_SkColorType.

        @param bm  SkBitmap to check
        @return    true if all pixels have opaque values or SkColorType is opaque
    */
    static bool ComputeIsOpaque(const SkBitmap& bm) {
        return bm.pixmap().computeIsOpaque();
    }

    /** Returns SkRect { 0, 0, width(), height() }.

        @param bounds  container for floating point rectangle

        example: https://fiddle.skia.org/c/@Bitmap_getBounds
    */
    void getBounds(SkRect* bounds) const;

    /** Returns SkIRect { 0, 0, width(), height() }.

        @param bounds  container for integral rectangle

        example: https://fiddle.skia.org/c/@Bitmap_getBounds_2
    */
    void getBounds(SkIRect* bounds) const;

    /** Returns SkIRect { 0, 0, width(), height() }.

        @return  integral rectangle from origin to width() and height()
    */
    SkIRect bounds() const { return fPixmap.info().bounds(); }

    /** Returns SkISize { width(), height() }.

        @return  integral size of width() and height()
    */
    SkISize dimensions() const { return fPixmap.info().dimensions(); }

    /** Returns the bounds of this bitmap, offset by its SkPixelRef origin.

        @return  bounds within SkPixelRef bounds
    */
    SkIRect getSubset() const {
        SkIPoint origin = this->pixelRefOrigin();
        return SkIRect::MakeXYWH(origin.x(), origin.y(), this->width(), this->height());
    }

    /** Sets width, height, SkAlphaType, SkColorType, SkColorSpace, and optional
        rowBytes. Frees pixels, and returns true if successful.

        imageInfo.alphaType() may be altered to a value permitted by imageInfo.colorSpace().
        If imageInfo.colorType() is kUnknown_SkColorType, imageInfo.alphaType() is
        set to kUnknown_SkAlphaType.
        If imageInfo.colorType() is kAlpha_8_SkColorType and imageInfo.alphaType() is
        kUnpremul_SkAlphaType, imageInfo.alphaType() is replaced by kPremul_SkAlphaType.
        If imageInfo.colorType() is kRGB_565_SkColorType or kGray_8_SkColorType,
        imageInfo.alphaType() is set to kOpaque_SkAlphaType.
        If imageInfo.colorType() is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: imageInfo.alphaType() remains
        unchanged.

        rowBytes must equal or exceed imageInfo.minRowBytes(). If imageInfo.colorSpace() is
        kUnknown_SkColorType, rowBytes is ignored and treated as zero; for all other
        SkColorSpace values, rowBytes of zero is treated as imageInfo.minRowBytes().

        Calls reset() and returns false if:
        - rowBytes exceeds 31 bits
        - imageInfo.width() is negative
        - imageInfo.height() is negative
        - rowBytes is positive and less than imageInfo.width() times imageInfo.bytesPerPixel()

        @param imageInfo  contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param rowBytes   imageInfo.minRowBytes() or larger; or zero
        @return           true if SkImageInfo set successfully

        example: https://fiddle.skia.org/c/@Bitmap_setInfo
    */
    bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);

    /** \enum SkBitmap::AllocFlags
        AllocFlags is obsolete.  We always zero pixel memory when allocated.
    */
    enum AllocFlags {
        kZeroPixels_AllocFlag = 1 << 0, //!< zero pixel memory.  No effect.  This is the default.
    };

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory. Memory is zeroed.

        Returns false and calls reset() if SkImageInfo could not be set, or memory could
        not be allocated, or memory could not optionally be zeroed.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of calloc().

        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param flags  kZeroPixels_AllocFlag, or zero
        @return       true if pixels allocation is successful
    */
    [[nodiscard]] bool tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory. Memory is zeroed.

        Aborts execution if SkImageInfo could not be set, or memory could
        not be allocated, or memory could not optionally
        be zeroed. Abort steps may be provided by the user at compile time by defining
        SK_ABORT.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of calloc().

        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param flags  kZeroPixels_AllocFlag, or zero

        example: https://fiddle.skia.org/c/@Bitmap_allocPixelsFlags
    */
    void allocPixelsFlags(const SkImageInfo& info, uint32_t flags);

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.

        Returns false and calls reset() if SkImageInfo could not be set, or memory could
        not be allocated.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of malloc().

        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param rowBytes  size of pixel row or larger; may be zero
        @return          true if pixel storage is allocated
    */
    [[nodiscard]] bool tryAllocPixels(const SkImageInfo& info, size_t rowBytes);

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.

        Aborts execution if SkImageInfo could not be set, or memory could
        not be allocated. Abort steps may be provided by
        the user at compile time by defining SK_ABORT.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of malloc().

        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param rowBytes  size of pixel row or larger; may be zero

        example: https://fiddle.skia.org/c/@Bitmap_allocPixels
    */
    void allocPixels(const SkImageInfo& info, size_t rowBytes);

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory.

        Returns false and calls reset() if SkImageInfo could not be set, or memory could
        not be allocated.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of malloc().

        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @return      true if pixel storage is allocated
    */
    [[nodiscard]] bool tryAllocPixels(const SkImageInfo& info) {
        return this->tryAllocPixels(info, info.minRowBytes());
    }

    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
        memory.

        Aborts execution if SkImageInfo could not be set, or memory could
        not be allocated. Abort steps may be provided by
        the user at compile time by defining SK_ABORT.

        On most platforms, allocating pixel memory may succeed even though there is
        not sufficient memory to hold pixels; allocation does not take place
        until the pixels are written to. The actual behavior depends on the platform
        implementation of malloc().

        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace

        example: https://fiddle.skia.org/c/@Bitmap_allocPixels_2
    */
    void allocPixels(const SkImageInfo& info);

    /** Sets SkImageInfo to width, height, and native color type; and allocates
        pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
        otherwise, sets to kPremul_SkAlphaType.

        Calls reset() and returns false if width exceeds 29 bits or is negative,
        or height is negative.

        Returns false if allocation fails.

        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
        the platform. SkBitmap drawn to output device skips converting its pixel format.

        @param width     pixel column count; must be zero or greater
        @param height    pixel row count; must be zero or greater
        @param isOpaque  true if pixels do not have transparency
        @return          true if pixel storage is allocated
    */
    [[nodiscard]] bool tryAllocN32Pixels(int width, int height, bool isOpaque = false);

    /** Sets SkImageInfo to width, height, and the native color type; and allocates
        pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
        otherwise, sets to kPremul_SkAlphaType.

        Aborts if width exceeds 29 bits or is negative, or height is negative, or
        allocation fails. Abort steps may be provided by the user at compile time by
        defining SK_ABORT.

        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
        the platform. SkBitmap drawn to output device skips converting its pixel format.

        @param width     pixel column count; must be zero or greater
        @param height    pixel row count; must be zero or greater
        @param isOpaque  true if pixels do not have transparency

        example: https://fiddle.skia.org/c/@Bitmap_allocN32Pixels
    */
    void allocN32Pixels(int width, int height, bool isOpaque = false);

    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
        containing pixels and rowBytes. releaseProc, if not nullptr, is called
        immediately on failure or when pixels are no longer referenced. context may be
        nullptr.

        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
        calls releaseProc if present, calls reset(), and returns false.

        Otherwise, if pixels equals nullptr: sets SkImageInfo, calls releaseProc if
        present, returns true.

        If SkImageInfo is set, pixels is not nullptr, and releaseProc is not nullptr:
        when pixels are no longer referenced, calls releaseProc with pixels and context
        as parameters.

        @param info         contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param pixels       address or pixel storage; may be nullptr
        @param rowBytes     size of pixel row or larger
        @param releaseProc  function called when pixels can be deleted; may be nullptr
        @param context      caller state passed to releaseProc; may be nullptr
        @return             true if SkImageInfo is set to info
    */
    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                       void (*releaseProc)(void* addr, void* context), void* context);

    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
        containing pixels and rowBytes.

        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
        calls reset(), and returns false.

        Otherwise, if pixels equals nullptr: sets SkImageInfo, returns true.

        Caller must ensure that pixels are valid for the lifetime of SkBitmap and SkPixelRef.

        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
        @param pixels    address or pixel storage; may be nullptr
        @param rowBytes  size of pixel row or larger
        @return          true if SkImageInfo is set to info
    */
    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
        return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);
    }

    /** Sets SkImageInfo to pixmap.info() following the rules in setInfo(), and creates
        SkPixelRef containing pixmap.addr() and pixmap.rowBytes().

        If SkImageInfo could not be set, or pixmap.rowBytes() is less than
        SkImageInfo::minRowBytes(): calls reset(), and returns false.

        Otherwise, if pixmap.addr() equals nullptr: sets SkImageInfo, returns true.

        Caller must ensure that pixmap is valid for the lifetime of SkBitmap and SkPixelRef.

        @param pixmap  SkImageInfo, pixel address, and rowBytes()
        @return        true if SkImageInfo was set to pixmap.info()

        example: https://fiddle.skia.org/c/@Bitmap_installPixels_3
    */
    bool installPixels(const SkPixmap& pixmap);

    /** Deprecated.
    */
    bool installMaskPixels(SkMaskBuilder& mask);

    /** Replaces SkPixelRef with pixels, preserving SkImageInfo and rowBytes().
        Sets SkPixelRef origin to (0, 0).

        If pixels is nullptr, or if info().colorType() equals kUnknown_SkColorType;
        release reference to SkPixelRef, and set SkPixelRef to nullptr.

        Caller is responsible for handling ownership pixel memory for the lifetime
        of SkBitmap and SkPixelRef.

        @param pixels  address of pixel storage, managed by caller

        example: https://fiddle.skia.org/c/@Bitmap_setPixels
    */
    void setPixels(void* pixels);

    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
        The allocation size is determined by SkImageInfo width, height, and SkColorType.

        Returns false if info().colorType() is kUnknown_SkColorType, or allocation fails.

        @return  true if the allocation succeeds
    */
    [[nodiscard]] bool tryAllocPixels() {
        return this->tryAllocPixels((Allocator*)nullptr);
    }

    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
        The allocation size is determined by SkImageInfo width, height, and SkColorType.

        Aborts if info().colorType() is kUnknown_SkColorType, or allocation fails.
        Abort steps may be provided by the user at compile
        time by defining SK_ABORT.

        example: https://fiddle.skia.org/c/@Bitmap_allocPixels_3
    */
    void allocPixels();

    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
        The allocation size is determined by SkImageInfo width, height, and SkColorType.
        If allocator is nullptr, use HeapAllocator instead.

        Returns false if Allocator::allocPixelRef return false.

        @param allocator  instance of SkBitmap::Allocator instantiation
        @return           true if custom allocator reports success
    */
    [[nodiscard]] bool tryAllocPixels(Allocator* allocator);

    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
        The allocation size is determined by SkImageInfo width, height, and SkColorType.
        If allocator is nullptr, use HeapAllocator instead.

        Aborts if Allocator::allocPixelRef return false. Abort steps may be provided by
        the user at compile time by defining SK_ABORT.

        @param allocator  instance of SkBitmap::Allocator instantiation

        example: https://fiddle.skia.org/c/@Bitmap_allocPixels_4
    */
    void allocPixels(Allocator* allocator);

    /** Returns SkPixelRef, which contains: pixel base address; its dimensions; and
        rowBytes(), the interval from one row to the next. Does not change SkPixelRef
        reference count. SkPixelRef may be shared by multiple bitmaps.
        If SkPixelRef has not been set, returns nullptr.

        @return  SkPixelRef, or nullptr
    */
    SkPixelRef* pixelRef() const { return fPixelRef.get(); }

    /** Returns origin of pixels within SkPixelRef. SkBitmap bounds is always contained
        by SkPixelRef bounds, which may be the same size or larger. Multiple SkBitmap
        can share the same SkPixelRef, where each SkBitmap has different bounds.

        The returned origin added to SkBitmap dimensions equals or is smaller than the
        SkPixelRef dimensions.

        Returns (0, 0) if SkPixelRef is nullptr.

        @return  pixel origin within SkPixelRef

        example: https://fiddle.skia.org/c/@Bitmap_pixelRefOrigin
    */
    SkIPoint pixelRefOrigin() const;

    /** Replaces pixelRef and origin in SkBitmap.  dx and dy specify the offset
        within the SkPixelRef pixels for the top-left corner of the bitmap.

        Asserts in debug builds if dx or dy are out of range. Pins dx and dy
        to legal range in release builds.

        The caller is responsible for ensuring that the pixels match the
        SkColorType and SkAlphaType in SkImageInfo.

        @param pixelRef  SkPixelRef describing pixel address and rowBytes()
        @param dx        column offset in SkPixelRef for bitmap origin
        @param dy        row offset in SkPixelRef for bitmap origin

        example: https://fiddle.skia.org/c/@Bitmap_setPixelRef
    */
    void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);

    /** Returns true if SkBitmap is can be drawn.

        @return  true if getPixels() is not nullptr
    */
    bool readyToDraw() const {
        return this->getPixels() != nullptr;
    }

    /** Returns a unique value corresponding to the pixels in SkPixelRef.
        Returns a different value after notifyPixelsChanged() has been called.
        Returns zero if SkPixelRef is nullptr.

        Determines if pixels have changed since last examined.

        @return  unique value for pixels in SkPixelRef

        example: https://fiddle.skia.org/c/@Bitmap_getGenerationID
    */
    uint32_t getGenerationID() const;

    /** Marks that pixels in SkPixelRef have changed. Subsequent calls to
        getGenerationID() return a different value.

        example: https://fiddle.skia.org/c/@Bitmap_notifyPixelsChanged
    */
    void notifyPixelsChanged() const;

    /** Replaces pixel values with c, interpreted as being in the sRGB SkColorSpace.
        All pixels contained by bounds() are affected. If the colorType() is
        kGray_8_SkColorType or kRGB_565_SkColorType, then alpha is ignored; RGB is
        treated as opaque. If colorType() is kAlpha_8_SkColorType, then RGB is ignored.

        @param c            unpremultiplied color

        example: https://fiddle.skia.org/c/@Bitmap_eraseColor
    */
    void eraseColor(SkColor4f) const;

    /** Replaces pixel values with c, interpreted as being in the sRGB SkColorSpace.
        All pixels contained by bounds() are affected. If the colorType() is
        kGray_8_SkColorType or kRGB_565_SkColorType, then alpha is ignored; RGB is
        treated as opaque. If colorType() is kAlpha_8_SkColorType, then RGB is ignored.

        Input color is ultimately converted to an SkColor4f, so eraseColor(SkColor4f c)
        will have higher color resolution.

        @param c  unpremultiplied color.

        example: https://fiddle.skia.org/c/@Bitmap_eraseColor
    */
    void eraseColor(SkColor c) const;

    /** Replaces pixel values with unpremultiplied color built from a, r, g, and b,
        interpreted as being in the sRGB SkColorSpace. All pixels contained by
        bounds() are affected. If the colorType() is kGray_8_SkColorType or
        kRGB_565_SkColorType, then a is ignored; r, g, and b are treated as opaque.
        If colorType() is kAlpha_8_SkColorType, then r, g, and b are ignored.

        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
        @param r  amount of red, from no red (0) to full red (255)
        @param g  amount of green, from no green (0) to full green (255)
        @param b  amount of blue, from no blue (0) to full blue (255)
    */
    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
        this->eraseColor(SkColorSetARGB(a, r, g, b));
    }

    /** Replaces pixel values inside area with c. interpreted as being in the sRGB
        SkColorSpace. If area does not intersect bounds(), call has no effect.

        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
        then RGB is ignored.

        @param c            unpremultiplied color
        @param area         rectangle to fill

        example: https://fiddle.skia.org/c/@Bitmap_erase
    */
    void erase(SkColor4f c, const SkIRect& area) const;

    /** Replaces pixel values inside area with c. interpreted as being in the sRGB
        SkColorSpace. If area does not intersect bounds(), call has no effect.

        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
        then RGB is ignored.

        Input color is ultimately converted to an SkColor4f, so erase(SkColor4f c)
        will have higher color resolution.

        @param c     unpremultiplied color
        @param area  rectangle to fill

        example: https://fiddle.skia.org/c/@Bitmap_erase
    */
    void erase(SkColor c, const SkIRect& area) const;

    /** Deprecated.
    */
    void eraseArea(const SkIRect& area, SkColor c) const {
        this->erase(c, area);
    }

    /** Returns pixel at (x, y) as unpremultiplied color.
        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.

        Input is not validated: out of bounds values of x or y trigger an assert() if
        built with SK_DEBUG defined; and returns undefined values or may crash if
        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
        pixel address is nullptr.

        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
        conversion to unpremultiplied color; original pixel data may have additional
        precision.

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   pixel converted to unpremultiplied color
    */
    SkColor getColor(int x, int y) const {
        return this->pixmap().getColor(x, y);
    }

    /** Returns pixel at (x, y) as unpremultiplied float color.
        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.

        Input is not validated: out of bounds values of x or y trigger an assert() if
        built with SK_DEBUG defined; and returns undefined values or may crash if
        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
        pixel address is nullptr.

        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
        conversion to unpremultiplied color.

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   pixel converted to unpremultiplied color
    */
    SkColor4f getColor4f(int x, int y) const { return this->pixmap().getColor4f(x, y); }

    /** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
        This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
        (and more precise if the pixels store more than 8 bits per component).

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   alpha converted to normalized float
     */
    float getAlphaf(int x, int y) const {
        return this->pixmap().getAlphaf(x, y);
    }

    /** Returns pixel address at (x, y).

        Input is not validated: out of bounds values of x or y, or kUnknown_SkColorType,
        trigger an assert() if built with SK_DEBUG defined. Returns nullptr if
        SkColorType is kUnknown_SkColorType, or SkPixelRef is nullptr.

        Performs a lookup of pixel size; for better performance, call
        one of: getAddr8(), getAddr16(), or getAddr32().

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   generic pointer to pixel

        example: https://fiddle.skia.org/c/@Bitmap_getAddr
    */
    void* getAddr(int x, int y) const;

    /** Returns address at (x, y).

        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
        - SkPixelRef is nullptr
        - bytesPerPixel() is not four
        - x is negative, or not less than width()
        - y is negative, or not less than height()

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   unsigned 32-bit pointer to pixel at (x, y)
    */
    inline uint32_t* getAddr32(int x, int y) const;

    /** Returns address at (x, y).

        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
        - SkPixelRef is nullptr
        - bytesPerPixel() is not two
        - x is negative, or not less than width()
        - y is negative, or not less than height()

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   unsigned 16-bit pointer to pixel at (x, y)
    */
    inline uint16_t* getAddr16(int x, int y) const;

    /** Returns address at (x, y).

        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
        - SkPixelRef is nullptr
        - bytesPerPixel() is not one
        - x is negative, or not less than width()
        - y is negative, or not less than height()

        @param x  column index, zero or greater, and less than width()
        @param y  row index, zero or greater, and less than height()
        @return   unsigned 8-bit pointer to pixel at (x, y)
    */
    inline uint8_t* getAddr8(int x, int y) const;

    /** Shares SkPixelRef with dst. Pixels are not copied; SkBitmap and dst point
        to the same pixels; dst bounds() are set to the intersection of subset
        and the original bounds().

        subset may be larger than bounds(). Any area outside of bounds() is ignored.

        Any contents of dst are discarded.

        Return false if:
        - dst is nullptr
        - SkPixelRef is nullptr
        - subset does not intersect bounds()

        @param dst     SkBitmap set to subset
        @param subset  rectangle of pixels to reference
        @return        true if dst is replaced by subset

        example: https://fiddle.skia.org/c/@Bitmap_extractSubset
    */
    bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;

    /** Copies a SkRect of pixels from SkBitmap to dstPixels. Copy starts at (srcX, srcY),
        and does not exceed SkBitmap (width(), height()).

        dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
        destination. dstRowBytes specifics the gap from one destination row to the next.
        Returns true if pixels are copied. Returns false if:
        - dstInfo has no address
        - dstRowBytes is less than dstInfo.minRowBytes()
        - SkPixelRef is nullptr

        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
        If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
        If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
        match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
        false if pixel conversion is not possible.

        srcX and srcY may be negative to copy only top or left of source. Returns
        false if width() or height() is zero or negative.
        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().

        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
        @param dstPixels    destination pixel storage
        @param dstRowBytes  destination row length
        @param srcX         column index whose absolute value is less than width()
        @param srcY         row index whose absolute value is less than height()
        @return             true if pixels are copied to dstPixels
    */
    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                    int srcX, int srcY) const;

    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (srcX, srcY), and
        does not exceed SkBitmap (width(), height()).

        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
        and row bytes of destination. dst.rowBytes() specifics the gap from one destination
        row to the next. Returns true if pixels are copied. Returns false if:
        - dst pixel storage equals nullptr
        - dst.rowBytes is less than SkImageInfo::minRowBytes()
        - SkPixelRef is nullptr

        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
        false if pixel conversion is not possible.

        srcX and srcY may be negative to copy only top or left of source. Returns
        false if width() or height() is zero or negative.
        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().

        @param dst   destination SkPixmap: SkImageInfo, pixels, row bytes
        @param srcX  column index whose absolute value is less than width()
        @param srcY  row index whose absolute value is less than height()
        @return      true if pixels are copied to dst

        example: https://fiddle.skia.org/c/@Bitmap_readPixels_2
    */
    bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;

    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (0, 0), and
        does not exceed SkBitmap (width(), height()).

        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
        and row bytes of destination. dst.rowBytes() specifics the gap from one destination
        row to the next. Returns true if pixels are copied. Returns false if:
        - dst pixel storage equals nullptr
        - dst.rowBytes is less than SkImageInfo::minRowBytes()
        - SkPixelRef is nullptr

        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
        false if pixel conversion is not possible.

        @param dst  destination SkPixmap: SkImageInfo, pixels, row bytes
        @return     true if pixels are copied to dst
    */
    bool readPixels(const SkPixmap& dst) const {
        return this->readPixels(dst, 0, 0);
    }

    /** Copies a SkRect of pixels from src. Copy starts at (dstX, dstY), and does not exceed
        (src.width(), src.height()).

        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
        and row bytes of source. src.rowBytes() specifics the gap from one source
        row to the next. Returns true if pixels are copied. Returns false if:
        - src pixel storage equals nullptr
        - src.rowBytes is less than SkImageInfo::minRowBytes()
        - SkPixelRef is nullptr

        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
        false if pixel conversion is not possible.

        dstX and dstY may be negative to copy only top or left of source. Returns
        false if width() or height() is zero or negative.
        Returns false if abs(dstX) >= Bitmap width(), or if abs(dstY) >= Bitmap height().

        @param src   source SkPixmap: SkImageInfo, pixels, row bytes
        @param dstX  column index whose absolute value is less than width()
        @param dstY  row index whose absolute value is less than height()
        @return      true if src pixels are copied to SkBitmap

        example: https://fiddle.skia.org/c/@Bitmap_writePixels
    */
    bool writePixels(const SkPixmap& src, int dstX, int dstY);

    /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed
        (src.width(), src.height()).

        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
        and row bytes of source. src.rowBytes() specifics the gap from one source
        row to the next. Returns true if pixels are copied. Returns false if:
        - src pixel storage equals nullptr
        - src.rowBytes is less than SkImageInfo::minRowBytes()
        - SkPixelRef is nullptr

        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
        false if pixel conversion is not possible.

        @param src  source SkPixmap: SkImageInfo, pixels, row bytes
        @return     true if src pixels are copied to SkBitmap
    */
    bool writePixels(const SkPixmap& src) {
        return this->writePixels(src, 0, 0);
    }

    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
        or dst pixels cannot be allocated.

        Uses HeapAllocator to reserve memory for dst SkPixelRef.

        @param dst  holds SkPixelRef to fill with alpha layer
        @return     true if alpha layer was constructed in dst SkPixelRef
    */
    bool extractAlpha(SkBitmap* dst) const {
        return this->extractAlpha(dst, nullptr, nullptr, nullptr);
    }

    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
        or dst pixels cannot be allocated.

        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
        generates mask alpha from SkBitmap. Uses HeapAllocator to reserve memory for dst
        SkPixelRef. Sets offset to top-left position for dst for alignment with SkBitmap;
        (0, 0) unless SkMaskFilter generates mask.

        @param dst     holds SkPixelRef to fill with alpha layer
        @param paint   holds optional SkMaskFilter; may be nullptr
        @param offset  top-left position for dst; may be nullptr
        @return        true if alpha layer was constructed in dst SkPixelRef
    */
    bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
                      SkIPoint* offset) const {
        return this->extractAlpha(dst, paint, nullptr, offset);
    }

    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
        or dst pixels cannot be allocated.

        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
        generates mask alpha from SkBitmap. allocator may reference a custom allocation
        class or be set to nullptr to use HeapAllocator. Sets offset to top-left
        position for dst for alignment with SkBitmap; (0, 0) unless SkMaskFilter generates
        mask.

        @param dst        holds SkPixelRef to fill with alpha layer
        @param paint      holds optional SkMaskFilter; may be nullptr
        @param allocator  function to reserve memory for SkPixelRef; may be nullptr
        @param offset     top-left position for dst; may be nullptr
        @return           true if alpha layer was constructed in dst SkPixelRef
    */
    bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
                      SkIPoint* offset) const;

    /** Copies SkBitmap pixel address, row bytes, and SkImageInfo to pixmap, if address
        is available, and returns true. If pixel address is not available, return
        false and leave pixmap unchanged.

        pixmap contents become invalid on any future change to SkBitmap.

        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
        @return        true if SkBitmap has direct access to pixels

        example: https://fiddle.skia.org/c/@Bitmap_peekPixels
    */
    bool peekPixels(SkPixmap* pixmap) const;

    /**
     *  Make a shader with the specified tiling, matrix and sampling.
     */
    sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
                               const SkMatrix* localMatrix = nullptr) const;
    sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
                               const SkMatrix& lm) const;
    /** Defaults to clamp in both X and Y. */
    sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
    sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
                               const SkMatrix* lm = nullptr) const;

    /**
     *  Returns a new image from the bitmap. If the bitmap is marked immutable, this will
     *  share the pixel buffer. If not, it will make a copy of the pixels for the image.
     */
    sk_sp<SkImage> asImage() const;

    /** Asserts if internal values are illegal or inconsistent. Only available if
        SK_DEBUG is defined at compile time.
    */
    SkDEBUGCODE(void validate() const;)

    /** \class SkBitmap::Allocator
        Abstract subclass of HeapAllocator.
    */
    class Allocator : public SkRefCnt {
    public:

        /** Allocates the pixel memory for the bitmap, given its dimensions and
            SkColorType. Returns true on success, where success means either setPixels()
            or setPixelRef() was called.

            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output
            @return        true if SkPixelRef was allocated
        */
        virtual bool allocPixelRef(SkBitmap* bitmap) = 0;
    private:
        using INHERITED = SkRefCnt;
    };

    /** \class SkBitmap::HeapAllocator
        Subclass of SkBitmap::Allocator that returns a SkPixelRef that allocates its pixel
        memory from the heap. This is the default SkBitmap::Allocator invoked by
        allocPixels().
    */
    class HeapAllocator : public Allocator {
    public:

        /** Allocates the pixel memory for the bitmap, given its dimensions and
            SkColorType. Returns true on success, where success means either setPixels()
            or setPixelRef() was called.

            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output
            @return        true if pixels are allocated

        example: https://fiddle.skia.org/c/@Bitmap_HeapAllocator_allocPixelRef
        */
        bool allocPixelRef(SkBitmap* bitmap) override;
    };

private:
    sk_sp<SkPixelRef>   fPixelRef;
    SkPixmap            fPixmap;
    sk_sp<SkMipmap>     fMips;

    friend class SkImage_Raster;
    friend class SkReadBuffer;        // unflatten
    friend class GrProxyProvider;     // fMips
};

///////////////////////////////////////////////////////////////////////////////

inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
    SkASSERT(fPixmap.addr());
    return fPixmap.writable_addr32(x, y);
}

inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
    SkASSERT(fPixmap.addr());
    return fPixmap.writable_addr16(x, y);
}

inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
    SkASSERT(fPixmap.addr());
    return fPixmap.writable_addr8(x, y);
}

#endif
