land http://codereview.appspot.com/5244058/ - add matrix to SkView
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 11 Nov 2011 21:42:12 +0000 (21:42 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 11 Nov 2011 21:42:12 +0000 (21:42 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@2670 2bbb7eff-a529-9590-31e7-b0007b416f81

include/views/SkView.h
samplecode/SampleApp.cpp
samplecode/SampleApp.h
src/views/SkView.cpp

index 5cb6e4aff504808c9d091e19793a645cbbebe8d3..a5349c21ba230a9daa0c49134b26b64369a14b4f 100644 (file)
@@ -14,6 +14,7 @@
 #include "SkRect.h"
 #include "SkDOM.h"
 #include "SkTDict.h"
+#include "SkMatrix.h"
 
 class SkCanvas;
 class SkLayerView;
@@ -80,6 +81,12 @@ public:
     /** 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 @@ public:
     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 @@ protected:
 
 private:
     SkScalar    fWidth, fHeight;
+    SkMatrix    fMatrix;
     SkPoint     fLoc;
     SkView*     fParent;
     SkView*     fFirstChild;
@@ -354,6 +374,8 @@ private:
     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
index 35a822a2798a79120a401d6d6277676b455ff759..ffe56b104ddaa193a9848ca67f1a2ed3d368e193 100644 (file)
@@ -751,50 +751,13 @@ void SampleWindow::draw(SkCanvas* canvas) {
         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 @@ void SampleWindow::changeZoomLevel(float delta) {
     } else {
         fZoomScale = SK_Scalar1;
     }
+    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 @@ bool SampleWindow::onEvent(const SkEvent& evt) {
     }
     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 @@ SkView::Click* SampleWindow::onFindClickHandler(SkScalar x, SkScalar y) {
 
 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 @@ bool SampleWindow::onClick(Click* click) {
                 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;
index 0f1a2af1a210e040f72b09fa6d149dff60614f54..0a605357e14e5eabbcf7b7629dbdaf7a2fed578b 100644 (file)
@@ -187,7 +187,7 @@ private:
     void updatePointer(int x, int y);
     void magnify(SkCanvas* canvas);
     void showZoomer(SkCanvas* canvas);
-
+    void updateMatrix();
     void postAnimatingEvent();
 
     typedef SkOSWindow INHERITED;
index 5b154392e8f8bc57aa7ae34033a26ab20de5d0f6..fc1ddfbfc5828fd686313155059f74148d899dd6 100644 (file)
@@ -15,7 +15,7 @@ SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags))
        fWidth = fHeight = 0;
        fLoc.set(0, 0);
        fParent = fFirstChild = fNextSibling = fPrevSibling = NULL;
-       
+    fMatrix.setIdentity();
        fContainsFocus = 0;
 }
 
@@ -82,7 +82,7 @@ void SkView::setLoc(SkScalar x, SkScalar y)
        {
                this->inval(NULL);
                fLoc.set(x, y);
-               this->inval(NULL);
+        this->inval(NULL);
        }
 }
 
@@ -92,6 +92,13 @@ void SkView::offset(SkScalar dx, SkScalar dy)
                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 @@ void SkView::draw(SkCanvas* canvas)
         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 @@ SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y)
     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 @@ void SkView::detachAllChildren()
                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);
        }
 }