diff --git a/gn/flutter_defines.gni b/gn/flutter_defines.gni index 97be7d8d66..e880850586 100644 --- a/gn/flutter_defines.gni +++ b/gn/flutter_defines.gni @@ -13,6 +13,7 @@ flutter_defines = [ "SK_DISABLE_AAA", # API staging + "SK_SUPPORT_LEGACY_CANVAS_MATRIX_VIRTUALS", # Flutter doesn't deserialize anything. "SK_DISABLE_READBUFFER", diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 36b9c46983..9b5b1078c8 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -2554,13 +2554,24 @@ protected: virtual bool onDoSaveBehind(const SkRect*) { return true; } virtual void willRestore() {} virtual void didRestore() {} - virtual void didConcat(const SkMatrix& ) {} - virtual void didSetMatrix(const SkMatrix& ) {} + + // These are called when the canvas' matrix is modified. They are passed the new value(s) + // that are being pre-concat with the CTM. Even though everything could be expressed with + // just didConcat44(), we have 3 other specializations: translate, scale, concat (3x3), + // to save the SkCanvas from having to construct the 4x4 matrix each time. + // + virtual void didConcat44(const SkScalar[16]) {} // column major + virtual void didConcat(const SkMatrix&) {} + virtual void didSetMatrix(const SkMatrix&) {} +#ifdef SK_SUPPORT_LEGACY_CANVAS_MATRIX_VIRTUALS virtual void didTranslate(SkScalar dx, SkScalar dy) { this->didConcat(SkMatrix::MakeTrans(dx, dy)); } - // just pass an array for now, until we decide on the "public" form for the matrix - virtual void didConcat44(const SkScalar[]) {} +#else + virtual void didTranslate(SkScalar, SkScalar) {} +#endif + // is only called if SK_SUPPORT_LEGACY_CANVAS_MATRIX_VIRTUALS is not set + virtual void didScale(SkScalar, SkScalar) {} // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using diff --git a/include/private/SkM44.h b/include/private/SkM44.h index 7fd7945946..3dfd768255 100644 --- a/include/private/SkM44.h +++ b/include/private/SkM44.h @@ -157,8 +157,11 @@ public: } SkM44& preTranslate(SkScalar x, SkScalar y); + SkM44& preScale(SkScalar x, SkScalar y); SkM44& preConcat(const SkMatrix&); + const SkScalar* peek_colMajor() const { return fMat; } + private: /* Stored in column-major. * Indices diff --git a/include/utils/SkLuaCanvas.h b/include/utils/SkLuaCanvas.h index f75c8f219c..5ae4fd1e27 100644 --- a/include/utils/SkLuaCanvas.h +++ b/include/utils/SkLuaCanvas.h @@ -27,8 +27,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, diff --git a/include/utils/SkNWayCanvas.h b/include/utils/SkNWayCanvas.h index 72bed680bf..1b2673eebb 100644 --- a/include/utils/SkNWayCanvas.h +++ b/include/utils/SkNWayCanvas.h @@ -30,8 +30,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 17978aefb6..08e1b84e50 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1439,9 +1439,24 @@ void SkCanvas::translate(SkScalar dx, SkScalar dy) { } void SkCanvas::scale(SkScalar sx, SkScalar sy) { +#ifdef SK_SUPPORT_LEGACY_CANVAS_MATRIX_VIRTUALS SkMatrix m; m.setScale(sx, sy); this->concat(m); +#else + if (sx != 1 || sy != 1) { + this->checkForDeferredSave(); + fMCRec->fMatrix.preScale(sx, sy); + + // shouldn't need to do this (theoretically), as the state shouldn't have changed, + // but pre-scaling by a non-finite does change it, so we have to recompute. + fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate(); + + FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix)); + + this->didScale(sx, sy); + } +#endif } void SkCanvas::rotate(SkScalar degrees) { diff --git a/src/core/SkCanvasMatrix.h b/src/core/SkCanvasMatrix.h index a3038b868d..fe1605f34f 100644 --- a/src/core/SkCanvasMatrix.h +++ b/src/core/SkCanvasMatrix.h @@ -18,6 +18,7 @@ public: void reset() { fM.setIdentity(); } void preTranslate(SkScalar x, SkScalar y) { fM.preTranslate(x, y); } + void preScale(SkScalar x, SkScalar y) { fM.preScale(x, y); } void preConcat(const SkMatrix& m) { fM.preConcat(m); } void preConcat44(const SkScalar m[]) { fM.setConcat(fM, m); } diff --git a/src/core/SkM44.cpp b/src/core/SkM44.cpp index 7cd1218efd..37e9c982e7 100644 --- a/src/core/SkM44.cpp +++ b/src/core/SkM44.cpp @@ -92,11 +92,19 @@ SkM44& SkM44::preTranslate(SkScalar x, SkScalar y) { sk4f c1 = sk4f::Load(fMat + 4); sk4f c3 = sk4f::Load(fMat + 12); - // only need to update the last column skvx::mad(c0, x, skvx::mad(c1, y, c3)).store(fMat + 12); return *this; } +SkM44& SkM44::preScale(SkScalar x, SkScalar y) { + sk4f c0 = sk4f::Load(fMat + 0); + sk4f c1 = sk4f::Load(fMat + 4); + + (c0 * x).store(fMat + 0); + (c1 * y).store(fMat + 4); + return *this; +} + /////////////////////////////////////////////////////////////////////////////// /** We always perform the calculation in doubles, to avoid prematurely losing diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index 715d131f97..7a8863b8dd 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -104,8 +104,9 @@ enum DrawType { DRAW_EDGEAA_QUAD, DRAW_BEHIND_PAINT, + CONCAT44, - LAST_DRAWTYPE_ENUM = DRAW_BEHIND_PAINT, + LAST_DRAWTYPE_ENUM = CONCAT44, }; enum DrawVertexFlags { diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 46ba4a42d2..23fe725d1f 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -219,6 +219,25 @@ void SkPictureRecord::recordScale(const SkMatrix& m) { this->validate(initialOffset, size); } +void SkPictureRecord::didConcat44(const SkScalar m[16]) { + this->validate(fWriter.bytesWritten(), 0); + // op + matrix + size_t size = kUInt32Size + 16 * sizeof(SkScalar); + size_t initialOffset = this->addDraw(CONCAT44, &size); + fWriter.write(m, 16 * sizeof(SkScalar)); + this->validate(initialOffset, size); + + this->INHERITED::didConcat44(m); +} + +void SkPictureRecord::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} + +void SkPictureRecord::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} + void SkPictureRecord::didConcat(const SkMatrix& matrix) { switch (matrix.getType()) { case SkMatrix::kTranslate_Mask: diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index b83eec2893..3b9d45af63 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -162,8 +162,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 16827f07a4..17b8e628dd 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -93,8 +93,10 @@ template <> void Draw::draw(const DrawBehind& r) { } DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); +DRAW(Concat44, concat44(r.matrix.peek_colMajor())); DRAW(Concat, concat(r.matrix)); DRAW(Translate, translate(r.dx, r.dy)); +DRAW(Scale, scale(r.sx, r.sy)); DRAW(ClipPath, clipPath(r.path, r.opAA.op(), r.opAA.aa())); DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op(), r.opAA.aa())); @@ -246,7 +248,9 @@ private: template void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = op.matrix; } + void updateCTM(const Concat44& op) { fCTM.preConcat(op.matrix.asM33()); } void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); } + void updateCTM(const Scale& op) { fCTM.preScale(op.sx, op.sy); } void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); } // The bounds of these ops must be calculated when we hit the Restore @@ -258,6 +262,8 @@ private: void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const Concat&) { this->pushControl(); } + void trackBounds(const Concat44&) { this->pushControl(); } + void trackBounds(const Scale&) { this->pushControl(); } void trackBounds(const Translate&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index df584499bb..bc94cfcec6 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -370,6 +370,10 @@ void SkRecorder::didRestore() { this->append(this->getTotalMatrix()); } +void SkRecorder::didConcat44(const SkScalar m[16]) { + this->append(m); +} + void SkRecorder::didConcat(const SkMatrix& matrix) { this->append(matrix); } @@ -378,6 +382,10 @@ void SkRecorder::didSetMatrix(const SkMatrix& matrix) { this->append(matrix); } +void SkRecorder::didScale(SkScalar sx, SkScalar sy) { + this->append(sx, sy); +} + void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) { this->append(dx, dy); } diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h index c20f84cf8c..f15ee1b462 100644 --- a/src/core/SkRecorder.h +++ b/src/core/SkRecorder.h @@ -67,8 +67,10 @@ public: void willRestore() override {} void didRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; void didTranslate(SkScalar, SkScalar) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h index 2c246961bc..e97a13543f 100644 --- a/src/core/SkRecords.h +++ b/src/core/SkRecords.h @@ -23,6 +23,7 @@ #include "include/core/SkString.h" #include "include/core/SkTextBlob.h" #include "include/core/SkVertices.h" +#include "include/private/SkM44.h" #include "src/core/SkDrawShadowInfo.h" namespace SkRecords { @@ -46,7 +47,9 @@ namespace SkRecords { M(SaveBehind) \ M(SetMatrix) \ M(Translate) \ + M(Scale) \ M(Concat) \ + M(Concat44) \ M(ClipPath) \ M(ClipRRect) \ M(ClipRect) \ @@ -153,6 +156,13 @@ struct TypedMatrix : public SkMatrix { TypedMatrix(const SkMatrix& matrix); }; +struct Matrix44 : public SkM44 { + Matrix44() {} + Matrix44(const SkScalar m[16]) { + this->setColMajor(m); + } +}; + enum Tags { kDraw_Tag = 1, // May draw something (usually named DrawFoo). kHasImage_Tag = 2, // Contains an SkImage or SkBitmap. @@ -191,11 +201,17 @@ RECORD(SetMatrix, 0, TypedMatrix matrix); RECORD(Concat, 0, TypedMatrix matrix); +RECORD(Concat44, 0, + Matrix44 matrix); RECORD(Translate, 0, SkScalar dx; SkScalar dy); +RECORD(Scale, 0, + SkScalar sx; + SkScalar sy); + struct ClipOpAndAA { ClipOpAndAA() {} ClipOpAndAA(SkClipOp op, bool aa) : fOp(static_cast(op)), fAA(aa) {} diff --git a/src/utils/SkLuaCanvas.cpp b/src/utils/SkLuaCanvas.cpp index f756ee6c6e..060a1e16d3 100644 --- a/src/utils/SkLuaCanvas.cpp +++ b/src/utils/SkLuaCanvas.cpp @@ -110,6 +110,15 @@ void SkLuaCanvas::willRestore() { this->INHERITED::willRestore(); } +void SkLuaCanvas::didConcat44(const SkScalar m[16]) { + // TODO +} +void SkLuaCanvas::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} +void SkLuaCanvas::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} void SkLuaCanvas::didConcat(const SkMatrix& matrix) { switch (matrix.getType()) { case SkMatrix::kTranslate_Mask: { diff --git a/src/utils/SkNWayCanvas.cpp b/src/utils/SkNWayCanvas.cpp index 1ce6318e5c..245be9ce73 100644 --- a/src/utils/SkNWayCanvas.cpp +++ b/src/utils/SkNWayCanvas.cpp @@ -92,6 +92,14 @@ void SkNWayCanvas::willRestore() { this->INHERITED::willRestore(); } +void SkNWayCanvas::didConcat44(const SkScalar m[16]) { + Iter iter(fList); + while (iter.next()) { + iter->concat44(m); + } + this->INHERITED::didConcat44(m); +} + void SkNWayCanvas::didConcat(const SkMatrix& matrix) { Iter iter(fList); while (iter.next()) { @@ -108,6 +116,22 @@ void SkNWayCanvas::didSetMatrix(const SkMatrix& matrix) { this->INHERITED::didSetMatrix(matrix); } +void SkNWayCanvas::didScale(SkScalar x, SkScalar y) { + Iter iter(fList); + while (iter.next()) { + iter->scale(x, y); + } + this->INHERITED::didScale(x, y); +} + +void SkNWayCanvas::didTranslate(SkScalar x, SkScalar y) { + Iter iter(fList); + while (iter.next()) { + iter->translate(x, y); + } + this->INHERITED::didTranslate(x, y); +} + void SkNWayCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) { Iter iter(fList); while (iter.next()) { diff --git a/tests/RecordDrawTest.cpp b/tests/RecordDrawTest.cpp index f9b463f4cc..2c80dc77b1 100644 --- a/tests/RecordDrawTest.cpp +++ b/tests/RecordDrawTest.cpp @@ -46,7 +46,7 @@ DEF_TEST(RecordDraw_LazySaves, r) { assert_type(r, record, 0); assert_type (r, record, 1); - assert_type (r, record, 2); + assert_type (r, record, 2); assert_type (r, record, 3); recorder.save(); diff --git a/tools/debugger/DebugCanvas.cpp b/tools/debugger/DebugCanvas.cpp index 578b001c25..14a94bbc01 100644 --- a/tools/debugger/DebugCanvas.cpp +++ b/tools/debugger/DebugCanvas.cpp @@ -312,6 +312,19 @@ void DebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) { this->addDrawCommand(new ClipRegionCommand(region, op)); } +void DebugCanvas::didConcat44(const SkScalar m[16]) { + // TODO + this->INHERITED::didConcat44(m); +} + +void DebugCanvas::didScale(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeScale(x, y)); +} + +void DebugCanvas::didTranslate(SkScalar x, SkScalar y) { + this->didConcat(SkMatrix::MakeTrans(x, y)); +} + void DebugCanvas::didConcat(const SkMatrix& matrix) { this->addDrawCommand(new ConcatCommand(matrix)); this->INHERITED::didConcat(matrix); diff --git a/tools/debugger/DebugCanvas.h b/tools/debugger/DebugCanvas.h index 9053f7cd56..d7ddafca89 100644 --- a/tools/debugger/DebugCanvas.h +++ b/tools/debugger/DebugCanvas.h @@ -129,9 +129,11 @@ protected: bool onDoSaveBehind(const SkRect*) override; void willRestore() override; + void didConcat44(const SkScalar[16]) override; void didConcat(const SkMatrix&) override; - void didSetMatrix(const SkMatrix&) override; + void didScale(SkScalar, SkScalar) override; + void didTranslate(SkScalar, SkScalar) override; void onDrawAnnotation(const SkRect&, const char[], SkData*) override; void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;