q5 2.14.1 → 2.14.4
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/package.json +1 -1
- package/q5.js +194 -70
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +1 -0
- package/src/q5-2d-drawing.js +9 -8
- package/src/q5-core.js +0 -3
- package/src/q5-math.js +1 -0
- package/src/q5-webgpu-canvas.js +11 -1
- package/src/q5-webgpu-drawing.js +169 -56
- package/src/q5-webgpu-text.js +3 -2
package/src/q5-webgpu-drawing.js
CHANGED
|
@@ -3,6 +3,8 @@ Q5.renderers.webgpu.drawing = ($, q) => {
|
|
|
3
3
|
drawStack = $.drawStack,
|
|
4
4
|
vertexStack = new Float32Array(1e7),
|
|
5
5
|
vertIndex = 0;
|
|
6
|
+
const TAU = Math.PI * 2;
|
|
7
|
+
const HALF_PI = Math.PI / 2;
|
|
6
8
|
|
|
7
9
|
let drawingShader = Q5.device.createShaderModule({
|
|
8
10
|
label: 'drawingShader',
|
|
@@ -116,10 +118,10 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
116
118
|
drawStack.push(0, 4);
|
|
117
119
|
};
|
|
118
120
|
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
let
|
|
122
|
-
|
|
121
|
+
const addArc = (x, y, a, b, startAngle, endAngle, n, ci, ti) => {
|
|
122
|
+
let angleRange = endAngle - startAngle;
|
|
123
|
+
let angleIncrement = angleRange / n;
|
|
124
|
+
let t = startAngle;
|
|
123
125
|
|
|
124
126
|
let v = vertexStack,
|
|
125
127
|
i = vertIndex;
|
|
@@ -144,27 +146,14 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
144
146
|
t += angleIncrement;
|
|
145
147
|
}
|
|
146
148
|
|
|
147
|
-
// close the triangle strip
|
|
148
|
-
// add center vertex
|
|
149
|
-
v[i++] = x;
|
|
150
|
-
v[i++] = y;
|
|
151
|
-
v[i++] = ci;
|
|
152
|
-
v[i++] = ti;
|
|
153
|
-
|
|
154
|
-
// add first perimeter vertex
|
|
155
|
-
v[i++] = x + a;
|
|
156
|
-
v[i++] = y;
|
|
157
|
-
v[i++] = ci;
|
|
158
|
-
v[i++] = ti;
|
|
159
|
-
|
|
160
149
|
vertIndex = i;
|
|
161
|
-
drawStack.push(0, (n + 1) * 2
|
|
150
|
+
drawStack.push(0, (n + 1) * 2);
|
|
162
151
|
};
|
|
163
152
|
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
let angleIncrement =
|
|
167
|
-
let t =
|
|
153
|
+
const addArcStroke = (x, y, outerA, outerB, innerA, innerB, startAngle, endAngle, n, ci, ti) => {
|
|
154
|
+
let angleRange = endAngle - startAngle;
|
|
155
|
+
let angleIncrement = angleRange / n;
|
|
156
|
+
let t = startAngle;
|
|
168
157
|
|
|
169
158
|
let v = vertexStack,
|
|
170
159
|
i = vertIndex;
|
|
@@ -193,45 +182,106 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
193
182
|
}
|
|
194
183
|
|
|
195
184
|
vertIndex = i;
|
|
196
|
-
drawStack.push(0, (n + 1) * 2);
|
|
185
|
+
drawStack.push(0, (n + 1) * 2);
|
|
197
186
|
};
|
|
198
187
|
|
|
199
188
|
$.rectMode = (x) => ($._rectMode = x);
|
|
200
189
|
|
|
201
|
-
$.rect = (x, y, w, h) => {
|
|
190
|
+
$.rect = (x, y, w, h, rr = 0) => {
|
|
202
191
|
let [l, r, t, b] = $._calcBox(x, y, w, h, $._rectMode);
|
|
203
192
|
let ci, ti;
|
|
204
193
|
if ($._matrixDirty) $._saveMatrix();
|
|
205
194
|
ti = $._matrixIndex;
|
|
206
195
|
|
|
196
|
+
if (!rr) {
|
|
197
|
+
if ($._doFill) {
|
|
198
|
+
ci = $._fill;
|
|
199
|
+
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if ($._doStroke) {
|
|
203
|
+
ci = $._stroke;
|
|
204
|
+
let sw = $._strokeWeight / 2;
|
|
205
|
+
|
|
206
|
+
// Calculate stroke positions
|
|
207
|
+
let lsw = l - sw,
|
|
208
|
+
rsw = r + sw,
|
|
209
|
+
tsw = t + sw,
|
|
210
|
+
bsw = b - sw,
|
|
211
|
+
lpsw = l + sw,
|
|
212
|
+
rpsw = r - sw,
|
|
213
|
+
tpsw = t - sw,
|
|
214
|
+
bpsw = b + sw;
|
|
215
|
+
|
|
216
|
+
addRect(lsw, tpsw, rsw, tpsw, rsw, tsw, lsw, tsw, ci, ti); // Top
|
|
217
|
+
addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // Bottom
|
|
218
|
+
|
|
219
|
+
// Adjust side strokes to avoid overlapping corners
|
|
220
|
+
tsw = t - sw;
|
|
221
|
+
bsw = b + sw;
|
|
222
|
+
|
|
223
|
+
addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // Left
|
|
224
|
+
addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // Right
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
l += rr;
|
|
230
|
+
r -= rr;
|
|
231
|
+
t -= rr;
|
|
232
|
+
b += rr;
|
|
233
|
+
|
|
234
|
+
// Clamp radius
|
|
235
|
+
rr = Math.min(rr, Math.min(w, h) / 2);
|
|
236
|
+
|
|
237
|
+
let n = getArcSegments(rr * $._scale);
|
|
238
|
+
|
|
239
|
+
let trr = t + rr,
|
|
240
|
+
brr = b - rr,
|
|
241
|
+
lrr = l - rr,
|
|
242
|
+
rrr = r + rr;
|
|
243
|
+
|
|
207
244
|
if ($._doFill) {
|
|
208
245
|
ci = $._fill;
|
|
209
|
-
|
|
246
|
+
// Corner arcs
|
|
247
|
+
addArc(r, b, rr, rr, -HALF_PI, 0, n, ci, ti);
|
|
248
|
+
addArc(l, b, rr, rr, -Math.PI, -HALF_PI, n, ci, ti);
|
|
249
|
+
addArc(l, t, rr, rr, Math.PI, HALF_PI, n, ci, ti);
|
|
250
|
+
addArc(r, t, rr, rr, 0, HALF_PI, n, ci, ti);
|
|
251
|
+
|
|
252
|
+
addRect(l, trr, r, trr, r, brr, l, brr, ci, ti); // center
|
|
253
|
+
addRect(l, t, lrr, t, lrr, b, l, b, ci, ti); // Left
|
|
254
|
+
addRect(rrr, t, r, t, r, b, rrr, b, ci, ti); // Right
|
|
210
255
|
}
|
|
211
256
|
|
|
212
257
|
if ($._doStroke) {
|
|
213
258
|
ci = $._stroke;
|
|
214
|
-
let
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
259
|
+
let hsw = $._hsw;
|
|
260
|
+
|
|
261
|
+
let outerA = rr + hsw,
|
|
262
|
+
outerB = rr + hsw,
|
|
263
|
+
innerA = rr - hsw,
|
|
264
|
+
innerB = rr - hsw;
|
|
265
|
+
// Corner arc strokes
|
|
266
|
+
addArcStroke(r, b, outerA, outerB, innerA, innerB, -HALF_PI, 0, n, ci, ti);
|
|
267
|
+
addArcStroke(l, b, outerA, outerB, innerA, innerB, -Math.PI, -HALF_PI, n, ci, ti);
|
|
268
|
+
addArcStroke(l, t, outerA, outerB, innerA, innerB, Math.PI, HALF_PI, n, ci, ti);
|
|
269
|
+
addArcStroke(r, t, outerA, outerB, innerA, innerB, 0, HALF_PI, n, ci, ti);
|
|
270
|
+
|
|
271
|
+
let lrrMin = lrr - hsw,
|
|
272
|
+
lrrMax = lrr + hsw,
|
|
273
|
+
rrrMin = rrr - hsw,
|
|
274
|
+
rrrMax = rrr + hsw,
|
|
275
|
+
trrMin = trr - hsw,
|
|
276
|
+
trrMax = trr + hsw,
|
|
277
|
+
brrMin = brr - hsw,
|
|
278
|
+
brrMax = brr + hsw;
|
|
279
|
+
|
|
280
|
+
// Side strokes - positioned outside
|
|
281
|
+
addRect(lrrMin, t, lrrMax, t, lrrMax, b, lrrMin, b, ci, ti); // Left
|
|
282
|
+
addRect(rrrMin, t, rrrMax, t, rrrMax, b, rrrMin, b, ci, ti); // Right
|
|
283
|
+
addRect(l, trrMin, r, trrMin, r, trrMax, l, trrMax, ci, ti); // Top
|
|
284
|
+
addRect(l, brrMin, r, brrMin, r, brrMax, l, brrMax, ci, ti); // Bottom
|
|
235
285
|
}
|
|
236
286
|
};
|
|
237
287
|
|
|
@@ -268,6 +318,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
268
318
|
d < 2400 ? 90 :
|
|
269
319
|
100;
|
|
270
320
|
|
|
321
|
+
$._ellipseMode = Q5.CENTER;
|
|
271
322
|
$.ellipseMode = (x) => ($._ellipseMode = x);
|
|
272
323
|
|
|
273
324
|
$.ellipse = (x, y, w, h) => {
|
|
@@ -279,30 +330,83 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
279
330
|
let ti = $._matrixIndex;
|
|
280
331
|
|
|
281
332
|
if ($._doFill) {
|
|
282
|
-
|
|
333
|
+
addArc(x, -y, a, b, 0, TAU, n, $._fill, ti);
|
|
283
334
|
}
|
|
284
335
|
if ($._doStroke) {
|
|
285
336
|
let sw = $._strokeWeight / 2;
|
|
286
337
|
// Draw the stroke as a ring using triangle strips
|
|
287
|
-
|
|
338
|
+
addArcStroke(x, -y, a + sw, b + sw, a - sw, b - sw, 0, TAU, n, $._stroke, ti);
|
|
288
339
|
}
|
|
289
340
|
};
|
|
290
341
|
|
|
291
342
|
$.circle = (x, y, d) => $.ellipse(x, y, d, d);
|
|
292
343
|
|
|
344
|
+
$.arc = (x, y, w, h, start, stop) => {
|
|
345
|
+
if (start === stop) return $.ellipse(x, y, w, h);
|
|
346
|
+
|
|
347
|
+
// Convert angles if needed
|
|
348
|
+
if ($._angleMode) {
|
|
349
|
+
start = $.radians(start);
|
|
350
|
+
stop = $.radians(stop);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Normalize angles
|
|
354
|
+
start %= TAU;
|
|
355
|
+
stop %= TAU;
|
|
356
|
+
if (start < 0) start += TAU;
|
|
357
|
+
if (stop < 0) stop += TAU;
|
|
358
|
+
if (start > stop) stop += TAU;
|
|
359
|
+
if (start == stop) return $.ellipse(x, y, w, h);
|
|
360
|
+
|
|
361
|
+
// Calculate position based on ellipseMode
|
|
362
|
+
let a, b;
|
|
363
|
+
if ($._ellipseMode == $.CENTER) {
|
|
364
|
+
a = w / 2;
|
|
365
|
+
b = h / 2;
|
|
366
|
+
} else if ($._ellipseMode == $.RADIUS) {
|
|
367
|
+
a = w;
|
|
368
|
+
b = h;
|
|
369
|
+
} else if ($._ellipseMode == $.CORNER) {
|
|
370
|
+
x += w / 2;
|
|
371
|
+
y += h / 2;
|
|
372
|
+
a = w / 2;
|
|
373
|
+
b = h / 2;
|
|
374
|
+
} else if ($._ellipseMode == $.CORNERS) {
|
|
375
|
+
x = (x + w) / 2;
|
|
376
|
+
y = (y + h) / 2;
|
|
377
|
+
a = (w - x) / 2;
|
|
378
|
+
b = (h - y) / 2;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
let ti = $._matrixIndex;
|
|
382
|
+
if ($._matrixDirty) $._saveMatrix();
|
|
383
|
+
let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * $._scale);
|
|
384
|
+
|
|
385
|
+
// Draw fill
|
|
386
|
+
if ($._doFill) {
|
|
387
|
+
addArc(x, -y, a, b, start, stop, n, $._fill, ti);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Draw stroke
|
|
391
|
+
if ($._doStroke) {
|
|
392
|
+
let sw = $._strokeWeight;
|
|
393
|
+
addArcStroke(x, -y, a + sw, b + sw, a - sw, b - sw, start, stop, n, $._stroke, ti);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
|
|
293
397
|
$.point = (x, y) => {
|
|
294
398
|
if ($._matrixDirty) $._saveMatrix();
|
|
295
399
|
let ti = $._matrixIndex,
|
|
296
400
|
ci = $._stroke,
|
|
297
401
|
sw = $._strokeWeight;
|
|
298
402
|
|
|
299
|
-
if (
|
|
403
|
+
if ($._scaledSW < 2) {
|
|
300
404
|
let [l, r, t, b] = $._calcBox(x, y, sw, sw, 'corner');
|
|
301
405
|
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
302
406
|
} else {
|
|
303
|
-
let n = getArcSegments(
|
|
407
|
+
let n = getArcSegments($._scaledSW);
|
|
304
408
|
sw /= 2;
|
|
305
|
-
|
|
409
|
+
addArc(x, -y, sw, sw, 0, TAU, n, ci, ti);
|
|
306
410
|
}
|
|
307
411
|
};
|
|
308
412
|
|
|
@@ -317,7 +421,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
317
421
|
let ti = $._matrixIndex,
|
|
318
422
|
ci = $._stroke,
|
|
319
423
|
sw = $._strokeWeight,
|
|
320
|
-
hsw =
|
|
424
|
+
hsw = $._hsw;
|
|
321
425
|
|
|
322
426
|
// calculate the direction vector and length
|
|
323
427
|
let dx = x2 - x1,
|
|
@@ -330,10 +434,10 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
330
434
|
|
|
331
435
|
addRect(x1 + px, -y1 - py, x1 - px, -y1 + py, x2 - px, -y2 + py, x2 + px, -y2 - py, ci, ti);
|
|
332
436
|
|
|
333
|
-
if (
|
|
334
|
-
let n = getArcSegments(
|
|
335
|
-
|
|
336
|
-
|
|
437
|
+
if ($._scaledSW > 2 && $._strokeJoin != 'none') {
|
|
438
|
+
let n = getArcSegments($._scaledSW);
|
|
439
|
+
addArc(x1, -y1, hsw, hsw, 0, TAU, n, ci, ti);
|
|
440
|
+
addArc(x2, -y2, hsw, hsw, 0, TAU, n, ci, ti);
|
|
337
441
|
}
|
|
338
442
|
};
|
|
339
443
|
|
|
@@ -370,6 +474,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
370
474
|
}
|
|
371
475
|
}
|
|
372
476
|
|
|
477
|
+
// calculate catmull-rom spline curve points
|
|
373
478
|
for (let i = 0; i < points.length - 3; i++) {
|
|
374
479
|
let p0 = points[i];
|
|
375
480
|
let p1 = points[i + 1];
|
|
@@ -444,17 +549,25 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
444
549
|
}
|
|
445
550
|
|
|
446
551
|
if ($._doStroke) {
|
|
552
|
+
let hsw = $._hsw,
|
|
553
|
+
n = getArcSegments($._scaledSW),
|
|
554
|
+
ti = $._matrixIndex,
|
|
555
|
+
ogStrokeJoin = $._strokeJoin;
|
|
556
|
+
$._strokeJoin = 'none';
|
|
447
557
|
// draw lines between vertices
|
|
448
558
|
for (let i = 0; i < shapeVertCount - 1; i++) {
|
|
449
559
|
let v1 = i * 4;
|
|
450
560
|
let v2 = (i + 1) * 4;
|
|
451
561
|
$.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
|
|
562
|
+
|
|
563
|
+
addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n, $._stroke, ti);
|
|
452
564
|
}
|
|
453
565
|
if (close) {
|
|
454
566
|
let v1 = (shapeVertCount - 1) * 4;
|
|
455
567
|
let v2 = 0;
|
|
456
568
|
$.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
|
|
457
569
|
}
|
|
570
|
+
$._strokeJoin = ogStrokeJoin;
|
|
458
571
|
}
|
|
459
572
|
|
|
460
573
|
// reset for the next shape
|
package/src/q5-webgpu-text.js
CHANGED
|
@@ -305,8 +305,9 @@ fn fragmentMain(f : FragmentParams) -> @location(0) vec4f {
|
|
|
305
305
|
leadPercent = 1.25;
|
|
306
306
|
|
|
307
307
|
$.textFont = (fontName) => {
|
|
308
|
-
|
|
309
|
-
if ($._font
|
|
308
|
+
let font = fonts[fontName];
|
|
309
|
+
if (font) $._font = font;
|
|
310
|
+
else if (font === undefined) $._loadDefaultFont(fontName);
|
|
310
311
|
};
|
|
311
312
|
|
|
312
313
|
$.textSize = (size) => {
|