virtual void didRestore() {}
virtual void didConcat(const SkMatrix&) {}
virtual void didSetMatrix(const SkMatrix&) {}
+ virtual void didTranslate(SkScalar dx, SkScalar dy) {
+ this->didConcat(SkMatrix::MakeTrans(dx, dy));
+ }
#ifdef SK_EXPERIMENTAL_SHADOWING
virtual void didTranslateZ(SkScalar) {}
M(Save) \
M(SaveLayer) \
M(SetMatrix) \
+ M(Translate) \
M(TranslateZ) \
M(Concat) \
M(ClipPath) \
RECORD(Concat, 0,
TypedMatrix matrix);
+RECORD(Translate, 0,
+ SkScalar dx;
+ SkScalar dy);
RECORD(TranslateZ, 0, SkScalar z);
struct RegionOpAndAA {
/////////////////////////////////////////////////////////////////////////////
void SkCanvas::translate(SkScalar dx, SkScalar dy) {
- SkMatrix m;
- m.setTranslate(dx, dy);
- this->concat(m);
+ this->checkForDeferredSave();
+ fDeviceCMDirty = true;
+ fMCRec->fMatrix.preTranslate(dx,dy);
+
+ // Translate shouldn't affect the is-scale-translateness of the matrix.
+ SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
+
+ this->didTranslate(dx,dy);
}
void SkCanvas::scale(SkScalar sx, SkScalar sy) {
namespace {
#define TYPES(M) \
M(Save) M(Restore) M(SaveLayer) \
- M(Concat) M(SetMatrix) M(TranslateZ) \
+ M(Concat) M(SetMatrix) M(Translate) M(TranslateZ) \
M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \
M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawOval) M(DrawRRect) M(DrawDRRect) \
M(DrawAnnotation) M(DrawDrawable) M(DrawPicture) M(DrawShadowedPicture) \
}
void makeThreadsafe() { make_threadsafe(nullptr, &matrix); }
};
+ struct Translate final : Op {
+ static const auto kType = Type::Translate;
+ Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
+ SkScalar dx,dy;
+ void draw(SkCanvas* c, const SkMatrix&) {
+ c->translate(dx, dy);
+ }
+ };
struct TranslateZ final : Op {
static const auto kType = Type::TranslateZ;
TranslateZ(SkScalar dz) : dz(dz) {}
this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
}
-void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); }
-void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); }
+void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); }
+void SkLiteDL::setMatrix(const SkMatrix& matrix) { this->push<SetMatrix>(0, matrix); }
+void SkLiteDL::translate(SkScalar dx, SkScalar dy) { this->push<Translate>(0, dx, dy); }
void SkLiteDL::translateZ(SkScalar dz) { this->push<TranslateZ>(0, dz); }
void SkLiteDL::clipPath(const SkPath& path, SkRegion::Op op, bool aa) {
void concat (const SkMatrix&);
void setMatrix (const SkMatrix&);
+ void translate(SkScalar, SkScalar);
void translateZ(SkScalar);
void clipPath (const SkPath&, SkRegion::Op, bool aa);
}
void SkLiteRecorder::willRestore() { fDL->restore(); }
-void SkLiteRecorder::didConcat (const SkMatrix& matrix) { fDL-> concat(matrix); }
-void SkLiteRecorder::didSetMatrix(const SkMatrix& matrix) { fDL->setMatrix(matrix); }
+void SkLiteRecorder::didConcat (const SkMatrix& matrix) { fDL-> concat(matrix); }
+void SkLiteRecorder::didSetMatrix(const SkMatrix& matrix) { fDL->setMatrix(matrix); }
+void SkLiteRecorder::didTranslate(SkScalar dx, SkScalar dy) { fDL->translate(dx, dy); }
void SkLiteRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle style) {
fDL->clipRect(rect, op, style==kSoft_ClipEdgeStyle);
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
+ void didTranslate(SkScalar, SkScalar) override;
void onClipRect (const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
void onClipRRect (const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
return;
}
- if (this->hasPerspective()) {
+ if (fTypeMask <= kTranslate_Mask) {
+ fMat[kMTransX] += dx;
+ fMat[kMTransY] += dy;
+ this->setTypeMask((fMat[kMTransX] != 0 || fMat[kMTransY] != 0) ? kTranslate_Mask
+ : kIdentity_Mask);
+ } else if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
this->preConcat(m);
void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
SkASSERT(dst);
SkASSERT(this->isScaleTranslate());
-
+
SkScalar sx = fMat[kMScaleX];
SkScalar sy = fMat[kMScaleY];
SkScalar tx = fMat[kMTransX];
r.saveLayerFlags)));
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
DRAW(Concat, concat(r.matrix));
+DRAW(Translate, translate(r.dx, r.dy));
DRAW(ClipPath, clipPath(r.path, r.opAA.op, r.opAA.aa));
DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa));
SkMatrix ctm;
};
- // Only Restore, SetMatrix, and Concat change the CTM.
+ // Only Restore, SetMatrix, Concat, and Translate change the CTM.
template <typename T> void updateCTM(const T&) {}
void updateCTM(const Restore& op) { fCTM = op.matrix; }
void updateCTM(const SetMatrix& op) { fCTM = op.matrix; }
void updateCTM(const Concat& op) { fCTM.preConcat(op.matrix); }
+ void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); }
// Most ops don't change the clip.
template <typename T> void updateClipBounds(const T&) {}
void trackBounds(const SetMatrix&) { this->pushControl(); }
void trackBounds(const Concat&) { this->pushControl(); }
+ void trackBounds(const Translate&) { this->pushControl(); }
+ void trackBounds(const TranslateZ&) { this->pushControl(); }
void trackBounds(const ClipRect&) { this->pushControl(); }
void trackBounds(const ClipRRect&) { this->pushControl(); }
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) {
APPEND(SetMatrix, matrix);
}
+void SkRecorder::didTranslate(SkScalar dx, SkScalar dy) {
+ APPEND(Translate, dx, dy);
+}
+
void SkRecorder::didTranslateZ(SkScalar z) {
#ifdef SK_EXPERIMENTAL_SHADOWING
APPEND(TranslateZ, z);
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
+ void didTranslate(SkScalar, SkScalar) override;
#ifdef SK_EXPERIMENTAL_SHADOWING
void didTranslateZ(SkScalar) override;