Added the framework for having canvas/recorder/picture record depth_set's.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2127233002

Committed: https://skia.googlesource.com/skia/+/6d3fb898d5f73a82e36f11c712a633c3921ed518
Review-Url: https://codereview.chromium.org/2127233002
This commit is contained in:
vjiaoblack 2016-07-13 08:35:40 -07:00 committed by Commit bot
parent 0abddf7bb7
commit 1185d90c78
15 changed files with 145 additions and 5 deletions

View File

@ -451,6 +451,13 @@ public:
*/
void resetMatrix();
/** Add the specified translation to the current draw depth of the canvas.
@param z The distance to translate in Z.
Negative into screen, positive out of screen.
Without translation, the draw depth defaults to 0.
*/
void translateZ(SkScalar z);
/**
* Modify the current clip with the specified rectangle.
* @param rect The rect to combine with the current clip
@ -501,7 +508,8 @@ public:
matrix, clipRegion() assumes its argument is already in device
coordinates, and so no transformation is performed.
@param deviceRgn The region to apply to the current clip
@param op The region op to apply to the current clip
@param op The regio
n op to apply to the current clip
*/
void clipRegion(const SkRegion& deviceRgn,
SkRegion::Op op = SkRegion::kIntersect_Op);
@ -1260,6 +1268,10 @@ public:
void temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds);
protected:
/** Returns the current (cumulative) draw depth of the canvas.
*/
SkScalar getZ() const;
/** After calling saveLayer(), there can be any number of devices that make
up the top-most drawing area. LayerIter can be used to iterate through
those devices. Note that the iterator is only valid until the next API
@ -1325,6 +1337,7 @@ protected:
virtual void didRestore() {}
virtual void didConcat(const SkMatrix&) {}
virtual void didSetMatrix(const SkMatrix&) {}
virtual void didTranslateZ(SkScalar) {}
virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);

View File

@ -47,6 +47,7 @@ namespace SkRecords {
M(Save) \
M(SaveLayer) \
M(SetMatrix) \
M(TranslateZ) \
M(Concat) \
M(ClipPath) \
M(ClipRRect) \
@ -218,6 +219,8 @@ RECORD(SetMatrix, 0,
RECORD(Concat, 0,
TypedMatrix matrix);
RECORD(TranslateZ, 0, SkScalar z);
struct RegionOpAndAA {
RegionOpAndAA() {}
RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {}

View File

@ -294,17 +294,22 @@ public:
SkMatrix fMatrix;
int fDeferredSaveCount;
// This is the current cumulative depth (aggregate of all done translateZ calls)
SkScalar fCurDrawDepth;
MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
fFilter = nullptr;
fLayer = nullptr;
fTopLayer = nullptr;
fMatrix.reset();
fDeferredSaveCount = 0;
fCurDrawDepth = 0;
// don't bother initializing fNext
inc_rec();
}
MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix),
fCurDrawDepth(prev.fCurDrawDepth) {
fFilter = SkSafeRef(prev.fFilter);
fLayer = nullptr;
fTopLayer = prev.fTopLayer;
@ -1539,6 +1544,16 @@ void SkCanvas::resetMatrix() {
this->setMatrix(SkMatrix::I());
}
void SkCanvas::translateZ(SkScalar z) {
this->checkForDeferredSave();
this->fMCRec->fCurDrawDepth += z;
this->didTranslateZ(z);
}
SkScalar SkCanvas::getZ() const {
return this->fMCRec->fCurDrawDepth;
}
//////////////////////////////////////////////////////////////////////////////
void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {

View File

@ -52,6 +52,7 @@ enum DrawType {
SAVE_LAYER_SAVEFLAGS_DEPRECATED,
SCALE,
SET_MATRIX,
TRANSLATE_Z,
SKEW,
TRANSLATE,
NOOP,

View File

@ -129,8 +129,8 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
reader->skip(size - 4);
} break;
case CLIP_PATH: {
const SkPath& path = fPictureData->getPath(reader);
uint32_t packed = reader->readInt();
const SkPath& path = fPictureData->getPath(reader);
uint32_t packed = reader->readInt();
SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
bool doAA = ClipParams_unpackDoAA(packed);
size_t offsetToRestore = reader->readInt();
@ -616,6 +616,10 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
SkScalar dy = reader->readScalar();
canvas->translate(dx, dy);
} break;
case TRANSLATE_Z: {
SkScalar dz = reader->readScalar();
canvas->translateZ(dz);
}
default:
SkASSERTF(false, "Unknown draw type: %d", op);
}

View File

@ -218,6 +218,15 @@ void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
this->INHERITED::didSetMatrix(matrix);
}
void SkPictureRecord::didTranslateZ(SkScalar z) {
this->validate(fWriter.bytesWritten(), 0);
// set Z
size_t size = sizeof(SkScalar);
size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
this->validate(initialOffset, size);
}
static bool regionOpExpands(SkRegion::Op op) {
switch (op) {
case SkRegion::kUnion_Op:

View File

@ -159,6 +159,8 @@ protected:
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
void didTranslateZ(SkScalar) override;
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
void onDrawText(const void* text, size_t, SkScalar x, SkScalar y, const SkPaint&) override;

View File

@ -87,6 +87,8 @@ DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa));
DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa));
DRAW(ClipRegion, clipRegion(r.region, r.op));
DRAW(TranslateZ, SkCanvas::translateZ(r.z));
DRAW(DrawBitmap, drawBitmap(r.bitmap.shallowCopy(), r.left, r.top, r.paint));
DRAW(DrawBitmapNine, drawBitmapNine(r.bitmap.shallowCopy(), r.center, r.dst, r.paint));
DRAW(DrawBitmapRect,
@ -288,6 +290,8 @@ private:
void trackBounds(const ClipPath&) { this->pushControl(); }
void trackBounds(const ClipRegion&) { this->pushControl(); }
void trackBounds(const TranslateZ&) { this->pushControl(); }
// For all other ops, we can calculate and store the bounds directly now.
template <typename T> void trackBounds(const T& op) {
fBounds[fCurrentOp] = this->bounds(op);

View File

@ -369,6 +369,10 @@ void SkRecorder::didSetMatrix(const SkMatrix& matrix) {
APPEND(SetMatrix, matrix);
}
void SkRecorder::didTranslateZ(SkScalar z) {
APPEND(TranslateZ, z);
}
void SkRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
INHERITED(onClipRect, rect, op, edgeStyle);
SkRecords::RegionOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);

View File

@ -60,6 +60,7 @@ public:
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
void didTranslateZ(SkScalar) override;
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
void onDrawDrawable(SkDrawable*, const SkMatrix*) override;

View File

@ -779,6 +779,27 @@ DEF_TEST(Canvas_ClipEmptyPath, reporter) {
canvas.restore();
}
class SkTestCanvas : public SkCanvas {
public:
void testUpdateDepth(skiatest::Reporter* reporter) {
// set some depths (with picture enabled), then check them as they get set
REPORTER_ASSERT(reporter, this->getZ() == 0);
this->translateZ(-10);
REPORTER_ASSERT(reporter, this->getZ() == -10);
this->save();
this->translateZ(20);
REPORTER_ASSERT(reporter, this->getZ() == 10);
this->restore();
REPORTER_ASSERT(reporter, this->getZ() == -10);
this->translateZ(13.14f);
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(this->getZ(),3.14f));
}
};
namespace {
class MockFilterCanvas : public SkPaintFilterCanvas {
@ -812,6 +833,11 @@ DEF_TEST(PaintFilterCanvas_ConsistentState, reporter) {
REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
REPORTER_ASSERT(reporter, clip1 == clip2);
SkTestCanvas* tCanvas;
tCanvas = (SkTestCanvas*) new SkCanvas(100,100);
tCanvas->testUpdateDepth(reporter);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -690,6 +690,11 @@ void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
this->INHERITED::didSetMatrix(matrix);
}
void SkDebugCanvas::didTranslateZ(SkScalar z) {
this->addDrawCommand(new SkTranslateZCommand(z));
this->INHERITED::didTranslateZ(z);
}
void SkDebugCanvas::toggleCommand(int index, bool toggle) {
SkASSERT(index < fCommandVector.count());
fCommandVector[index]->setVisible(toggle);

View File

@ -194,6 +194,8 @@ protected:
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
void didTranslateZ(SkScalar) override;
void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,

View File

@ -28,6 +28,7 @@
#define SKDEBUGCANVAS_ATTRIBUTE_COMMAND "command"
#define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE "visible"
#define SKDEBUGCANVAS_ATTRIBUTE_MATRIX "matrix"
#define SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS "drawDepthTranslation"
#define SKDEBUGCANVAS_ATTRIBUTE_COORDS "coords"
#define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS "bounds"
#define SKDEBUGCANVAS_ATTRIBUTE_PAINT "paint"
@ -211,6 +212,7 @@ const char* SkDrawCommand::GetCommandString(OpType type) {
case kSave_OpType: return "Save";
case kSaveLayer_OpType: return "SaveLayer";
case kSetMatrix_OpType: return "SetMatrix";
case kTranslateZ_OpType: return "TranslateZ";
default:
SkDebugf("OpType error 0x%08x\n", type);
SkASSERT(0);
@ -268,6 +270,8 @@ SkDrawCommand* SkDrawCommand::fromJSON(Json::Value& command, UrlDataManager& url
INSTALL_FACTORY(Save);
INSTALL_FACTORY(SaveLayer);
INSTALL_FACTORY(SetMatrix);
INSTALL_FACTORY(TranslateZ);
}
SkString name = SkString(command[SKDEBUGCANVAS_ATTRIBUTE_COMMAND].asCString());
FROM_JSON* factory = factories.find(name);
@ -470,6 +474,11 @@ Json::Value SkDrawCommand::MakeJsonMatrix(const SkMatrix& matrix) {
return result;
}
Json::Value SkDrawCommand::MakeJsonScalar(SkScalar z) {
Json::Value result(z);
return result;
}
Json::Value SkDrawCommand::MakeJsonPath(const SkPath& path) {
Json::Value result(Json::objectValue);
switch (path.getFillType()) {
@ -1482,6 +1491,11 @@ static void extract_json_matrix(Json::Value& matrix, SkMatrix* result) {
result->set9(values);
}
static void extract_json_scalar(Json::Value& scalar, SkScalar* result) {
SkScalar value = scalar.asFloat();
*result = value;
}
static void extract_json_path(Json::Value& path, SkPath* result) {
const char* fillType = path[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE].asCString();
if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_WINDING)) {
@ -3295,3 +3309,26 @@ SkSetMatrixCommand* SkSetMatrixCommand::fromJSON(Json::Value& command,
extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
return new SkSetMatrixCommand(matrix);
}
SkTranslateZCommand::SkTranslateZCommand(SkScalar z)
: INHERITED(kTranslateZ_OpType) {
fZTranslate = z;
fInfo.push(SkObjectParser::ScalarToString(fZTranslate, "drawDepthTranslation"));
}
void SkTranslateZCommand::execute(SkCanvas* canvas) const {
canvas->translateZ(fZTranslate);
}
Json::Value SkTranslateZCommand::toJSON(UrlDataManager& urlDataManager) const {
Json::Value result = INHERITED::toJSON(urlDataManager);
result[SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS] = MakeJsonScalar(fZTranslate);
return result;
}
SkTranslateZCommand* SkTranslateZCommand::fromJSON(Json::Value& command,
UrlDataManager& urlDataManager) {
SkScalar z;
extract_json_scalar(command[SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS], &z);
return new SkTranslateZCommand(z);
}

View File

@ -56,8 +56,9 @@ public:
kSave_OpType,
kSaveLayer_OpType,
kSetMatrix_OpType,
kTranslateZ_OpType,
kLast_OpType = kSetMatrix_OpType
kLast_OpType = kTranslateZ_OpType
};
static const int kOpTypeCount = kLast_OpType + 1;
@ -125,6 +126,7 @@ public:
static Json::Value MakeJsonRect(const SkRect& rect);
static Json::Value MakeJsonIRect(const SkIRect&);
static Json::Value MakeJsonMatrix(const SkMatrix&);
static Json::Value MakeJsonScalar(SkScalar);
static Json::Value MakeJsonPath(const SkPath& path);
static Json::Value MakeJsonRegion(const SkRegion& region);
static Json::Value MakeJsonPaint(const SkPaint& paint, UrlDataManager& urlDataManager);
@ -731,4 +733,16 @@ private:
typedef SkDrawCommand INHERITED;
};
class SkTranslateZCommand : public SkDrawCommand {
public:
SkTranslateZCommand(SkScalar);
void execute(SkCanvas* canvas) const override;
Json::Value toJSON(UrlDataManager& urlDataManager) const override;
static SkTranslateZCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
private:
SkScalar fZTranslate;
typedef SkDrawCommand INHERITED;
};
#endif