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/LICENSE +17 -0
- package/README.md +65 -0
- package/example/Roboto-Bold.ttf +0 -0
- package/example/Roboto-Regular.ttf +0 -0
- package/example/entypo.ttf +0 -0
- package/example/images/image1.jpg +0 -0
- package/example/images/image10.jpg +0 -0
- package/example/images/image11.jpg +0 -0
- package/example/images/image12.jpg +0 -0
- package/example/images/image2.jpg +0 -0
- package/example/images/image3.jpg +0 -0
- package/example/images/image4.jpg +0 -0
- package/example/images/image5.jpg +0 -0
- package/example/images/image6.jpg +0 -0
- package/example/images/image7.jpg +0 -0
- package/example/images/image8.jpg +0 -0
- package/example/images/image9.jpg +0 -0
- package/example.js +1386 -0
- package/index.html +29 -0
- package/nanovg.js +3205 -0
- package/nanovg_gl.js +1429 -0
- package/package.json +16 -0
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
|
+
|