[M56] More fixes for distance field paths
authorJim Van Verth <jvanverth@google.com>
Wed, 11 Jan 2017 19:17:00 +0000 (14:17 -0500)
committerJim Van Verth <jvanverth@google.com>
Mon, 23 Jan 2017 21:11:35 +0000 (16:11 -0500)
Disables use of SDFs for very small paths (because of blurring) and
adds a border of 1 pixel in device space to handle antialiasing.

BUG=chromium:677889

Change-Id: Icd2f7e80323b1255f8de52b97360e9a2d995c765
Reviewed-on: https://skia-review.googlesource.com/6895
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>

gm/pathfill.cpp
src/gpu/batches/GrAADistanceFieldPathRenderer.cpp
src/gpu/batches/GrAADistanceFieldPathRenderer.h

index da0efea..2562e7c 100644 (file)
@@ -140,6 +140,49 @@ static SkScalar make_line(SkPath* path) {
     return SkIntToScalar(40);
 }
 
+static SkScalar make_info(SkPath* path) {
+    path->moveTo(24, 4);
+    path->cubicTo(12.94999980926514f,
+                  4,
+                  4,
+                  12.94999980926514f,
+                  4,
+                  24);
+    path->cubicTo(4,
+                  35.04999923706055f,
+                  12.94999980926514f,
+                  44,
+                  24,
+                  44);
+    path->cubicTo(35.04999923706055f,
+                  44,
+                  44,
+                  35.04999923706055f,
+                  44,
+                  24);
+    path->cubicTo(44,
+                  12.95000076293945f,
+                  35.04999923706055f,
+                  4,
+                  24,
+                  4);
+    path->close();
+    path->moveTo(26, 34);
+    path->lineTo(22, 34);
+    path->lineTo(22, 22);
+    path->lineTo(26, 22);
+    path->lineTo(26, 34);
+    path->close();
+    path->moveTo(26, 18);
+    path->lineTo(22, 18);
+    path->lineTo(22, 14);
+    path->lineTo(26, 14);
+    path->lineTo(26, 18);
+    path->close();
+
+    return SkIntToScalar(44);
+}
+
 constexpr MakePathProc gProcs[] = {
     make_frame,
     make_triangle,
@@ -158,11 +201,14 @@ constexpr MakePathProc gProcs[] = {
 class PathFillGM : public skiagm::GM {
     SkPath  fPath[N];
     SkScalar fDY[N];
+    SkPath  fInfoPath;
 protected:
     void onOnceBeforeDraw() override {
         for (size_t i = 0; i < N; i++) {
             fDY[i] = gProcs[i](&fPath[i]);
         }
+
+        (void) make_info(&fInfoPath);
     }
 
 
@@ -182,6 +228,10 @@ protected:
             canvas->drawPath(fPath[i], paint);
             canvas->translate(SkIntToScalar(0), fDY[i]);
         }
+
+        canvas->scale(0.300000011920929f, 0.300000011920929f);
+        canvas->translate(50, 50);
+        canvas->drawPath(fInfoPath, paint);
     }
 
 private:
index 759f44f..1736dbb 100644 (file)
@@ -35,6 +35,7 @@ static int g_NumFreedShapes = 0;
 #endif
 
 // mip levels
+static const int kMinSize = 16;
 static const int kSmallMIP = 32;
 static const int kMediumMIP = 73;
 static const int kLargeMIP = 162;
@@ -103,14 +104,17 @@ bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c
         return false;
     }
 
-    // only support paths with bounds within kMediumMIP by kMediumMIP,
-    // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP
-    // the goal is to accelerate rendering of lots of small paths that may be scaling
+    // Only support paths with bounds within kMediumMIP by kMediumMIP,
+    // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP.
+    // For clarity, the original or scaled path should be at least kMinSize by kMinSize.
+    // TODO: revisit this last criteria with Joel's patch.
+    // The goal is to accelerate rendering of lots of small paths that may be scaling.
     SkScalar maxScale = args.fViewMatrix->getMaxScale();
     SkRect bounds = args.fShape->styledBounds();
     SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
 
-    return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP;
+    return maxDim <= kMediumMIP &&
+           maxDim * maxScale >= kMinSize && maxDim * maxScale <= 2.0f*kLargeMIP;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -385,29 +389,12 @@ private:
         // set the bounds rect to the original bounds
         shapeData->fBounds = bounds;
 
-        // set up texture coordinates
-        SkScalar texLeft = bounds.fLeft;
-        SkScalar texTop = bounds.fTop;
-        SkScalar texRight = bounds.fRight;
-        SkScalar texBottom = bounds.fBottom;
-
-        // transform original path's bounds to texture space
-        texLeft *= scale;
-        texTop *= scale;
-        texRight *= scale;
-        texBottom *= scale;
+        // set up path to texture coordinate transform
+        shapeData->fScale = scale;
         dx -= SK_DistanceFieldPad + kAntiAliasPad;
         dy -= SK_DistanceFieldPad + kAntiAliasPad;
-        texLeft += atlasLocation.fX - dx;
-        texTop += atlasLocation.fY - dy;
-        texRight += atlasLocation.fX - dx;
-        texBottom += atlasLocation.fY - dy;
-
-        GrTexture* texture = atlas->getTexture();
-        shapeData->fTexCoords.setLTRB(texLeft / texture->width(),
-                                      texTop / texture->height(),
-                                      texRight / texture->width(),
-                                      texBottom / texture->height());
+        shapeData->fTranslate.fX = atlasLocation.fX - dx;
+        shapeData->fTranslate.fY = atlasLocation.fY - dy;
 
         fShapeCache->add(shapeData);
         fShapeList->addToTail(shapeData);
@@ -427,10 +414,15 @@ private:
 
         SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
 
+        // outset bounds to include ~1 pixel of AA in device space
+        SkRect bounds = shapeData->fBounds;
+        SkScalar outset = SkScalarInvert(maxScale);
+        bounds.outset(outset, outset);
+
         // vertex positions
         // TODO make the vertex attributes a struct
-        positions->setRectFan(shapeData->fBounds.left(), shapeData->fBounds.top(),
-                              shapeData->fBounds.right(), shapeData->fBounds.bottom(), vertexStride);
+        positions->setRectFan(bounds.left(), bounds.top(), bounds.right(), bounds.bottom(),
+                              vertexStride);
 
         // colors
         for (int i = 0; i < kVerticesPerQuad; i++) {
@@ -438,11 +430,32 @@ private:
             *colorPtr = color;
         }
 
+        // set up texture coordinates
+        SkScalar texLeft = bounds.fLeft;
+        SkScalar texTop = bounds.fTop;
+        SkScalar texRight = bounds.fRight;
+        SkScalar texBottom = bounds.fBottom;
+
+        // transform original path's bounds to texture space
+        SkScalar scale = shapeData->fScale;
+        const SkVector& translate = shapeData->fTranslate;
+        texLeft *= scale;
+        texTop *= scale;
+        texRight *= scale;
+        texBottom *= scale;
+        texLeft += translate.fX;
+        texTop += translate.fY;
+        texRight += translate.fX;
+        texBottom += translate.fY;
+
         // vertex texture coords
         // TODO make these int16_t
         SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(GrColor));
-        textureCoords->setRectFan(shapeData->fTexCoords.left(), shapeData->fTexCoords.top(),
-                                  shapeData->fTexCoords.right(), shapeData->fTexCoords.bottom(),
+        GrTexture* texture = atlas->getTexture();
+        textureCoords->setRectFan(texLeft / texture->width(),
+                                  texTop / texture->height(),
+                                  texRight / texture->width(),
+                                  texBottom / texture->height(),
                                   vertexStride);
     }
 
index b4c3e6c..51dca86 100644 (file)
@@ -69,10 +69,11 @@ private:
             // 64x64 max, 128x128 max) and the GrShape's key.
             SkAutoSTArray<24, uint32_t> fKey;
         };
-        Key                   fKey;
+        Key fKey;
         GrBatchAtlas::AtlasID fID;
-        SkRect                fBounds;
-        SkRect                fTexCoords;
+        SkRect   fBounds;
+        SkScalar fScale;
+        SkVector fTranslate;
         SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeData);
 
         static inline const Key& GetKey(const ShapeData& data) {