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, &center);
-        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, &center);
+        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);
 	}
 }