Use ARM fixes for SDF encoding.
This pulls out the encoding fixes by Joel Liang from
https://codereview.chromium.org/1643143002/
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1726763002
Review URL: https://codereview.chromium.org/1726763002
diff --git a/src/core/SkDistanceFieldGen.cpp b/src/core/SkDistanceFieldGen.cpp
index 147aefa..187a5bf 100755
--- a/src/core/SkDistanceFieldGen.cpp
+++ b/src/core/SkDistanceFieldGen.cpp
@@ -316,14 +316,20 @@
#define DUMP_EDGE 0
#if !DUMP_EDGE
-static unsigned char pack_distance_field_val(float dist, float distanceMagnitude) {
- if (dist <= -distanceMagnitude) {
- return 255;
- } else if (dist > distanceMagnitude) {
- return 0;
- } else {
- return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude);
- }
+template <int distanceMagnitude>
+static unsigned char pack_distance_field_val(float dist) {
+ // The distance field is constructed as unsigned char values, so that the zero value is at 128,
+ // Beside 128, we have 128 values in range [0, 128), but only 127 values in range (128, 255].
+ // So we multiply distanceMagnitude by 127/128 at the latter range to avoid overflow.
+ dist = SkScalarPin(-dist, -distanceMagnitude, distanceMagnitude * 127.0f / 128.0f);
+
+ // Scale into the positive range for unsigned distance.
+ dist += distanceMagnitude;
+
+ // Scale into unsigned char range.
+ // Round to place negative and positive values as equally as possible around 128
+ // (which represents zero).
+ return (unsigned char)SkScalarRoundToInt(dist / (2 * distanceMagnitude) * 256.0f);
}
#endif
@@ -441,7 +447,7 @@
} else {
dist = SkScalarSqrt(currData->fDistSq);
}
- *dfPtr++ = pack_distance_field_val(dist, (float)SK_DistanceFieldMagnitude);
+ *dfPtr++ = pack_distance_field_val<SK_DistanceFieldMagnitude>(dist);
#endif
++currData;
++currEdge;
diff --git a/src/core/SkDistanceFieldGen.h b/src/core/SkDistanceFieldGen.h
index 4a09ace..5e7af52 100644
--- a/src/core/SkDistanceFieldGen.h
+++ b/src/core/SkDistanceFieldGen.h
@@ -10,7 +10,7 @@
#include "SkTypes.h"
// the max magnitude for the distance field
-// distance values are limited to the range [-SK_DistanceFieldMagnitude, SK_DistanceFieldMagnitude)
+// distance values are limited to the range (-SK_DistanceFieldMagnitude, SK_DistanceFieldMagnitude]
#define SK_DistanceFieldMagnitude 4
// we need to pad around the original glyph to allow our maximum distance of
// SK_DistanceFieldMagnitude texels away from any edge
@@ -18,9 +18,10 @@
// the rect we render with is inset from the distance field glyph size to allow for bilerp
#define SK_DistanceFieldInset 2
-// for the fragment shader
-// The distance field is constructed as unsigned char values, so that the zero value is at 128,
-// and the range is [-4, 4 - 1/255). Hence our multiplier is 8 - 1/32 and zero threshold is 128/255.
+// For the fragment shader:
+// The distance field is constructed as unsigned char values,
+// so that the zero value is at 128, and the supported range of distances is [-4 * 127/128, 4].
+// Hence our multiplier (width of the range) is 4 * 255/128 and zero threshold is 128/255.
#define SK_DistanceFieldMultiplier "7.96875"
#define SK_DistanceFieldThreshold "0.50196078431"