| Index: src/pipe/SkGPipeWrite.cpp
|
| diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
|
| index f361e5ed67ecf092b4fd3a10f41f793e4f5cac69..41b02344805ffceb09c1797367a78355024a7e1d 100644
|
| --- a/src/pipe/SkGPipeWrite.cpp
|
| +++ b/src/pipe/SkGPipeWrite.cpp
|
| @@ -22,6 +22,7 @@
|
| #include "SkPatchUtils.h"
|
| #include "SkPathEffect.h"
|
| #include "SkPictureFlat.h"
|
| +#include "SkPtrRecorder.h"
|
| #include "SkRasterizer.h"
|
| #include "SkRRect.h"
|
| #include "SkShader.h"
|
| @@ -35,7 +36,7 @@ enum {
|
| kSizeOfFlatRRect = sizeof(SkRect) + 4 * sizeof(SkVector)
|
| };
|
|
|
| -static bool isCrossProcess(uint32_t flags) {
|
| +static bool is_cross_process(uint32_t flags) {
|
| return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
|
| }
|
|
|
| @@ -338,6 +339,10 @@ private:
|
| }
|
| }
|
|
|
| + typedef SkAutoSTMalloc<128, uint8_t> TypefaceBuffer;
|
| + size_t getInProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuffer*);
|
| + size_t getCrossProcessTypefaces(const SkRefCntSet& typefaceSet, TypefaceBuffer*);
|
| +
|
| // Should be called after any calls to an SkFlatDictionary::findAndReplace
|
| // if a new SkFlatData was added when in cross process mode
|
| void flattenFactoryNames();
|
| @@ -411,7 +416,7 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
|
| fBitmapHeap->endAddingOwnersDeferral(added);
|
| int index = flat->index();
|
| if (added) {
|
| - if (isCrossProcess(fFlags)) {
|
| + if (is_cross_process(fFlags)) {
|
| this->flattenFactoryNames();
|
| }
|
| size_t flatSize = flat->flatSize();
|
| @@ -436,10 +441,10 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
|
| SkWriter32* writer, uint32_t flags,
|
| uint32_t width, uint32_t height)
|
| : SkCanvas(width, height)
|
| - , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
|
| + , fFactorySet(is_cross_process(flags) ? SkNEW(SkNamedFactorySet) : NULL)
|
| , fWriter(*writer)
|
| , fFlags(flags)
|
| - , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
|
| + , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, is_cross_process(flags))
|
| , fFlatDictionary(&fFlattenableHeap)
|
| {
|
| fController = controller;
|
| @@ -938,23 +943,76 @@ void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const
|
| }
|
| }
|
|
|
| +size_t SkGPipeCanvas::getInProcessTypefaces(const SkRefCntSet& typefaceSet,
|
| + TypefaceBuffer* buffer) {
|
| + // When in-process, we simply write out the typeface pointers.
|
| + size_t size = typefaceSet.count() * sizeof(SkTypeface*);
|
| + buffer->reset(size);
|
| + typefaceSet.copyToArray(reinterpret_cast<SkRefCnt**>(buffer->get()));
|
| +
|
| + return size;
|
| +}
|
| +
|
| +size_t SkGPipeCanvas::getCrossProcessTypefaces(const SkRefCntSet& typefaceSet,
|
| + TypefaceBuffer* buffer) {
|
| + // For cross-process we use typeface IDs.
|
| + size_t size = typefaceSet.count() * sizeof(uint32_t);
|
| + buffer->reset(size);
|
| +
|
| + uint32_t* idBuffer = reinterpret_cast<uint32_t*>(buffer->get());
|
| + SkRefCntSet::Iter iter(typefaceSet);
|
| + int i = 0;
|
| +
|
| + for (void* setPtr = iter.next(); setPtr; setPtr = iter.next()) {
|
| + idBuffer[i++] = this->getTypefaceID(reinterpret_cast<SkTypeface*>(setPtr));
|
| + }
|
| +
|
| + SkASSERT(i == typefaceSet.count());
|
| +
|
| + return size;
|
| +}
|
| +
|
| void SkGPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
|
| const SkPaint& paint) {
|
| NOTIFY_SETUP(this);
|
| this->writePaint(paint);
|
|
|
| // FIXME: this is inefficient but avoids duplicating the blob serialization logic.
|
| + SkRefCntSet typefaceSet;
|
| SkWriteBuffer blobBuffer;
|
| + blobBuffer.setTypefaceRecorder(&typefaceSet);
|
| blob->flatten(blobBuffer);
|
|
|
| - size_t size = sizeof(uint32_t) + 2 * sizeof(SkScalar) + blobBuffer.bytesWritten();
|
| + // Unlike most draw ops (which only use one paint/typeface), text blobs may reference
|
| + // an arbitrary number of typefaces. Since the one-paint-per-op model is not applicable,
|
| + // we need to serialize these explicitly.
|
| + TypefaceBuffer typefaceBuffer;
|
| + size_t typefaceSize = is_cross_process(fFlags)
|
| + ? this->getCrossProcessTypefaces(typefaceSet, &typefaceBuffer)
|
| + : this->getInProcessTypefaces(typefaceSet, &typefaceBuffer);
|
| +
|
| + // blob byte count + typeface count + x + y + blob data + an index (cross-process)
|
| + // or pointer (in-process) for each typeface
|
| + size_t size = 2 * sizeof(uint32_t)
|
| + + 2 * sizeof(SkScalar)
|
| + + blobBuffer.bytesWritten()
|
| + + typefaceSize;
|
| +
|
| if (this->needOpBytes(size)) {
|
| this->writeOp(kDrawTextBlob_DrawOp);
|
| + SkDEBUGCODE(size_t initialOffset = fWriter.bytesWritten();)
|
| +
|
| fWriter.writeScalar(x);
|
| fWriter.writeScalar(y);
|
| +
|
| + fWriter.write32(typefaceSet.count());
|
| + fWriter.write(typefaceBuffer.get(), typefaceSize);
|
| +
|
| fWriter.write32(SkToU32(blobBuffer.bytesWritten()));
|
| uint32_t* pad = fWriter.reservePad(blobBuffer.bytesWritten());
|
| blobBuffer.writeToMemory(pad);
|
| +
|
| + SkASSERT(initialOffset + size == fWriter.bytesWritten());
|
| }
|
| }
|
|
|
| @@ -1197,7 +1255,7 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
|
| }
|
|
|
| if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
|
| - if (isCrossProcess(fFlags)) {
|
| + if (is_cross_process(fFlags)) {
|
| uint32_t id = this->getTypefaceID(paint.getTypeface());
|
| *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
|
| } else if (this->needOpBytes(sizeof(void*))) {
|
|
|