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 "SkColorTable.h"
     11 #include "SkFlattenableBuffers.h"
     12 #include "SkStream.h"
     13 #include "SkTemplates.h"
     14 
     15 SK_DEFINE_INST_COUNT(SkColorTable)
     16 
     17 SkColorTable::SkColorTable(int count)
     18     : f16BitCache(NULL), fFlags(0)
     19 {
     20     if (count < 0)
     21         count = 0;
     22     else if (count > 256)
     23         count = 256;
     24 
     25     fCount = SkToU16(count);
     26     fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
     27     memset(fColors, 0, count * sizeof(SkPMColor));
     28 
     29     SkDEBUGCODE(fColorLockCount = 0;)
     30     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     31 }
     32 
     33 // As copy constructor is hidden in the class hierarchy, we need to call
     34 // default constructor explicitly to suppress a compiler warning.
     35 SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
     36     f16BitCache = NULL;
     37     fFlags = src.fFlags;
     38     int count = src.count();
     39     fCount = SkToU16(count);
     40     fColors = reinterpret_cast<SkPMColor*>(
     41                                     sk_malloc_throw(count * sizeof(SkPMColor)));
     42     memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
     43 
     44     SkDEBUGCODE(fColorLockCount = 0;)
     45     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     46 }
     47 
     48 SkColorTable::SkColorTable(const SkPMColor colors[], int count)
     49     : f16BitCache(NULL), fFlags(0)
     50 {
     51     if (count < 0)
     52         count = 0;
     53     else if (count > 256)
     54         count = 256;
     55 
     56     fCount = SkToU16(count);
     57     fColors = reinterpret_cast<SkPMColor*>(
     58                                     sk_malloc_throw(count * sizeof(SkPMColor)));
     59 
     60     if (colors)
     61         memcpy(fColors, colors, count * sizeof(SkPMColor));
     62 
     63     SkDEBUGCODE(fColorLockCount = 0;)
     64     SkDEBUGCODE(f16BitCacheLockCount = 0;)
     65 }
     66 
     67 SkColorTable::~SkColorTable()
     68 {
     69     SkASSERT(fColorLockCount == 0);
     70     SkASSERT(f16BitCacheLockCount == 0);
     71 
     72     sk_free(fColors);
     73     sk_free(f16BitCache);
     74 }
     75 
     76 void SkColorTable::setFlags(unsigned flags)
     77 {
     78     fFlags = SkToU8(flags);
     79 }
     80 
     81 void SkColorTable::unlockColors(bool changed)
     82 {
     83     SkASSERT(fColorLockCount != 0);
     84     SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
     85     if (changed)
     86         this->inval16BitCache();
     87 }
     88 
     89 void SkColorTable::inval16BitCache()
     90 {
     91     SkASSERT(f16BitCacheLockCount == 0);
     92     if (f16BitCache)
     93     {
     94         sk_free(f16BitCache);
     95         f16BitCache = NULL;
     96     }
     97 }
     98 
     99 #include "SkColorPriv.h"
    100 
    101 static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
    102 {
    103     while (--count >= 0)
    104         *dst++ = SkPixel32ToPixel16_ToU16(*src++);
    105 }
    106 
    107 const uint16_t* SkColorTable::lock16BitCache()
    108 {
    109     if (fFlags & kColorsAreOpaque_Flag)
    110     {
    111         if (f16BitCache == NULL) // build the cache
    112         {
    113             f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
    114             build_16bitcache(f16BitCache, fColors, fCount);
    115         }
    116     }
    117     else    // our colors have alpha, so no cache
    118     {
    119         this->inval16BitCache();
    120         if (f16BitCache)
    121         {
    122             sk_free(f16BitCache);
    123             f16BitCache = NULL;
    124         }
    125     }
    126 
    127     SkDEBUGCODE(f16BitCacheLockCount += 1);
    128     return f16BitCache;
    129 }
    130 
    131 void SkColorTable::setIsOpaque(bool isOpaque) {
    132     if (isOpaque) {
    133         fFlags |= kColorsAreOpaque_Flag;
    134     } else {
    135         fFlags &= ~kColorsAreOpaque_Flag;
    136     }
    137 }
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 
    141 SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
    142     f16BitCache = NULL;
    143     SkDEBUGCODE(fColorLockCount = 0;)
    144     SkDEBUGCODE(f16BitCacheLockCount = 0;)
    145 
    146     fFlags = buffer.readUInt();
    147     fCount = buffer.getArrayCount();
    148     fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
    149     SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors);
    150 #ifdef SK_DEBUG
    151     SkASSERT((unsigned)fCount <= 256);
    152     SkASSERT(countRead == fCount);
    153 #endif
    154 }
    155 
    156 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
    157     buffer.writeUInt(fFlags);
    158     buffer.writeColorArray(fColors, fCount);
    159 }
    160