Skip to content

Commit

Permalink
Image fallback expressions within paint properties (#11049)
Browse files Browse the repository at this point in the history
* Adding tests for icon-color, line-color and text-color

* Expanded tests to cover opacity, circle-radius and line-width

* Adding zoom render test

* Added tests for feature-state 

* Feature state fix

* Added Flow type to painter

* Shallow copy of style._availableImages

* Updating benchmark to use images
  • Loading branch information
SnailBones committed Oct 18, 2021
1 parent 19e7cef commit f95b8fa
Show file tree
Hide file tree
Showing 28 changed files with 799 additions and 72 deletions.
1 change: 1 addition & 0 deletions bench/benchmarks/symbol_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default class SymbolLayout extends Layout {
tileResult.iconMap,
tileResult.imageAtlas.iconPositions,
false,
this.parser.style.listImages(),
tileResult.tileID.canonical,
tileResult.tileZoom);
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export interface Bucket {
+stateDependentLayers: Array<any>;
+stateDependentLayerIds: Array<string>;
populate(features: Array<IndexedFeature>, options: PopulateParameters, canonical: CanonicalTileID): void;
update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}): void;
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}): void;
isEmpty(): boolean;

upload(context: Context): void;
Expand Down
10 changes: 5 additions & 5 deletions src/data/bucket/circle_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
const {geometry, index, sourceLayerIndex} = bucketFeature;
const feature = features[index].feature;

this.addFeature(bucketFeature, geometry, index, canonical);
this.addFeature(bucketFeature, geometry, index, options.availableImages, canonical);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
}
}

update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}) {
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, availableImages, imagePositions);
}

isEmpty() {
Expand Down Expand Up @@ -158,7 +158,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
this.segments.destroy();
}

addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID) {
addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, availableImages: Array<string>, canonical: CanonicalTileID) {
for (const ring of geometry) {
for (const point of ring) {
const x = point.x;
Expand Down Expand Up @@ -192,7 +192,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
}
}

this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, {}, canonical);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, {}, availableImages, canonical);
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/data/bucket/fill_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,22 @@ class FillBucket implements Bucket {
// so are stored during populate until later updated with positions by tile worker in addFeatures
this.patternFeatures.push(patternFeature);
} else {
this.addFeature(bucketFeature, geometry, index, canonical, {});
this.addFeature(bucketFeature, geometry, index, canonical, {}, options.availableImages);
}

const feature = features[index].feature;
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
}
}

update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}) {
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, availableImages, imagePositions);
}

addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string>) {
for (const feature of this.patternFeatures) {
this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions);
this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions, availableImages);
}
}

Expand Down Expand Up @@ -166,7 +166,7 @@ class FillBucket implements Bucket {
this.segments2.destroy();
}

addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string> = []) {
for (const polygon of classifyRings(geometry, EARCUT_MAX_RINGS)) {
let numVertices = 0;
for (const ring of polygon) {
Expand Down Expand Up @@ -220,7 +220,7 @@ class FillBucket implements Bucket {
triangleSegment.vertexLength += numVertices;
triangleSegment.primitiveLength += indices.length / 3;
}
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, availableImages, canonical);
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/data/bucket/fill_extrusion_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,25 +244,25 @@ class FillExtrusionBucket implements Bucket {
if (this.hasPattern) {
this.features.push(addPatternDependencies('fill-extrusion', this.layers, bucketFeature, this.zoom, options));
} else {
this.addFeature(bucketFeature, bucketFeature.geometry, index, canonical, {});
this.addFeature(bucketFeature, bucketFeature.geometry, index, canonical, {}, options.availableImages);
}

options.featureIndex.insert(feature, bucketFeature.geometry, index, sourceLayerIndex, this.index, vertexArrayOffset);
}
this.sortBorders();
}

addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string>) {
for (const feature of this.features) {
const {geometry} = feature;
this.addFeature(feature, geometry, feature.index, canonical, imagePositions);
this.addFeature(feature, geometry, feature.index, canonical, imagePositions, availableImages);
}
this.sortBorders();
}

update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}) {
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, availableImages, imagePositions);
}

isEmpty() {
Expand Down Expand Up @@ -301,7 +301,7 @@ class FillExtrusionBucket implements Bucket {
this.segments.destroy();
}

addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string>) {
const metadata = this.enableTerrain ? new PartMetadata() : null;

for (const polygon of classifyRings(geometry, EARCUT_MAX_RINGS)) {
Expand Down Expand Up @@ -432,7 +432,7 @@ class FillExtrusionBucket implements Bucket {
assert(!this.centroidVertexArray.length || this.centroidVertexArray.length === this.layoutVertexArray.length);
}

this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, availableImages, canonical);
}

sortBorders() {
Expand Down
14 changes: 7 additions & 7 deletions src/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class LineBucket implements Bucket {
this.patternFeatures.push(patternBucketFeature);

} else {
this.addFeature(bucketFeature, geometry, index, canonical, lineAtlas.positions);
this.addFeature(bucketFeature, geometry, index, canonical, lineAtlas.positions, options.availableImages);
}

const feature = features[index].feature;
Expand Down Expand Up @@ -266,14 +266,14 @@ class LineBucket implements Bucket {

}

update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}) {
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, availableImages, imagePositions);
}

addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeatures(options: PopulateParameters, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string>) {
for (const feature of this.patternFeatures) {
this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions);
this.addFeature(feature, feature.geometry, feature.index, canonical, imagePositions, availableImages);
}
}

Expand Down Expand Up @@ -313,7 +313,7 @@ class LineBucket implements Bucket {
}
}

addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}) {
addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, canonical: CanonicalTileID, imagePositions: {[_: string]: ImagePosition}, availableImages: Array<string>) {
const layout = this.layers[0].layout;
const join = layout.get('line-join').evaluate(feature, {});
const cap = layout.get('line-cap').evaluate(feature, {});
Expand All @@ -325,7 +325,7 @@ class LineBucket implements Bucket {
this.addLine(line, feature, join, cap, miterLimit, roundLimit);
}

this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, canonical);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions, availableImages, canonical);
}

addLine(vertices: Array<Point>, feature: BucketFeature, join: string, cap: string, miterLimit: number, roundLimit: number) {
Expand Down
9 changes: 5 additions & 4 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,10 +553,10 @@ class SymbolBucket implements Bucket {
}
}

update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[_: string]: ImagePosition}) {
update(states: FeatureStates, vtLayer: VectorTileLayer, availableImages: Array<string>, imagePositions: {[_: string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.text.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, imagePositions);
this.icon.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, imagePositions);
this.text.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, availableImages, imagePositions);
this.icon.programConfigurations.updatePaintArrays(states, vtLayer, this.layers, availableImages, imagePositions);
}

isEmpty() {
Expand Down Expand Up @@ -634,6 +634,7 @@ class SymbolBucket implements Bucket {
lineStartIndex: number,
lineLength: number,
associatedIconIndex: number,
availableImages: Array<string>,
canonical: CanonicalTileID) {
const indexArray = arrays.indexArray;
const layoutVertexArray = arrays.layoutVertexArray;
Expand Down Expand Up @@ -667,7 +668,7 @@ class SymbolBucket implements Bucket {
this.glyphOffsetArray.emplaceBack(glyphOffset[0]);

if (i === quads.length - 1 || sectionIndex !== quads[i + 1].sectionIndex) {
arrays.programConfigurations.populatePaintArrays(layoutVertexArray.length, feature, feature.index, {}, canonical, sections && sections[sectionIndex]);
arrays.programConfigurations.populatePaintArrays(layoutVertexArray.length, feature, feature.index, {}, availableImages, canonical, sections && sections[sectionIndex]);
}
}

Expand Down
Loading

0 comments on commit f95b8fa

Please sign in to comment.