gfx/skia/trunk/src/pipe/SkGPipeWrite.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial