namespace skiagm {
static SkBitmap make_bitmap() {
- SkBitmap bm;
-
- SkColorTable* ctable = new SkColorTable(1);
- SkPMColor* c = ctable->lockColors();
- c[0] = SkPackARGB32(0x80, 0x80, 0, 0);
- ctable->unlockColors(true);
+ const SkPMColor c[] = { SkPackARGB32(0x80, 0x80, 0, 0) };
+ SkColorTable* ctable = new SkColorTable(c, SK_ARRAY_COUNT(c));
+ SkBitmap bm;
bm.setConfig(SkBitmap::kIndex8_Config, 1, 1);
bm.allocPixels(ctable);
ctable->unref();
kLastEnum_SkAlphaType = kUnpremul_SkAlphaType
};
+static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
+ return (unsigned)at <= kOpaque_SkAlphaType;
+}
#endif
}
~SkAutoLockColors() {
if (fCTable) {
- fCTable->unlockColors(false);
+ fCTable->unlockColors();
}
}
*/
const SkPMColor* lockColors(SkColorTable* ctable) {
if (fCTable) {
- fCTable->unlockColors(false);
+ fCTable->unlockColors();
}
fCTable = ctable;
fColors = ctable ? ctable->lockColors() : NULL;
#ifndef SkColorTable_DEFINED
#define SkColorTable_DEFINED
+#include "SkAlpha.h"
#include "SkColor.h"
#include "SkFlattenable.h"
/** Makes a deep copy of colors.
*/
SkColorTable(const SkColorTable& src);
- /** Preallocates the colortable to have 'count' colors, which
- * are initially set to 0.
- */
- explicit SkColorTable(int count);
- SkColorTable(const SkPMColor colors[], int count);
+ SkColorTable(const SkPMColor colors[], int count,
+ SkAlphaType alphaType = kPremul_SkAlphaType);
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);
+ SkAlphaType alphaType() const { return (SkAlphaType)fAlphaType; }
- bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; }
- void setIsOpaque(bool isOpaque);
+ bool isOpaque() const {
+ return SkAlphaTypeIsOpaque(this->alphaType());
+ }
/** Returns the number of colors in the table.
*/
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(NULL, 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() {
+ /**
+ * Return the array of colors for reading. This must be balanced by a call
+ * to unlockColors().
+ */
+ const SkPMColor* lockColors() {
SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);)
return fColors;
}
- /** Balancing call to lockColors(). If the colors have been changed, pass true.
- */
- void unlockColors(bool changed);
+
+ /**
+ * Balancing call to lockColors().
+ */
+ void unlockColors();
/** Similar to lockColors(), lock16BitCache() returns the array of
RGB16 colors that mirror the 32bit colors. However, this function
SkPMColor* fColors;
uint16_t* f16BitCache;
uint16_t fCount;
- uint8_t fFlags;
+ uint8_t fAlphaType;
SkDEBUGCODE(int fColorLockCount;)
SkDEBUGCODE(int f16BitCacheLockCount;)
#include "SkView.h"
static SkBitmap make_bitmap() {
- SkBitmap bm;
- SkColorTable* ctable = new SkColorTable(256);
-
- SkPMColor* c = ctable->lockColors();
+ SkPMColor c[256];
for (int i = 0; i < 256; i++) {
c[i] = SkPackARGB32(255 - i, 0, 0, 0);
}
- ctable->unlockColors(true);
+
+ SkBitmap bm;
+ SkColorTable* ctable = new SkColorTable(c, 256);
+
bm.setConfig(SkBitmap::kIndex8_Config, 256, 256);
bm.allocPixels(ctable);
ctable->unref();
}
static SkBitmap make_bitmap() {
- SkBitmap bm;
- SkColorTable* ctable = new SkColorTable(256);
-
- SkPMColor* c = ctable->lockColors();
+ SkPMColor c[256];
for (int i = 0; i < 256; i++) {
c[i] = SkPackARGB32(0xFF, i, 0, 0);
}
- ctable->unlockColors(true);
+ SkColorTable* ctable = new SkColorTable(c, 256, kOpaque_SkAlphaType);
+
+ SkBitmap bm;
bm.setConfig(SkBitmap::kIndex8_Config, 256, 32);
bm.allocPixels(ctable);
ctable->unref();
static void setBitmapOpaque(SkBitmap* bm, bool isOpaque) {
SkAutoLockPixels alp(*bm); // needed for ctable
bm->setIsOpaque(isOpaque);
+#if 0
SkColorTable* ctable = bm->getColorTable();
if (ctable) {
- ctable->setIsOpaque(isOpaque);
+ if (ctable->isOpaque() != isOpaque) {
+ // how do we change a colortable? don't want to
+ }
}
+#endif
}
static void draw2(SkCanvas* canvas, const SkBitmap& bm) {
#include "SkUtils.h"
static SkBitmap make_bitmap() {
- SkBitmap bm;
const int N = 1;
- SkColorTable* ctable = new SkColorTable(N);
- SkPMColor* c = ctable->lockColors();
+ SkPMColor c[N];
for (int i = 0; i < N; i++) {
c[i] = SkPackARGB32(0x80, 0x80, 0, 0);
}
- ctable->unlockColors(true);
+ SkColorTable* ctable = new SkColorTable(c, N);
+
+ SkBitmap bm;
bm.setConfig(SkBitmap::kIndex8_Config, 1, 1);
bm.allocPixels(ctable);
ctable->unref();
static void setBitmapOpaque(SkBitmap* bm, bool isOpaque) {
SkAutoLockPixels alp(*bm); // needed for ctable
bm->setIsOpaque(isOpaque);
+#if 0
+ // TODO - I think we just want to not allow this anymore
SkColorTable* ctable = bm->getColorTable();
if (ctable) {
ctable->setIsOpaque(isOpaque);
}
+#endif
}
virtual void onDrawContent(SkCanvas* canvas) {
return (fFlags & kImageIsOpaque_Flag) != 0;
case kIndex8_Config: {
- uint32_t flags = 0;
+ bool isOpaque;
this->lockPixels();
- // if lockPixels failed, we may not have a ctable ptr
- if (fColorTable) {
- flags = fColorTable->getFlags();
- }
+ isOpaque = fColorTable && fColorTable->isOpaque();
this->unlockPixels();
-
- return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0;
+ return isOpaque;
}
case kRGB_565_Config:
s += rb;
alpha += alphaRowBytes;
}
- ct->unlockColors(false);
+ ct->unlockColors();
}
} else { // src is opaque, so just fill alpha[] with 0xFF
memset(alpha, 0xFF, h * alphaRowBytes);
#define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
#define RETURNDST(src) table[src]
#define SRC_TO_FILTER(src) table[src]
-#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false)
+#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors()
#include "SkBitmapProcState_sample.h"
#undef FILTER_PROC
const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
#define RETURNDST(src) SkAlphaMulQ(table[src], alphaScale)
#define SRC_TO_FILTER(src) table[src]
-#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false)
+#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors()
#include "SkBitmapProcState_sample.h"
// SRC == 4444
#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config)
#define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
#define SRC_TO_FILTER(src) table[src]
-#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false)
+#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors()
#include "SkBitmapProcState_shaderproc.h"
#undef NAME_WRAP
SK_DEFINE_INST_COUNT(SkColorTable)
-SkColorTable::SkColorTable(int count)
- : f16BitCache(NULL), fFlags(0)
-{
- if (count < 0)
- count = 0;
- else if (count > 256)
- count = 256;
-
- fCount = SkToU16(count);
- fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
- memset(fColors, 0, count * sizeof(SkPMColor));
-
- SkDEBUGCODE(fColorLockCount = 0;)
- SkDEBUGCODE(f16BitCacheLockCount = 0;)
-}
-
// As copy constructor is hidden in the class hierarchy, we need to call
// default constructor explicitly to suppress a compiler warning.
SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
f16BitCache = NULL;
- fFlags = src.fFlags;
+ fAlphaType = src.fAlphaType;
int count = src.count();
fCount = SkToU16(count);
fColors = reinterpret_cast<SkPMColor*>(
SkDEBUGCODE(f16BitCacheLockCount = 0;)
}
-SkColorTable::SkColorTable(const SkPMColor colors[], int count)
- : f16BitCache(NULL), fFlags(0)
+SkColorTable::SkColorTable(const SkPMColor colors[], int count, SkAlphaType at)
+ : f16BitCache(NULL), fAlphaType(SkToU8(at))
{
- if (count < 0)
+ SkASSERT(0 == count || NULL != colors);
+
+ if (count < 0) {
count = 0;
- else if (count > 256)
+ } else if (count > 256) {
count = 256;
+ }
fCount = SkToU16(count);
fColors = reinterpret_cast<SkPMColor*>(
sk_malloc_throw(count * sizeof(SkPMColor)));
- if (colors)
- memcpy(fColors, colors, count * sizeof(SkPMColor));
+ memcpy(fColors, colors, count * sizeof(SkPMColor));
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
sk_free(f16BitCache);
}
-void SkColorTable::setFlags(unsigned flags)
-{
- fFlags = SkToU8(flags);
-}
-
-void SkColorTable::unlockColors(bool changed)
-{
+void SkColorTable::unlockColors() {
SkASSERT(fColorLockCount != 0);
SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
- if (changed)
- this->inval16BitCache();
-}
-
-void SkColorTable::inval16BitCache()
-{
- SkASSERT(f16BitCacheLockCount == 0);
- if (f16BitCache)
- {
- sk_free(f16BitCache);
- f16BitCache = NULL;
- }
}
#include "SkColorPriv.h"
-static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
-{
- while (--count >= 0)
+static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[],
+ int count) {
+ while (--count >= 0) {
*dst++ = SkPixel32ToPixel16_ToU16(*src++);
+ }
}
-const uint16_t* SkColorTable::lock16BitCache()
-{
- if (fFlags & kColorsAreOpaque_Flag)
- {
- if (f16BitCache == NULL) // build the cache
- {
- f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
- build_16bitcache(f16BitCache, fColors, fCount);
- }
- }
- else // our colors have alpha, so no cache
- {
- this->inval16BitCache();
- if (f16BitCache)
- {
- sk_free(f16BitCache);
- f16BitCache = NULL;
- }
+const uint16_t* SkColorTable::lock16BitCache() {
+ if (this->isOpaque() && NULL == f16BitCache) {
+ f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
+ build_16bitcache(f16BitCache, fColors, fCount);
}
SkDEBUGCODE(f16BitCacheLockCount += 1);
return f16BitCache;
}
-void SkColorTable::setIsOpaque(bool isOpaque) {
- if (isOpaque) {
- fFlags |= kColorsAreOpaque_Flag;
- } else {
- fFlags &= ~kColorsAreOpaque_Flag;
- }
-}
-
///////////////////////////////////////////////////////////////////////////////
SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
- fFlags = buffer.readUInt();
+ fAlphaType = SkToU8(buffer.readUInt());
fCount = buffer.getArrayCount();
fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors);
}
void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
- buffer.writeUInt(fFlags);
+ buffer.writeUInt(fAlphaType);
buffer.writeColorArray(fColors, fCount);
}
}
if fSource.getColorTable())
- fSource.getColorTable()->unlockColors(false);
+ fSource.getColorTable()->unlockColors();
}
private:
#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src])
#define SkSPRITE_NEXT_ROW
-#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false)
+#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors()
#include "SkSpriteBlitterTemplate.h"
#define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Blend
#define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
#define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
#define SkSPRITE_NEXT_ROW
-#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false);
+#define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors();
#include "SkSpriteBlitterTemplate.h"
///////////////////////////////////////////////////////////////////////////////
char* dst = (char*)buffer;
memcpy(dst, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
- ctable->unlockColors(false);
+ ctable->unlockColors();
// always skip a full 256 number of entries, even if we memcpy'd fewer
dst += kGrColorTableSize;
if (NULL == cmap) {
return error_return(gif, *bm, "null cmap");
}
-
colorCount = cmap->ColorCount;
- SkAutoTMalloc<SkPMColor> colorStorage(colorCount);
- SkPMColor* colorPtr = colorStorage.get();
+ if (colorCount > 256) {
+ colorCount = 256; // our kIndex8 can't support more
+ }
+
+ SkPMColor colorPtr[256]; // storage for worst-case
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
for (int index = 0; index < colorCount; index++) {
colorPtr[index] = SkPackARGB32(0xFF,
cmap->Colors[index].Red,
bool reallyHasAlpha = transpIndex >= 0;
if (reallyHasAlpha) {
colorPtr[transpIndex] = SK_ColorTRANSPARENT; // ram in a transparent SkPMColor
+ alphaType = kPremul_SkAlphaType;
}
- SkAutoTUnref<SkColorTable> ctable(SkNEW_ARGS(SkColorTable, (colorPtr, colorCount)));
- ctable->setIsOpaque(!reallyHasAlpha);
+ SkAutoTUnref<SkColorTable> ctable(SkNEW_ARGS(SkColorTable,
+ (colorPtr, colorCount,
+ alphaType)));
if (!this->allocPixelRef(bm, ctable)) {
return error_return(gif, *bm, "allocPixelRef");
}
png_colorp palette;
png_bytep trans;
int numTrans;
- bool reallyHasAlpha = false;
- SkColorTable* colorTable = NULL;
png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette);
the colortable by 1 (if its < 256) and duplicate the last color into that slot.
*/
int colorCount = numPalette + (numPalette < 256);
+ SkPMColor colorStorage[256]; // worst-case storage
+ SkPMColor* colorPtr = colorStorage;
- colorTable = SkNEW_ARGS(SkColorTable, (colorCount));
-
- SkPMColor* colorPtr = colorTable->lockColors();
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL);
*hasAlphap = (numTrans > 0);
} else {
numTrans = 0;
- colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
}
+
// check for bad images that might make us crash
if (numTrans > numPalette) {
numTrans = numPalette;
*colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue);
palette++;
}
- reallyHasAlpha |= (transLessThanFF < 0);
+ bool reallyHasAlpha = (transLessThanFF < 0);
for (; index < numPalette; index++) {
*colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
if (numPalette < 256) {
*colorPtr = colorPtr[-1];
}
- colorTable->unlockColors(true);
- *colorTablep = colorTable;
+
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
+ if (reallyHasAlpha) {
+ if (this->getRequireUnpremultipliedColors()) {
+ alphaType = kUnpremul_SkAlphaType;
+ } else {
+ alphaType = kPremul_SkAlphaType;
+ }
+ }
+
+ *colorTablep = SkNEW_ARGS(SkColorTable,
+ (colorStorage, colorCount, alphaType));
*reallyHasAlphap = reallyHasAlpha;
return true;
}
);
}
- s.fBitmap->getColorTable()->unlockColors(false);
+ s.fBitmap->getColorTable()->unlockColors();
}
#endif // SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)