SkGPipeWrite.cpp revision 0c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451
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 10 11#include "SkCanvas.h" 12#include "SkData.h" 13#include "SkDevice.h" 14#include "SkPaint.h" 15#include "SkGPipe.h" 16#include "SkGPipePriv.h" 17#include "SkStream.h" 18#include "SkTSearch.h" 19#include "SkTypeface.h" 20#include "SkWriter32.h" 21#include "SkColorFilter.h" 22#include "SkDrawLooper.h" 23#include "SkMaskFilter.h" 24#include "SkRasterizer.h" 25#include "SkShader.h" 26 27static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { 28 SkASSERT(paintFlat < kCount_PaintFlats); 29 switch (paintFlat) { 30 case kColorFilter_PaintFlat: return paint.getColorFilter(); 31 case kDrawLooper_PaintFlat: return paint.getLooper(); 32 case kMaskFilter_PaintFlat: return paint.getMaskFilter(); 33 case kPathEffect_PaintFlat: return paint.getPathEffect(); 34 case kRasterizer_PaintFlat: return paint.getRasterizer(); 35 case kShader_PaintFlat: return paint.getShader(); 36 case kXfermode_PaintFlat: return paint.getXfermode(); 37 } 38 SkDEBUGFAIL("never gets here"); 39 return NULL; 40} 41 42static size_t estimateFlattenSize(const SkPath& path) { 43 int n = path.countPoints(); 44 size_t bytes = 3 * sizeof(int32_t); 45 bytes += n * sizeof(SkPoint); 46 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras 47 48#ifdef SK_DEBUG 49 { 50 SkWriter32 writer(1024); 51 path.flatten(writer); 52 SkASSERT(writer.size() <= bytes); 53 } 54#endif 55 return bytes; 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(size); 65 SkAutoDataUnref data(stream.copyToData()); 66 writer->write(data.data(), size); 67 } 68 return 4 + size; 69} 70 71/////////////////////////////////////////////////////////////////////////////// 72 73class SkGPipeCanvas : public SkCanvas { 74public: 75 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*); 76 virtual ~SkGPipeCanvas(); 77 78 void finish() { 79 if (!fDone) { 80 if (this->needOpBytes()) { 81 this->writeOp(kDone_DrawOp); 82 this->doNotify(); 83 } 84 fDone = true; 85 } 86 } 87 88 // overrides from SkCanvas 89 virtual int save(SaveFlags); 90 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags); 91 virtual void restore(); 92 virtual bool translate(SkScalar dx, SkScalar dy); 93 virtual bool scale(SkScalar sx, SkScalar sy); 94 virtual bool rotate(SkScalar degrees); 95 virtual bool skew(SkScalar sx, SkScalar sy); 96 virtual bool concat(const SkMatrix& matrix); 97 virtual void setMatrix(const SkMatrix& matrix); 98 virtual bool clipRect(const SkRect& rect, SkRegion::Op op); 99 virtual bool clipPath(const SkPath& path, SkRegion::Op op); 100 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op); 101 virtual void clear(SkColor); 102 virtual void drawPaint(const SkPaint& paint); 103 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[], 104 const SkPaint&); 105 virtual void drawRect(const SkRect& rect, const SkPaint&); 106 virtual void drawPath(const SkPath& path, const SkPaint&); 107 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 108 const SkPaint*); 109 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src, 110 const SkRect& dst, const SkPaint*); 111 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 112 const SkPaint*); 113 virtual void drawSprite(const SkBitmap&, int left, int top, 114 const SkPaint*); 115 virtual void drawText(const void* text, size_t byteLength, SkScalar x, 116 SkScalar y, const SkPaint&); 117 virtual void drawPosText(const void* text, size_t byteLength, 118 const SkPoint pos[], const SkPaint&); 119 virtual void drawPosTextH(const void* text, size_t byteLength, 120 const SkScalar xpos[], SkScalar constY, const SkPaint&); 121 virtual void drawTextOnPath(const void* text, size_t byteLength, 122 const SkPath& path, const SkMatrix* matrix, 123 const SkPaint&); 124 virtual void drawPicture(SkPicture& picture); 125 virtual void drawVertices(VertexMode, int vertexCount, 126 const SkPoint vertices[], const SkPoint texs[], 127 const SkColor colors[], SkXfermode*, 128 const uint16_t indices[], int indexCount, 129 const SkPaint&); 130 virtual void drawData(const void*, size_t); 131 132private: 133 SkFactorySet* fFactorySet; // optional, only used if cross-process 134 SkGPipeController* fController; 135 SkWriter32& fWriter; 136 size_t fBlockSize; // amount allocated for writer 137 size_t fBytesNotified; 138 bool fDone; 139 140 SkRefCntSet fTypefaceSet; 141 142 uint32_t getTypefaceID(SkTypeface*); 143 144 inline void writeOp(DrawOps op, unsigned flags, unsigned data) { 145 fWriter.write32(DrawOp_packOpFlagData(op, flags, data)); 146 } 147 148 inline void writeOp(DrawOps op) { 149 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0)); 150 } 151 152 bool needOpBytes(size_t size = 0); 153 154 inline void doNotify() { 155 if (!fDone) { 156 size_t bytes = fWriter.size() - fBytesNotified; 157 fController->notifyWritten(bytes); 158 fBytesNotified += bytes; 159 } 160 } 161 162 struct FlatData { 163 uint32_t fIndex; // always > 0 164 uint32_t fSize; 165 166 void* data() { return (char*)this + sizeof(*this); } 167 168 static int Compare(const FlatData* a, const FlatData* b) { 169 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize)); 170 } 171 }; 172 SkTDArray<FlatData*> fFlatArray; 173 int fCurrFlatIndex[kCount_PaintFlats]; 174 int flattenToIndex(SkFlattenable* obj, PaintFlats); 175 176 SkPaint fPaint; 177 void writePaint(const SkPaint&); 178 179 class AutoPipeNotify { 180 public: 181 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {} 182 ~AutoPipeNotify() { fCanvas->doNotify(); } 183 private: 184 SkGPipeCanvas* fCanvas; 185 }; 186 friend class AutoPipeNotify; 187 188 typedef SkCanvas INHERITED; 189}; 190 191// return 0 for NULL (or unflattenable obj), or index-base-1 192int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) { 193 if (NULL == obj) { 194 return 0; 195 } 196 197 SkFlattenableWriteBuffer tmpWriter(1024); 198 tmpWriter.setFlags(SkFlattenableWriteBuffer::kInlineFactoryNames_Flag); 199 tmpWriter.setFactoryRecorder(fFactorySet); 200 201 tmpWriter.writeFlattenable(obj); 202 size_t len = tmpWriter.size(); 203 size_t allocSize = len + sizeof(FlatData); 204 205 SkAutoSMalloc<1024> storage(allocSize); 206 FlatData* flat = (FlatData*)storage.get(); 207 flat->fSize = len; 208 tmpWriter.flatten(flat->data()); 209 210 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(), 211 fFlatArray.count(), flat, sizeof(flat), 212 &FlatData::Compare); 213 if (index < 0) { 214 index = ~index; 215 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize); 216 memcpy(copy, flat, allocSize); 217 *fFlatArray.insert(index) = copy; 218 // call this after the insert, so that count() will have been grown 219 copy->fIndex = fFlatArray.count(); 220// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex); 221 222 if (this->needOpBytes(len)) { 223 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex); 224 fWriter.write(copy->data(), len); 225 } 226 } 227 return fFlatArray[index]->fIndex; 228} 229 230/////////////////////////////////////////////////////////////////////////////// 231 232#define MIN_BLOCK_SIZE (16 * 1024) 233 234SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, 235 SkWriter32* writer, SkFactorySet* fset) 236 : fWriter(*writer) { 237 fFactorySet = fset; 238 fController = controller; 239 fDone = false; 240 fBlockSize = 0; // need first block from controller 241 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); 242 243 // we need a device to limit our clip 244 // should the caller give us the bounds? 245 // We don't allocate pixels for the bitmap 246 SkBitmap bitmap; 247 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767); 248 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); 249 this->setDevice(device)->unref(); 250} 251 252SkGPipeCanvas::~SkGPipeCanvas() { 253 this->finish(); 254 255 fFlatArray.freeAll(); 256} 257 258bool SkGPipeCanvas::needOpBytes(size_t needed) { 259 if (fDone) { 260 return false; 261 } 262 263 needed += 4; // size of DrawOp atom 264 if (fWriter.size() + needed > fBlockSize) { 265 void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize); 266 if (NULL == block) { 267 fDone = true; 268 return false; 269 } 270 fWriter.reset(block, fBlockSize); 271 fBytesNotified = 0; 272 } 273 return true; 274} 275 276uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) { 277 uint32_t id = 0; // 0 means default/null typeface 278 if (face) { 279 id = fTypefaceSet.find(face); 280 if (0 == id) { 281 id = fTypefaceSet.add(face); 282 size_t size = writeTypeface(NULL, face); 283 if (this->needOpBytes(size)) { 284 this->writeOp(kDef_Typeface_DrawOp); 285 writeTypeface(&fWriter, face); 286 } 287 } 288 } 289 return id; 290} 291 292/////////////////////////////////////////////////////////////////////////////// 293 294#define NOTIFY_SETUP(canvas) \ 295 AutoPipeNotify apn(canvas) 296 297int SkGPipeCanvas::save(SaveFlags flags) { 298 NOTIFY_SETUP(this); 299 if (this->needOpBytes()) { 300 this->writeOp(kSave_DrawOp, 0, flags); 301 } 302 return this->INHERITED::save(flags); 303} 304 305int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 306 SaveFlags saveFlags) { 307 NOTIFY_SETUP(this); 308 size_t size = 0; 309 unsigned opFlags = 0; 310 311 if (bounds) { 312 opFlags |= kSaveLayer_HasBounds_DrawOpFlag; 313 size += sizeof(SkRect); 314 } 315 if (paint) { 316 opFlags |= kSaveLayer_HasPaint_DrawOpFlag; 317 this->writePaint(*paint); 318 } 319 320 if (this->needOpBytes(size)) { 321 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags); 322 if (bounds) { 323 fWriter.writeRect(*bounds); 324 } 325 } 326 327 // we just pass on the save, so we don't create a layer 328 return this->INHERITED::save(saveFlags); 329} 330 331void SkGPipeCanvas::restore() { 332 NOTIFY_SETUP(this); 333 if (this->needOpBytes()) { 334 this->writeOp(kRestore_DrawOp); 335 } 336 this->INHERITED::restore(); 337} 338 339bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) { 340 if (dx || dy) { 341 NOTIFY_SETUP(this); 342 if (this->needOpBytes(2 * sizeof(SkScalar))) { 343 this->writeOp(kTranslate_DrawOp); 344 fWriter.writeScalar(dx); 345 fWriter.writeScalar(dy); 346 } 347 } 348 return this->INHERITED::translate(dx, dy); 349} 350 351bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) { 352 if (sx || sy) { 353 NOTIFY_SETUP(this); 354 if (this->needOpBytes(2 * sizeof(SkScalar))) { 355 this->writeOp(kScale_DrawOp); 356 fWriter.writeScalar(sx); 357 fWriter.writeScalar(sy); 358 } 359 } 360 return this->INHERITED::scale(sx, sy); 361} 362 363bool SkGPipeCanvas::rotate(SkScalar degrees) { 364 if (degrees) { 365 NOTIFY_SETUP(this); 366 if (this->needOpBytes(sizeof(SkScalar))) { 367 this->writeOp(kRotate_DrawOp); 368 fWriter.writeScalar(degrees); 369 } 370 } 371 return this->INHERITED::rotate(degrees); 372} 373 374bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) { 375 if (sx || sy) { 376 NOTIFY_SETUP(this); 377 if (this->needOpBytes(2 * sizeof(SkScalar))) { 378 this->writeOp(kSkew_DrawOp); 379 fWriter.writeScalar(sx); 380 fWriter.writeScalar(sy); 381 } 382 } 383 return this->INHERITED::skew(sx, sy); 384} 385 386bool SkGPipeCanvas::concat(const SkMatrix& matrix) { 387 if (!matrix.isIdentity()) { 388 NOTIFY_SETUP(this); 389 if (this->needOpBytes(matrix.flatten(NULL))) { 390 this->writeOp(kConcat_DrawOp); 391 SkWriteMatrix(&fWriter, matrix); 392 } 393 } 394 return this->INHERITED::concat(matrix); 395} 396 397void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) { 398 NOTIFY_SETUP(this); 399 if (this->needOpBytes(matrix.flatten(NULL))) { 400 this->writeOp(kSetMatrix_DrawOp); 401 SkWriteMatrix(&fWriter, matrix); 402 } 403 this->INHERITED::setMatrix(matrix); 404} 405 406bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) { 407 NOTIFY_SETUP(this); 408 if (this->needOpBytes(sizeof(SkRect))) { 409 this->writeOp(kClipRect_DrawOp, 0, rgnOp); 410 fWriter.writeRect(rect); 411 } 412 return this->INHERITED::clipRect(rect, rgnOp); 413} 414 415bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) { 416 NOTIFY_SETUP(this); 417 if (this->needOpBytes(estimateFlattenSize(path))) { 418 this->writeOp(kClipPath_DrawOp, 0, rgnOp); 419 path.flatten(fWriter); 420 } 421 // we just pass on the bounds of the path 422 return this->INHERITED::clipRect(path.getBounds(), rgnOp); 423} 424 425bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) { 426 NOTIFY_SETUP(this); 427 if (this->needOpBytes(region.flatten(NULL))) { 428 this->writeOp(kClipRegion_DrawOp, 0, rgnOp); 429 SkWriteRegion(&fWriter, region); 430 } 431 return this->INHERITED::clipRegion(region, rgnOp); 432} 433 434/////////////////////////////////////////////////////////////////////////////// 435 436void SkGPipeCanvas::clear(SkColor color) { 437 NOTIFY_SETUP(this); 438 unsigned flags = 0; 439 if (color) { 440 flags |= kClear_HasColor_DrawOpFlag; 441 } 442 if (this->needOpBytes(sizeof(SkColor))) { 443 this->writeOp(kDrawClear_DrawOp, flags, 0); 444 if (color) { 445 fWriter.write32(color); 446 } 447 } 448} 449 450void SkGPipeCanvas::drawPaint(const SkPaint& paint) { 451 NOTIFY_SETUP(this); 452 this->writePaint(paint); 453 if (this->needOpBytes()) { 454 this->writeOp(kDrawPaint_DrawOp); 455 } 456} 457 458void SkGPipeCanvas::drawPoints(PointMode mode, size_t count, 459 const SkPoint pts[], const SkPaint& paint) { 460 if (count) { 461 NOTIFY_SETUP(this); 462 this->writePaint(paint); 463 if (this->needOpBytes(4 + count * sizeof(SkPoint))) { 464 this->writeOp(kDrawPoints_DrawOp, mode, 0); 465 fWriter.write32(count); 466 fWriter.write(pts, count * sizeof(SkPoint)); 467 } 468 } 469} 470 471void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 472 NOTIFY_SETUP(this); 473 this->writePaint(paint); 474 if (this->needOpBytes(sizeof(SkRect))) { 475 this->writeOp(kDrawRect_DrawOp); 476 fWriter.writeRect(rect); 477 } 478} 479 480void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 481 NOTIFY_SETUP(this); 482 this->writePaint(paint); 483 if (this->needOpBytes(estimateFlattenSize(path))) { 484 this->writeOp(kDrawPath_DrawOp); 485 path.flatten(fWriter); 486 } 487} 488 489void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, 490 const SkPaint*) { 491 UNIMPLEMENTED 492} 493 494void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src, 495 const SkRect& dst, const SkPaint*) { 496 UNIMPLEMENTED 497} 498 499void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&, 500 const SkPaint*) { 501 UNIMPLEMENTED 502} 503 504void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top, 505 const SkPaint*) { 506 UNIMPLEMENTED 507} 508 509void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x, 510 SkScalar y, const SkPaint& paint) { 511 if (byteLength) { 512 NOTIFY_SETUP(this); 513 this->writePaint(paint); 514 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) { 515 this->writeOp(kDrawText_DrawOp); 516 fWriter.write32(byteLength); 517 fWriter.writePad(text, byteLength); 518 fWriter.writeScalar(x); 519 fWriter.writeScalar(y); 520 } 521 } 522} 523 524void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength, 525 const SkPoint pos[], const SkPaint& paint) { 526 if (byteLength) { 527 NOTIFY_SETUP(this); 528 this->writePaint(paint); 529 int count = paint.textToGlyphs(text, byteLength, NULL); 530 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) { 531 this->writeOp(kDrawPosText_DrawOp); 532 fWriter.write32(byteLength); 533 fWriter.writePad(text, byteLength); 534 fWriter.write32(count); 535 fWriter.write(pos, count * sizeof(SkPoint)); 536 } 537 } 538} 539 540void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength, 541 const SkScalar xpos[], SkScalar constY, 542 const SkPaint& paint) { 543 if (byteLength) { 544 NOTIFY_SETUP(this); 545 this->writePaint(paint); 546 int count = paint.textToGlyphs(text, byteLength, NULL); 547 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) { 548 this->writeOp(kDrawPosTextH_DrawOp); 549 fWriter.write32(byteLength); 550 fWriter.writePad(text, byteLength); 551 fWriter.write32(count); 552 fWriter.write(xpos, count * sizeof(SkScalar)); 553 fWriter.writeScalar(constY); 554 } 555 } 556} 557 558void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength, 559 const SkPath& path, const SkMatrix* matrix, 560 const SkPaint& paint) { 561 if (byteLength) { 562 NOTIFY_SETUP(this); 563 unsigned flags = 0; 564 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path); 565 if (matrix) { 566 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag; 567 size += matrix->flatten(NULL); 568 } 569 this->writePaint(paint); 570 if (this->needOpBytes(size)) { 571 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0); 572 573 fWriter.write32(byteLength); 574 fWriter.writePad(text, byteLength); 575 576 path.flatten(fWriter); 577 if (matrix) { 578 SkWriteMatrix(&fWriter, *matrix); 579 } 580 } 581 } 582} 583 584void SkGPipeCanvas::drawPicture(SkPicture& picture) { 585 // we want to playback the picture into individual draw calls 586 this->INHERITED::drawPicture(picture); 587} 588 589void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount, 590 const SkPoint vertices[], const SkPoint texs[], 591 const SkColor colors[], SkXfermode*, 592 const uint16_t indices[], int indexCount, 593 const SkPaint& paint) { 594 if (0 == vertexCount) { 595 return; 596 } 597 598 NOTIFY_SETUP(this); 599 size_t size = 4 + vertexCount * sizeof(SkPoint); 600 this->writePaint(paint); 601 unsigned flags = 0; 602 if (texs) { 603 flags |= kDrawVertices_HasTexs_DrawOpFlag; 604 size += vertexCount * sizeof(SkPoint); 605 } 606 if (colors) { 607 flags |= kDrawVertices_HasColors_DrawOpFlag; 608 size += vertexCount * sizeof(SkColor); 609 } 610 if (indices && indexCount > 0) { 611 flags |= kDrawVertices_HasIndices_DrawOpFlag; 612 size += 4 + SkAlign4(indexCount * sizeof(uint16_t)); 613 } 614 615 if (this->needOpBytes(size)) { 616 this->writeOp(kDrawVertices_DrawOp, flags, 0); 617 fWriter.write32(mode); 618 fWriter.write32(vertexCount); 619 fWriter.write(vertices, vertexCount * sizeof(SkPoint)); 620 if (texs) { 621 fWriter.write(texs, vertexCount * sizeof(SkPoint)); 622 } 623 if (colors) { 624 fWriter.write(colors, vertexCount * sizeof(SkColor)); 625 } 626 627 // TODO: flatten xfermode 628 629 if (indices && indexCount > 0) { 630 fWriter.write32(indexCount); 631 fWriter.writePad(indices, indexCount * sizeof(uint16_t)); 632 } 633 } 634} 635 636void SkGPipeCanvas::drawData(const void* ptr, size_t size) { 637 if (size && ptr) { 638 NOTIFY_SETUP(this); 639 unsigned data = 0; 640 if (size < (1 << DRAWOPS_DATA_BITS)) { 641 data = (unsigned)size; 642 } 643 if (this->needOpBytes(4 + SkAlign4(size))) { 644 this->writeOp(kDrawData_DrawOp, 0, data); 645 if (0 == data) { 646 fWriter.write32(size); 647 } 648 fWriter.writePad(ptr, size); 649 } 650 } 651} 652 653/////////////////////////////////////////////////////////////////////////////// 654 655template <typename T> uint32_t castToU32(T value) { 656 union { 657 T fSrc; 658 uint32_t fDst; 659 } data; 660 data.fSrc = value; 661 return data.fDst; 662} 663 664void SkGPipeCanvas::writePaint(const SkPaint& paint) { 665 SkPaint& base = fPaint; 666 uint32_t storage[32]; 667 uint32_t* ptr = storage; 668 669 if (base.getFlags() != paint.getFlags()) { 670 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags()); 671 base.setFlags(paint.getFlags()); 672 } 673 if (base.getColor() != paint.getColor()) { 674 *ptr++ = PaintOp_packOp(kColor_PaintOp); 675 *ptr++ = paint.getColor(); 676 base.setColor(paint.getColor()); 677 } 678 if (base.getStyle() != paint.getStyle()) { 679 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle()); 680 base.setStyle(paint.getStyle()); 681 } 682 if (base.getStrokeJoin() != paint.getStrokeJoin()) { 683 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin()); 684 base.setStrokeJoin(paint.getStrokeJoin()); 685 } 686 if (base.getStrokeCap() != paint.getStrokeCap()) { 687 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap()); 688 base.setStrokeCap(paint.getStrokeCap()); 689 } 690 if (base.getStrokeWidth() != paint.getStrokeWidth()) { 691 *ptr++ = PaintOp_packOp(kWidth_PaintOp); 692 *ptr++ = castToU32(paint.getStrokeWidth()); 693 base.setStrokeWidth(paint.getStrokeWidth()); 694 } 695 if (base.getStrokeMiter() != paint.getStrokeMiter()) { 696 *ptr++ = PaintOp_packOp(kMiter_PaintOp); 697 *ptr++ = castToU32(paint.getStrokeMiter()); 698 base.setStrokeMiter(paint.getStrokeMiter()); 699 } 700 if (base.getTextEncoding() != paint.getTextEncoding()) { 701 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding()); 702 base.setTextEncoding(paint.getTextEncoding()); 703 } 704 if (base.getHinting() != paint.getHinting()) { 705 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting()); 706 base.setHinting(paint.getHinting()); 707 } 708 if (base.getTextAlign() != paint.getTextAlign()) { 709 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign()); 710 base.setTextAlign(paint.getTextAlign()); 711 } 712 if (base.getTextSize() != paint.getTextSize()) { 713 *ptr++ = PaintOp_packOp(kTextSize_PaintOp); 714 *ptr++ = castToU32(paint.getTextSize()); 715 base.setTextSize(paint.getTextSize()); 716 } 717 if (base.getTextScaleX() != paint.getTextScaleX()) { 718 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp); 719 *ptr++ = castToU32(paint.getTextScaleX()); 720 base.setTextScaleX(paint.getTextScaleX()); 721 } 722 if (base.getTextSkewX() != paint.getTextSkewX()) { 723 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp); 724 *ptr++ = castToU32(paint.getTextSkewX()); 725 base.setTextSkewX(paint.getTextSkewX()); 726 } 727 728 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { 729 uint32_t id = this->getTypefaceID(paint.getTypeface()); 730 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); 731 base.setTypeface(paint.getTypeface()); 732 } 733 734 for (int i = 0; i < kCount_PaintFlats; i++) { 735 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i); 736 SkASSERT(index >= 0 && index <= fFlatArray.count()); 737 if (index != fCurrFlatIndex[i]) { 738 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index); 739 fCurrFlatIndex[i] = index; 740 } 741 } 742 743 size_t size = (char*)ptr - (char*)storage; 744 if (size && this->needOpBytes(size)) { 745 this->writeOp(kPaintOp_DrawOp, 0, size); 746 fWriter.write(storage, size); 747 for (size_t i = 0; i < size/4; i++) { 748// SkDebugf("[%d] %08X\n", i, storage[i]); 749 } 750 } 751} 752 753/////////////////////////////////////////////////////////////////////////////// 754 755#include "SkGPipe.h" 756 757SkGPipeWriter::SkGPipeWriter() : fWriter(0) { 758 fCanvas = NULL; 759} 760 761SkGPipeWriter::~SkGPipeWriter() { 762 this->endRecording(); 763 SkSafeUnref(fCanvas); 764} 765 766SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, 767 uint32_t flags) { 768 if (NULL == fCanvas) { 769 fWriter.reset(NULL, 0); 770 fFactorySet.reset(); 771 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, 772 (flags & kCrossProcess_Flag) ? 773 &fFactorySet : NULL)); 774 } 775 return fCanvas; 776} 777 778void SkGPipeWriter::endRecording() { 779 if (fCanvas) { 780 fCanvas->finish(); 781 fCanvas->unref(); 782 fCanvas = NULL; 783 } 784} 785 786