Re-land "converted OverdrawColorFilter to SkSL"

This reverts commit 2d3cac58fcc8f2d398a421b0341c36479a6ba324.

Bug: skia:
Change-Id: I6607d419f6b30c3e17b52ec5ce67d489bd1ad1dc
Reviewed-on: https://skia-review.googlesource.com/64080
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index c585dd2..edc1605 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -348,6 +348,8 @@
   "$_src/gpu/effects/GrMatrixConvolutionEffect.h",
   "$_src/gpu/effects/GrNonlinearColorSpaceXformEffect.cpp",
   "$_src/gpu/effects/GrNonlinearColorSpaceXformEffect.h",
+  "$_src/gpu/effects/GrOverdrawFragmentProcessor.cpp",
+  "$_src/gpu/effects/GrOverdrawFragmentProcessor.h",
   "$_src/gpu/effects/GrOvalEffect.cpp",
   "$_src/gpu/effects/GrOvalEffect.h",
   "$_src/gpu/effects/GrPorterDuffXferProcessor.cpp",
diff --git a/gn/run_sksllex.py b/gn/run_sksllex.py
old mode 100644
new mode 100755
diff --git a/gn/sksl.gni b/gn/sksl.gni
index a508783..5eef5b1 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -35,5 +35,6 @@
   "$_src/gpu/effects/GrDitherEffect.fp",
   "$_src/gpu/effects/GrEllipseEffect.fp",
   "$_src/gpu/effects/GrRectBlurEffect.fp",
+  "$_src/gpu/effects/GrOverdrawFragmentProcessor.fp",
   "$_src/gpu/effects/GrSimpleTextureEffect.fp",
 ]
diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp
index 2dd4a43..01dab65 100644
--- a/src/effects/SkOverdrawColorFilter.cpp
+++ b/src/effects/SkOverdrawColorFilter.cpp
@@ -64,136 +64,14 @@
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawColorFilter)
     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawColorFilter)
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
-
 #if SK_SUPPORT_GPU
 
-#include "GrFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-
-class OverdrawFragmentProcessor : public GrFragmentProcessor {
-public:
-    static std::unique_ptr<GrFragmentProcessor> Make(const SkPMColor* colors);
-
-    const char* name() const override { return "Overdraw"; }
-
-    std::unique_ptr<GrFragmentProcessor> clone() const override {
-        return std::unique_ptr<GrFragmentProcessor>(new OverdrawFragmentProcessor(fColors));
-    }
-
-private:
-    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
-    bool onIsEqual(const GrFragmentProcessor&) const override;
-
-    OverdrawFragmentProcessor(const GrColor4f* colors);
-
-    GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
-
-    typedef GrFragmentProcessor INHERITED;
-};
-
-class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor {
-public:
-    GLOverdrawFragmentProcessor(const GrColor4f* colors);
-
-    void emitCode(EmitArgs&) override;
-
-protected:
-    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override {}
-
-private:
-    GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
-
-    typedef GrGLSLFragmentProcessor INHERITED;
-};
+#include "effects/GrOverdrawFragmentProcessor.h"
 
 std::unique_ptr<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(
         GrContext*, const GrColorSpaceInfo&) const {
-    return OverdrawFragmentProcessor::Make(fColors);
-}
-
-std::unique_ptr<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) {
-    GrColor4f grColors[SkOverdrawColorFilter::kNumColors];
-    for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) {
-        grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]),
-                                                             SkGetPackedG32(colors[i]),
-                                                             SkGetPackedB32(colors[i]),
-                                                             SkGetPackedA32(colors[i])));
-    }
-
-    return std::unique_ptr<GrFragmentProcessor>(new OverdrawFragmentProcessor(grColors));
-}
-
-// This could implement the constant input -> constant output optimization, but we don't really
-// care given how this is used.
-OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors)
-        : INHERITED(kOverdrawFragmentProcessor_ClassID, kNone_OptimizationFlags) {
-    memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
-}
-
-GrGLSLFragmentProcessor* OverdrawFragmentProcessor::onCreateGLSLInstance() const {
-    return new GLOverdrawFragmentProcessor(fColors);
-}
-
-bool OverdrawFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
-    const OverdrawFragmentProcessor& that = other.cast<OverdrawFragmentProcessor>();
-    return 0 == memcmp(fColors, that.fColors,
-                       sizeof(GrColor4f) * SkOverdrawColorFilter::kNumColors);
-}
-
-GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) {
-    memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
-}
-
-void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
-    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    if (nullptr == args.fInputColor) {
-        fragBuilder->codeAppendf("%s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                     fColors[5].fRGBA[0],
-                                                                     fColors[5].fRGBA[1],
-                                                                     fColors[5].fRGBA[2],
-                                                                     fColors[5].fRGBA[3]);
-    } else {
-        fragBuilder->codeAppendf("half alpha = 255.0 * %s.a;", args.fInputColor);
-        fragBuilder->codeAppendf("if (alpha < 0.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[0].fRGBA[0],
-                                                                         fColors[0].fRGBA[1],
-                                                                         fColors[0].fRGBA[2],
-                                                                         fColors[0].fRGBA[3]);
-        fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[1].fRGBA[0],
-                                                                         fColors[1].fRGBA[1],
-                                                                         fColors[1].fRGBA[2],
-                                                                         fColors[1].fRGBA[3]);
-        fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[2].fRGBA[0],
-                                                                         fColors[2].fRGBA[1],
-                                                                         fColors[2].fRGBA[2],
-                                                                         fColors[2].fRGBA[3]);
-        fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[3].fRGBA[0],
-                                                                         fColors[3].fRGBA[1],
-                                                                         fColors[3].fRGBA[2],
-                                                                         fColors[3].fRGBA[3]);
-        fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[4].fRGBA[0],
-                                                                         fColors[4].fRGBA[1],
-                                                                         fColors[4].fRGBA[2],
-                                                                         fColors[4].fRGBA[3]);
-        fragBuilder->codeAppendf("} else {");
-        fragBuilder->codeAppendf("    %s.rgba = half4(%f, %f, %f, %f);", args.fOutputColor,
-                                                                         fColors[5].fRGBA[0],
-                                                                         fColors[5].fRGBA[1],
-                                                                         fColors[5].fRGBA[2],
-                                                                         fColors[5].fRGBA[3]);
-        fragBuilder->codeAppendf("}");
-    }
+    return GrOverdrawFragmentProcessor::Make(fColors[0], fColors[1], fColors[2], fColors[3],
+                                             fColors[4], fColors[5]);
 }
 
 #endif
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index e07254a..d8e4f2d 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -121,6 +121,7 @@
         kGrMeshTestProcessor_ClassID,
         kGrMorphologyEffect_ClassID,
         kGrNonlinearColorSpaceXformEffect_ClassID,
+        kGrOverdrawFragmentProcessor_ClassID,
         kGrPathProcessor_ClassID,
         kGrPerlinNoise2Effect_ClassID,
         kGrPipelineDynamicStateTestProcessor_ClassID,
@@ -138,7 +139,6 @@
         kInstanceProcessor_ClassID,
         kLumaColorFilterEffect_ClassID,
         kMSAAQuadProcessor_ClassID,
-        kOverdrawFragmentProcessor_ClassID,
         kPDLCDXferProcessor_ClassID,
         kPorterDuffXferProcessor_ClassID,
         kPremulFragmentProcessor_ClassID,
diff --git a/src/gpu/effects/GrOverdrawFragmentProcessor.cpp b/src/gpu/effects/GrOverdrawFragmentProcessor.cpp
new file mode 100644
index 0000000..31ab53d
--- /dev/null
+++ b/src/gpu/effects/GrOverdrawFragmentProcessor.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * This file was autogenerated from GrOverdrawFragmentProcessor.fp; do not modify.
+ */
+#include "GrOverdrawFragmentProcessor.h"
+#if SK_SUPPORT_GPU
+#include "glsl/GrGLSLFragmentProcessor.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "SkSLCPP.h"
+#include "SkSLUtil.h"
+class GrGLSLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor {
+public:
+    GrGLSLOverdrawFragmentProcessor() {}
+    void emitCode(EmitArgs& args) override {
+        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+        const GrOverdrawFragmentProcessor& _outer = args.fFp.cast<GrOverdrawFragmentProcessor>();
+        (void)_outer;
+        auto color0 = _outer.color0();
+        (void)color0;
+        auto color1 = _outer.color1();
+        (void)color1;
+        auto color2 = _outer.color2();
+        (void)color2;
+        auto color3 = _outer.color3();
+        (void)color3;
+        auto color4 = _outer.color4();
+        (void)color4;
+        auto color5 = _outer.color5();
+        (void)color5;
+        fragBuilder->codeAppendf(
+                "half alpha = half(255.0 * float(%s.w));\nif (float(alpha) < 0.5) {\n    %s = "
+                "half4(%f, %f, %f, %f);\n} else if (float(alpha) < 1.5) {\n    %s = half4(%f, %f, "
+                "%f, %f);\n} else if (float(alpha) < 2.5) {\n    %s = half4(%f, %f, %f, %f);\n} "
+                "else if (float(alpha) < 3.5) {\n    %s = half4(%f, %f, %f, %f);\n} else if "
+                "(float(alpha) < 4.5) {\n    %s = half4(%f, %f, %f, %f);\n} else {\n    %s = "
+                "half4(%f, %f, %f, %f);\n}\n",
+                args.fInputColor ? args.fInputColor : "half4(1)", args.fOutputColor,
+                SkGetPackedR32(_outer.color0()) / 255.0, SkGetPackedG32(_outer.color0()) / 255.0,
+                SkGetPackedB32(_outer.color0()) / 255.0, SkGetPackedA32(_outer.color0()) / 255.0,
+                args.fOutputColor, SkGetPackedR32(_outer.color1()) / 255.0,
+                SkGetPackedG32(_outer.color1()) / 255.0, SkGetPackedB32(_outer.color1()) / 255.0,
+                SkGetPackedA32(_outer.color1()) / 255.0, args.fOutputColor,
+                SkGetPackedR32(_outer.color2()) / 255.0, SkGetPackedG32(_outer.color2()) / 255.0,
+                SkGetPackedB32(_outer.color2()) / 255.0, SkGetPackedA32(_outer.color2()) / 255.0,
+                args.fOutputColor, SkGetPackedR32(_outer.color3()) / 255.0,
+                SkGetPackedG32(_outer.color3()) / 255.0, SkGetPackedB32(_outer.color3()) / 255.0,
+                SkGetPackedA32(_outer.color3()) / 255.0, args.fOutputColor,
+                SkGetPackedR32(_outer.color4()) / 255.0, SkGetPackedG32(_outer.color4()) / 255.0,
+                SkGetPackedB32(_outer.color4()) / 255.0, SkGetPackedA32(_outer.color4()) / 255.0,
+                args.fOutputColor, SkGetPackedR32(_outer.color5()) / 255.0,
+                SkGetPackedG32(_outer.color5()) / 255.0, SkGetPackedB32(_outer.color5()) / 255.0,
+                SkGetPackedA32(_outer.color5()) / 255.0);
+    }
+
+private:
+    void onSetData(const GrGLSLProgramDataManager& pdman,
+                   const GrFragmentProcessor& _proc) override {}
+};
+GrGLSLFragmentProcessor* GrOverdrawFragmentProcessor::onCreateGLSLInstance() const {
+    return new GrGLSLOverdrawFragmentProcessor();
+}
+void GrOverdrawFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+                                                        GrProcessorKeyBuilder* b) const {}
+bool GrOverdrawFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
+    const GrOverdrawFragmentProcessor& that = other.cast<GrOverdrawFragmentProcessor>();
+    (void)that;
+    if (fColor0 != that.fColor0) return false;
+    if (fColor1 != that.fColor1) return false;
+    if (fColor2 != that.fColor2) return false;
+    if (fColor3 != that.fColor3) return false;
+    if (fColor4 != that.fColor4) return false;
+    if (fColor5 != that.fColor5) return false;
+    return true;
+}
+GrOverdrawFragmentProcessor::GrOverdrawFragmentProcessor(const GrOverdrawFragmentProcessor& src)
+        : INHERITED(kGrOverdrawFragmentProcessor_ClassID, src.optimizationFlags())
+        , fColor0(src.fColor0)
+        , fColor1(src.fColor1)
+        , fColor2(src.fColor2)
+        , fColor3(src.fColor3)
+        , fColor4(src.fColor4)
+        , fColor5(src.fColor5) {}
+std::unique_ptr<GrFragmentProcessor> GrOverdrawFragmentProcessor::clone() const {
+    return std::unique_ptr<GrFragmentProcessor>(new GrOverdrawFragmentProcessor(*this));
+}
+#endif
diff --git a/src/gpu/effects/GrOverdrawFragmentProcessor.fp b/src/gpu/effects/GrOverdrawFragmentProcessor.fp
new file mode 100644
index 0000000..2e9df97
--- /dev/null
+++ b/src/gpu/effects/GrOverdrawFragmentProcessor.fp
@@ -0,0 +1,23 @@
+layout(ctype=SkPMColor) in half4 color0;
+layout(ctype=SkPMColor) in half4 color1;
+layout(ctype=SkPMColor) in half4 color2;
+layout(ctype=SkPMColor) in half4 color3;
+layout(ctype=SkPMColor) in half4 color4;
+layout(ctype=SkPMColor) in half4 color5;
+
+void main() {
+    half alpha = 255.0 * sk_InColor.a;
+    if (alpha < 0.5) {
+        sk_OutColor = color0;
+    } else if (alpha < 1.5) {
+        sk_OutColor = color1;
+    } else if (alpha < 2.5) {
+        sk_OutColor = color2;
+    } else if (alpha < 3.5) {
+        sk_OutColor = color3;
+    } else if (alpha < 4.5) {
+        sk_OutColor = color4;
+    } else {
+        sk_OutColor = color5;
+    }
+}
\ No newline at end of file
diff --git a/src/gpu/effects/GrOverdrawFragmentProcessor.h b/src/gpu/effects/GrOverdrawFragmentProcessor.h
new file mode 100644
index 0000000..2b468fe
--- /dev/null
+++ b/src/gpu/effects/GrOverdrawFragmentProcessor.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * This file was autogenerated from GrOverdrawFragmentProcessor.fp; do not modify.
+ */
+#ifndef GrOverdrawFragmentProcessor_DEFINED
+#define GrOverdrawFragmentProcessor_DEFINED
+#include "SkTypes.h"
+#if SK_SUPPORT_GPU
+#include "GrFragmentProcessor.h"
+#include "GrCoordTransform.h"
+class GrOverdrawFragmentProcessor : public GrFragmentProcessor {
+public:
+    SkPMColor color0() const { return fColor0; }
+    SkPMColor color1() const { return fColor1; }
+    SkPMColor color2() const { return fColor2; }
+    SkPMColor color3() const { return fColor3; }
+    SkPMColor color4() const { return fColor4; }
+    SkPMColor color5() const { return fColor5; }
+    static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor color0, SkPMColor color1,
+                                                     SkPMColor color2, SkPMColor color3,
+                                                     SkPMColor color4, SkPMColor color5) {
+        return std::unique_ptr<GrFragmentProcessor>(
+                new GrOverdrawFragmentProcessor(color0, color1, color2, color3, color4, color5));
+    }
+    GrOverdrawFragmentProcessor(const GrOverdrawFragmentProcessor& src);
+    std::unique_ptr<GrFragmentProcessor> clone() const override;
+    const char* name() const override { return "OverdrawFragmentProcessor"; }
+
+private:
+    GrOverdrawFragmentProcessor(SkPMColor color0, SkPMColor color1, SkPMColor color2,
+                                SkPMColor color3, SkPMColor color4, SkPMColor color5)
+            : INHERITED(kGrOverdrawFragmentProcessor_ClassID, kNone_OptimizationFlags)
+            , fColor0(color0)
+            , fColor1(color1)
+            , fColor2(color2)
+            , fColor3(color3)
+            , fColor4(color4)
+            , fColor5(color5) {}
+    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
+    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+    bool onIsEqual(const GrFragmentProcessor&) const override;
+    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
+    SkPMColor fColor0;
+    SkPMColor fColor1;
+    SkPMColor fColor2;
+    SkPMColor fColor3;
+    SkPMColor fColor4;
+    SkPMColor fColor5;
+    typedef GrFragmentProcessor INHERITED;
+};
+#endif
+#endif
diff --git a/src/sksl/README b/src/sksl/README
index 1fdf09f..7c2cf04 100644
--- a/src/sksl/README
+++ b/src/sksl/README
@@ -118,3 +118,6 @@
   the program's key. Matrix variables additionally support 'key=identity',
   which causes the key to consider only whether or not the matrix is an
   identity matrix.
+* 'float4' / 'half4' variables support an additional 'ctype' layout key,
+  providing the type they should be represented as from within the C++ code.
+  Currently the only two supported ctypes are 'SkRect' and 'SkPMColor'.
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index b5362bf..3f1d156 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -130,7 +130,8 @@
            var.fModifiers.fLayout.fBuiltin == -1;
 }
 
-void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
+void CPPCodeGenerator::writeRuntimeValue(const Type& type, const Layout& layout,
+                                         const String& cppCode) {
     if (type.isFloat()) {
         this->write("%f");
         fFormatArgs.push_back(cppCode);
@@ -146,10 +147,17 @@
         fFormatArgs.push_back(cppCode + ".fY");
     } else if (type == *fContext.fFloat4_Type || type == *fContext.fHalf4_Type) {
         this->write(type.name() + "(%f, %f, %f, %f)");
-        fFormatArgs.push_back(cppCode + ".left()");
-        fFormatArgs.push_back(cppCode + ".top()");
-        fFormatArgs.push_back(cppCode + ".right()");
-        fFormatArgs.push_back(cppCode + ".bottom()");
+        if (layout.fCType == "SkPMColor") {
+            fFormatArgs.push_back("SkGetPackedR32(" + cppCode + ") / 255.0");
+            fFormatArgs.push_back("SkGetPackedG32(" + cppCode + ") / 255.0");
+            fFormatArgs.push_back("SkGetPackedB32(" + cppCode + ") / 255.0");
+            fFormatArgs.push_back("SkGetPackedA32(" + cppCode + ") / 255.0");
+        } else {
+            fFormatArgs.push_back(cppCode + ".left()");
+            fFormatArgs.push_back(cppCode + ".top()");
+            fFormatArgs.push_back(cppCode + ".right()");
+            fFormatArgs.push_back(cppCode + ".bottom()");
+        }
     } else {
         printf("unsupported runtime value type '%s'\n", String(type.fName).c_str());
         ASSERT(false);
@@ -158,7 +166,7 @@
 
 void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
     if (is_private(var)) {
-        this->writeRuntimeValue(var.fType, var.fName);
+        this->writeRuntimeValue(var.fType, var.fModifiers.fLayout, var.fName);
     } else {
         this->writeExpression(value, kTopLevel_Precedence);
     }
@@ -234,7 +242,7 @@
                 fFormatArgs.push_back(code);
             } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
                 String name(ref.fVariable.fName);
-                this->writeRuntimeValue(ref.fVariable.fType,
+                this->writeRuntimeValue(ref.fVariable.fType, ref.fVariable.fModifiers.fLayout,
                                         String::printf("_outer.%s()", name.c_str()).c_str());
             } else {
                 this->write(ref.fVariable.fName);
@@ -321,7 +329,7 @@
     static constexpr const char* kPrefix = "sk_Args.";
     if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
         const char* name = s.fName.c_str() + strlen(kPrefix);
-        this->writeRuntimeValue(s.fType, HCodeGenerator::FieldName(name).c_str());
+        this->writeRuntimeValue(s.fType, Layout(), HCodeGenerator::FieldName(name).c_str());
     } else {
         this->write(s.fName.c_str());
     }
@@ -414,7 +422,8 @@
                         return;
                     }
                     this->writef("%s %s;\n",
-                                 HCodeGenerator::FieldType(fContext, decl.fVar->fType).c_str(),
+                                 HCodeGenerator::FieldType(fContext, decl.fVar->fType,
+                                                           decl.fVar->fModifiers.fLayout).c_str(),
                                  String(decl.fVar->fName).c_str());
                 }
             }
diff --git a/src/sksl/SkSLCPPCodeGenerator.h b/src/sksl/SkSLCPPCodeGenerator.h
index 2766522..77331da 100644
--- a/src/sksl/SkSLCPPCodeGenerator.h
+++ b/src/sksl/SkSLCPPCodeGenerator.h
@@ -62,7 +62,7 @@
     void addUniform(const Variable& var);
 
     // writes a printf escape that will be filled in at runtime by the given C++ expression string
-    void writeRuntimeValue(const Type& type, const String& cppCode);
+    void writeRuntimeValue(const Type& type, const Layout& layout, const String& cppCode);
 
     void writeVarInitializer(const Variable& var, const Expression& value) override;
 
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 21f4f28..da67126 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -23,8 +23,11 @@
 , fFullName(String::printf("Gr%s", fName.c_str()))
 , fSectionAndParameterHelper(*program, *errors) {}
 
-String HCodeGenerator::ParameterType(const Context& context, const Type& type) {
-    if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
+String HCodeGenerator::ParameterType(const Context& context, const Type& type,
+                                     const Layout& layout) {
+    if (layout.fCType != "") {
+        return layout.fCType;
+    } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
         return "float";
     } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
         return "SkPoint";
@@ -42,7 +45,8 @@
     return type.name();
 }
 
-String HCodeGenerator::FieldType(const Context& context, const Type& type) {
+String HCodeGenerator::FieldType(const Context& context, const Type& type,
+                                 const Layout& layout) {
     if (type.kind() == Type::kSampler_Kind) {
         return "TextureSampler";
     } else if (type == *context.fFragmentProcessor_Type) {
@@ -51,7 +55,7 @@
         ASSERT(false);
         return "<error>";
     }
-    return ParameterType(context, type);
+    return ParameterType(context, type, layout);
 }
 
 void HCodeGenerator::writef(const char* s, va_list va) {
@@ -134,7 +138,8 @@
         this->writef("    static std::unique_ptr<GrFragmentProcessor> Make(");
         separator = "";
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-            this->writef("%s%s %s", separator, ParameterType(fContext, param->fType).c_str(),
+            this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
+                                                             param->fModifiers.fLayout).c_str(),
                          String(param->fName).c_str());
             separator = ", ";
         }
@@ -176,7 +181,8 @@
     this->writef("    %s(", fFullName.c_str());
     const char* separator = "";
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
-        this->writef("%s%s %s", separator, ParameterType(fContext, param->fType).c_str(),
+        this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
+                                                         param->fModifiers.fLayout).c_str(),
                      String(param->fName).c_str());
         separator = ", ";
     }
@@ -235,7 +241,8 @@
         if (param->fType == *fContext.fFragmentProcessor_Type) {
             continue;
         }
-        this->writef("    %s %s;\n", FieldType(fContext, param->fType).c_str(),
+        this->writef("    %s %s;\n", FieldType(fContext, param->fType,
+                                               param->fModifiers.fLayout).c_str(),
                      FieldName(String(param->fName).c_str()).c_str());
     }
     for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
@@ -267,7 +274,8 @@
         String nameString(param->fName);
         const char* name = nameString.c_str();
         this->writef("    %s %s() const { return %s; }\n",
-                     FieldType(fContext, param->fType).c_str(), name, FieldName(name).c_str());
+                     FieldType(fContext, param->fType, param->fModifiers.fLayout).c_str(), name,
+                     FieldName(name).c_str());
     }
     this->writeMake();
     this->writef("    %s(const %s& src);\n"
diff --git a/src/sksl/SkSLHCodeGenerator.h b/src/sksl/SkSLHCodeGenerator.h
index 5d3b0e7..fa5544a 100644
--- a/src/sksl/SkSLHCodeGenerator.h
+++ b/src/sksl/SkSLHCodeGenerator.h
@@ -37,9 +37,9 @@
 
     bool generateCode() override;
 
-    static String ParameterType(const Context& context, const Type& type);
+    static String ParameterType(const Context& context, const Type& type, const Layout& layout);
 
-    static String FieldType(const Context& context, const Type& type);
+    static String FieldType(const Context& context, const Type& type, const Layout& layout);
 
     static String FieldName(const char* varName) {
         return String::printf("f%c%s", toupper(varName[0]), varName + 1);
diff --git a/src/sksl/SkSLLayoutLexer.cpp b/src/sksl/SkSLLayoutLexer.cpp
index 432095a..a8f31b8 100644
--- a/src/sksl/SkSLLayoutLexer.cpp
+++ b/src/sksl/SkSLLayoutLexer.cpp
@@ -18,329 +18,341 @@
         1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 1, 1, 1,  1,  1,  1,  1,  1,  1,
         1,  1,  1,  1,  1,  1,  1,  3,  1,  4,  5,  6,  7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
         17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 1, 1, 1, 1,  1};
-static int16_t transitions[29][207] = {
+static int16_t transitions[29][212] = {
         {
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,   2, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 14, 0, 0, 0, 0,   0,   0,  0,
-                22,  0, 0, 0,   26,  0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
-                0,   0, 0, 0,   0,   0,  0, 50, 0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   61,  0,  0,
-                0,   0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   83, 0,
-                0,   0, 0, 0,   0,   90, 0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
-                0,   0, 0, 0,   110, 0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
-                0,   0, 0, 130, 0,   0,  0, 0,  0, 136, 0, 0, 0, 0,  0, 0, 0, 0,   0,   0,  0,
-                148, 0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,   166, 0,  0,
-                0,   0, 0, 0,   0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 186, 0,   0,  0,
-                0,   0, 0, 193, 0,   0,  0, 0,  0, 0,   0, 0, 0, 0,  0, 0, 0, 0,
+                0, 2, 0,   0,  0,   0, 0,  0, 0,   0, 0,  0, 0, 14, 0,   0, 0,   0, 0, 0, 0,   22,
+                0, 0, 0,   26, 0,   0, 0,  0, 0,   0, 0,  0, 0, 0,  0,   0, 0,   0, 0, 0, 0,   0,
+                0, 0, 0,   0,  0,   0, 0,  0, 0,   0, 55, 0, 0, 0,  0,   0, 0,   0, 0, 0, 0,   66,
+                0, 0, 0,   0,  0,   0, 0,  0, 0,   0, 0,  0, 0, 0,  0,   0, 0,   0, 0, 0, 0,   88,
+                0, 0, 0,   0,  0,   0, 95, 0, 0,   0, 0,  0, 0, 0,  0,   0, 0,   0, 0, 0, 0,   0,
+                0, 0, 0,   0,  115, 0, 0,  0, 0,   0, 0,  0, 0, 0,  0,   0, 0,   0, 0, 0, 0,   0,
+                0, 0, 135, 0,  0,   0, 0,  0, 141, 0, 0,  0, 0, 0,  0,   0, 0,   0, 0, 0, 153, 0,
+                0, 0, 0,   0,  0,   0, 0,  0, 0,   0, 0,  0, 0, 0,  0,   0, 171, 0, 0, 0, 0,   0,
+                0, 0, 0,   0,  0,   0, 0,  0, 0,   0, 0,  0, 0, 0,  191, 0, 0,   0, 0, 0, 0,   198,
+                0, 0, 0,   0,  0,   0, 0,  0, 0,   0, 0,  0, 0, 0,
         },
         {
-                0, 2,  0,   0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 23, 0,   0,   0,   0, 0,   0,   30, 0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   0,   0, 0,   0,   51, 0,  0, 54, 0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   0,   0, 70,  0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   0,   0, 91,  0,   0,  94, 0, 0,  0,   0, 0, 0, 0, 102, 0, 0, 0,
-                0, 0,  108, 0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   0,   0, 0,   0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   0,   0, 154, 0,   0,  0,  0, 0,  0,   0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   172, 0,   0, 0,   0,   0,  0,  0, 0,  181, 0, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0,   0,   194, 0, 0,   197, 0,  0,  0, 0,  0,   0, 0, 0, 0, 0,
+                0,   2, 0,   0,   0,   0, 0, 0,  0,  0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                23,  0, 0,   0,   0,   0, 0, 30, 0,  0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                0,   0, 0,   0,   0,   0, 0, 0,  0,  0,   0,  56, 0, 0, 59, 0, 0, 0, 0,   0, 0, 0,
+                0,   0, 0,   0,   0,   0, 0, 0,  75, 0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                0,   0, 0,   0,   0,   0, 0, 96, 0,  0,   99, 0,  0, 0, 0,  0, 0, 0, 107, 0, 0, 0,
+                0,   0, 113, 0,   0,   0, 0, 0,  0,  0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                0,   0, 0,   0,   0,   0, 0, 0,  0,  0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                0,   0, 0,   0,   159, 0, 0, 0,  0,  0,   0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                177, 0, 0,   0,   0,   0, 0, 0,  0,  186, 0,  0,  0, 0, 0,  0, 0, 0, 0,   0, 0, 0,
+                199, 0, 0,   202, 0,   0, 0, 0,  0,  0,   0,  0,  0, 0,
         },
         {
-                0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,   2, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 0,  0, 0, 0,   0, 0, 55,  0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 69,
-                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 95, 0, 0, 98,  0, 0, 101, 0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                116, 0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 149, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 0,  0, 0, 167, 0, 0, 0,   0, 0,   0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0, 0,
-                0,   0, 0,  0, 0, 0,   0, 0, 0,   0, 0,   0, 0, 198, 0, 0, 201, 0, 0, 0, 0, 0, 0,
+                0, 42, 0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   60, 0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 74,  0, 0, 0,   0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   100, 0, 0, 103, 0,  0, 106, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 121, 0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 154,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   0,  0, 172, 0, 0, 0, 0,
+                0, 0,  0, 0, 0,   0, 0, 0,   0, 0, 0,   0,   0, 0, 0,   0,  0, 0,   0, 0, 0, 0,
+                0, 0,  0, 0, 203, 0, 0, 206, 0, 0, 0,   0,   0, 0,
         },
         {
-                0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0,  13,  0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 44, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   92, 0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 146, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  195, 0,  0, 0,   0, 0,  0, 0, 0, 0, 0, 0, 0,
+                0,  2, 0, 0, 0, 6, 0,   0,   0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                49, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                97, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0,  0, 0, 0, 0, 0, 151, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0,   200, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,   2, 0,   0,   0,   0,  0,  0,  0,   0, 11, 0, 0, 0,   0,   0, 0,   0, 0,
-                0,   0, 0,   0,   0,   0,  0,  27, 0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                0,   0, 0,   0,   0,   0,  45, 0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                58,  0, 0,   0,   0,   0,  0,  65, 0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                77,  0, 0,   0,   0,   82, 0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                96,  0, 0,   0,   0,   0,  0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 112, 0, 0,
-                0,   0, 117, 0,   0,   0,  0,  0,  123, 0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                134, 0, 0,   0,   138, 0,  0,  0,  142, 0, 0,  0, 0, 147, 0,   0, 0,   0, 152,
-                0,   0, 0,   156, 0,   0,  0,  0,  0,   0, 0,  0, 0, 0,   0,   0, 0,   0, 0,
-                0,   0, 0,   0,   176, 0,  0,  0,  0,   0, 0,  0, 0, 185, 0,   0, 0,   0, 0,
-                0,   0, 0,   0,   0,   0,  0,  0,  199, 0, 0,  0, 0, 0,   205, 0, 0,
+                0,   2,   0,   0,   0, 0,  0,   0,   0, 0,   11, 0,   0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0,   0,   0,   0, 0,  27,  0,   0, 0,   0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0,   0,   0,   0, 46, 0,   0,   0, 50,  0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0,   63,  0,   0, 0,  0,   0,   0, 70,  0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                0,   82,  0,   0,   0, 0,  87,  0,   0, 0,   0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                101, 0,   0,   0,   0, 0,  0,   0,   0, 0,   0,  0,   0, 0, 0, 0, 117, 0, 0,   0,
+                0,   122, 0,   0,   0, 0,  0,   128, 0, 0,   0,  0,   0, 0, 0, 0, 0,   0, 139, 0,
+                0,   0,   143, 0,   0, 0,  147, 0,   0, 0,   0,  152, 0, 0, 0, 0, 157, 0, 0,   0,
+                161, 0,   0,   0,   0, 0,  0,   0,   0, 0,   0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                181, 0,   0,   0,   0, 0,  0,   0,   0, 190, 0,  0,   0, 0, 0, 0, 0,   0, 0,   0,
+                0,   0,   0,   204, 0, 0,  0,   0,   0, 210, 0,  0,
         },
         {
-                0, 2, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 120, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0,
+                0, 2, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 125, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,   2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0,   0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 155, 0,
-                0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,
-                183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
+                0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 160, 0, 0, 0, 0,   0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 188, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
         },
         {
-                0, 2, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 56, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-                0, 0, 0, 0,  0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0,
+                0, 2,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 209, 0, 0, 0,
         },
         {
-                0,   42,  0,  4, 0, 0, 7, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   0,   0,
-                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   32, 0,   0, 0, 0, 37, 0,  0, 40,  0,   0,
-                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   62,  0,
-                0,   0,   0,  0, 0, 0, 0, 0, 72, 0,   0,  0,   0, 0, 0, 0,  80, 0, 0,   0,   0,
-                0,   0,   87, 0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 0,   104, 0,
-                0,   0,   0,  0, 0, 0, 0, 0, 0,  115, 0,  0,   0, 0, 0, 0,  0,  0, 0,   0,   126,
-                0,   128, 0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0, 145, 0,   0,
-                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  159, 0, 0, 0, 0,  0,  0, 0,   0,   0,
-                0,   0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  180, 0, 0, 0, 0,  0,  0, 0,   0,   0,
-                190, 0,   0,  0, 0, 0, 0, 0, 0,  0,   0,  0,   0, 0, 0, 0,  0,  0,
+                0,   47, 0, 4,  0, 0, 7, 0, 0,   0,   0,  0, 0, 0, 0,  0, 0, 0,   0,   0, 0,   0,
+                0,   0,  0, 0,  0, 0, 0, 0, 0,   32,  0,  0, 0, 0, 37, 0, 0, 40,  0,   0, 0,   0,
+                0,   0,  0, 0,  0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,  0, 0, 0,   0,   0, 0,   0,
+                67,  0,  0, 0,  0, 0, 0, 0, 0,   0,   77, 0, 0, 0, 0,  0, 0, 0,   85,  0, 0,   0,
+                0,   0,  0, 92, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,  0, 0, 0,   0,   0, 109, 0,
+                0,   0,  0, 0,  0, 0, 0, 0, 0,   120, 0,  0, 0, 0, 0,  0, 0, 0,   0,   0, 131, 0,
+                133, 0,  0, 0,  0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,  0, 0, 150, 0,   0, 0,   0,
+                0,   0,  0, 0,  0, 0, 0, 0, 0,   164, 0,  0, 0, 0, 0,  0, 0, 0,   0,   0, 0,   0,
+                0,   0,  0, 0,  0, 0, 0, 0, 185, 0,   0,  0, 0, 0, 0,  0, 0, 0,   195, 0, 0,   0,
+                0,   0,  0, 0,  0, 0, 0, 0, 0,   0,   0,  0, 0, 0,
         },
         {
-                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
         },
         {
-                0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,  79, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
-                24, 25, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,   0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 137, 0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   184,
-                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,
+                0,  84, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,   0, 24,
+                25, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   142, 0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 189, 0,   0, 0,
+                0,  0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
         },
         {
-                0, 107, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 112, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0,   2, 0,   0, 5,   0, 0, 8, 0, 0, 0,   12, 0,   0,   0, 0, 0,   0,  0, 0,  0,
-                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  34,  0,   0, 0, 0,   0,  0, 41, 0,
-                43,  0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 59,  0,  0, 0,  63,
-                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 74,  0,  0,   0,   0, 0, 0,   81, 0, 0,  0,
-                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  97,  0,   0, 0, 0,   0,  0, 0,  0,
-                106, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 0,   0,  0, 0,  0,
-                0,   0, 129, 0, 0,   0, 0, 0, 0, 0, 0,   0,  0,   0,   0, 0, 0,   0,  0, 0,  0,
-                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,  160, 0,   0, 0, 0,   0,  0, 0,  0,
-                169, 0, 0,   0, 173, 0, 0, 0, 0, 0, 0,   0,  0,   182, 0, 0, 0,   0,  0, 0,  0,
-                0,   0, 0,   0, 0,   0, 0, 0, 0, 0, 200, 0,  0,   0,   0, 0, 206, 0,
+                0,   2,   0, 0,  5, 0, 0,   8, 0, 0, 0,   12, 0,   0,   0, 0, 0, 0, 0,  0,   0, 0,
+                0,   0,   0, 0,  0, 0, 0,   0, 0, 0, 0,   34, 0,   0,   0, 0, 0, 0, 41, 0,   0, 0,
+                0,   0,   0, 48, 0, 0, 0,   0, 0, 0, 0,   0,  0,   0,   0, 0, 0, 0, 0,  64,  0, 0,
+                0,   68,  0, 0,  0, 0, 0,   0, 0, 0, 0,   0,  79,  0,   0, 0, 0, 0, 0,  86,  0, 0,
+                0,   0,   0, 0,  0, 0, 0,   0, 0, 0, 0,   0,  0,   102, 0, 0, 0, 0, 0,  0,   0, 0,
+                111, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0,   0,  0,   0,   0, 0, 0, 0, 0,  0,   0, 0,
+                0,   134, 0, 0,  0, 0, 0,   0, 0, 0, 0,   0,  0,   0,   0, 0, 0, 0, 0,  0,   0, 0,
+                0,   0,   0, 0,  0, 0, 0,   0, 0, 0, 165, 0,  0,   0,   0, 0, 0, 0, 0,  174, 0, 0,
+                0,   178, 0, 0,  0, 0, 0,   0, 0, 0, 187, 0,  0,   0,   0, 0, 0, 0, 0,  0,   0, 0,
+                0,   0,   0, 0,  0, 0, 205, 0, 0, 0, 0,   0,  211, 0,
         },
         {
-                0, 119, 0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 19, 0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 33, 0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 68, 0,
-                0, 0,   0, 73, 0, 0, 0,   0, 0, 0,  100, 0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   105, 0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   150, 0,   0, 0, 0, 0, 0, 0,  158, 0, 0,  0,
-                0, 0,   0, 0,  0, 0, 168, 0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
-                0, 0,   0, 0,  0, 0, 0,   0, 0, 0,  0,   0,   0,   0, 0, 0, 0, 0, 0,  0,   0, 0,  0,
+                0,   124, 0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 19,  0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 33, 0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0,
+                0,   0,   0, 0, 0, 0, 73, 0, 0,   0, 0,  78, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 110,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0,
+                155, 0,   0, 0, 0, 0, 0,  0, 163, 0, 0,  0,  0, 0, 0, 0, 0, 0, 173, 0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0,
+                0,   0,   0, 0, 0, 0, 0,  0, 0,   0, 0,  0,  0, 0,
         },
         {
-                0, 157, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 17,  18,  0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 47, 0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   88, 0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 133, 0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
-                0, 0,   0, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0,  0, 0,
+                0,  162, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17,  18,  0, 0, 0,  0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 45, 0, 0, 0,
+                52, 0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,  0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 93, 0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,  0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 0, 0, 0,  0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,  0, 0, 0,
+                0,  0,   0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,  0, 0, 0,
+                0,  0,   0, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0,
         },
         {
-                0, 2,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0, 2, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 20,  0,   0, 0,
-                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
-                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
-                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 86, 0,   0, 0,   0,   0, 0,
-                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   113, 0, 0,
-                0, 0, 0, 0, 125, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 135, 0,   0, 0,
-                0, 0, 0, 0, 143, 144, 0, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0,  0,   0, 0,   0,   0, 0,
-                0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  179, 0, 0,   0,   0, 0,
-                0, 0, 0, 0, 189, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0,   0, 0,   0,   0, 0,
+                0, 2, 0,  0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 20, 0, 0,
+                0, 0, 0,  0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,  0, 0,
+                0, 0, 91, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 130, 0,   0,   0,   0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0,   148, 149, 0,   0, 0,  0, 0,
+                0, 0, 0,  158, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0,   0,   0,   194, 0, 0,  0, 0,
+                0, 0, 0,  0,   0, 0, 0, 0,   0, 0, 0, 0, 0, 0,
         },
         {
-                0,   175, 0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  15, 0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 35, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   0,   0, 0, 75, 0,   0, 0,   0, 0, 0,  0, 89, 84, 0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   118, 0, 0, 0,  122, 0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0,   0,   0,   0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                162, 0,   164, 0, 0, 0,  0,   0, 170, 0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
-                0,   192, 187, 0, 0, 0,  0,   0, 0,   0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0,
+                0,  180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  15,  0,   0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35,  0,  0,   0,   0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0,   0,   0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   80, 0,   0,   0,   0, 0, 0, 0,   94,
+                89, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0,   0,   0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,  0,   0,   127, 0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0,   0,   0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 0,  169, 0,   0,   0, 0, 0, 175, 0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  197, 192, 0,   0, 0, 0, 0,   0,
+                0,  0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
         },
         {
-                0,  178, 0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   0,   21,
-                0,  0,   0,   0, 0, 0,   0,  0,  0,   31, 0,  0, 0, 0,   0, 0, 0, 39, 0,   0,   0,
-                0,  0,   0,   0, 0, 0,   49, 0,  0,   52, 53, 0, 0, 0,   0, 0, 0, 60, 0,   0,   0,
-                0,  0,   0,   0, 0, 0,   0,  71, 0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   0,   0,
-                85, 0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,  103, 0,   0,
-                0,  0,   0,   0, 0, 0,   0,  0,  114, 0,  0,  0, 0, 0,   0, 0, 0, 0,  124, 0,   0,
-                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 140, 0, 0, 0, 0,  0,   0,   0,
-                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 161, 0, 0, 0, 0,  0,   0,   0,
-                0,  0,   171, 0, 0, 174, 0,  0,  177, 0,  0,  0, 0, 0,   0, 0, 0, 0,  0,   188, 0,
-                0,  0,   0,   0, 0, 0,   0,  0,  0,   0,  0,  0, 0, 0,   0, 0, 0, 0,
+                0,  183, 0,  0, 0,   0,   0, 0,   0,   0,  0,  0, 0,   0,  0, 0,   0,  0,  0,   0,
+                21, 0,   0,  0, 0,   0,   0, 0,   0,   0,  31, 0, 0,   0,  0, 0,   0,  0,  39,  0,
+                0,  0,   43, 0, 0,   0,   0, 0,   0,   0,  0,  0, 0,   54, 0, 0,   57, 58, 0,   0,
+                0,  0,   0,  0, 65,  0,   0, 0,   0,   0,  0,  0, 0,   0,  0, 76,  0,  0,  0,   0,
+                0,  0,   0,  0, 0,   0,   0, 0,   0,   90, 0,  0, 0,   0,  0, 0,   0,  0,  0,   0,
+                0,  0,   0,  0, 0,   0,   0, 108, 0,   0,  0,  0, 0,   0,  0, 0,   0,  0,  119, 0,
+                0,  0,   0,  0, 0,   0,   0, 0,   129, 0,  0,  0, 0,   0,  0, 0,   0,  0,  0,   0,
+                0,  0,   0,  0, 145, 0,   0, 0,   0,   0,  0,  0, 0,   0,  0, 0,   0,  0,  0,   0,
+                0,  0,   0,  0, 0,   166, 0, 0,   0,   0,  0,  0, 0,   0,  0, 176, 0,  0,  179, 0,
+                0,  182, 0,  0, 0,   0,   0, 0,   0,   0,  0,  0, 193, 0,  0, 0,   0,  0,  0,   0,
+                0,  0,   0,  0, 0,   0,   0, 0,   0,   0,  0,  0,
         },
         {
-                0, 2,  0, 36, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 16,  0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
-                0, 48, 0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 163, 0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
-                0, 0,  0, 0,  0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0,
+                0, 2, 0, 36, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16,  0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 168, 0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0, 0, 0, 0, 0,
+                0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,
         },
         {
-                0, 2, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 67, 0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 151, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,  0, 0, 0,   0, 0, 0, 0,
+                0,  2, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                72, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0,
+                0,  0, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
+                0,  0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         },
         {
-                0, 2, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
+                0, 2, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 51, 0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  0, 0, 0,
+                0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0,
         },
         {
-                0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 78,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   99, 0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,  0, 0, 0, 0, 0,
-                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0,  0, 0, 0, 0,
+                0, 2, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 44, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 83, 0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 0,   0, 0, 0, 0, 0,  0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,  0, 0, 0, 207, 0, 0, 0, 0, 0,
         },
 };
 
-static int8_t accepts[207] = {
-        -1, -1, 23, 23, -1, -1, -1, -1, -1, 3,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, 6,  23, -1, -1, -1,
-        4,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7,  -1, -1,
-        -1, -1, -1, -1, -1, -1, 20, 23, -1, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, 14, 13, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, -1, 1,  23, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, 19, 23, -1, -1, -1, -1, 2,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, 8,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9,  23, -1, -1, -1,
-        -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 23, -1, 5,  23, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, 17, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 23, -1, -1, 21,
+static int8_t accepts[212] = {
+        -1, -1, 24, 24, -1, -1, -1, -1, -1, 3,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, 6,  24, -1,
+        -1, -1, 23, 24, -1, -1, -1, 4,  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, 7,  -1, -1, -1, -1, -1, -1, -1, -1, 20, 24, -1, 22, 24, -1, -1, -1,
+        -1, -1, -1, -1, -1, 14, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1,
+        -1, 1,  24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, 24, -1, -1, -1, -1, 2,  -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8,  -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, 9,  24, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, 11, 24, -1, 5,  24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 16,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 24, -1, -1, 21,
 };
 
 LayoutToken LayoutLexer::next() {
@@ -353,7 +365,7 @@
     LayoutToken::Kind lastAccept = LayoutToken::Kind::INVALID;
     int lastAcceptEnd = startOffset + 1;
     while (offset < fLength) {
-        if ((uint8_t) fText[offset] >= 127) {
+        if ((uint8_t)fText[offset] >= 127) {
             break;
         }
         state = transitions[mappings[(int)fText[offset]]][state];
diff --git a/src/sksl/SkSLLayoutLexer.h b/src/sksl/SkSLLayoutLexer.h
index f3d250a..148a8f3 100644
--- a/src/sksl/SkSLLayoutLexer.h
+++ b/src/sksl/SkSLLayoutLexer.h
@@ -61,6 +61,8 @@
         WHEN,
 #undef KEY
         KEY,
+#undef CTYPE
+        CTYPE,
 #undef INVALID
         INVALID,
     };
diff --git a/src/sksl/SkSLLexer.cpp b/src/sksl/SkSLLexer.cpp
index c97ded9..ac9cb2b 100644
--- a/src/sksl/SkSLLexer.cpp
+++ b/src/sksl/SkSLLexer.cpp
@@ -926,7 +926,7 @@
     Token::Kind lastAccept = Token::Kind::INVALID;
     int lastAcceptEnd = startOffset + 1;
     while (offset < fLength) {
-        if ((uint8_t) fText[offset] >= 127) {
+        if ((uint8_t)fText[offset] >= 127) {
             break;
         }
         state = transitions[mappings[(int)fText[offset]]][state];
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 9bfa62f..267d802 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -515,7 +515,7 @@
                                                           this->text(name), std::move(sizes)));
 }
 
-/** (EQ INT_LITERAL)? */
+/** EQ INT_LITERAL */
 int Parser::layoutInt() {
     if (!this->expect(Token::EQ, "'='")) {
         return -1;
@@ -527,6 +527,19 @@
     return -1;
 }
 
+/** EQ IDENTIFIER */
+StringFragment Parser::layoutIdentifier() {
+    if (!this->expect(Token::EQ, "'='")) {
+        return StringFragment();
+    }
+    Token resultToken;
+    if (!this->expect(Token::IDENTIFIER, "an identifier", &resultToken)) {
+        return StringFragment();
+    }
+    return this->text(resultToken);
+}
+
+
 /** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
 String Parser::layoutCode() {
     if (!this->expect(Token::EQ, "'='")) {
@@ -604,12 +617,13 @@
     int maxVertices = -1;
     int invocations = -1;
     String when;
+    StringFragment ctype;
     Layout::Key key = Layout::kNo_Key;
     if (this->checkNext(Token::LAYOUT)) {
         if (!this->expect(Token::LPAREN, "'('")) {
             return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
                           originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
-                          pushConstant, primitive, maxVertices, invocations, when, key);
+                          pushConstant, primitive, maxVertices, invocations, when, key, ctype);
         }
         for (;;) {
             Token t = this->nextToken();
@@ -684,6 +698,9 @@
                     case LayoutToken::KEY:
                         key = this->layoutKey();
                         break;
+                    case LayoutToken::CTYPE:
+                        ctype = this->layoutIdentifier();
+                        break;
                     default:
                         ASSERT(false);
                 }
@@ -702,7 +719,7 @@
     }
     return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex,
                   originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
-                  pushConstant, primitive, maxVertices, invocations, when, key);
+                  pushConstant, primitive, maxVertices, invocations, when, key, ctype);
 }
 
 /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE |
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 5391f6c..8485500 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -140,6 +140,8 @@
 
     int layoutInt();
 
+    StringFragment layoutIdentifier();
+
     String layoutCode();
 
     Layout::Key layoutKey();
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index ba80fb6..4452102 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -2093,7 +2093,7 @@
             Type intfStruct(-1, name, fields);
             Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false,
                           Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1,
-                          -1, "", Layout::kNo_Key);
+                          -1, "", Layout::kNo_Key, StringFragment());
             Variable* intfVar = new Variable(-1,
                                              Modifiers(layout, Modifiers::kUniform_Flag),
                                              name,
diff --git a/src/sksl/SkSLString.h b/src/sksl/SkSLString.h
index 7522939..143f7c6 100644
--- a/src/sksl/SkSLString.h
+++ b/src/sksl/SkSLString.h
@@ -27,7 +27,7 @@
 // Represents a (not necessarily null-terminated) slice of a string.
 struct StringFragment {
     StringFragment()
-    : fChars(nullptr)
+    : fChars("")
     , fLength(0) {}
 
     StringFragment(const char* chars)
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index dc67628..9c4fcb1 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -100,7 +100,7 @@
     Layout(int location, int offset, int binding, int index, int set, int builtin,
            int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage,
            bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive,
-           int maxVertices, int invocations, String when, Key key)
+           int maxVertices, int invocations, String when, Key key, StringFragment ctype)
     : fLocation(location)
     , fOffset(offset)
     , fBinding(binding)
@@ -117,7 +117,8 @@
     , fMaxVertices(maxVertices)
     , fInvocations(invocations)
     , fWhen(when)
-    , fKey(key) {}
+    , fKey(key)
+    , fCType(ctype) {}
 
     Layout()
     : fLocation(-1)
@@ -280,6 +281,7 @@
     int fInvocations;
     String fWhen;
     Key fKey;
+    StringFragment fCType;
 };
 
 } // namespace
diff --git a/src/sksl/lex/layout.lex b/src/sksl/lex/layout.lex
index 66d3088..a0c3987 100644
--- a/src/sksl/lex/layout.lex
+++ b/src/sksl/lex/layout.lex
@@ -20,4 +20,5 @@
 INVOCATIONS                 = "invocations"
 WHEN                        = "when"
 KEY                         = "key"
+CTYPE                       = "ctype"
 INVALID                     = .