Force tiles in SampleApp to integer boundaries.
authorbungeman <bungeman@google.com>
Thu, 3 Mar 2016 21:32:38 +0000 (13:32 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 3 Mar 2016 21:32:38 +0000 (13:32 -0800)
The current behavior is to create tiles from the rounded ideal tile size,
tell the tile that it's upper left pixel is at the ideal location, and
then draw those tiles at the ideal locations. As a result, the tiles are
be out of phase with each other internally and then actually drawn at
the rounded pixel location instead of the ideal location.

The new behavior is to always round up to get the tile size, make the
tile translation an integer offset, and then draw at the exact pixel.

This also modifies SampleApp to use the numeric keypad to provide an
extra manual 1/32 pixel translation for fine grained movement.

BUG=skia:5020

Review URL: https://codereview.chromium.org/1763833002

samplecode/SampleApp.cpp
samplecode/SampleApp.h
src/views/unix/XkeysToSkKeys.h

index 7ebac5f..6d5f647 100644 (file)
@@ -876,7 +876,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
     fHintingState = 0;
     fFilterQualityIndex = 0;
     fFlipAxis = 0;
-    fScrollTestX = fScrollTestY = 0;
 
     fMouseX = fMouseY = 0;
     fFatBitsScale = 8;
@@ -885,6 +884,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
 
     fZoomLevel = 0;
     fZoomScale = SK_Scalar1;
+    fOffset = { 0, 0 };
 
     fMagnify = false;
 
@@ -1062,14 +1062,14 @@ void SampleWindow::draw(SkCanvas* canvas) {
     if (kNo_Tiling == fTilingMode) {
         this->INHERITED::draw(canvas); // no looping or surfaces needed
     } else {
-        const int w = SkScalarRoundToInt(tile.width());
-        const int h = SkScalarRoundToInt(tile.height());
-        SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
+        const SkScalar w = SkScalarCeilToScalar(tile.width());
+        const SkScalar h = SkScalarCeilToScalar(tile.height());
+        SkImageInfo info = SkImageInfo::MakeN32Premul(SkScalarTruncToInt(w), SkScalarTruncToInt(h));
         SkAutoTUnref<SkSurface> surface(canvas->newSurface(info));
         SkCanvas* tileCanvas = surface->getCanvas();
 
-        for (SkScalar y = 0; y < height(); y += tile.height()) {
-            for (SkScalar x = 0; x < width(); x += tile.width()) {
+        for (SkScalar y = 0; y < height(); y += h) {
+            for (SkScalar x = 0; x < width(); x += w) {
                 SkAutoCanvasRestore acr(tileCanvas, true);
                 tileCanvas->translate(-x, -y);
                 tileCanvas->clear(0);
@@ -1462,6 +1462,11 @@ void SampleWindow::beforeChild(SkView* child, SkCanvas* canvas) {
     }
 }
 
+void SampleWindow::changeOffset(SkVector delta) {
+    fOffset += delta;
+    this->updateMatrix();
+}
+
 void SampleWindow::changeZoomLevel(float delta) {
     fZoomLevel += delta;
     if (fZoomLevel > 0) {
@@ -1479,6 +1484,7 @@ void SampleWindow::changeZoomLevel(float delta) {
 void SampleWindow::updateMatrix(){
     SkMatrix m;
     m.reset();
+
     if (fZoomLevel) {
         SkPoint center;
         //m = this->getLocalMatrix();//.invert(&m);
@@ -1491,6 +1497,8 @@ void SampleWindow::updateMatrix(){
         m.postTranslate(cx, cy);
     }
 
+    m.postTranslate(fOffset.fX, fOffset.fY);
+
     if (fFlipAxis) {
         m.preTranslate(fZoomCenterX, fZoomCenterY);
         if (fFlipAxis & kFlipAxis_X) {
@@ -1685,13 +1693,7 @@ bool SampleWindow::onHandleChar(SkUnichar uni) {
     }
 
     if (0xFF != dx && 0xFF != dy) {
-        if ((dx | dy) == 0) {
-            fScrollTestX = fScrollTestY = 0;
-        } else {
-            fScrollTestX += dx;
-            fScrollTestY += dy;
-        }
-        this->inval(nullptr);
+        this->changeOffset({SkIntToScalar(dx / 32.0f), SkIntToScalar(dy / 32.0f)});
         return true;
     }
 
@@ -1855,6 +1857,10 @@ bool SampleWindow::onHandleKey(SkKey key) {
             }
         }
     }
+
+    int dx = 0xFF;
+    int dy = 0xFF;
+
     switch (key) {
         case kRight_SkKey:
             if (this->nextSample()) {
@@ -1882,9 +1888,26 @@ bool SampleWindow::onHandleKey(SkKey key) {
         case kBack_SkKey:
             this->showOverview();
             return true;
+
+        case k5_SkKey: dx =  0; dy =  0; break;
+        case k8_SkKey: dx =  0; dy = -1; break;
+        case k6_SkKey: dx =  1; dy =  0; break;
+        case k2_SkKey: dx =  0; dy =  1; break;
+        case k4_SkKey: dx = -1; dy =  0; break;
+        case k7_SkKey: dx = -1; dy = -1; break;
+        case k9_SkKey: dx =  1; dy = -1; break;
+        case k3_SkKey: dx =  1; dy =  1; break;
+        case k1_SkKey: dx = -1; dy =  1; break;
+
         default:
             break;
     }
+
+    if (0xFF != dx && 0xFF != dy) {
+        this->changeOffset({SkIntToScalar(dx / 32.0f), SkIntToScalar(dy / 32.0f)});
+        return true;
+    }
+
     return this->INHERITED::onHandleKey(key);
 }
 
@@ -2048,6 +2071,9 @@ void SampleWindow::updateTitle() {
     title.prepend(fFlipAxis & kFlipAxis_Y ? "Y " : nullptr);
     title.prepend(gHintingStates[fHintingState].label);
 
+    if (fOffset.fX || fOffset.fY) {
+        title.prependf("(%.2f, %.2f) ", SkScalarToFloat(fOffset.fX), SkScalarToFloat(fOffset.fY));
+    }
     if (fZoomLevel) {
         title.prependf("{%.2f} ", SkScalarToFloat(fZoomLevel));
     }
index d4157fa..7ee07d8 100644 (file)
@@ -129,6 +129,7 @@ public:
 
     void setZoomCenter(float x, float y);
     void changeZoomLevel(float delta);
+    void changeOffset(SkVector delta);
     bool nextSample();
     bool previousSample();
     bool goToSample(int i);
@@ -172,6 +173,7 @@ private:
     SkTouchGesture fGesture;
     SkScalar fZoomLevel;
     SkScalar fZoomScale;
+    SkVector fOffset;
 
     DeviceType fDeviceType;
     DeviceManager* fDevManager;
@@ -209,7 +211,6 @@ private:
 
     int fMSAASampleCount;
 
-    int fScrollTestX, fScrollTestY;
     SkScalar fZoomCenterX, fZoomCenterY;
 
     //Stores global settings
index 30eb97d..9cc9885 100644 (file)
@@ -31,6 +31,35 @@ SkKey XKeyToSkKey(KeySym keysym) {
             return kDown_SkKey;
         case XK_Up:
             return kUp_SkKey;
+        case XK_KP_0:
+        case XK_KP_Insert:
+            return k0_SkKey;
+        case XK_KP_1:
+        case XK_KP_End:
+            return k1_SkKey;
+        case XK_KP_2:
+        case XK_KP_Down:
+            return k2_SkKey;
+        case XK_KP_3:
+        case XK_KP_Page_Down:
+            return k3_SkKey;
+        case XK_KP_4:
+        case XK_KP_Left:
+            return k4_SkKey;
+        case XK_KP_5:
+            return k5_SkKey;
+        case XK_KP_6:
+        case XK_KP_Right:
+            return k6_SkKey;
+        case XK_KP_7:
+        case XK_KP_Home:
+            return k7_SkKey;
+        case XK_KP_8:
+        case XK_KP_Up:
+            return k8_SkKey;
+        case XK_KP_9:
+        case XK_KP_Page_Up:
+            return k9_SkKey;
         default:
             return kNONE_SkKey;
     }