In SkGPipe, only serialize SkTypefaces in cross process mode.
Also make SkGPipeController ref the recording canvas to ensure that objects used by SkGPipeCanvas (e.g. SharedHeap and fTypefaceSet, which hold references to objects to which pointers are written to the stream) survive to be played back even if SkGPipeWriter.endRecording() is called. BUG= TEST=TypefaceGM Review URL: https://codereview.appspot.com/6447055 git-svn-id: http://skia.googlecode.com/svn/trunk@4817 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
cc6e5efe03
commit
3cb969f27d
83
gm/typeface.cpp
Normal file
83
gm/typeface.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkString.h"
|
||||
#include "SkTypeface.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
const char* gFaces[] = {
|
||||
"Times Roman",
|
||||
"Hiragino Maru Gothic Pro",
|
||||
"Papyrus",
|
||||
"Helvetica",
|
||||
"Courier New"
|
||||
};
|
||||
|
||||
class TypefaceGM : public GM {
|
||||
public:
|
||||
TypefaceGM() {
|
||||
fFaces = new SkTypeface*[SK_ARRAY_COUNT(gFaces)];
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) {
|
||||
fFaces[i] = SkTypeface::CreateFromName(gFaces[i], SkTypeface::kNormal);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TypefaceGM() {
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) {
|
||||
fFaces[i]->unref();
|
||||
}
|
||||
delete fFaces;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual SkString onShortName() SK_OVERRIDE {
|
||||
return SkString("typeface");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() SK_OVERRIDE {
|
||||
return SkISize::Make(640, 480);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||
SkString text("Typefaces are fun!");
|
||||
SkScalar y = 0;
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gFaces); i++) {
|
||||
this->drawWithFace(text, i, y, paint, canvas);
|
||||
}
|
||||
// Now go backwards
|
||||
for (int i = SK_ARRAY_COUNT(gFaces) - 1; i >= 0; i--) {
|
||||
this->drawWithFace(text, i, y, paint, canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void drawWithFace(const SkString& text, int i, SkScalar& y, SkPaint& paint,
|
||||
SkCanvas* canvas) {
|
||||
paint.setTypeface(fFaces[i]);
|
||||
y += paint.getFontMetrics(NULL);
|
||||
canvas->drawText(text.c_str(), text.size(), 0, y, paint);
|
||||
}
|
||||
|
||||
SkTypeface** fFaces;
|
||||
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static GM* MyFactory(void*) { return new TypefaceGM; }
|
||||
static GMRegistry reg(MyFactory);
|
||||
|
||||
} // skiagm
|
@ -62,6 +62,7 @@
|
||||
'../gm/tilemodes.cpp',
|
||||
'../gm/tinybitmap.cpp',
|
||||
'../gm/twopointradial.cpp',
|
||||
'../gm/typeface.cpp',
|
||||
'../gm/verttext.cpp',
|
||||
'../gm/verttext2.cpp',
|
||||
'../gm/xfermodes.cpp',
|
||||
|
@ -46,8 +46,13 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SkGPipeCanvas;
|
||||
|
||||
class SkGPipeController {
|
||||
public:
|
||||
SkGPipeController() : fCanvas(NULL) {}
|
||||
virtual ~SkGPipeController();
|
||||
|
||||
/**
|
||||
* Called periodically by the writer, to get a working buffer of RAM to
|
||||
* write into. The actual size of the block is also returned, and must be
|
||||
@ -69,6 +74,12 @@ public:
|
||||
*/
|
||||
virtual void notifyWritten(size_t bytes) = 0;
|
||||
virtual int numberOfReaders() const { return 1; }
|
||||
|
||||
private:
|
||||
friend class SkGPipeWriter;
|
||||
void setCanvas(SkGPipeCanvas*);
|
||||
|
||||
SkGPipeCanvas* fCanvas;
|
||||
};
|
||||
|
||||
class SkGPipeWriter {
|
||||
@ -116,9 +127,9 @@ public:
|
||||
size_t storageAllocatedForRecording();
|
||||
|
||||
private:
|
||||
class SkGPipeCanvas* fCanvas;
|
||||
SkFactorySet fFactorySet;
|
||||
SkWriter32 fWriter;
|
||||
SkGPipeCanvas* fCanvas;
|
||||
SkFactorySet* fFactorySet;
|
||||
SkWriter32 fWriter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,7 @@ enum DrawOps {
|
||||
kTranslate_DrawOp,
|
||||
|
||||
kPaintOp_DrawOp,
|
||||
kSetTypeface_DrawOp,
|
||||
|
||||
kDef_Typeface_DrawOp,
|
||||
kDef_Flattenable_DrawOp,
|
||||
@ -193,8 +194,8 @@ private:
|
||||
};
|
||||
|
||||
static inline bool shouldFlattenBitmaps(uint32_t flags) {
|
||||
return flags & SkGPipeWriter::kCrossProcess_Flag
|
||||
&& !(flags & SkGPipeWriter::kSharedAddressSpace_Flag);
|
||||
return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag
|
||||
&& !(flags & SkGPipeWriter::kSharedAddressSpace_Flag));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -509,13 +509,23 @@ static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
|
||||
break;
|
||||
}
|
||||
|
||||
case kTypeface_PaintOp: state->setTypeface(p, data); break;
|
||||
case kTypeface_PaintOp:
|
||||
SkASSERT(SkToBool(state->getFlags() &
|
||||
SkGPipeWriter::kCrossProcess_Flag));
|
||||
state->setTypeface(p, data); break;
|
||||
default: SkDEBUGFAIL("bad paintop"); return;
|
||||
}
|
||||
SkASSERT(reader->offset() <= stop);
|
||||
} while (reader->offset() < stop);
|
||||
}
|
||||
|
||||
static void typeface_rp(SkCanvas*, SkReader32* reader, uint32_t,
|
||||
SkGPipeState* state) {
|
||||
SkASSERT(!SkToBool(state->getFlags() & SkGPipeWriter::kCrossProcess_Flag));
|
||||
SkPaint* p = state->editPaint();
|
||||
p->setTypeface(static_cast<SkTypeface*>(reader->readPtr()));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void def_Typeface_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState* state) {
|
||||
@ -585,6 +595,7 @@ static const ReadProc gReadTable[] = {
|
||||
translate_rp,
|
||||
|
||||
paintOp_rp,
|
||||
typeface_rp,
|
||||
def_Typeface_rp,
|
||||
def_PaintFlat_rp,
|
||||
def_Bitmap_rp,
|
||||
|
@ -522,7 +522,7 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
|
||||
}
|
||||
|
||||
uint32_t writeBufferFlags;
|
||||
if (fFlags & SkGPipeWriter::kCrossProcess_Flag) {
|
||||
if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) {
|
||||
writeBufferFlags = (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
|
||||
| SkFlattenableWriteBuffer::kCrossProcess_Flag);
|
||||
} else {
|
||||
@ -1213,8 +1213,18 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
|
||||
}
|
||||
|
||||
if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
|
||||
uint32_t id = this->getTypefaceID(paint.getTypeface());
|
||||
*ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
|
||||
if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) {
|
||||
uint32_t id = this->getTypefaceID(paint.getTypeface());
|
||||
*ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
|
||||
} else if (this->needOpBytes(sizeof(void*))) {
|
||||
// Add to the set for ref counting.
|
||||
fTypefaceSet.add(paint.getTypeface());
|
||||
// It is safe to write the typeface to the stream before the rest
|
||||
// of the paint unless we ever send a kReset_PaintOp, which we
|
||||
// currently never do.
|
||||
this->writeOp(kSetTypeface_DrawOp);
|
||||
fWriter.writePtr(paint.getTypeface());
|
||||
}
|
||||
base.setTypeface(paint.getTypeface());
|
||||
}
|
||||
|
||||
@ -1251,23 +1261,36 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
|
||||
|
||||
#include "SkGPipe.h"
|
||||
|
||||
SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
|
||||
SkGPipeController::~SkGPipeController() {
|
||||
SkSafeUnref(fCanvas);
|
||||
}
|
||||
|
||||
void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
|
||||
SkRefCnt_SafeAssign(fCanvas, canvas);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkGPipeWriter::SkGPipeWriter()
|
||||
: fFactorySet(SkNEW(SkFactorySet))
|
||||
, fWriter(0) {
|
||||
fCanvas = NULL;
|
||||
}
|
||||
|
||||
SkGPipeWriter::~SkGPipeWriter() {
|
||||
this->endRecording();
|
||||
SkSafeUnref(fCanvas);
|
||||
fFactorySet->unref();
|
||||
}
|
||||
|
||||
SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
|
||||
if (NULL == fCanvas) {
|
||||
fWriter.reset(NULL, 0);
|
||||
fFactorySet.reset();
|
||||
fFactorySet->reset();
|
||||
fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
|
||||
(flags & kCrossProcess_Flag) ?
|
||||
&fFactorySet : NULL, flags));
|
||||
fFactorySet : NULL, flags));
|
||||
}
|
||||
controller->setCanvas(fCanvas);
|
||||
return fCanvas;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user