ol 10.4.1-dev.1740542736318 → 10.4.1-dev.1740574913397

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 (53) hide show
  1. package/dist/ol.d.ts +47 -33
  2. package/dist/ol.d.ts.map +1 -1
  3. package/dist/ol.js +1 -1
  4. package/dist/ol.js.map +1 -1
  5. package/expr/gpu.d.ts +0 -5
  6. package/expr/gpu.d.ts.map +1 -1
  7. package/expr/gpu.js +3 -8
  8. package/layer/BaseVector.d.ts +2 -2
  9. package/layer/BaseVector.d.ts.map +1 -1
  10. package/layer/BaseVector.js +1 -1
  11. package/layer/Flow.d.ts.map +1 -1
  12. package/layer/Flow.js +1 -2
  13. package/layer/Heatmap.d.ts +54 -18
  14. package/layer/Heatmap.d.ts.map +1 -1
  15. package/layer/Heatmap.js +169 -50
  16. package/layer/WebGLPoints.d.ts +1 -1
  17. package/layer/WebGLPoints.d.ts.map +1 -1
  18. package/layer/WebGLPoints.js +2 -2
  19. package/layer/WebGLTile.d.ts.map +1 -1
  20. package/layer/WebGLTile.js +1 -2
  21. package/package.json +1 -1
  22. package/render/webgl/MixedGeometryBatch.d.ts.map +1 -1
  23. package/render/webgl/MixedGeometryBatch.js +4 -0
  24. package/{webgl → render/webgl}/ShaderBuilder.d.ts +28 -29
  25. package/render/webgl/ShaderBuilder.d.ts.map +1 -0
  26. package/{webgl → render/webgl}/ShaderBuilder.js +115 -123
  27. package/render/webgl/VectorStyleRenderer.d.ts +2 -2
  28. package/render/webgl/VectorStyleRenderer.d.ts.map +1 -1
  29. package/render/webgl/VectorStyleRenderer.js +3 -3
  30. package/render/webgl/{utils.d.ts → bufferUtil.d.ts} +1 -37
  31. package/render/webgl/bufferUtil.d.ts.map +1 -0
  32. package/render/webgl/{utils.js → bufferUtil.js} +2 -123
  33. package/render/webgl/compileUtil.d.ts +51 -0
  34. package/render/webgl/compileUtil.d.ts.map +1 -0
  35. package/render/webgl/compileUtil.js +203 -0
  36. package/render/webgl/encodeUtil.d.ts +20 -0
  37. package/render/webgl/encodeUtil.d.ts.map +1 -0
  38. package/render/webgl/encodeUtil.js +39 -0
  39. package/render/webgl/style.d.ts +57 -0
  40. package/render/webgl/style.d.ts.map +1 -0
  41. package/{webgl/styleparser.js → render/webgl/style.js} +187 -322
  42. package/renderer/webgl/PointsLayer.js +1 -1
  43. package/renderer/webgl/VectorLayer.d.ts +1 -0
  44. package/renderer/webgl/VectorLayer.d.ts.map +1 -1
  45. package/renderer/webgl/VectorLayer.js +4 -1
  46. package/renderer/webgl/VectorTileLayer.d.ts.map +1 -1
  47. package/renderer/webgl/VectorTileLayer.js +5 -3
  48. package/util.js +1 -1
  49. package/worker/webgl.js +1 -1
  50. package/render/webgl/utils.d.ts.map +0 -1
  51. package/webgl/ShaderBuilder.d.ts.map +0 -1
  52. package/webgl/styleparser.d.ts +0 -57
  53. package/webgl/styleparser.d.ts.map +0 -1
@@ -1,9 +1,8 @@
1
1
  /**
2
- * Utilities for parsing literal style objects
3
- * @module ol/webgl/styleparser
2
+ * Utilities for parsing flat styles for WebGL renderers
3
+ * @module ol/render/webgl/style
4
4
  */
5
- import {assert} from '../asserts.js';
6
- import {asArray} from '../color.js';
5
+ import {assert} from '../../asserts.js';
7
6
  import {
8
7
  BooleanType,
9
8
  ColorType,
@@ -12,85 +11,23 @@ import {
12
11
  SizeType,
13
12
  StringType,
14
13
  computeGeometryType,
15
- newParsingContext,
16
- } from '../expr/expression.js';
14
+ } from '../../expr/expression.js';
17
15
  import {
18
16
  FEATURE_ID_PROPERTY_NAME,
19
17
  GEOMETRY_TYPE_PROPERTY_NAME,
20
- buildExpression,
21
18
  getStringNumberEquivalent,
22
19
  newCompilationContext,
23
20
  stringToGlsl,
24
- uniformNameForVariable,
25
- } from '../expr/gpu.js';
21
+ } from '../../expr/gpu.js';
26
22
  import {ShaderBuilder} from './ShaderBuilder.js';
27
-
28
- /**
29
- * Recursively parses a style expression and outputs a GLSL-compatible string. Takes in a compilation context that
30
- * will be read and modified during the parsing operation.
31
- * @param {import("../expr/gpu.js").CompilationContext} compilationContext Compilation context
32
- * @param {import("../expr/expression.js").EncodedExpression} value Value
33
- * @param {number} [expectedType] Expected final type (can be several types combined)
34
- * @return {string} GLSL-compatible output
35
- */
36
- export function expressionToGlsl(compilationContext, value, expectedType) {
37
- const parsingContext = newParsingContext();
38
- return buildExpression(
39
- value,
40
- expectedType,
41
- parsingContext,
42
- compilationContext,
43
- );
44
- }
45
-
46
- /**
47
- * Packs all components of a color into a two-floats array
48
- * @param {import("../color.js").Color|string} color Color as array of numbers or string
49
- * @return {Array<number>} Vec2 array containing the color in compressed form
50
- */
51
- export function packColor(color) {
52
- const array = asArray(color);
53
- const r = array[0] * 256;
54
- const g = array[1];
55
- const b = array[2] * 256;
56
- const a = Math.round(array[3] * 255);
57
- return [r + g, b + a];
58
- }
59
-
60
- const UNPACK_COLOR_FN = `vec4 unpackColor(vec2 packedColor) {
61
- return vec4(
62
- fract(floor(packedColor[0] / 256.0) / 256.0),
63
- fract(packedColor[0] / 256.0),
64
- fract(floor(packedColor[1] / 256.0) / 256.0),
65
- fract(packedColor[1] / 256.0)
66
- );
67
- }`;
68
-
69
- /**
70
- * @param {number} type Value type
71
- * @return {1|2|3|4} The amount of components for this value
72
- */
73
- function getGlslSizeFromType(type) {
74
- if (type === ColorType || type === SizeType) {
75
- return 2;
76
- }
77
- if (type === NumberArrayType) {
78
- return 4;
79
- }
80
- return 1;
81
- }
82
-
83
- /**
84
- * @param {number} type Value type
85
- * @return {'float'|'vec2'|'vec3'|'vec4'} The corresponding GLSL type for this value
86
- */
87
- function getGlslTypeFromType(type) {
88
- const size = getGlslSizeFromType(type);
89
- if (size > 1) {
90
- return /** @type {'vec2'|'vec3'|'vec4'} */ (`vec${size}`);
91
- }
92
- return 'float';
93
- }
23
+ import {
24
+ applyContextToBuilder,
25
+ expressionToGlsl,
26
+ generateAttributesFromContext,
27
+ generateUniformsFromContext,
28
+ getGlslSizeFromType,
29
+ getGlslTypeFromType,
30
+ } from './compileUtil.js';
94
31
 
95
32
  /**
96
33
  * see https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
@@ -105,9 +42,9 @@ export function computeHash(input) {
105
42
  }
106
43
 
107
44
  /**
108
- * @param {import("../style/flat.js").FlatStyle} style Style
45
+ * @param {import("../../style/flat.js").FlatStyle} style Style
109
46
  * @param {ShaderBuilder} builder Shader builder
110
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
47
+ * @param {import("../../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
111
48
  * @param {'shape-'|'circle-'|'icon-'} prefix Properties prefix
112
49
  */
113
50
  function parseCommonSymbolProperties(style, builder, vertContext, prefix) {
@@ -197,9 +134,9 @@ function getColorFromDistanceField(
197
134
  /**
198
135
  * This will parse an image property provided by `<prefix>-src`
199
136
  * The image size expression in GLSL will be returned
200
- * @param {import("../style/flat.js").FlatStyle} style Style
137
+ * @param {import("../../style/flat.js").FlatStyle} style Style
201
138
  * @param {ShaderBuilder} builder Shader builder
202
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
139
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
203
140
  * @param {'icon-'|'fill-pattern-'|'stroke-pattern-'} prefix Property prefix
204
141
  * @param {string} textureId A identifier that will be used in the generated uniforms: `sample2d u_texture<id>` and `vec2 u_texture<id>_size`
205
142
  * @return {string} The image size expression
@@ -230,9 +167,9 @@ function parseImageProperties(style, builder, uniforms, prefix, textureId) {
230
167
 
231
168
  /**
232
169
  * This will parse an image's offset properties provided by `<prefix>-offset`, `<prefix>-offset-origin` and `<prefix>-size`
233
- * @param {import("../style/flat.js").FlatStyle} style Style
170
+ * @param {import("../../style/flat.js").FlatStyle} style Style
234
171
  * @param {'icon-'|'fill-pattern-'|'stroke-pattern-'} prefix Property prefix
235
- * @param {import("../expr/gpu.js").CompilationContext} context Shader compilation context (vertex or fragment)
172
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context (vertex or fragment)
236
173
  * @param {string} imageSize Pixel size of the full image as a GLSL expression
237
174
  * @param {string} sampleSize Pixel size of the sample in the image as a GLSL expression
238
175
  * @return {string} The offset expression
@@ -267,46 +204,31 @@ function parseImageOffsetProperties(
267
204
  }
268
205
 
269
206
  /**
270
- * @param {import("../style/flat.js").FlatStyle} style Style
207
+ * @param {import("../../style/flat.js").FlatStyle} style Style
271
208
  * @param {ShaderBuilder} builder Shader builder
272
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
273
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
274
- * @param {import("../expr/gpu.js").CompilationContext} fragContext Fragment shader compilation context
209
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
210
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context
275
211
  */
276
- function parseCircleProperties(
277
- style,
278
- builder,
279
- uniforms,
280
- vertContext,
281
- fragContext,
282
- ) {
212
+ function parseCircleProperties(style, builder, uniforms, context) {
283
213
  // this function takes in screen coordinates in pixels and returns the signed distance field
284
214
  // (0 on the boundary, negative inside the circle, positive outside, values in pixels)
285
- fragContext.functions['circleDistanceField'] =
215
+ context.functions['circleDistanceField'] =
286
216
  `float circleDistanceField(vec2 point, float radius) {
287
217
  return length(point) - radius;
288
218
  }`;
289
219
 
290
- parseCommonSymbolProperties(style, builder, vertContext, 'circle-');
220
+ parseCommonSymbolProperties(style, builder, context, 'circle-');
291
221
 
292
222
  // OPACITY
293
223
  let opacity = null;
294
224
  if ('circle-opacity' in style) {
295
- opacity = expressionToGlsl(
296
- fragContext,
297
- style['circle-opacity'],
298
- NumberType,
299
- );
225
+ opacity = expressionToGlsl(context, style['circle-opacity'], NumberType);
300
226
  }
301
227
 
302
228
  // SCALE
303
229
  let currentPoint = 'coordsPx';
304
230
  if ('circle-scale' in style) {
305
- const scale = expressionToGlsl(
306
- fragContext,
307
- style['circle-scale'],
308
- SizeType,
309
- );
231
+ const scale = expressionToGlsl(context, style['circle-scale'], SizeType);
310
232
  currentPoint = `coordsPx / ${scale}`;
311
233
  }
312
234
 
@@ -314,7 +236,7 @@ function parseCircleProperties(
314
236
  let fillColor = null;
315
237
  if ('circle-fill-color' in style) {
316
238
  fillColor = expressionToGlsl(
317
- fragContext,
239
+ context,
318
240
  style['circle-fill-color'],
319
241
  ColorType,
320
242
  );
@@ -324,24 +246,20 @@ function parseCircleProperties(
324
246
  let strokeColor = null;
325
247
  if ('circle-stroke-color' in style) {
326
248
  strokeColor = expressionToGlsl(
327
- fragContext,
249
+ context,
328
250
  style['circle-stroke-color'],
329
251
  ColorType,
330
252
  );
331
253
  }
332
254
 
333
255
  // RADIUS
334
- let radius = expressionToGlsl(
335
- fragContext,
336
- style['circle-radius'],
337
- NumberType,
338
- );
256
+ let radius = expressionToGlsl(context, style['circle-radius'], NumberType);
339
257
 
340
258
  // STROKE WIDTH
341
259
  let strokeWidth = null;
342
260
  if ('circle-stroke-width' in style) {
343
261
  strokeWidth = expressionToGlsl(
344
- fragContext,
262
+ context,
345
263
  style['circle-stroke-width'],
346
264
  NumberType,
347
265
  );
@@ -361,27 +279,20 @@ function parseCircleProperties(
361
279
  }
362
280
 
363
281
  /**
364
- * @param {import("../style/flat.js").FlatStyle} style Style
282
+ * @param {import("../../style/flat.js").FlatStyle} style Style
365
283
  * @param {ShaderBuilder} builder Shader builder
366
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
367
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
368
- * @param {import("../expr/gpu.js").CompilationContext} fragContext Fragment shader compilation context
284
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
285
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context
369
286
  */
370
- function parseShapeProperties(
371
- style,
372
- builder,
373
- uniforms,
374
- vertContext,
375
- fragContext,
376
- ) {
377
- fragContext.functions['round'] = `float round(float v) {
287
+ function parseShapeProperties(style, builder, uniforms, context) {
288
+ context.functions['round'] = `float round(float v) {
378
289
  return sign(v) * floor(abs(v) + 0.5);
379
290
  }`;
380
291
 
381
292
  // these functions take in screen coordinates in pixels and returns the signed distance field
382
293
  // (0 on the boundary, negative inside the polygon, positive outside, values in pixels)
383
294
  // inspired by https://github.com/zranger1/PixelblazePatterns/blob/master/Toolkit/sdf2d.md#n-sided-regular-polygon
384
- fragContext.functions['starDistanceField'] =
295
+ context.functions['starDistanceField'] =
385
296
  `float starDistanceField(vec2 point, float numPoints, float radius, float radius2, float angle) {
386
297
  float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
387
298
  float c = cos(startAngle);
@@ -397,7 +308,7 @@ function parseShapeProperties(
397
308
  vec2 edgeNormal = vec2(radius2 * sin(alpha * 0.5), -radius2 * cos(alpha * 0.5) + radius);
398
309
  return dot(normalize(edgeNormal), tipToPoint);
399
310
  }`;
400
- fragContext.functions['regularDistanceField'] =
311
+ context.functions['regularDistanceField'] =
401
312
  `float regularDistanceField(vec2 point, float numPoints, float radius, float angle) {
402
313
  float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
403
314
  float c = cos(startAngle);
@@ -413,36 +324,32 @@ function parseShapeProperties(
413
324
  return inSector.x - radiusIn;
414
325
  }`;
415
326
 
416
- parseCommonSymbolProperties(style, builder, vertContext, 'shape-');
327
+ parseCommonSymbolProperties(style, builder, context, 'shape-');
417
328
 
418
329
  // OPACITY
419
330
  let opacity = null;
420
331
  if ('shape-opacity' in style) {
421
- opacity = expressionToGlsl(fragContext, style['shape-opacity'], NumberType);
332
+ opacity = expressionToGlsl(context, style['shape-opacity'], NumberType);
422
333
  }
423
334
 
424
335
  // SCALE
425
336
  let currentPoint = 'coordsPx';
426
337
  if ('shape-scale' in style) {
427
- const scale = expressionToGlsl(fragContext, style['shape-scale'], SizeType);
338
+ const scale = expressionToGlsl(context, style['shape-scale'], SizeType);
428
339
  currentPoint = `coordsPx / ${scale}`;
429
340
  }
430
341
 
431
342
  // FILL COLOR
432
343
  let fillColor = null;
433
344
  if ('shape-fill-color' in style) {
434
- fillColor = expressionToGlsl(
435
- fragContext,
436
- style['shape-fill-color'],
437
- ColorType,
438
- );
345
+ fillColor = expressionToGlsl(context, style['shape-fill-color'], ColorType);
439
346
  }
440
347
 
441
348
  // STROKE COLOR
442
349
  let strokeColor = null;
443
350
  if ('shape-stroke-color' in style) {
444
351
  strokeColor = expressionToGlsl(
445
- fragContext,
352
+ context,
446
353
  style['shape-stroke-color'],
447
354
  ColorType,
448
355
  );
@@ -452,7 +359,7 @@ function parseShapeProperties(
452
359
  let strokeWidth = null;
453
360
  if ('shape-stroke-width' in style) {
454
361
  strokeWidth = expressionToGlsl(
455
- fragContext,
362
+ context,
456
363
  style['shape-stroke-width'],
457
364
  NumberType,
458
365
  );
@@ -460,25 +367,21 @@ function parseShapeProperties(
460
367
 
461
368
  // SHAPE TYPE
462
369
  const numPoints = expressionToGlsl(
463
- fragContext,
370
+ context,
464
371
  style['shape-points'],
465
372
  NumberType,
466
373
  );
467
374
  let angle = '0.';
468
375
  if ('shape-angle' in style) {
469
- angle = expressionToGlsl(fragContext, style['shape-angle'], NumberType);
376
+ angle = expressionToGlsl(context, style['shape-angle'], NumberType);
470
377
  }
471
378
  let shapeField;
472
- let radius = expressionToGlsl(fragContext, style['shape-radius'], NumberType);
379
+ let radius = expressionToGlsl(context, style['shape-radius'], NumberType);
473
380
  if (strokeWidth !== null) {
474
381
  radius = `${radius} + ${strokeWidth} * 0.5`;
475
382
  }
476
383
  if ('shape-radius2' in style) {
477
- let radius2 = expressionToGlsl(
478
- fragContext,
479
- style['shape-radius2'],
480
- NumberType,
481
- );
384
+ let radius2 = expressionToGlsl(context, style['shape-radius2'], NumberType);
482
385
  if (strokeWidth !== null) {
483
386
  radius2 = `${radius2} + ${strokeWidth} * 0.5`;
484
387
  }
@@ -499,29 +402,22 @@ function parseShapeProperties(
499
402
  }
500
403
 
501
404
  /**
502
- * @param {import("../style/flat.js").FlatStyle} style Style
405
+ * @param {import("../../style/flat.js").FlatStyle} style Style
503
406
  * @param {ShaderBuilder} builder Shader builder
504
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
505
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
506
- * @param {import("../expr/gpu.js").CompilationContext} fragContext Fragment shader compilation context
407
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
408
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context
507
409
  */
508
- function parseIconProperties(
509
- style,
510
- builder,
511
- uniforms,
512
- vertContext,
513
- fragContext,
514
- ) {
410
+ function parseIconProperties(style, builder, uniforms, context) {
515
411
  // COLOR
516
412
  let color = 'vec4(1.0)';
517
413
  if ('icon-color' in style) {
518
- color = expressionToGlsl(fragContext, style['icon-color'], ColorType);
414
+ color = expressionToGlsl(context, style['icon-color'], ColorType);
519
415
  }
520
416
 
521
417
  // OPACITY
522
418
  if ('icon-opacity' in style) {
523
419
  color = `${color} * vec4(1.0, 1.0, 1.0, ${expressionToGlsl(
524
- fragContext,
420
+ context,
525
421
  style['icon-opacity'],
526
422
  NumberType,
527
423
  )})`;
@@ -546,17 +442,17 @@ function parseIconProperties(
546
442
  if ('icon-width' in style && 'icon-height' in style) {
547
443
  builder.setSymbolSizeExpression(
548
444
  `vec2(${expressionToGlsl(
549
- vertContext,
445
+ context,
550
446
  style['icon-width'],
551
447
  NumberType,
552
- )}, ${expressionToGlsl(vertContext, style['icon-height'], NumberType)})`,
448
+ )}, ${expressionToGlsl(context, style['icon-height'], NumberType)})`,
553
449
  );
554
450
  }
555
451
 
556
452
  // tex coord
557
453
  if ('icon-offset' in style && 'icon-size' in style) {
558
454
  const sampleSize = expressionToGlsl(
559
- vertContext,
455
+ context,
560
456
  style['icon-size'],
561
457
  NumberArrayType,
562
458
  );
@@ -565,7 +461,7 @@ function parseIconProperties(
565
461
  const offset = parseImageOffsetProperties(
566
462
  style,
567
463
  'icon-',
568
- vertContext,
464
+ context,
569
465
  'v_quadSizePx',
570
466
  sampleSize,
571
467
  );
@@ -574,17 +470,17 @@ function parseIconProperties(
574
470
  );
575
471
  }
576
472
 
577
- parseCommonSymbolProperties(style, builder, vertContext, 'icon-');
473
+ parseCommonSymbolProperties(style, builder, context, 'icon-');
578
474
 
579
475
  if ('icon-anchor' in style) {
580
476
  const anchor = expressionToGlsl(
581
- vertContext,
477
+ context,
582
478
  style['icon-anchor'],
583
479
  NumberArrayType,
584
480
  );
585
481
  let scale = `1.0`;
586
482
  if (`icon-scale` in style) {
587
- scale = expressionToGlsl(vertContext, style[`icon-scale`], SizeType);
483
+ scale = expressionToGlsl(context, style[`icon-scale`], SizeType);
588
484
  }
589
485
  let shiftPx;
590
486
  if (
@@ -622,22 +518,15 @@ function parseIconProperties(
622
518
  }
623
519
 
624
520
  /**
625
- * @param {import("../style/flat.js").FlatStyle} style Style
521
+ * @param {import("../../style/flat.js").FlatStyle} style Style
626
522
  * @param {ShaderBuilder} builder Shader Builder
627
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
628
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
629
- * @param {import("../expr/gpu.js").CompilationContext} fragContext Fragment shader compilation context
523
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
524
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context
630
525
  */
631
- function parseStrokeProperties(
632
- style,
633
- builder,
634
- uniforms,
635
- vertContext,
636
- fragContext,
637
- ) {
526
+ function parseStrokeProperties(style, builder, uniforms, context) {
638
527
  if ('stroke-color' in style) {
639
528
  builder.setStrokeColorExpression(
640
- expressionToGlsl(fragContext, style['stroke-color'], ColorType),
529
+ expressionToGlsl(context, style['stroke-color'], ColorType),
641
530
  );
642
531
  }
643
532
  if ('stroke-pattern-src' in style) {
@@ -653,14 +542,14 @@ function parseStrokeProperties(
653
542
  let offsetExpression = 'vec2(0.)';
654
543
  if ('stroke-pattern-offset' in style && 'stroke-pattern-size' in style) {
655
544
  sampleSizeExpression = expressionToGlsl(
656
- fragContext,
545
+ context,
657
546
  style[`stroke-pattern-size`],
658
547
  NumberArrayType,
659
548
  );
660
549
  offsetExpression = parseImageOffsetProperties(
661
550
  style,
662
551
  'stroke-pattern-',
663
- fragContext,
552
+ context,
664
553
  sizeExpression,
665
554
  sampleSizeExpression,
666
555
  );
@@ -668,12 +557,12 @@ function parseStrokeProperties(
668
557
  let spacingExpression = '0.';
669
558
  if ('stroke-pattern-spacing' in style) {
670
559
  spacingExpression = expressionToGlsl(
671
- fragContext,
560
+ context,
672
561
  style['stroke-pattern-spacing'],
673
562
  NumberType,
674
563
  );
675
564
  }
676
- fragContext.functions['sampleStrokePattern'] =
565
+ context.functions['sampleStrokePattern'] =
677
566
  `vec4 sampleStrokePattern(sampler2D texture, vec2 textureSize, vec2 textureOffset, vec2 sampleSize, float spacingPx, float currentLengthPx, float currentRadiusRatio, float lineWidth) {
678
567
  float currentLengthScaled = currentLengthPx * sampleSize.y / lineWidth;
679
568
  float spacingScaled = spacingPx * sampleSize.y / lineWidth;
@@ -696,36 +585,36 @@ function parseStrokeProperties(
696
585
 
697
586
  if ('stroke-width' in style) {
698
587
  builder.setStrokeWidthExpression(
699
- expressionToGlsl(vertContext, style['stroke-width'], NumberType),
588
+ expressionToGlsl(context, style['stroke-width'], NumberType),
700
589
  );
701
590
  }
702
591
 
703
592
  if ('stroke-offset' in style) {
704
593
  builder.setStrokeOffsetExpression(
705
- expressionToGlsl(vertContext, style['stroke-offset'], NumberType),
594
+ expressionToGlsl(context, style['stroke-offset'], NumberType),
706
595
  );
707
596
  }
708
597
 
709
598
  if ('stroke-line-cap' in style) {
710
599
  builder.setStrokeCapExpression(
711
- expressionToGlsl(vertContext, style['stroke-line-cap'], StringType),
600
+ expressionToGlsl(context, style['stroke-line-cap'], StringType),
712
601
  );
713
602
  }
714
603
 
715
604
  if ('stroke-line-join' in style) {
716
605
  builder.setStrokeJoinExpression(
717
- expressionToGlsl(vertContext, style['stroke-line-join'], StringType),
606
+ expressionToGlsl(context, style['stroke-line-join'], StringType),
718
607
  );
719
608
  }
720
609
 
721
610
  if ('stroke-miter-limit' in style) {
722
611
  builder.setStrokeMiterLimitExpression(
723
- expressionToGlsl(vertContext, style['stroke-miter-limit'], NumberType),
612
+ expressionToGlsl(context, style['stroke-miter-limit'], NumberType),
724
613
  );
725
614
  }
726
615
 
727
616
  if ('stroke-line-dash' in style) {
728
- fragContext.functions['getSingleDashDistance'] =
617
+ context.functions['getSingleDashDistance'] =
729
618
  `float getSingleDashDistance(float distance, float radius, float dashOffset, float dashLength, float dashLengthTotal, float capType) {
730
619
  float localDistance = mod(distance, dashLengthTotal);
731
620
  float distanceSegment = abs(localDistance - dashOffset - dashLength * 0.5) - dashLength * 0.5;
@@ -739,7 +628,7 @@ function parseStrokeProperties(
739
628
  }`;
740
629
 
741
630
  let dashPattern = style['stroke-line-dash'].map((v) =>
742
- expressionToGlsl(fragContext, v, NumberType),
631
+ expressionToGlsl(context, v, NumberType),
743
632
  );
744
633
  // if pattern has odd length, concatenate it with itself to be even
745
634
  if (dashPattern.length % 2 === 1) {
@@ -749,7 +638,7 @@ function parseStrokeProperties(
749
638
  let offsetExpression = '0.';
750
639
  if ('stroke-line-dash-offset' in style) {
751
640
  offsetExpression = expressionToGlsl(
752
- vertContext,
641
+ context,
753
642
  style['stroke-line-dash-offset'],
754
643
  NumberType,
755
644
  );
@@ -774,7 +663,7 @@ function parseStrokeProperties(
774
663
  distanceExpression = `min(${distanceExpression}, getSingleDashDistance(distance, radius, ${currentDashOffset}, dashLength${i}, totalDashLength, capType))`;
775
664
  }
776
665
 
777
- fragContext.functions[dashFunctionName] =
666
+ context.functions[dashFunctionName] =
778
667
  `float ${dashFunctionName}(float distance, float radius, float capType) {
779
668
  ${dashLengthsDef.join('\n ')}
780
669
  float totalDashLength = ${totalLengthDef};
@@ -787,22 +676,15 @@ function parseStrokeProperties(
787
676
  }
788
677
 
789
678
  /**
790
- * @param {import("../style/flat.js").FlatStyle} style Style
679
+ * @param {import("../../style/flat.js").FlatStyle} style Style
791
680
  * @param {ShaderBuilder} builder Shader Builder
792
- * @param {Object<string,import("../webgl/Helper").UniformValue>} uniforms Uniforms
793
- * @param {import("../expr/gpu.js").CompilationContext} vertContext Vertex shader compilation context
794
- * @param {import("../expr/gpu.js").CompilationContext} fragContext Fragment shader compilation context
681
+ * @param {Object<string,import("../../webgl/Helper").UniformValue>} uniforms Uniforms
682
+ * @param {import("../../expr/gpu.js").CompilationContext} context Shader compilation context
795
683
  */
796
- function parseFillProperties(
797
- style,
798
- builder,
799
- uniforms,
800
- vertContext,
801
- fragContext,
802
- ) {
684
+ function parseFillProperties(style, builder, uniforms, context) {
803
685
  if ('fill-color' in style) {
804
686
  builder.setFillColorExpression(
805
- expressionToGlsl(fragContext, style['fill-color'], ColorType),
687
+ expressionToGlsl(context, style['fill-color'], ColorType),
806
688
  );
807
689
  }
808
690
  if ('fill-pattern-src' in style) {
@@ -818,19 +700,19 @@ function parseFillProperties(
818
700
  let offsetExpression = 'vec2(0.)';
819
701
  if ('fill-pattern-offset' in style && 'fill-pattern-size' in style) {
820
702
  sampleSizeExpression = expressionToGlsl(
821
- fragContext,
703
+ context,
822
704
  style[`fill-pattern-size`],
823
705
  NumberArrayType,
824
706
  );
825
707
  offsetExpression = parseImageOffsetProperties(
826
708
  style,
827
709
  'fill-pattern-',
828
- fragContext,
710
+ context,
829
711
  sizeExpression,
830
712
  sampleSizeExpression,
831
713
  );
832
714
  }
833
- fragContext.functions['sampleFillPattern'] =
715
+ context.functions['sampleFillPattern'] =
834
716
  `vec4 sampleFillPattern(sampler2D texture, vec2 textureSize, vec2 textureOffset, vec2 sampleSize, vec2 pxOrigin, vec2 pxPosition) {
835
717
  float scaleRatio = pow(2., mod(u_zoom + 0.5, 1.) - 0.5);
836
718
  vec2 pxRelativePos = pxPosition - pxOrigin;
@@ -857,160 +739,62 @@ function parseFillProperties(
857
739
  /**
858
740
  * @typedef {Object} StyleParseResult
859
741
  * @property {ShaderBuilder} builder Shader builder pre-configured according to a given style
860
- * @property {import("../render/webgl/VectorStyleRenderer.js").UniformDefinitions} uniforms Uniform definitions
861
- * @property {import("../render/webgl/VectorStyleRenderer.js").AttributeDefinitions} attributes Attribute definitions
742
+ * @property {import("./VectorStyleRenderer.js").UniformDefinitions} uniforms Uniform definitions
743
+ * @property {import("./VectorStyleRenderer.js").AttributeDefinitions} attributes Attribute definitions
862
744
  */
863
745
 
864
746
  /**
865
- * Parses a {@link import("../style/flat.js").FlatStyle} object and returns a {@link ShaderBuilder}
747
+ * Parses a {@link import("../../style/flat.js").FlatStyle} object and returns a {@link ShaderBuilder}
866
748
  * object that has been configured according to the given style, as well as `attributes` and `uniforms`
867
749
  * arrays to be fed to the `WebGLPointsRenderer` class.
868
750
  *
869
751
  * Also returns `uniforms` and `attributes` properties as expected by the
870
752
  * {@link module:ol/renderer/webgl/PointsLayer~WebGLPointsLayerRenderer}.
871
753
  *
872
- * @param {import("../style/flat.js").FlatStyle} style Flat style.
873
- * @param {import('../style/flat.js').StyleVariables} [variables] Style variables.
874
- * @param {import("../expr/expression.js").EncodedExpression} [filter] Filter (if any)
754
+ * @param {import("../../style/flat.js").FlatStyle} style Flat style.
755
+ * @param {import('../../style/flat.js').StyleVariables} [variables] Style variables.
756
+ * @param {import("../../expr/expression.js").EncodedExpression} [filter] Filter (if any)
875
757
  * @return {StyleParseResult} Result containing shader params, attributes and uniforms.
876
758
  */
877
759
  export function parseLiteralStyle(style, variables, filter) {
878
- const vertContext = newCompilationContext();
879
-
880
- /**
881
- * @type {import("../expr/gpu.js").CompilationContext}
882
- */
883
- const fragContext = {
884
- ...newCompilationContext(),
885
- inFragmentShader: true,
886
- variables: vertContext.variables,
887
- };
760
+ const context = newCompilationContext();
888
761
 
889
762
  const builder = new ShaderBuilder();
890
763
 
891
- /** @type {Object<string,import("../webgl/Helper").UniformValue>} */
764
+ /** @type {Object<string,import("../../webgl/Helper").UniformValue>} */
892
765
  const uniforms = {};
893
766
 
894
767
  if ('icon-src' in style) {
895
- parseIconProperties(style, builder, uniforms, vertContext, fragContext);
768
+ parseIconProperties(style, builder, uniforms, context);
896
769
  } else if ('shape-points' in style) {
897
- parseShapeProperties(style, builder, uniforms, vertContext, fragContext);
770
+ parseShapeProperties(style, builder, uniforms, context);
898
771
  } else if ('circle-radius' in style) {
899
- parseCircleProperties(style, builder, uniforms, vertContext, fragContext);
772
+ parseCircleProperties(style, builder, uniforms, context);
900
773
  }
901
- parseStrokeProperties(style, builder, uniforms, vertContext, fragContext);
902
- parseFillProperties(style, builder, uniforms, vertContext, fragContext);
774
+ parseStrokeProperties(style, builder, uniforms, context);
775
+ parseFillProperties(style, builder, uniforms, context);
903
776
 
904
777
  // note that the style filter may have already been applied earlier when building the rendering instructions
905
778
  // this is still needed in case a filter cannot be evaluated statically beforehand (e.g. depending on time)
906
779
  if (filter) {
907
- const parsedFilter = expressionToGlsl(fragContext, filter, BooleanType);
780
+ const parsedFilter = expressionToGlsl(context, filter, BooleanType);
908
781
  builder.setFragmentDiscardExpression(`!${parsedFilter}`);
909
782
  }
910
783
 
911
- // define one uniform per variable
912
- for (const varName in fragContext.variables) {
913
- const variable = fragContext.variables[varName];
914
- const uniformName = uniformNameForVariable(variable.name);
915
- let glslType = getGlslTypeFromType(variable.type);
916
- if (variable.type === ColorType) {
917
- // we're not packing colors when they're passed as uniforms
918
- glslType = 'vec4';
919
- }
920
- builder.addUniform(`${glslType} ${uniformName}`);
921
-
922
- uniforms[uniformName] = () => {
923
- const value = variables[variable.name];
924
- if (typeof value === 'number') {
925
- return value;
926
- }
927
- if (typeof value === 'boolean') {
928
- return value ? 1 : 0;
929
- }
930
- if (variable.type === ColorType) {
931
- return asArray(value || '#eee');
932
- }
933
- if (typeof value === 'string') {
934
- return getStringNumberEquivalent(value);
935
- }
936
- return value;
937
- };
938
- }
939
-
940
- // for each feature attribute used in the fragment shader, define a varying that will be used to pass data
941
- // from the vertex to the fragment shader, as well as an attribute in the vertex shader (if not already present)
942
- for (const propName in fragContext.properties) {
943
- const property = fragContext.properties[propName];
944
- if (!vertContext.properties[propName]) {
945
- vertContext.properties[propName] = property;
946
- }
947
- let type = getGlslTypeFromType(property.type);
948
- let expression = `a_prop_${property.name}`;
949
- if (property.type === ColorType) {
950
- type = 'vec4';
951
- expression = `unpackColor(${expression})`;
952
- builder.addVertexShaderFunction(UNPACK_COLOR_FN);
953
- }
954
- builder.addVarying(`v_prop_${property.name}`, type, expression);
955
- }
956
-
957
- // for each feature attribute used in the vertex shader, define an attribute in the vertex shader.
958
- for (const propName in vertContext.properties) {
959
- const property = vertContext.properties[propName];
960
- builder.addAttribute(
961
- `${getGlslTypeFromType(property.type)} a_prop_${property.name}`,
962
- );
963
- }
964
-
965
- // add functions that were collected in the compilation contexts
966
- for (const functionName in vertContext.functions) {
967
- builder.addVertexShaderFunction(vertContext.functions[functionName]);
968
- }
969
- for (const functionName in fragContext.functions) {
970
- builder.addFragmentShaderFunction(fragContext.functions[functionName]);
971
- }
972
-
973
784
  /**
974
- * @type {import('../render/webgl/VectorStyleRenderer.js').AttributeDefinitions}
785
+ * @type {import('./VectorStyleRenderer.js').AttributeDefinitions}
975
786
  */
976
787
  const attributes = {};
977
788
 
978
- // Define attributes with their callback for each property used in the vertex shader
979
- for (const propName in vertContext.properties) {
980
- const property = vertContext.properties[propName];
981
- const callback = (feature) => {
982
- const value = feature.get(property.name);
983
- if (property.type === ColorType) {
984
- return packColor([...asArray(value || '#eee')]);
985
- }
986
- if (typeof value === 'string') {
987
- return getStringNumberEquivalent(value);
988
- }
989
- if (typeof value === 'boolean') {
990
- return value ? 1 : 0;
991
- }
992
- return value;
993
- };
994
-
995
- attributes[`prop_${property.name}`] = {
996
- size: getGlslSizeFromType(property.type),
997
- callback,
998
- };
999
- }
1000
-
1001
789
  // Define attributes for special inputs
1002
790
  function defineSpecialInput(contextPropName, glslPropName, type, callback) {
1003
- const inVertContext = vertContext[contextPropName];
1004
- const inFragContext = fragContext[contextPropName];
1005
- if (!inVertContext && !inFragContext) {
791
+ if (!context[contextPropName]) {
1006
792
  return;
1007
793
  }
1008
794
  const glslType = getGlslTypeFromType(type);
1009
795
  const attrSize = getGlslSizeFromType(type);
1010
- builder.addAttribute(`${glslType} a_${glslPropName}`);
1011
- if (inFragContext) {
1012
- builder.addVarying(`v_${glslPropName}`, glslType, `a_${glslPropName}`);
1013
- }
796
+ builder.addAttribute(`a_${glslPropName}`, glslType);
797
+
1014
798
  attributes[glslPropName] = {
1015
799
  size: attrSize,
1016
800
  callback,
@@ -1033,5 +817,86 @@ export function parseLiteralStyle(style, variables, filter) {
1033
817
  },
1034
818
  );
1035
819
 
1036
- return {builder, attributes, uniforms};
820
+ applyContextToBuilder(builder, context);
821
+
822
+ return {
823
+ builder,
824
+ attributes: {...attributes, ...generateAttributesFromContext(context)},
825
+ uniforms: {
826
+ ...uniforms,
827
+ ...generateUniformsFromContext(context, variables),
828
+ },
829
+ };
830
+ }
831
+
832
+ /**
833
+ * @typedef {import('./VectorStyleRenderer.js').AsShaders} StyleAsShaders
834
+ */
835
+ /**
836
+ * @typedef {import('./VectorStyleRenderer.js').AsRule} StyleAsRule
837
+ */
838
+
839
+ /**
840
+ * Takes in either a Flat Style or an array of shaders (used as input for the webgl vector layer classes)
841
+ * and breaks it down into separate styles to be used by the VectorStyleRenderer class.
842
+ * @param {import('../../style/flat.js').FlatStyleLike | Array<StyleAsShaders> | StyleAsShaders} style Flat style or shaders
843
+ * @return {Array<StyleAsShaders | StyleAsRule>} Separate styles as shaders or rules with a single flat style and a filter
844
+ */
845
+ export function breakDownFlatStyle(style) {
846
+ // possible cases:
847
+ // - single shader
848
+ // - multiple shaders
849
+ // - single style
850
+ // - multiple styles
851
+ // - multiple rules
852
+ const asArray = Array.isArray(style) ? style : [style];
853
+
854
+ // if array of rules: break rules into separate styles, compute "else" filters
855
+ if ('style' in asArray[0]) {
856
+ /** @type {Array<StyleAsRule>} */
857
+ const styles = [];
858
+ const rules = /** @type {Array<import('../../style/flat.js').Rule>} */ (
859
+ asArray
860
+ );
861
+ const previousFilters = [];
862
+ for (const rule of rules) {
863
+ const ruleStyles = Array.isArray(rule.style) ? rule.style : [rule.style];
864
+ /** @type {import("../../expr/expression.js").EncodedExpression} */
865
+ let currentFilter = rule.filter;
866
+ if (rule.else && previousFilters.length) {
867
+ currentFilter = [
868
+ 'all',
869
+ ...previousFilters.map((filter) => ['!', filter]),
870
+ ];
871
+ if (rule.filter) {
872
+ currentFilter.push(rule.filter);
873
+ }
874
+ if (currentFilter.length < 3) {
875
+ currentFilter = currentFilter[1];
876
+ }
877
+ }
878
+ if (rule.filter) {
879
+ previousFilters.push(rule.filter);
880
+ }
881
+ /** @type {Array<StyleAsRule>} */
882
+ const stylesWithFilters = ruleStyles.map((style) => ({
883
+ style,
884
+ ...(currentFilter && {filter: currentFilter}),
885
+ }));
886
+ styles.push(...stylesWithFilters);
887
+ }
888
+ return styles;
889
+ }
890
+
891
+ // if array of shaders: return as is
892
+ if ('builder' in asArray[0]) {
893
+ return /** @type {Array<StyleAsShaders>} */ (asArray);
894
+ }
895
+
896
+ return asArray.map(
897
+ (style) =>
898
+ /** @type {StyleAsRule} */ ({
899
+ style,
900
+ }),
901
+ );
1037
902
  }