1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkPixelRef_DEFINED
18#define SkPixelRef_DEFINED
19
20#include "SkRefCnt.h"
21#include "SkString.h"
22
23class SkColorTable;
24class SkMutex;
25class SkFlattenableReadBuffer;
26class SkFlattenableWriteBuffer;
27
28/** \class SkPixelRef
29
30    This class is the smart container for pixel memory, and is used with
31    SkBitmap. A pixelref is installed into a bitmap, and then the bitmap can
32    access the actual pixel memory by calling lockPixels/unlockPixels.
33
34    This class can be shared/accessed between multiple threads.
35*/
36class SkPixelRef : public SkRefCnt {
37public:
38    explicit SkPixelRef(SkMutex* mutex = NULL);
39
40    /** Return the pixel memory returned from lockPixels, or null if the
41        lockCount is 0.
42    */
43    void* pixels() const { return fPixels; }
44
45    /** Return the current colorTable (if any) if pixels are locked, or null.
46    */
47    SkColorTable* colorTable() const { return fColorTable; }
48
49    /** Return the current lockcount (defaults to 0)
50    */
51    int getLockCount() const { return fLockCount; }
52
53    /** Call to access the pixel memory, which is returned. Balance with a call
54        to unlockPixels().
55    */
56    void lockPixels();
57    /** Call to balanace a previous call to lockPixels(). Returns the pixels
58        (or null) after the unlock. NOTE: lock calls can be nested, but the
59        matching number of unlock calls must be made in order to free the
60        memory (if the subclass implements caching/deferred-decoding.)
61    */
62    void unlockPixels();
63
64    /** Returns a non-zero, unique value corresponding to the pixels in this
65        pixelref. Each time the pixels are changed (and notifyPixelsChanged is
66        called), a different generation ID will be returned.
67    */
68    uint32_t getGenerationID() const;
69
70    /** Call this if you have changed the contents of the pixels. This will in-
71        turn cause a different generation ID value to be returned from
72        getGenerationID().
73    */
74    void notifyPixelsChanged();
75
76    /** Returns true if this pixelref is marked as immutable, meaning that the
77        contents of its pixels will not change for the lifetime of the pixelref.
78    */
79    bool isImmutable() const { return fIsImmutable; }
80
81    /** Marks this pixelref is immutable, meaning that the contents of its
82        pixels will not change for the lifetime of the pixelref. This state can
83        be set on a pixelref, but it cannot be cleared once it is set.
84    */
85    void setImmutable();
86
87    /** Return the optional URI string associated with this pixelref. May be
88        null.
89    */
90    const char* getURI() const { return fURI.size() ? fURI.c_str() : NULL; }
91
92    /** Copy a URI string to this pixelref, or clear the URI if the uri is null
93     */
94    void setURI(const char uri[]) {
95        fURI.set(uri);
96    }
97
98    /** Copy a URI string to this pixelref
99     */
100    void setURI(const char uri[], size_t len) {
101        fURI.set(uri, len);
102    }
103
104    /** Assign a URI string to this pixelref.
105    */
106    void setURI(const SkString& uri) { fURI = uri; }
107
108    // serialization
109
110    typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&);
111
112    virtual Factory getFactory() const { return NULL; }
113    virtual void flatten(SkFlattenableWriteBuffer&) const;
114
115    static Factory NameToFactory(const char name[]);
116    static const char* FactoryToName(Factory);
117    static void Register(const char name[], Factory);
118
119    class Registrar {
120    public:
121        Registrar(const char name[], Factory factory) {
122            SkPixelRef::Register(name, factory);
123        }
124    };
125
126protected:
127    /** Called when the lockCount goes from 0 to 1. The caller will have already
128        acquire a mutex for thread safety, so this method need not do that.
129    */
130    virtual void* onLockPixels(SkColorTable**) = 0;
131    /** Called when the lock count goes from 1 to 0. The caller will have
132        already acquire a mutex for thread safety, so this method need not do
133        that.
134    */
135    virtual void onUnlockPixels() = 0;
136
137    /** Return the mutex associated with this pixelref. This value is assigned
138        in the constructor, and cannot change during the lifetime of the object.
139    */
140    SkMutex* mutex() const { return fMutex; }
141
142    SkPixelRef(SkFlattenableReadBuffer&, SkMutex*);
143
144private:
145    SkMutex*        fMutex; // must remain in scope for the life of this object
146    void*           fPixels;
147    SkColorTable*   fColorTable;    // we do not track ownership, subclass does
148    int             fLockCount;
149
150    mutable uint32_t fGenerationID;
151
152    SkString    fURI;
153
154    // can go from false to true, but never from true to false
155    bool    fIsImmutable;
156};
157
158#endif
159