land http://codereview.appspot.com/5244058/ - add matrix to SkView
git-svn-id: http://skia.googlecode.com/svn/trunk@2670 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/views/SkView.h b/include/views/SkView.h
index 5cb6e4a..a5349c2 100644
--- a/include/views/SkView.h
+++ b/include/views/SkView.h
@@ -14,6 +14,7 @@
#include "SkRect.h"
#include "SkDOM.h"
#include "SkTDict.h"
+#include "SkMatrix.h"
class SkCanvas;
class SkLayerView;
@@ -80,6 +81,12 @@
/** Return a rectangle set to [0, 0, width, height] */
void getLocalBounds(SkRect* bounds) const;
+ /** Loc - the view's offset with respect to its parent in its view hiearchy.
+ NOTE: For more complex transforms, use Local Matrix. The tranformations
+ are applied in the following order:
+ canvas->translate(fLoc.fX, fLoc.fY);
+ canvas->concat(fMatrix);
+ */
/** Return the view's left edge */
SkScalar locX() const { return fLoc.fX; }
/** Return the view's top edge */
@@ -89,6 +96,18 @@
void setLoc(const SkPoint& loc) { this->setLoc(loc.fX, loc.fY); }
void setLocX(SkScalar x) { this->setLoc(x, fLoc.fY); }
void setLocY(SkScalar y) { this->setLoc(fLoc.fX, y); }
+
+ /** Local Matrix - matrix used to tranform the view with respect to its
+ parent in its view hiearchy. Use setLocalMatrix to apply matrix
+ transformations to the current view and in turn affect its children.
+ NOTE: For simple offsets, use Loc. The transformations are applied in
+ the following order:
+ canvas->translate(fLoc.fX, fLoc.fY);
+ canvas->concat(fMatrix);
+ */
+ const SkMatrix& getLocalMatrix() const { return fMatrix; }
+ void setLocalMatrix(const SkMatrix& matrix);
+
/** Offset (move) the view by the specified dx and dy. This does not affect the view's size */
void offset(SkScalar dx, SkScalar dy);
@@ -338,6 +357,7 @@
private:
SkScalar fWidth, fHeight;
+ SkMatrix fMatrix;
SkPoint fLoc;
SkView* fParent;
SkView* fFirstChild;
@@ -354,6 +374,8 @@
bool setFocusView(SkView* fvOrNull);
SkView* acceptFocus(FocusDirection);
void detachFromParent_NoLayout();
+ /** Compute the matrix to transform view-local coordinates into global ones */
+ void localToGlobal(SkMatrix* matrix) const;
};
#endif
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 35a822a..ffe56b1 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -751,50 +751,13 @@
gAnimTimePrev = gAnimTime;
gAnimTime = SkTime::GetMSecs();
}
-
- SkScalar cx = fZoomCenterX;
- SkScalar cy = fZoomCenterY;
-
- if (fZoomLevel) {
- SkMatrix m;
- SkPoint center;
- m = canvas->getTotalMatrix();//.invert(&m);
- m.mapXY(cx, cy, ¢er);
- cx = center.fX;
- cy = center.fY;
-
- m.setTranslate(-cx, -cy);
- m.postScale(fZoomScale, fZoomScale);
- m.postTranslate(cx, cy);
-
- canvas->concat(m);
- }
-
- if (fFlipAxis) {
- SkMatrix m;
- m.setTranslate(cx, cy);
- if (fFlipAxis & kFlipAxis_X) {
- m.preScale(-SK_Scalar1, SK_Scalar1);
- }
- if (fFlipAxis & kFlipAxis_Y) {
- m.preScale(SK_Scalar1, -SK_Scalar1);
- }
- m.preTranslate(-cx, -cy);
- canvas->concat(m);
- }
- // Apply any gesture matrix
- if (true) {
- const SkMatrix& localM = fGesture.localM();
- if (localM.getType() & SkMatrix::kScale_Mask) {
- canvas->setExternalMatrix(&localM);
- }
- canvas->concat(localM);
- canvas->concat(fGesture.globalM());
-
- if (fGesture.isActive()) {
- this->inval(NULL);
- }
+ const SkMatrix& localM = fGesture.localM();
+ if (localM.getType() & SkMatrix::kScale_Mask) {
+ canvas->setExternalMatrix(&localM);
+ }
+ if (fGesture.isActive()) {
+ this->updateMatrix();
}
if (fNClip) {
@@ -1224,12 +1187,44 @@
} else {
fZoomScale = SK_Scalar1;
}
-
- this->updateTitle();
-
- this->inval(NULL);
+ this->updateMatrix();
}
+void SampleWindow::updateMatrix(){
+ SkMatrix m;
+ m.reset();
+ if (fZoomLevel) {
+ SkPoint center;
+ //m = this->getLocalMatrix();//.invert(&m);
+ m.mapXY(fZoomCenterX, fZoomCenterY, ¢er);
+ SkScalar cx = center.fX;
+ SkScalar cy = center.fY;
+
+ m.setTranslate(-cx, -cy);
+ m.postScale(fZoomScale, fZoomScale);
+ m.postTranslate(cx, cy);
+ }
+
+ if (fFlipAxis) {
+ m.preTranslate(fZoomCenterX, fZoomCenterY);
+ if (fFlipAxis & kFlipAxis_X) {
+ m.preScale(-SK_Scalar1, SK_Scalar1);
+ }
+ if (fFlipAxis & kFlipAxis_Y) {
+ m.preScale(SK_Scalar1, -SK_Scalar1);
+ }
+ m.preTranslate(-fZoomCenterX, -fZoomCenterY);
+ //canvas->concat(m);
+ }
+ // Apply any gesture matrix
+ m.preConcat(fGesture.localM());
+ m.preConcat(fGesture.globalM());
+
+ this->setLocalMatrix(m);
+
+ this->updateTitle();
+ this->inval(NULL);
+}
bool SampleWindow::previousSample() {
fCurrIndex = (fCurrIndex - 1 + fSamples.count()) % fSamples.count();
this->loadView(create_transition(curr_view(this), (*fSamples[fCurrIndex])(),
@@ -1331,14 +1326,12 @@
}
if (SkOSMenu::FindSwitchState(evt, "Flip X", NULL)) {
fFlipAxis ^= kFlipAxis_X;
- this->updateTitle();
- this->inval(NULL);
+ this->updateMatrix();
return true;
}
if (SkOSMenu::FindSwitchState(evt, "Flip Y", NULL)) {
fFlipAxis ^= kFlipAxis_Y;
- this->updateTitle();
- this->inval(NULL);
+ this->updateMatrix();
return true;
}
if (SkOSMenu::FindAction(evt,"Save to PDF")) {
@@ -1619,8 +1612,8 @@
bool SampleWindow::onClick(Click* click) {
if (GestureClick::IsGesture(click)) {
- float x = SkScalarToFloat(click->fCurr.fX);
- float y = SkScalarToFloat(click->fCurr.fY);
+ float x = click->fICurr.fX;
+ float y = click->fICurr.fY;
switch (click->fState) {
case SkView::Click::kDown_State:
@@ -1628,11 +1621,11 @@
break;
case SkView::Click::kMoved_State:
fGesture.touchMoved(click->fOwner, x, y);
- this->inval(NULL);
+ this->updateMatrix();
break;
case SkView::Click::kUp_State:
fGesture.touchEnd(click->fOwner);
- this->inval(NULL);
+ this->updateMatrix();
break;
}
return true;
diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h
index 0f1a2af..0a60535 100644
--- a/samplecode/SampleApp.h
+++ b/samplecode/SampleApp.h
@@ -187,7 +187,7 @@
void updatePointer(int x, int y);
void magnify(SkCanvas* canvas);
void showZoomer(SkCanvas* canvas);
-
+ void updateMatrix();
void postAnimatingEvent();
typedef SkOSWindow INHERITED;
diff --git a/src/views/SkView.cpp b/src/views/SkView.cpp
index 5b15439..fc1ddfb 100644
--- a/src/views/SkView.cpp
+++ b/src/views/SkView.cpp
@@ -15,7 +15,7 @@
fWidth = fHeight = 0;
fLoc.set(0, 0);
fParent = fFirstChild = fNextSibling = fPrevSibling = NULL;
-
+ fMatrix.setIdentity();
fContainsFocus = 0;
}
@@ -82,7 +82,7 @@
{
this->inval(NULL);
fLoc.set(x, y);
- this->inval(NULL);
+ this->inval(NULL);
}
}
@@ -92,6 +92,13 @@
this->setLoc(fLoc.fX + dx, fLoc.fY + dy);
}
+void SkView::setLocalMatrix(const SkMatrix& matrix)
+{
+ this->inval(NULL);
+ fMatrix = matrix;
+ this->inval(NULL);
+}
+
void SkView::draw(SkCanvas* canvas)
{
if (fWidth && fHeight && this->isVisible())
@@ -108,8 +115,10 @@
if (this->isClipToBounds()) {
canvas->clipRect(r);
}
- canvas->translate(fLoc.fX, fLoc.fY);
-
+
+ canvas->translate(fLoc.fX, fLoc.fY);
+ canvas->concat(fMatrix);
+
if (fParent) {
fParent->beforeChild(this, canvas);
}
@@ -369,11 +378,14 @@
if (this->onSendClickToChildren(x, y)) {
F2BIter iter(this);
SkView* child;
-
+
while ((child = iter.next()) != NULL)
{
- Click* click = child->findClickHandler(x - child->fLoc.fX,
- y - child->fLoc.fY);
+ SkPoint p;
+ child->globalToLocal(x, y, &p);
+
+ Click* click = child->findClickHandler(p.fX, p.fY);
+
if (click) {
return click;
}
@@ -594,20 +606,30 @@
fFirstChild->detachFromParent_NoLayout();
}
+void SkView::localToGlobal(SkMatrix* matrix) const
+{
+ if (matrix) {
+ matrix->reset();
+ const SkView* view = this;
+ while (view)
+ {
+ matrix->preConcat(view->getLocalMatrix());
+ matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY);
+ view = view->fParent;
+ }
+ }
+}
void SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const
{
SkASSERT(this);
-
if (local)
{
- const SkView* view = this;
- while (view)
- {
- x -= view->fLoc.fX;
- y -= view->fLoc.fY;
- view = view->fParent;
- }
- local->set(x, y);
+ SkMatrix m;
+ this->localToGlobal(&m);
+ SkPoint p;
+ m.invert(&m);
+ m.mapXY(x, y, &p);
+ local->set(p.fX, p.fY);
}
}