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