gfx/skia/trunk/src/core/SkPicture.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    10 #include "SkPictureFlat.h"
    11 #include "SkPicturePlayback.h"
    12 #include "SkPictureRecord.h"
    14 #include "SkBitmapDevice.h"
    15 #include "SkCanvas.h"
    16 #include "SkChunkAlloc.h"
    17 #include "SkPicture.h"
    18 #include "SkRegion.h"
    19 #include "SkStream.h"
    20 #include "SkTDArray.h"
    21 #include "SkTSearch.h"
    22 #include "SkTime.h"
    24 #include "SkReader32.h"
    25 #include "SkWriter32.h"
    26 #include "SkRTree.h"
    27 #include "SkBBoxHierarchyRecord.h"
    29 #define DUMP_BUFFER_SIZE 65536
    31 //#define ENABLE_TIME_DRAW    // dumps milliseconds for each draw
    34 #ifdef SK_DEBUG
    35 // enable SK_DEBUG_TRACE to trace DrawType elements when
    36 //     recorded and played back
    37 // #define SK_DEBUG_TRACE
    38 // enable SK_DEBUG_SIZE to see the size of picture components
    39 // #define SK_DEBUG_SIZE
    40 // enable SK_DEBUG_DUMP to see the contents of recorded elements
    41 // #define SK_DEBUG_DUMP
    42 // enable SK_DEBUG_VALIDATE to check internal structures for consistency
    43 // #define SK_DEBUG_VALIDATE
    44 #endif
    46 #if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
    47 const char* DrawTypeToString(DrawType drawType) {
    48     switch (drawType) {
    49         case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
    50         case CLIP_PATH: return "CLIP_PATH";
    51         case CLIP_REGION: return "CLIP_REGION";
    52         case CLIP_RECT: return "CLIP_RECT";
    53         case CLIP_RRECT: return "CLIP_RRECT";
    54         case CONCAT: return "CONCAT";
    55         case DRAW_BITMAP: return "DRAW_BITMAP";
    56         case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
    57         case DRAW_BITMAP_NINE: return "DRAW_BITMAP_NINE";
    58         case DRAW_BITMAP_RECT_TO_RECT: return "DRAW_BITMAP_RECT_TO_RECT";
    59         case DRAW_CLEAR: return "DRAW_CLEAR";
    60         case DRAW_DATA: return "DRAW_DATA";
    61         case DRAW_OVAL: return "DRAW_OVAL";
    62         case DRAW_PAINT: return "DRAW_PAINT";
    63         case DRAW_PATH: return "DRAW_PATH";
    64         case DRAW_PICTURE: return "DRAW_PICTURE";
    65         case DRAW_POINTS: return "DRAW_POINTS";
    66         case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
    67         case DRAW_POS_TEXT_TOP_BOTTOM: return "DRAW_POS_TEXT_TOP_BOTTOM";
    68         case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
    69         case DRAW_POS_TEXT_H_TOP_BOTTOM: return "DRAW_POS_TEXT_H_TOP_BOTTOM";
    70         case DRAW_RECT: return "DRAW_RECT";
    71         case DRAW_RRECT: return "DRAW_RRECT";
    72         case DRAW_SPRITE: return "DRAW_SPRITE";
    73         case DRAW_TEXT: return "DRAW_TEXT";
    74         case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
    75         case DRAW_TEXT_TOP_BOTTOM: return "DRAW_TEXT_TOP_BOTTOM";
    76         case DRAW_VERTICES: return "DRAW_VERTICES";
    77         case RESTORE: return "RESTORE";
    78         case ROTATE: return "ROTATE";
    79         case SAVE: return "SAVE";
    80         case SAVE_LAYER: return "SAVE_LAYER";
    81         case SCALE: return "SCALE";
    82         case SET_MATRIX: return "SET_MATRIX";
    83         case SKEW: return "SKEW";
    84         case TRANSLATE: return "TRANSLATE";
    85         case NOOP: return "NOOP";
    86         default:
    87             SkDebugf("DrawType error 0x%08x\n", drawType);
    88             SkASSERT(0);
    89             break;
    90     }
    91     SkASSERT(0);
    92     return NULL;
    93 }
    94 #endif
    96 #ifdef SK_DEBUG_VALIDATE
    97 static void validateMatrix(const SkMatrix* matrix) {
    98     SkScalar scaleX = matrix->getScaleX();
    99     SkScalar scaleY = matrix->getScaleY();
   100     SkScalar skewX = matrix->getSkewX();
   101     SkScalar skewY = matrix->getSkewY();
   102     SkScalar perspX = matrix->getPerspX();
   103     SkScalar perspY = matrix->getPerspY();
   104     if (scaleX != 0 && skewX != 0)
   105         SkDebugf("scaleX != 0 && skewX != 0\n");
   106     SkASSERT(scaleX == 0 || skewX == 0);
   107     SkASSERT(scaleY == 0 || skewY == 0);
   108     SkASSERT(perspX == 0);
   109     SkASSERT(perspY == 0);
   110 }
   111 #endif
   114 ///////////////////////////////////////////////////////////////////////////////
   116 SkPicture::SkPicture() {
   117     fRecord = NULL;
   118     fPlayback = NULL;
   119     fWidth = fHeight = 0;
   120     fAccelData = NULL;
   121 }
   123 SkPicture::SkPicture(const SkPicture& src)
   124     : INHERITED()
   125     , fAccelData(NULL) {
   126     fWidth = src.fWidth;
   127     fHeight = src.fHeight;
   128     fRecord = NULL;
   130     /*  We want to copy the src's playback. However, if that hasn't been built
   131         yet, we need to fake a call to endRecording() without actually calling
   132         it (since it is destructive, and we don't want to change src).
   133      */
   134     if (src.fPlayback) {
   135         fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
   136     } else if (src.fRecord) {
   137         // here we do a fake src.endRecording()
   138         fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
   139     } else {
   140         fPlayback = NULL;
   141     }
   142 }
   144 SkPicture::~SkPicture() {
   145     SkSafeUnref(fRecord);
   146     SkDELETE(fPlayback);
   147     SkSafeUnref(fAccelData);
   148 }
   150 void SkPicture::internalOnly_EnableOpts(bool enableOpts) {
   151     if (NULL != fRecord) {
   152         fRecord->internalOnly_EnableOpts(enableOpts);
   153     }
   154 }
   156 void SkPicture::swap(SkPicture& other) {
   157     SkTSwap(fRecord, other.fRecord);
   158     SkTSwap(fPlayback, other.fPlayback);
   159     SkTSwap(fAccelData, other.fAccelData);
   160     SkTSwap(fWidth, other.fWidth);
   161     SkTSwap(fHeight, other.fHeight);
   162 }
   164 SkPicture* SkPicture::clone() const {
   165     SkPicture* clonedPicture = SkNEW(SkPicture);
   166     clone(clonedPicture, 1);
   167     return clonedPicture;
   168 }
   170 void SkPicture::clone(SkPicture* pictures, int count) const {
   171     SkPictCopyInfo copyInfo;
   173     for (int i = 0; i < count; i++) {
   174         SkPicture* clone = &pictures[i];
   176         clone->fWidth = fWidth;
   177         clone->fHeight = fHeight;
   178         SkSafeSetNull(clone->fRecord);
   179         SkDELETE(clone->fPlayback);
   181         /*  We want to copy the src's playback. However, if that hasn't been built
   182             yet, we need to fake a call to endRecording() without actually calling
   183             it (since it is destructive, and we don't want to change src).
   184          */
   185         if (fPlayback) {
   186             clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, &copyInfo));
   187         } else if (fRecord) {
   188             // here we do a fake src.endRecording()
   189             clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, true));
   190         } else {
   191             clone->fPlayback = NULL;
   192         }
   193     }
   194 }
   196 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
   197     static int32_t gNextID = 0;
   199     int32_t id = sk_atomic_inc(&gNextID);
   200     if (id >= 1 << (8 * sizeof(Domain))) {
   201         SK_CRASH();
   202     }
   204     return static_cast<Domain>(id);
   205 }
   207 ///////////////////////////////////////////////////////////////////////////////
   209 SkCanvas* SkPicture::beginRecording(int width, int height,
   210                                     uint32_t recordingFlags) {
   211     if (fPlayback) {
   212         SkDELETE(fPlayback);
   213         fPlayback = NULL;
   214     }
   215     SkSafeUnref(fAccelData);
   216     SkSafeSetNull(fRecord);
   218     // Must be set before calling createBBoxHierarchy
   219     fWidth = width;
   220     fHeight = height;
   222     const SkISize size = SkISize::Make(width, height);
   224     if (recordingFlags & kOptimizeForClippedPlayback_RecordingFlag) {
   225         SkBBoxHierarchy* tree = this->createBBoxHierarchy();
   226         SkASSERT(NULL != tree);
   227         fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordingFlags, tree));
   228         tree->unref();
   229     } else {
   230         fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags));
   231     }
   232     fRecord->beginRecording();
   234     return fRecord;
   235 }
   237 SkBBoxHierarchy* SkPicture::createBBoxHierarchy() const {
   238     // These values were empirically determined to produce reasonable
   239     // performance in most cases.
   240     static const int kRTreeMinChildren = 6;
   241     static const int kRTreeMaxChildren = 11;
   243     SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
   244                                        SkIntToScalar(fHeight));
   245     bool sortDraws = false;  // Do not sort draw calls when bulk loading.
   247     return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
   248                            aspectRatio, sortDraws);
   249 }
   251 SkCanvas* SkPicture::getRecordingCanvas() const {
   252     // will be null if we are not recording
   253     return fRecord;
   254 }
   256 void SkPicture::endRecording() {
   257     if (NULL == fPlayback) {
   258         if (NULL != fRecord) {
   259             fRecord->endRecording();
   260             fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
   261             SkSafeSetNull(fRecord);
   262         }
   263     }
   264     SkASSERT(NULL == fRecord);
   265 }
   267 void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
   268     this->endRecording();
   269     if (NULL != fPlayback) {
   270         fPlayback->draw(*surface, callback);
   271     }
   272 }
   274 ///////////////////////////////////////////////////////////////////////////////
   276 #include "SkStream.h"
   278 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
   280 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
   281     if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
   282         return false;
   283     }
   285     if (info.fVersion < MIN_PICTURE_VERSION ||
   286         info.fVersion > CURRENT_PICTURE_VERSION) {
   287         return false;
   288     }
   290     return true;
   291 }
   293 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
   294     if (NULL == stream) {
   295         return false;
   296     }
   298     // Check magic bytes.
   299     SkPictInfo info;
   300     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
   301     if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
   302         return false;
   303     }
   305     if (pInfo != NULL) {
   306         *pInfo = info;
   307     }
   308     return true;
   309 }
   311 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
   312     // Check magic bytes.
   313     SkPictInfo info;
   314     SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
   315     if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
   316         return false;
   317     }
   319     if (pInfo != NULL) {
   320         *pInfo = info;
   321     }
   322     return true;
   323 }
   325 SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height)
   326     : fPlayback(playback)
   327     , fRecord(NULL)
   328     , fWidth(width)
   329     , fHeight(height)
   330     , fAccelData(NULL) {}
   332 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
   333     SkPictInfo info;
   335     if (!InternalOnly_StreamIsSKP(stream, &info)) {
   336         return NULL;
   337     }
   339     SkPicturePlayback* playback;
   340     // Check to see if there is a playback to recreate.
   341     if (stream->readBool()) {
   342         playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
   343         if (NULL == playback) {
   344             return NULL;
   345         }
   346     } else {
   347         playback = NULL;
   348     }
   350     return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
   351 }
   353 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
   354     SkPictInfo info;
   356     if (!InternalOnly_BufferIsSKP(buffer, &info)) {
   357         return NULL;
   358     }
   360     SkPicturePlayback* playback;
   361     // Check to see if there is a playback to recreate.
   362     if (buffer.readBool()) {
   363         playback = SkPicturePlayback::CreateFromBuffer(buffer);
   364         if (NULL == playback) {
   365             return NULL;
   366         }
   367     } else {
   368         playback = NULL;
   369     }
   371     return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
   372 }
   374 void SkPicture::createHeader(SkPictInfo* info) const {
   375     // Copy magic bytes at the beginning of the header
   376     SkASSERT(sizeof(kMagic) == 8);
   377     SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
   378     memcpy(info->fMagic, kMagic, sizeof(kMagic));
   380     // Set picture info after magic bytes in the header
   381     info->fVersion = CURRENT_PICTURE_VERSION;
   382     info->fWidth = fWidth;
   383     info->fHeight = fHeight;
   384     info->fFlags = SkPictInfo::kCrossProcess_Flag;
   385     // TODO: remove this flag, since we're always float (now)
   386     info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
   388     if (8 == sizeof(void*)) {
   389         info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
   390     }
   391 }
   393 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
   394     SkPicturePlayback* playback = fPlayback;
   396     if (NULL == playback && fRecord) {
   397         playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
   398     }
   400     SkPictInfo header;
   401     this->createHeader(&header);
   402     stream->write(&header, sizeof(header));
   403     if (playback) {
   404         stream->writeBool(true);
   405         playback->serialize(stream, encoder);
   406         // delete playback if it is a local version (i.e. cons'd up just now)
   407         if (playback != fPlayback) {
   408             SkDELETE(playback);
   409         }
   410     } else {
   411         stream->writeBool(false);
   412     }
   413 }
   415 void SkPicture::flatten(SkWriteBuffer& buffer) const {
   416     SkPicturePlayback* playback = fPlayback;
   418     if (NULL == playback && fRecord) {
   419         playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
   420     }
   422     SkPictInfo header;
   423     this->createHeader(&header);
   424     buffer.writeByteArray(&header, sizeof(header));
   425     if (playback) {
   426         buffer.writeBool(true);
   427         playback->flatten(buffer);
   428         // delete playback if it is a local version (i.e. cons'd up just now)
   429         if (playback != fPlayback) {
   430             SkDELETE(playback);
   431         }
   432     } else {
   433         buffer.writeBool(false);
   434     }
   435 }
   437 bool SkPicture::willPlayBackBitmaps() const {
   438     if (!fPlayback) {
   439         return false;
   440     }
   441     return fPlayback->containsBitmaps();
   442 }
   444 #ifdef SK_BUILD_FOR_ANDROID
   445 void SkPicture::abortPlayback() {
   446     if (NULL == fPlayback) {
   447         return;
   448     }
   449     fPlayback->abort();
   450 }
   451 #endif

mercurial