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