nanovgjs 0.1.0

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.
package/nanovg_gl.js ADDED
@@ -0,0 +1,1429 @@
1
+ const GLNVG_LOC_VIEWSIZE = 0;
2
+ const GLNVG_LOC_TEX = 1;
3
+ const GLNVG_LOC_FRAG = 2;
4
+ const GLNVG_LOC_INNECOL = 3;
5
+ const GLNVG_MAX_LOCS = 4;
6
+
7
+ const NVG_ANTIALIAS = 1 << 0;
8
+ const NVG_STENCIL_STROKES = 1 << 1;
9
+ const NVG_DEBUG = 1 << 2;
10
+ const NVG_IMAGE_NODELETE = 1 << 16;
11
+
12
+ const NANOVG_GL_USE_UNIFORMBUFFER = false;
13
+
14
+ const NANOVG_GL_USE_STATE_FILTER = true;
15
+
16
+ const GLNVG_NONE = 0;
17
+ const GLNVG_FILL = 1;
18
+ const GLNVG_CONVEXFILL = 2;
19
+ const GLNVG_STROKE = 3;
20
+ const GLNVG_TRIANGLES = 4;
21
+
22
+ const NANOVG_GL_UNIFORMARRAY_SIZE = 11;
23
+
24
+ const NSVG_SHADER_FILLGRAD = 0;
25
+ const NSVG_SHADER_FILLIMG = 1;
26
+ const NSVG_SHADER_SIMPLE = 2;
27
+ const NSVG_SHADER_IMG = 3;
28
+
29
+ const GLNVG_FRAG_BINDING = 0;
30
+
31
+ class GLNVGblend {
32
+ constructor() {
33
+ this.srcRGB = 0;
34
+ this.dstRGB = 0;
35
+ this.srcAlpha = 0;
36
+ this.dstAlpha = 0;
37
+ }
38
+ }
39
+
40
+ class GLNVGcall {
41
+ constructor() {
42
+ this.type = 0;
43
+ this.image = 0;
44
+ this.pathOffset = 0;
45
+ this.pathCount = 0;
46
+ this.triangleOffset = 0;
47
+ this.triangleCount = 0;
48
+ this.uniformOffset = 0;
49
+ this.blendFunc = new GLNVGblend();
50
+ }
51
+ }
52
+
53
+ class GLNVGpath {
54
+ constructor() {
55
+ this.fillOffset = 0;
56
+ this.fillCount = 0;
57
+ this.strokeOffset = 0;
58
+ this.strokeCount = 0;
59
+ }
60
+ }
61
+
62
+ const SIZEOF_FLOAT = 4;
63
+ const SIZEOF_INT = 4;
64
+
65
+ const FLOATS_PER_BYTE = 1 / Float32Array.BYTES_PER_ELEMENT;
66
+
67
+ class GLNVGfragUniforms {
68
+ constructor(buffer, byteOffset = 0) {
69
+ const floatOffset = byteOffset / Float32Array.BYTES_PER_ELEMENT;
70
+ const floatSize = 44; // 176 bytes / 4 = 44 floats total
71
+
72
+ if (buffer instanceof Float32Array) {
73
+ this.buffer = buffer.subarray(floatOffset, floatOffset + floatSize);
74
+ } else {
75
+ this.buffer = new Float32Array(buffer, byteOffset, floatSize);
76
+ }
77
+
78
+ this.offsets = {
79
+ scissorMat: 0, // 12 floats (mat3x4)
80
+ paintMat: 12, // 12 floats (mat3x4)
81
+ innerCol: 24, // 4 floats (vec4)
82
+ outerCol: 28, // 4 floats (vec4)
83
+ scissorExt: 32, // 2 floats (vec2)
84
+ scissorScale: 34, // 2 floats (vec2)
85
+ extent: 36, // 2 floats (vec2)
86
+ radius: 38, // 1 float
87
+ feather: 39, // 1 float
88
+ strokeMult: 40, // 1 float
89
+ strokeThr: 41, // 1 float
90
+ texType: 42, // 1 float/int
91
+ type: 43, // 1 float/int
92
+ };
93
+ }
94
+
95
+ get size() {
96
+ return 44 * 4; // 44 floats * 4 bytes = 176 bytes
97
+ }
98
+
99
+ set scissorMat(mat) {
100
+ if (mat && mat.length >= 12) {
101
+ this.buffer.set(mat.slice(0, 12), this.offsets.scissorMat);
102
+ }
103
+ }
104
+
105
+ set paintMat(mat) {
106
+ if (mat && mat.length >= 12) {
107
+ this.buffer.set(mat.slice(0, 12), this.offsets.paintMat);
108
+ }
109
+ }
110
+
111
+ set innerCol(color) {
112
+ this.buffer[this.offsets.innerCol] = color.r;
113
+ this.buffer[this.offsets.innerCol + 1] = color.g;
114
+ this.buffer[this.offsets.innerCol + 2] = color.b;
115
+ this.buffer[this.offsets.innerCol + 3] = color.a;
116
+ }
117
+
118
+ set outerCol(color) {
119
+ this.buffer[this.offsets.outerCol] = color.r;
120
+ this.buffer[this.offsets.outerCol + 1] = color.g;
121
+ this.buffer[this.offsets.outerCol + 2] = color.b;
122
+ this.buffer[this.offsets.outerCol + 3] = color.a;
123
+ }
124
+
125
+ set scissorExt(ext) {
126
+ this.buffer[this.offsets.scissorExt] = ext[0];
127
+ this.buffer[this.offsets.scissorExt + 1] = ext[1];
128
+ }
129
+
130
+ set scissorScale(scale) {
131
+ this.buffer[this.offsets.scissorScale] = scale[0];
132
+ this.buffer[this.offsets.scissorScale + 1] = scale[1];
133
+ }
134
+
135
+ set extent(extent) {
136
+ this.buffer[this.offsets.extent] = extent[0];
137
+ this.buffer[this.offsets.extent + 1] = extent[1];
138
+ }
139
+
140
+ set radius(value) {
141
+ this.buffer[this.offsets.radius] = value;
142
+ }
143
+
144
+ set feather(value) {
145
+ this.buffer[this.offsets.feather] = value;
146
+ }
147
+
148
+ set strokeMult(value) {
149
+ this.buffer[this.offsets.strokeMult] = value;
150
+ }
151
+
152
+ set strokeThr(value) {
153
+ this.buffer[this.offsets.strokeThr] = value;
154
+ }
155
+
156
+ set texType(value) {
157
+ this.buffer[this.offsets.texType] = value;
158
+ }
159
+
160
+ set type(value) {
161
+ this.buffer[this.offsets.type] = value;
162
+ }
163
+
164
+ get innerCol() {
165
+ return [
166
+ this.buffer[this.offsets.innerCol],
167
+ this.buffer[this.offsets.innerCol + 1],
168
+ this.buffer[this.offsets.innerCol + 2],
169
+ this.buffer[this.offsets.innerCol + 3]
170
+ ];
171
+ }
172
+
173
+ get outerCol() {
174
+ return [
175
+ this.buffer[this.offsets.outerCol],
176
+ this.buffer[this.offsets.outerCol + 1],
177
+ this.buffer[this.offsets.outerCol + 2],
178
+ this.buffer[this.offsets.outerCol + 3]
179
+ ];
180
+ }
181
+ }
182
+
183
+ class GLNVGshader {
184
+ constructor() {
185
+ this.prog = 0;
186
+ this.frag = 0;
187
+ this.vert = 0;
188
+ this.loc = new Array(GLNVG_MAX_LOCS).fill(0);
189
+ }
190
+ }
191
+
192
+ class GLNVGcontext {
193
+ constructor() {
194
+ this.shader = new GLNVGshader();
195
+ this.textures = null;
196
+ this.view = [0.0, 0.0];
197
+ this.ntextures = 0;
198
+ this.ctextures = 0;
199
+ this.textureId = 0;
200
+ this.vertBuf = null;
201
+ this.vertArr = null;
202
+ this.fragBuf = null;
203
+ this.fragSize = 0;
204
+ this.flags = 0;
205
+ this.calls = null;
206
+ this.ccalls = 0;
207
+ this.ncalls = 0;
208
+ this.paths = null;
209
+ this.cpaths = 0;
210
+ this.npaths = 0;
211
+ this.verts = null;
212
+ this.cverts = 0;
213
+ this.nverts = 0;
214
+ this.uniforms = null;
215
+ this.cuniforms = 0;
216
+ this.nuniforms = 0;
217
+
218
+ if(NANOVG_GL_USE_STATE_FILTER){
219
+ this.boundTexture = 0;
220
+ this.stencilMsk = 0;
221
+ this.stencilFnc = 0;
222
+ this.stencilFuncRef = 0;
223
+ this.stencilFuncMask = 0;
224
+ this.blendFunc = new GLNVGblend();
225
+ }
226
+ this.dummyTex = 0;
227
+ }
228
+ }
229
+
230
+ class GLNVGtexture {
231
+ constructor() {
232
+ this.id = 0;
233
+ this.tex = null;
234
+ this.width = 0;
235
+ this.height = 0;
236
+ this.type = 0;
237
+ this.flags = 0;
238
+ }
239
+ }
240
+
241
+ function glnvg__renderCreate(gl) {
242
+ let glnvgContext = new GLNVGcontext();
243
+
244
+ Object.assign(gl, glnvgContext);
245
+ gl.flags = (gl.edgeAntiAlias ? NVG_ANTIALIAS : 0) | NVG_STENCIL_STROKES;
246
+
247
+ var align = 4;
248
+
249
+ let shaderHeader =
250
+ "#version 100\n"
251
+ +((NANOVG_GL_USE_UNIFORMBUFFER) ? "#define USE_UNIFORMBUFFER 1\n" : "#define UNIFORMARRAY_SIZE 11\n" )
252
+ +((gl.edgeAntiAlias) ? "#define EDGE_AA 1" : "")
253
+ ;
254
+
255
+ const fillVertShader =
256
+ `precision mediump float;
257
+ uniform vec2 viewSize;
258
+ attribute vec2 vertex;
259
+ attribute vec2 tcoord;
260
+ varying vec2 ftcoord;
261
+ varying vec2 fpos;
262
+ void main(void) {
263
+ ftcoord = tcoord;
264
+ fpos = vertex;
265
+ gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);
266
+ }`;
267
+
268
+ const fillFragShader = `
269
+ #if defined(GL_FRAGMENT_PRECISION_HIGH)
270
+ precision highp float;
271
+ #else
272
+ precision mediump float;
273
+ #endif
274
+ uniform sampler2D tex;
275
+ varying vec2 ftcoord;
276
+ varying vec2 fpos;
277
+
278
+
279
+ #ifndef USE_UNIFORMBUFFER
280
+ uniform vec4 frag[UNIFORMARRAY_SIZE];
281
+ #define scissorMat mat3(frag[0].xyz, frag[1].xyz, frag[2].xyz)
282
+ #define paintMat mat3(frag[3].xyz, frag[4].xyz, frag[5].xyz)
283
+ #define innerCol frag[6]
284
+ #define outerCol frag[7]
285
+ #define scissorExt frag[8].xy
286
+ #define scissorScale frag[8].zw
287
+ #define extent frag[9].xy
288
+ #define radius frag[9].z
289
+ #define feather frag[9].w
290
+ #define strokeMult frag[10].x
291
+ #define strokeThr frag[10].y
292
+ #define texType int(frag[10].z)
293
+ #define type int(frag[10].w)
294
+ #else
295
+ uniform mat3 scissorMat;
296
+ uniform mat3 paintMat;
297
+ uniform vec4 innerCol;
298
+ uniform vec4 outerCol;
299
+ uniform vec2 scissorExt;
300
+ uniform vec2 scissorScale;
301
+ uniform vec2 extent;
302
+ uniform float radius;
303
+ uniform float feather;
304
+ uniform float strokeMult;
305
+ uniform float strokeThr;
306
+ uniform highp int texType;
307
+ uniform highp int type;
308
+ #endif
309
+
310
+ float sdroundrect(vec2 pt, vec2 ext, float rad) {
311
+ vec2 ext2 = ext - vec2(rad, rad);
312
+ vec2 d = abs(pt) - ext2;
313
+ return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - rad;
314
+ }
315
+
316
+ float scissorMask(vec2 p) {
317
+ vec2 sc = (abs((scissorMat * vec3(p, 1.0)).xy) - scissorExt);
318
+ sc = vec2(0.5, 0.5) - sc * scissorScale;
319
+ return clamp(sc.x, 0.0, 1.0) * clamp(sc.y, 0.0, 1.0);
320
+ }
321
+
322
+ #ifdef EDGE_AA
323
+ float strokeMask() {
324
+ return min(1.0, (1.0 - abs(ftcoord.x * 2.0 - 1.0)) * strokeMult) * min(1.0, ftcoord.y);
325
+ }
326
+ #endif
327
+
328
+ void main(void) {
329
+ vec4 result;
330
+ float scissor = scissorMask(fpos);
331
+
332
+ #ifdef EDGE_AA
333
+ float strokeAlpha = strokeMask();
334
+ if (strokeAlpha < strokeThr) discard;
335
+ #else
336
+ float strokeAlpha = 1.0;
337
+ #endif
338
+
339
+ if (type == 0) {
340
+ vec2 pt = (paintMat * vec3(fpos, 1.0)).xy;
341
+ float d = clamp((sdroundrect(pt, extent, radius) + feather * 0.5) / feather, 0.0, 1.0);
342
+ vec4 color = mix(innerCol, outerCol, d);
343
+ color *= strokeAlpha * scissor;
344
+ result = color;
345
+ // DEBUG: Show gradient parameter
346
+ //result = vec4(d, d, d, 1.0); // Shows gradient interpolation
347
+ //result = vec4(innerCol.rgb, 1.0); // Shows inner color
348
+ //result = vec4(outerCol.rgb, 1.0); // Shows outer color
349
+ } else if (type == 1) {
350
+ vec2 pt = (paintMat * vec3(fpos, 1.0)).xy / extent;
351
+ vec4 color = texture2D(tex, pt);
352
+ if (texType == 1) color = vec4(color.xyz * color.w, color.w);
353
+ if (texType == 2) color = vec4(color.x);
354
+ color *= innerCol;
355
+ color *= strokeAlpha * scissor;
356
+ result = color;
357
+ } else if (type == 2) {
358
+ result = innerCol * strokeAlpha * scissor;
359
+ } else if (type == 3) {
360
+ vec4 color = texture2D(tex, ftcoord);
361
+ if (texType == 1) color = vec4(color.xyz * color.w, color.w);
362
+ if (texType == 2) color = vec4(color.x);
363
+ color *= scissor;
364
+ result = color * innerCol;
365
+ }
366
+
367
+ gl_FragColor = result;
368
+ }
369
+ `;
370
+
371
+ glnvg__checkError(gl, "init");
372
+
373
+ if (glnvg__createShader(gl, "shader", shaderHeader, null, fillVertShader, fillFragShader) == 0) return 0;
374
+
375
+ glnvg__checkError(gl, "uniform locations");
376
+ glnvg__getUniforms(gl, gl.shader);
377
+
378
+ gl.vertBuf = gl.createBuffer();
379
+
380
+ if (NANOVG_GL_USE_UNIFORMBUFFER) {
381
+ gl.uniformBlockBinding(gl.shader.prog, gl.shader.loc[GLNVG_LOC_FRAG], GLNVG_FRAG_BINDING);
382
+ gl.fragBuf = gl.createBuffer();
383
+ gl.bindBuffer(gl.UNIFORM_BUFFER, gl.fragBuf);
384
+ align = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
385
+ }
386
+ let fragUniforms = new GLNVGfragUniforms();
387
+ gl.fragSize = fragUniforms.size + align - fragUniforms.size % align;
388
+ gl.dummyTex = glnvg__renderCreateTexture(gl, NVG_TEXTURE_ALPHA, 1, 1, 0, null);
389
+
390
+ glnvg__checkError(gl, "create done");
391
+
392
+ gl.flush();
393
+
394
+ return 1;
395
+ }
396
+
397
+ function glnvg__checkError(gl, str) {
398
+ if ((gl.flags & NVG_DEBUG) === 0) return;
399
+ const err = gl.getError();
400
+ if (err !== gl.NO_ERROR) {
401
+ console.log(`Error ${err.toString(16)} after ${str}`);
402
+ return;
403
+ }
404
+ }
405
+
406
+ function glnvg__createShader(gl, name, header, opts, vshader, fshader) {
407
+ let status;
408
+ let prog, vert, frag;
409
+ const str = [];
410
+ str[0] = header;
411
+ str[1] = opts !== null ? opts : '';
412
+
413
+ prog = gl.createProgram();
414
+ vert = gl.createShader(gl.VERTEX_SHADER);
415
+ frag = gl.createShader(gl.FRAGMENT_SHADER);
416
+ str[2] = vshader;
417
+ gl.shaderSource(vert, str.join('\n'));
418
+ str[2] = fshader;
419
+ gl.shaderSource(frag, str.join('\n'));
420
+
421
+ gl.compileShader(vert);
422
+ status = gl.getShaderParameter(vert, gl.COMPILE_STATUS);
423
+ if (!status) {
424
+ console.log("could not compile shader:" + gl.getShaderInfoLog(vert));
425
+ glnvg__dumpShaderError(gl, vert, name, 'vert');
426
+ return 0;
427
+ }
428
+
429
+ gl.compileShader(frag);
430
+ status = gl.getShaderParameter(frag, gl.COMPILE_STATUS);
431
+ if (!status) {
432
+ console.log("could not compile shader:" + gl.getShaderInfoLog(frag));
433
+ glnvg__dumpShaderError(gl, frag, name, 'frag');
434
+ return 0;
435
+ }
436
+
437
+ gl.attachShader(prog, vert);
438
+ gl.attachShader(prog, frag);
439
+
440
+ gl.bindAttribLocation(prog, 0, 'vertex');
441
+ gl.bindAttribLocation(prog, 1, 'tcoord');
442
+
443
+ gl.linkProgram(prog);
444
+ status = gl.getProgramParameter(prog, gl.LINK_STATUS);
445
+ if (!status) {
446
+ glnvg__dumpProgramError(gl, prog, name);
447
+ return 0;
448
+ }
449
+
450
+ gl.shader.prog = prog;
451
+ gl.shader.vert = vert;
452
+ gl.shader.frag = frag;
453
+
454
+ return 1;
455
+ }
456
+
457
+ function glnvg__renderUpdateTexture(gl, image, x, y, w, h, data) {
458
+ const tex = glnvg__findTexture(gl, image);
459
+ if (!tex) return 0;
460
+
461
+ glnvg__bindTexture(gl, tex.tex);
462
+
463
+ const isWebGL2 = gl.getParameter(gl.VERSION).indexOf('WebGL 2') !== -1;
464
+
465
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, tex.type === NVG_TEXTURE_RGBA ? 4 : 1);
466
+
467
+ let uploadData = data;
468
+ if (!isWebGL2) {
469
+ if (x !== 0 || y !== 0) {
470
+ console.warn('Partial texture updates not supported in WebGL1 without extensions.');
471
+ return 0;
472
+ }
473
+ } else {
474
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, tex.width);
475
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, x);
476
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, y);
477
+ }
478
+
479
+ const format = tex.type === NVG_TEXTURE_RGBA ? gl.RGBA : gl.LUMINANCE;
480
+ const subX = isWebGL2 ? 0 : x;
481
+ const subY = isWebGL2 ? 0 : y;
482
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, subX, subY, w, h, format, gl.UNSIGNED_BYTE, uploadData);
483
+
484
+ if (isWebGL2) {
485
+ gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);
486
+ gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
487
+ gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
488
+ }
489
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
490
+
491
+ return 1;
492
+ }
493
+
494
+ function glnvg__renderCreateTexture(gl, type, w, h, imageFlags, data) {
495
+ var tex = glnvg__allocTexture(gl);
496
+
497
+ if (tex === null) return 0;
498
+
499
+ if (glnvg__nearestPow2(w) !== w || glnvg__nearestPow2(h) !== h) {
500
+ if ((imageFlags & NVG_IMAGE_REPEATX) !== 0 || (imageFlags & NVG_IMAGE_REPEATY) !== 0) {
501
+ console.log("Repeat X/Y is not supported for non power-of-two textures (" + w + " x " + h + ")");
502
+ imageFlags &= ~(NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
503
+ }
504
+ if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
505
+ console.log("Mip-maps is not support for non power-of-two textures (" + w + " x " + h + ")");
506
+ imageFlags &= ~NVG_IMAGE_GENERATE_MIPMAPS;
507
+ }
508
+ }
509
+
510
+ var texId = gl.createTexture();
511
+ tex.tex = texId;
512
+ tex.width = w;
513
+ tex.height = h;
514
+ tex.type = type;
515
+ tex.flags = imageFlags;
516
+ glnvg__bindTexture(gl, tex.tex);
517
+
518
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
519
+
520
+ const isWebGL2 = gl.getParameter(gl.VERSION).indexOf('WebGL 2') !== -1;
521
+ const format = type === NVG_TEXTURE_RGBA ? gl.RGBA : (isWebGL2 ? gl.RED : gl.LUMINANCE);
522
+ const isElementSource =
523
+ typeof ImageBitmap !== "undefined" && data instanceof ImageBitmap ||
524
+ typeof HTMLImageElement !== "undefined" && data instanceof HTMLImageElement ||
525
+ typeof HTMLCanvasElement !== "undefined" && data instanceof HTMLCanvasElement ||
526
+ typeof ImageData !== "undefined" && data instanceof ImageData;
527
+
528
+ if (isElementSource) {
529
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, format, gl.UNSIGNED_BYTE, data);
530
+ } else {
531
+ gl.texImage2D(gl.TEXTURE_2D, 0, format, w, h, 0, format, gl.UNSIGNED_BYTE, data);
532
+ }
533
+
534
+ if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
535
+ if (imageFlags & NVG_IMAGE_NEAREST) {
536
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
537
+ } else {
538
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
539
+ }
540
+ } else {
541
+ if (imageFlags & NVG_IMAGE_NEAREST) {
542
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
543
+ } else {
544
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
545
+ }
546
+ }
547
+
548
+ if (imageFlags & NVG_IMAGE_NEAREST) {
549
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
550
+ } else {
551
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
552
+ }
553
+
554
+ if (imageFlags & NVG_IMAGE_REPEATX)
555
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
556
+ else
557
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
558
+
559
+ if (imageFlags & NVG_IMAGE_REPEATY)
560
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
561
+ else
562
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
563
+
564
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
565
+
566
+ if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) {
567
+ gl.generateMipmap(gl.TEXTURE_2D);
568
+ }
569
+
570
+ glnvg__checkError(gl, "create tex");
571
+ glnvg__bindTexture(gl, null);
572
+
573
+ return tex.id;
574
+ }
575
+
576
+ function glnvg__renderStroke(gl, paint, compositeOperation, scissor, fringe, strokeWidth, paths, npaths) {
577
+ let call = glnvg__allocCall(gl);
578
+ if (call === null) return;
579
+
580
+ call.type = GLNVG_STROKE;
581
+ call.pathOffset = glnvg__allocPaths(gl, npaths);
582
+ if (call.pathOffset === -1) gotoError();
583
+ call.pathCount = npaths;
584
+ call.image = paint.image;
585
+ call.blendFunc = glnvg__blendCompositeOperation(compositeOperation);
586
+
587
+ let maxverts = glnvg__maxVertCount(paths, npaths);
588
+ let offset = glnvg__allocVerts(gl, maxverts);
589
+ if (offset === -1) gotoError();
590
+
591
+ for (let i = 0; i < npaths; i++) {
592
+ let copy = gl.paths[call.pathOffset + i];
593
+ let path = paths[i];
594
+ copy.fillOffset = 0;
595
+ copy.fillCount = 0;
596
+ copy.strokeOffset = 0;
597
+ copy.strokeCount = 0;
598
+
599
+ if (path.nstroke > 0) {
600
+ copy.strokeOffset = offset;
601
+ copy.strokeCount = path.nstroke;
602
+
603
+ let destView = new Float32Array(gl.verts, offset * NVG_VERTEX_SIZEOF, path.nstroke * 4);
604
+ destView.set(path.stroke);
605
+ offset += path.nstroke;
606
+ }
607
+ }
608
+
609
+ if (gl.flags & NVG_STENCIL_STROKES) {
610
+ call.uniformOffset = glnvg__allocFragUniforms(gl, 2);
611
+ if (call.uniformOffset === -1) gotoError();
612
+
613
+ glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call.uniformOffset), paint, scissor, strokeWidth, fringe, -1.0);
614
+ glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call.uniformOffset + gl.fragSize), paint, scissor, strokeWidth, fringe, 1.0 - 0.5 / 255.0);
615
+ } else {
616
+ call.uniformOffset = glnvg__allocFragUniforms(gl, 1);
617
+ if (call.uniformOffset === -1) gotoError();
618
+
619
+ glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call.uniformOffset), paint, scissor, strokeWidth, fringe, -1.0);
620
+ }
621
+
622
+ return;
623
+
624
+ function gotoError() {
625
+ if (gl.ncalls > 0) gl.ncalls--;
626
+ }
627
+ }
628
+
629
+ function glnvg__renderViewport(gl, width, height, devicePixelRatio) {
630
+ gl.view[0] = width;
631
+ gl.view[1] = height;
632
+ }
633
+
634
+
635
+ function glnvg__dumpShaderError(gl, shader, name, type) {
636
+ const infoLog = gl.getShaderInfoLog(shader);
637
+ console.error(`Shader ${name}/${type} error:\n${infoLog}`);
638
+ }
639
+
640
+ function glnvg__dumpProgramError(gl, program, name) {
641
+ const infoLog = gl.getProgramInfoLog(program);
642
+ console.error(`Program ${name} error:\n${infoLog}`);
643
+ }
644
+
645
+ function glnvg__getUniforms(gl, shader) {
646
+ shader.loc[GLNVG_LOC_VIEWSIZE] = gl.getUniformLocation(shader.prog, "viewSize");
647
+ shader.loc[GLNVG_LOC_TEX] = gl.getUniformLocation(shader.prog, "tex");
648
+
649
+ shader.loc[GLNVG_LOC_INNECOL] = gl.getUniformLocation(shader.prog, "innerCol");
650
+
651
+ if(NANOVG_GL_USE_UNIFORMBUFFER){
652
+ shader.loc[GLNVG_LOC_FRAG] = gl.getUniformBlockIndex(shader.prog, "frag");
653
+ }else{
654
+ shader.loc[GLNVG_LOC_FRAG] = gl.getUniformLocation(shader.prog, "frag[0]");
655
+ if (!shader.loc[GLNVG_LOC_FRAG]) {
656
+ shader.loc[GLNVG_LOC_FRAG] = gl.getUniformLocation(shader.prog, "frag");
657
+ }
658
+ }
659
+ }
660
+
661
+ function glnvg__renderFill(gl, paint, compositeOperation, scissor, fringe, bounds, paths, npaths) {
662
+ var call = glnvg__allocCall(gl);
663
+ if (call == null) return;
664
+
665
+ call.type = GLNVG_FILL;
666
+ call.triangleCount = 4;
667
+ call.pathOffset = glnvg__allocPaths(gl, npaths);
668
+ if (call.pathOffset === -1) return;
669
+ call.pathCount = npaths;
670
+ call.image = paint.image;
671
+ call.blendFunc = glnvg__blendCompositeOperation(compositeOperation);
672
+
673
+ if (npaths === 1 && paths[0].convex) {
674
+ call.type = GLNVG_CONVEXFILL;
675
+ call.triangleCount = 0;
676
+ }
677
+
678
+ let maxverts = glnvg__maxVertCount(paths, npaths) + call.triangleCount;
679
+ let offset = glnvg__allocVerts(gl, maxverts);
680
+ if (offset === -1) return;
681
+
682
+ for (let i = 0; i < npaths; i++) {
683
+ let copy = gl.paths[call.pathOffset + i];
684
+ let path = paths[i];
685
+ copy.fillOffset = 0;
686
+ copy.fillCount = 0;
687
+ copy.strokeOffset = 0;
688
+ copy.strokeCount = 0;
689
+
690
+ if (path.nfill > 0) {
691
+ copy.fillOffset = offset;
692
+ copy.fillCount = path.nfill;
693
+
694
+ let destView = new Float32Array(gl.verts, offset * NVG_VERTEX_SIZEOF, path.nfill * 4);
695
+ destView.set(path.fill);
696
+
697
+ offset += path.nfill;
698
+ }
699
+
700
+ if (path.nstroke > 0) {
701
+ copy.strokeOffset = offset;
702
+ copy.strokeCount = path.nstroke;
703
+
704
+ let destView = new Float32Array(gl.verts, offset * NVG_VERTEX_SIZEOF, path.nstroke * 4);
705
+ destView.set(path.stroke);
706
+
707
+ offset += path.nstroke;
708
+ }
709
+ }
710
+
711
+ if (call.type === GLNVG_FILL) {
712
+ call.triangleOffset = offset;
713
+
714
+ for (let i = 0; i < 4; i++) {
715
+ let vtx = new NVGvertex(gl.verts, call.triangleOffset + i);
716
+
717
+ switch(i) {
718
+ case 0: nvg__vset(vtx, bounds[2], bounds[3], 0.5, 1.0); break;
719
+ case 1: nvg__vset(vtx, bounds[2], bounds[1], 0.5, 1.0); break;
720
+ case 2: nvg__vset(vtx, bounds[0], bounds[3], 0.5, 1.0); break;
721
+ case 3: nvg__vset(vtx, bounds[0], bounds[1], 0.5, 1.0); break;
722
+ }
723
+ }
724
+
725
+ call.uniformOffset = glnvg__allocFragUniforms(gl, 2);
726
+ if (call.uniformOffset === -1) return;
727
+
728
+ let frag = nvg__fragUniformPtr(gl, call.uniformOffset);
729
+ frag.strokeThr = -1.0;
730
+ frag.type = NSVG_SHADER_SIMPLE;
731
+
732
+ glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call.uniformOffset + gl.fragSize),
733
+ paint, scissor, fringe, fringe, -1.0);
734
+ } else {
735
+ call.uniformOffset = glnvg__allocFragUniforms(gl, 1);
736
+ if (call.uniformOffset === -1) return;
737
+
738
+ glnvg__convertPaint(gl, nvg__fragUniformPtr(gl, call.uniformOffset),
739
+ paint, scissor, fringe, fringe, -1.0);
740
+ }
741
+ }
742
+
743
+ function glnvg__allocCall(gl) {
744
+ if (gl.ncalls + 1 > gl.ccalls) {
745
+ var calls;
746
+ var ccalls = Math.max(gl.ncalls + 1, 128) + Math.floor(gl.ccalls / 2);
747
+ calls = new Array(ccalls);
748
+ for (var i = 0; i < ccalls; i++) {
749
+ calls[i] = i < gl.ncalls && gl.calls ? gl.calls[i] : new GLNVGcall();
750
+ }
751
+ if (calls === null) return null;
752
+ gl.calls = calls;
753
+ gl.ccalls = ccalls;
754
+ }
755
+ let ret = gl.calls[gl.ncalls++];
756
+ Object.assign(ret, new GLNVGcall());
757
+ return ret;
758
+ }
759
+
760
+ function glnvg__allocPaths(gl, n) {
761
+ let ret = 0;
762
+ if (gl.npaths + n > gl.cpaths) {
763
+ let cpaths = Math.max(gl.npaths + n, 128) + Math.floor(gl.cpaths / 2);
764
+ let paths = new Array(cpaths);
765
+ for (let i = 0; i < cpaths; i++) {
766
+ paths[i] = i < gl.npaths && gl.paths ? gl.paths[i] : new GLNVGpath();
767
+ }
768
+ if (paths === null) return -1;
769
+ gl.paths = paths;
770
+ gl.cpaths = cpaths;
771
+ }
772
+ ret = gl.npaths;
773
+ gl.npaths += n;
774
+ return ret;
775
+ }
776
+
777
+ function glnvg__allocVerts(gl, n) {
778
+ let ret = 0;
779
+ if (gl.nverts + n > gl.cverts) {
780
+ let cverts = Math.max(gl.nverts + n, 4096) + Math.floor(gl.cverts / 2);
781
+
782
+ let newVerts = new ArrayBuffer(cverts * NVG_VERTEX_SIZEOF);
783
+
784
+ if (gl.verts && gl.nverts > 0) {
785
+ let oldView = new Uint8Array(gl.verts, 0, gl.nverts * NVG_VERTEX_SIZEOF);
786
+ let newView = new Uint8Array(newVerts);
787
+ newView.set(oldView);
788
+ }
789
+
790
+ gl.verts = newVerts;
791
+ gl.cverts = cverts;
792
+ }
793
+ ret = gl.nverts;
794
+ gl.nverts += n;
795
+ return ret;
796
+ }
797
+
798
+ /*function glnvg__allocVerts(gl, n) {
799
+ let ret = 0;
800
+ let cverts = Math.max(gl.nverts + n, 4096) + Math.floor(gl.cverts / 2);
801
+ if (gl.verts == null)
802
+ gl.verts = new ArrayBuffer(n * NVG_VERTEX_SIZEOF);
803
+ else{
804
+ let oldView = new Float32Array(gl.verts);
805
+ console.log("oldView: " + oldView.length)
806
+ console.log("newView: " + n * 4)
807
+ let newLength = (oldView.length + n * 4);
808
+ console.log("newLength: " + newLength)
809
+ let newBuffer = new ArrayBuffer(newLength * 4);
810
+ let newView = new Float32Array(newBuffer);
811
+ newView.set(oldView.subarray(0, newLength));
812
+ gl.verts = newBuffer;
813
+ }
814
+ gl.cverts = cverts;
815
+ ret = gl.nverts;
816
+ gl.nverts += n;
817
+ return ret;
818
+ }*/
819
+
820
+ function glnvg__blendCompositeOperation(op) {
821
+ const blend = {
822
+ srcRGB: glnvg_convertBlendFuncFactor(op.srcRGB),
823
+ dstRGB: glnvg_convertBlendFuncFactor(op.dstRGB),
824
+ srcAlpha: glnvg_convertBlendFuncFactor(op.srcAlpha),
825
+ dstAlpha: glnvg_convertBlendFuncFactor(op.dstAlpha)
826
+ };
827
+ const INVALID_ENUM = 0x0500;
828
+ const ONE = 1;
829
+ const ONE_MINUS_SRC_ALPHA = 0x0303;
830
+ if (
831
+ blend.srcRGB === INVALID_ENUM ||
832
+ blend.dstRGB === INVALID_ENUM ||
833
+ blend.srcAlpha === INVALID_ENUM ||
834
+ blend.dstAlpha === INVALID_ENUM
835
+ ) {
836
+ blend.srcRGB = ONE;
837
+ blend.dstRGB = ONE_MINUS_SRC_ALPHA;
838
+ blend.srcAlpha = ONE;
839
+ blend.dstAlpha = ONE_MINUS_SRC_ALPHA;
840
+ }
841
+ return blend;
842
+ }
843
+
844
+ function glnvg__renderFlush(ctx) {
845
+ const gl = ctx.params.userPtr;
846
+
847
+ if (gl.ncalls > 0) {
848
+
849
+ gl.useProgram(gl.shader.prog);
850
+ gl.enable(gl.CULL_FACE);
851
+ gl.cullFace(gl.BACK);
852
+ gl.frontFace(gl.CCW);
853
+ gl.enable(gl.BLEND);
854
+ gl.disable(gl.DEPTH_TEST);
855
+ gl.disable(gl.SCISSOR_TEST);
856
+ gl.colorMask(true, true, true, true);
857
+ gl.stencilMask(0xffffffff);
858
+ gl.stencilFunc(gl.ALWAYS, 0, 0xffffffff);
859
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
860
+
861
+ gl.activeTexture(gl.TEXTURE0);
862
+ gl.bindTexture(gl.TEXTURE_2D, null);
863
+
864
+ if(NANOVG_GL_USE_STATE_FILTER){
865
+ gl.boundTexture = 0;
866
+ gl.stencilMsk = 0xffffffff;
867
+ gl.stencilFnc = gl.ALWAYS;
868
+ gl.stencilFuncRef = 0;
869
+ gl.stencilFuncMask = 0xffffffff;
870
+ gl.blendFunc.srcRGB = gl.INVALID_ENUM;
871
+ gl.blendFunc.srcAlpha = gl.INVALID_ENUM;
872
+ gl.blendFunc.dstRGB = gl.INVALID_ENUM;
873
+ gl.blendFunc.dstAlpha = gl.INVALID_ENUM;
874
+ }
875
+
876
+ if(NANOVG_GL_USE_UNIFORMBUFFER){
877
+ gl.bindBuffer(gl.UNIFORM_BUFFER, gl.fragBuf);
878
+ gl.bufferData(gl.UNIFORM_BUFFER, gl.uniforms, gl.STREAM_DRAW);
879
+ }
880
+
881
+ gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertBuf);
882
+
883
+ const vertexData = new Float32Array(gl.verts, 0, gl.nverts * 4);
884
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STREAM_DRAW);
885
+
886
+ gl.enableVertexAttribArray(0);
887
+ gl.enableVertexAttribArray(1);
888
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 16, 0);
889
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 16, 8);
890
+
891
+ gl.uniform1i(gl.shader.loc[GLNVG_LOC_TEX], 0);
892
+ gl.uniform2fv(gl.shader.loc[GLNVG_LOC_VIEWSIZE], gl.view);
893
+
894
+ for (let i = 0; i < gl.ncalls; i++) {
895
+ const call = gl.calls[i];
896
+
897
+ glnvg__blendFuncSeparate(gl, call.blendFunc);
898
+
899
+ if (call.type === GLNVG_FILL)
900
+ glnvg__fill(gl, call);
901
+ else if (call.type === GLNVG_CONVEXFILL)
902
+ glnvg__convexFill(gl, call);
903
+ else if (call.type === GLNVG_STROKE)
904
+ glnvg__stroke(gl, call);
905
+ else if (call.type === GLNVG_TRIANGLES)
906
+ glnvg__triangles(gl, call);
907
+ }
908
+
909
+ gl.disableVertexAttribArray(0);
910
+ gl.disableVertexAttribArray(1);
911
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
912
+ gl.useProgram(null);
913
+ glnvg__bindTexture(gl, null);
914
+ }
915
+
916
+ gl.nverts = 0;
917
+ gl.npaths = 0;
918
+ gl.ncalls = 0;
919
+ gl.nuniforms = 0;
920
+ }
921
+
922
+ function glnvg__blendFuncSeparate(gl, blend) {
923
+ if(NANOVG_GL_USE_STATE_FILTER){
924
+ if (
925
+ gl.blendFunc.srcRGB !== blend.srcRGB ||
926
+ gl.blendFunc.dstRGB !== blend.dstRGB ||
927
+ gl.blendFunc.srcAlpha !== blend.srcAlpha ||
928
+ gl.blendFunc.dstAlpha !== blend.dstAlpha
929
+ ) {
930
+ gl.blendFunc = blend;
931
+ gl.blendFuncSeparate(blend.srcRGB, blend.dstRGB, blend.srcAlpha, blend.dstAlpha);
932
+ }
933
+ }else{
934
+ gl.blendFuncSeparate(blend.srcRGB, blend.dstRGB, blend.srcAlpha, blend.dstAlpha);
935
+ }
936
+ }
937
+
938
+ function glnvg__setUniforms(gl, uniformOffset, image) {
939
+ let tex = null;
940
+
941
+ const frag = nvg__fragUniformPtr(gl, uniformOffset);
942
+
943
+ gl.uniform4fv(gl.shader.loc[GLNVG_LOC_FRAG], frag.buffer);
944
+
945
+ if (image !== 0) tex = glnvg__findTexture(gl, image);
946
+ if (tex === null) tex = glnvg__findTexture(gl, gl.dummyTex);
947
+ glnvg__bindTexture(gl, tex !== null ? tex.tex : null);
948
+ }
949
+
950
+
951
+ function glnvg__fill(gl, call) {
952
+ let paths = [];
953
+ for (let i = call.pathOffset; i < call.pathOffset + call.pathCount; i++) {
954
+ paths.push(gl.paths[i]);
955
+ }
956
+ let npaths = call.pathCount;
957
+
958
+ gl.enable(gl.STENCIL_TEST);
959
+ glnvg__stencilMask(gl, 0xff);
960
+ glnvg__stencilFunc(gl, gl.ALWAYS, 0, 0xff);
961
+ gl.colorMask(false, false, false, false);
962
+
963
+ glnvg__setUniforms(gl, call.uniformOffset, 0);
964
+ glnvg__checkError(gl, "fill simple");
965
+
966
+ gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.INCR_WRAP);
967
+ gl.stencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.DECR_WRAP);
968
+ gl.disable(gl.CULL_FACE);
969
+ for (let i = 0; i < npaths; i++)
970
+ gl.drawArrays(gl.TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
971
+ gl.enable(gl.CULL_FACE);
972
+
973
+ gl.colorMask(true, true, true, true);
974
+
975
+ glnvg__setUniforms(gl, call.uniformOffset + gl.fragSize, call.image);
976
+ glnvg__checkError(gl, "fill fill");
977
+
978
+ if (gl.flags & NVG_ANTIALIAS) {
979
+ glnvg__stencilFunc(gl, gl.EQUAL, 0x00, 0xff);
980
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
981
+ for (let i = 0; i < npaths; i++)
982
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
983
+ }
984
+
985
+ glnvg__stencilFunc(gl, gl.NOTEQUAL, 0x0, 0xff);
986
+ gl.stencilOp(gl.ZERO, gl.ZERO, gl.ZERO);
987
+ gl.drawArrays(gl.TRIANGLE_STRIP, call.triangleOffset, call.triangleCount);
988
+
989
+ gl.disable(gl.STENCIL_TEST);
990
+ }
991
+
992
+ function glnvg__convexFill(gl, call) {
993
+ const paths = gl.paths.slice(call.pathOffset, call.pathOffset + call.pathCount);
994
+ const npaths = call.pathCount;
995
+
996
+ glnvg__setUniforms(gl, call.uniformOffset, call.image);
997
+ glnvg__checkError(gl, "convex fill");
998
+
999
+ for (let i = 0; i < npaths; i++) {
1000
+ if (paths[i].fillCount > 0) {
1001
+ gl.drawArrays(gl.TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount);
1002
+ }
1003
+ if (paths[i].strokeCount > 0) {
1004
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
1005
+ }
1006
+ }
1007
+ }
1008
+
1009
+ function glnvg__stroke(gl, call) {
1010
+ let paths = [];
1011
+ for (let i = call.pathOffset; i < call.pathOffset + call.pathCount; i++) {
1012
+ paths.push(gl.paths[i]);
1013
+ }
1014
+ let npaths = call.pathCount;
1015
+ const hadCull = gl.isEnabled(gl.CULL_FACE);
1016
+ gl.disable(gl.CULL_FACE);
1017
+
1018
+ if (gl.flags & NVG_STENCIL_STROKES) {
1019
+ gl.enable(gl.STENCIL_TEST);
1020
+ glnvg__stencilMask(gl, 0xff);
1021
+
1022
+ glnvg__stencilFunc(gl, gl.EQUAL, 0x0, 0xff);
1023
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
1024
+ glnvg__setUniforms(gl, call.uniformOffset + gl.fragSize, call.image);
1025
+ glnvg__checkError(gl, "stroke fill 0");
1026
+ for (let i = 0; i < npaths; i++)
1027
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
1028
+
1029
+ glnvg__setUniforms(gl, call.uniformOffset, call.image);
1030
+ glnvg__stencilFunc(gl, gl.EQUAL, 0x00, 0xff);
1031
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
1032
+ for (let i = 0; i < npaths; i++)
1033
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
1034
+
1035
+ gl.colorMask(false, false, false, false);
1036
+ glnvg__stencilFunc(gl, gl.ALWAYS, 0x0, 0xff);
1037
+ gl.stencilOp(gl.ZERO, gl.ZERO, gl.ZERO);
1038
+ glnvg__checkError(gl, "stroke fill 1");
1039
+ for (let i = 0; i < npaths; i++)
1040
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
1041
+ gl.colorMask(true, true, true, true);
1042
+
1043
+ gl.disable(gl.STENCIL_TEST);
1044
+ } else {
1045
+ glnvg__setUniforms(gl, call.uniformOffset, call.image);
1046
+ glnvg__checkError(gl, "stroke fill");
1047
+ for (let i = 0; i < npaths; i++)
1048
+ gl.drawArrays(gl.TRIANGLE_STRIP, paths[i].strokeOffset, paths[i].strokeCount);
1049
+ }
1050
+
1051
+ if (hadCull) gl.enable(gl.CULL_FACE);
1052
+ }
1053
+
1054
+ function glnvg__triangles(gl, call) {
1055
+ glnvg__setUniforms(gl, call.uniformOffset, call.image);
1056
+ glnvg__checkError(gl, "triangles fill");
1057
+
1058
+ gl.drawArrays(gl.TRIANGLES, call.triangleOffset, call.triangleCount);
1059
+ }
1060
+
1061
+ function glnvg__maxVertCount(paths, npaths) {
1062
+ let count = 0;
1063
+ for (let i = 0; i < npaths; i++) {
1064
+ count += paths[i].nfill;
1065
+ count += paths[i].nstroke;
1066
+ }
1067
+ return count;
1068
+ }
1069
+
1070
+ function nvg__vset(vtx, x, y, u, v) {
1071
+ vtx.x = x;
1072
+ vtx.y = y;
1073
+ vtx.u = u;
1074
+ vtx.v = v;
1075
+ }
1076
+
1077
+ function glnvg__allocFragUniforms(gl, n) {
1078
+ let ret = 0;
1079
+ let structSize = gl.fragSize;
1080
+
1081
+ if (gl.nuniforms + n > gl.cuniforms) {
1082
+ let cuniforms = Math.max(gl.nuniforms + n, 128) + Math.floor(gl.cuniforms / 2);
1083
+ let totalFloats = (structSize * cuniforms) / Float32Array.BYTES_PER_ELEMENT;
1084
+
1085
+ let newUniforms = new Float32Array(totalFloats);
1086
+
1087
+ if (gl.uniforms && gl.nuniforms > 0) {
1088
+ let oldSize = (structSize * gl.nuniforms) / Float32Array.BYTES_PER_ELEMENT;
1089
+ newUniforms.set(gl.uniforms.subarray(0, oldSize));
1090
+ }
1091
+
1092
+ gl.uniforms = newUniforms;
1093
+ gl.cuniforms = cuniforms;
1094
+ }
1095
+
1096
+ ret = gl.nuniforms * structSize;
1097
+ gl.nuniforms += n;
1098
+ return ret;
1099
+ }
1100
+
1101
+ //function nvg__fragUniformPtr(gl, i) {
1102
+ // return new GLNVGfragUniforms(gl.uniforms.subarray(i * gl.fragSize, (i + 1) * gl.fragSize));
1103
+ //}
1104
+
1105
+ function nvg__fragUniformPtr(gl, byteOffset) {
1106
+ const floatOffset = byteOffset / Float32Array.BYTES_PER_ELEMENT;
1107
+ return new GLNVGfragUniforms(gl.uniforms, byteOffset);
1108
+ }
1109
+
1110
+
1111
+ function glnvg__convertPaint(gl, frag, paint, scissor, width, fringe, strokeThr) {
1112
+ let tex = null;
1113
+ const invxform = new Float32Array(6);
1114
+ frag.buffer.fill(0);
1115
+
1116
+ frag.innerCol = glnvg__premulColor(paint.innerColor);
1117
+ frag.outerCol = glnvg__premulColor(paint.outerColor);
1118
+
1119
+ if (scissor.extent[0] < -0.5 || scissor.extent[1] < -0.5) {
1120
+ const zeroMat = new Float32Array(12);
1121
+ frag.scissorMat = zeroMat;
1122
+ frag.scissorExt = [1.0, 1.0];
1123
+ frag.scissorScale = [1.0, 1.0];
1124
+ } else {
1125
+ const scissorMat3x4 = new Float32Array(12);
1126
+ nvgTransformInverse(invxform, scissor.xform);
1127
+ glnvg__xformToMat3x4(scissorMat3x4, invxform);
1128
+ frag.scissorMat = scissorMat3x4;
1129
+ frag.scissorExt = [scissor.extent[0], scissor.extent[1]];
1130
+ frag.scissorScale = [
1131
+ Math.sqrt(scissor.xform[0] * scissor.xform[0] + scissor.xform[2] * scissor.xform[2]) / fringe,
1132
+ Math.sqrt(scissor.xform[1] * scissor.xform[1] + scissor.xform[3] * scissor.xform[3]) / fringe
1133
+ ];
1134
+ }
1135
+
1136
+ frag.extent = [paint.extent[0], paint.extent[1]];
1137
+ frag.strokeMult = (width * 0.5 + fringe * 0.5) / fringe;
1138
+ frag.strokeThr = strokeThr;
1139
+
1140
+ if (paint.image !== 0 && paint.image !== undefined && paint.image !== null) {
1141
+ tex = glnvg__findTexture(gl, paint.image);
1142
+ if (tex === null) return 0;
1143
+ if ((tex.flags & NVG_IMAGE_FLIPY) !== 0) {
1144
+ const m1 = new Float32Array(6);
1145
+ const m2 = new Float32Array(6);
1146
+ nvgTransformTranslate(m1, 0.0, frag.extent[1] * 0.5);
1147
+ nvgTransformMultiply(m1, paint.xform);
1148
+ nvgTransformScale(m2, 1.0, -1.0);
1149
+ nvgTransformMultiply(m2, m1);
1150
+ nvgTransformTranslate(m1, 0.0, -frag.extent[1] * 0.5);
1151
+ nvgTransformMultiply(m1, m2);
1152
+ nvgTransformInverse(invxform, m1);
1153
+ } else {
1154
+ nvgTransformInverse(invxform, paint.xform);
1155
+ }
1156
+ frag.type = NSVG_SHADER_FILLIMG;
1157
+
1158
+ if(NANOVG_GL_USE_UNIFORMBUFFER){
1159
+ if (tex.type === NVG_TEXTURE_RGBA)
1160
+ frag.texType = (tex.flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1;
1161
+ else
1162
+ frag.texType = 2;
1163
+ }else{
1164
+ if (tex.type === NVG_TEXTURE_RGBA)
1165
+ frag.texType = (tex.flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0 : 1.0;
1166
+ else
1167
+ frag.texType = 2.0;
1168
+ }
1169
+ } else {
1170
+ frag.type = NSVG_SHADER_FILLGRAD;
1171
+ frag.radius = paint.radius;
1172
+ frag.feather = paint.feather;
1173
+ nvgTransformInverse(invxform, paint.xform);
1174
+ }
1175
+
1176
+ const paintMat3x4 = new Float32Array(12);
1177
+ glnvg__xformToMat3x4(paintMat3x4, invxform);
1178
+ frag.paintMat = paintMat3x4;
1179
+
1180
+ return 1;
1181
+ }
1182
+
1183
+ function glnvg_convertBlendFuncFactor(factor) {
1184
+ if (factor === NVG_ZERO)
1185
+ return 0; // ZERO
1186
+ if (factor === NVG_ONE)
1187
+ return 1; // ONE
1188
+ if (factor === NVG_SRC_COLOR)
1189
+ return 0x0300; // SRC_COLOR
1190
+ if (factor === NVG_ONE_MINUS_SRC_COLOR)
1191
+ return 0x0301; // ONE_MINUS_SRC_COLOR
1192
+ if (factor === NVG_DST_COLOR)
1193
+ return 0x0306; // DST_COLOR
1194
+ if (factor === NVG_ONE_MINUS_DST_COLOR)
1195
+ return 0x0307; // ONE_MINUS_DST_COLOR
1196
+ if (factor === NVG_SRC_ALPHA)
1197
+ return 0x0302; // SRC_ALPHA
1198
+ if (factor === NVG_ONE_MINUS_SRC_ALPHA)
1199
+ return 0x0303; // ONE_MINUS_SRC_ALPHA
1200
+ if (factor === NVG_DST_ALPHA)
1201
+ return 0x0304; // DST_ALPHA
1202
+ if (factor === NVG_ONE_MINUS_DST_ALPHA)
1203
+ return 0x0305; // ONE_MINUS_DST_ALPHA
1204
+ if (factor === NVG_SRC_ALPHA_SATURATE)
1205
+ return 0x0308; // SRC_ALPHA_SATURATE
1206
+ return 0x0500; // INVALID_ENUM
1207
+ }
1208
+
1209
+ function glnvg__maxi(a, b) {
1210
+ return a > b ? a : b;
1211
+ }
1212
+
1213
+ function glnvg__premulColor(c) {
1214
+ return {
1215
+ r: c.rgba[0] * c.rgba[3],
1216
+ g: c.rgba[1] * c.rgba[3],
1217
+ b: c.rgba[2] * c.rgba[3],
1218
+ a: c.rgba[3]
1219
+ };
1220
+ }
1221
+
1222
+ function glnvg__xformToMat3x4(m3, t) {
1223
+ m3[0] = t[0];
1224
+ m3[1] = t[1];
1225
+ m3[2] = 0.0;
1226
+ m3[3] = 0.0;
1227
+ m3[4] = t[2];
1228
+ m3[5] = t[3];
1229
+ m3[6] = 0.0;
1230
+ m3[7] = 0.0;
1231
+ m3[8] = t[4];
1232
+ m3[9] = t[5];
1233
+ m3[10] = 1.0;
1234
+ m3[11] = 0.0;
1235
+ }
1236
+
1237
+ function glnvg__findTexture(gl, id) {
1238
+ for (let i = 0; i < gl.ntextures; i++) {
1239
+ if (gl.textures[i].id === id) {
1240
+ return gl.textures[i];
1241
+ }
1242
+ }
1243
+ return null;
1244
+ }
1245
+
1246
+ function glnvg__allocTexture(gl) {
1247
+ var tex = null;
1248
+ var i;
1249
+
1250
+ for (i = 0; i < gl.ntextures; i++) {
1251
+ if (gl.textures[i].id === 0) {
1252
+ tex = gl.textures[i];
1253
+ break;
1254
+ }
1255
+ }
1256
+
1257
+ if (tex === null) {
1258
+ if (gl.ntextures + 1 > gl.ctextures) {
1259
+ var textures;
1260
+ var ctextures = glnvg__maxi(gl.ntextures + 1, 4) + Math.floor(gl.ctextures / 2);
1261
+ textures = new Array(ctextures);
1262
+ for (var j = 0; j < ctextures; j++) {
1263
+ textures[j] = j < gl.ntextures && gl.textures ? gl.textures[j] : new GLNVGtexture();
1264
+ }
1265
+ if (textures === null) return null;
1266
+ gl.textures = textures;
1267
+ gl.ctextures = ctextures;
1268
+ }
1269
+ tex = gl.textures[gl.ntextures++];
1270
+ }
1271
+
1272
+ tex.id = ++gl.textureId;
1273
+
1274
+ return tex;
1275
+ }
1276
+
1277
+ function glnvg__nearestPow2(num) {
1278
+ var n = num > 0 ? num - 1 : 0;
1279
+ n |= n >> 1;
1280
+ n |= n >> 2;
1281
+ n |= n >> 4;
1282
+ n |= n >> 8;
1283
+ n |= n >> 16;
1284
+ n++;
1285
+ return n;
1286
+ }
1287
+
1288
+ function glnvg__stencilMask(gl, mask) {
1289
+ if (NANOVG_GL_USE_STATE_FILTER) {
1290
+ if (gl.stencilMsk !== mask) {
1291
+ gl.stencilMsk = mask;
1292
+ gl.stencilMask(mask);
1293
+ }
1294
+ } else {
1295
+ gl.stencilMsk = mask;
1296
+ }
1297
+ }
1298
+
1299
+ function glnvg__stencilFunc(gl, func, ref, mask) {
1300
+ if (NANOVG_GL_USE_STATE_FILTER) {
1301
+ if (
1302
+ gl.stencilFnc !== func ||
1303
+ gl.stencilFuncRef !== ref ||
1304
+ gl.stencilFuncMask !== mask
1305
+ ) {
1306
+ gl.stencilFnc = func;
1307
+ gl.stencilFuncRef = ref;
1308
+ gl.stencilFuncMask = mask;
1309
+ gl.stencilFunc(func, ref, mask);
1310
+ }
1311
+ } else {
1312
+ gl.stencilFunc(func, ref, mask);
1313
+ }
1314
+ }
1315
+
1316
+ function glnvg__bindTexture(gl, tex) {
1317
+ if (NANOVG_GL_USE_STATE_FILTER){
1318
+ if (gl.boundTexture !== tex) {
1319
+ gl.boundTexture = tex;
1320
+ gl.bindTexture(gl.TEXTURE_2D, tex);
1321
+ }
1322
+ }
1323
+ else
1324
+ gl.bindTexture(gl.TEXTURE_2D, tex);
1325
+ }
1326
+
1327
+ function glnvg__deleteTexture(gl, id) {
1328
+ for (let i = 0; i < gl.ntextures; i++) {
1329
+ const tex = gl.textures[i];
1330
+ if (tex.id === id) {
1331
+ if (tex.tex && (tex.flags & NVG_IMAGE_NODELETE) === 0) {
1332
+ gl.deleteTexture(tex.tex);
1333
+ }
1334
+ gl.textures[i] = new GLNVGtexture();
1335
+ return 1;
1336
+ }
1337
+ }
1338
+ return 0;
1339
+ }
1340
+
1341
+ function glnvg__renderDeleteTexture(gl, image) {
1342
+ return glnvg__deleteTexture(gl, image);
1343
+ }
1344
+
1345
+ function glnvg__renderGetTextureSize(gl, image) {
1346
+ const tex = glnvg__findTexture(gl, image);
1347
+ if (tex === null) return [0, 0];
1348
+ return [tex.width, tex.height];
1349
+ }
1350
+
1351
+ function glnvg__renderCancel(gl) {
1352
+ gl.nverts = 0;
1353
+ gl.npaths = 0;
1354
+ gl.ncalls = 0;
1355
+ gl.nuniforms = 0;
1356
+ }
1357
+
1358
+ function glnvg__renderTriangles(gl, paint, compositeOperation, scissor, verts, nverts, fringe) {
1359
+ const call = glnvg__allocCall(gl);
1360
+ if (call === null) return;
1361
+
1362
+ call.type = GLNVG_TRIANGLES;
1363
+ call.image = paint.image;
1364
+ call.blendFunc = glnvg__blendCompositeOperation(compositeOperation);
1365
+
1366
+ call.triangleOffset = glnvg__allocVerts(gl, nverts);
1367
+ if (call.triangleOffset === -1) {
1368
+ if (gl.ncalls > 0) gl.ncalls--;
1369
+ return;
1370
+ }
1371
+ call.triangleCount = nverts;
1372
+
1373
+ const destView = new Float32Array(gl.verts, call.triangleOffset * NVG_VERTEX_SIZEOF, nverts * 4);
1374
+ if (verts instanceof ArrayBuffer) {
1375
+ destView.set(new Float32Array(verts, 0, nverts * 4));
1376
+ } else if (verts instanceof Float32Array) {
1377
+ destView.set(verts.subarray(0, nverts * 4));
1378
+ } else {
1379
+ for (let i = 0; i < nverts; i++) {
1380
+ const dst = i * 4;
1381
+ destView[dst + 0] = verts[i].x;
1382
+ destView[dst + 1] = verts[i].y;
1383
+ destView[dst + 2] = verts[i].u;
1384
+ destView[dst + 3] = verts[i].v;
1385
+ }
1386
+ }
1387
+
1388
+ call.uniformOffset = glnvg__allocFragUniforms(gl, 1);
1389
+ if (call.uniformOffset === -1) {
1390
+ if (gl.ncalls > 0) gl.ncalls--;
1391
+ return;
1392
+ }
1393
+
1394
+ const frag = nvg__fragUniformPtr(gl, call.uniformOffset);
1395
+ glnvg__convertPaint(gl, frag, paint, scissor, 1.0, fringe, -1.0);
1396
+ frag.type = NSVG_SHADER_IMG;
1397
+ }
1398
+
1399
+ function glnvg__deleteShader(gl, shader) {
1400
+ if (shader.prog) gl.deleteProgram(shader.prog);
1401
+ if (shader.vert) gl.deleteShader(shader.vert);
1402
+ if (shader.frag) gl.deleteShader(shader.frag);
1403
+ }
1404
+
1405
+ function glnvg__renderDelete(gl) {
1406
+ if (!gl) return;
1407
+
1408
+ glnvg__deleteShader(gl, gl.shader);
1409
+
1410
+ if (gl.vertBuf) gl.deleteBuffer(gl.vertBuf);
1411
+ if (gl.fragBuf) gl.deleteBuffer(gl.fragBuf);
1412
+ if (gl.vertArr && gl.deleteVertexArray) gl.deleteVertexArray(gl.vertArr);
1413
+
1414
+ if (gl.textures) {
1415
+ for (let i = 0; i < gl.ntextures; i++) {
1416
+ const tex = gl.textures[i];
1417
+ if (tex && tex.tex && (tex.flags & NVG_IMAGE_NODELETE) === 0) {
1418
+ gl.deleteTexture(tex.tex);
1419
+ }
1420
+ }
1421
+ }
1422
+
1423
+ gl.textures = null;
1424
+ gl.paths = null;
1425
+ gl.verts = null;
1426
+ gl.uniforms = null;
1427
+ gl.calls = null;
1428
+ }
1429
+