From c04f3e7d1b03263091d664390f132192351734a9 Mon Sep 17 00:00:00 2001
From: Vladimir Agafonkin <agafonkin@gmail.com>
Date: Fri, 4 Nov 2016 23:04:43 -0700
Subject: [PATCH] derive paint attribute names from properties

---
 js/data/bucket/circle_bucket.js         |  8 +++----
 js/data/bucket/fill_bucket.js           |  6 +++---
 js/data/bucket/fill_extrusion_bucket.js |  6 +++---
 js/data/bucket/line_bucket.js           |  2 +-
 js/data/program_configuration.js        | 28 ++++++++++++-------------
 test/js/data/bucket.test.js             | 16 +++++++-------
 6 files changed, 32 insertions(+), 34 deletions(-)

diff --git a/js/data/bucket/circle_bucket.js b/js/data/bucket/circle_bucket.js
index a790cc25df5..f71404a4870 100644
--- a/js/data/bucket/circle_bucket.js
+++ b/js/data/bucket/circle_bucket.js
@@ -13,10 +13,10 @@ const circleInterface = {
     elementArrayType: createElementArrayType(),
 
     paintAttributes: [
-        {name: 'a_color',   paintProperty: 'circle-color',   type: 'Uint8'},
-        {name: 'a_radius',  paintProperty: 'circle-radius',  type: 'Uint16', multiplier: 10},
-        {name: 'a_blur',    paintProperty: 'circle-blur',    type: 'Uint16', multiplier: 10},
-        {name: 'a_opacity', paintProperty: 'circle-opacity', type: 'Uint8',  multiplier: 255}
+        {property: 'circle-color',   type: 'Uint8'},
+        {property: 'circle-radius',  type: 'Uint16', multiplier: 10},
+        {property: 'circle-blur',    type: 'Uint16', multiplier: 10},
+        {property: 'circle-opacity', type: 'Uint8',  multiplier: 255}
     ]
 };
 
diff --git a/js/data/bucket/fill_bucket.js b/js/data/bucket/fill_bucket.js
index 40e6c59ed3a..2ed7c7630c0 100644
--- a/js/data/bucket/fill_bucket.js
+++ b/js/data/bucket/fill_bucket.js
@@ -17,9 +17,9 @@ const fillInterface = {
     elementArrayType2: createElementArrayType(2),
 
     paintAttributes: [
-        {name: 'a_color',         paintProperty: 'fill-color',         type: 'Uint8'},
-        {name: 'a_outline_color', paintProperty: 'fill-outline-color', type: 'Uint8'},
-        {name: 'a_opacity',       paintProperty: 'fill-opacity',       type: 'Uint8', multiplier: 255}
+        {property: 'fill-color',         type: 'Uint8'},
+        {property: 'fill-outline-color', type: 'Uint8'},
+        {property: 'fill-opacity',       type: 'Uint8', multiplier: 255}
     ]
 };
 
diff --git a/js/data/bucket/fill_extrusion_bucket.js b/js/data/bucket/fill_extrusion_bucket.js
index c1935e17ee0..9366e8f3f23 100644
--- a/js/data/bucket/fill_extrusion_bucket.js
+++ b/js/data/bucket/fill_extrusion_bucket.js
@@ -19,9 +19,9 @@ const fillExtrusionInterface = {
     elementArrayType: createElementArrayType(3),
 
     paintAttributes: [
-        {name: 'a_base',   paintProperty: 'fill-extrusion-base',   type: 'Uint16'},
-        {name: 'a_height', paintProperty: 'fill-extrusion-height', type: 'Uint16'},
-        {name: 'a_color',  paintProperty: 'fill-extrusion-color',  type: 'Uint8'}
+        {property: 'fill-extrusion-base',   type: 'Uint16'},
+        {property: 'fill-extrusion-height', type: 'Uint16'},
+        {property: 'fill-extrusion-color',  type: 'Uint8'}
     ]
 };
 
diff --git a/js/data/bucket/line_bucket.js b/js/data/bucket/line_bucket.js
index d7535e588f0..5d4d6887255 100644
--- a/js/data/bucket/line_bucket.js
+++ b/js/data/bucket/line_bucket.js
@@ -45,7 +45,7 @@ const lineInterface = {
         {name: 'a_data', components: 4, type: 'Uint8'}
     ]),
     paintAttributes: [
-        {name: 'a_color', paintProperty: 'line-color', type: 'Uint8'}
+        {property: 'line-color', type: 'Uint8'}
     ],
     elementArrayType: createElementArrayType()
 };
diff --git a/js/data/program_configuration.js b/js/data/program_configuration.js
index fb7af7ceb63..36f8ad25e53 100644
--- a/js/data/program_configuration.js
+++ b/js/data/program_configuration.js
@@ -2,7 +2,6 @@
 
 const createVertexArrayType = require('./vertex_array_type');
 const util = require('../util/util');
-const assert = require('assert');
 
 /**
  * ProgramConfiguration contains the logic for binding style layer properties and tile
@@ -34,14 +33,12 @@ class ProgramConfiguration {
         const self = new ProgramConfiguration();
 
         for (const attributeConfig of attributes) {
-
-            const attribute = normalizeAttribute(attributeConfig, layer);
-            assert(attribute.name.indexOf('a_') === 0);
+            const attribute = normalizePaintAttribute(attributeConfig, layer);
             const name = attribute.name.slice(2);
 
-            if (layer.isPaintValueFeatureConstant(attribute.paintProperty)) {
+            if (layer.isPaintValueFeatureConstant(attribute.property)) {
                 self.addZoomDrivenAttribute(name, attribute);
-            } else if (layer.isPaintValueZoomConstant(attribute.paintProperty)) {
+            } else if (layer.isPaintValueZoomConstant(attribute.property)) {
                 self.addDataDrivenAttribute(name, attribute);
             } else {
                 self.addDataAndZoomDrivenAttribute(name, attribute, layer, zoom);
@@ -102,7 +99,7 @@ class ProgramConfiguration {
 
         // Pick the index of the first offset to add to the buffers.
         let numStops = 0;
-        const zoomLevels = layer.getPaintValueStopZoomLevels(attribute.paintProperty);
+        const zoomLevels = layer.getPaintValueStopZoomLevels(attribute.property);
         while (numStops < zoomLevels.length && zoomLevels[numStops] < zoom) numStops++;
         const stopOffset = Math.max(0, Math.min(zoomLevels.length - 4, numStops - 2));
 
@@ -111,7 +108,7 @@ class ProgramConfiguration {
         vert.define.push(`uniform lowp float ${tName};`);
         this.interpolationUniforms.push({
             name: tName,
-            paintProperty: attribute.paintProperty,
+            property: attribute.property,
             stopOffset
         });
 
@@ -166,10 +163,10 @@ class ProgramConfiguration {
             let value;
             if (attribute.zoomStops) {
                 // add one multi-component value like color0, or pack multiple single-component values into a four component attribute
-                const values = attribute.zoomStops.map((zoom) => layer.getPaintValue(attribute.paintProperty, util.extend({}, globalProperties, {zoom}), featureProperties));
+                const values = attribute.zoomStops.map((zoom) => layer.getPaintValue(attribute.property, util.extend({}, globalProperties, {zoom}), featureProperties));
                 value = values.length === 1 ? values[0] : values;
             } else {
-                value = layer.getPaintValue(attribute.paintProperty, globalProperties, featureProperties);
+                value = layer.getPaintValue(attribute.property, globalProperties, featureProperties);
             }
 
             for (let i = start; i < length; i++) {
@@ -191,7 +188,7 @@ class ProgramConfiguration {
 
     setUniforms(gl, program, layer, globalProperties) {
         for (const uniform of this.uniforms) {
-            const value = layer.getPaintValue(uniform.paintProperty, globalProperties);
+            const value = layer.getPaintValue(uniform.property, globalProperties);
             if (uniform.components === 4) {
                 gl.uniform4fv(program[uniform.name], value);
             } else {
@@ -201,7 +198,7 @@ class ProgramConfiguration {
         for (const uniform of this.interpolationUniforms) {
             // stopInterp indicates which stops need to be interpolated.
             // If stopInterp is 3.5 then interpolate half way between stops 3 and 4.
-            const stopInterp = layer.getPaintInterpolationT(uniform.paintProperty, globalProperties);
+            const stopInterp = layer.getPaintInterpolationT(uniform.property, globalProperties);
             // We can only store four stop values in the buffers. stopOffset is the number of stops that come
             // before the stops that were added to the buffers.
             gl.uniform1f(program[uniform.name], Math.max(0, Math.min(4, stopInterp - uniform.stopOffset)));
@@ -209,9 +206,12 @@ class ProgramConfiguration {
     }
 }
 
-function normalizeAttribute(attribute, layer) {
-    const isColor = layer._paintSpecifications[attribute.paintProperty].type === 'color';
+function normalizePaintAttribute(attribute, layer) {
+    const name = attribute.property.replace(`${layer.type}-`, '').replace(/-/g, '_');
+    const isColor = layer._paintSpecifications[attribute.property].type === 'color';
+
     return util.extend({
+        name: `a_${name}`,
         components: isColor ? 4 : 1,
         multiplier: isColor ? 255 : 1
     }, attribute);
diff --git a/test/js/data/bucket.test.js b/test/js/data/bucket.test.js
index c81f5343bae..4c24ab42927 100644
--- a/test/js/data/bucket.test.js
+++ b/test/js/data/bucket.test.js
@@ -43,9 +43,8 @@ test('Bucket', (t) => {
             elementArrayType2: createElementArrayType(2),
 
             paintAttributes: options.paintAttributes || [{
-                name: 'a_map',
-                type: 'Int16',
-                paintProperty: 'circle-opacity'
+                property: 'circle-opacity',
+                type: 'Int16'
             }]
         };
 
@@ -96,7 +95,7 @@ test('Bucket', (t) => {
         const paintVertex = bucket.arrays.layerData.layerid.paintVertexArray;
         t.equal(paintVertex.length, 1);
         const p0 = paintVertex.get(0);
-        t.equal(p0.a_map, 17);
+        t.equal(p0.a_opacity, 17);
 
         const testElement = bucket.arrays.elementArray;
         t.equal(testElement.length, 1);
@@ -125,8 +124,8 @@ test('Bucket', (t) => {
         const v0 = bucket.arrays.layoutVertexArray.get(0);
         const a0 = bucket.arrays.layerData.one.paintVertexArray.get(0);
         const b0 = bucket.arrays.layerData.two.paintVertexArray.get(0);
-        t.equal(a0.a_map, 17);
-        t.equal(b0.a_map, 17);
+        t.equal(a0.a_opacity, 17);
+        t.equal(b0.a_opacity, 17);
         t.equal(v0.a_box0, 34);
         t.equal(v0.a_box1, 84);
 
@@ -136,9 +135,8 @@ test('Bucket', (t) => {
     t.test('add features, disabled attribute', (t) => {
         const bucket = create({
             paintAttributes: [{
-                name: 'a_map',
-                type: 'Int16',
-                paintProperty: 'circle-opacity'
+                property: 'circle-opacity',
+                type: 'Int16'
             }],
             layoutAttributes: [],
             layers: [