Skip to content

Commit 46a73c4

Browse files
committed
Encapsulate SymbolBucket's unique requirements
SymbolBucket is in several ways the "odd bucket out": * It's the only bucket type that works with multiple program interfaces -- one for glyphs, one for icons, and one for collision boxes. * It's the only bucket type whose instances are reused to build buffers multiple times. Previously, the Bucket base class was generalized such that it could support multiple program interfaces for any Bucket subtype, and re-create buffers at any time. However, this added complexity to all subtypes other than Symbol. Now, SymbolBucket encapsulates its differences: * It uses ArrayGroup/BufferGroup directly, creating one for each of its three interfaces. In turn, the other bucket types, their corresponding layer rendering functions, and the Bucket base class, can all assume a single program interface. * It recreates these arrays when needed, while the Bucket base class creates them once, in the constructor.
1 parent 3252ad1 commit 46a73c4

18 files changed

+310
-379
lines changed

js/data/bucket.js

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ const ArrayGroup = require('./array_group');
44
const BufferGroup = require('./buffer_group');
55
const util = require('../util/util');
66

7-
const FAKE_ZOOM_HISTORY = { lastIntegerZoom: Infinity, lastIntegerZoomTime: 0, lastZoom: 0 };
8-
97
/**
108
* The `Bucket` class is the single point of knowledge about turning vector
119
* tiles into WebGL buffers.
@@ -25,23 +23,20 @@ class Bucket {
2523
* built for this tile. This object facilitates sharing of `Buffer`s be
2624
between `Bucket`s.
2725
*/
28-
constructor (options) {
26+
constructor (options, programInterface) {
2927
this.zoom = options.zoom;
3028
this.overscaling = options.overscaling;
3129
this.layers = options.layers;
3230
this.index = options.index;
3331

3432
if (options.arrays) {
35-
this.bufferGroups = util.mapObject(options.arrays, (arrayGroup, programName) => {
36-
return new BufferGroup(this.programInterfaces[programName], options.layers, options.zoom, arrayGroup);
37-
});
33+
this.buffers = new BufferGroup(programInterface, options.layers, options.zoom, options.arrays);
34+
} else {
35+
this.arrays = new ArrayGroup(programInterface, options.layers, options.zoom);
3836
}
3937
}
4038

4139
populate(features, options) {
42-
this.createArrays();
43-
this.recalculateStyleLayers();
44-
4540
for (const feature of features) {
4641
if (this.layers[0].filter(feature)) {
4742
this.addFeature(feature);
@@ -50,39 +45,20 @@ class Bucket {
5045
}
5146
}
5247

53-
createArrays() {
54-
this.arrays = util.mapObject(this.programInterfaces, (programInterface) => {
55-
return new ArrayGroup(programInterface, this.layers, this.zoom);
56-
});
57-
}
58-
59-
destroy() {
60-
for (const programName in this.bufferGroups) {
61-
this.bufferGroups[programName].destroy();
62-
}
63-
}
64-
6548
isEmpty() {
66-
for (const programName in this.arrays) {
67-
if (!this.arrays[programName].isEmpty()) {
68-
return false;
69-
}
70-
}
71-
return true;
49+
return this.arrays.isEmpty();
7250
}
7351

7452
serialize(transferables) {
7553
return {
7654
zoom: this.zoom,
7755
layerIds: this.layers.map((l) => l.id),
78-
arrays: util.mapObject(this.arrays, (a) => a.serialize(transferables))
56+
arrays: this.arrays.serialize(transferables)
7957
};
8058
}
8159

82-
recalculateStyleLayers() {
83-
for (const layer of this.layers) {
84-
layer.recalculate(this.zoom, FAKE_ZOOM_HISTORY);
85-
}
60+
destroy() {
61+
this.buffers.destroy();
8662
}
8763
}
8864

js/data/bucket/circle_bucket.js

Lines changed: 51 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,54 @@ const ElementArrayType = require('../element_array_type');
66
const loadGeometry = require('../load_geometry');
77
const EXTENT = require('../extent');
88

9-
const circleInterfaces = {
10-
circle: {
11-
layoutVertexArrayType: new VertexArrayType([{
12-
name: 'a_pos',
13-
components: 2,
14-
type: 'Int16'
15-
}]),
16-
elementArrayType: new ElementArrayType(),
17-
18-
paintAttributes: [{
19-
name: 'a_color',
20-
components: 4,
21-
type: 'Uint8',
22-
getValue: (layer, globalProperties, featureProperties) => {
23-
return layer.getPaintValue("circle-color", globalProperties, featureProperties);
24-
},
25-
multiplier: 255,
26-
paintProperty: 'circle-color'
27-
}, {
28-
name: 'a_radius',
29-
components: 1,
30-
type: 'Uint16',
31-
isLayerConstant: false,
32-
getValue: (layer, globalProperties, featureProperties) => {
33-
return [layer.getPaintValue("circle-radius", globalProperties, featureProperties)];
34-
},
35-
multiplier: 10,
36-
paintProperty: 'circle-radius'
37-
}, {
38-
name: 'a_blur',
39-
components: 1,
40-
type: 'Uint16',
41-
isLayerConstant: false,
42-
getValue: (layer, globalProperties, featureProperties) => {
43-
return [layer.getPaintValue("circle-blur", globalProperties, featureProperties)];
44-
},
45-
multiplier: 10,
46-
paintProperty: 'circle-blur'
47-
}, {
48-
name: 'a_opacity',
49-
components: 1,
50-
type: 'Uint16',
51-
isLayerConstant: false,
52-
getValue: (layer, globalProperties, featureProperties) => {
53-
return [layer.getPaintValue("circle-opacity", globalProperties, featureProperties)];
54-
},
55-
multiplier: 255,
56-
paintProperty: 'circle-opacity'
57-
}]
58-
}
9+
const circleInterface = {
10+
layoutVertexArrayType: new VertexArrayType([{
11+
name: 'a_pos',
12+
components: 2,
13+
type: 'Int16'
14+
}]),
15+
elementArrayType: new ElementArrayType(),
16+
17+
paintAttributes: [{
18+
name: 'a_color',
19+
components: 4,
20+
type: 'Uint8',
21+
getValue: (layer, globalProperties, featureProperties) => {
22+
return layer.getPaintValue("circle-color", globalProperties, featureProperties);
23+
},
24+
multiplier: 255,
25+
paintProperty: 'circle-color'
26+
}, {
27+
name: 'a_radius',
28+
components: 1,
29+
type: 'Uint16',
30+
isLayerConstant: false,
31+
getValue: (layer, globalProperties, featureProperties) => {
32+
return [layer.getPaintValue("circle-radius", globalProperties, featureProperties)];
33+
},
34+
multiplier: 10,
35+
paintProperty: 'circle-radius'
36+
}, {
37+
name: 'a_blur',
38+
components: 1,
39+
type: 'Uint16',
40+
isLayerConstant: false,
41+
getValue: (layer, globalProperties, featureProperties) => {
42+
return [layer.getPaintValue("circle-blur", globalProperties, featureProperties)];
43+
},
44+
multiplier: 10,
45+
paintProperty: 'circle-blur'
46+
}, {
47+
name: 'a_opacity',
48+
components: 1,
49+
type: 'Uint16',
50+
isLayerConstant: false,
51+
getValue: (layer, globalProperties, featureProperties) => {
52+
return [layer.getPaintValue("circle-opacity", globalProperties, featureProperties)];
53+
},
54+
multiplier: 255,
55+
paintProperty: 'circle-opacity'
56+
}]
5957
};
6058

6159
function addCircleVertex(layoutVertexArray, x, y, extrudeX, extrudeY) {
@@ -72,13 +70,12 @@ function addCircleVertex(layoutVertexArray, x, y, extrudeX, extrudeY) {
7270
* @private
7371
*/
7472
class CircleBucket extends Bucket {
75-
76-
get programInterfaces() {
77-
return circleInterfaces;
73+
constructor(options) {
74+
super(options, circleInterface);
7875
}
7976

8077
addFeature(feature) {
81-
const arrays = this.arrays.circle;
78+
const arrays = this.arrays;
8279

8380
for (const ring of loadGeometry(feature)) {
8481
for (const point of ring) {

js/data/bucket/fill_bucket.js

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,52 @@ const classifyRings = require('../../util/classify_rings');
99
const assert = require('assert');
1010
const EARCUT_MAX_RINGS = 500;
1111

12-
const fillInterfaces = {
13-
fill: {
14-
layoutVertexArrayType: new VertexArrayType([{
15-
name: 'a_pos',
16-
components: 2,
17-
type: 'Int16'
18-
}]),
19-
elementArrayType: new ElementArrayType(3),
20-
elementArrayType2: new ElementArrayType(2),
21-
22-
paintAttributes: [{
23-
name: 'a_color',
24-
components: 4,
25-
type: 'Uint8',
26-
getValue: (layer, globalProperties, featureProperties) => {
27-
return layer.getPaintValue("fill-color", globalProperties, featureProperties);
28-
},
29-
multiplier: 255,
30-
paintProperty: 'fill-color'
31-
}, {
32-
name: 'a_outline_color',
33-
components: 4,
34-
type: 'Uint8',
35-
getValue: (layer, globalProperties, featureProperties) => {
36-
return layer.getPaintValue("fill-outline-color", globalProperties, featureProperties);
37-
},
38-
multiplier: 255,
39-
paintProperty: 'fill-outline-color'
40-
}, {
41-
name: 'a_opacity',
42-
components: 1,
43-
type: 'Uint8',
44-
getValue: (layer, globalProperties, featureProperties) => {
45-
return [layer.getPaintValue("fill-opacity", globalProperties, featureProperties)];
46-
},
47-
multiplier: 255,
48-
paintProperty: 'fill-opacity'
49-
}]
50-
}
12+
const fillInterface = {
13+
layoutVertexArrayType: new VertexArrayType([{
14+
name: 'a_pos',
15+
components: 2,
16+
type: 'Int16'
17+
}]),
18+
elementArrayType: new ElementArrayType(3),
19+
elementArrayType2: new ElementArrayType(2),
20+
21+
paintAttributes: [{
22+
name: 'a_color',
23+
components: 4,
24+
type: 'Uint8',
25+
getValue: (layer, globalProperties, featureProperties) => {
26+
return layer.getPaintValue("fill-color", globalProperties, featureProperties);
27+
},
28+
multiplier: 255,
29+
paintProperty: 'fill-color'
30+
}, {
31+
name: 'a_outline_color',
32+
components: 4,
33+
type: 'Uint8',
34+
getValue: (layer, globalProperties, featureProperties) => {
35+
return layer.getPaintValue("fill-outline-color", globalProperties, featureProperties);
36+
},
37+
multiplier: 255,
38+
paintProperty: 'fill-outline-color'
39+
}, {
40+
name: 'a_opacity',
41+
components: 1,
42+
type: 'Uint8',
43+
getValue: (layer, globalProperties, featureProperties) => {
44+
return [layer.getPaintValue("fill-opacity", globalProperties, featureProperties)];
45+
},
46+
multiplier: 255,
47+
paintProperty: 'fill-opacity'
48+
}]
5149
};
5250

5351
class FillBucket extends Bucket {
54-
get programInterfaces() {
55-
return fillInterfaces;
52+
constructor(options) {
53+
super(options, fillInterface);
5654
}
5755

5856
addFeature(feature) {
59-
const arrays = this.arrays.fill;
57+
const arrays = this.arrays;
6058

6159
for (const polygon of classifyRings(loadGeometry(feature), EARCUT_MAX_RINGS)) {
6260
let numVertices = 0;

0 commit comments

Comments
 (0)