Use uint16_t instead of SkIPoint16 when clipping texCoords for text.

The texCoords and texture indices are packed into two uint16_t, so that
should be used instead of SkIPoint16 for clipping. This CL also cleans up
the clipping code a little, and keeps everything in int arithmetic
(since the positions and coords are pixel/texel aligned).

Bug: skia:6990
Change-Id: I9a237f7df32467adb6a56ddeca6352cbd4f8dd6f
Reviewed-on: https://skia-review.googlesource.com/62360
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index e8a0115..257fb3b 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -83,10 +83,11 @@
         SkPoint* blobPositionLT = reinterpret_cast<SkPoint*>(blobVertices);
         SkPoint* blobPositionRB = reinterpret_cast<SkPoint*>(blobVertices + 3*vertexStride);
 
-        SkRect positionRect = SkRect::MakeLTRB(blobPositionLT->fX,
-                                               blobPositionLT->fY,
-                                               blobPositionRB->fX,
-                                               blobPositionRB->fY);
+        // positions for bitmap glyphs are pixel boundary aligned
+        SkIRect positionRect = SkIRect::MakeLTRB(blobPositionLT->fX,
+                                                 blobPositionLT->fY,
+                                                 blobPositionRB->fX,
+                                                 blobPositionRB->fY);
         if (clipRect.contains(positionRect)) {
             memcpy(currVertex, blobVertices, 4 * vertexStride);
             currVertex += 4 * vertexStride;
@@ -95,82 +96,82 @@
             // In the LCD case the color will be garbage, but we'll overwrite it with the texcoords
             // and it avoids a lot of conditionals.
             SkColor color = *reinterpret_cast<SkColor*>(blobVertices + sizeof(SkPoint));
-            size_t coordOffset = vertexStride - sizeof(SkIPoint16);
-            SkIPoint16* blobCoordsLT = reinterpret_cast<SkIPoint16*>(blobVertices + coordOffset);
-            SkIPoint16* blobCoordsRB = reinterpret_cast<SkIPoint16*>(blobVertices +
-                                                                     3*vertexStride +
-                                                                     coordOffset);
-            SkIRect coordsRect = SkIRect::MakeLTRB(blobCoordsLT->fX / 2,
-                                                   blobCoordsLT->fY / 2,
-                                                   blobCoordsRB->fX / 2,
-                                                   blobCoordsRB->fY / 2);
-            int pageIndexX = blobCoordsLT->fX & 0x1;
-            int pageIndexY = blobCoordsLT->fY & 0x1;
+            size_t coordOffset = vertexStride - 2*sizeof(uint16_t);
+            uint16_t* blobCoordsLT = reinterpret_cast<uint16_t*>(blobVertices + coordOffset);
+            uint16_t* blobCoordsRB = reinterpret_cast<uint16_t*>(blobVertices + 3*vertexStride +
+                                                                 coordOffset);
+            // Pull out the texel coordinates and texture index bits
+            uint16_t coordsRectL = blobCoordsLT[0] >> 1;
+            uint16_t coordsRectT = blobCoordsLT[1] >> 1;
+            uint16_t coordsRectR = blobCoordsRB[0] >> 1;
+            uint16_t coordsRectB = blobCoordsRB[1] >> 1;
+            uint16_t pageIndexX = blobCoordsLT[0] & 0x1;
+            uint16_t pageIndexY = blobCoordsLT[1] & 0x1;
 
-            SkASSERT(positionRect.width() == coordsRect.width());
+            int positionRectWidth = positionRect.width();
+            int positionRectHeight = positionRect.height();
+            SkASSERT(positionRectWidth == (coordsRectR - coordsRectL));
+            SkASSERT(positionRectHeight == (coordsRectB - coordsRectT));
 
             // Clip position and texCoords to the clipRect
-            if (positionRect.fLeft < clipRect.fLeft) {
-                coordsRect.fLeft += clipRect.fLeft - positionRect.fLeft;
-                positionRect.fLeft = clipRect.fLeft;
-            }
-            if (positionRect.fTop < clipRect.fTop) {
-                coordsRect.fTop += clipRect.fTop - positionRect.fTop;
-                positionRect.fTop = clipRect.fTop;
-            }
-            if (positionRect.fRight > clipRect.fRight) {
-                coordsRect.fRight += clipRect.fRight - positionRect.fRight;
-                positionRect.fRight = clipRect.fRight;
-            }
-            if (positionRect.fBottom > clipRect.fBottom) {
-                coordsRect.fBottom += clipRect.fBottom - positionRect.fBottom;
-                positionRect.fBottom = clipRect.fBottom;
-            }
-            if (positionRect.fLeft > positionRect.fRight) {
-                positionRect.fLeft = positionRect.fRight;
-            }
-            if (positionRect.fTop > positionRect.fBottom) {
-                positionRect.fTop = positionRect.fBottom;
-            }
-            coordsRect.fLeft = 2 * coordsRect.fLeft | pageIndexX;
-            coordsRect.fTop = 2 * coordsRect.fTop | pageIndexY;
-            coordsRect.fRight = 2 * coordsRect.fRight | pageIndexX;
-            coordsRect.fBottom = 2 * coordsRect.fBottom | pageIndexY;
+            unsigned int delta;
+            delta = SkTMin(SkTMax(clipRect.fLeft - positionRect.fLeft, 0), positionRectWidth);
+            coordsRectL += delta;
+            positionRect.fLeft += delta;
 
+            delta = SkTMin(SkTMax(clipRect.fTop - positionRect.fTop, 0), positionRectHeight);
+            coordsRectT += delta;
+            positionRect.fTop += delta;
+
+            delta = SkTMin(SkTMax(positionRect.fRight - clipRect.fRight, 0), positionRectWidth);
+            coordsRectR -= delta;
+            positionRect.fRight -= delta;
+
+            delta = SkTMin(SkTMax(positionRect.fBottom - clipRect.fBottom, 0), positionRectHeight);
+            coordsRectB -= delta;
+            positionRect.fBottom -= delta;
+
+            // Repack texel coordinates and index
+            coordsRectL = coordsRectL << 1 | pageIndexX;
+            coordsRectT = coordsRectT << 1 | pageIndexY;
+            coordsRectR = coordsRectR << 1 | pageIndexX;
+            coordsRectB = coordsRectB << 1 | pageIndexY;
+
+            // Set new positions and coords
             SkPoint* currPosition = reinterpret_cast<SkPoint*>(currVertex);
             currPosition->fX = positionRect.fLeft;
             currPosition->fY = positionRect.fTop;
             *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
-            SkIPoint16* currCoords = reinterpret_cast<SkIPoint16*>(currVertex + coordOffset);
-            currCoords->fX = coordsRect.fLeft;
-            currCoords->fY = coordsRect.fTop;
+            uint16_t* currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
+            currCoords[0] = coordsRectL;
+            currCoords[1] = coordsRectT;
             currVertex += vertexStride;
 
             currPosition = reinterpret_cast<SkPoint*>(currVertex);
             currPosition->fX = positionRect.fLeft;
             currPosition->fY = positionRect.fBottom;
             *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
-            currCoords = reinterpret_cast<SkIPoint16*>(currVertex + coordOffset);
-            currCoords->fX = coordsRect.fLeft;
-            currCoords->fY = coordsRect.fBottom;
+            currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
+            currCoords[0] = coordsRectL;
+            currCoords[1] = coordsRectB;
             currVertex += vertexStride;
 
             currPosition = reinterpret_cast<SkPoint*>(currVertex);
             currPosition->fX = positionRect.fRight;
             currPosition->fY = positionRect.fTop;
             *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
-            currCoords = reinterpret_cast<SkIPoint16*>(currVertex + coordOffset);
-            currCoords->fX = coordsRect.fRight;
-            currCoords->fY = coordsRect.fTop;
+            currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
+            currCoords[0] = coordsRectR;
+            currCoords[1] = coordsRectT;
             currVertex += vertexStride;
 
             currPosition = reinterpret_cast<SkPoint*>(currVertex);
             currPosition->fX = positionRect.fRight;
             currPosition->fY = positionRect.fBottom;
             *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
-            currCoords = reinterpret_cast<SkIPoint16*>(currVertex + coordOffset);
-            currCoords->fX = coordsRect.fRight;
-            currCoords->fY = coordsRect.fBottom;
+            currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
+            currCoords[0] = coordsRectR;
+            currCoords[1] = coordsRectB;
             currVertex += vertexStride;
         }