Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2007 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 "SkPictureFlat.h"
     11 #include "SkPicturePlayback.h"
     12 #include "SkPictureRecord.h"
     13 
     14 #include "SkCanvas.h"
     15 #include "SkChunkAlloc.h"
     16 #include "SkPicture.h"
     17 #include "SkRegion.h"
     18 #include "SkStream.h"
     19 #include "SkTDArray.h"
     20 #include "SkTSearch.h"
     21 #include "SkTime.h"
     22 
     23 #include "SkReader32.h"
     24 #include "SkWriter32.h"
     25 
     26 #define DUMP_BUFFER_SIZE 65536
     27 
     28 //#define ENABLE_TIME_DRAW    // dumps milliseconds for each draw
     29 
     30 
     31 #ifdef SK_DEBUG
     32 // enable SK_DEBUG_TRACE to trace DrawType elements when
     33 //     recorded and played back
     34 // #define SK_DEBUG_TRACE
     35 // enable SK_DEBUG_SIZE to see the size of picture components
     36 // #define SK_DEBUG_SIZE
     37 // enable SK_DEBUG_DUMP to see the contents of recorded elements
     38 // #define SK_DEBUG_DUMP
     39 // enable SK_DEBUG_VALIDATE to check internal structures for consistency
     40 // #define SK_DEBUG_VALIDATE
     41 #endif
     42 
     43 #if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
     44 const char* DrawTypeToString(DrawType drawType) {
     45     switch (drawType) {
     46         case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
     47         case CLIP_PATH: return "CLIP_PATH";
     48         case CLIP_REGION: return "CLIP_REGION";
     49         case CLIP_RECT: return "CLIP_RECT";
     50         case CONCAT: return "CONCAT";
     51         case DRAW_BITMAP: return "DRAW_BITMAP";
     52         case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
     53         case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT";
     54         case DRAW_PAINT: return "DRAW_PAINT";
     55         case DRAW_PATH: return "DRAW_PATH";
     56         case DRAW_PICTURE: return "DRAW_PICTURE";
     57         case DRAW_POINTS: return "DRAW_POINTS";
     58         case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
     59         case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
     60         case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL";
     61         case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE";
     62         case DRAW_SPRITE: return "DRAW_SPRITE";
     63         case DRAW_TEXT: return "DRAW_TEXT";
     64         case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
     65         case RESTORE: return "RESTORE";
     66         case ROTATE: return "ROTATE";
     67         case SAVE: return "SAVE";
     68         case SAVE_LAYER: return "SAVE_LAYER";
     69         case SCALE: return "SCALE";
     70         case SKEW: return "SKEW";
     71         case TRANSLATE: return "TRANSLATE";
     72         default:
     73             SkDebugf("DrawType error 0x%08x\n", drawType);
     74             SkASSERT(0);
     75             break;
     76     }
     77     SkASSERT(0);
     78     return NULL;
     79 }
     80 #endif
     81 
     82 #ifdef SK_DEBUG_VALIDATE
     83 static void validateMatrix(const SkMatrix* matrix) {
     84     SkScalar scaleX = matrix->getScaleX();
     85     SkScalar scaleY = matrix->getScaleY();
     86     SkScalar skewX = matrix->getSkewX();
     87     SkScalar skewY = matrix->getSkewY();
     88     SkScalar perspX = matrix->getPerspX();
     89     SkScalar perspY = matrix->getPerspY();
     90     if (scaleX != 0 && skewX != 0)
     91         SkDebugf("scaleX != 0 && skewX != 0\n");
     92     SkASSERT(scaleX == 0 || skewX == 0);
     93     SkASSERT(scaleY == 0 || skewY == 0);
     94     SkASSERT(perspX == 0);
     95     SkASSERT(perspY == 0);
     96 }
     97 #endif
     98 
     99 
    100 ///////////////////////////////////////////////////////////////////////////////
    101 
    102 SkPicture::SkPicture() {
    103     fRecord = NULL;
    104     fPlayback = NULL;
    105     fWidth = fHeight = 0;
    106 }
    107 
    108 SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() {
    109     fWidth = src.fWidth;
    110     fHeight = src.fHeight;
    111     fRecord = NULL;
    112 
    113     /*  We want to copy the src's playback. However, if that hasn't been built
    114         yet, we need to fake a call to endRecording() without actually calling
    115         it (since it is destructive, and we don't want to change src).
    116      */
    117     if (src.fPlayback) {
    118         fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
    119     } else if (src.fRecord) {
    120         // here we do a fake src.endRecording()
    121         fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
    122     } else {
    123         fPlayback = NULL;
    124     }
    125 }
    126 
    127 SkPicture::~SkPicture() {
    128     SkSafeUnref(fRecord);
    129     SkDELETE(fPlayback);
    130 }
    131 
    132 void SkPicture::swap(SkPicture& other) {
    133     SkTSwap(fRecord, other.fRecord);
    134     SkTSwap(fPlayback, other.fPlayback);
    135     SkTSwap(fWidth, other.fWidth);
    136     SkTSwap(fHeight, other.fHeight);
    137 }
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 
    141 SkCanvas* SkPicture::beginRecording(int width, int height,
    142                                     uint32_t recordingFlags) {
    143     if (fPlayback) {
    144         SkDELETE(fPlayback);
    145         fPlayback = NULL;
    146     }
    147 
    148     if (NULL != fRecord) {
    149         fRecord->unref();
    150         fRecord = NULL;
    151     }
    152 
    153     fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
    154 
    155     fWidth = width;
    156     fHeight = height;
    157 
    158     SkBitmap bm;
    159     bm.setConfig(SkBitmap::kNo_Config, width, height);
    160     fRecord->setBitmapDevice(bm);
    161 
    162     return fRecord;
    163 }
    164 
    165 SkCanvas* SkPicture::getRecordingCanvas() const {
    166     // will be null if we are not recording
    167     return fRecord;
    168 }
    169 
    170 void SkPicture::endRecording() {
    171     if (NULL == fPlayback) {
    172         if (NULL != fRecord) {
    173             fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
    174             fRecord->unref();
    175             fRecord = NULL;
    176         }
    177     }
    178     SkASSERT(NULL == fRecord);
    179 }
    180 
    181 void SkPicture::draw(SkCanvas* surface) {
    182     this->endRecording();
    183     if (fPlayback) {
    184         fPlayback->draw(*surface);
    185     }
    186 }
    187 
    188 ///////////////////////////////////////////////////////////////////////////////
    189 
    190 #include "SkStream.h"
    191 
    192 #define PICTURE_VERSION     1
    193 
    194 SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
    195     const uint32_t  pictureVersion = stream->readU32();
    196     if (pictureVersion != PICTURE_VERSION_ICS &&
    197         pictureVersion != PICTURE_VERSION_JB) {
    198         sk_throw();
    199     }
    200 
    201     fWidth = stream->readU32();
    202     fHeight = stream->readU32();
    203 
    204     fRecord = NULL;
    205     fPlayback = NULL;
    206 
    207     if (stream->readBool()) {
    208         fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream, pictureVersion));
    209     }
    210 }
    211 
    212 void SkPicture::serialize(SkWStream* stream) const {
    213     SkPicturePlayback* playback = fPlayback;
    214 
    215     if (NULL == playback && fRecord) {
    216         playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
    217     }
    218 
    219     stream->write32(PICTURE_VERSION_JB);
    220     stream->write32(fWidth);
    221     stream->write32(fHeight);
    222     if (playback) {
    223         stream->writeBool(true);
    224         playback->serialize(stream);
    225         // delete playback if it is a local version (i.e. cons'd up just now)
    226         if (playback != fPlayback) {
    227             SkDELETE(playback);
    228         }
    229     } else {
    230         stream->writeBool(false);
    231     }
    232 }
    233 
    234 void SkPicture::abortPlayback() {
    235     if (NULL == fPlayback) {
    236         return;
    237     }
    238     fPlayback->abort();
    239 }
    240 
    241 
    242