LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkPictureRecord.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 592 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 84 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "SkPictureRecord.h"
       9             : #include "SkImage_Base.h"
      10             : #include "SkPatchUtils.h"
      11             : #include "SkPixelRef.h"
      12             : #include "SkRRect.h"
      13             : #include "SkRSXform.h"
      14             : #include "SkTextBlob.h"
      15             : #include "SkTSearch.h"
      16             : #include "SkClipOpPriv.h"
      17             : 
      18             : #define HEAP_BLOCK_SIZE 4096
      19             : 
      20             : enum {
      21             :     // just need a value that save or getSaveCount would never return
      22             :     kNoInitialSave = -1,
      23             : };
      24             : 
      25             : // A lot of basic types get stored as a uint32_t: bools, ints, paint indices, etc.
      26             : static int const kUInt32Size = 4;
      27             : 
      28           0 : SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
      29             :     : INHERITED(dimensions.width(), dimensions.height())
      30             :     , fRecordFlags(flags)
      31           0 :     , fInitialSaveCount(kNoInitialSave) {
      32           0 : }
      33             : 
      34           0 : SkPictureRecord::~SkPictureRecord() {
      35           0 :     fImageRefs.unrefAll();
      36           0 :     fPictureRefs.unrefAll();
      37           0 :     fDrawableRefs.unrefAll();
      38           0 :     fTextBlobRefs.unrefAll();
      39           0 :     fVerticesRefs.unrefAll();
      40           0 : }
      41             : 
      42             : ///////////////////////////////////////////////////////////////////////////////
      43             : 
      44           0 : void SkPictureRecord::willSave() {
      45             :     // record the offset to us, making it non-positive to distinguish a save
      46             :     // from a clip entry.
      47           0 :     fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
      48           0 :     this->recordSave();
      49             : 
      50           0 :     this->INHERITED::willSave();
      51           0 : }
      52             : 
      53           0 : void SkPictureRecord::recordSave() {
      54           0 :     fContentInfo.onSave();
      55             : 
      56             :     // op only
      57           0 :     size_t size = sizeof(kUInt32Size);
      58           0 :     size_t initialOffset = this->addDraw(SAVE, &size);
      59             : 
      60           0 :     this->validate(initialOffset, size);
      61           0 : }
      62             : 
      63           0 : SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLayerRec& rec) {
      64             :     // record the offset to us, making it non-positive to distinguish a save
      65             :     // from a clip entry.
      66           0 :     fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
      67           0 :     this->recordSaveLayer(rec);
      68             : 
      69           0 :     (void)this->INHERITED::getSaveLayerStrategy(rec);
      70             :     /*  No need for a (potentially very big) layer which we don't actually need
      71             :         at this time (and may not be able to afford since during record our
      72             :         clip starts out the size of the picture, which is often much larger
      73             :         than the size of the actual device we'll use during playback).
      74             :      */
      75           0 :     return kNoLayer_SaveLayerStrategy;
      76             : }
      77             : 
      78           0 : void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
      79           0 :     fContentInfo.onSaveLayer();
      80             : 
      81             :     // op + flatflags
      82           0 :     size_t size = 2 * kUInt32Size;
      83           0 :     uint32_t flatFlags = 0;
      84             : 
      85           0 :     if (rec.fBounds) {
      86           0 :         flatFlags |= SAVELAYERREC_HAS_BOUNDS;
      87           0 :         size += sizeof(*rec.fBounds);
      88             :     }
      89           0 :     if (rec.fPaint) {
      90           0 :         flatFlags |= SAVELAYERREC_HAS_PAINT;
      91           0 :         size += sizeof(uint32_t); // index
      92             :     }
      93           0 :     if (rec.fBackdrop) {
      94           0 :         flatFlags |= SAVELAYERREC_HAS_BACKDROP;
      95           0 :         size += sizeof(uint32_t); // (paint) index
      96             :     }
      97           0 :     if (rec.fSaveLayerFlags) {
      98           0 :         flatFlags |= SAVELAYERREC_HAS_FLAGS;
      99           0 :         size += sizeof(uint32_t);
     100             :     }
     101             : 
     102           0 :     const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
     103           0 :     this->addInt(flatFlags);
     104           0 :     if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
     105           0 :         this->addRect(*rec.fBounds);
     106             :     }
     107           0 :     if (flatFlags & SAVELAYERREC_HAS_PAINT) {
     108           0 :         this->addPaintPtr(rec.fPaint);
     109             :     }
     110           0 :     if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
     111             :         // overkill, but we didn't already track single flattenables, so using a paint for that
     112           0 :         SkPaint paint;
     113           0 :         paint.setImageFilter(sk_ref_sp(const_cast<SkImageFilter*>(rec.fBackdrop)));
     114           0 :         this->addPaint(paint);
     115             :     }
     116           0 :     if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
     117           0 :         this->addInt(rec.fSaveLayerFlags);
     118             :     }
     119           0 :     this->validate(initialOffset, size);
     120           0 : }
     121             : 
     122             : #ifdef SK_DEBUG
     123             : /*
     124             :  * Read the op code from 'offset' in 'writer' and extract the size too.
     125             :  */
     126           0 : static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
     127           0 :     uint32_t peek = writer->readTAt<uint32_t>(offset);
     128             : 
     129             :     uint32_t op;
     130           0 :     UNPACK_8_24(peek, op, *size);
     131           0 :     if (MASK_24 == *size) {
     132             :         // size required its own slot right after the op code
     133           0 :         *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
     134             :     }
     135           0 :     return (DrawType) op;
     136             : }
     137             : #endif//SK_DEBUG
     138             : 
     139           0 : void SkPictureRecord::willRestore() {
     140             : #if 0
     141             :     SkASSERT(fRestoreOffsetStack.count() > 1);
     142             : #endif
     143             : 
     144             :     // check for underflow
     145           0 :     if (fRestoreOffsetStack.count() == 0) {
     146           0 :         return;
     147             :     }
     148             : 
     149           0 :     this->recordRestore();
     150             : 
     151           0 :     fRestoreOffsetStack.pop();
     152             : 
     153           0 :     this->INHERITED::willRestore();
     154             : }
     155             : 
     156           0 : void SkPictureRecord::recordRestore(bool fillInSkips) {
     157           0 :     fContentInfo.onRestore();
     158             : 
     159           0 :     if (fillInSkips) {
     160           0 :         this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
     161             :     }
     162           0 :     size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
     163           0 :     size_t initialOffset = this->addDraw(RESTORE, &size);
     164           0 :     this->validate(initialOffset, size);
     165           0 : }
     166             : 
     167           0 : void SkPictureRecord::recordTranslate(const SkMatrix& m) {
     168           0 :     SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
     169             : 
     170             :     // op + dx + dy
     171           0 :     size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
     172           0 :     size_t initialOffset = this->addDraw(TRANSLATE, &size);
     173           0 :     this->addScalar(m.getTranslateX());
     174           0 :     this->addScalar(m.getTranslateY());
     175           0 :     this->validate(initialOffset, size);
     176           0 : }
     177             : 
     178           0 : void SkPictureRecord::recordScale(const SkMatrix& m) {
     179           0 :     SkASSERT(SkMatrix::kScale_Mask == m.getType());
     180             : 
     181             :     // op + sx + sy
     182           0 :     size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
     183           0 :     size_t initialOffset = this->addDraw(SCALE, &size);
     184           0 :     this->addScalar(m.getScaleX());
     185           0 :     this->addScalar(m.getScaleY());
     186           0 :     this->validate(initialOffset, size);
     187           0 : }
     188             : 
     189           0 : void SkPictureRecord::didConcat(const SkMatrix& matrix) {
     190           0 :     switch (matrix.getType()) {
     191             :         case SkMatrix::kTranslate_Mask:
     192           0 :             this->recordTranslate(matrix);
     193           0 :             break;
     194             :         case SkMatrix::kScale_Mask:
     195           0 :             this->recordScale(matrix);
     196           0 :             break;
     197             :         default:
     198           0 :             this->recordConcat(matrix);
     199           0 :             break;
     200             :     }
     201           0 :     this->INHERITED::didConcat(matrix);
     202           0 : }
     203             : 
     204           0 : void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
     205           0 :     this->validate(fWriter.bytesWritten(), 0);
     206             :     // op + matrix
     207           0 :     size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
     208           0 :     size_t initialOffset = this->addDraw(CONCAT, &size);
     209           0 :     this->addMatrix(matrix);
     210           0 :     this->validate(initialOffset, size);
     211           0 : }
     212             : 
     213           0 : void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
     214           0 :     this->validate(fWriter.bytesWritten(), 0);
     215             :     // op + matrix
     216           0 :     size_t size = kUInt32Size + matrix.writeToMemory(nullptr);
     217           0 :     size_t initialOffset = this->addDraw(SET_MATRIX, &size);
     218           0 :     this->addMatrix(matrix);
     219           0 :     this->validate(initialOffset, size);
     220           0 :     this->INHERITED::didSetMatrix(matrix);
     221           0 : }
     222             : 
     223           0 : void SkPictureRecord::didTranslateZ(SkScalar z) {
     224             : #ifdef SK_EXPERIMENTAL_SHADOWING
     225             :     this->validate(fWriter.bytesWritten(), 0);
     226             :     // op + scalar
     227             :     size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
     228             :     size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
     229             :     this->addScalar(z);
     230             :     this->validate(initialOffset, size);
     231             :     this->INHERITED::didTranslateZ(z);
     232             : #endif
     233           0 : }
     234             : 
     235           0 : static bool clipOpExpands(SkClipOp op) {
     236           0 :     switch (op) {
     237             :         case kUnion_SkClipOp:
     238             :         case kXOR_SkClipOp:
     239             :         case kReverseDifference_SkClipOp:
     240             :         case kReplace_SkClipOp:
     241           0 :             return true;
     242             :         case kIntersect_SkClipOp:
     243             :         case kDifference_SkClipOp:
     244           0 :             return false;
     245             :         default:
     246           0 :             SkDEBUGFAIL("unknown clipop");
     247           0 :             return false;
     248             :     }
     249             : }
     250             : 
     251           0 : void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
     252           0 :     int32_t offset = fRestoreOffsetStack.top();
     253           0 :     while (offset > 0) {
     254           0 :         uint32_t peek = fWriter.readTAt<uint32_t>(offset);
     255           0 :         fWriter.overwriteTAt(offset, restoreOffset);
     256           0 :         offset = peek;
     257             :     }
     258             : 
     259             : #ifdef SK_DEBUG
     260             :     // offset of 0 has been disabled, so we skip it
     261           0 :     if (offset > 0) {
     262             :         // assert that the final offset value points to a save verb
     263             :         uint32_t opSize;
     264           0 :         DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
     265           0 :         SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
     266           0 :         SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
     267           0 :         SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
     268             :     }
     269             : #endif
     270           0 : }
     271             : 
     272           0 : void SkPictureRecord::beginRecording() {
     273             :     // we have to call this *after* our constructor, to ensure that it gets
     274             :     // recorded. This is balanced by restoreToCount() call from endRecording,
     275             :     // which in-turn calls our overridden restore(), so those get recorded too.
     276           0 :     fInitialSaveCount = this->save();
     277           0 : }
     278             : 
     279           0 : void SkPictureRecord::endRecording() {
     280           0 :     SkASSERT(kNoInitialSave != fInitialSaveCount);
     281           0 :     this->restoreToCount(fInitialSaveCount);
     282           0 : }
     283             : 
     284           0 : size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkClipOp op) {
     285           0 :     if (fRestoreOffsetStack.isEmpty()) {
     286           0 :         return -1;
     287             :     }
     288             : 
     289             :     // The RestoreOffset field is initially filled with a placeholder
     290             :     // value that points to the offset of the previous RestoreOffset
     291             :     // in the current stack level, thus forming a linked list so that
     292             :     // the restore offsets can be filled in when the corresponding
     293             :     // restore command is recorded.
     294           0 :     int32_t prevOffset = fRestoreOffsetStack.top();
     295             : 
     296           0 :     if (clipOpExpands(op)) {
     297             :         // Run back through any previous clip ops, and mark their offset to
     298             :         // be 0, disabling their ability to trigger a jump-to-restore, otherwise
     299             :         // they could hide this clips ability to expand the clip (i.e. go from
     300             :         // empty to non-empty).
     301           0 :         this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
     302             : 
     303             :         // Reset the pointer back to the previous clip so that subsequent
     304             :         // restores don't overwrite the offsets we just cleared.
     305           0 :         prevOffset = 0;
     306             :     }
     307             : 
     308           0 :     size_t offset = fWriter.bytesWritten();
     309           0 :     this->addInt(prevOffset);
     310           0 :     fRestoreOffsetStack.top() = SkToU32(offset);
     311           0 :     return offset;
     312             : }
     313             : 
     314           0 : void SkPictureRecord::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
     315           0 :     this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
     316           0 :     this->INHERITED::onClipRect(rect, op, edgeStyle);
     317           0 : }
     318             : 
     319           0 : size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkClipOp op, bool doAA) {
     320             :     // id + rect + clip params
     321           0 :     size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
     322             :     // recordRestoreOffsetPlaceholder doesn't always write an offset
     323           0 :     if (!fRestoreOffsetStack.isEmpty()) {
     324             :         // + restore offset
     325           0 :         size += kUInt32Size;
     326             :     }
     327           0 :     size_t initialOffset = this->addDraw(CLIP_RECT, &size);
     328           0 :     this->addRect(rect);
     329           0 :     this->addInt(ClipParams_pack(op, doAA));
     330           0 :     size_t offset = this->recordRestoreOffsetPlaceholder(op);
     331             : 
     332           0 :     this->validate(initialOffset, size);
     333           0 :     return offset;
     334             : }
     335             : 
     336           0 : void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
     337           0 :     this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
     338           0 :     this->INHERITED::onClipRRect(rrect, op, edgeStyle);
     339           0 : }
     340             : 
     341           0 : size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
     342             :     // op + rrect + clip params
     343           0 :     size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
     344             :     // recordRestoreOffsetPlaceholder doesn't always write an offset
     345           0 :     if (!fRestoreOffsetStack.isEmpty()) {
     346             :         // + restore offset
     347           0 :         size += kUInt32Size;
     348             :     }
     349           0 :     size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
     350           0 :     this->addRRect(rrect);
     351           0 :     this->addInt(ClipParams_pack(op, doAA));
     352           0 :     size_t offset = recordRestoreOffsetPlaceholder(op);
     353           0 :     this->validate(initialOffset, size);
     354           0 :     return offset;
     355             : }
     356             : 
     357           0 : void SkPictureRecord::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
     358           0 :     int pathID = this->addPathToHeap(path);
     359           0 :     this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
     360           0 :     this->INHERITED::onClipPath(path, op, edgeStyle);
     361           0 : }
     362             : 
     363           0 : size_t SkPictureRecord::recordClipPath(int pathID, SkClipOp op, bool doAA) {
     364             :     // op + path index + clip params
     365           0 :     size_t size = 3 * kUInt32Size;
     366             :     // recordRestoreOffsetPlaceholder doesn't always write an offset
     367           0 :     if (!fRestoreOffsetStack.isEmpty()) {
     368             :         // + restore offset
     369           0 :         size += kUInt32Size;
     370             :     }
     371           0 :     size_t initialOffset = this->addDraw(CLIP_PATH, &size);
     372           0 :     this->addInt(pathID);
     373           0 :     this->addInt(ClipParams_pack(op, doAA));
     374           0 :     size_t offset = recordRestoreOffsetPlaceholder(op);
     375           0 :     this->validate(initialOffset, size);
     376           0 :     return offset;
     377             : }
     378             : 
     379           0 : void SkPictureRecord::onClipRegion(const SkRegion& region, SkClipOp op) {
     380           0 :     this->recordClipRegion(region, op);
     381           0 :     this->INHERITED::onClipRegion(region, op);
     382           0 : }
     383             : 
     384           0 : size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkClipOp op) {
     385             :     // op + clip params + region
     386           0 :     size_t size = 2 * kUInt32Size + region.writeToMemory(nullptr);
     387             :     // recordRestoreOffsetPlaceholder doesn't always write an offset
     388           0 :     if (!fRestoreOffsetStack.isEmpty()) {
     389             :         // + restore offset
     390           0 :         size += kUInt32Size;
     391             :     }
     392           0 :     size_t initialOffset = this->addDraw(CLIP_REGION, &size);
     393           0 :     this->addRegion(region);
     394           0 :     this->addInt(ClipParams_pack(op, false));
     395           0 :     size_t offset = this->recordRestoreOffsetPlaceholder(op);
     396             : 
     397           0 :     this->validate(initialOffset, size);
     398           0 :     return offset;
     399             : }
     400             : 
     401           0 : void SkPictureRecord::onDrawPaint(const SkPaint& paint) {
     402             :     // op + paint index
     403           0 :     size_t size = 2 * kUInt32Size;
     404           0 :     size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
     405           0 :     this->addPaint(paint);
     406           0 :     this->validate(initialOffset, size);
     407           0 : }
     408             : 
     409           0 : void SkPictureRecord::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
     410             :                                    const SkPaint& paint) {
     411           0 :     fContentInfo.onDrawPoints(count, paint);
     412             : 
     413             :     // op + paint index + mode + count + point data
     414           0 :     size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
     415           0 :     size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
     416           0 :     this->addPaint(paint);
     417             : 
     418           0 :     this->addInt(mode);
     419           0 :     this->addInt(SkToInt(count));
     420           0 :     fWriter.writeMul4(pts, count * sizeof(SkPoint));
     421           0 :     this->validate(initialOffset, size);
     422           0 : }
     423             : 
     424           0 : void SkPictureRecord::onDrawOval(const SkRect& oval, const SkPaint& paint) {
     425             :     // op + paint index + rect
     426           0 :     size_t size = 2 * kUInt32Size + sizeof(oval);
     427           0 :     size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
     428           0 :     this->addPaint(paint);
     429           0 :     this->addRect(oval);
     430           0 :     this->validate(initialOffset, size);
     431           0 : }
     432             : 
     433           0 : void SkPictureRecord::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
     434             :                                 bool useCenter, const SkPaint& paint) {
     435             :     // op + paint index + rect + start + sweep + bool (as int)
     436             :     size_t size = 2 * kUInt32Size + sizeof(oval) + sizeof(startAngle) + sizeof(sweepAngle) +
     437           0 :                   sizeof(int);
     438           0 :     size_t initialOffset = this->addDraw(DRAW_ARC, &size);
     439           0 :     this->addPaint(paint);
     440           0 :     this->addRect(oval);
     441           0 :     this->addScalar(startAngle);
     442           0 :     this->addScalar(sweepAngle);
     443           0 :     this->addInt(useCenter);
     444           0 :     this->validate(initialOffset, size);
     445           0 : }
     446             : 
     447           0 : void SkPictureRecord::onDrawRect(const SkRect& rect, const SkPaint& paint) {
     448             :     // op + paint index + rect
     449           0 :     size_t size = 2 * kUInt32Size + sizeof(rect);
     450           0 :     size_t initialOffset = this->addDraw(DRAW_RECT, &size);
     451           0 :     this->addPaint(paint);
     452           0 :     this->addRect(rect);
     453           0 :     this->validate(initialOffset, size);
     454           0 : }
     455             : 
     456           0 : void SkPictureRecord::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
     457             :     // op + paint index + region
     458           0 :     size_t regionBytes = region.writeToMemory(nullptr);
     459           0 :     size_t size = 2 * kUInt32Size + regionBytes;
     460           0 :     size_t initialOffset = this->addDraw(DRAW_REGION, &size);
     461           0 :     this->addPaint(paint);
     462           0 :     fWriter.writeRegion(region);
     463           0 :     this->validate(initialOffset, size);
     464           0 : }
     465             : 
     466           0 : void SkPictureRecord::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
     467             :     // op + paint index + rrect
     468           0 :     size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
     469           0 :     size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
     470           0 :     this->addPaint(paint);
     471           0 :     this->addRRect(rrect);
     472           0 :     this->validate(initialOffset, size);
     473           0 : }
     474             : 
     475           0 : void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
     476             :                                    const SkPaint& paint) {
     477             :     // op + paint index + rrects
     478           0 :     size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
     479           0 :     size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
     480           0 :     this->addPaint(paint);
     481           0 :     this->addRRect(outer);
     482           0 :     this->addRRect(inner);
     483           0 :     this->validate(initialOffset, size);
     484           0 : }
     485             : 
     486           0 : void SkPictureRecord::onDrawPath(const SkPath& path, const SkPaint& paint) {
     487           0 :     fContentInfo.onDrawPath(path, paint);
     488             : 
     489             :     // op + paint index + path index
     490           0 :     size_t size = 3 * kUInt32Size;
     491           0 :     size_t initialOffset = this->addDraw(DRAW_PATH, &size);
     492           0 :     this->addPaint(paint);
     493           0 :     this->addPath(path);
     494           0 :     this->validate(initialOffset, size);
     495           0 : }
     496             : 
     497           0 : void SkPictureRecord::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
     498             :                                   const SkPaint* paint) {
     499             :     // op + paint_index + image_index + x + y
     500           0 :     size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
     501           0 :     size_t initialOffset = this->addDraw(DRAW_IMAGE, &size);
     502           0 :     this->addPaintPtr(paint);
     503           0 :     this->addImage(image);
     504           0 :     this->addScalar(x);
     505           0 :     this->addScalar(y);
     506           0 :     this->validate(initialOffset, size);
     507           0 : }
     508             : 
     509           0 : void SkPictureRecord::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
     510             :                                       const SkPaint* paint, SrcRectConstraint constraint) {
     511             :     // id + paint_index + image_index + bool_for_src + constraint
     512           0 :     size_t size = 5 * kUInt32Size;
     513           0 :     if (src) {
     514           0 :         size += sizeof(*src);   // + rect
     515             :     }
     516           0 :     size += sizeof(dst);        // + rect
     517             : 
     518           0 :     size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
     519           0 :     this->addPaintPtr(paint);
     520           0 :     this->addImage(image);
     521           0 :     this->addRectPtr(src);  // may be null
     522           0 :     this->addRect(dst);
     523           0 :     this->addInt(constraint);
     524           0 :     this->validate(initialOffset, size);
     525           0 : }
     526             : 
     527           0 : void SkPictureRecord::onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst,
     528             :                                       const SkPaint* paint) {
     529             :     // id + paint_index + image_index + center + dst
     530           0 :     size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
     531             : 
     532           0 :     size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
     533           0 :     this->addPaintPtr(paint);
     534           0 :     this->addImage(img);
     535           0 :     this->addIRect(center);
     536           0 :     this->addRect(dst);
     537           0 :     this->validate(initialOffset, size);
     538           0 : }
     539             : 
     540           0 : void SkPictureRecord::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
     541             :                                          const SkRect& dst, const SkPaint* paint) {
     542             :     // xCount + xDivs + yCount+ yDivs
     543           0 :     int flagCount = (nullptr == lattice.fFlags) ? 0 : (lattice.fXCount + 1) * (lattice.fYCount + 1);
     544           0 :     size_t latticeSize = (1 + lattice.fXCount + 1 + lattice.fYCount + 1) * kUInt32Size +
     545           0 :                          SkAlign4(flagCount * sizeof(SkCanvas::Lattice::Flags)) + sizeof(SkIRect);
     546             : 
     547             :     // op + paint index + image index + lattice + dst rect
     548           0 :     size_t size = 3 * kUInt32Size + latticeSize + sizeof(dst);
     549           0 :     size_t initialOffset = this->addDraw(DRAW_IMAGE_LATTICE, &size);
     550           0 :     this->addPaintPtr(paint);
     551           0 :     this->addImage(image);
     552           0 :     this->addInt(lattice.fXCount);
     553           0 :     fWriter.writePad(lattice.fXDivs, lattice.fXCount * kUInt32Size);
     554           0 :     this->addInt(lattice.fYCount);
     555           0 :     fWriter.writePad(lattice.fYDivs, lattice.fYCount * kUInt32Size);
     556           0 :     this->addInt(flagCount);
     557           0 :     fWriter.writePad(lattice.fFlags, flagCount * sizeof(SkCanvas::Lattice::Flags));
     558           0 :     SkASSERT(lattice.fBounds);
     559           0 :     this->addIRect(*lattice.fBounds);
     560           0 :     this->addRect(dst);
     561           0 :     this->validate(initialOffset, size);
     562           0 : }
     563             : 
     564           0 : void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
     565             :                                  const SkPaint& paint) {
     566             :     // op + paint index + length + 'length' worth of chars + x + y
     567           0 :     size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
     568             : 
     569           0 :     DrawType op = DRAW_TEXT;
     570           0 :     size_t initialOffset = this->addDraw(op, &size);
     571           0 :     this->addPaint(paint);
     572           0 :     this->addText(text, byteLength);
     573           0 :     this->addScalar(x);
     574           0 :     this->addScalar(y);
     575           0 :     this->validate(initialOffset, size);
     576           0 : }
     577             : 
     578           0 : void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
     579             :                                     const SkPaint& paint) {
     580           0 :     int points = paint.countText(text, byteLength);
     581             : 
     582             :     // op + paint index + length + 'length' worth of data + num points + x&y point data
     583           0 :     size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
     584             : 
     585           0 :     DrawType op = DRAW_POS_TEXT;
     586             : 
     587           0 :     size_t initialOffset = this->addDraw(op, &size);
     588           0 :     this->addPaint(paint);
     589           0 :     this->addText(text, byteLength);
     590           0 :     this->addInt(points);
     591           0 :     fWriter.writeMul4(pos, points * sizeof(SkPoint));
     592           0 :     this->validate(initialOffset, size);
     593           0 : }
     594             : 
     595           0 : void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
     596             :                                      SkScalar constY, const SkPaint& paint) {
     597           0 :     int points = paint.countText(text, byteLength);
     598             : 
     599             :     // op + paint index + length + 'length' worth of data + num points
     600           0 :     size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
     601             :     // + y + the actual points
     602           0 :     size += 1 * kUInt32Size + points * sizeof(SkScalar);
     603             : 
     604           0 :     size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
     605           0 :     this->addPaint(paint);
     606           0 :     this->addText(text, byteLength);
     607           0 :     this->addInt(points);
     608           0 :     this->addScalar(constY);
     609           0 :     fWriter.writeMul4(xpos, points * sizeof(SkScalar));
     610           0 :     this->validate(initialOffset, size);
     611           0 : }
     612             : 
     613           0 : void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
     614             :                                        const SkMatrix* matrix, const SkPaint& paint) {
     615             :     // op + paint index + length + 'length' worth of data + path index + matrix
     616           0 :     const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
     617           0 :     size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(nullptr);
     618           0 :     size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
     619           0 :     this->addPaint(paint);
     620           0 :     this->addText(text, byteLength);
     621           0 :     this->addPath(path);
     622           0 :     this->addMatrix(m);
     623           0 :     this->validate(initialOffset, size);
     624           0 : }
     625             : 
     626           0 : void SkPictureRecord::onDrawTextRSXform(const void* text, size_t byteLength,
     627             :                                         const SkRSXform xform[], const SkRect* cull,
     628             :                                         const SkPaint& paint) {
     629           0 :     const int count = paint.countText(text, byteLength);
     630             :     // [op + paint-index + count + flags + length] + [text] + [xform] + cull
     631           0 :     size_t size = 5 * kUInt32Size + SkAlign4(byteLength) + count * sizeof(SkRSXform);
     632           0 :     uint32_t flags = 0;
     633           0 :     if (cull) {
     634           0 :         flags |= DRAW_TEXT_RSXFORM_HAS_CULL;
     635           0 :         size += sizeof(SkRect);
     636             :     }
     637             : 
     638           0 :     size_t initialOffset = this->addDraw(DRAW_TEXT_RSXFORM, &size);
     639           0 :     this->addPaint(paint);
     640           0 :     this->addInt(count);
     641           0 :     this->addInt(flags);
     642           0 :     this->addText(text, byteLength);
     643           0 :     fWriter.write(xform, count * sizeof(SkRSXform));
     644           0 :     if (cull) {
     645           0 :         fWriter.write(cull, sizeof(SkRect));
     646             :     }
     647           0 :     this->validate(initialOffset, size);
     648           0 : }
     649             : 
     650           0 : void SkPictureRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
     651             :                                      const SkPaint& paint) {
     652             : 
     653             :     // op + paint index + blob index + x/y
     654           0 :     size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
     655           0 :     size_t initialOffset = this->addDraw(DRAW_TEXT_BLOB, &size);
     656             : 
     657           0 :     this->addPaint(paint);
     658           0 :     this->addTextBlob(blob);
     659           0 :     this->addScalar(x);
     660           0 :     this->addScalar(y);
     661             : 
     662           0 :     this->validate(initialOffset, size);
     663           0 : }
     664             : 
     665           0 : void SkPictureRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
     666             :                                     const SkPaint* paint) {
     667             :     // op + picture index
     668           0 :     size_t size = 2 * kUInt32Size;
     669             :     size_t initialOffset;
     670             : 
     671           0 :     if (nullptr == matrix && nullptr == paint) {
     672           0 :         initialOffset = this->addDraw(DRAW_PICTURE, &size);
     673           0 :         this->addPicture(picture);
     674             :     } else {
     675           0 :         const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
     676           0 :         size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
     677           0 :         initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
     678           0 :         this->addPaintPtr(paint);
     679           0 :         this->addMatrix(m);
     680           0 :         this->addPicture(picture);
     681             :     }
     682           0 :     this->validate(initialOffset, size);
     683           0 : }
     684             : 
     685           0 : void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
     686             :                                             const SkMatrix* matrix,
     687             :                                             const SkPaint* paint,
     688             :                                             const SkShadowParams& params) {
     689             :     // op + picture index
     690           0 :     size_t size = 2 * kUInt32Size;
     691             :     size_t initialOffset;
     692             : 
     693             :     // TODO: handle recording params.
     694           0 :     if (nullptr == matrix && nullptr == paint) {
     695           0 :         initialOffset = this->addDraw(DRAW_PICTURE, &size);
     696           0 :         this->addPicture(picture);
     697             :     } else {
     698           0 :         const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
     699           0 :         size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
     700           0 :         initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
     701           0 :         this->addPaintPtr(paint);
     702           0 :         this->addMatrix(m);
     703           0 :         this->addPicture(picture);
     704             :     }
     705           0 :     this->validate(initialOffset, size);
     706           0 : }
     707             : 
     708           0 : void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
     709             :     // op + drawable index
     710           0 :     size_t size = 2 * kUInt32Size;
     711             :     size_t initialOffset;
     712             : 
     713           0 :     if (nullptr == matrix) {
     714           0 :         initialOffset = this->addDraw(DRAW_DRAWABLE, &size);
     715           0 :         this->addDrawable(drawable);
     716             :     } else {
     717           0 :         size += matrix->writeToMemory(nullptr);    // matrix
     718           0 :         initialOffset = this->addDraw(DRAW_DRAWABLE_MATRIX, &size);
     719           0 :         this->addMatrix(*matrix);
     720           0 :         this->addDrawable(drawable);
     721             :     }
     722           0 :     this->validate(initialOffset, size);
     723           0 : }
     724             : 
     725           0 : void SkPictureRecord::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
     726             :                                            const SkPaint& paint) {
     727             :     // op + paint index + vertices index + mode
     728           0 :     size_t size = 4 * kUInt32Size;
     729           0 :     size_t initialOffset = this->addDraw(DRAW_VERTICES_OBJECT, &size);
     730             : 
     731           0 :     this->addPaint(paint);
     732           0 :     this->addVertices(vertices);
     733           0 :     this->addInt(static_cast<uint32_t>(mode));
     734             : 
     735           0 :     this->validate(initialOffset, size);
     736           0 : }
     737             : 
     738           0 : void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
     739             :                                   const SkPoint texCoords[4], SkBlendMode bmode,
     740             :                                   const SkPaint& paint) {
     741             :     // op + paint index + patch 12 control points + flag + patch 4 colors + 4 texture coordinates
     742           0 :     size_t size = 2 * kUInt32Size + SkPatchUtils::kNumCtrlPts * sizeof(SkPoint) + kUInt32Size;
     743           0 :     uint32_t flag = 0;
     744           0 :     if (colors) {
     745           0 :         flag |= DRAW_VERTICES_HAS_COLORS;
     746           0 :         size += SkPatchUtils::kNumCorners * sizeof(SkColor);
     747             :     }
     748           0 :     if (texCoords) {
     749           0 :         flag |= DRAW_VERTICES_HAS_TEXS;
     750           0 :         size += SkPatchUtils::kNumCorners * sizeof(SkPoint);
     751             :     }
     752           0 :     if (SkBlendMode::kModulate != bmode) {
     753           0 :         flag |= DRAW_VERTICES_HAS_XFER;
     754           0 :         size += kUInt32Size;
     755             :     }
     756             : 
     757           0 :     size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
     758           0 :     this->addPaint(paint);
     759           0 :     this->addPatch(cubics);
     760           0 :     this->addInt(flag);
     761             : 
     762             :     // write optional parameters
     763           0 :     if (colors) {
     764           0 :         fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
     765             :     }
     766           0 :     if (texCoords) {
     767           0 :         fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint));
     768             :     }
     769           0 :     if (flag & DRAW_VERTICES_HAS_XFER) {
     770           0 :         this->addInt((int)bmode);
     771             :     }
     772           0 :     this->validate(initialOffset, size);
     773           0 : }
     774             : 
     775           0 : void SkPictureRecord::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
     776             :                                   const SkColor colors[], int count, SkBlendMode mode,
     777             :                                   const SkRect* cull, const SkPaint* paint) {
     778             :     // [op + paint-index + atlas-index + flags + count] + [xform] + [tex] + [*colors + mode] + cull
     779           0 :     size_t size = 5 * kUInt32Size + count * sizeof(SkRSXform) + count * sizeof(SkRect);
     780           0 :     uint32_t flags = 0;
     781           0 :     if (colors) {
     782           0 :         flags |= DRAW_ATLAS_HAS_COLORS;
     783           0 :         size += count * sizeof(SkColor);
     784           0 :         size += sizeof(uint32_t);   // xfermode::mode
     785             :     }
     786           0 :     if (cull) {
     787           0 :         flags |= DRAW_ATLAS_HAS_CULL;
     788           0 :         size += sizeof(SkRect);
     789             :     }
     790             : 
     791           0 :     size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
     792           0 :     this->addPaintPtr(paint);
     793           0 :     this->addImage(atlas);
     794           0 :     this->addInt(flags);
     795           0 :     this->addInt(count);
     796           0 :     fWriter.write(xform, count * sizeof(SkRSXform));
     797           0 :     fWriter.write(tex, count * sizeof(SkRect));
     798             : 
     799             :     // write optional parameters
     800           0 :     if (colors) {
     801           0 :         fWriter.write(colors, count * sizeof(SkColor));
     802           0 :         this->addInt((int)mode);
     803             :     }
     804           0 :     if (cull) {
     805           0 :         fWriter.write(cull, sizeof(SkRect));
     806             :     }
     807           0 :     this->validate(initialOffset, size);
     808           0 : }
     809             : 
     810           0 : void SkPictureRecord::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
     811           0 :     size_t keyLen = fWriter.WriteStringSize(key);
     812           0 :     size_t valueLen = fWriter.WriteDataSize(value);
     813           0 :     size_t size = 4 + sizeof(SkRect) + keyLen + valueLen;
     814             : 
     815           0 :     size_t initialOffset = this->addDraw(DRAW_ANNOTATION, &size);
     816           0 :     this->addRect(rect);
     817           0 :     fWriter.writeString(key);
     818           0 :     fWriter.writeData(value);
     819           0 :     this->validate(initialOffset, size);
     820           0 : }
     821             : 
     822             : ///////////////////////////////////////////////////////////////////////////////
     823             : 
     824           0 : template <typename T> int find_or_append_uniqueID(SkTDArray<const T*>& array, const T* obj) {
     825           0 :     int index = array.select([&](const T* elem) {
     826           0 :         return elem->uniqueID() == obj->uniqueID();
     827           0 :     });
     828           0 :     if (index < 0) {
     829           0 :         index = array.count();
     830           0 :         *array.append() = SkRef(obj);
     831             :     }
     832           0 :     return index;
     833             : }
     834             : 
     835           0 : sk_sp<SkSurface> SkPictureRecord::onNewSurface(const SkImageInfo& info, const SkSurfaceProps&) {
     836           0 :     return nullptr;
     837             : }
     838             : 
     839           0 : void SkPictureRecord::addImage(const SkImage* image) {
     840             :     // convention for images is 0-based index
     841           0 :     this->addInt(find_or_append_uniqueID(fImageRefs, image));
     842           0 : }
     843             : 
     844           0 : void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
     845           0 :     fWriter.writeMatrix(matrix);
     846           0 : }
     847             : 
     848           0 : void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
     849           0 :     fContentInfo.onAddPaintPtr(paint);
     850             : 
     851           0 :     if (paint) {
     852           0 :         fPaints.push_back(*paint);
     853           0 :         this->addInt(fPaints.count());
     854             :     } else {
     855           0 :         this->addInt(0);
     856             :     }
     857           0 : }
     858             : 
     859           0 : int SkPictureRecord::addPathToHeap(const SkPath& path) {
     860           0 :     if (int* n = fPaths.find(path)) {
     861           0 :         return *n;
     862             :     }
     863           0 :     int n = fPaths.count() + 1;  // 0 is reserved for null / error.
     864           0 :     fPaths.set(path, n);
     865           0 :     return n;
     866             : }
     867             : 
     868           0 : void SkPictureRecord::addPath(const SkPath& path) {
     869           0 :     this->addInt(this->addPathToHeap(path));
     870           0 : }
     871             : 
     872           0 : void SkPictureRecord::addPatch(const SkPoint cubics[12]) {
     873           0 :     fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint));
     874           0 : }
     875             : 
     876           0 : void SkPictureRecord::addPicture(const SkPicture* picture) {
     877             :     // follow the convention of recording a 1-based index
     878           0 :     this->addInt(find_or_append_uniqueID(fPictureRefs, picture) + 1);
     879           0 : }
     880             : 
     881           0 : void SkPictureRecord::addDrawable(SkDrawable* drawable) {
     882           0 :     int index = fDrawableRefs.find(drawable);
     883           0 :     if (index < 0) {    // not found
     884           0 :         index = fDrawableRefs.count();
     885           0 :         *fDrawableRefs.append() = drawable;
     886           0 :         drawable->ref();
     887             :     }
     888             :     // follow the convention of recording a 1-based index
     889           0 :     this->addInt(index + 1);
     890           0 : }
     891             : 
     892           0 : void SkPictureRecord::addPoint(const SkPoint& point) {
     893           0 :     fWriter.writePoint(point);
     894           0 : }
     895             : 
     896           0 : void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
     897           0 :     fWriter.writeMul4(pts, count * sizeof(SkPoint));
     898           0 : }
     899             : 
     900           0 : void SkPictureRecord::addNoOp() {
     901           0 :     size_t size = kUInt32Size; // op
     902           0 :     this->addDraw(NOOP, &size);
     903           0 : }
     904             : 
     905           0 : void SkPictureRecord::addRect(const SkRect& rect) {
     906           0 :     fWriter.writeRect(rect);
     907           0 : }
     908             : 
     909           0 : void SkPictureRecord::addRectPtr(const SkRect* rect) {
     910           0 :     if (fWriter.writeBool(rect != nullptr)) {
     911           0 :         fWriter.writeRect(*rect);
     912             :     }
     913           0 : }
     914             : 
     915           0 : void SkPictureRecord::addIRect(const SkIRect& rect) {
     916           0 :     fWriter.write(&rect, sizeof(rect));
     917           0 : }
     918             : 
     919           0 : void SkPictureRecord::addIRectPtr(const SkIRect* rect) {
     920           0 :     if (fWriter.writeBool(rect != nullptr)) {
     921           0 :         *(SkIRect*)fWriter.reserve(sizeof(SkIRect)) = *rect;
     922             :     }
     923           0 : }
     924             : 
     925           0 : void SkPictureRecord::addRRect(const SkRRect& rrect) {
     926           0 :     fWriter.writeRRect(rrect);
     927           0 : }
     928             : 
     929           0 : void SkPictureRecord::addRegion(const SkRegion& region) {
     930           0 :     fWriter.writeRegion(region);
     931           0 : }
     932             : 
     933           0 : void SkPictureRecord::addText(const void* text, size_t byteLength) {
     934           0 :     fContentInfo.onDrawText();
     935           0 :     addInt(SkToInt(byteLength));
     936           0 :     fWriter.writePad(text, byteLength);
     937           0 : }
     938             : 
     939           0 : void SkPictureRecord::addTextBlob(const SkTextBlob* blob) {
     940             :     // follow the convention of recording a 1-based index
     941           0 :     this->addInt(find_or_append_uniqueID(fTextBlobRefs, blob) + 1);
     942           0 : }
     943             : 
     944           0 : void SkPictureRecord::addVertices(const SkVertices* vertices) {
     945             :     // follow the convention of recording a 1-based index
     946           0 :     this->addInt(find_or_append_uniqueID(fVerticesRefs, vertices) + 1);
     947           0 : }
     948             : 
     949             : ///////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.13