Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2009 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkBitmap.h"
     11 #include "SkFlattenable.h"
     12 #include "SkStream.h"
     13 #include "SkTemplates.h"
     14 
     15 SkColorTable::SkColorTable(int count)
     16     : f16BitCache(NULL), fFlags(0)
     17 {
     18     if (count < 0)
     19         count = 0;
     20     else if (count > 256)
     21         count = 256;
     22 
     23     fCount = SkToU16(count);
     24     fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
     25     memset(fColors, 0, count * sizeof(SkPMColor));
     26 
     27     SkDEBUGCODE(fColorLockCount = 0;)
     28     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     29 }
     30 
     31 // call SkRefCnt's constructor explicitly, to avoid warning
     32 SkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() {
     33     f16BitCache = NULL;
     34     fFlags = src.fFlags;
     35     int count = src.count();
     36     fCount = SkToU16(count);
     37     fColors = reinterpret_cast<SkPMColor*>(
     38                                     sk_malloc_throw(count * sizeof(SkPMColor)));
     39     memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
     40 
     41     SkDEBUGCODE(fColorLockCount = 0;)
     42     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     43 }
     44 
     45 SkColorTable::SkColorTable(const SkPMColor colors[], int count)
     46     : f16BitCache(NULL), fFlags(0)
     47 {
     48     if (count < 0)
     49         count = 0;
     50     else if (count > 256)
     51         count = 256;
     52 
     53     fCount = SkToU16(count);
     54     fColors = reinterpret_cast<SkPMColor*>(
     55                                     sk_malloc_throw(count * sizeof(SkPMColor)));
     56 
     57     if (colors)
     58         memcpy(fColors, colors, count * sizeof(SkPMColor));
     59 
     60     SkDEBUGCODE(fColorLockCount = 0;)
     61     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     62 }
     63 
     64 SkColorTable::~SkColorTable()
     65 {
     66     SkASSERT(fColorLockCount == 0);
     67     SkASSERT(f16BitCacheLockCount == 0);
     68 
     69     sk_free(fColors);
     70     sk_free(f16BitCache);
     71 }
     72 
     73 void SkColorTable::setFlags(unsigned flags)
     74 {
     75     fFlags = SkToU8(flags);
     76 }
     77 
     78 void SkColorTable::unlockColors(bool changed)
     79 {
     80     SkASSERT(fColorLockCount != 0);
     81     SkDEBUGCODE(fColorLockCount -= 1;)
     82     if (changed)
     83         this->inval16BitCache();
     84 }
     85 
     86 void SkColorTable::inval16BitCache()
     87 {
     88     SkASSERT(f16BitCacheLockCount == 0);
     89     if (f16BitCache)
     90     {
     91         sk_free(f16BitCache);
     92         f16BitCache = NULL;
     93     }
     94 }
     95 
     96 #include "SkColorPriv.h"
     97 
     98 static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
     99 {
    100     while (--count >= 0)
    101         *dst++ = SkPixel32ToPixel16_ToU16(*src++);
    102 }
    103 
    104 const uint16_t* SkColorTable::lock16BitCache()
    105 {
    106     if (fFlags & kColorsAreOpaque_Flag)
    107     {
    108         if (f16BitCache == NULL) // build the cache
    109         {
    110             f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
    111             build_16bitcache(f16BitCache, fColors, fCount);
    112         }
    113     }
    114     else    // our colors have alpha, so no cache
    115     {
    116         this->inval16BitCache();
    117         if (f16BitCache)
    118         {
    119             sk_free(f16BitCache);
    120             f16BitCache = NULL;
    121         }
    122     }
    123 
    124     SkDEBUGCODE(f16BitCacheLockCount += 1);
    125     return f16BitCache;
    126 }
    127 
    128 void SkColorTable::setIsOpaque(bool isOpaque) {
    129     if (isOpaque) {
    130         fFlags |= kColorsAreOpaque_Flag;
    131     } else {
    132         fFlags &= ~kColorsAreOpaque_Flag;
    133     }
    134 }
    135 
    136 ///////////////////////////////////////////////////////////////////////////////
    137 
    138 SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
    139     f16BitCache = NULL;
    140     SkDEBUGCODE(fColorLockCount = 0;)
    141     SkDEBUGCODE(f16BitCacheLockCount = 0;)
    142 
    143     fCount = buffer.readU16();
    144     SkASSERT((unsigned)fCount <= 256);
    145 
    146     fFlags = buffer.readU8();
    147 
    148     fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
    149     buffer.read(fColors, fCount * sizeof(SkPMColor));
    150 }
    151 
    152 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
    153     int count = this->count();
    154     buffer.write16(count);
    155     buffer.write8(this->getFlags());
    156     buffer.writeMul4(fColors, count * sizeof(SkPMColor));
    157 }
    158 
    159