From f03bb566e25ace918f8fdda3cb8426626a00894c Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Fri, 11 Nov 2011 21:42:12 +0000 Subject: [PATCH] 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 --- include/views/SkView.h | 22 +++++++++++ samplecode/SampleApp.cpp | 99 ++++++++++++++++++++++-------------------------- samplecode/SampleApp.h | 2 +- src/views/SkView.cpp | 54 ++++++++++++++++++-------- 4 files changed, 107 insertions(+), 70 deletions(-) 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 @@ 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 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 @@ 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, ¢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 @@ 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, ¢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 @@ 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; 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 @@ private: 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 @@ 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); } } -- 2.7.4