aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expectations/gm/ignored-tests.txt3
-rw-r--r--gm/textblob.cpp8
-rw-r--r--src/core/SkPtrRecorder.h21
-rw-r--r--src/pipe/SkGPipeRead.cpp18
-rw-r--r--src/pipe/SkGPipeWrite.cpp70
5 files changed, 109 insertions, 11 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 377575edad..0e6ef7918f 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -41,3 +41,6 @@ multipicturedraw_pathclip_tiled
# rileya - https://codereview.chromium.org/516463005/ will rebaseline after bots cycle
yuv_to_rgb_effect
+
+# fmalita - added typeface to test pipe serialization
+textblob
diff --git a/gm/textblob.cpp b/gm/textblob.cpp
index 6837363898..a0340071f7 100644
--- a/gm/textblob.cpp
+++ b/gm/textblob.cpp
@@ -66,8 +66,10 @@ const SkScalar kFontSize = 16;
class TextBlobGM : public skiagm::GM {
public:
- TextBlobGM(const char* txt) {
+ TextBlobGM(const char* txt)
+ : fTypeface(sk_tool_utils::create_portable_typeface("Times", SkTypeface::kNormal)) {
SkPaint p;
+ p.setTypeface(fTypeface);
size_t txtLen = strlen(txt);
int glyphCount = p.textToGlyphs(txt, txtLen, NULL);
@@ -111,6 +113,7 @@ private:
font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
font.setAntiAlias(true);
font.setSubpixelText(true);
+ font.setTypeface(fTypeface);
for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
unsigned currentGlyph = 0;
@@ -173,7 +176,8 @@ private:
return builder.build();
}
- SkTDArray<uint16_t> fGlyphs;
+ SkTDArray<uint16_t> fGlyphs;
+ SkAutoTUnref<SkTypeface> fTypeface;
typedef skiagm::GM INHERITED;
};
diff --git a/src/core/SkPtrRecorder.h b/src/core/SkPtrRecorder.h
index 06e14ab6ec..83200f5275 100644
--- a/src/core/SkPtrRecorder.h
+++ b/src/core/SkPtrRecorder.h
@@ -58,6 +58,27 @@ public:
*/
void reset();
+ /**
+ * Set iterator.
+ */
+ class Iter {
+ public:
+ Iter(const SkPtrSet& set)
+ : fSet(set)
+ , fIndex(0) {}
+
+ /**
+ * Return the next ptr in the set or null if the end was reached.
+ */
+ void* next() {
+ return fIndex < fSet.fList.count() ? fSet.fList[fIndex++].fPtr : NULL;
+ }
+
+ private:
+ const SkPtrSet& fSet;
+ int fIndex;
+ };
+
protected:
virtual void incPtr(void*) {}
virtual void decPtr(void*) {}
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 4bd4fa6a5c..8cb0e34d0a 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -194,8 +194,8 @@ public:
*fTypefaces.append() = SkTypeface::Deserialize(&stream);
}
- void setTypeface(SkPaint* paint, unsigned id) {
- paint->setTypeface(id ? fTypefaces[id - 1] : NULL);
+ SkTypeface* getTypeface(unsigned id) const {
+ return id ? fTypefaces[id - 1] : NULL;
}
private:
@@ -676,11 +676,22 @@ static void drawTextBlob_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkScalar x = reader->readScalar();
SkScalar y = reader->readScalar();
+ int typefaceCount = reader->readU32();
+ SkAutoSTMalloc<16, SkTypeface*> typefaceArray(typefaceCount);
+ if (state->getFlags() & SkGPipeWriter::kCrossProcess_Flag) {
+ for (int i = 0; i < typefaceCount; ++i) {
+ typefaceArray[i] = state->getTypeface(reader->readU32());
+ }
+ } else {
+ reader->read(typefaceArray.get(), typefaceCount * sizeof(SkTypeface*));
+ }
+
size_t blobSize = reader->readU32();
const void* data = reader->skip(SkAlign4(blobSize));
if (state->shouldDraw()) {
SkReadBuffer blobBuffer(data, blobSize);
+ blobBuffer.setTypefaceArray(typefaceArray.get(), typefaceCount);
SkAutoTUnref<const SkTextBlob> blob(SkTextBlob::CreateFromBuffer(blobBuffer));
SkASSERT(blob.get());
@@ -731,7 +742,8 @@ static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
case kTypeface_PaintOp:
SkASSERT(SkToBool(state->getFlags() &
SkGPipeWriter::kCrossProcess_Flag));
- state->setTypeface(p, data); break;
+ p->setTypeface(state->getTypeface(data));
+ break;
default: SkDEBUGFAIL("bad paintop"); return;
}
SkASSERT(reader->offset() <= stop);
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index f361e5ed67..41b0234480 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*))) {