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