#Topic Bitmap
#Alias Bitmaps
#Alias Bitmap_Reference

#Subtopic Overview
    #Subtopic Subtopics
    #Populate
    ##
##

#Class SkBitmap

Bitmap describes a two-dimensional raster pixel array. Bitmap is built on
Image_Info, containing integer width and height, Color_Type and Alpha_Type
describing the pixel format, and Color_Space describing the range of colors.
Bitmap points to Pixel_Ref, which describes the physical array of pixels.
Image_Info bounds may be located anywhere fully inside Pixel_Ref bounds.

Bitmap can be drawn using Canvas. Bitmap can be a drawing destination for Canvas
draw methods. Bitmap flexibility as a pixel container limits some optimizations
available to the target platform.

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

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

Bitmap is not thread safe. Each thread must have its own copy of Bitmap fields,
although threads may share the underlying pixel array.

#Subtopic Row_Bytes
#Line # interval from one row to the next ##
Bitmap pixels may be contiguous, or may have a gap at the end of each row.
Row_Bytes is the interval from one row to the next. Row_Bytes may be specified;
sometimes passing zero will compute the Row_Bytes from the row width and the
number of bytes in a pixel. Row_Bytes may be larger than the row requires. This
is useful to position one or more Bitmaps within a shared pixel array.
##

#Subtopic Related_Functions
#Populate
##

#Subtopic Classes_and_Structs
#Populate
##

#Subtopic Constructors
#Populate
##

#Subtopic Operators
#Populate
##

#Subtopic Member_Functions
#Populate
##

# ------------------------------------------------------------------------------

#Class Allocator
#Line # abstract subclass of HeapAllocator ##
#Code
    class Allocator : public SkRefCnt {
    public:
        virtual bool allocPixelRef(SkBitmap* bitmap) = 0;
    };
##

Abstract subclass of HeapAllocator.

# ------------------------------------------------------------------------------

#Method virtual bool allocPixelRef(SkBitmap* bitmap) = 0

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

#Param bitmap  Bitmap containing Image_Info as input, and Pixel_Ref as output ##

#Return  true if Pixel_Ref was allocated ##

#NoExample
##

#SeeAlso HeapAllocator

##

#Class Allocator ##

# ------------------------------------------------------------------------------

#Class HeapAllocator
#Line # allocates pixel memory from heap ##

#Code
    class HeapAllocator : public Allocator {
    public:
        bool allocPixelRef(SkBitmap* bitmap) override;
    };
##

Subclass of Allocator that returns a Pixel_Ref that allocates its pixel
memory from the heap. This is the default Allocator invoked by
allocPixels.

# ------------------------------------------------------------------------------

#Method bool allocPixelRef(SkBitmap* bitmap) override

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

#Param bitmap  Bitmap containing Image_Info as input, and Pixel_Ref as output ##

#Return  true if pixels are allocated ##

#Example
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType));
    SkDebugf("pixel address = %p\n", bitmap.getPixels());
    SkBitmap::HeapAllocator stdalloc;
    if (!stdalloc.allocPixelRef(&bitmap)) {
        SkDebugf("pixel allocation failed\n");
    } else {
        SkDebugf("pixel address = %p\n", bitmap.getPixels());
    }
#StdOut
#Volatile
pixel address = (nil)
pixel address = 0x560ddd0ac670
##
##

#SeeAlso Allocator tryAllocPixels

##

#Class HeapAllocator ##

# ------------------------------------------------------------------------------

#Method SkBitmap()

#Line # constructs with default values ##
Creates an empty Bitmap without pixels, with kUnknown_SkColorType, 
kUnknown_SkAlphaType, and with a width and height of zero. Pixel_Ref origin is
set to (0, 0). Bitmap is not volatile.

Use setInfo to associate SkColorType, SkAlphaType, width, and height
after Bitmap has been created.

#Return  empty Bitmap ##

#Example
void draw(SkCanvas* canvas) {
    const char* alphas[] = {"Unknown", "Opaque", "Premul", "Unpremul"};
    const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                            "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
    SkBitmap bitmap;
    for (int i = 0; i < 2; ++i) {
       SkDebugf("width: %2d  height: %2d", bitmap.width(), bitmap.height());
       SkDebugf("  color: k%s_SkColorType", colors[bitmap.colorType()]);
       SkDebugf("  alpha: k%s_SkAlphaType\n", alphas[bitmap.alphaType()]);
       bitmap.setInfo(SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType),
                      0);
    }
}
#StdOut
width:  0  height:  0  color: kUnknown_SkColorType  alpha: kUnknown_SkAlphaType
width: 25  height: 35  color: kRGBA_8888_SkColorType  alpha: kOpaque_SkAlphaType
##
##

#SeeAlso setInfo

##

# ------------------------------------------------------------------------------

#Method SkBitmap(const SkBitmap& src)

#Line # shares ownership of pixels ##
Copies settings from src to returned Bitmap. Shares pixels if src has pixels
allocated, so both bitmaps reference the same pixels.

#Param src  Bitmap to copy Image_Info, and share Pixel_Ref ##

#Return  copy of src ##

#Example
void draw(SkCanvas* canvas) {
    SkBitmap original;
    original.tryAllocPixels(SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    SkDebugf("original has pixels before copy: %s\n", original.getPixels() ? "true" : "false");
    SkBitmap copy(original);  
    SkDebugf("original has pixels after copy: %s\n", original.getPixels() ? "true" : "false");
    SkDebugf("copy has pixels: %s\n", copy.getPixels() ? "true" : "false");
}
#StdOut
original has pixels before copy: true
original has pixels after copy: true
copy has pixels: true
##
##

#SeeAlso setInfo setPixelRef setPixels swap

##

# ------------------------------------------------------------------------------

#Method SkBitmap(SkBitmap&& src)

#Line # takes ownership of pixels ##
Copies settings from src to returned Bitmap. Moves ownership of src pixels to
Bitmap.

#Param src  Bitmap to copy Image_Info, and reassign Pixel_Ref ##

#Return  copy of src ##

#Example
void draw(SkCanvas* canvas) {
    SkBitmap original;
    original.tryAllocPixels(SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    SkDebugf("original has pixels before move: %s\n", original.getPixels() ? "true" : "false");
    SkBitmap copy(std::move(original));  
    SkDebugf("original has pixels after move: %s\n", original.getPixels() ? "true" : "false");
    SkDebugf("copy has pixels: %s\n", copy.getPixels() ? "true" : "false");
}
#StdOut
original has pixels before move: true
original has pixels after move: false
copy has pixels: true
##
##

#SeeAlso setInfo setPixelRef setPixels swap

##

# ------------------------------------------------------------------------------

#Method ~SkBitmap()

#Line # releases ownership of pixels ##
Decrements Pixel_Ref reference count, if Pixel_Ref is not nullptr.

#NoExample
##

#SeeAlso Pixel_Ref

##

# ------------------------------------------------------------------------------

#Method SkBitmap& operator=(const SkBitmap& src)

#Line # shares ownership of pixels ##
Copies settings from src to returned Bitmap. Shares pixels if src has pixels
allocated, so both bitmaps reference the same pixels.

#Param src  Bitmap to copy Image_Info, and share Pixel_Ref ##

#Return  copy of src ##

#Example
void draw(SkCanvas* canvas) {
    SkBitmap original;
    original.tryAllocPixels(SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    SkDebugf("original has pixels before copy: %s\n", original.getPixels() ? "true" : "false");
    SkBitmap copy = original;  
    SkDebugf("original has pixels after copy: %s\n", original.getPixels() ? "true" : "false");
    SkDebugf("copy has pixels: %s\n", copy.getPixels() ? "true" : "false");
}
#StdOut
original has pixels before copy: true
original has pixels after copy: true
copy has pixels: true
##
##

#SeeAlso setInfo setPixelRef setPixels swap

##

# ------------------------------------------------------------------------------

#Method SkBitmap& operator=(SkBitmap&& src)

#Line # takes ownership of pixels ##
Copies settings from src to returned Bitmap. Moves ownership of src pixels to
Bitmap.

#Param src  Bitmap to copy Image_Info, and reassign Pixel_Ref ##

#Return  copy of src ##

#Example
void draw(SkCanvas* canvas) {
    SkBitmap original;
    original.tryAllocPixels(SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    SkDebugf("original has pixels before move: %s\n", original.getPixels() ? "true" : "false");
    SkBitmap copy = std::move(original);  
    SkDebugf("original has pixels after move: %s\n", original.getPixels() ? "true" : "false");
    SkDebugf("copy has pixels: %s\n", copy.getPixels() ? "true" : "false");
}
#StdOut
original has pixels before move: true
original has pixels after move: false
copy has pixels: true
##
##

#SeeAlso setInfo setPixelRef setPixels swap

##

# ------------------------------------------------------------------------------

#Method void swap(SkBitmap& other)

#Line # exchanges Bitmap pair ##
Swaps the fields of the two bitmaps.

#Param other  Bitmap exchanged with original ##

#Example
void draw(SkCanvas* canvas) {
    auto debugster = [](const char* prefix, const SkBitmap& b) -> void {
        const char* alphas[] = {"Unknown", "Opaque", "Premul", "Unpremul"};
        const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                                "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
        SkDebugf("%s width:%d height:%d colorType:k%s_SkColorType alphaType:k%s_SkAlphaType\n",
                 prefix, b.width(), b.height(), colors[b.colorType()], alphas[b.alphaType()]);
    };
    SkBitmap one, two;
    one.tryAllocPixels(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    two.tryAllocPixels(SkImageInfo::Make(2, 2, kBGRA_8888_SkColorType, kPremul_SkAlphaType));
    for (int index = 0; index < 2; ++index) {
       debugster("one", one);
       debugster("two", two);
       one.swap(two);
    }
}
#StdOut
one width:1 height:1 colorType:kRGBA_8888_SkColorType alphaType:kOpaque_SkAlphaType
two width:2 height:2 colorType:kBGRA_8888_SkColorType alphaType:kPremul_SkAlphaType
one width:2 height:2 colorType:kBGRA_8888_SkColorType alphaType:kPremul_SkAlphaType
two width:1 height:1 colorType:kRGBA_8888_SkColorType alphaType:kOpaque_SkAlphaType
##
##

#SeeAlso SkBitmap(SkBitmap&& src) operator=(SkBitmap&& src)

##

# ------------------------------------------------------------------------------

#Method const SkPixmap& pixmap() const

#Line # returns Pixmap ##
Returns a constant reference to the Pixmap holding the Bitmap pixel
address, row bytes, and Image_Info.

#Return reference to Pixmap describing this Bitmap ##

#Example
    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::MakeN32Premul(10, 11));
    SkCanvas offscreen(bitmap);
    offscreen.clear(SK_ColorWHITE);
    SkPaint paint;
    offscreen.drawString("&", 0, 10, paint);
    const SkPixmap& pixmap = bitmap.pixmap();
    if (pixmap.addr()) {
        SkPMColor pmWhite = *pixmap.addr32(0, 0);
        for (int y = 0; y < pixmap.height(); ++y) {
            for (int x = 0; x < pixmap.width(); ++x) {
                SkDebugf("%c", *pixmap.addr32(x, y) == pmWhite ? '-' : 'x');
            }
            SkDebugf("\n");
        }
    }
    #StdOut
----------
---xx-----
--x--x----
--x-------
--xx------
--x-x---x-
-x---x--x-
-x----xx--
-xx---x---
--xxxx-xx-
----------
    #StdOut ##

##

#SeeAlso peekPixels installPixels readPixels writePixels

##

# ------------------------------------------------------------------------------

#Method const SkImageInfo& info() const

#Line # returns Image_Info ##
Returns width, height, Alpha_Type, Color_Type, and Color_Space.

#Return reference to Image_Info  ##

#Example
#Image 4
void draw(SkCanvas* canvas) {
    // SkBitmap source;  // pre-populated with soccer ball by fiddle.skia.org
    const SkImageInfo& info = source.info();
    const char* alphas[] = {"Unknown", "Opaque", "Premul", "Unpremul"};
    const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                            "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
    SkDebugf("width: %d height: %d color: %s alpha: %s\n", info.width(), info.height(),
                colors[info.colorType()], alphas[info.alphaType()]);
#StdOut
width: 56 height: 56 color: BGRA_8888 alpha: Opaque
##
}
##

#SeeAlso Image_Info

##

# ------------------------------------------------------------------------------

#Method int width() const

#Line # returns pixel column count ##
Returns pixel count in each row. Should be equal or less than:

#Formula
rowBytes() / info().bytesPerPixel()
##
. 

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

#Return  pixel width in Image_Info ##

#Example
    SkImageInfo info = SkImageInfo::MakeA8(16, 32);
    SkBitmap bitmap;
    bitmap.setInfo(info);
    SkDebugf("bitmap width: %d  info width: %d\n", bitmap.width(), info.width());
#StdOut
bitmap width: 16  info width: 16
##
##

#SeeAlso height() SkPixelRef::width() SkImageInfo::width()

##

# ------------------------------------------------------------------------------

#Method int height() const

#Line # returns pixel row count ##
Returns pixel row count.

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

#Return pixel height in Image_Info ##

#Example
    SkImageInfo info = SkImageInfo::MakeA8(16, 32);
    SkBitmap bitmap;
    bitmap.setInfo(info);
    SkDebugf("bitmap height: %d  info height: %d\n", bitmap.height(), info.height());
#StdOut
bitmap height: 32  info height: 32
##
##

#SeeAlso width() SkPixelRef::height() SkImageInfo::height()

##

# ------------------------------------------------------------------------------

#Method SkColorType colorType() const

#Line # returns Image_Info Color_Type ##
Returns Color_Type, one of: kUnknown_SkColorType, kAlpha_8_SkColorType,
kRGB_565_SkColorType, kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
kBGRA_8888_SkColorType, kGray_8_SkColorType, kRGBA_F16_SkColorType.

#Return  Color_Type in Image_Info ##

#Example
    const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                            "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeA8(16, 32));
    SkDebugf("color type: k" "%s" "_SkColorType\n", colors[bitmap.colorType()]);
#StdOut
color type: kAlpha_8_SkColorType
##
##

#SeeAlso alphaType() SkImageInfo::colorType

##

# ------------------------------------------------------------------------------

#Method SkAlphaType alphaType() const

#Line # returns Image_Info Alpha_Type ##
Returns Alpha_Type, one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,
kPremul_SkAlphaType, kUnpremul_SkAlphaType.

#Return  Alpha_Type in Image_Info ##

#Example
    const char* alphas[] = {"Unknown", "Opaque", "Premul", "Unpremul"};
    SkPixmap pixmap(SkImageInfo::MakeA8(16, 32), nullptr, 64);
    SkDebugf("alpha type: k" "%s" "_SkAlphaType\n", alphas[pixmap.alphaType()]);
#StdOut
alpha type: kPremul_SkAlphaType
##
##

#SeeAlso colorType() SkImageInfo::alphaType

##

# ------------------------------------------------------------------------------

#Method SkColorSpace* colorSpace() const

#Line # returns Image_Info Color_Space ##
Returns Color_Space, the range of colors, associated with Image_Info. The
reference count of Color_Space is unchanged. The returned Color_Space is
immutable.

#Return Color_Space in Image_Info, or nullptr ##

#Example
#Description
SkColorSpace::MakeSRGBLinear creates Color_Space with linear gamma
and an sRGB gamut. This Color_Space gamma is not close to sRGB gamma.
##
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(16, 32, kPremul_SkAlphaType, 
            SkColorSpace::MakeSRGBLinear()));
    SkColorSpace* colorSpace = bitmap.colorSpace();
    SkDebugf("gammaCloseToSRGB: %s  gammaIsLinear: %s  isSRGB: %s\n",
            colorSpace->gammaCloseToSRGB() ? "true" : "false",
            colorSpace->gammaIsLinear() ? "true" : "false",
            colorSpace->isSRGB() ? "true" : "false");
#StdOut
gammaCloseToSRGB: false  gammaIsLinear: true  isSRGB: false
##
##

#SeeAlso Color_Space SkImageInfo::colorSpace

##

# ------------------------------------------------------------------------------

#Method sk_sp<SkColorSpace> refColorSpace() const

#Line # returns Image_Info Color_Space ##
Returns a smart pointer to Color_Space, the range of colors, associated with
Image_Info. The smart pointer tracks the number of objects sharing this
Color_Space reference so the memory is released when the owners destruct.

The returned Color_Space is immutable.

#Return Color_Space in Image_Info wrapped in a smart pointer ##

#Example
    SkBitmap bitmap1, bitmap2;
    bitmap1.setInfo(SkImageInfo::MakeN32(16, 32, kPremul_SkAlphaType, 
            SkColorSpace::MakeSRGBLinear()));
    bitmap2.setInfo(SkImageInfo::MakeN32(16, 32, kPremul_SkAlphaType,
            bitmap1.refColorSpace()));
    SkColorSpace* colorSpace = bitmap2.colorSpace();
    SkDebugf("gammaCloseToSRGB: %s  gammaIsLinear: %s  isSRGB: %s\n",
            colorSpace->gammaCloseToSRGB() ? "true" : "false",
            colorSpace->gammaIsLinear() ? "true" : "false",
            colorSpace->isSRGB() ? "true" : "false");
#StdOut
gammaCloseToSRGB: false  gammaIsLinear: true  isSRGB: false
##
##

#SeeAlso Color_Space SkImageInfo::colorSpace

##

# ------------------------------------------------------------------------------

#Method int bytesPerPixel() const

#Line # returns number of bytes in pixel based on Color_Type ##
Returns number of bytes per pixel required by Color_Type.
Returns zero if colorType( is kUnknown_SkColorType.

#Return  bytes in pixel ##

#Example
    const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                            "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
    SkImageInfo info = SkImageInfo::MakeA8(1, 1);
    SkBitmap bitmap;
    for (SkColorType colorType : { kUnknown_SkColorType,     kAlpha_8_SkColorType,
                                   kRGB_565_SkColorType,     kARGB_4444_SkColorType, 
                                   kRGBA_8888_SkColorType,
                                   kBGRA_8888_SkColorType,   kGray_8_SkColorType,
                                   kRGBA_F16_SkColorType } ) {
        bitmap.setInfo(info.makeColorType(colorType));
        SkDebugf("color: k" "%s" "_SkColorType" "%*s" "bytesPerPixel: %d\n",
                colors[colorType], 13 - strlen(colors[colorType]), " ",
                bitmap.bytesPerPixel());
    }
#StdOut
color: kUnknown_SkColorType      bytesPerPixel: 0
color: kAlpha_8_SkColorType      bytesPerPixel: 1
color: kRGB_565_SkColorType      bytesPerPixel: 2
color: kARGB_4444_SkColorType    bytesPerPixel: 2
color: kRGBA_8888_SkColorType    bytesPerPixel: 4
color: kBGRA_8888_SkColorType    bytesPerPixel: 4
color: kGray_8_SkColorType       bytesPerPixel: 1
color: kRGBA_F16_SkColorType     bytesPerPixel: 8
##
##

#SeeAlso rowBytes rowBytesAsPixels width shiftPerPixel

##

# ------------------------------------------------------------------------------

#Method int rowBytesAsPixels() const

#Line # returns interval between rows in pixels ##
Returns number of pixels that fit on row. Should be greater than or equal to
width().

#Return  maximum pixels per row ##

#Example
    SkBitmap bitmap;
    for (int rowBytes : { 4, 5, 6, 7, 8} ) {
        bitmap.setInfo(SkImageInfo::MakeN32(1, 1, kPremul_SkAlphaType), rowBytes);
        SkDebugf("rowBytes: %d rowBytesAsPixels: %d\n", rowBytes, bitmap.rowBytesAsPixels());
    }
#StdOut
rowBytes: 4 rowBytesAsPixels: 1
rowBytes: 5 rowBytesAsPixels: 1
rowBytes: 6 rowBytesAsPixels: 1
rowBytes: 7 rowBytesAsPixels: 1
rowBytes: 8 rowBytesAsPixels: 2
##
##

#SeeAlso rowBytes shiftPerPixel width bytesPerPixel

##

# ------------------------------------------------------------------------------

#Method int shiftPerPixel() const

#Line # returns bit shift from pixels to bytes ##
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 ##

#Example
    const char* colors[] = {"Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                            "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16"};
    SkImageInfo info = SkImageInfo::MakeA8(1, 1);
    SkBitmap bitmap;
    for (SkColorType colorType : { kUnknown_SkColorType,   kAlpha_8_SkColorType,
                                   kRGB_565_SkColorType,   kARGB_4444_SkColorType, 
                                   kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,
                                   kGray_8_SkColorType,    kRGBA_F16_SkColorType } ) {
        bitmap.setInfo(info.makeColorType(colorType));
        SkDebugf("color: k" "%s" "_SkColorType" "%*s" "shiftPerPixel: %d\n",
                colors[colorType], 10 - strlen(colors[colorType]), " ",
                bitmap.shiftPerPixel());
    }
#StdOut
color: kUnknown_SkColorType   shiftPerPixel: 0
color: kAlpha_8_SkColorType   shiftPerPixel: 0
color: kRGB_565_SkColorType   shiftPerPixel: 1
color: kARGB_4444_SkColorType shiftPerPixel: 1
color: kRGBA_8888_SkColorType shiftPerPixel: 2
color: kBGRA_8888_SkColorType shiftPerPixel: 2
color: kGray_8_SkColorType    shiftPerPixel: 0
color: kRGBA_F16_SkColorType  shiftPerPixel: 3
##
##

#SeeAlso rowBytes rowBytesAsPixels width bytesPerPixel

##

# ------------------------------------------------------------------------------

#Method bool empty() const

#Line # returns true if Image_Info has zero width() or height() ##
Returns true if either width() or height() are zero.

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

#Return  true if dimensions do not enclose area ##

#Example
    SkBitmap bitmap;
    for (int width : { 0, 2 } ) {
        for (int height : { 0, 2 } ) {
             bitmap.setInfo(SkImageInfo::MakeA8(width, height));
             SkDebugf("width: %d height: %d empty: %s\n", width, height,
                      bitmap.empty() ? "true" : "false");
        }
    }
#StdOut
width: 0 height: 0 empty: true
width: 0 height: 2 empty: true
width: 2 height: 0 empty: true
width: 2 height: 2 empty: false
##
##

#SeeAlso height() width() drawsNothing 

##

# ------------------------------------------------------------------------------

#Method bool isNull() const

#Line # returns true if Pixel_Ref is nullptr ##
Return true if Pixel_Ref is nullptr.

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

#Return  true if no Pixel_Ref is associated ##

#Example
    SkBitmap bitmap;
    SkDebugf("empty bitmap does %shave pixels\n", bitmap.isNull() ? "not " : "");
    bitmap.setInfo(SkImageInfo::MakeA8(8, 8));
    SkDebugf("bitmap with dimensions does %shave pixels\n", bitmap.isNull() ? "not " : "");
    bitmap.allocPixels();
    SkDebugf("allocated bitmap does %shave pixels\n", bitmap.isNull() ? "not " : "");
#StdOut
empty bitmap does not have pixels
bitmap with dimensions does not have pixels
allocated bitmap does have pixels
##
##

#SeeAlso empty() drawsNothing pixelRef

##

# ------------------------------------------------------------------------------

#Method bool drawsNothing() const

#Line # returns true if no width(), no height(), or no Pixel_Ref ##
Return true if width() or height() are zero, or if Pixel_Ref is nullptr.
If true, Bitmap has no effect when drawn or drawn into.

#Return  true if drawing has no effect ##

#Example
    SkBitmap bitmap;
    for (int w : { 0, 8 } ) {
        for (bool allocate : { false, true} ) {
            bitmap.setInfo(SkImageInfo::MakeA8(w, 8));
            allocate ? bitmap.allocPixels() : (void) 0 ;
            SkDebugf("empty:%s isNull:%s drawsNothing:%s\n", bitmap.empty() ? "true " : "false",
                     bitmap.isNull() ? "true " : "false", bitmap.drawsNothing() ? "true" : "false");
        }
    }
#StdOut
empty:true  isNull:true  drawsNothing:true
empty:true  isNull:false drawsNothing:true
empty:false isNull:true  drawsNothing:true
empty:false isNull:false drawsNothing:false
##
##

#SeeAlso empty() isNull pixelRef

##

# ------------------------------------------------------------------------------

#Method size_t rowBytes() const

#Line # returns interval between rows in bytes ##
Returns row bytes, the interval from one pixel row to the next. Row bytes
is at least as large as 
#Formula
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 ##

#Example
   SkBitmap bitmap;
   for (int rowBytes : { 2, 8 } ) {
       bool result = bitmap.setInfo(SkImageInfo::MakeA8(4, 4), rowBytes);
       SkDebugf("setInfo returned:%s rowBytes:%d\n", result ? "true " : "false", bitmap.rowBytes());
    }
#StdOut
setInfo returned:false rowBytes:0
setInfo returned:true  rowBytes:8
##
##

#SeeAlso info() setInfo SkImageInfo::minRowBytes

##

# ------------------------------------------------------------------------------

#Method bool setAlphaType(SkAlphaType alphaType)

#Line # sets Alpha_Type of shared pixels ##
Sets Alpha_Type, if alphaType is compatible with Color_Type.
Returns true unless alphaType is kUnknown_SkAlphaType and current Alpha_Type
is not kUnknown_SkAlphaType.

Returns true if Color_Type is kUnknown_SkColorType. alphaType is ignored, and
Alpha_Type remains kUnknown_SkAlphaType.

Returns true if Color_Type is kRGB_565_SkColorType or kGray_8_SkColorType.
alphaType is ignored, and Alpha_Type remains kOpaque_SkAlphaType.

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

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

This changes Alpha_Type in Pixel_Ref; all bitmaps sharing Pixel_Ref
are affected.

#Param alphaType  one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,
                          kPremul_SkAlphaType, kUnpremul_SkAlphaType
##

#Return  true if Alpha_Type is set ##

#Example
void draw(SkCanvas* canvas) {
    const char* colors[] = { "Unknown", "Alpha_8", "RGB_565", "ARGB_4444", "RGBA_8888", "RGB_888x",
                             "BGRA_8888", "RGBA_1010102", "RGB_101010x", "Gray_8", "RGBA_F16" };
    const char* alphas[] = {"Unknown ", "Opaque  ", "Premul  ", "Unpremul"}; 
    SkBitmap bitmap;
    SkAlphaType alphaTypes[] = { kUnknown_SkAlphaType, kOpaque_SkAlphaType,
                                 kPremul_SkAlphaType, kUnpremul_SkAlphaType };
    SkDebugf("%88s", "Canonical    Unknown           Opaque            Premul            Unpremul\n");
    for (SkColorType colorType : { kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
                            kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType, 
                            kGray_8_SkColorType, kRGBA_F16_SkColorType } ) {
        for (SkAlphaType canonicalAlphaType : alphaTypes) {
            SkColorTypeValidateAlphaType(colorType, kUnknown_SkAlphaType, &canonicalAlphaType );
            SkDebugf("%10s %10s ", colors[(int) colorType], alphas[(int) canonicalAlphaType ]);
            for (SkAlphaType alphaType : alphaTypes) {
                bitmap.setInfo(SkImageInfo::Make(4, 4, colorType, canonicalAlphaType));
                bool result = bitmap.setAlphaType(alphaType);
                SkDebugf("%s %s    ", result ? "true " : "false", alphas[(int) bitmap.alphaType()]);
            }
            SkDebugf("\n");
        }
    }
}
##

#SeeAlso Alpha_Type Color_Type Image_Info setInfo

##

# ------------------------------------------------------------------------------

#Method void* getPixels() const

#Line # returns address of pixels ##
Returns pixel address, the base address corresponding to the pixel origin.

#Return  pixel address ##

#Example
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(4, 4, kPremul_SkAlphaType));
    bitmap.allocPixels();
    bitmap.eraseColor(0x00000000);
    void* baseAddr = bitmap.getPixels();
    *(SkPMColor*)baseAddr = 0xFFFFFFFF;
    SkDebugf("bitmap.getColor(0, 1) %c= 0x00000000\n",
              bitmap.getColor(0, 1)  == 0x00000000 ? '=' : '!');
    SkDebugf("bitmap.getColor(0, 0) %c= 0xFFFFFFFF\n",
              bitmap.getColor(0, 0)  == 0xFFFFFFFF ? '=' : '!');
#StdOut
bitmap.getColor(0, 1) == 0x00000000
bitmap.getColor(0, 0) == 0xFFFFFFFF
##
##

#SeeAlso isNull drawsNothing

##

# ------------------------------------------------------------------------------

#Method size_t computeByteSize() const

#Line # returns size required for pixels ##
Returns minimum memory required for pixel storage.
Does not include unused memory on last row when rowBytesAsPixels exceeds width().
Returns zero 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 ##

#Example
    SkBitmap bitmap;
    for (int width : { 1, 1000, 1000000 } ) {
        for (int height: { 1, 1000, 1000000 } ) {
            SkImageInfo imageInfo = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType);
            bitmap.setInfo(imageInfo, width * 5);
            SkDebugf("width: %7d height: %7d computeByteSize: %13lld\n", width, height,
                     bitmap.computeByteSize());
        }
    }
#StdOut
width:       1 height:       1 computeByteSize:             4
width:       1 height:    1000 computeByteSize:          4999
width:       1 height: 1000000 computeByteSize:       4999999
width:    1000 height:       1 computeByteSize:          4000
width:    1000 height:    1000 computeByteSize:       4999000
width:    1000 height: 1000000 computeByteSize:    4999999000
width: 1000000 height:       1 computeByteSize:       4000000
width: 1000000 height:    1000 computeByteSize:    4999000000
width: 1000000 height: 1000000 computeByteSize: 4999999000000
##
##

#SeeAlso SkImageInfo::computeByteSize

##

# ------------------------------------------------------------------------------

#Method bool isImmutable() const

#Line # returns true if pixels will not change ##
Returns true if pixels can not change.

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

#Return  true if pixels are immutable ##

#Example
    SkBitmap original; 
    SkImageInfo info = SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
    if (original.tryAllocPixels(info)) {
        original.setImmutable();
        SkBitmap copy;
        original.extractSubset(&copy, {5, 10, 15, 20});  
        SkDebugf("original is " "%s" "immutable\n", original.isImmutable() ? "" : "not ");
        SkDebugf("copy is " "%s" "immutable\n", copy.isImmutable() ? "" : "not ");
    }
#StdOut
original is immutable
copy is immutable
##
##

#SeeAlso setImmutable SkPixelRef::isImmutable SkImage

##

# ------------------------------------------------------------------------------

#Method void setImmutable()

#Line # marks that pixels will not change ##
Sets internal flag to mark Bitmap as immutable. Once set, pixels can not change.
Any other bitmap sharing the same Pixel_Ref are also marked as immutable. 
Once Pixel_Ref is marked immutable, the setting cannot be cleared.

Writing to immutable Bitmap pixels triggers an assert on debug builds.
 
#Example
#Description
Triggers assert if SK_DEBUG is true, runs fine otherwise.
##
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(4, 4, kPremul_SkAlphaType));
    bitmap.allocPixels();
    SkCanvas offscreen(bitmap);
    SkDebugf("draw white\n");
    offscreen.clear(SK_ColorWHITE);
    bitmap.setImmutable();
    SkDebugf("draw black\n");
    offscreen.clear(SK_ColorBLACK);
##

#SeeAlso isImmutable SkPixelRef::setImmutable SkImage

##

# ------------------------------------------------------------------------------

#Method bool isOpaque() const

#Line # returns true if Image_Info describes opaque pixels ##
Returns true if Alpha_Type is kOpaque_SkAlphaType.
Does not check if Color_Type allows Alpha, or if any pixel value has
transparency.

#Return  true if Image_Info describes opaque Alpha ##

#Example
#Description
    isOpaque ignores whether all pixels are opaque or not.
##
    const int height = 2;
    const int width = 2;
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType));
    for (int index = 0; index < 2; ++index) {
        bitmap.allocPixels();
        bitmap.eraseColor(0x00000000);
        SkDebugf("isOpaque: %s\n", bitmap.isOpaque() ? "true" : "false");
        bitmap.eraseColor(0xFFFFFFFF);
        SkDebugf("isOpaque: %s\n", bitmap.isOpaque() ? "true" : "false");
        bitmap.setInfo(bitmap.info().makeAlphaType(kOpaque_SkAlphaType));
    }
#StdOut
isOpaque: false
isOpaque: false
isOpaque: true
isOpaque: true
##
##

#SeeAlso ComputeIsOpaque SkImageInfo::isOpaque

##

# ------------------------------------------------------------------------------

#Method bool isVolatile() const

#Line # returns true if pixels should not be cached ##
If true, provides a hint to caller that pixels should not
be cached. Only true if setIsVolatile has been called to mark as volatile.

Volatile state is not shared by other bitmaps sharing the same Pixel_Ref.

#Return  true if marked volatile ##

#Example
    SkBitmap original; 
    SkImageInfo info = SkImageInfo::Make(25, 35, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
    if (original.tryAllocPixels(info)) {
        original.setIsVolatile(true);
        SkBitmap copy;
        original.extractSubset(&copy, {5, 10, 15, 20});  
        SkDebugf("original is " "%s" "volatile\n", original.isVolatile() ? "" : "not ");
        SkDebugf("copy is " "%s" "volatile\n", copy.isImmutable() ? "" : "not ");
    }
#StdOut
original is volatile
copy is not volatile
##
##

#SeeAlso setIsVolatile

##

# ------------------------------------------------------------------------------

#Method void setIsVolatile(bool isVolatile)

#Line # marks if pixels should not be cached ##
Sets if pixels should be read from Pixel_Ref on every access. Bitmaps are not
volatile by default; a GPU back end may upload pixel values expecting them to be
accessed repeatedly. Marking temporary Bitmaps as volatile provides a hint to
Device that the Bitmap pixels should not be cached. This can
improve performance by avoiding overhead and reducing resource
consumption on Device.

#Param isVolatile  true if backing pixels are temporary ##

#Example
#Height 20
    SkBitmap bitmap; 
    bitmap.setInfo(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    bitmap.allocPixels();
    bitmap.eraseColor(SK_ColorRED);
    canvas->scale(16, 16);
    canvas->drawBitmap(bitmap, 0, 0);
    *(SkPMColor*) bitmap.getPixels() = SkPreMultiplyColor(SK_ColorBLUE);
    canvas->drawBitmap(bitmap, 2, 0);
    bitmap.setIsVolatile(true);
    *(SkPMColor*) bitmap.getPixels() = SkPreMultiplyColor(SK_ColorGREEN);
    canvas->drawBitmap(bitmap, 4, 0);
##

#SeeAlso isVolatile

##

# ------------------------------------------------------------------------------

#Method void reset()

#Line # sets to default values, releases pixel ownership ##
Resets to its initial state; all fields are set to zero, as if Bitmap 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 Pixel_Ref is allocated, its reference count is decreased by one, releasing
its memory if Bitmap is the sole owner.

#Example
    SkBitmap bitmap; 
    bitmap.setInfo(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    bitmap.allocPixels();
    SkDebugf("width:%d height:%d isNull:%s\n", bitmap.width(), bitmap.height(),
             bitmap.isNull() ? "true" : "false");
    bitmap.reset();
    SkDebugf("width:%d height:%d isNull:%s\n", bitmap.width(), bitmap.height(),
             bitmap.isNull() ? "true" : "false");
#StdOut
width:1 height:1 isNull:false
width:0 height:0 isNull:true
##
##

#SeeAlso SkBitmap() SkAlphaType SkColorType

##

# ------------------------------------------------------------------------------

#Method static bool ComputeIsOpaque(const SkBitmap& bm)

#Line # returns true if all pixels are opaque ##
Returns true if all pixels are opaque. Color_Type determines how pixels
are encoded, and whether pixel describes Alpha. Returns true for Color_Types
without alpha in each pixel; for other Color_Types, returns true if all
pixels have alpha values equivalent to 1.0 or greater.

For Color_Types kRGB_565_SkColorType or kGray_8_SkColorType: always
returns true. For Color_Types kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
kRGBA_8888_SkColorType: returns true if all pixel Alpha values are 255.
For Color_Type 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  Bitmap to check ##

#Return true if all pixels have opaque values or Color_Type is opaque ##

#Example
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(2, 2, kN32_SkColorType, kPremul_SkAlphaType));
    for (int index = 0; index < 2; ++index) {
        bitmap.allocPixels();
        bitmap.eraseColor(0x00000000);
        SkDebugf("computeIsOpaque: %s\n", SkBitmap::ComputeIsOpaque(bitmap) ? "true" : "false");
        bitmap.eraseColor(0xFFFFFFFF);
        SkDebugf("computeIsOpaque: %s\n", SkBitmap::ComputeIsOpaque(bitmap) ? "true" : "false");
        bitmap.setInfo(bitmap.info().makeAlphaType(kOpaque_SkAlphaType));
    }
#StdOut
computeIsOpaque: false
computeIsOpaque: true
computeIsOpaque: false
computeIsOpaque: true
##
##

#SeeAlso isOpaque Color_Type Alpha

##

# ------------------------------------------------------------------------------

#Method void getBounds(SkRect* bounds) const

#Line # returns width() and height() as Rectangle ##
Returns Rect { 0, 0, width(), height() }.

#Param bounds container for floating point rectangle ##

#Example
#Height 160
#Image 3
    SkRect bounds;
    source.getBounds(&bounds);
    bounds.offset(100, 100);
    SkPaint paint;
    paint.setColor(SK_ColorGRAY);
    canvas->scale(.25f, .25f);
    canvas->drawRect(bounds, paint);
    canvas->drawBitmap(source, 40, 40);
##

#SeeAlso bounds() 

##

# ------------------------------------------------------------------------------

#Method void getBounds(SkIRect* bounds) const

Returns IRect { 0, 0, width(), height() }.

#Param bounds container for integral rectangle ##

#Example
#Image 3
    SkIRect bounds;
    source.getBounds(&bounds);
    bounds.inset(100, 100);
    SkBitmap bitmap;
    source.extractSubset(&bitmap, bounds);
    canvas->scale(.5f, .5f);
    canvas->drawBitmap(bitmap, 10, 10);
##

#SeeAlso bounds() 

##

# ------------------------------------------------------------------------------

#Method SkIRect bounds() const

#Line # returns width() and height() as Rectangle ##
Returns IRect { 0, 0, width(), height() }.

#Return  integral rectangle from origin to width() and height() ##

#Example
#Height 128
#Image 4
    canvas->scale(.5f, .5f);
    SkIRect bounds = source.bounds();
    for (int x : { 0, bounds.width() } ) {
        for (int y : { 0, bounds.height() } ) {
            canvas->drawBitmap(source, x, y);
        }
    }
##

#SeeAlso getBounds 

##

# ------------------------------------------------------------------------------

#Method SkISize dimensions() const

#Line # returns width() and height() ##
Returns ISize { width(), height() }.

#Return integral size of width() and height() ##

#Example
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::MakeN32(33, 55, kOpaque_SkAlphaType));
    SkISize dimensions = bitmap.dimensions();
    SkRect bounds;
    bitmap.getBounds(&bounds);
    SkRect dimensionsAsBounds = SkRect::Make(dimensions);
    SkDebugf("dimensionsAsBounds %c= bounds\n", dimensionsAsBounds == bounds ? '=' : '!');
##

#SeeAlso height() width()

##

# ------------------------------------------------------------------------------

#Method SkIRect getSubset() const

#Line # returns bounds offset by origin ##
Returns the bounds of this bitmap, offset by its Pixel_Ref origin.

#Return bounds within Pixel_Ref bounds ##

#Example
#Image 3
    SkIRect bounds;
    source.getBounds(&bounds);
    bounds.inset(100, 100);
    SkBitmap subset;
    source.extractSubset(&subset, bounds);
    SkIRect r = source.getSubset();
    SkDebugf("source: %d, %d, %d, %d\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
    r = subset.getSubset();
    SkDebugf("subset: %d, %d, %d, %d\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
source: 0, 0, 512, 512
subset: 100, 100, 412, 412
##
##

#SeeAlso extractSubset getBounds

##

# ------------------------------------------------------------------------------

#Method bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0)

#Line # sets height, width, Color_Type, and so on, releasing pixels ##
Sets width, height, Alpha_Type, Color_Type, Color_Space, 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
Color_Space values, rowBytes of zero is treated as imageInfo.minRowBytes.

Calls reset() and returns false if:
#List
# 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, Alpha_Type, Color_Type, Color_Space ##
#Param rowBytes   imageInfo.minRowBytes or larger; or zero ##

#Return  true if Image_Info set successfully ##

#Example
#Height 96
###^
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::MakeN32(44, 16, kOpaque_SkAlphaType));
bitmap.allocPixels();
bitmap.eraseColor(SK_ColorGREEN);
SkCanvas offscreen(bitmap);
SkPaint paint;
offscreen.drawString("!@#$%", 0, 12, paint);
canvas->scale(6, 6);
canvas->drawBitmap(bitmap, 0, 0);
^^^#
##

#SeeAlso Alpha_Type Color_Type Color_Space height rowBytes width

##

# ------------------------------------------------------------------------------

#Enum AllocFlags

#Code
    enum AllocFlags {
        kZeroPixels_AllocFlag = 1 << 0,
    };
##

AllocFlags provides the option to zero pixel memory when allocated.

#Const kZeroPixels_AllocFlag 1
    Instructs tryAllocPixelsFlags and allocPixelsFlags to zero pixel memory.  
##

#NoExample
##

#SeeAlso tryAllocPixelsFlags allocPixelsFlags erase() eraseColor

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags)

#Line # allocates pixels from Image_Info with options if possible ##
Sets Image_Info to info following the rules in setInfo and allocates pixel
memory. If flags is kZeroPixels_AllocFlag, memory is zeroed. 

Returns false and calls reset() if Image_Info 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 malloc(), if flags is zero, and calloc(), if flags is
kZeroPixels_AllocFlag.

Passing kZeroPixels_AllocFlag is usually faster than separately calling
eraseColor(SK_ColorTRANSPARENT).

#Param info  contains width, height, Alpha_Type, Color_Type, Color_Space ##
#Param flags  kZeroPixels_AllocFlag, or zero ##

#Return  true if pixels allocation is successful ##

#Example
    SkBitmap bitmap;
    if (!bitmap.tryAllocPixelsFlags(SkImageInfo::MakeN32(10000, 10000, kOpaque_SkAlphaType), 
                                    SkBitmap::kZeroPixels_AllocFlag)) {
        SkDebugf("bitmap allocation failed!\n");
    } else {
        SkDebugf("bitmap allocation succeeded!\n");
    }
#StdOut
bitmap allocation succeeded!
##
##

#SeeAlso allocPixelsFlags tryAllocPixels SkMallocPixelRef::MakeZeroed

##

# ------------------------------------------------------------------------------

#Method void allocPixelsFlags(const SkImageInfo& info, uint32_t flags)

#Line # allocates pixels from Image_Info with options, or aborts ##
Sets Image_Info to info following the rules in setInfo and allocates pixel
memory. If flags is kZeroPixels_AllocFlag, memory is zeroed. 

Aborts execution if Image_Info 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 malloc(), if flags is zero, and calloc(), if flags is
kZeroPixels_AllocFlag.

Passing kZeroPixels_AllocFlag is usually faster than separately calling
eraseColor(SK_ColorTRANSPARENT).

#Param info  contains width, height, Alpha_Type, Color_Type, Color_Space ##
#Param flags  kZeroPixels_AllocFlag, or zero ##

#Example
#Height 128
#Description
Text is drawn on a transparent background; drawing the bitmap a second time
lets the first draw show through.
##
###^
SkBitmap bitmap;
bitmap.allocPixelsFlags(SkImageInfo::MakeN32(44, 16, kPremul_SkAlphaType), 
                        SkBitmap::kZeroPixels_AllocFlag);
SkCanvas offscreen(bitmap);
SkPaint paint;
offscreen.drawString("!@#$%", 0, 12, paint);
canvas->scale(6, 6);
canvas->drawBitmap(bitmap, 0, 0);
canvas->drawBitmap(bitmap, 8, 8);
^^^#
##

#SeeAlso tryAllocPixelsFlags allocPixels SkMallocPixelRef::MakeZeroed

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes)

#Line # allocates pixels from Image_Info if possible ##
#ToDo  am I ever conflicted about setInfo rules. It needs to be able to be replicated
       if, for instance, I generate one-page-per-method HTML-style documentation
       I'm not so sure it makes sense to put the indirection in for .h either unless
       my mantra is that .h should abbreviate full documentation. And, what to do
       for generated markdown? At least there the rules are a click away, although
       a pop-down in place would be way better. Hmmm.
##

Sets Image_Info 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 Image_Info 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, Alpha_Type, Color_Type, Color_Space ##
#Param rowBytes  size of pixel row or larger; may be zero  ##

#Return  true if pixel storage is allocated ##

#Example
#Image 3
SkBitmap bitmap;
SkImageInfo info = SkImageInfo::Make(64, 256, kGray_8_SkColorType, kOpaque_SkAlphaType);
if (bitmap.tryAllocPixels(info, 0)) {
    SkCanvas offscreen(bitmap);
    offscreen.scale(.5f, .5f);
    for (int x : { 0, 64, 128, 192 } ) {
        offscreen.drawBitmap(source, -x, 0);
        canvas->drawBitmap(bitmap, x, 0);
    }
}
##

#SeeAlso tryAllocPixelsFlags allocPixels SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method void allocPixels(const SkImageInfo& info, size_t rowBytes)

#Line # allocates pixels from Image_Info, or aborts ##
Sets Image_Info 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 Image_Info 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, Alpha_Type, Color_Type, Color_Space ##
#Param rowBytes  size of pixel row or larger; may be zero  ##

#Example
#Image 3
SkBitmap bitmap;
SkImageInfo info = SkImageInfo::Make(256, 64, kGray_8_SkColorType, kOpaque_SkAlphaType);
bitmap.allocPixels(info, info.width() * info.bytesPerPixel() + 64);
SkCanvas offscreen(bitmap);
offscreen.scale(.5f, .5f);
for (int y : { 0, 64, 128, 192 } ) {
    offscreen.drawBitmap(source, 0, -y);
    canvas->drawBitmap(bitmap, 0, y);
}
##

#SeeAlso tryAllocPixels allocPixelsFlags SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info)

Sets Image_Info to info following the rules in setInfo and allocates pixel
memory. 

Returns false and calls reset() if Image_Info 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, Alpha_Type, Color_Type, Color_Space ##

#Return  true if pixel storage is allocated ##

#Example
#Image 3
SkBitmap bitmap;
if (bitmap.tryAllocPixels(SkImageInfo::Make(64, 64, kGray_8_SkColorType, kOpaque_SkAlphaType))) {
    SkCanvas offscreen(bitmap);
    offscreen.scale(.25f, .5f);
    for (int y : { 0, 64, 128, 192 } ) {
        offscreen.drawBitmap(source, -y, -y);
        canvas->drawBitmap(bitmap, y, y);
    }
}
##

#SeeAlso tryAllocPixelsFlags allocPixels SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method void allocPixels(const SkImageInfo& info)

Sets Image_Info to info following the rules in setInfo and allocates pixel
memory. 

Aborts execution if Image_Info 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, Alpha_Type, Color_Type, Color_Space ##

#Example
#Image 4
SkBitmap bitmap;
bitmap.allocPixels(SkImageInfo::Make(64, 64, kGray_8_SkColorType, kOpaque_SkAlphaType));
SkCanvas offscreen(bitmap);
offscreen.scale(.5f, .5f);
for (int y : { 0, 64, 128, 192 } ) {
    offscreen.drawBitmap(source, -y, -y);
    canvas->drawBitmap(bitmap, y, y);
}
##

#SeeAlso tryAllocPixels allocPixelsFlags SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false)

#Line # allocates compatible Color_ARGB pixels if possible ##
Sets Image_Info to width, height, and Native_Color_Type; and allocates 
pixel memory. If isOpaque is true, sets Image_Info 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 Bitmap that matches SkPMColor, the native pixel arrangement on
the platform. Bitmap 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 ##

#Example
#Height 160
    SkBitmap bitmap;
    if (bitmap.tryAllocN32Pixels(80, 80)) {
        bitmap.eraseColor(SK_ColorTRANSPARENT);
        bitmap.erase(0x7f3f7fff, SkIRect::MakeWH(50, 30));
        bitmap.erase(0x3f7fff3f, SkIRect::MakeXYWH(20, 10, 50, 30));
        bitmap.erase(0x5fff3f7f, SkIRect::MakeXYWH(40, 20, 50, 30));
        canvas->drawBitmap(bitmap, 0, 0);
        for (int x : { 0, 30, 60, 90 } ) {
            canvas->drawBitmap(bitmap, x, 70);
        }
    }
##

#SeeAlso tryAllocPixels allocN32Pixels SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method void allocN32Pixels(int width, int height, bool isOpaque = false)

#Line # allocates compatible Color_ARGB pixels, or aborts ##
Sets Image_Info to width, height, and the Native_Color_Type; and allocates 
pixel memory. If isOpaque is true, sets Image_Info to kPremul_SkAlphaType;
otherwise, sets to kOpaque_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 Bitmap that matches SkPMColor, the native pixel arrangement on
the platform. Bitmap 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
    SkRandom random;
    SkBitmap bitmap;
    bitmap.allocN32Pixels(64, 64);
    bitmap.eraseColor(SK_ColorTRANSPARENT);
    for (int y = 0; y < 256; y += 64) {
        for (int x = 0; x < 256; x += 64) {
            SkColor color = random.nextU();
            uint32_t w = random.nextRangeU(4, 32);
            uint32_t cx = random.nextRangeU(0, 64 - w);
            uint32_t h = random.nextRangeU(4, 32);
            uint32_t cy = random.nextRangeU(0, 64 - h);
            bitmap.erase(color, SkIRect::MakeXYWH(cx, cy, w, h));
            canvas->drawBitmap(bitmap, x, y);
        }
    }
##

#SeeAlso allocPixels tryAllocN32Pixels SkMallocPixelRef::MakeAllocate

##

# ------------------------------------------------------------------------------

#Method bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                       void (*releaseProc)(void* addr, void* context), void* context)
#Line # creates Pixel_Ref, with optional release function ##

Sets Image_Info to info following the rules in setInfo, and creates Pixel_Ref
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 Image_Info 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 Image_Info, calls releaseProc if
present, returns true.

If Image_Info 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, Alpha_Type, Color_Type, Color_Space ##
#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 Image_Info is set to info ##

#Example
#Description
releaseProc is called immediately because rowBytes is too small for Pixel_Ref.
##
#Function
static void releaseProc(void* addr, void* ) {
    SkDebugf("releaseProc called\n");
    delete[] (uint32_t*) addr; 
}

##

void draw(SkCanvas* canvas) {
   SkBitmap bitmap;
   void* pixels = new uint32_t[8 * 8];
   SkImageInfo info = SkImageInfo::MakeN32(8, 8, kOpaque_SkAlphaType);
   SkDebugf("before installPixels\n");
   bool installed = bitmap.installPixels(info, pixels, 16, releaseProc, nullptr);
   SkDebugf("install " "%s" "successful\n", installed ? "" : "not ");
}
#StdOut
before installPixels
releaseProc called
install not successful
##
##

#SeeAlso allocPixels

##

# ------------------------------------------------------------------------------

#Method bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes)

Sets Image_Info to info following the rules in setInfo, and creates Pixel_Ref
containing pixels and rowBytes.

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

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

Caller must ensure that pixels are valid for the lifetime of Bitmap and Pixel_Ref.

#Param info  contains width, height, Alpha_Type, Color_Type, Color_Space ##
#Param pixels  address or pixel storage; may be nullptr ##
#Param rowBytes  size of pixel row or larger ##

#Return  true if Image_Info is set to info ##

#Example
#Description
#Bug 7079 ##
GPU does not support kUnpremul_SkAlphaType, does not assert that it does not.
##
void draw(SkCanvas* canvas) {
   SkRandom random;
   SkBitmap bitmap;
   const int width = 8;
   const int height = 8;
   uint32_t pixels[width * height];
   for (unsigned x = 0; x < width * height; ++x) {
       pixels[x] = random.nextU();
   }
   SkImageInfo info = SkImageInfo::MakeN32(width, height, kUnpremul_SkAlphaType);
   if (bitmap.installPixels(info, pixels, info.minRowBytes())) {
       canvas->scale(32, 32);
       canvas->drawBitmap(bitmap, 0, 0);
   }
}
##

#SeeAlso allocPixels

##

# ------------------------------------------------------------------------------

#Method bool installPixels(const SkPixmap& pixmap)

Sets Image_Info to pixmap.info() following the rules in setInfo, and creates
Pixel_Ref containing pixmap.addr() and pixmap.rowBytes.

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

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

Caller must ensure that pixmap is valid for the lifetime of Bitmap and Pixel_Ref.

#Param pixmap  Image_Info, pixel address, and rowBytes ##

#Return  true if Image_Info was set to pixmap.info() ##

#Example
#Description
Draw a five by five bitmap, and draw it again with a center white pixel.
##
#Height 64
    uint8_t storage[][5] = {{ 0xCA, 0xDA, 0xCA, 0xC9, 0xA3 },
                            { 0xAC, 0xA8, 0x89, 0x47, 0x87 },
                            { 0x4B, 0x25, 0x25, 0x25, 0x46 },
                            { 0x90, 0x81, 0x25, 0x41, 0x33 },
                            { 0x75, 0x55, 0x44, 0x20, 0x00 }};
    SkImageInfo imageInfo = SkImageInfo::Make(5, 5, kGray_8_SkColorType, kOpaque_SkAlphaType);
    SkPixmap pixmap(imageInfo, storage[0], sizeof(storage) / 5);
    SkBitmap bitmap;
    bitmap.installPixels(pixmap);
    canvas->scale(10, 10);
    canvas->drawBitmap(bitmap, 0, 0);
    *pixmap.writable_addr8(2, 2) = 0xFF;
    bitmap.installPixels(pixmap);
    canvas->drawBitmap(bitmap, 10, 0);
##

#SeeAlso allocPixels

##

# ------------------------------------------------------------------------------

#Method bool installMaskPixels(const SkMask& mask)

#Line # creates Pixel_Ref from Mask ##
Sets Image_Info to mask width, mask height, kAlpha_8_SkColorType, and
kPremul_SkAlphaType. Sets Pixel_Ref to mask image and mask rowBytes.

Returns false and calls reset() if mask format is not SkMask::kA8_Format,
or if mask width or mask height is negative, or if mask rowBytes is less
than mask width.

Caller must ensure that mask is valid for the lifetime of Bitmap and Pixel_Ref.

#Param mask  Alpha 8-bit bitmap ##

#Return true if Image_Info and Pixel_Ref refer to mask ##

#Example
#Description
Draw a five by five bitmap, and draw it again with a center white pixel.
##
#Height 64
    uint8_t storage[][5] = {{ 0xCA, 0xDA, 0xCA, 0xC9, 0xA3 },
                            { 0xAC, 0xA8, 0x89, 0x47, 0x87 },
                            { 0x4B, 0x25, 0x25, 0x25, 0x46 },
                            { 0x90, 0x81, 0x25, 0x41, 0x33 },
                            { 0x75, 0x55, 0x44, 0x20, 0x00 }};
    SkMask mask;
    mask.fImage = storage[0];
    mask.fBounds = SkIRect::MakeWH(5, 5);
    mask.fRowBytes = 5;
    mask.fFormat = SkMask::kA8_Format;
    SkBitmap bitmap;
    bitmap.installMaskPixels(mask);
    canvas->scale(10, 10);
    canvas->drawBitmap(bitmap, 0, 0);
    storage[2][2] = 0xFF;
    bitmap.installMaskPixels(mask);
    canvas->drawBitmap(bitmap, 10, 0);
##

#SeeAlso installPixels allocPixels

##

# ------------------------------------------------------------------------------

#Method void setPixels(void* pixels)

#Line # sets Pixel_Ref without an offset ##
Replaces Pixel_Ref with pixels, preserving Image_Info and rowBytes.
Sets Pixel_Ref origin to (0, 0).

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

Caller is responsible for handling ownership pixel memory for the lifetime
of Bitmap and Pixel_Ref.

#Param pixels  address of pixel storage, managed by caller ##

#Example
#Height 50
    uint8_t set1[5] = { 0xCA, 0xDA, 0xCA, 0xC9, 0xA3 };
    uint8_t set2[5] = { 0xAC, 0xA8, 0x89, 0x47, 0x87 };
    SkBitmap bitmap;
    bitmap.installPixels(SkImageInfo::Make(5, 1, kGray_8_SkColorType, kOpaque_SkAlphaType), set1, 5);
    canvas->scale(10, 50);
    canvas->drawBitmap(bitmap, 0, 0);
    bitmap.setPixels(set2);
    canvas->drawBitmap(bitmap, 10, 0);
##

#SeeAlso installPixels allocPixels

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocPixels()

Allocates pixel memory with HeapAllocator, and replaces existing Pixel_Ref.
The allocation size is determined by Image_Info width, height, and Color_Type.

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

#Return  true if the allocation succeeds
##

#Example
#Height 50
#Description 
Bitmap hosts and draws gray values in set1. tryAllocPixels replaces Pixel_Ref
and erases it to black, but does not alter set1. setPixels replaces black
Pixel_Ref with set1. 
##
    uint8_t set1[5] = { 0xCA, 0xDA, 0xCA, 0xC9, 0xA3 };
    SkBitmap bitmap;
    bitmap.installPixels(SkImageInfo::Make(5, 1, kGray_8_SkColorType, kOpaque_SkAlphaType), set1, 5);
    canvas->scale(10, 50);
    canvas->drawBitmap(bitmap, 0, 0);
    if (bitmap.tryAllocPixels()) {
        bitmap.eraseColor(SK_ColorBLACK);
        canvas->drawBitmap(bitmap, 8, 0);
        bitmap.setPixels(set1);
        canvas->drawBitmap(bitmap, 16, 0);
    }
##

#SeeAlso allocPixels installPixels setPixels

##

# ------------------------------------------------------------------------------

#Method void allocPixels()

Allocates pixel memory with HeapAllocator, and replaces existing Pixel_Ref.
The allocation size is determined by Image_Info width, height, and Color_Type.

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
#Height 50
#Description 
Bitmap hosts and draws gray values in set1. allocPixels replaces Pixel_Ref
and erases it to black, but does not alter set1. setPixels replaces black
Pixel_Ref with set2. 
##
    uint8_t set1[5] = { 0xCA, 0xDA, 0xCA, 0xC9, 0xA3 };
    uint8_t set2[5] = { 0xAC, 0xA8, 0x89, 0x47, 0x87 };
    SkBitmap bitmap;
    bitmap.installPixels(SkImageInfo::Make(5, 1, kGray_8_SkColorType, kOpaque_SkAlphaType), set1, 5);
    canvas->scale(10, 50);
    canvas->drawBitmap(bitmap, 0, 0);
    bitmap.allocPixels();
    bitmap.eraseColor(SK_ColorBLACK);
    canvas->drawBitmap(bitmap, 8, 0);
    bitmap.setPixels(set2);
    canvas->drawBitmap(bitmap, 16, 0);
##

#SeeAlso tryAllocPixels installPixels setPixels

##

# ------------------------------------------------------------------------------

#Method bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator)

Allocates pixel memory with allocator, and replaces existing Pixel_Ref.
The allocation size is determined by Image_Info width, height, and Color_Type.
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
##

#Example
#Height 100
#Description
HeapAllocator limits the maximum size of Bitmap to two gigabytes. Using
a custom allocator, this limitation may be relaxed. This example can be
modified to allocate an eight gigabyte Bitmap on a 64 bit platform with
sufficient memory.
##
#Function
class LargePixelRef : public SkPixelRef {
public:
    LargePixelRef(const SkImageInfo& info, char* storage, size_t rowBytes)
        : SkPixelRef(info.width(), info.height(), storage, rowBytes) {
    }

    ~LargePixelRef() override {
        delete[] (char* ) this->pixels();
    }
};

class LargeAllocator : public SkBitmap::Allocator {
public:
    bool allocPixelRef(SkBitmap* bitmap) override {
        const SkImageInfo& info = bitmap->info();
        uint64_t rowBytes = info.minRowBytes64();
        uint64_t size = info.height() * rowBytes;
        char* addr = new char[size];
        if (nullptr == addr) {
            return false;
        }
        sk_sp<SkPixelRef> pr = sk_sp<SkPixelRef>(new LargePixelRef(info, addr, rowBytes));
        if (!pr) {
            return false;
        }
        bitmap->setPixelRef(std::move(pr), 0, 0);
        return true;
    }
};

##

void draw(SkCanvas* canvas) {
   LargeAllocator largeAllocator;
   SkBitmap bitmap;
   int width = 100; // make this 20000
   int height = 100; // and this 100000 to allocate 8 gigs on a 64-bit platform
   bitmap.setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType));
   if (bitmap.tryAllocPixels(&largeAllocator)) {
       bitmap.eraseColor(0xff55aa33);
       canvas->drawBitmap(bitmap, 0, 0);
   }
}

##

#SeeAlso allocPixels Allocator Pixel_Ref

##

# ------------------------------------------------------------------------------

#Method void allocPixels(Allocator* allocator)

Allocates pixel memory with allocator, and replaces existing Pixel_Ref.
The allocation size is determined by Image_Info width, height, and Color_Type.
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
#Height 32
#Function
class TinyAllocator : public SkBitmap::Allocator {
public:
    bool allocPixelRef(SkBitmap* bitmap) override {
        const SkImageInfo& info = bitmap->info();
        if (info.height() * info.minRowBytes() > sizeof(storage)) {
            return false;
        }
        sk_sp<SkPixelRef> pr = sk_sp<SkPixelRef>(
                new SkPixelRef(info.width(), info.height(), storage, info.minRowBytes()));
        bitmap->setPixelRef(std::move(pr), 0, 0);
        return true;
    }

    char storage[16];
};

##

void draw(SkCanvas* canvas) {
   TinyAllocator tinyAllocator;
   SkBitmap bitmap;
   bitmap.setInfo(SkImageInfo::MakeN32(2, 2, kOpaque_SkAlphaType));
   if (bitmap.tryAllocPixels(&tinyAllocator)) {
       bitmap.eraseColor(0xff55aa33);
       bitmap.erase(0xffaa3355, SkIRect::MakeXYWH(1, 1, 1, 1));
       canvas->scale(16, 16);
       canvas->drawBitmap(bitmap, 0, 0);
   }
}
##

#SeeAlso allocPixels Allocator Pixel_Ref

##

# ------------------------------------------------------------------------------

#Method SkPixelRef* pixelRef() const

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

#Return  Pixel_Ref, or nullptr ##

#Example
#Image 3
   SkBitmap subset;
   source.extractSubset(&subset, SkIRect::MakeXYWH(32, 64, 128, 256));
   SkDebugf("src ref %c= sub ref\n", source.pixelRef() == subset.pixelRef() ? '=' : '!');
   SkDebugf("src pixels %c= sub pixels\n", source.getPixels() == subset.getPixels() ? '=' : '!');
   SkDebugf("src addr %c= sub addr\n", source.getAddr(32, 64) == subset.getAddr(0, 0) ? '=' : '!');
##

#SeeAlso getPixels getAddr

##

# ------------------------------------------------------------------------------

#Method SkIPoint pixelRefOrigin() const

#Line # returns offset within Pixel_Ref ##
Returns origin of pixels within Pixel_Ref. Bitmap bounds is always contained
by Pixel_Ref bounds, which may be the same size or larger. Multiple Bitmaps
can share the same Pixel_Ref, where each Bitmap has different bounds.

The returned origin added to Bitmap dimensions equals or is smaller than the
Pixel_Ref dimensions.

Returns (0, 0) if Pixel_Ref is nullptr.

#Return  pixel origin within Pixel_Ref ##

#Example
#Image 3
   SkBitmap subset;
   source.extractSubset(&subset, SkIRect::MakeXYWH(32, 64, 128, 256));
   SkIPoint sourceOrigin = source.pixelRefOrigin();
   SkIPoint subsetOrigin = subset.pixelRefOrigin();
   SkDebugf("source origin: %d, %d\n", sourceOrigin.fX, sourceOrigin.fY);
   SkDebugf("subset origin: %d, %d\n", subsetOrigin.fX, subsetOrigin.fY);
#StdOut
source origin: 0, 0
subset origin: 32, 64
##
##

#SeeAlso SkPixelRef getSubset setPixelRef

##

# ------------------------------------------------------------------------------

#Method void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy)

#Line # sets Pixel_Ref and offset ##
Replaces pixelRef and origin in Bitmap.  dx and dy specify the offset
within the Pixel_Ref 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
Color_Type and Alpha_Type in Image_Info.

#Param pixelRef  Pixel_Ref describing pixel address and rowBytes ##
#Param dx   column offset in Pixel_Ref for bitmap origin ##
#Param dy   row offset in Pixel_Ref for bitmap origin ##

#Example
#Height 140
#Image 5
#Description
Treating 32 bit data as 8 bit data is unlikely to produce useful results.
##
    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(source.width() - 5, source.height() - 5, 
                   kGray_8_SkColorType, kOpaque_SkAlphaType), source.rowBytes());
    bitmap.setPixelRef(sk_ref_sp(source.pixelRef()), 5, 5);
    canvas->drawBitmap(bitmap, 10, 10);
##

#SeeAlso setInfo

##

# ------------------------------------------------------------------------------

#Method bool readyToDraw() const

#Line # returns true if address of pixels is not nullptr ##
Returns true if Bitmap is can be drawn.

#Return  true if getPixels() is not nullptr ##

#Example
#Image 5
#Height 160
    if (source.readyToDraw()) {
        canvas->drawBitmap(source, 10, 10);
    }
##

#SeeAlso getPixels drawsNothing

##

# ------------------------------------------------------------------------------

#Method uint32_t getGenerationID() const

#Line # returns unique ID ##
Returns a unique value corresponding to the pixels in Pixel_Ref. 
Returns a different value after notifyPixelsChanged has been called.
Returns zero if Pixel_Ref is nullptr.

Determines if pixels have changed since last examined.

#Return unique value for pixels in Pixel_Ref ##

#Example
    SkBitmap bitmap;
    SkDebugf("empty id %u\n", bitmap.getGenerationID());
    bitmap.allocPixels(SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType));
    SkDebugf("alloc id %u\n", bitmap.getGenerationID());
    bitmap.eraseColor(SK_ColorRED);
    SkDebugf("erase id %u\n", bitmap.getGenerationID());
#StdOut
#Volatile
empty id 0
alloc id 4
erase id 6
##    
##

#SeeAlso notifyPixelsChanged Pixel_Ref

##

# ------------------------------------------------------------------------------

#Method void notifyPixelsChanged() const

#Line # marks pixels as changed, altering the unique ID ##
Marks that pixels in Pixel_Ref have changed. Subsequent calls to 
getGenerationID() return a different value.

#Example
#Height 20
    SkBitmap bitmap; 
    bitmap.setInfo(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
    bitmap.allocPixels();
    bitmap.eraseColor(SK_ColorRED);
    canvas->scale(16, 16);
    canvas->drawBitmap(bitmap, 0, 0);
    *(SkPMColor*) bitmap.getPixels() = SkPreMultiplyColor(SK_ColorBLUE);
    canvas->drawBitmap(bitmap, 2, 0);
    bitmap.notifyPixelsChanged();
    *(SkPMColor*) bitmap.getPixels() = SkPreMultiplyColor(SK_ColorGREEN);
    canvas->drawBitmap(bitmap, 4, 0);
##

#SeeAlso getGenerationID isVolatile Pixel_Ref

##

# ------------------------------------------------------------------------------

#Method void eraseColor(SkColor c) const

#Line # writes Color to pixels ##
Replaces pixel values with c. All pixels contained by bounds() are affected.
If the colorType is kGray_8_SkColorType or k565_SkColorType, then Color_Alpha
is ignored; Color_RGB is treated as opaque. If colorType is kAlpha_8_SkColorType,
then Color_RGB is ignored.

#Param c  Unpremultiplied Color ##

#Example
#Height 20
    SkBitmap bitmap; 
    bitmap.allocPixels(SkImageInfo::MakeN32(1, 1, kOpaque_SkAlphaType));
    bitmap.eraseColor(SK_ColorRED);
    canvas->scale(16, 16);
    canvas->drawBitmap(bitmap, 0, 0);
##

#SeeAlso eraseARGB erase

##

# ------------------------------------------------------------------------------

#Method void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const

#Line # writes Color to pixels ##
Replaces pixel values with Unpremultiplied Color built from a, r, g, and b.
All pixels contained by bounds() are affected.
If the colorType is kGray_8_SkColorType or k565_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 Color_Alpha, from fully transparent (0) to fully opaque (255) ##
#Param r    amount of Color_RGB_Red, from no red (0) to full red (255) ##
#Param g    amount of Color_RGB_Green, from no green (0) to full green (255) ##
#Param b    amount of Color_RGB_Blue, from no blue (0) to full blue (255) ##

#Example
#Height 80
    SkBitmap bitmap; 
    bitmap.allocPixels(SkImageInfo::MakeN32(1, 1, kPremul_SkAlphaType));
    bitmap.eraseARGB(0x7f, 0xff, 0x7f, 0x3f);
    canvas->scale(50, 50);
    canvas->drawBitmap(bitmap, 0, 0);
    canvas->drawBitmap(bitmap, .5f, .5f);
##

#SeeAlso eraseColor erase

##

# ------------------------------------------------------------------------------

#Method void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const

#Line # deprecated ##
Deprecated. Use eraseARGB or eraseColor.

#Param r    amount of red ##
#Param g    amount of green ##
#Param b    amount of blue ##

#NoExample
##

#SeeAlso eraseColor eraseARGB erase

##

# ------------------------------------------------------------------------------

#Method void erase(SkColor c, const SkIRect& area) const

#Line # writes Color to rectangle of pixels ##
Replaces pixel values inside area with c. If area does not intersect bounds(),
call has no effect.

If the colorType is kGray_8_SkColorType or k565_SkColorType, then Color_Alpha
is ignored; Color_RGB is treated as opaque. If colorType is kAlpha_8_SkColorType,
then Color_RGB is ignored.

#Param c  Unpremultiplied Color ##
#Param area  rectangle to fill ##

#Example
#Height 70
    SkBitmap bitmap; 
    bitmap.allocPixels(SkImageInfo::MakeN32(2, 2, kPremul_SkAlphaType));
    bitmap.erase(0x7fff7f3f, SkIRect::MakeWH(1, 1));
    bitmap.erase(0x7f7f3fff, SkIRect::MakeXYWH(0, 1, 1, 1));
    bitmap.erase(0x7f3fff7f, SkIRect::MakeXYWH(1, 0, 1, 1));
    bitmap.erase(0x7f1fbf5f, SkIRect::MakeXYWH(1, 1, 1, 1));
    canvas->scale(25, 25);
    canvas->drawBitmap(bitmap, 0, 0);
    canvas->drawBitmap(bitmap, .5f, .5f);

##

#SeeAlso eraseColor eraseARGB eraseRGB SkCanvas::drawRect

##

# ------------------------------------------------------------------------------

#Method void eraseArea(const SkIRect& area, SkColor c) const

#Line # deprecated ##
Legacy call to be deprecated.

#Deprecated 
##

##

# ------------------------------------------------------------------------------

#Method SkColor getColor(int x, int y) const

#Line # returns one pixel as Unpremultiplied Color ##
Returns pixel at (x, y) as Unpremultiplied Color.
Returns black with Alpha if Color_Type 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 Color_Type is kUnknown_SkColorType or
pixel address is nullptr.

Color_Space in Image_Info 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 ##

#Example
    const int w = 4;
    const int h = 4;
    SkColor colors[][w] = {
        0x00000000, 0x2a0e002a, 0x55380055, 0x7f7f007f,
        0x2a000e2a, 0x551c1c55, 0x7f542a7f, 0xaaaa38aa,
        0x55003855, 0x7f2a547f, 0xaa7171aa, 0xd4d48dd4,
        0x7f007f7f, 0xaa38aaaa, 0xd48dd4d4, 0xffffffff, 
    };
    SkDebugf("Premultiplied:\n");
    for (int y = 0; y < h; ++y) {
        SkDebugf("(0, %d) ", y);
        for (int x = 0; x < w; ++x) {
            SkDebugf("0x%08x%c", colors[y][x], x == w - 1 ? '\n' : ' ');
        }
    }
    SkPixmap pixmap(SkImageInfo::MakeN32(w, h, kPremul_SkAlphaType), colors, w * 4);
    SkBitmap bitmap;
    bitmap.installPixels(pixmap);
    SkDebugf("Unpremultiplied:\n");
    for (int y = 0; y < h; ++y) {
        SkDebugf("(0, %d) ", y);
        for (int x = 0; x < w; ++x) {
            SkDebugf("0x%08x%c", bitmap.getColor(x, y), x == w - 1 ? '\n' : ' ');
        }
    }
#StdOut
Premultiplied:
(0, 0) 0x00000000 0x2a0e002a 0x55380055 0x7f7f007f 
(0, 1) 0x2a000e2a 0x551c1c55 0x7f542a7f 0xaaaa38aa 
(0, 2) 0x55003855 0x7f2a547f 0xaa7171aa 0xd4d48dd4 
(0, 3) 0x7f007f7f 0xaa38aaaa 0xd48dd4d4 0xffffffff 
Unpremultiplied:
(0, 0) 0x00000000 0x2a5500ff 0x55a800ff 0x7fff00ff 
(0, 1) 0x2a0055ff 0x555454ff 0x7fa954ff 0xaaff54ff 
(0, 2) 0x5500a8ff 0x7f54a9ff 0xaaaaaaff 0xd4ffaaff 
(0, 3) 0x7f00ffff 0xaa54ffff 0xd4aaffff 0xffffffff 
##
##

#SeeAlso getAddr readPixels

##

# ------------------------------------------------------------------------------

#Method void* getAddr(int x, int y) const

#Line # returns readable pixel address as void pointer ##
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
Color_Type is kUnknown_SkColorType, or Pixel_Ref 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
#Image 3
    char* row0 = (char* ) source.getAddr(0, 0);
    char* row1 = (char* ) source.getAddr(0, 1);
    SkDebugf("addr interval %c= rowBytes\n", row1 - row0 == source.rowBytes() ? '=' : '!');
#StdOut
addr interval == rowBytes
##
##

#SeeAlso getAddr8 getAddr16 getAddr32 readPixels SkPixmap::addr

##

# ------------------------------------------------------------------------------

#Method inline uint32_t* getAddr32(int x, int y) const

#Line # returns readable pixel address as 32-bit pointer ##
Returns address at (x, y). 

Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
#List
# Pixel_Ref 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) ##

#Example
#Image 3
    uint32_t* row0 = source.getAddr32(0, 0);
    uint32_t* row1 = source.getAddr32(0, 1);
    size_t interval = (row1 - row0) * source.bytesPerPixel();
    SkDebugf("addr interval %c= rowBytes\n", interval == source.rowBytes() ? '=' : '!');
#StdOut
addr interval == rowBytes
##
##

#SeeAlso getAddr8 getAddr16 getAddr readPixels SkPixmap::addr32

##

# ------------------------------------------------------------------------------

#Method inline uint16_t* getAddr16(int x, int y) const

#Line # returns readable pixel address as 16-bit pointer ##
Returns address at (x, y). 

Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
#List
# Pixel_Ref 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)##

#Example
#Image 3
    SkBitmap bitmap16;
    SkImageInfo dstInfo = SkImageInfo::Make(source.width(), source.height(), kARGB_4444_SkColorType, 
                     kPremul_SkAlphaType);
    bitmap16.allocPixels(dstInfo);
    if (source.readPixels(dstInfo, bitmap16.getPixels(), bitmap16.rowBytes(), 0, 0)) {
        uint16_t* row0 = bitmap16.getAddr16(0, 0);
        uint16_t* row1 = bitmap16.getAddr16(0, 1);
        size_t interval = (row1 - row0) * bitmap16.bytesPerPixel();
        SkDebugf("addr interval %c= rowBytes\n", interval == bitmap16.rowBytes() ? '=' : '!');
    }
#StdOut
addr interval == rowBytes
##
##

#SeeAlso getAddr8 getAddr getAddr32 readPixels SkPixmap::addr16

##

# ------------------------------------------------------------------------------

#Method inline uint8_t* getAddr8(int x, int y) const

#Line # returns readable pixel address as 8-bit pointer ##
Returns address at (x, y). 

Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
#List
# Pixel_Ref 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) ##

#Example
   SkBitmap bitmap;
   const int width = 8;
   const int height = 8;
   uint8_t pixels[height][width];
   SkImageInfo info = SkImageInfo::Make(width, height, kGray_8_SkColorType, kOpaque_SkAlphaType);
   if (bitmap.installPixels(info, pixels, info.minRowBytes())) {
       SkDebugf("&pixels[4][2] %c= bitmap.getAddr8(2, 4)\n",
                 &pixels[4][2]  == bitmap.getAddr8(2, 4) ? '=' : '!');
   }
#StdOut
&pixels[4][2] == bitmap.getAddr8(2, 4)
##
##

#SeeAlso getAddr getAddr16 getAddr32 readPixels SkPixmap::addr8

##

# ------------------------------------------------------------------------------

#Method bool extractSubset(SkBitmap* dst, const SkIRect& subset) const

#Line # creates Bitmap, sharing pixels if possible ##
Shares Pixel_Ref with dst. Pixels are not copied; Bitmap 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. isVolatile setting is copied to dst.
dst is set to colorType, alphaType, and colorSpace.

Return false if:
#List
# dst is nullptr ##
# Pixel_Ref is nullptr ##
# subset does not intersect bounds() ##
## 


#Param dst  Bitmap set to subset ##
#Param subset  rectangle of pixels to reference ##

#Return  true if dst is replaced by subset
##

#Example
#Image 3
    SkIRect bounds, s;
    source.getBounds(&bounds);
    SkDebugf("bounds: %d, %d, %d, %d\n", bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
    SkBitmap subset;
    for (int left: { -100, 0, 100, 1000 } ) {
         for (int right: { 0, 100, 1000 } ) {
             SkIRect b = SkIRect::MakeLTRB(left, 100, right, 200);
             bool success = source.extractSubset(&subset, b);
             SkDebugf("subset: %4d, %4d, %4d, %4d  ", b.fLeft, b.fTop, b.fRight, b.fBottom);
             SkDebugf("success; %s", success ? "true" : "false");
             if (success) {
                 subset.getBounds(&s);  
                 SkDebugf("  subset: %d, %d, %d, %d", s.fLeft, s.fTop, s.fRight, s.fBottom);
             }
             SkDebugf("\n");
         } 
    }
#StdOut
bounds: 0, 0, 512, 512
subset: -100,  100,    0,  200  success; false
subset: -100,  100,  100,  200  success; true  subset: 0, 0, 100, 100
subset: -100,  100, 1000,  200  success; true  subset: 0, 0, 512, 100
subset:    0,  100,    0,  200  success; false
subset:    0,  100,  100,  200  success; true  subset: 0, 0, 100, 100
subset:    0,  100, 1000,  200  success; true  subset: 0, 0, 512, 100
subset:  100,  100,    0,  200  success; false
subset:  100,  100,  100,  200  success; false
subset:  100,  100, 1000,  200  success; true  subset: 0, 0, 412, 100
subset: 1000,  100,    0,  200  success; false
subset: 1000,  100,  100,  200  success; false
subset: 1000,  100, 1000,  200  success; false
##
##

#SeeAlso readPixels writePixels SkCanvas::drawBitmap

##

# ------------------------------------------------------------------------------

#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                    int srcX, int srcY, SkTransferFunctionBehavior behavior) const
#Line # copies and converts pixels ##

Copies Rect of pixels from Bitmap pixels to dstPixels. Copy starts at (srcX, srcY),
and does not exceed Bitmap (width(), height()). 

dstInfo specifies width, height, Color_Type, Alpha_Type, and 
Color_Space of destination. dstRowBytes specifics the gap from one destination
row to the next. Returns true if pixels are copied. Returns false if:
#List
# dstInfo.addr() equals nullptr ##
# dstRowBytes is less than dstInfo.minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType must match.
If Bitmap colorType is kGray_8_SkColorType, dstInfo.colorSpace must match.
If Bitmap alphaType is kOpaque_SkAlphaType, dstInfo.alphaType must
match. If Bitmap 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 
#Formula
abs(srcX) >= Bitmap width()
##
, or if
#Formula
abs(srcY) >= Bitmap height()
##
.

If behavior is SkTransferFunctionBehavior::kRespect: converts source
pixels to a linear space before converting to dstInfo.
If behavior is SkTransferFunctionBehavior::kIgnore: source
pixels are treated as if they are linear, regardless of how they are encoded.

#Param dstInfo  destination width, height, Color_Type, Alpha_Type, Color_Space ##
#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() ##
#Param behavior  one of: SkTransferFunctionBehavior::kRespect,
                         SkTransferFunctionBehavior::kIgnore 
##

#Return  true if pixels are copied to dstPixels ##

#Example
#Height 64
void draw(SkCanvas* canvas) {
    const int width = 256;
    const int height = 32;
    std::vector<int32_t> dstPixels;
    dstPixels.resize(height * width * 4);
    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
    SkColor  gradColors[] = { 0xFFAA3300, 0x7F881122 };
    SkPoint  gradPoints[] = { { 0, 0 }, { width, 0 } };
    SkPaint gradPaint;
    gradPaint.setShader(SkGradientShader::MakeLinear(gradPoints, gradColors, nullptr,
                    SK_ARRAY_COUNT(gradColors), SkShader::kClamp_TileMode));
    for (auto behavior : { SkTransferFunctionBehavior::kRespect,
                           SkTransferFunctionBehavior::kIgnore} ) {
        SkBitmap bitmap;
        bitmap.allocPixels(info);
        SkCanvas srcCanvas(bitmap);
        srcCanvas.drawRect(SkRect::MakeWH(width, height), gradPaint);
        if (bitmap.readPixels(info, &dstPixels.front(), width * 4, 0, 0, behavior)) {
            SkPixmap dstPixmap(info, &dstPixels.front(), width * 4);
            bitmap.installPixels(dstPixmap);
            canvas->drawBitmap(bitmap, 0, 0);
        }
        canvas->translate(0, height);
    }
}
##

#SeeAlso writePixels SkPixmap::readPixels SkCanvas::readPixels SkImage::readPixels SkSurface::readPixels

##

# ------------------------------------------------------------------------------

#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
                    int srcX, int srcY) const

Copies a Rect of pixels from Bitmap to dstPixels. Copy starts at (srcX, srcY),
and does not exceed Bitmap (width(), height()). 

dstInfo specifies width, height, Color_Type, Alpha_Type, and Color_Space of
destination. dstRowBytes specifics the gap from one destination row to the next.
Returns true if pixels are copied. Returns false if:
#List
# dstInfo.addr() equals nullptr ##
# dstRowBytes is less than dstInfo.minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType must match.
If Bitmap colorType is kGray_8_SkColorType, dstInfo.colorSpace must match.
If Bitmap alphaType is kOpaque_SkAlphaType, dstInfo.alphaType must
match. If Bitmap 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 
#Formula
abs(srcX) >= Bitmap width()
##
, or if
#Formula
abs(srcY) >= Bitmap height()
##
.

#Param dstInfo  destination width, height, Color_Type, Alpha_Type, Color_Space ##
#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 ##

#Example
#Height 128
#Description
Transferring the gradient from 8 bits per component to 4 bits per component
creates visible banding.
##
    const int width = 256;
    const int height = 64;
    SkImageInfo srcInfo = SkImageInfo::MakeN32Premul(width, height);
    SkColor  gradColors[] = { 0xFFAA3300, 0x7F881122 };
    SkPoint  gradPoints[] = { { 0, 0 }, { 256, 0 } };
    SkPaint paint;
    paint.setShader(SkGradientShader::MakeLinear(gradPoints, gradColors, nullptr,
                    SK_ARRAY_COUNT(gradColors), SkShader::kClamp_TileMode));
    SkBitmap bitmap;
    bitmap.allocPixels(srcInfo);
    SkCanvas srcCanvas(bitmap);
    srcCanvas.drawRect(SkRect::MakeWH(width, height), paint);
    canvas->drawBitmap(bitmap, 0, 0);
    SkImageInfo dstInfo = srcInfo.makeColorType(kARGB_4444_SkColorType);
    std::vector<int16_t> dstPixels;
    dstPixels.resize(height * width);
    bitmap.readPixels(dstInfo, &dstPixels.front(), width * 2, 0, 0);
    SkPixmap dstPixmap(dstInfo, &dstPixels.front(), width * 2);
    bitmap.installPixels(dstPixmap);
    canvas->drawBitmap(bitmap, 0, 64);
##

#SeeAlso writePixels SkPixmap::readPixels SkCanvas::readPixels SkImage::readPixels SkSurface::readPixels

##

# ------------------------------------------------------------------------------

#Method bool readPixels(const SkPixmap& dst, int srcX, int srcY) const

Copies a Rect of pixels from Bitmap to dst. Copy starts at (srcX, srcY), and
does not exceed Bitmap (width(), height()). 

dst specifies width, height, Color_Type, Alpha_Type, Color_Space, 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:
#List
# dst pixel storage equals nullptr ##
# dst.rowBytes is less than SkImageInfo::minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst Color_Type must match.
If Bitmap colorType is kGray_8_SkColorType, dst Color_Space must match.
If Bitmap alphaType is kOpaque_SkAlphaType, dst Alpha_Type must
match. If Bitmap colorSpace is nullptr, dst Color_Space 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 
#Formula
abs(srcX) >= Bitmap width()
##
, or if
#Formula
abs(srcY) >= Bitmap height()
##
.

#Param dst  destination Pixmap: Image_Info, 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
#Image 3
    std::vector<int32_t> srcPixels;
    srcPixels.resize(source.height() * source.rowBytes());
    for (int y = 0; y < 4; ++y) {
        for (int x = 0; x < 4; ++x) {
            SkPixmap pixmap(SkImageInfo::MakeN32Premul(source.width() / 4, source.height() / 4),
                    &srcPixels.front() + x * source.height() * source.width() / 4 +
                    y * source.width() / 4, source.rowBytes());
            source.readPixels(pixmap, x * source.width() / 4, y * source.height() / 4);
        }
    }
    canvas->scale(.5f, .5f);
    SkBitmap bitmap;
    bitmap.installPixels(SkImageInfo::MakeN32Premul(source.width(), source.height()),
                             &srcPixels.front(), source.rowBytes());
    canvas->drawBitmap(bitmap, 0, 0);
##

#SeeAlso writePixels SkPixmap::readPixels SkCanvas::readPixels SkImage::readPixels SkSurface::readPixels

##

# ------------------------------------------------------------------------------

#Method bool readPixels(const SkPixmap& dst) const

Copies a Rect of pixels from Bitmap to dst. Copy starts at (0, 0), and
does not exceed Bitmap (width(), height()). 

dst specifies width, height, Color_Type, Alpha_Type, Color_Space, 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:
#List
# dst pixel storage equals nullptr ##
# dst.rowBytes is less than SkImageInfo::minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst Color_Type must match.
If Bitmap colorType is kGray_8_SkColorType, dst Color_Space must match.
If Bitmap alphaType is kOpaque_SkAlphaType, dst Alpha_Type must
match. If Bitmap colorSpace is nullptr, dst Color_Space must match. Returns
false if pixel conversion is not possible.
 
#Param dst  destination Pixmap: Image_Info, pixels, row bytes ##

#Return  true if pixels are copied to dst ##

#Example
#Height 128
#Image 3
    std::vector<int32_t> srcPixels;
    srcPixels.resize(source.height() * source.width() * 8);
    for (int i = 0;  i < 2; ++i) {
    SkPixmap pixmap(SkImageInfo::Make(source.width() * 2, source.height(), 
                    i ? kRGBA_8888_SkColorType : kBGRA_8888_SkColorType, kPremul_SkAlphaType),
                    &srcPixels.front() + i * source.width(), source.rowBytes() * 2);
        source.readPixels(pixmap);
    }
    canvas->scale(.25f, .25f);
    SkBitmap bitmap;
    bitmap.installPixels(SkImageInfo::MakeN32Premul(source.width() * 2, source.height()),
                         &srcPixels.front(), source.rowBytes() * 2);
    canvas->drawBitmap(bitmap, 0, 0);
##

#SeeAlso writePixels SkPixmap::readPixels SkCanvas::readPixels SkImage::readPixels SkSurface::readPixels

##

# ------------------------------------------------------------------------------

#Method bool writePixels(const SkPixmap& src, int dstX, int dstY)

#Line # copies and converts pixels ##
Copies a Rect of pixels from src. Copy starts at (dstX, dstY), and does not exceed
(src.width(), src.height()). 

src specifies width, height, Color_Type, Alpha_Type, Color_Space, 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:
#List
# src pixel storage equals nullptr ##
# src.rowBytes is less than SkImageInfo::minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; src Color_Type must match.
If Bitmap colorType is kGray_8_SkColorType, src Color_Space must match.
If Bitmap alphaType is kOpaque_SkAlphaType, src Alpha_Type must
match. If Bitmap colorSpace is nullptr, src Color_Space 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 
#Formula
abs(dstX) >= Bitmap width()
##
, or if
#Formula
abs(dstY) >= Bitmap height()
##
.

#Param src  source Pixmap: Image_Info, 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 Bitmap ##

#Example
#Image 3
    std::vector<int32_t> srcPixels;
    int width = image->width();
    int height = image->height();
    srcPixels.resize(height * width  * 4);
    SkPixmap pixmap(SkImageInfo::MakeN32Premul(width, height), (const void*) &srcPixels.front(),
                    width * 4);
    image->readPixels(pixmap, 0, 0);
    canvas->scale(.5f, .5f);
    width /= 4;
    height /= 4;
    for (int y = 0; y < 4; ++y) {
        for (int x = 0; x < 4; ++x) {
            SkBitmap bitmap;
            bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height));
            bitmap.writePixels(pixmap, -y * width, -x * height);
            canvas->drawBitmap(bitmap, x * width, y * height);
        }
    }
##

#SeeAlso readPixels 

##

# ------------------------------------------------------------------------------

#Method bool writePixels(const SkPixmap& src)

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

src specifies width, height, Color_Type, Alpha_Type, Color_Space, 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:
#List
# src pixel storage equals nullptr ##
# src.rowBytes is less than SkImageInfo::minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; src Color_Type must match.
If Bitmap colorType is kGray_8_SkColorType, src Color_Space must match.
If Bitmap alphaType is kOpaque_SkAlphaType, src Alpha_Type must
match. If Bitmap colorSpace is nullptr, src Color_Space must match. Returns
false if pixel conversion is not possible.

#Param src  source Pixmap: Image_Info, pixels, row bytes ##

#Return  true if src pixels are copied to Bitmap ##

#Example
#Height 80
    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2));
    bitmap.eraseColor(SK_ColorGREEN);
    SkPMColor color = 0xFF5599BB;
    SkPixmap src(SkImageInfo::MakeN32Premul(1, 1), &color, 4);
    bitmap.writePixels(src);
    canvas->scale(40, 40);
    canvas->drawBitmap(bitmap, 0, 0);
##

#SeeAlso readPixels

##

# ------------------------------------------------------------------------------

#Method bool writePixels(const SkPixmap& src, int x, int y, SkTransferFunctionBehavior behavior)

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

src specifies width, height, Color_Type, Alpha_Type, Color_Space, 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:
#List
# src pixel storage equals nullptr ##
# src.rowBytes is less than SkImageInfo::minRowBytes ##
# Pixel_Ref is nullptr ##
##

Pixels are copied only if pixel conversion is possible. If Bitmap colorType is
kGray_8_SkColorType, or kAlpha_8_SkColorType; src Color_Type must match.
If Bitmap colorType is kGray_8_SkColorType, src Color_Space must match.
If Bitmap alphaType is kOpaque_SkAlphaType, src Alpha_Type must
match. If Bitmap colorSpace is nullptr, src Color_Space must match. Returns
false if pixel conversion is not possible. Returns false if width() or height()
is zero or negative.

If behavior is SkTransferFunctionBehavior::kRespect: converts src
pixels to a linear space before converting to Image_Info.
If behavior is SkTransferFunctionBehavior::kIgnore: src
pixels are treated as if they are linear, regardless of how they are encoded.

#Param src  source Pixmap: Image_Info, pixels, row bytes ##
#Param x  column index whose absolute value is less than width() ##
#Param y  row index whose absolute value is less than height() ##
#Param behavior  one of: SkTransferFunctionBehavior::kRespect,
                         SkTransferFunctionBehavior::kIgnore 
##

#Return  true if src pixels are copied to Bitmap ##

#Example
#Height 64
    const int width = 256;
    const int height = 32;
    std::vector<int32_t> dstPixels;
    dstPixels.resize(height * width * 4);
    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
    SkColor  gradColors[] = { 0xFFAA3300, 0x7F881122 };
    SkPoint  gradPoints[] = { { 0, 0 }, { width, 0 } };
    SkPaint gradPaint;
    gradPaint.setShader(SkGradientShader::MakeLinear(gradPoints, gradColors, nullptr,
                    SK_ARRAY_COUNT(gradColors), SkShader::kClamp_TileMode));
    for (auto behavior : { SkTransferFunctionBehavior::kRespect,
                           SkTransferFunctionBehavior::kIgnore} ) {
        SkPixmap dstPixmap(info, &dstPixels.front(), width * 4);
        SkBitmap bitmap;
        bitmap.installPixels(dstPixmap);
        SkCanvas srcCanvas(bitmap);
        srcCanvas.drawRect(SkRect::MakeWH(width, height), gradPaint);
        if (bitmap.writePixels(dstPixmap, 0, 0, behavior)) {
            canvas->drawBitmap(bitmap, 0, 0);
        }
        canvas->translate(0, height);
    }
##

#SeeAlso readPixels

##

# ------------------------------------------------------------------------------

#Method bool hasHardwareMipMap() const

#Line # returns Mip_Map support present; Android only ##
#Private
Android framework only.
##

#Return  true if setHasHardwareMipMap has been called with true ##

#NoExample
##

#SeeAlso setHasHardwareMipMap

##

# ------------------------------------------------------------------------------

#Method void setHasHardwareMipMap(bool hasHardwareMipMap)

#Line # sets Mip_Map support present; Android only ##
#Private
Android framework only.
##

#Param hasHardwareMipMap  sets state ##

#NoExample
##

#SeeAlso hasHardwareMipMap

##

# ------------------------------------------------------------------------------

#Method bool extractAlpha(SkBitmap* dst) const

#Line # creates Bitmap containing Alpha of pixels ##
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 Pixel_Ref.

#Param dst  holds Pixel_Ref to fill with alpha layer ##

#Return  true if Alpha layer was constructed in dst Pixel_Ref ##

#Example
#Height 100
    SkBitmap alpha, bitmap;
    bitmap.allocN32Pixels(100, 100);
    SkCanvas offscreen(bitmap);
    offscreen.clear(0);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorBLUE);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(20);
    offscreen.drawCircle(50, 50, 39, paint);
    offscreen.flush();
    bitmap.extractAlpha(&alpha);
    paint.setColor(SK_ColorRED);
    canvas->drawBitmap(bitmap, 0, 0, &paint);
    canvas->drawBitmap(alpha, 100, 0, &paint);
##

#SeeAlso extractSubset

##

# ------------------------------------------------------------------------------

#Method bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
                      SkIPoint* offset) const

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 Mask_Filter, SkMaskFilter::filterMask 
generates Mask_Alpha from Bitmap. Uses HeapAllocator to reserve memory for dst
Pixel_Ref. Sets offset to top-left position for dst for alignment with Bitmap;
(0, 0) unless SkMaskFilter generates mask.

#Param dst  holds Pixel_Ref to fill with alpha layer ##
#Param paint  holds optional Mask_Filter; may be nullptr ##
#Param offset  top-left position for dst; may be nullptr ##

#Return  true if Alpha layer was constructed in dst Pixel_Ref ##

#Bug 7103 ##
#Example
#Height 160
    SkBitmap alpha, bitmap;
    bitmap.allocN32Pixels(100, 100);
    SkCanvas offscreen(bitmap);
    offscreen.clear(0);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorBLUE);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(20);
    offscreen.drawCircle(50, 50, 39, paint);
    offscreen.flush();
    const SkScalar kBlurSigma = SkBlurMaskFilter::ConvertRadiusToSigma(SkIntToScalar(25));
    paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma,
                                    SkBlurMaskFilter::kHighQuality_BlurFlag));
    SkIPoint offset;
    bitmap.extractAlpha(&alpha, &paint, &offset);
    paint.setColor(SK_ColorRED);
    canvas->drawBitmap(bitmap, 0, -offset.fY, &paint);
    canvas->drawBitmap(alpha, 100 + offset.fX, 0, &paint);
##

#SeeAlso extractSubset

##

# ------------------------------------------------------------------------------

#Method bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
                      SkIPoint* offset) const

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 Mask_Filter, SkMaskFilter::filterMask 
generates Mask_Alpha from Bitmap. 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 Bitmap; (0, 0) unless SkMaskFilter generates
mask.

#Param dst  holds Pixel_Ref to fill with alpha layer ##
#Param paint  holds optional Mask_Filter; may be nullptr ##
#Param allocator   method to reserve memory for Pixel_Ref; may be nullptr ##
#Param offset  top-left position for dst; may be nullptr ##

#Return  true if Alpha layer was constructed in dst Pixel_Ref ##

#Bug 7104 ##
#Example
#Height 128
    SkBitmap alpha, bitmap;
    bitmap.allocN32Pixels(100, 100);
    SkCanvas offscreen(bitmap);
    offscreen.clear(0);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(SK_ColorBLUE);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(20);
    offscreen.drawCircle(50, 50, 39, paint);
    offscreen.flush();
    paint.setMaskFilter(SkBlurMaskFilter::Make(kOuter_SkBlurStyle, 3));
    SkIPoint offset;
    bitmap.extractAlpha(&alpha, &paint, nullptr, &offset);
    paint.setColor(SK_ColorRED);
    canvas->drawBitmap(bitmap, 0, -offset.fY, &paint);
    canvas->drawBitmap(alpha, 100 + offset.fX, 0, &paint);
##

#SeeAlso extractSubset

##

# ------------------------------------------------------------------------------

#Method bool peekPixels(SkPixmap* pixmap) const

#Line # returns Pixmap if possible ##
Copies Bitmap pixel address, row bytes, and Image_Info 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 Bitmap.

#Param pixmap  storage for pixel state if pixels are readable; otherwise, ignored ##

#Return true if Bitmap has direct access to pixels ##

#Example
    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::MakeN32Premul(6, 11));
    SkCanvas offscreen(bitmap);
    offscreen.clear(SK_ColorWHITE);
    SkPaint paint;
    offscreen.drawString("?", 0, 10, paint);
    SkPixmap pixmap;
    if (bitmap.peekPixels(&pixmap)) {
        const SkPMColor* pixels = pixmap.addr32();
        SkPMColor pmWhite = pixels[0];
        for (int y = 0; y < bitmap.height(); ++y) {
            for (int x = 0; x < bitmap.width(); ++x) {
                SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
            }
            SkDebugf("\n");
        }
    }
    #StdOut
------
-xxx--
x---x-
----x-
---x--
--x---
--x---
------
--x---
--x---
------
    #StdOut ##
##

#SeeAlso pixmap() installPixels readPixels writePixels 

##

# ------------------------------------------------------------------------------

#Method void validate() const;

#Line # asserts if Bitmap is invalid (debug only) ##
Asserts if internal values are illegal or inconsistent. Only available if 
SK_DEBUG is defined at compile time.

#NoExample
##

#SeeAlso SkImageInfo::validate() 

##

# ------------------------------------------------------------------------------

#Method void toString(SkString* str) const;

#Line # converts Bitmap to machine readable form ##
#DefinedBy SK_TO_STRING_NONVIRT() ##

#Private
macro expands to: void toString(SkString* str) const;
##

Creates string representation of Bitmap. The representation is read by
internal debugging tools. The interface and implementation may be
suppressed by defining SK_IGNORE_TO_STRING.

#Param str  storage for string representation ##

#Example
    SkBitmap bitmap;
    int width = 6;
    int height = 11;
    bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height));
    SkString string;
    bitmap.toString(&string);
    SkString match;
    match.printf("(%d, %d)", width, height);
    int start = string.find(match.c_str());
    if (start >= 0) {
        SkString whStr(&string.c_str()[start], match.size());
        SkDebugf("bitmap dimensions %s\n", whStr.c_str());
    }
    #StdOut
    bitmap dimensions (6, 11)
    ##
##

#SeeAlso SkPaint::toString

##

#Class SkBitmap ##

#Topic Bitmap ##