ol 7.5.1 → 8.0.0-dev.1692053484481

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/DataTile.d.ts +2 -2
  2. package/DataTile.d.ts.map +1 -1
  3. package/DataTile.js +3 -2
  4. package/Image.d.ts +139 -40
  5. package/Image.d.ts.map +1 -1
  6. package/Image.js +194 -96
  7. package/ImageCanvas.d.ts +2 -2
  8. package/ImageCanvas.d.ts.map +1 -1
  9. package/ImageCanvas.js +2 -2
  10. package/Object.d.ts +7 -0
  11. package/Object.d.ts.map +1 -1
  12. package/Object.js +8 -0
  13. package/dist/ol.js +2 -2
  14. package/dist/ol.js.map +1 -1
  15. package/expr/cpu.d.ts +71 -0
  16. package/expr/cpu.d.ts.map +1 -0
  17. package/expr/cpu.js +312 -0
  18. package/expr/expression.d.ts +97 -0
  19. package/expr/expression.d.ts.map +1 -0
  20. package/expr/expression.js +373 -0
  21. package/has.d.ts +5 -0
  22. package/has.d.ts.map +1 -1
  23. package/has.js +6 -0
  24. package/index.d.ts +1 -2
  25. package/index.js +1 -1
  26. package/layer/Base.d.ts +12 -8
  27. package/layer/Base.d.ts.map +1 -1
  28. package/layer/Base.js +12 -8
  29. package/layer/BaseVector.d.ts.map +1 -1
  30. package/layer/BaseVector.js +67 -33
  31. package/layer/Heatmap.d.ts.map +1 -1
  32. package/layer/Heatmap.js +16 -55
  33. package/layer/Layer.d.ts +2 -2
  34. package/layer/Layer.d.ts.map +1 -1
  35. package/layer/Layer.js +1 -1
  36. package/layer/WebGLPoints.d.ts +7 -12
  37. package/layer/WebGLPoints.d.ts.map +1 -1
  38. package/layer/WebGLPoints.js +7 -12
  39. package/package.json +1 -1
  40. package/render/Feature.d.ts +8 -0
  41. package/render/Feature.d.ts.map +1 -1
  42. package/render/Feature.js +9 -0
  43. package/render/canvas/Immediate.d.ts.map +1 -1
  44. package/render/canvas/Immediate.js +5 -3
  45. package/render/canvas/TextBuilder.js +2 -2
  46. package/render/canvas/style.d.ts +69 -0
  47. package/render/canvas/style.d.ts.map +1 -0
  48. package/render/canvas/style.js +1192 -0
  49. package/render/canvas.js +1 -1
  50. package/render/webgl/VectorStyleRenderer.d.ts.map +1 -1
  51. package/render/webgl/VectorStyleRenderer.js +4 -0
  52. package/renderer/Layer.d.ts +2 -2
  53. package/renderer/Layer.d.ts.map +1 -1
  54. package/renderer/Layer.js +1 -1
  55. package/renderer/canvas/ImageLayer.d.ts +4 -4
  56. package/renderer/canvas/ImageLayer.d.ts.map +1 -1
  57. package/renderer/canvas/ImageLayer.js +17 -12
  58. package/renderer/canvas/Layer.d.ts +2 -2
  59. package/renderer/canvas/Layer.d.ts.map +1 -1
  60. package/renderer/canvas/Layer.js +1 -1
  61. package/renderer/canvas/VectorImageLayer.d.ts.map +1 -1
  62. package/renderer/canvas/VectorImageLayer.js +3 -2
  63. package/renderer/webgl/VectorLayer.d.ts +1 -2
  64. package/renderer/webgl/VectorLayer.d.ts.map +1 -1
  65. package/reproj/Image.d.ts +5 -5
  66. package/reproj/Image.d.ts.map +1 -1
  67. package/reproj/Image.js +6 -6
  68. package/reproj.d.ts +2 -2
  69. package/reproj.d.ts.map +1 -1
  70. package/reproj.js +1 -1
  71. package/resolution.d.ts +13 -0
  72. package/resolution.d.ts.map +1 -0
  73. package/resolution.js +18 -0
  74. package/source/Image.d.ts +44 -7
  75. package/source/Image.d.ts.map +1 -1
  76. package/source/Image.js +97 -8
  77. package/source/ImageArcGISRest.d.ts +0 -23
  78. package/source/ImageArcGISRest.d.ts.map +1 -1
  79. package/source/ImageArcGISRest.js +18 -120
  80. package/source/ImageMapGuide.d.ts +0 -24
  81. package/source/ImageMapGuide.d.ts.map +1 -1
  82. package/source/ImageMapGuide.js +21 -113
  83. package/source/ImageStatic.d.ts +2 -27
  84. package/source/ImageStatic.d.ts.map +1 -1
  85. package/source/ImageStatic.js +20 -70
  86. package/source/ImageWMS.d.ts +2 -46
  87. package/source/ImageWMS.d.ts.map +1 -1
  88. package/source/ImageWMS.js +43 -201
  89. package/source/{Stamen.d.ts → StadiaMaps.d.ts} +17 -7
  90. package/source/StadiaMaps.d.ts.map +1 -0
  91. package/source/{Stamen.js → StadiaMaps.js} +85 -38
  92. package/source/TileArcGISRest.d.ts.map +1 -1
  93. package/source/TileArcGISRest.js +11 -22
  94. package/source/TileWMS.d.ts +0 -1
  95. package/source/TileWMS.d.ts.map +1 -1
  96. package/source/TileWMS.js +43 -106
  97. package/source/arcgisRest.d.ts +88 -0
  98. package/source/arcgisRest.d.ts.map +1 -0
  99. package/source/arcgisRest.js +131 -0
  100. package/source/common.d.ts +5 -0
  101. package/source/common.d.ts.map +1 -1
  102. package/source/common.js +6 -0
  103. package/source/mapguide.d.ts +52 -0
  104. package/source/mapguide.d.ts.map +1 -0
  105. package/source/mapguide.js +116 -0
  106. package/source/static.d.ts +45 -0
  107. package/source/static.d.ts.map +1 -0
  108. package/source/static.js +44 -0
  109. package/source/wms.d.ts +109 -1
  110. package/source/wms.d.ts.map +1 -1
  111. package/source/wms.js +170 -0
  112. package/source.d.ts +5 -1
  113. package/source.d.ts.map +1 -1
  114. package/source.js +5 -1
  115. package/style/flat.d.ts +332 -173
  116. package/style/flat.d.ts.map +1 -1
  117. package/style/flat.js +176 -248
  118. package/style/literal.d.ts +27 -72
  119. package/style/literal.d.ts.map +1 -1
  120. package/style/literal.js +14 -35
  121. package/util.d.ts.map +1 -1
  122. package/util.js +1 -1
  123. package/webgl/Helper.d.ts +7 -2
  124. package/webgl/Helper.d.ts.map +1 -1
  125. package/webgl/Helper.js +16 -27
  126. package/webgl/ShaderBuilder.d.ts +4 -14
  127. package/webgl/ShaderBuilder.d.ts.map +1 -1
  128. package/webgl/ShaderBuilder.js +72 -72
  129. package/webgl/styleparser.d.ts +3 -9
  130. package/webgl/styleparser.d.ts.map +1 -1
  131. package/webgl/styleparser.js +503 -88
  132. package/ImageBase.d.ts +0 -65
  133. package/ImageBase.d.ts.map +0 -1
  134. package/ImageBase.js +0 -98
  135. package/source/Stamen.d.ts.map +0 -1
@@ -5,33 +5,13 @@
5
5
  import {ShaderBuilder} from './ShaderBuilder.js';
6
6
  import {
7
7
  ValueTypes,
8
+ arrayToGlsl,
8
9
  expressionToGlsl,
9
10
  getStringNumberEquivalent,
10
11
  uniformNameForVariable,
11
12
  } from '../style/expressions.js';
12
13
  import {asArray} from '../color.js';
13
-
14
- /**
15
- * @param {import('../style/literal.js').SymbolType} type Symbol type
16
- * @param {string} sizeExpressionGlsl Size expression
17
- * @return {string} The GLSL opacity function
18
- */
19
- export function getSymbolOpacityGlslFunction(type, sizeExpressionGlsl) {
20
- switch (type) {
21
- case 'square':
22
- case 'image':
23
- return '1.0';
24
- // taken from https://thebookofshaders.com/07/
25
- case 'circle':
26
- return `(1.0-smoothstep(1.-4./${sizeExpressionGlsl},1.,dot(v_quadCoord-.5,v_quadCoord-.5)*4.))`;
27
- case 'triangle':
28
- const st = '(v_quadCoord*2.-1.)';
29
- const a = `(atan(${st}.x,${st}.y))`;
30
- return `(1.0-smoothstep(.5-3./${sizeExpressionGlsl},.5,cos(floor(.5+${a}/2.094395102)*2.094395102-${a})*length(${st})))`;
31
- default:
32
- throw new Error(`Unexpected symbol type: ${type}`);
33
- }
34
- }
14
+ import {getUid} from '../util.js';
35
15
 
36
16
  /**
37
17
  * Packs all components of a color into a two-floats array
@@ -83,102 +63,531 @@ function getGlslTypeFromType(type) {
83
63
  }
84
64
 
85
65
  /**
86
- * @param {import("../style/literal").LiteralStyle} style Style
66
+ * @param {import("../style/literal.js").LiteralStyle} style Style
67
+ * @param {ShaderBuilder} builder Shader builder
68
+ * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
69
+ * @param {'shape-'|'circle-'|'icon-'} prefix Properties prefix
70
+ */
71
+ function parseCommonSymbolProperties(style, builder, vertContext, prefix) {
72
+ let radius;
73
+ if (`${prefix}radius` in style && prefix !== 'icon-') {
74
+ radius = expressionToGlsl(
75
+ vertContext,
76
+ style[`${prefix}radius`],
77
+ ValueTypes.NUMBER
78
+ );
79
+ } else if (`${prefix}radius1` in style && prefix === 'shape-') {
80
+ radius = expressionToGlsl(
81
+ vertContext,
82
+ style[`${prefix}radius1`],
83
+ ValueTypes.NUMBER
84
+ );
85
+ }
86
+ if (radius !== undefined) {
87
+ if (`${prefix}stroke-width` in style) {
88
+ radius = `(${radius} + ${expressionToGlsl(
89
+ vertContext,
90
+ style[`${prefix}stroke-width`],
91
+ ValueTypes.NUMBER
92
+ )} * 0.5)`;
93
+ }
94
+ builder.setSymbolSizeExpression(`vec2(${radius} * 2. + 0.5)`); // adding some padding for antialiasing
95
+ }
96
+ if (`${prefix}scale` in style) {
97
+ const scale = expressionToGlsl(
98
+ vertContext,
99
+ style[`${prefix}scale`],
100
+ ValueTypes.NUMBER | ValueTypes.NUMBER_ARRAY
101
+ );
102
+ builder.setSymbolSizeExpression(
103
+ `${builder.getSymbolSizeExpression()} * ${scale}`
104
+ );
105
+ }
106
+ if (`${prefix}displacement` in style) {
107
+ builder.setSymbolOffsetExpression(
108
+ expressionToGlsl(
109
+ vertContext,
110
+ style[`${prefix}displacement`],
111
+ ValueTypes.NUMBER_ARRAY
112
+ )
113
+ );
114
+ }
115
+ if (`${prefix}rotation` in style) {
116
+ builder.setSymbolRotationExpression(
117
+ expressionToGlsl(
118
+ vertContext,
119
+ style[`${prefix}rotation`],
120
+ ValueTypes.NUMBER
121
+ )
122
+ );
123
+ }
124
+ if (`${prefix}rotate-with-view` in style) {
125
+ builder.setSymbolRotateWithView(!!style[`${prefix}rotate-with-view`]);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * @param {string} distanceField The distance field expression
131
+ * @param {string|null} fillColor The fill color expression; null if no fill
132
+ * @param {string|null} strokeColor The stroke color expression; null if no stroke
133
+ * @param {string|null} strokeWidth The stroke width expression; null if no stroke
134
+ * @param {string|null} opacity The opacity expression; null if no stroke
135
+ * @return {string} The final color expression, based on the distance field and given params
136
+ */
137
+ function getColorFromDistanceField(
138
+ distanceField,
139
+ fillColor,
140
+ strokeColor,
141
+ strokeWidth,
142
+ opacity
143
+ ) {
144
+ let color = 'vec4(0.)';
145
+ if (fillColor !== null) {
146
+ color = fillColor;
147
+ }
148
+ if (strokeColor !== null && strokeWidth !== null) {
149
+ const strokeFillRatio = `smoothstep(-${strokeWidth} + 0.63, -${strokeWidth} - 0.58, ${distanceField})`;
150
+ color = `mix(${strokeColor}, ${color}, ${strokeFillRatio})`;
151
+ }
152
+ const shapeOpacity = `(1.0 - smoothstep(-0.63, 0.58, ${distanceField}))`;
153
+ let result = `${color} * ${shapeOpacity}`;
154
+ if (opacity !== null) {
155
+ result = `${result} * ${opacity}`;
156
+ }
157
+ return result;
158
+ }
159
+
160
+ /**
161
+ * @param {import("../style/literal.js").LiteralStyle} style Style
87
162
  * @param {ShaderBuilder} builder Shader builder
88
163
  * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
89
164
  * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
90
165
  * @param {import("../style/expressions.js").ParsingContext} fragContext Fragment shader parsing context
91
166
  */
92
- function parseSymbolProperties(
167
+ function parseCircleProperties(
93
168
  style,
94
169
  builder,
95
170
  uniforms,
96
171
  vertContext,
97
172
  fragContext
98
173
  ) {
99
- if (!('symbol' in style)) {
100
- return;
174
+ // this function takes in screen coordinates in pixels and returns the signed distance field
175
+ // (0 on the boundary, negative inside the circle, positive outside, values in pixels)
176
+ fragContext.functions[
177
+ 'circleDistanceField'
178
+ ] = `float circleDistanceField(vec2 point, float radius) {
179
+ return length(point) - radius;
180
+ }`;
181
+
182
+ parseCommonSymbolProperties(style, builder, vertContext, 'circle-');
183
+
184
+ // OPACITY
185
+ let opacity = null;
186
+ if ('circle-opacity' in style) {
187
+ opacity = expressionToGlsl(
188
+ fragContext,
189
+ style['circle-opacity'],
190
+ ValueTypes.NUMBER
191
+ );
192
+ }
193
+
194
+ // SCALE
195
+ let currentPoint = 'coordsPx';
196
+ if ('circle-scale' in style) {
197
+ const scale = expressionToGlsl(
198
+ fragContext,
199
+ style['circle-scale'],
200
+ ValueTypes.NUMBER | ValueTypes.NUMBER_ARRAY
201
+ );
202
+ currentPoint = `coordsPx / ${scale}`;
101
203
  }
102
204
 
103
- const symbolStyle = style.symbol;
104
- if ('color' in symbolStyle) {
105
- const color = symbolStyle.color;
106
- const opacity = symbolStyle.opacity !== undefined ? symbolStyle.opacity : 1;
107
- const parsedColor = expressionToGlsl(fragContext, color, ValueTypes.COLOR);
108
- const parsedOpacity = expressionToGlsl(
205
+ // FILL COLOR
206
+ let fillColor = null;
207
+ if ('circle-fill-color' in style) {
208
+ fillColor = expressionToGlsl(
109
209
  fragContext,
110
- opacity,
210
+ style['circle-fill-color'],
211
+ ValueTypes.COLOR
212
+ );
213
+ }
214
+
215
+ // STROKE COLOR
216
+ let strokeColor = null;
217
+ if ('circle-stroke-color' in style) {
218
+ strokeColor = expressionToGlsl(
219
+ fragContext,
220
+ style['circle-stroke-color'],
221
+ ValueTypes.COLOR
222
+ );
223
+ }
224
+
225
+ // RADIUS
226
+ let radius = expressionToGlsl(
227
+ fragContext,
228
+ style['circle-radius'],
229
+ ValueTypes.NUMBER
230
+ );
231
+
232
+ // STROKE WIDTH
233
+ let strokeWidth = null;
234
+ if ('circle-stroke-width' in style) {
235
+ strokeWidth = expressionToGlsl(
236
+ fragContext,
237
+ style['circle-stroke-width'],
111
238
  ValueTypes.NUMBER
112
239
  );
113
- builder.setSymbolColorExpression(
114
- `vec4(${parsedColor}.rgb, ${parsedColor}.a * ${parsedOpacity})`
240
+ radius = `(${radius} + ${strokeWidth} * 0.5)`;
241
+ }
242
+
243
+ // FINAL COLOR
244
+ const distanceField = `circleDistanceField(${currentPoint}, ${radius})`;
245
+ const colorExpression = getColorFromDistanceField(
246
+ distanceField,
247
+ fillColor,
248
+ strokeColor,
249
+ strokeWidth,
250
+ opacity
251
+ );
252
+ builder.setSymbolColorExpression(colorExpression);
253
+ }
254
+
255
+ /**
256
+ * @param {import("../style/literal.js").LiteralStyle} style Style
257
+ * @param {ShaderBuilder} builder Shader builder
258
+ * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
259
+ * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
260
+ * @param {import("../style/expressions.js").ParsingContext} fragContext Fragment shader parsing context
261
+ */
262
+ function parseShapeProperties(
263
+ style,
264
+ builder,
265
+ uniforms,
266
+ vertContext,
267
+ fragContext
268
+ ) {
269
+ fragContext.functions['PI'] = 'const float PI = 3.141592653589793238;';
270
+ fragContext.functions['TWO_PI'] = 'const float TWO_PI = 2.0 * PI;';
271
+ fragContext.functions['round'] = `float round(float v) {
272
+ return sign(v) * floor(abs(v) + 0.5);
273
+ }`;
274
+
275
+ // these functions take in screen coordinates in pixels and returns the signed distance field
276
+ // (0 on the boundary, negative inside the circle, positive outside, values in pixels)
277
+ // inspired by https://github.com/zranger1/PixelblazePatterns/blob/master/Toolkit/sdf2d.md#n-sided-regular-polygon
278
+ fragContext.functions[
279
+ 'starDistanceField'
280
+ ] = `float starDistanceField(vec2 point, float numPoints, float radiusIn, float radiusOut, float angle) {
281
+ float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
282
+ float c = cos(startAngle);
283
+ float s = sin(startAngle);
284
+ vec2 pointRotated = vec2(c * point.x - s * point.y, s * point.x + c * point.y);
285
+ float alpha = TWO_PI / numPoints; // the angle of one sector
286
+ float beta = atan(pointRotated.y, pointRotated.x);
287
+ float gamma = round(beta / alpha) * alpha; // angle in sector
288
+ c = cos(-gamma);
289
+ s = sin(-gamma);
290
+ vec2 inSector = vec2(c * pointRotated.x - s * pointRotated.y, abs(s * pointRotated.x + c * pointRotated.y));
291
+ vec2 tipToPoint = inSector + vec2(-radiusOut, 0.);
292
+ vec2 edgeNormal = vec2(radiusIn * sin(alpha * 0.5), -radiusIn * cos(alpha * 0.5) + radiusOut);
293
+ return dot(normalize(edgeNormal), tipToPoint);
294
+ }`;
295
+ fragContext.functions[
296
+ 'regularDistanceField'
297
+ ] = `float regularDistanceField(vec2 point, float numPoints, float radius, float angle) {
298
+ float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
299
+ float c = cos(startAngle);
300
+ float s = sin(startAngle);
301
+ vec2 pointRotated = vec2(c * point.x - s * point.y, s * point.x + c * point.y);
302
+ float alpha = TWO_PI / numPoints; // the angle of one sector
303
+ float radiusIn = radius * cos(PI / numPoints);
304
+ float beta = atan(pointRotated.y, pointRotated.x);
305
+ float gamma = round((beta - alpha * 0.5) / alpha) * alpha + alpha * 0.5; // angle in sector from mid
306
+ c = cos(-gamma);
307
+ s = sin(-gamma);
308
+ vec2 inSector = vec2(c * pointRotated.x - s * pointRotated.y, abs(s * pointRotated.x + c * pointRotated.y));
309
+ return inSector.x - radiusIn;
310
+ }`;
311
+
312
+ parseCommonSymbolProperties(style, builder, vertContext, 'shape-');
313
+
314
+ // OPACITY
315
+ let opacity = null;
316
+ if ('shape-opacity' in style) {
317
+ opacity = expressionToGlsl(
318
+ fragContext,
319
+ style['shape-opacity'],
320
+ ValueTypes.NUMBER
115
321
  );
116
322
  }
117
- if (symbolStyle.symbolType === 'image' && symbolStyle.src) {
118
- const texture = new Image();
119
- texture.crossOrigin =
120
- symbolStyle.crossOrigin === undefined
121
- ? 'anonymous'
122
- : symbolStyle.crossOrigin;
123
- texture.src = symbolStyle.src;
124
- builder
125
- .addUniform('sampler2D u_texture')
126
- .setSymbolColorExpression(
127
- `${builder.getSymbolColorExpression()} * texture2D(u_texture, v_texCoord)`
128
- );
129
- uniforms['u_texture'] = texture;
130
- } else if ('symbolType' in symbolStyle) {
131
- let visibleSize = builder.getSymbolSizeExpression();
132
- if ('size' in symbolStyle) {
133
- visibleSize = expressionToGlsl(
134
- fragContext,
135
- symbolStyle.size,
136
- ValueTypes.NUMBER_ARRAY | ValueTypes.NUMBER
137
- );
323
+
324
+ // SCALE
325
+ let currentPoint = 'coordsPx';
326
+ if ('shape-scale' in style) {
327
+ const scale = expressionToGlsl(
328
+ fragContext,
329
+ style['shape-scale'],
330
+ ValueTypes.NUMBER | ValueTypes.NUMBER_ARRAY
331
+ );
332
+ currentPoint = `coordsPx / ${scale}`;
333
+ }
334
+
335
+ // FILL COLOR
336
+ let fillColor = null;
337
+ if ('shape-fill-color' in style) {
338
+ fillColor = expressionToGlsl(
339
+ fragContext,
340
+ style['shape-fill-color'],
341
+ ValueTypes.COLOR
342
+ );
343
+ }
344
+
345
+ // STROKE COLOR
346
+ let strokeColor = null;
347
+ if ('shape-stroke-color' in style) {
348
+ strokeColor = expressionToGlsl(
349
+ fragContext,
350
+ style['shape-stroke-color'],
351
+ ValueTypes.COLOR
352
+ );
353
+ }
354
+
355
+ // STROKE WIDTH
356
+ let strokeWidth = null;
357
+ if ('shape-stroke-width' in style) {
358
+ strokeWidth = expressionToGlsl(
359
+ fragContext,
360
+ style['shape-stroke-width'],
361
+ ValueTypes.NUMBER
362
+ );
363
+ }
364
+
365
+ // SHAPE TYPE
366
+ const numPoints = expressionToGlsl(
367
+ fragContext,
368
+ style['shape-points'],
369
+ ValueTypes.NUMBER
370
+ );
371
+ let angle = '0.';
372
+ if ('shape-angle' in style) {
373
+ angle = expressionToGlsl(
374
+ fragContext,
375
+ style['shape-angle'],
376
+ ValueTypes.NUMBER
377
+ );
378
+ }
379
+ let shapeField;
380
+ if ('shape-radius' in style) {
381
+ let radius = expressionToGlsl(
382
+ fragContext,
383
+ style['shape-radius'],
384
+ ValueTypes.NUMBER
385
+ );
386
+ if (strokeWidth !== null) {
387
+ radius = `${radius} + ${strokeWidth} * 0.5`;
138
388
  }
139
- const symbolOpacity = getSymbolOpacityGlslFunction(
140
- symbolStyle.symbolType,
141
- `vec2(${visibleSize}).x`
389
+ shapeField = `regularDistanceField(${currentPoint}, ${numPoints}, ${radius}, ${angle})`;
390
+ } else {
391
+ let radiusOuter = expressionToGlsl(
392
+ fragContext,
393
+ style['shape-radius1'],
394
+ ValueTypes.NUMBER
142
395
  );
143
- builder.setSymbolColorExpression(
144
- `${builder.getSymbolColorExpression()} * vec4(1.0, 1.0, 1.0, ${symbolOpacity})`
396
+ let radiusInner = expressionToGlsl(
397
+ fragContext,
398
+ style['shape-radius2'],
399
+ ValueTypes.NUMBER
145
400
  );
401
+ if (strokeWidth !== null) {
402
+ radiusOuter = `${radiusOuter} + ${strokeWidth} * 0.5`;
403
+ radiusInner = `${radiusInner} + ${strokeWidth} * 0.5`;
404
+ }
405
+ shapeField = `starDistanceField(${currentPoint}, ${numPoints}, ${radiusInner}, ${radiusOuter}, ${angle})`;
146
406
  }
147
- if ('size' in symbolStyle) {
148
- const size = symbolStyle.size;
149
- const parsedSize = expressionToGlsl(
150
- vertContext,
151
- size,
152
- ValueTypes.NUMBER_ARRAY | ValueTypes.NUMBER
407
+
408
+ // FINAL COLOR
409
+ const colorExpression = getColorFromDistanceField(
410
+ shapeField,
411
+ fillColor,
412
+ strokeColor,
413
+ strokeWidth,
414
+ opacity
415
+ );
416
+ builder.setSymbolColorExpression(colorExpression);
417
+ }
418
+
419
+ /**
420
+ * @param {import("../style/literal.js").LiteralStyle} style Style
421
+ * @param {ShaderBuilder} builder Shader builder
422
+ * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
423
+ * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
424
+ * @param {import("../style/expressions.js").ParsingContext} fragContext Fragment shader parsing context
425
+ */
426
+ function parseIconProperties(
427
+ style,
428
+ builder,
429
+ uniforms,
430
+ vertContext,
431
+ fragContext
432
+ ) {
433
+ fragContext.functions[
434
+ 'samplePremultiplied'
435
+ ] = `vec4 samplePremultiplied(sampler2D sampler, vec2 texCoord) {
436
+ vec4 color = texture2D(sampler, texCoord);
437
+ return vec4(color.rgb * color.a, color.a);
438
+ }`;
439
+
440
+ // COLOR
441
+ let color = 'vec4(1.0)';
442
+ if ('icon-color' in style) {
443
+ color = expressionToGlsl(
444
+ fragContext,
445
+ style['icon-color'],
446
+ ValueTypes.COLOR
153
447
  );
154
- builder.setSymbolSizeExpression(`vec2(${parsedSize})`);
155
448
  }
156
- if ('textureCoord' in symbolStyle) {
157
- builder.setTextureCoordinateExpression(
158
- expressionToGlsl(
449
+
450
+ // OPACITY
451
+ if ('icon-opacity' in style) {
452
+ color = `${color} * ${expressionToGlsl(
453
+ fragContext,
454
+ style['icon-opacity'],
455
+ ValueTypes.NUMBER
456
+ )}`;
457
+ }
458
+
459
+ // IMAGE & SIZE
460
+ let image;
461
+ let size;
462
+ const textureId = getUid(style);
463
+ if ('icon-src' in style) {
464
+ image = new Image();
465
+ image.crossOrigin =
466
+ style['icon-cross-origin'] === undefined
467
+ ? 'anonymous'
468
+ : style['icon-cross-origin'];
469
+ image.src = style['icon-src'];
470
+ // the size is provided asynchronously using a uniform
471
+ uniforms[`u_texture${textureId}_size`] = () => {
472
+ return image.complete ? [image.width, image.height] : [0, 0];
473
+ };
474
+ size = `u_texture${textureId}_size`;
475
+ builder.addUniform(`vec2 u_texture${textureId}_size`);
476
+ } else {
477
+ image = style['icon-img'];
478
+ const imgSize = style['icon-img-size'];
479
+ size = arrayToGlsl(imgSize);
480
+ }
481
+ uniforms[`u_texture${textureId}`] = image;
482
+ builder
483
+ .addUniform(`sampler2D u_texture${textureId}`)
484
+ .setSymbolColorExpression(
485
+ `${color} * samplePremultiplied(u_texture${textureId}, v_texCoord)`
486
+ )
487
+ .setSymbolSizeExpression(size);
488
+
489
+ // override size if width/height were specified
490
+ if ('icon-width' in style && 'icon-height' in style) {
491
+ builder.setSymbolSizeExpression(
492
+ `vec2(${expressionToGlsl(
159
493
  vertContext,
160
- symbolStyle.textureCoord,
161
- ValueTypes.NUMBER_ARRAY
162
- )
494
+ style['icon-width'],
495
+ ValueTypes.NUMBER
496
+ )}, ${expressionToGlsl(
497
+ vertContext,
498
+ style['icon-height'],
499
+ ValueTypes.NUMBER
500
+ )})`
163
501
  );
164
502
  }
165
- if ('offset' in symbolStyle) {
166
- builder.setSymbolOffsetExpression(
167
- expressionToGlsl(vertContext, symbolStyle.offset, ValueTypes.NUMBER_ARRAY)
503
+
504
+ // tex coord
505
+ if ('icon-offset' in style && 'icon-size' in style) {
506
+ let offset = expressionToGlsl(
507
+ vertContext,
508
+ style['icon-offset'],
509
+ ValueTypes.NUMBER_ARRAY
168
510
  );
169
- }
170
- if ('rotation' in symbolStyle) {
171
- builder.setSymbolRotationExpression(
172
- expressionToGlsl(vertContext, symbolStyle.rotation, ValueTypes.NUMBER)
511
+ const sampleSize = expressionToGlsl(
512
+ vertContext,
513
+ style['icon-size'],
514
+ ValueTypes.NUMBER_ARRAY
515
+ );
516
+ const fullsize = builder.getSymbolSizeExpression();
517
+ builder.setSymbolSizeExpression(sampleSize);
518
+
519
+ if ('icon-offset-origin' in style) {
520
+ switch (style['icon-offset-origin']) {
521
+ case 'top-right':
522
+ offset = `vec2(v_quadSizePx.x, 0.) + ${sampleSize} * vec2(-1., 0.) + ${offset} * vec2(-1., 1.)`;
523
+ break;
524
+ case 'bottom-left':
525
+ offset = `vec2(0., v_quadSizePx.y) + ${sampleSize} * vec2(0., -1.) + ${offset} * vec2(1., -1.)`;
526
+ break;
527
+ case 'bottom-right':
528
+ offset = `v_quadSizePx - ${sampleSize} - ${offset}`;
529
+ break;
530
+ default: // pass
531
+ }
532
+ }
533
+ builder.setTextureCoordinateExpression(
534
+ `(vec4((${offset}).xyxy) + vec4(0., 0., ${sampleSize})) / (${fullsize}).xyxy`
173
535
  );
174
536
  }
175
- if ('rotateWithView' in symbolStyle) {
176
- builder.setSymbolRotateWithView(!!symbolStyle.rotateWithView);
537
+
538
+ parseCommonSymbolProperties(style, builder, vertContext, 'icon-');
539
+
540
+ if ('icon-anchor' in style) {
541
+ const anchor = expressionToGlsl(
542
+ vertContext,
543
+ style['icon-anchor'],
544
+ ValueTypes.NUMBER_ARRAY
545
+ );
546
+ let scale = `1.0`;
547
+ if (`icon-scale` in style) {
548
+ scale = expressionToGlsl(
549
+ vertContext,
550
+ style[`icon-scale`],
551
+ ValueTypes.NUMBER | ValueTypes.NUMBER_ARRAY
552
+ );
553
+ }
554
+ let shiftPx;
555
+ if (
556
+ style['icon-anchor-x-units'] === 'pixels' &&
557
+ style['icon-anchor-y-units'] === 'pixels'
558
+ ) {
559
+ shiftPx = `${anchor} * ${scale}`;
560
+ } else if (style['icon-anchor-x-units'] === 'pixels') {
561
+ shiftPx = `${anchor} * vec2(vec2(${scale}).x, v_quadSizePx.y)`;
562
+ } else if (style['icon-anchor-y-units'] === 'pixels') {
563
+ shiftPx = `${anchor} * vec2(v_quadSizePx.x, vec2(${scale}).x)`;
564
+ } else {
565
+ shiftPx = `${anchor} * v_quadSizePx`;
566
+ }
567
+ // default origin is top-left
568
+ let offsetPx = `v_quadSizePx * vec2(0.5, -0.5) + ${shiftPx} * vec2(-1., 1.)`;
569
+ if ('icon-anchor-origin' in style) {
570
+ switch (style['icon-anchor-origin']) {
571
+ case 'top-right':
572
+ offsetPx = `v_quadSizePx * -0.5 + ${shiftPx}`;
573
+ break;
574
+ case 'bottom-left':
575
+ offsetPx = `v_quadSizePx * 0.5 - ${shiftPx}`;
576
+ break;
577
+ case 'bottom-right':
578
+ offsetPx = `v_quadSizePx * vec2(-0.5, 0.5) + ${shiftPx} * vec2(1., -1.)`;
579
+ break;
580
+ default: // pass
581
+ }
582
+ }
583
+ builder.setSymbolOffsetExpression(
584
+ `${builder.getSymbolOffsetExpression()} + ${offsetPx}`
585
+ );
177
586
  }
178
587
  }
179
588
 
180
589
  /**
181
- * @param {import("../style/literal").LiteralStyle} style Style
590
+ * @param {import("../style/literal.js").LiteralStyle} style Style
182
591
  * @param {ShaderBuilder} builder Shader Builder
183
592
  * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
184
593
  * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
@@ -205,7 +614,7 @@ function parseStrokeProperties(
205
614
  }
206
615
 
207
616
  /**
208
- * @param {import("../style/literal").LiteralStyle} style Style
617
+ * @param {import("../style/literal.js").LiteralStyle} style Style
209
618
  * @param {ShaderBuilder} builder Shader Builder
210
619
  * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
211
620
  * @param {import("../style/expressions.js").ParsingContext} vertContext Vertex shader parsing context
@@ -233,14 +642,14 @@ function parseFillProperties(
233
642
  */
234
643
 
235
644
  /**
236
- * Parses a {@link import("../style/literal").LiteralStyle} object and returns a {@link ShaderBuilder}
645
+ * Parses a {@link import("../style/literal.js").LiteralStyle} object and returns a {@link ShaderBuilder}
237
646
  * object that has been configured according to the given style, as well as `attributes` and `uniforms`
238
647
  * arrays to be fed to the `WebGLPointsRenderer` class.
239
648
  *
240
649
  * Also returns `uniforms` and `attributes` properties as expected by the
241
650
  * {@link module:ol/renderer/webgl/PointsLayer~WebGLPointsLayerRenderer}.
242
651
  *
243
- * @param {import("../style/literal").LiteralStyle} style Literal style.
652
+ * @param {import("../style/literal.js").LiteralStyle} style Literal style.
244
653
  * @return {StyleParseResult} Result containing shader params, attributes and uniforms.
245
654
  */
246
655
  export function parseLiteralStyle(style) {
@@ -273,7 +682,13 @@ export function parseLiteralStyle(style) {
273
682
  /** @type {Object<string,import("../webgl/Helper").UniformValue>} */
274
683
  const uniforms = {};
275
684
 
276
- parseSymbolProperties(style, builder, uniforms, vertContext, fragContext);
685
+ if ('icon-src' in style || 'icon-img' in style) {
686
+ parseIconProperties(style, builder, uniforms, vertContext, fragContext);
687
+ } else if ('shape-points' in style) {
688
+ parseShapeProperties(style, builder, uniforms, vertContext, fragContext);
689
+ } else if ('circle-radius' in style) {
690
+ parseCircleProperties(style, builder, uniforms, vertContext, fragContext);
691
+ }
277
692
  parseStrokeProperties(style, builder, uniforms, vertContext, fragContext);
278
693
  parseFillProperties(style, builder, uniforms, vertContext, fragContext);
279
694