blob: 2b69f2bc3265ccfbdb76b51cf652cd03843b402a [file] [log] [blame]
/* include/graphics/SkBitmap.h
**
** Copyright 2006, Google Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef SkBitmap_DEFINED
#define SkBitmap_DEFINED
#include "SkColor.h"
#include "SkRefCnt.h"
// Android - we need to run as an embedded product, not X11
//#ifdef SK_BUILD_FOR_UNIX
//#include <X11/Xlib.h>
//#endif
class SkColorTable;
/** \class SkBitmap
The SkBitmap class specifies a raster bitmap. A bitmap has an integer width
and height, and a format (config), and a pointer to the actual pixels.
Bitmaps can be drawn into a SkCanvas, but they are also used to specify the target
of a SkCanvas' drawing operations.
*/
class SkBitmap {
public:
enum Config {
kNo_Config, //!< bitmap has not been configured
kA1_Config, //!< 1-bit per pixel, (0 is transparent, 1 is opaque)
kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors
kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
kARGB_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing)
kConfigCount
};
/** Default construct creates a bitmap with zero width and height, and no pixels.
Its config is set to kNo_Config.
*/
SkBitmap();
/** Constructor initializes the new bitmap by copying the src bitmap. All fields are copied,
but ownership of the pixels remains with the src bitmap.
*/
// This method is not exported to java.
SkBitmap(const SkBitmap& src);
/** Destructor that, if getOwnsPixels() returns true, will delete the pixel's memory.
*/
~SkBitmap();
/** Copies the src bitmap into this bitmap. Ownership of the src bitmap's pixels remains
with the src bitmap.
*/
SkBitmap& operator=(const SkBitmap& src);
/** Swap the fields of the two bitmaps. This routine is guaranteed to never fail or throw.
*/
// This method is not exported to java.
void swap(SkBitmap& other);
/** Return the config for the bitmap.
*/
Config getConfig() const { return (Config)fConfig; }
/** Return the bitmap's width, in pixels.
*/
int width() const { return fWidth; }
/** Return the bitmap's height, in pixels.
*/
int height() const { return fHeight; }
/** Return the number of bytes between subsequent rows of the bitmap.
*/
int rowBytes() const { return fRowBytes; }
/** Return the address of the pixels for this SkBitmap. This can be set either with
setPixels(), where the caller owns the buffer, or with allocPixels() or resizeAlloc(),
which marks the pixel memory to be owned by the SkBitmap (e.g. will be freed automatically
when the bitmap is destroyed).
*/
void* getPixels() const { return fPixels; }
/** Return the byte size of the pixels, based on the height and rowBytes
*/
size_t getSize() const { return fHeight * fRowBytes; }
/** Returns true if the bitmap is opaque (has no translucent/transparent pixels).
*/
bool isOpaque() const;
/** Specify if this bitmap's pixels are all opaque or not. Is only meaningful for configs
that support per-pixel alpha (RGB32, A1, A8).
*/
void setIsOpaque(bool);
/** Reset the bitmap to its initial state (see default constructor). If getOwnsPixels() returned
true, then the memory for the pixels is freed.
*/
void reset();
/** Set the bitmap's config and dimensions. If rowBytes is 0, then an appropriate value
is computed based on the bitmap's config and width. If getOwnsPixels() returned true,
then the pixel's memory is freed.
*/
void setConfig(Config, U16CPU width, U16CPU height, U16CPU rowBytes = 0);
/** Use this to assign a new pixel address for an existing bitmap. If getOwnsPixels() returned
true, then the previous pixel's memory is freed. The new address is "owned" by the called,
and getOwnsPixels() will now return false. This method is not exported to java.
*/
void setPixels(void* p);
/** If this is called, then the bitmap will dynamically allocate memory for its pixels
based on rowBytes and height. The SkBitmap will remember that it allocated
this, and will automatically free it as needed, thus getOwnsPixels() will now return true.
*/
void allocPixels();
/** Realloc the memory for the pixels based on the specified width and height. This
keeps the old value for config, and computes a rowBytes based on the config and the width.
This is similar, but more efficient than calling setConfig() followed by allocPixels().
*/
// not implemented
// void resizeAlloc(U16CPU width, U16CPU height);
/** Returns true if the current pixels have been allocated via allocPixels()
or resizeAlloc(). This method is not exported to java.
*/
bool getOwnsPixels() const;
/** Call this to explicitly change the ownership rule for the pixels. This may be called
after one bitmap is copied into another, to specify which bitmap should handle freeing
the memory. This method is not exported to java.
*/
void setOwnsPixels(bool ownsPixels);
/** Get the bitmap's colortable object.
Return the bitmap's colortable (if any). Does not affect the colortable's
reference count.
*/
SkColorTable* getColorTable() const { return fColorTable; }
/** Assign ctable to be the colortable for the bitmap, replacing any existing reference.
The reference count of ctable (if it is not nil) is incremented, and any existing
reference has its reference count decremented. NOTE: colortable's may be assigned
to any bitmap, but are only interpreted for kIndex8_Config bitmaps, where they
are required.
@return the ctable argument
*/
SkColorTable* setColorTable(SkColorTable* ctable);
/** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format
for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is ignored.
If the config is kA8_Config, then the r,g,b parameters are ignored.
*/
void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
/** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format
for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is presumed
to be 0xFF. If the config is kA8_Config, then the r,g,b parameters are ignored and the
pixels are all set to 0xFF.
*/
void eraseRGB(U8CPU r, U8CPU g, U8CPU b)
{
this->eraseARGB(0xFF, r, g, b);
}
/** Initialize the bitmap's pixels with the specified color, automatically converting into the correct format
for the bitmap's config. If the config is kRGB_565_Config, then the color's alpha value is presumed
to be 0xFF. If the config is kA8_Config, then only the color's alpha value is used.
*/
void eraseColor(SkColor c)
{
this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
}
/** Return a bitmap that is a quarter the size of this one
*/
bool quarterSizeFiltered(SkBitmap* dst) const;
/** Returns the address of the pixel specified by x,y.
Asserts that x,y are in range, and that the bitmap's config is either kARGB_8888_Config.
*/
// This method is not exported to java.
inline uint32_t* getAddr32(int x, int y) const;
/** Returns the address of the pixel specified by x,y.
Asserts that x,y are in range, and that the bitmap's config is kRGB_565_Config.
*/
// This method is not exported to java.
inline uint16_t* getAddr16(int x, int y) const;
/** Returns the address of the pixel specified by x,y.
Asserts that x,y are in range, and that the bitmap's config is either kA8_Config or kIndex8_Config.
*/
// This method is not exported to java.
inline uint8_t* getAddr8(int x, int y) const;
/** Returns the color corresponding to the pixel specified by x,y.
Asserts that x,y are in range, and that the bitmap's config is kIndex8_Config.
*/
// This method is not exported to java.
inline SkPMColor getIndex8Color(int x, int y) const;
/** Returns the address of the byte containing the pixel specified by x,y.
Asserts that x,y are in range, and that the bitmap's config is kA1_Config.
*/
// This method is not exported to java.
inline uint8_t* getAddr1(int x, int y) const;
// OS-specific helpers
#ifndef SK_USE_WXWIDGETS
#ifdef SK_BUILD_FOR_WIN
/** On Windows and PocketPC builds, this will draw the SkBitmap onto the
specified HDC
*/
void drawToHDC(HDC, int left, int top) const;
#elif defined(SK_BUILD_FOR_MAC)
/** On Mac OS X and Carbon builds, this will draw the SkBitmap onto the
specified WindowRef
*/
void drawToPort(WindowRef) const;
#endif
#endif
void buildMipMap(bool forceRebuild);
unsigned countMipLevels() const;
private:
SkColorTable* fColorTable; // only meaningful for kIndex8
#ifdef SK_SUPPORT_MIPMAP
struct MipLevel {
void* fPixels;
uint16_t fWidth, fHeight, fRowBytes;
uint8_t fConfig, fShift;
};
enum {
kMaxMipLevels = 5
};
struct MipMap {
MipLevel fLevel[kMaxMipLevels];
};
MipMap* fMipMap;
#endif
enum Flags {
kWeOwnThePixels_Flag = 0x01,
kWeOwnTheMipMap_Flag = 0x02,
kImageIsOpaque_Flag = 0x04
};
void* fPixels;
uint16_t fWidth, fHeight, fRowBytes;
uint8_t fConfig;
uint8_t fFlags;
#ifdef SK_SUPPORT_MIPMAP
const MipLevel* getMipLevel(unsigned level) const;
#endif
void freePixels();
friend class SkBitmapShader;
};
/** \class SkColorTable
SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by
8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable.
*/
class SkColorTable : public SkRefCnt {
public:
/** Constructs an empty color table (zero colors).
*/
SkColorTable();
virtual ~SkColorTable();
enum Flags {
kColorsAreOpaque_Flag = 0x01 //!< if set, all of the colors in the table are opaque (alpha==0xFF)
};
/** Returns the flag bits for the color table. These can be changed with setFlags().
*/
unsigned getFlags() const { return fFlags; }
/** Set the flags for the color table. See the Flags enum for possible values.
*/
void setFlags(unsigned flags);
/** Returns the number of colors in the table.
*/
int count() const { return fCount; }
/** Returns the specified color from the table. In the debug build, this asserts that
the index is in range (0 <= index < count).
*/
SkPMColor operator[](int index) const
{
SkASSERT(fColors != nil && (unsigned)index < fCount);
return fColors[index];
}
/** Specify the number of colors in the color table. This does not initialize the colors
to any value, just allocates memory for them. To initialize the values, either call
setColors(array, count), or follow setCount(count) with a call to
lockColors()/{set the values}/unlockColors(true).
*/
void setColors(int count) { this->setColors(nil, count); }
void setColors(const SkPMColor[], int count);
/** Return the array of colors for reading and/or writing. This must be
balanced by a call to unlockColors(changed?), telling the colortable if
the colors were changed during the lock.
*/
SkPMColor* lockColors()
{
SkDEBUGCODE(fColorLockCount += 1;)
return fColors;
}
/** Balancing call to lockColors(). If the colors have been changed, pass true.
*/
void unlockColors(bool changed)
{
SkASSERT(fColorLockCount != 0);
SkDEBUGCODE(fColorLockCount -= 1;)
}
/** Similar to lockColors(), lock16BitCache() returns the array of
RGB16 colors that mirror the 32bit colors. However, this function
will return nil if kColorsAreOpaque_Flag is not set.
Also, unlike lockColors(), the returned array here cannot be modified.
*/
const uint16_t* lock16BitCache();
/** Balancing call to lock16BitCache().
*/
void unlock16BitCache()
{
SkASSERT(f16BitCacheLockCount > 0);
SkDEBUGCODE(f16BitCacheLockCount -= 1);
}
private:
SkPMColor* fColors;
uint16_t* f16BitCache;
uint16_t fCount;
uint8_t fFlags;
SkDEBUGCODE(int fColorLockCount;)
SkDEBUGCODE(int f16BitCacheLockCount;)
void inval16BitCache();
};
//////////////////////////////////////////////////////////////////////////////////
inline uint32_t* SkBitmap::getAddr32(int x, int y) const
{
SkASSERT(fPixels);
SkASSERT(fConfig == kARGB_8888_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
}
inline uint16_t* SkBitmap::getAddr16(int x, int y) const
{
SkASSERT(fPixels);
SkASSERT(fConfig == kRGB_565_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
}
inline uint8_t* SkBitmap::getAddr8(int x, int y) const
{
SkASSERT(fPixels);
SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint8_t*)fPixels + y * fRowBytes + x;
}
inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const
{
SkASSERT(fPixels);
SkASSERT(fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
SkASSERT(fColorTable);
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}
// returns the address of the byte that contains the x coordinate
inline uint8_t* SkBitmap::getAddr1(int x, int y) const
{
SkASSERT(fPixels);
SkASSERT(fConfig == kA1_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
}
#endif