const SkMatrix& localM();
const SkMatrix& globalM() const { return fGlobalM; }
+ void setTransLimit(const SkRect& contentRect, const SkRect& windowRect);
+
private:
enum State {
kEmpty_State,
double fLastUpMillis;
SkPoint fLastUpP;
+ // The following rects are used to limit the translation so the content never leaves the window
+ SkRect fContentRect, fWindowRect;
+ bool fIsTransLimited = false;
+ void limitTrans(); // here we only limit the translation with respect to globalM
void flushLocalM();
int findRec(void* owner) const;
void appendNewRec(void* owner, float x, float y);
* found in the LICENSE file.
*/
-
+#include <algorithm>
#include "SkTouchGesture.h"
#include "SkMatrix.h"
}
void SkTouchGesture::reset() {
+ fIsTransLimited = false;
fTouches.reset();
fState = kEmpty_State;
fLocalM.reset();
}
fTouches.removeShuffle(index);
+
+ limitTrans();
}
float SkTouchGesture::computePinch(const Rec& rec0, const Rec& rec1) {
fLastUpP.set(x, y);
return found;
}
+
+void SkTouchGesture::setTransLimit(const SkRect& contentRect, const SkRect& windowRect) {
+ fIsTransLimited = true;
+ fContentRect = contentRect;
+ fWindowRect = windowRect;
+}
+
+void SkTouchGesture::limitTrans() {
+ if (!fIsTransLimited) {
+ return;
+ }
+
+ SkRect scaledContent = fContentRect;
+ fGlobalM.mapRect(&scaledContent);
+ const SkScalar ZERO = 0;
+
+ fGlobalM.postTranslate(ZERO, std::min(ZERO, fWindowRect.fBottom - scaledContent.fTop));
+ fGlobalM.postTranslate(ZERO, std::max(ZERO, fWindowRect.fTop - scaledContent.fBottom));
+ fGlobalM.postTranslate(std::min(ZERO, fWindowRect.fRight - scaledContent.fLeft), ZERO);
+ fGlobalM.postTranslate(std::max(ZERO, fWindowRect.fLeft - scaledContent.fRight), ZERO);
+}
}
void Viewer::setupCurrentSlide(int previousSlide) {
+ fGesture.reset();
+ fDefaultMatrix.reset();
+ fDefaultMatrixInv.reset();
+
+ if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
+ const SkRect contentRect = fWindow->getContentRect();
+ const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
+ const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
+ if (contentRect.width() > 0 && contentRect.height() > 0) {
+ fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit);
+ bool inverted = fDefaultMatrix.invert(&fDefaultMatrixInv);
+ SkASSERT(inverted);
+ }
+ }
+
+ if (fWindow->supportsContentRect()) {
+ const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
+ SkRect windowRect = fWindow->getContentRect();
+ fDefaultMatrixInv.mapRect(&windowRect);
+ fGesture.setTransLimit(SkRect::MakeWH(slideSize.width(), slideSize.height()), windowRect);
+ }
+
this->updateTitle();
fSlides[fCurrentSlide]->load();
if (previousSlide >= 0) {
}
canvas->clear(SK_ColorWHITE);
- if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
- const SkRect contentRect = fWindow->getContentRect();
- const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
- const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
- SkMatrix matrix;
- matrix.setRectToRect(slideBounds, contentRect, SkMatrix::kCenter_ScaleToFit);
- canvas->concat(matrix);
- }
+ canvas->concat(fDefaultMatrix);
canvas->concat(computeMatrix());
fSlides[fCurrentSlide]->draw(canvas);
bool Viewer::onTouch(int owner, Window::InputState state, float x, float y) {
void* castedOwner = reinterpret_cast<void*>(owner);
+ SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
switch (state) {
case Window::kUp_InputState: {
fGesture.touchEnd(castedOwner);
break;
}
case Window::kDown_InputState: {
- fGesture.touchBegin(castedOwner, x, y);
+ fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY);
break;
}
case Window::kMove_InputState: {
- fGesture.touchMoved(castedOwner, x, y);
+ fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY);
break;
}
}