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 "SkReadBuffer.h"
12#include "SkWriteBuffer.h"
13#include "SkStream.h"
14#include "SkTemplates.h"
15
16// As copy constructor is hidden in the class hierarchy, we need to call
17// default constructor explicitly to suppress a compiler warning.
18SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
19    f16BitCache = NULL;
20    fAlphaType = src.fAlphaType;
21    int count = src.count();
22    fCount = SkToU16(count);
23    fColors = reinterpret_cast<SkPMColor*>(
24                                    sk_malloc_throw(count * sizeof(SkPMColor)));
25    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
26
27    SkDEBUGCODE(fColorLockCount = 0;)
28    SkDEBUGCODE(f16BitCacheLockCount = 0;)
29}
30
31SkColorTable::SkColorTable(const SkPMColor colors[], int count, SkAlphaType at)
32    : f16BitCache(NULL), fAlphaType(SkToU8(at))
33{
34    SkASSERT(0 == count || colors);
35
36    if (count < 0) {
37        count = 0;
38    } else if (count > 256) {
39        count = 256;
40    }
41
42    fCount = SkToU16(count);
43    fColors = reinterpret_cast<SkPMColor*>(
44                                    sk_malloc_throw(count * sizeof(SkPMColor)));
45
46    memcpy(fColors, colors, count * sizeof(SkPMColor));
47
48    SkDEBUGCODE(fColorLockCount = 0;)
49    SkDEBUGCODE(f16BitCacheLockCount = 0;)
50}
51
52SkColorTable::~SkColorTable()
53{
54    SkASSERT(fColorLockCount == 0);
55    SkASSERT(f16BitCacheLockCount == 0);
56
57    sk_free(fColors);
58    sk_free(f16BitCache);
59}
60
61void SkColorTable::unlockColors() {
62    SkASSERT(fColorLockCount != 0);
63    SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
64}
65
66#include "SkColorPriv.h"
67
68static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[],
69                                    int count) {
70    while (--count >= 0) {
71        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
72    }
73}
74
75const uint16_t* SkColorTable::lock16BitCache() {
76    if (this->isOpaque() && NULL == f16BitCache) {
77        f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
78        build_16bitcache(f16BitCache, fColors, fCount);
79    }
80
81    SkDEBUGCODE(f16BitCacheLockCount += 1);
82    return f16BitCache;
83}
84
85///////////////////////////////////////////////////////////////////////////////
86
87SkColorTable::SkColorTable(SkReadBuffer& buffer) {
88    f16BitCache = NULL;
89    SkDEBUGCODE(fColorLockCount = 0;)
90    SkDEBUGCODE(f16BitCacheLockCount = 0;)
91
92    fAlphaType = SkToU8(buffer.readUInt());
93    fCount = buffer.getArrayCount();
94    size_t allocSize = fCount * sizeof(SkPMColor);
95    SkDEBUGCODE(bool success = false;)
96    if (buffer.validateAvailable(allocSize)) {
97        fColors = (SkPMColor*)sk_malloc_throw(allocSize);
98        SkDEBUGCODE(success =) buffer.readColorArray(fColors, fCount);
99    } else {
100        fCount = 0;
101        fColors = NULL;
102    }
103#ifdef SK_DEBUG
104    SkASSERT((unsigned)fCount <= 256);
105    SkASSERT(success);
106#endif
107}
108
109void SkColorTable::writeToBuffer(SkWriteBuffer& buffer) const {
110    buffer.writeUInt(fAlphaType);
111    buffer.writeColorArray(fColors, fCount);
112}
113