SkPictureRecord.h revision d9ea09e1f29b303e6fa36079e99729d2951925b9
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkPictureRecord_DEFINED
9#define SkPictureRecord_DEFINED
10
11#include "SkCanvas.h"
12#include "SkFlattenable.h"
13#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
14#include "SkMatrixClipStateMgr.h"
15#endif
16#include "SkPathHeap.h"
17#include "SkPicture.h"
18#include "SkPictureFlat.h"
19#include "SkTemplates.h"
20#include "SkWriter32.h"
21
22class SkBBoxHierarchy;
23class SkOffsetTable;
24class SkPictureStateTree;
25
26// These macros help with packing and unpacking a single byte value and
27// a 3 byte value into/out of a uint32_t
28#define MASK_24 0x00FFFFFF
29#define UNPACK_8_24(combined, small, large)             \
30    small = (combined >> 24) & 0xFF;                    \
31    large = combined & MASK_24;
32#define PACK_8_24(small, large) ((small << 24) | large)
33
34
35class SkPictureRecord : public SkCanvas {
36public:
37    SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
38    virtual ~SkPictureRecord();
39
40    virtual void clear(SkColor) SK_OVERRIDE;
41    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
42    virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
43                            const SkPaint&) SK_OVERRIDE;
44    virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE;
45    virtual void drawRect(const SkRect&, const SkPaint&) SK_OVERRIDE;
46    virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE;
47    virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
48    virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
49                            const SkPaint*) SK_OVERRIDE;
50    virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src,
51                                      const SkRect& dst, const SkPaint* paint,
52                                      DrawBitmapRectFlags flags) SK_OVERRIDE;
53    virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
54                                  const SkPaint*) SK_OVERRIDE;
55    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
56                                const SkRect& dst, const SkPaint*) SK_OVERRIDE;
57    virtual void drawSprite(const SkBitmap&, int left, int top,
58                            const SkPaint*) SK_OVERRIDE;
59    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
60                          SkScalar y, const SkPaint&) SK_OVERRIDE;
61    virtual void drawPosText(const void* text, size_t byteLength,
62                             const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
63    virtual void drawPosTextH(const void* text, size_t byteLength,
64                      const SkScalar xpos[], SkScalar constY, const SkPaint&) SK_OVERRIDE;
65    virtual void drawTextOnPath(const void* text, size_t byteLength,
66                            const SkPath& path, const SkMatrix* matrix,
67                                const SkPaint&) SK_OVERRIDE;
68    virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
69    virtual void drawVertices(VertexMode, int vertexCount,
70                          const SkPoint vertices[], const SkPoint texs[],
71                          const SkColor colors[], SkXfermode*,
72                          const uint16_t indices[], int indexCount,
73                              const SkPaint&) SK_OVERRIDE;
74    virtual void drawData(const void*, size_t) SK_OVERRIDE;
75    virtual void beginCommentGroup(const char* description) SK_OVERRIDE;
76    virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE;
77    virtual void endCommentGroup() SK_OVERRIDE;
78    virtual bool isDrawingToLayer() const SK_OVERRIDE;
79
80    void addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData&,
81                                 SkScalar minY, SkScalar maxY);
82
83    const SkTDArray<SkPicture* >& getPictureRefs() const {
84        return fPictureRefs;
85    }
86
87    void setFlags(uint32_t recordFlags) {
88        fRecordFlags = recordFlags;
89    }
90
91    const SkWriter32& writeStream() const {
92        return fWriter;
93    }
94
95    void beginRecording();
96    void endRecording();
97
98    void internalOnly_EnableOpts(bool optsEnabled) {
99        fOptsEnabled = optsEnabled;
100    }
101
102private:
103    void handleOptimization(int opt);
104    int recordRestoreOffsetPlaceholder(SkRegion::Op);
105    void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset);
106
107#ifndef SK_COLLAPSE_MATRIX_CLIP_STATE
108    SkTDArray<int32_t> fRestoreOffsetStack;
109    int fFirstSavedLayerIndex;
110    enum {
111        kNoSavedLayerIndex = -1
112    };
113#endif
114
115    SkTDArray<uint32_t> fCullOffsetStack;
116
117    /*
118     * Write the 'drawType' operation and chunk size to the skp. 'size'
119     * can potentially be increased if the chunk size needs its own storage
120     * location (i.e., it overflows 24 bits).
121     * Returns the start offset of the chunk. This is the location at which
122     * the opcode & size are stored.
123     * TODO: since we are handing the size into here we could call reserve
124     * and then return a pointer to the memory storage. This could decrease
125     * allocation overhead but could lead to more wasted space (the tail
126     * end of blocks could go unused). Possibly add a second addDraw that
127     * operates in this manner.
128     */
129    size_t addDraw(DrawType drawType, uint32_t* size) {
130        size_t offset = fWriter.bytesWritten();
131
132        this->predrawNotify();
133
134    #ifdef SK_DEBUG_TRACE
135        SkDebugf("add %s\n", DrawTypeToString(drawType));
136    #endif
137
138        SkASSERT(0 != *size);
139        SkASSERT(((uint8_t) drawType) == drawType);
140
141        if (0 != (*size & ~MASK_24) || *size == MASK_24) {
142            fWriter.writeInt(PACK_8_24(drawType, MASK_24));
143            *size += 1;
144            fWriter.writeInt(*size);
145        } else {
146            fWriter.writeInt(PACK_8_24(drawType, *size));
147        }
148
149        return offset;
150    }
151
152    void addInt(int value) {
153        fWriter.writeInt(value);
154    }
155    void addScalar(SkScalar scalar) {
156        fWriter.writeScalar(scalar);
157    }
158
159    // The command at 'offset' in the skp uses the specified bitmap
160    void trackBitmapUse(int bitmapID, size_t offset);
161    int addBitmap(const SkBitmap& bitmap);
162    void addMatrix(const SkMatrix& matrix);
163    const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
164    const SkFlatData* addPaintPtr(const SkPaint* paint);
165    void addFlatPaint(const SkFlatData* flatPaint);
166    void addPath(const SkPath& path);
167    void addPicture(SkPicture& picture);
168    void addPoint(const SkPoint& point);
169    void addPoints(const SkPoint pts[], int count);
170    void addRect(const SkRect& rect);
171    void addRectPtr(const SkRect* rect);
172    void addIRect(const SkIRect& rect);
173    void addIRectPtr(const SkIRect* rect);
174    void addRRect(const SkRRect&);
175    void addRegion(const SkRegion& region);
176    void addText(const void* text, size_t byteLength);
177
178    int find(const SkBitmap& bitmap);
179
180#ifdef SK_DEBUG_DUMP
181public:
182    void dumpMatrices();
183    void dumpPaints();
184#endif
185
186#ifdef SK_DEBUG_SIZE
187public:
188    size_t size() const;
189    int bitmaps(size_t* size) const;
190    int matrices(size_t* size) const;
191    int paints(size_t* size) const;
192    int paths(size_t* size) const;
193    int regions(size_t* size) const;
194    size_t streamlen() const;
195
196    size_t fPointBytes, fRectBytes, fTextBytes;
197    int fPointWrites, fRectWrites, fTextWrites;
198#endif
199
200#ifdef SK_DEBUG_VALIDATE
201public:
202    void validate(size_t initialOffset, uint32_t size) const;
203private:
204    void validateBitmaps() const;
205    void validateMatrices() const;
206    void validatePaints() const;
207    void validatePaths() const;
208    void validateRegions() const;
209#else
210public:
211    void validate(size_t initialOffset, uint32_t size) const {
212        SkASSERT(fWriter.bytesWritten() == initialOffset + size);
213    }
214#endif
215
216protected:
217    virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
218    const void* onPeekPixels(SkImageInfo*, size_t*) SK_OVERRIDE {
219        return NULL;
220    }
221
222    virtual void willSave(SaveFlags) SK_OVERRIDE;
223    virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
224    virtual void willRestore() SK_OVERRIDE;
225
226    virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
227    virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
228
229    virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
230    virtual void onPushCull(const SkRect&) SK_OVERRIDE;
231    virtual void onPopCull() SK_OVERRIDE;
232
233    virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
234    virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
235    virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
236    virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
237
238    // Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
239    // tweaked by paint.computeFastBounds().
240    static void ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]);
241
242    // Make sure that flat has fTopBot written.
243    static void WriteTopBot(const SkPaint& paint, const SkFlatData& flat) {
244        if (!flat.isTopBotWritten()) {
245            ComputeFontMetricsTopBottom(paint, flat.writableTopBot());
246            SkASSERT(flat.isTopBotWritten());
247        }
248    }
249    // Will return a cached version when possible.
250    const SkFlatData* getFlatPaintData(const SkPaint& paint);
251    /**
252     * SkBBoxRecord::drawPosTextH gets a flat paint and uses it,
253     * then it calls this, using the extra parameter, to avoid duplication.
254     */
255    void drawPosTextHImpl(const void* text, size_t byteLength,
256                          const SkScalar xpos[], SkScalar constY,
257                          const SkPaint& paint, const SkFlatData* flatPaintData);
258
259    int addPathToHeap(const SkPath& path);  // does not write to ops stream
260
261    // These entry points allow the writing of matrices, clips, saves &
262    // restores to be deferred (e.g., if the MC state is being collapsed and
263    // only written out as needed).
264    void recordConcat(const SkMatrix& matrix);
265    void recordTranslate(const SkMatrix& matrix);
266    void recordScale(const SkMatrix& matrix);
267    int recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA);
268    int recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA);
269    int recordClipPath(int pathID, SkRegion::Op op, bool doAA);
270    int recordClipRegion(const SkRegion& region, SkRegion::Op op);
271    void recordSave(SaveFlags flags);
272    void recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
273    void recordRestore(bool fillInSkips = true);
274
275    // These are set to NULL in our constructor, but may be changed by
276    // subclasses, in which case they will be SkSafeUnref'd in our destructor.
277    SkBBoxHierarchy* fBoundingHierarchy;
278    SkPictureStateTree* fStateTree;
279
280    // Allocated in the constructor and managed by this class.
281    SkBitmapHeap* fBitmapHeap;
282
283private:
284    friend class MatrixClipState; // for access to *Impl methods
285    friend class SkMatrixClipStateMgr; // for access to *Impl methods
286
287    SkChunkFlatController fFlattenableHeap;
288
289    SkPaintDictionary fPaints;
290
291    SkPathHeap* fPathHeap;  // reference counted
292    SkWriter32 fWriter;
293
294    // we ref each item in these arrays
295    SkTDArray<SkPicture*> fPictureRefs;
296
297    uint32_t fRecordFlags;
298    bool     fOptsEnabled;
299    int      fInitialSaveCount;
300
301    SkAutoTUnref<SkOffsetTable> fBitmapUseOffsets;
302
303    friend class SkPicturePlayback;
304    friend class SkPictureTester; // for unit testing
305
306#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
307    SkMatrixClipStateMgr fMCMgr;
308#endif
309
310    typedef SkCanvas INHERITED;
311};
312
313#endif
314