1 2 /* 3 * Copyright 2011 Google Inc. 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 #include "SkAnnotation.h" 10 #include "SkBitmapDevice.h" 11 #include "SkBitmapHeap.h" 12 #include "SkCanvas.h" 13 #include "SkColorFilter.h" 14 #include "SkData.h" 15 #include "SkDrawLooper.h" 16 #include "SkGPipe.h" 17 #include "SkGPipePriv.h" 18 #include "SkImageFilter.h" 19 #include "SkMaskFilter.h" 20 #include "SkWriteBuffer.h" 21 #include "SkPaint.h" 22 #include "SkPatchUtils.h" 23 #include "SkPathEffect.h" 24 #include "SkPictureFlat.h" 25 #include "SkPtrRecorder.h" 26 #include "SkRasterizer.h" 27 #include "SkRRect.h" 28 #include "SkShader.h" 29 #include "SkStream.h" 30 #include "SkTextBlob.h" 31 #include "SkTSearch.h" 32 #include "SkTypeface.h" 33 #include "SkWriter32.h" 34 35 enum { 36 kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector) 37 }; 38 39 static bool is_cross_process(uint32_t flags) { 40 return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag); 41 } 42 43 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { 44 SkASSERT(paintFlat < kCount_PaintFlats); 45 switch (paintFlat) { 46 case kColorFilter_PaintFlat: return paint.getColorFilter(); 47 case kDrawLooper_PaintFlat: return paint.getLooper(); 48 case kMaskFilter_PaintFlat: return paint.getMaskFilter(); 49 case kPathEffect_PaintFlat: return paint.getPathEffect(); 50 case kRasterizer_PaintFlat: return paint.getRasterizer(); 51 case kShader_PaintFlat: return paint.getShader(); 52 case kImageFilter_PaintFlat: return paint.getImageFilter(); 53 case kXfermode_PaintFlat: return paint.getXfermode(); 54 } 55 SkDEBUGFAIL("never gets here"); 56 return NULL; 57 } 58 59 static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) { 60 SkASSERT(typeface); 61 SkDynamicMemoryWStream stream; 62 typeface->serialize(&stream); 63 size_t size = stream.getOffset(); 64 if (writer) { 65 writer->write32(SkToU32(size)); 66 SkAutoDataUnref data(stream.copyToData()); 67 writer->writePad(data->data(), size); 68 } 69 return 4 + SkAlign4(size); 70 } 71 72 /////////////////////////////////////////////////////////////////////////////// 73 74 class FlattenableHeap : public SkFlatController { 75 public: 76 FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess) 77 : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0) 78 , fNumFlatsToKeep(numFlatsToKeep) { 79 SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset)); 80 if (isCrossProcess) { 81 this->setNamedFactorySet(fset); 82 } 83 } 84 85 ~FlattenableHeap() { 86 fPointers.freeAll(); 87 } 88 89 virtual void* allocThrow(size_t bytes) SK_OVERRIDE; 90 91 virtual void unalloc(void* ptr) SK_OVERRIDE; 92 93 void setBitmapStorage(SkBitmapHeap* heap) { 94 this->setBitmapHeap(heap); 95 } 96 97 const SkFlatData* flatToReplace() const; 98 99 // Mark an SkFlatData as one that should not be returned by flatToReplace. 100 // Takes the result of SkFlatData::index() as its parameter. 101 void markFlatForKeeping(int index) { 102 *fFlatsThatMustBeKept.append() = index; 103 } 104 105 void markAllFlatsSafeToDelete() { 106 fFlatsThatMustBeKept.reset(); 107 } 108 109 private: 110 // Keep track of the indices (i.e. the result of SkFlatData::index()) of 111 // flats that must be kept, since they are on the current paint. 112 SkTDArray<int> fFlatsThatMustBeKept; 113 SkTDArray<void*> fPointers; 114 const int fNumFlatsToKeep; 115 116 typedef SkFlatController INHERITED; 117 }; 118 119 void FlattenableHeap::unalloc(void* ptr) { 120 int indexToRemove = fPointers.rfind(ptr); 121 if (indexToRemove >= 0) { 122 sk_free(ptr); 123 fPointers.remove(indexToRemove); 124 } 125 } 126 127 void* FlattenableHeap::allocThrow(size_t bytes) { 128 void* ptr = sk_malloc_throw(bytes); 129 *fPointers.append() = ptr; 130 return ptr; 131 } 132 133 const SkFlatData* FlattenableHeap::flatToReplace() const { 134 // First, determine whether we should replace one. 135 if (fPointers.count() > fNumFlatsToKeep) { 136 // Look through the flattenable heap. 137 // TODO: Return the LRU flat. 138 for (int i = 0; i < fPointers.count(); i++) { 139 SkFlatData* potential = (SkFlatData*)fPointers[i]; 140 // Make sure that it is not one that must be kept. 141 bool mustKeep = false; 142 for (int j = 0; j < fFlatsThatMustBeKept.count(); j++) { 143 if (potential->index() == fFlatsThatMustBeKept[j]) { 144 mustKeep = true; 145 break; 146 } 147 } 148 if (!mustKeep) { 149 return potential; 150 } 151 } 152 } 153 return NULL; 154 } 155 156 /////////////////////////////////////////////////////////////////////////////// 157 158 struct SkFlattenableTraits { 159 static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) { 160 buffer.writeFlattenable(&flattenable); 161 } 162 // No need to define unflatten if we never call it. 163 }; 164 typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary; 165 166 /////////////////////////////////////////////////////////////////////////////// 167 168 /** 169 * If SkBitmaps are to be flattened to send to the reader, this class is 170 * provided to the SkBitmapHeap to tell the SkGPipeCanvas to do so. 171 */ 172 class BitmapShuttle : public SkBitmapHeap::ExternalStorage { 173 public: 174 BitmapShuttle(SkGPipeCanvas*); 175 176 ~BitmapShuttle(); 177 178 virtual bool insert(const SkBitmap& bitmap, int32_t slot) SK_OVERRIDE; 179 180 /** 181 * Remove the SkGPipeCanvas used for insertion. After this, calls to 182 * insert will crash. 183 */ 184 void removeCanvas(); 185 186 private: 187 SkGPipeCanvas* fCanvas; 188 }; 189 190 /////////////////////////////////////////////////////////////////////////////// 191 192 class SkGPipeCanvas : public SkCanvas { 193 public: 194 SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, 195 uint32_t width, uint32_t height); 196 virtual ~SkGPipeCanvas(); 197 198 /** 199 * Called when nothing else is to be written to the stream. Any repeated 200 * calls are ignored. 201 * 202 * @param notifyReaders Whether to send a message to the reader(s) that 203 * the writer is through sending commands. Should generally be true, 204 * unless there is an error which prevents further messages from 205 * being sent. 206 */ 207 void finish(bool notifyReaders) { 208 if (fDone) { 209 return; 210 } 211 if (notifyReaders && this->needOpBytes()) { 212 this->writeOp(kDone_DrawOp); 213 this->doNotify(); 214 } 215 if (shouldFlattenBitmaps(fFlags)) { 216 // The following circular references exist: 217 // fFlattenableHeap -> fWriteBuffer -> fBitmapStorage -> fExternalStorage -> fCanvas 218 // fBitmapHeap -> fExternalStorage -> fCanvas 219 // fFlattenableHeap -> fBitmapStorage -> fExternalStorage -> fCanvas 220 221 // Break them all by destroying the final link to this SkGPipeCanvas. 222 fBitmapShuttle->removeCanvas(); 223 } 224 fDone = true; 225 } 226 227 void flushRecording(bool detachCurrentBlock); 228 size_t freeMemoryIfPossible(size_t bytesToFree); 229 230 size_t storageAllocatedForRecording() { 231 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->bytesAllocated(); 232 } 233 234 // overrides from SkCanvas 235 virtual bool isDrawingToLayer() const SK_OVERRIDE; 236 virtual void clear(SkColor) SK_OVERRIDE; 237 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; 238 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 239 const SkPaint&) SK_OVERRIDE; 240 virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; 241 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE; 242 virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; 243 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; 244 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 245 const SkPaint*) SK_OVERRIDE; 246 virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, 247 const SkRect& dst, const SkPaint* paint, 248 DrawBitmapRectFlags flags) SK_OVERRIDE; 249 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 250 const SkPaint*) SK_OVERRIDE; 251 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 252 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; 253 virtual void drawSprite(const SkBitmap&, int left, int top, 254 const SkPaint*) SK_OVERRIDE; 255 virtual void drawVertices(VertexMode, int vertexCount, 256 const SkPoint vertices[], const SkPoint texs[], 257 const SkColor colors[], SkXfermode*, 258 const uint16_t indices[], int indexCount, 259 const SkPaint&) SK_OVERRIDE; 260 virtual void drawData(const void*, size_t) SK_OVERRIDE; 261 virtual void beginCommentGroup(const char* description) SK_OVERRIDE; 262 virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; 263 virtual void endCommentGroup() SK_OVERRIDE; 264 265 /** 266 * Flatten an SkBitmap to send to the reader, where it will be referenced 267 * according to slot. 268 */ 269 bool shuttleBitmap(const SkBitmap&, int32_t slot); 270 271 protected: 272 virtual void willSave() SK_OVERRIDE; 273 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE; 274 virtual void willRestore() SK_OVERRIDE; 275 276 virtual void didConcat(const SkMatrix&) SK_OVERRIDE; 277 virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE; 278 279 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE; 280 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 281 const SkPaint&) SK_OVERRIDE; 282 virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 283 const SkPaint&) SK_OVERRIDE; 284 virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 285 SkScalar constY, const SkPaint&) SK_OVERRIDE; 286 virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 287 const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE; 288 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 289 const SkPaint& paint) SK_OVERRIDE; 290 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 291 const SkPoint texCoords[4], SkXfermode* xmode, 292 const SkPaint& paint) SK_OVERRIDE; 293 virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 294 virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 295 virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; 296 virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE; 297 298 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) SK_OVERRIDE; 299 300 private: 301 void recordTranslate(const SkMatrix&); 302 void recordScale(const SkMatrix&); 303 void recordConcat(const SkMatrix&); 304 305 enum { 306 kNoSaveLayer = -1, 307 }; 308 SkNamedFactorySet* fFactorySet; 309 int fFirstSaveLayerStackLevel; 310 SkBitmapHeap* fBitmapHeap; 311 SkGPipeController* fController; 312 SkWriter32& fWriter; 313 size_t fBlockSize; // amount allocated for writer 314 size_t fBytesNotified; 315 bool fDone; 316 const uint32_t fFlags; 317 318 SkRefCntSet fTypefaceSet; 319 320 uint32_t getTypefaceID(SkTypeface*); 321 322 inline void writeOp(DrawOps op, unsigned flags, unsigned data) { 323 fWriter.write32(DrawOp_packOpFlagData(op, flags, data)); 324 } 325 326 inline void writeOp(DrawOps op) { 327 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0)); 328 } 329 330 bool needOpBytes(size_t size = 0); 331 332 inline void doNotify() { 333 if (!fDone) { 334 size_t bytes = fWriter.bytesWritten() - fBytesNotified; 335 if (bytes > 0) { 336 fController->notifyWritten(bytes); 337 fBytesNotified += bytes; 338 } 339 } 340 } 341 342 typedef SkAutoSTMalloc<128, uint8_t> TypefaceBuffer; 343 size_t getInProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuffer*); 344 size_t getCrossProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuffer*); 345 346 // Should be called after any calls to an SkFlatDictionary::findAndReplace 347 // if a new SkFlatData was added when in cross process mode 348 void flattenFactoryNames(); 349 350 FlattenableHeap fFlattenableHeap; 351 FlatDictionary fFlatDictionary; 352 SkAutoTUnref<BitmapShuttle> fBitmapShuttle; 353 int fCurrFlatIndex[kCount_PaintFlats]; 354 355 int flattenToIndex(SkFlattenable* obj, PaintFlats); 356 357 // Common code used by drawBitmap*. Behaves differently depending on the 358 // type of SkBitmapHeap being used, which is determined by the flags used. 359 bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, 360 size_t opBytesNeeded, const SkPaint* paint); 361 362 SkPaint fPaint; 363 void writePaint(const SkPaint&); 364 365 class AutoPipeNotify { 366 public: 367 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {} 368 ~AutoPipeNotify() { fCanvas->doNotify(); } 369 private: 370 SkGPipeCanvas* fCanvas; 371 }; 372 friend class AutoPipeNotify; 373 374 typedef SkCanvas INHERITED; 375 }; 376 377 void SkGPipeCanvas::flattenFactoryNames() { 378 const char* name; 379 while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) { 380 size_t len = strlen(name); 381 if (this->needOpBytes(SkWriter32::WriteStringSize(name, len))) { 382 this->writeOp(kDef_Factory_DrawOp); 383 fWriter.writeString(name, len); 384 } 385 } 386 } 387 388 bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) { 389 SkASSERT(shouldFlattenBitmaps(fFlags)); 390 SkWriteBuffer buffer; 391 buffer.setNamedFactoryRecorder(fFactorySet); 392 buffer.writeBitmap(bm); 393 this->flattenFactoryNames(); 394 size_t size = buffer.bytesWritten(); 395 if (this->needOpBytes(size)) { 396 this->writeOp(kDef_Bitmap_DrawOp, 0, slot); 397 void* dst = static_cast<void*>(fWriter.reserve(size)); 398 buffer.writeToMemory(dst); 399 return true; 400 } 401 return false; 402 } 403 404 // return 0 for NULL (or unflattenable obj), or index-base-1 405 // return ~(index-base-1) if an old flattenable was replaced 406 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) { 407 SkASSERT(!fDone && fBitmapHeap != NULL); 408 if (NULL == obj) { 409 return 0; 410 } 411 412 fBitmapHeap->deferAddingOwners(); 413 bool added, replaced; 414 const SkFlatData* flat = fFlatDictionary.findAndReplace(*obj, fFlattenableHeap.flatToReplace(), 415 &added, &replaced); 416 fBitmapHeap->endAddingOwnersDeferral(added); 417 int index = flat->index(); 418 if (added) { 419 if (is_cross_process(fFlags)) { 420 this->flattenFactoryNames(); 421 } 422 size_t flatSize = flat->flatSize(); 423 if (this->needOpBytes(flatSize)) { 424 this->writeOp(kDef_Flattenable_DrawOp, paintflat, index); 425 fWriter.write(flat->data(), flatSize); 426 } 427 } 428 if (replaced) { 429 index = ~index; 430 } 431 return index; 432 } 433 434 /////////////////////////////////////////////////////////////////////////////// 435 436 #define MIN_BLOCK_SIZE (16 * 1024) 437 #define BITMAPS_TO_KEEP 5 438 #define FLATTENABLES_TO_KEEP 10 439 440 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, 441 SkWriter32* writer, uint32_t flags, 442 uint32_t width, uint32_t height) 443 : SkCanvas(width, height) 444 , fFactorySet(is_cross_process(flags) ? SkNEW(SkNamedFactorySet) : NULL) 445 , fWriter(*writer) 446 , fFlags(flags) 447 , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, is_cross_process(flags)) 448 , fFlatDictionary(&fFlattenableHeap) 449 { 450 fController = controller; 451 fDone = false; 452 fBlockSize = 0; // need first block from controller 453 fBytesNotified = 0; 454 fFirstSaveLayerStackLevel = kNoSaveLayer; 455 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); 456 457 // Tell the reader the appropriate flags to use. 458 if (this->needOpBytes()) { 459 this->writeOp(kReportFlags_DrawOp, fFlags, 0); 460 } 461 462 if (shouldFlattenBitmaps(flags)) { 463 fBitmapShuttle.reset(SkNEW_ARGS(BitmapShuttle, (this))); 464 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, (fBitmapShuttle.get(), BITMAPS_TO_KEEP)); 465 } else { 466 fBitmapHeap = SkNEW_ARGS(SkBitmapHeap, 467 (BITMAPS_TO_KEEP, controller->numberOfReaders())); 468 if (this->needOpBytes(sizeof(void*))) { 469 this->writeOp(kShareBitmapHeap_DrawOp); 470 fWriter.writePtr(static_cast<void*>(fBitmapHeap)); 471 } 472 } 473 fFlattenableHeap.setBitmapStorage(fBitmapHeap); 474 this->doNotify(); 475 } 476 477 SkGPipeCanvas::~SkGPipeCanvas() { 478 this->finish(true); 479 SkSafeUnref(fFactorySet); 480 SkSafeUnref(fBitmapHeap); 481 } 482 483 bool SkGPipeCanvas::needOpBytes(size_t needed) { 484 if (fDone) { 485 return false; 486 } 487 488 needed += 4; // size of DrawOp atom 489 needed = SkAlign4(needed); 490 if (fWriter.bytesWritten() + needed > fBlockSize) { 491 // Before we wipe out any data that has already been written, read it out. 492 this->doNotify(); 493 494 // If we're going to allocate a new block, allocate enough to make it worthwhile. 495 needed = SkTMax<size_t>(MIN_BLOCK_SIZE, needed); 496 497 void* block = fController->requestBlock(needed, &fBlockSize); 498 if (NULL == block) { 499 // Do not notify the readers, which would call this function again. 500 this->finish(false); 501 return false; 502 } 503 SkASSERT(SkIsAlign4(fBlockSize)); 504 fWriter.reset(block, fBlockSize); 505 fBytesNotified = 0; 506 } 507 return true; 508 } 509 510 uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { 511 uint32_t id = 0; // 0 means default/null typeface 512 if (face) { 513 id = fTypefaceSet.find(face); 514 if (0 == id) { 515 id = fTypefaceSet.add(face); 516 size_t size = writeTypeface(NULL, face); 517 if (this->needOpBytes(size)) { 518 this->writeOp(kDef_Typeface_DrawOp); 519 writeTypeface(&fWriter, face); 520 } 521 } 522 } 523 return id; 524 } 525 526 /////////////////////////////////////////////////////////////////////////////// 527 528 #define NOTIFY_SETUP(canvas) \ 529 AutoPipeNotify apn(canvas) 530 531 void SkGPipeCanvas::willSave() { 532 NOTIFY_SETUP(this); 533 if (this->needOpBytes()) { 534 this->writeOp(kSave_DrawOp); 535 } 536 537 this->INHERITED::willSave(); 538 } 539 540 SkCanvas::SaveLayerStrategy SkGPipeCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint, 541 SaveFlags saveFlags) { 542 NOTIFY_SETUP(this); 543 size_t size = 0; 544 unsigned opFlags = 0; 545 546 if (bounds) { 547 opFlags |= kSaveLayer_HasBounds_DrawOpFlag; 548 size += sizeof(SkRect); 549 } 550 if (paint) { 551 opFlags |= kSaveLayer_HasPaint_DrawOpFlag; 552 this->writePaint(*paint); 553 } 554 555 if (this->needOpBytes(size)) { 556 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags); 557 if (bounds) { 558 fWriter.writeRect(*bounds); 559 } 560 } 561 562 if (kNoSaveLayer == fFirstSaveLayerStackLevel){ 563 fFirstSaveLayerStackLevel = this->getSaveCount(); 564 } 565 566 this->INHERITED::willSaveLayer(bounds, paint, saveFlags); 567 // we don't create a layer 568 return kNoLayer_SaveLayerStrategy; 569 } 570 571 void SkGPipeCanvas::willRestore() { 572 NOTIFY_SETUP(this); 573 if (this->needOpBytes()) { 574 this->writeOp(kRestore_DrawOp); 575 } 576 577 if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){ 578 fFirstSaveLayerStackLevel = kNoSaveLayer; 579 } 580 581 this->INHERITED::willRestore(); 582 } 583 584 bool SkGPipeCanvas::isDrawingToLayer() const { 585 return kNoSaveLayer != fFirstSaveLayerStackLevel; 586 } 587 588 void SkGPipeCanvas::recordTranslate(const SkMatrix& m) { 589 if (this->needOpBytes(2 * sizeof(SkScalar))) { 590 this->writeOp(kTranslate_DrawOp); 591 fWriter.writeScalar(m.getTranslateX()); 592 fWriter.writeScalar(m.getTranslateY()); 593 } 594 } 595 596 void SkGPipeCanvas::recordScale(const SkMatrix& m) { 597 if (this->needOpBytes(2 * sizeof(SkScalar))) { 598 this->writeOp(kScale_DrawOp); 599 fWriter.writeScalar(m.getScaleX()); 600 fWriter.writeScalar(m.getScaleY()); 601 } 602 } 603 604 void SkGPipeCanvas::recordConcat(const SkMatrix& m) { 605 if (this->needOpBytes(m.writeToMemory(NULL))) { 606 this->writeOp(kConcat_DrawOp); 607 fWriter.writeMatrix(m); 608 } 609 } 610 611 void SkGPipeCanvas::didConcat(const SkMatrix& matrix) { 612 if (!matrix.isIdentity()) { 613 NOTIFY_SETUP(this); 614 switch (matrix.getType()) { 615 case SkMatrix::kTranslate_Mask: 616 this->recordTranslate(matrix); 617 break; 618 case SkMatrix::kScale_Mask: 619 this->recordScale(matrix); 620 break; 621 default: 622 this->recordConcat(matrix); 623 break; 624 } 625 } 626 627 this->INHERITED::didConcat(matrix); 628 } 629 630 void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) { 631 NOTIFY_SETUP(this); 632 if (this->needOpBytes(matrix.writeToMemory(NULL))) { 633 this->writeOp(kSetMatrix_DrawOp); 634 fWriter.writeMatrix(matrix); 635 } 636 this->INHERITED::didSetMatrix(matrix); 637 } 638 639 void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp, 640 ClipEdgeStyle edgeStyle) { 641 NOTIFY_SETUP(this); 642 if (this->needOpBytes(sizeof(SkRect))) { 643 unsigned flags = 0; 644 if (kSoft_ClipEdgeStyle == edgeStyle) { 645 flags = kClip_HasAntiAlias_DrawOpFlag; 646 } 647 this->writeOp(kClipRect_DrawOp, flags, rgnOp); 648 fWriter.writeRect(rect); 649 } 650 this->INHERITED::onClipRect(rect, rgnOp, edgeStyle); 651 } 652 653 void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp, 654 ClipEdgeStyle edgeStyle) { 655 NOTIFY_SETUP(this); 656 if (this->needOpBytes(kSizeOfFlatRRect)) { 657 unsigned flags = 0; 658 if (kSoft_ClipEdgeStyle == edgeStyle) { 659 flags = kClip_HasAntiAlias_DrawOpFlag; 660 } 661 this->writeOp(kClipRRect_DrawOp, flags, rgnOp); 662 fWriter.writeRRect(rrect); 663 } 664 this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle); 665 } 666 667 void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp, 668 ClipEdgeStyle edgeStyle) { 669 NOTIFY_SETUP(this); 670 if (this->needOpBytes(path.writeToMemory(NULL))) { 671 unsigned flags = 0; 672 if (kSoft_ClipEdgeStyle == edgeStyle) { 673 flags = kClip_HasAntiAlias_DrawOpFlag; 674 } 675 this->writeOp(kClipPath_DrawOp, flags, rgnOp); 676 fWriter.writePath(path); 677 } 678 // we just pass on the bounds of the path 679 this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle); 680 } 681 682 void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) { 683 NOTIFY_SETUP(this); 684 if (this->needOpBytes(region.writeToMemory(NULL))) { 685 this->writeOp(kClipRegion_DrawOp, 0, rgnOp); 686 fWriter.writeRegion(region); 687 } 688 this->INHERITED::onClipRegion(region, rgnOp); 689 } 690 691 /////////////////////////////////////////////////////////////////////////////// 692 693 void SkGPipeCanvas::clear(SkColor color) { 694 NOTIFY_SETUP(this); 695 unsigned flags = 0; 696 if (color) { 697 flags |= kClear_HasColor_DrawOpFlag; 698 } 699 if (this->needOpBytes(sizeof(SkColor))) { 700 this->writeOp(kDrawClear_DrawOp, flags, 0); 701 if (color) { 702 fWriter.write32(color); 703 } 704 } 705 } 706 707 void SkGPipeCanvas::drawPaint(const SkPaint& paint) { 708 NOTIFY_SETUP(this); 709 this->writePaint(paint); 710 if (this->needOpBytes()) { 711 this->writeOp(kDrawPaint_DrawOp); 712 } 713 } 714 715 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count, 716 const SkPoint pts[], const SkPaint& paint) { 717 if (count) { 718 NOTIFY_SETUP(this); 719 this->writePaint(paint); 720 if (this->needOpBytes(4 + count * sizeof(SkPoint))) { 721 this->writeOp(kDrawPoints_DrawOp, mode, 0); 722 fWriter.write32(SkToU32(count)); 723 fWriter.write(pts, count * sizeof(SkPoint)); 724 } 725 } 726 } 727 728 void SkGPipeCanvas::drawOval(const SkRect& rect, const SkPaint& paint) { 729 NOTIFY_SETUP(this); 730 this->writePaint(paint); 731 if (this->needOpBytes(sizeof(SkRect))) { 732 this->writeOp(kDrawOval_DrawOp); 733 fWriter.writeRect(rect); 734 } 735 } 736 737 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 738 NOTIFY_SETUP(this); 739 this->writePaint(paint); 740 if (this->needOpBytes(sizeof(SkRect))) { 741 this->writeOp(kDrawRect_DrawOp); 742 fWriter.writeRect(rect); 743 } 744 } 745 746 void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 747 NOTIFY_SETUP(this); 748 this->writePaint(paint); 749 if (this->needOpBytes(kSizeOfFlatRRect)) { 750 this->writeOp(kDrawRRect_DrawOp); 751 fWriter.writeRRect(rrect); 752 } 753 } 754 755 void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 756 const SkPaint& paint) { 757 NOTIFY_SETUP(this); 758 this->writePaint(paint); 759 if (this->needOpBytes(kSizeOfFlatRRect * 2)) { 760 this->writeOp(kDrawDRRect_DrawOp); 761 fWriter.writeRRect(outer); 762 fWriter.writeRRect(inner); 763 } 764 } 765 766 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 767 NOTIFY_SETUP(this); 768 this->writePaint(paint); 769 if (this->needOpBytes(path.writeToMemory(NULL))) { 770 this->writeOp(kDrawPath_DrawOp); 771 fWriter.writePath(path); 772 } 773 } 774 775 bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, 776 unsigned flags, 777 size_t opBytesNeeded, 778 const SkPaint* paint) { 779 if (fDone) { 780 return false; 781 } 782 783 if (paint != NULL) { 784 flags |= kDrawBitmap_HasPaint_DrawOpFlag; 785 this->writePaint(*paint); 786 } 787 // This needs to run first so its calls to needOpBytes() and its writes 788 // don't interlace with the needOpBytes() and write below. 789 SkASSERT(fBitmapHeap != NULL); 790 int32_t bitmapIndex = fBitmapHeap->insert(bm); 791 if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) { 792 return false; 793 } 794 795 if (this->needOpBytes(opBytesNeeded)) { 796 this->writeOp(op, flags, bitmapIndex); 797 return true; 798 } 799 return false; 800 } 801 802 void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, 803 const SkPaint* paint) { 804 NOTIFY_SETUP(this); 805 size_t opBytesNeeded = sizeof(SkScalar) * 2; 806 807 if (this->commonDrawBitmap(bm, kDrawBitmap_DrawOp, 0, opBytesNeeded, paint)) { 808 fWriter.writeScalar(left); 809 fWriter.writeScalar(top); 810 } 811 } 812 813 void SkGPipeCanvas::drawBitmapRectToRect(const SkBitmap& bm, const SkRect* src, 814 const SkRect& dst, const SkPaint* paint, 815 DrawBitmapRectFlags dbmrFlags) { 816 NOTIFY_SETUP(this); 817 size_t opBytesNeeded = sizeof(SkRect); 818 bool hasSrc = src != NULL; 819 unsigned flags; 820 if (hasSrc) { 821 flags = kDrawBitmap_HasSrcRect_DrawOpFlag; 822 opBytesNeeded += sizeof(int32_t) * 4; 823 } else { 824 flags = 0; 825 } 826 if (dbmrFlags & kBleed_DrawBitmapRectFlag) { 827 flags |= kDrawBitmap_Bleed_DrawOpFlag; 828 } 829 830 if (this->commonDrawBitmap(bm, kDrawBitmapRectToRect_DrawOp, flags, opBytesNeeded, paint)) { 831 if (hasSrc) { 832 fWriter.writeRect(*src); 833 } 834 fWriter.writeRect(dst); 835 } 836 } 837 838 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap& bm, const SkMatrix& matrix, 839 const SkPaint* paint) { 840 NOTIFY_SETUP(this); 841 size_t opBytesNeeded = matrix.writeToMemory(NULL); 842 843 if (this->commonDrawBitmap(bm, kDrawBitmapMatrix_DrawOp, 0, opBytesNeeded, paint)) { 844 fWriter.writeMatrix(matrix); 845 } 846 } 847 848 void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center, 849 const SkRect& dst, const SkPaint* paint) { 850 NOTIFY_SETUP(this); 851 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(SkRect); 852 853 if (this->commonDrawBitmap(bm, kDrawBitmapNine_DrawOp, 0, opBytesNeeded, paint)) { 854 fWriter.write32(center.fLeft); 855 fWriter.write32(center.fTop); 856 fWriter.write32(center.fRight); 857 fWriter.write32(center.fBottom); 858 fWriter.writeRect(dst); 859 } 860 } 861 862 void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top, 863 const SkPaint* paint) { 864 NOTIFY_SETUP(this); 865 size_t opBytesNeeded = sizeof(int32_t) * 2; 866 867 if (this->commonDrawBitmap(bm, kDrawSprite_DrawOp, 0, opBytesNeeded, paint)) { 868 fWriter.write32(left); 869 fWriter.write32(top); 870 } 871 } 872 873 void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 874 const SkPaint& paint) { 875 if (byteLength) { 876 NOTIFY_SETUP(this); 877 this->writePaint(paint); 878 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) { 879 this->writeOp(kDrawText_DrawOp); 880 fWriter.write32(SkToU32(byteLength)); 881 fWriter.writePad(text, byteLength); 882 fWriter.writeScalar(x); 883 fWriter.writeScalar(y); 884 } 885 } 886 } 887 888 void SkGPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 889 const SkPaint& paint) { 890 if (byteLength) { 891 NOTIFY_SETUP(this); 892 this->writePaint(paint); 893 int count = paint.textToGlyphs(text, byteLength, NULL); 894 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) { 895 this->writeOp(kDrawPosText_DrawOp); 896 fWriter.write32(SkToU32(byteLength)); 897 fWriter.writePad(text, byteLength); 898 fWriter.write32(count); 899 fWriter.write(pos, count * sizeof(SkPoint)); 900 } 901 } 902 } 903 904 void SkGPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 905 SkScalar constY, const SkPaint& paint) { 906 if (byteLength) { 907 NOTIFY_SETUP(this); 908 this->writePaint(paint); 909 int count = paint.textToGlyphs(text, byteLength, NULL); 910 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) { 911 this->writeOp(kDrawPosTextH_DrawOp); 912 fWriter.write32(SkToU32(byteLength)); 913 fWriter.writePad(text, byteLength); 914 fWriter.write32(count); 915 fWriter.write(xpos, count * sizeof(SkScalar)); 916 fWriter.writeScalar(constY); 917 } 918 } 919 } 920 921 void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 922 const SkMatrix* matrix, const SkPaint& paint) { 923 if (byteLength) { 924 NOTIFY_SETUP(this); 925 unsigned flags = 0; 926 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL); 927 if (matrix) { 928 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag; 929 size += matrix->writeToMemory(NULL); 930 } 931 this->writePaint(paint); 932 if (this->needOpBytes(size)) { 933 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0); 934 935 fWriter.write32(SkToU32(byteLength)); 936 fWriter.writePad(text, byteLength); 937 938 fWriter.writePath(path); 939 if (matrix) { 940 fWriter.writeMatrix(*matrix); 941 } 942 } 943 } 944 } 945 946 size_t SkGPipeCanvas::getInProcessTypefaces(const SkRefCntSet& typefaceSet, 947 TypefaceBuffer* buffer) { 948 // When in-process, we simply write out the typeface pointers. 949 size_t size = typefaceSet.count() * sizeof(SkTypeface*); 950 buffer->reset(size); 951 typefaceSet.copyToArray(reinterpret_cast<SkRefCnt**>(buffer->get())); 952 953 return size; 954 } 955 956 size_t SkGPipeCanvas::getCrossProcessTypefaces(const SkRefCntSet& typefaceSet, 957 TypefaceBuffer* buffer) { 958 // For cross-process we use typeface IDs. 959 size_t size = typefaceSet.count() * sizeof(uint32_t); 960 buffer->reset(size); 961 962 uint32_t* idBuffer = reinterpret_cast<uint32_t*>(buffer->get()); 963 SkRefCntSet::Iter iter(typefaceSet); 964 int i = 0; 965 966 for (void* setPtr = iter.next(); setPtr; setPtr = iter.next()) { 967 idBuffer[i++] = this->getTypefaceID(reinterpret_cast<SkTypeface*>(setPtr)); 968 } 969 970 SkASSERT(i == typefaceSet.count()); 971 972 return size; 973 } 974 975 void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 976 const SkPaint& paint) { 977 NOTIFY_SETUP(this); 978 this->writePaint(paint); 979 980 // FIXME: this is inefficient but avoids duplicating the blob serialization logic. 981 SkRefCntSet typefaceSet; 982 SkWriteBuffer blobBuffer; 983 blobBuffer.setTypefaceRecorder(&typefaceSet); 984 blob->flatten(blobBuffer); 985 986 // Unlike most draw ops (which only use one paint/typeface), text blobs may reference 987 // an arbitrary number of typefaces. Since the one-paint-per-op model is not applicable, 988 // we need to serialize these explicitly. 989 TypefaceBuffer typefaceBuffer; 990 size_t typefaceSize = is_cross_process(fFlags) 991 ? this->getCrossProcessTypefaces(typefaceSet, &typefaceBuffer) 992 : this->getInProcessTypefaces(typefaceSet, &typefaceBuffer); 993 994 // blob byte count + typeface count + x + y + blob data + an index (cross-process) 995 // or pointer (in-process) for each typeface 996 size_t size = 2 * sizeof(uint32_t) 997 + 2 * sizeof(SkScalar) 998 + blobBuffer.bytesWritten() 999 + typefaceSize; 1000 1001 if (this->needOpBytes(size)) { 1002 this->writeOp(kDrawTextBlob_DrawOp); 1003 SkDEBUGCODE(size_t initialOffset = fWriter.bytesWritten();) 1004 1005 fWriter.writeScalar(x); 1006 fWriter.writeScalar(y); 1007 1008 fWriter.write32(typefaceSet.count()); 1009 fWriter.write(typefaceBuffer.get(), typefaceSize); 1010 1011 fWriter.write32(SkToU32(blobBuffer.bytesWritten())); 1012 uint32_t* pad = fWriter.reservePad(blobBuffer.bytesWritten()); 1013 blobBuffer.writeToMemory(pad); 1014 1015 SkASSERT(initialOffset + size == fWriter.bytesWritten()); 1016 } 1017 } 1018 1019 void SkGPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 1020 const SkPaint* paint) { 1021 // we want to playback the picture into individual draw calls 1022 // 1023 // todo: do we always have to unroll? If the pipe is not cross-process, seems like 1024 // we could just ref the picture and move on...? <reed, scroggo> 1025 // 1026 this->INHERITED::onDrawPicture(picture, matrix, paint); 1027 } 1028 1029 void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount, 1030 const SkPoint vertices[], const SkPoint texs[], 1031 const SkColor colors[], SkXfermode* xfer, 1032 const uint16_t indices[], int indexCount, 1033 const SkPaint& paint) { 1034 if (0 == vertexCount) { 1035 return; 1036 } 1037 1038 NOTIFY_SETUP(this); 1039 this->writePaint(paint); 1040 1041 unsigned flags = 0; // packs with the op, so needs no extra space 1042 1043 size_t size = 0; 1044 size += 4; // vmode 1045 size += 4; // vertex count 1046 size += vertexCount * sizeof(SkPoint); // vertices 1047 1048 if (texs) { 1049 flags |= kDrawVertices_HasTexs_DrawOpFlag; 1050 size += vertexCount * sizeof(SkPoint); 1051 } 1052 if (colors) { 1053 flags |= kDrawVertices_HasColors_DrawOpFlag; 1054 size += vertexCount * sizeof(SkColor); 1055 } 1056 if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) { 1057 flags |= kDrawVertices_HasXfermode_DrawOpFlag; 1058 size += sizeof(int32_t); // SkXfermode::Mode 1059 } 1060 if (indices && indexCount > 0) { 1061 flags |= kDrawVertices_HasIndices_DrawOpFlag; 1062 size += 4; // index count 1063 size += SkAlign4(indexCount * sizeof(uint16_t)); // indices 1064 } 1065 1066 if (this->needOpBytes(size)) { 1067 this->writeOp(kDrawVertices_DrawOp, flags, 0); 1068 fWriter.write32(vmode); 1069 fWriter.write32(vertexCount); 1070 fWriter.write(vertices, vertexCount * sizeof(SkPoint)); 1071 if (flags & kDrawVertices_HasTexs_DrawOpFlag) { 1072 fWriter.write(texs, vertexCount * sizeof(SkPoint)); 1073 } 1074 if (flags & kDrawVertices_HasColors_DrawOpFlag) { 1075 fWriter.write(colors, vertexCount * sizeof(SkColor)); 1076 } 1077 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) { 1078 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; 1079 SkAssertResult(xfer->asMode(&mode)); 1080 fWriter.write32(mode); 1081 } 1082 if (flags & kDrawVertices_HasIndices_DrawOpFlag) { 1083 fWriter.write32(indexCount); 1084 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 1085 } 1086 } 1087 } 1088 1089 void SkGPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 1090 const SkPoint texCoords[4], SkXfermode* xmode, 1091 const SkPaint& paint) { 1092 NOTIFY_SETUP(this); 1093 1094 size_t size = SkPatchUtils::kNumCtrlPts * sizeof(SkPoint); 1095 unsigned flags = 0; 1096 if (colors) { 1097 flags |= kDrawVertices_HasColors_DrawOpFlag; 1098 size += SkPatchUtils::kNumCorners * sizeof(SkColor); 1099 } 1100 if (texCoords) { 1101 flags |= kDrawVertices_HasTexs_DrawOpFlag; 1102 size += SkPatchUtils::kNumCorners * sizeof(SkPoint); 1103 } 1104 if (xmode) { 1105 SkXfermode::Mode mode; 1106 if (xmode->asMode(&mode) && SkXfermode::kModulate_Mode != mode) { 1107 flags |= kDrawVertices_HasXfermode_DrawOpFlag; 1108 size += sizeof(int32_t); 1109 } 1110 } 1111 1112 this->writePaint(paint); 1113 if (this->needOpBytes(size)) { 1114 this->writeOp(kDrawPatch_DrawOp, flags, 0); 1115 1116 fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); 1117 1118 if (colors) { 1119 fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); 1120 } 1121 1122 if (texCoords) { 1123 fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); 1124 } 1125 1126 if (flags & kDrawVertices_HasXfermode_DrawOpFlag) { 1127 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; 1128 SkAssertResult(xmode->asMode(&mode)); 1129 fWriter.write32(mode); 1130 } 1131 } 1132 } 1133 1134 void SkGPipeCanvas::drawData(const void* ptr, size_t size) { 1135 if (size && ptr) { 1136 NOTIFY_SETUP(this); 1137 unsigned data = 0; 1138 if (size < (1 << DRAWOPS_DATA_BITS)) { 1139 data = (unsigned)size; 1140 } 1141 if (this->needOpBytes(4 + SkAlign4(size))) { 1142 this->writeOp(kDrawData_DrawOp, 0, data); 1143 if (0 == data) { 1144 fWriter.write32(SkToU32(size)); 1145 } 1146 fWriter.writePad(ptr, size); 1147 } 1148 } 1149 } 1150 1151 void SkGPipeCanvas::beginCommentGroup(const char* description) { 1152 // ignore for now 1153 } 1154 1155 void SkGPipeCanvas::addComment(const char* kywd, const char* value) { 1156 // ignore for now 1157 } 1158 1159 void SkGPipeCanvas::endCommentGroup() { 1160 // ignore for now 1161 } 1162 1163 void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) { 1164 this->doNotify(); 1165 if (detachCurrentBlock) { 1166 // force a new block to be requested for the next recorded command 1167 fBlockSize = 0; 1168 } 1169 } 1170 1171 size_t SkGPipeCanvas::freeMemoryIfPossible(size_t bytesToFree) { 1172 return (NULL == fBitmapHeap) ? 0 : fBitmapHeap->freeMemoryIfPossible(bytesToFree); 1173 } 1174 1175 /////////////////////////////////////////////////////////////////////////////// 1176 1177 template <typename T> uint32_t castToU32(T value) { 1178 union { 1179 T fSrc; 1180 uint32_t fDst; 1181 } data; 1182 data.fSrc = value; 1183 return data.fDst; 1184 } 1185 1186 void SkGPipeCanvas::writePaint(const SkPaint& paint) { 1187 if (fDone) { 1188 return; 1189 } 1190 SkPaint& base = fPaint; 1191 uint32_t storage[32]; 1192 uint32_t* ptr = storage; 1193 1194 if (base.getFlags() != paint.getFlags()) { 1195 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags()); 1196 base.setFlags(paint.getFlags()); 1197 } 1198 if (base.getColor() != paint.getColor()) { 1199 *ptr++ = PaintOp_packOp(kColor_PaintOp); 1200 *ptr++ = paint.getColor(); 1201 base.setColor(paint.getColor()); 1202 } 1203 if (base.getFilterLevel() != paint.getFilterLevel()) { 1204 *ptr++ = PaintOp_packOpData(kFilterLevel_PaintOp, paint.getFilterLevel()); 1205 base.setFilterLevel(paint.getFilterLevel()); 1206 } 1207 if (base.getStyle() != paint.getStyle()) { 1208 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle()); 1209 base.setStyle(paint.getStyle()); 1210 } 1211 if (base.getStrokeJoin() != paint.getStrokeJoin()) { 1212 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin()); 1213 base.setStrokeJoin(paint.getStrokeJoin()); 1214 } 1215 if (base.getStrokeCap() != paint.getStrokeCap()) { 1216 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap()); 1217 base.setStrokeCap(paint.getStrokeCap()); 1218 } 1219 if (base.getStrokeWidth() != paint.getStrokeWidth()) { 1220 *ptr++ = PaintOp_packOp(kWidth_PaintOp); 1221 *ptr++ = castToU32(paint.getStrokeWidth()); 1222 base.setStrokeWidth(paint.getStrokeWidth()); 1223 } 1224 if (base.getStrokeMiter() != paint.getStrokeMiter()) { 1225 *ptr++ = PaintOp_packOp(kMiter_PaintOp); 1226 *ptr++ = castToU32(paint.getStrokeMiter()); 1227 base.setStrokeMiter(paint.getStrokeMiter()); 1228 } 1229 if (base.getTextEncoding() != paint.getTextEncoding()) { 1230 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding()); 1231 base.setTextEncoding(paint.getTextEncoding()); 1232 } 1233 if (base.getHinting() != paint.getHinting()) { 1234 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting()); 1235 base.setHinting(paint.getHinting()); 1236 } 1237 if (base.getTextAlign() != paint.getTextAlign()) { 1238 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign()); 1239 base.setTextAlign(paint.getTextAlign()); 1240 } 1241 if (base.getTextSize() != paint.getTextSize()) { 1242 *ptr++ = PaintOp_packOp(kTextSize_PaintOp); 1243 *ptr++ = castToU32(paint.getTextSize()); 1244 base.setTextSize(paint.getTextSize()); 1245 } 1246 if (base.getTextScaleX() != paint.getTextScaleX()) { 1247 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp); 1248 *ptr++ = castToU32(paint.getTextScaleX()); 1249 base.setTextScaleX(paint.getTextScaleX()); 1250 } 1251 if (base.getTextSkewX() != paint.getTextSkewX()) { 1252 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 1253 *ptr++ = castToU32(paint.getTextSkewX()); 1254 base.setTextSkewX(paint.getTextSkewX()); 1255 } 1256 1257 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 1258 if (is_cross_process(fFlags)) { 1259 uint32_t id = this->getTypefaceID(paint.getTypeface()); 1260 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 1261 } else if (this->needOpBytes(sizeof(void*))) { 1262 // Add to the set for ref counting. 1263 fTypefaceSet.add(paint.getTypeface()); 1264 // It is safe to write the typeface to the stream before the rest 1265 // of the paint unless we ever send a kReset_PaintOp, which we 1266 // currently never do. 1267 this->writeOp(kSetTypeface_DrawOp); 1268 fWriter.writePtr(paint.getTypeface()); 1269 } 1270 base.setTypeface(paint.getTypeface()); 1271 } 1272 1273 // This is a new paint, so all old flats can be safely purged, if necessary. 1274 fFlattenableHeap.markAllFlatsSafeToDelete(); 1275 for (int i = 0; i < kCount_PaintFlats; i++) { 1276 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i); 1277 bool replaced = index < 0; 1278 if (replaced) { 1279 index = ~index; 1280 } 1281 // Store the index of any flat that needs to be kept. 0 means no flat. 1282 if (index > 0) { 1283 fFlattenableHeap.markFlatForKeeping(index); 1284 } 1285 SkASSERT(index >= 0 && index <= fFlatDictionary.count()); 1286 if (index != fCurrFlatIndex[i] || replaced) { 1287 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index); 1288 fCurrFlatIndex[i] = index; 1289 } 1290 } 1291 1292 size_t size = (char*)ptr - (char*)storage; 1293 if (size && this->needOpBytes(size)) { 1294 this->writeOp(kPaintOp_DrawOp, 0, SkToU32(size)); 1295 fWriter.write(storage, size); 1296 for (size_t i = 0; i < size/4; i++) { 1297 // SkDebugf("[%d] %08X\n", i, storage[i]); 1298 } 1299 } 1300 1301 // 1302 // Do these after we've written kPaintOp_DrawOp 1303 1304 if (base.getAnnotation() != paint.getAnnotation()) { 1305 if (NULL == paint.getAnnotation()) { 1306 if (this->needOpBytes()) { 1307 this->writeOp(kSetAnnotation_DrawOp, 0, 0); 1308 } 1309 } else { 1310 SkWriteBuffer buffer; 1311 paint.getAnnotation()->writeToBuffer(buffer); 1312 const size_t size = buffer.bytesWritten(); 1313 if (this->needOpBytes(size)) { 1314 this->writeOp(kSetAnnotation_DrawOp, 0, SkToU32(size)); 1315 buffer.writeToMemory(fWriter.reserve(size)); 1316 } 1317 } 1318 base.setAnnotation(paint.getAnnotation()); 1319 } 1320 } 1321 1322 /////////////////////////////////////////////////////////////////////////////// 1323 1324 #include "SkGPipe.h" 1325 1326 SkGPipeController::~SkGPipeController() { 1327 SkSafeUnref(fCanvas); 1328 } 1329 1330 void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) { 1331 SkRefCnt_SafeAssign(fCanvas, canvas); 1332 } 1333 1334 /////////////////////////////////////////////////////////////////////////////// 1335 1336 SkGPipeWriter::SkGPipeWriter() 1337 : fWriter(0) { 1338 fCanvas = NULL; 1339 } 1340 1341 SkGPipeWriter::~SkGPipeWriter() { 1342 this->endRecording(); 1343 } 1344 1345 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags, 1346 uint32_t width, uint32_t height) { 1347 if (NULL == fCanvas) { 1348 fWriter.reset(NULL, 0); 1349 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height)); 1350 } 1351 controller->setCanvas(fCanvas); 1352 return fCanvas; 1353 } 1354 1355 void SkGPipeWriter::endRecording() { 1356 if (fCanvas) { 1357 fCanvas->finish(true); 1358 fCanvas->unref(); 1359 fCanvas = NULL; 1360 } 1361 } 1362 1363 void SkGPipeWriter::flushRecording(bool detachCurrentBlock) { 1364 if (fCanvas) { 1365 fCanvas->flushRecording(detachCurrentBlock); 1366 } 1367 } 1368 1369 size_t SkGPipeWriter::freeMemoryIfPossible(size_t bytesToFree) { 1370 if (fCanvas) { 1371 return fCanvas->freeMemoryIfPossible(bytesToFree); 1372 } 1373 return 0; 1374 } 1375 1376 size_t SkGPipeWriter::storageAllocatedForRecording() const { 1377 return NULL == fCanvas ? 0 : fCanvas->storageAllocatedForRecording(); 1378 } 1379 1380 /////////////////////////////////////////////////////////////////////////////// 1381 1382 BitmapShuttle::BitmapShuttle(SkGPipeCanvas* canvas) { 1383 SkASSERT(canvas != NULL); 1384 fCanvas = canvas; 1385 fCanvas->ref(); 1386 } 1387 1388 BitmapShuttle::~BitmapShuttle() { 1389 this->removeCanvas(); 1390 } 1391 1392 bool BitmapShuttle::insert(const SkBitmap& bitmap, int32_t slot) { 1393 SkASSERT(fCanvas != NULL); 1394 return fCanvas->shuttleBitmap(bitmap, slot); 1395 } 1396 1397 void BitmapShuttle::removeCanvas() { 1398 if (NULL == fCanvas) { 1399 return; 1400 } 1401 fCanvas->unref(); 1402 fCanvas = NULL; 1403 } 1404