q5 2.4.5 → 2.4.10
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 +230 -152
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +10 -10
- package/src/q5-2d-text.js +164 -128
- package/src/q5-webgpu-canvas.js +2 -2
- package/src/q5-webgpu-image.js +23 -4
- package/src/q5-webgpu-text.js +30 -7
- package/src/readme.md +2 -10
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -596,6 +596,13 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
596
596
|
return c;
|
|
597
597
|
};
|
|
598
598
|
|
|
599
|
+
$.clear = () => {
|
|
600
|
+
$.ctx.save();
|
|
601
|
+
$.ctx.resetTransform();
|
|
602
|
+
$.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
|
|
603
|
+
$.ctx.restore();
|
|
604
|
+
};
|
|
605
|
+
|
|
599
606
|
if ($._scope == 'image') return;
|
|
600
607
|
|
|
601
608
|
$._resizeCanvas = (w, h) => {
|
|
@@ -632,7 +639,7 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
632
639
|
}
|
|
633
640
|
if (c.a <= 0) return ($._doFill = false);
|
|
634
641
|
}
|
|
635
|
-
$.ctx.fillStyle = c.toString();
|
|
642
|
+
$.ctx.fillStyle = $._fill = c.toString();
|
|
636
643
|
};
|
|
637
644
|
$.noFill = () => ($._doFill = false);
|
|
638
645
|
$.stroke = function (c) {
|
|
@@ -645,24 +652,17 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
645
652
|
}
|
|
646
653
|
if (c.a <= 0) return ($._doStroke = false);
|
|
647
654
|
}
|
|
648
|
-
$.ctx.strokeStyle = c.toString();
|
|
655
|
+
$.ctx.strokeStyle = $._stroke = c.toString();
|
|
649
656
|
};
|
|
650
657
|
$.strokeWeight = (n) => {
|
|
651
658
|
if (!n) $._doStroke = false;
|
|
652
659
|
if ($._da) n *= $._da;
|
|
653
|
-
$.ctx.lineWidth = n || 0.0001;
|
|
660
|
+
$.ctx.lineWidth = $._strokeWeight = n || 0.0001;
|
|
654
661
|
};
|
|
655
662
|
$.noStroke = () => ($._doStroke = false);
|
|
656
663
|
|
|
657
664
|
$.opacity = (a) => ($.ctx.globalAlpha = a);
|
|
658
665
|
|
|
659
|
-
$.clear = () => {
|
|
660
|
-
$.ctx.save();
|
|
661
|
-
$.ctx.resetTransform();
|
|
662
|
-
$.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
|
|
663
|
-
$.ctx.restore();
|
|
664
|
-
};
|
|
665
|
-
|
|
666
666
|
// DRAWING MATRIX
|
|
667
667
|
|
|
668
668
|
$.translate = (x, y) => {
|
|
@@ -1422,11 +1422,23 @@ Q5.DILATE = 6;
|
|
|
1422
1422
|
Q5.ERODE = 7;
|
|
1423
1423
|
Q5.BLUR = 8;
|
|
1424
1424
|
Q5.renderers.q2d.text = ($, q) => {
|
|
1425
|
-
$.
|
|
1426
|
-
$.
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1425
|
+
$._textAlign = 'left';
|
|
1426
|
+
$._textBaseline = 'alphabetic';
|
|
1427
|
+
|
|
1428
|
+
let font = 'sans-serif',
|
|
1429
|
+
tSize = 12,
|
|
1430
|
+
leading = 15,
|
|
1431
|
+
leadDiff = 3,
|
|
1432
|
+
emphasis = 'normal',
|
|
1433
|
+
fontMod = false,
|
|
1434
|
+
styleHash = 0,
|
|
1435
|
+
styleHashes = [],
|
|
1436
|
+
useCache = false,
|
|
1437
|
+
genTextImage = false,
|
|
1438
|
+
cacheSize = 0,
|
|
1439
|
+
cacheMax = 12000;
|
|
1440
|
+
|
|
1441
|
+
let cache = ($._textCache = {});
|
|
1430
1442
|
|
|
1431
1443
|
$.loadFont = (url, cb) => {
|
|
1432
1444
|
q._preloadCount++;
|
|
@@ -1439,156 +1451,162 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
1439
1451
|
});
|
|
1440
1452
|
return name;
|
|
1441
1453
|
};
|
|
1442
|
-
|
|
1454
|
+
|
|
1455
|
+
$.textFont = (x) => {
|
|
1456
|
+
font = x;
|
|
1457
|
+
fontMod = true;
|
|
1458
|
+
styleHash = -1;
|
|
1459
|
+
};
|
|
1443
1460
|
$.textSize = (x) => {
|
|
1444
|
-
if (x === undefined) return
|
|
1461
|
+
if (x === undefined) return tSize;
|
|
1445
1462
|
if ($._da) x *= $._da;
|
|
1446
|
-
|
|
1463
|
+
tSize = x;
|
|
1464
|
+
fontMod = true;
|
|
1465
|
+
styleHash = -1;
|
|
1447
1466
|
if (!$._leadingSet) {
|
|
1448
|
-
|
|
1449
|
-
|
|
1467
|
+
leading = x * 1.25;
|
|
1468
|
+
leadDiff = leading - x;
|
|
1450
1469
|
}
|
|
1451
1470
|
};
|
|
1471
|
+
$.textStyle = (x) => {
|
|
1472
|
+
emphasis = x;
|
|
1473
|
+
fontMod = true;
|
|
1474
|
+
styleHash = -1;
|
|
1475
|
+
};
|
|
1452
1476
|
$.textLeading = (x) => {
|
|
1453
|
-
if (x === undefined) return
|
|
1477
|
+
if (x === undefined) return leading;
|
|
1454
1478
|
if ($._da) x *= $._da;
|
|
1455
|
-
|
|
1456
|
-
|
|
1479
|
+
leading = x;
|
|
1480
|
+
leadDiff = x - tSize;
|
|
1457
1481
|
$._leadingSet = true;
|
|
1482
|
+
styleHash = -1;
|
|
1458
1483
|
};
|
|
1459
|
-
$.textStyle = (x) => ($._textStyle = x);
|
|
1460
1484
|
$.textAlign = (horiz, vert) => {
|
|
1461
|
-
$.ctx.textAlign = horiz;
|
|
1485
|
+
$.ctx.textAlign = $._textAlign = horiz;
|
|
1462
1486
|
if (vert) {
|
|
1463
|
-
$.ctx.textBaseline = vert == $.CENTER ? 'middle' : vert;
|
|
1487
|
+
$.ctx.textBaseline = $._textBaseline = vert == $.CENTER ? 'middle' : vert;
|
|
1464
1488
|
}
|
|
1489
|
+
styleHash = -1;
|
|
1465
1490
|
};
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
$.ctx.font = `${$._textStyle} ${$._textSize}px ${$._textFont}`;
|
|
1472
|
-
return $.ctx.measureText(str).actualBoundingBoxAscent;
|
|
1473
|
-
};
|
|
1474
|
-
$.textDescent = (str) => {
|
|
1475
|
-
$.ctx.font = `${$._textStyle} ${$._textSize}px ${$._textFont}`;
|
|
1476
|
-
return $.ctx.measureText(str).actualBoundingBoxDescent;
|
|
1477
|
-
};
|
|
1491
|
+
|
|
1492
|
+
$.textWidth = (str) => $.ctx.measureText(str).width;
|
|
1493
|
+
$.textAscent = (str) => $.ctx.measureText(str).actualBoundingBoxAscent;
|
|
1494
|
+
$.textDescent = (str) => $.ctx.measureText(str).actualBoundingBoxDescent;
|
|
1495
|
+
|
|
1478
1496
|
$.textFill = $.fill;
|
|
1479
1497
|
$.textStroke = $.stroke;
|
|
1480
1498
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
set(k, v) {
|
|
1488
|
-
v.lastAccessed = Date.now();
|
|
1489
|
-
super.set(k, v);
|
|
1490
|
-
if (this.size > this.maxSize) this.gc();
|
|
1491
|
-
}
|
|
1492
|
-
get(k) {
|
|
1493
|
-
const v = super.get(k);
|
|
1494
|
-
if (v) v.lastAccessed = Date.now();
|
|
1495
|
-
return v;
|
|
1496
|
-
}
|
|
1497
|
-
gc() {
|
|
1498
|
-
let t = Infinity;
|
|
1499
|
-
let oldest;
|
|
1500
|
-
let i = 0;
|
|
1501
|
-
for (const [k, v] of this.entries()) {
|
|
1502
|
-
if (v.lastAccessed < t) {
|
|
1503
|
-
t = v.lastAccessed;
|
|
1504
|
-
oldest = i;
|
|
1505
|
-
}
|
|
1506
|
-
i++;
|
|
1507
|
-
}
|
|
1508
|
-
i = oldest;
|
|
1509
|
-
for (const k of this.keys()) {
|
|
1510
|
-
if (i == 0) {
|
|
1511
|
-
oldest = k;
|
|
1512
|
-
break;
|
|
1513
|
-
}
|
|
1514
|
-
i--;
|
|
1515
|
-
}
|
|
1516
|
-
this.delete(oldest);
|
|
1499
|
+
let updateStyleHash = () => {
|
|
1500
|
+
let styleString = font + tSize + emphasis + leading;
|
|
1501
|
+
|
|
1502
|
+
let hash = 5381;
|
|
1503
|
+
for (let i = 0; i < styleString.length; i++) {
|
|
1504
|
+
hash = (hash * 33) ^ styleString.charCodeAt(i);
|
|
1517
1505
|
}
|
|
1506
|
+
styleHash = hash >>> 0;
|
|
1518
1507
|
};
|
|
1519
|
-
|
|
1520
|
-
$.textCache = (
|
|
1521
|
-
if (maxSize)
|
|
1522
|
-
if (
|
|
1523
|
-
return
|
|
1524
|
-
};
|
|
1525
|
-
$._genTextImageKey = (str, w, h) => {
|
|
1526
|
-
return (
|
|
1527
|
-
str.slice(0, 200) +
|
|
1528
|
-
$._textStyle +
|
|
1529
|
-
$._textSize +
|
|
1530
|
-
$._textFont +
|
|
1531
|
-
($._doFill ? $.ctx.fillStyle : '') +
|
|
1532
|
-
'_' +
|
|
1533
|
-
($._doStroke && $._strokeSet ? $.ctx.lineWidth + $.ctx.strokeStyle + '_' : '') +
|
|
1534
|
-
(w || '') +
|
|
1535
|
-
(h ? 'x' + h : '')
|
|
1536
|
-
);
|
|
1508
|
+
|
|
1509
|
+
$.textCache = (enable, maxSize) => {
|
|
1510
|
+
if (maxSize) cacheMax = maxSize;
|
|
1511
|
+
if (enable !== undefined) useCache = enable;
|
|
1512
|
+
return useCache;
|
|
1537
1513
|
};
|
|
1538
1514
|
$.createTextImage = (str, w, h) => {
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
$._textCache = true;
|
|
1544
|
-
$._genTextImage = true;
|
|
1545
|
-
$.text(str, 0, 0, w, h);
|
|
1546
|
-
$._genTextImage = false;
|
|
1547
|
-
$._textCache = og;
|
|
1548
|
-
return $._tic.get(k);
|
|
1515
|
+
genTextImage = true;
|
|
1516
|
+
img = $.text(str, 0, 0, w, h);
|
|
1517
|
+
genTextImage = false;
|
|
1518
|
+
return img;
|
|
1549
1519
|
};
|
|
1520
|
+
|
|
1521
|
+
let lines = [];
|
|
1550
1522
|
$.text = (str, x, y, w, h) => {
|
|
1551
1523
|
if (str === undefined || (!$._doFill && !$._doStroke)) return;
|
|
1552
1524
|
str = str.toString();
|
|
1553
|
-
let lines = str.split('\n');
|
|
1554
1525
|
if ($._da) {
|
|
1555
1526
|
x *= $._da;
|
|
1556
1527
|
y *= $._da;
|
|
1557
1528
|
}
|
|
1558
1529
|
let ctx = $.ctx;
|
|
1559
|
-
|
|
1530
|
+
let img, tX, tY;
|
|
1560
1531
|
|
|
1561
|
-
|
|
1532
|
+
if (fontMod) {
|
|
1533
|
+
ctx.font = `${emphasis} ${tSize}px ${font}`;
|
|
1534
|
+
fontMod = false;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
if (useCache || genTextImage) {
|
|
1538
|
+
if (styleHash == -1) updateStyleHash();
|
|
1562
1539
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1540
|
+
img = cache[str];
|
|
1541
|
+
if (img) img = img[styleHash];
|
|
1542
|
+
|
|
1543
|
+
if (img) {
|
|
1544
|
+
if (img._fill == $._fill && img._stroke == $._stroke && img._strokeWeight == $._strokeWeight) {
|
|
1545
|
+
if (genTextImage) return img;
|
|
1546
|
+
return $.textImage(img, x, y);
|
|
1547
|
+
} else img.clear();
|
|
1548
|
+
}
|
|
1566
1549
|
}
|
|
1567
1550
|
|
|
1568
|
-
if (
|
|
1551
|
+
if (str.indexOf('\n') == -1) lines[0] = str;
|
|
1552
|
+
else lines = str.split('\n');
|
|
1553
|
+
|
|
1554
|
+
if (w) {
|
|
1555
|
+
let wrapped = [];
|
|
1556
|
+
for (let line of lines) {
|
|
1557
|
+
let i = 0;
|
|
1558
|
+
|
|
1559
|
+
while (i < line.length) {
|
|
1560
|
+
let max = i + w;
|
|
1561
|
+
if (max >= line.length) {
|
|
1562
|
+
wrapped.push(line.slice(i));
|
|
1563
|
+
break;
|
|
1564
|
+
}
|
|
1565
|
+
let end = line.lastIndexOf(' ', max);
|
|
1566
|
+
if (end === -1 || end < i) {
|
|
1567
|
+
end = max;
|
|
1568
|
+
}
|
|
1569
|
+
wrapped.push(line.slice(i, end));
|
|
1570
|
+
i = end;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
lines = wrapped;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
if (!useCache && !genTextImage) {
|
|
1569
1577
|
tX = x;
|
|
1570
1578
|
tY = y;
|
|
1571
1579
|
} else {
|
|
1572
|
-
cacheKey = $._genTextImageKey(str, w, h);
|
|
1573
|
-
img = $._tic.get(cacheKey);
|
|
1574
|
-
if (img && !$._genTextImage) return $.textImage(img, x, y);
|
|
1575
|
-
|
|
1576
1580
|
tX = 0;
|
|
1577
|
-
tY =
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1581
|
+
tY = leading * lines.length;
|
|
1582
|
+
|
|
1583
|
+
if (!img) {
|
|
1584
|
+
let measure = ctx.measureText(' ');
|
|
1585
|
+
let ascent = measure.fontBoundingBoxAscent;
|
|
1586
|
+
let descent = measure.fontBoundingBoxDescent;
|
|
1587
|
+
h ??= tY + descent;
|
|
1588
|
+
|
|
1589
|
+
img = $.createImage.call($, Math.ceil(ctx.measureText(str).width), Math.ceil(h), {
|
|
1590
|
+
pixelDensity: $._pixelDensity
|
|
1591
|
+
});
|
|
1592
|
+
|
|
1593
|
+
img._ascent = ascent;
|
|
1594
|
+
img._descent = descent;
|
|
1595
|
+
img._top = descent + leadDiff;
|
|
1596
|
+
img._middle = img._top + ascent * 0.5;
|
|
1597
|
+
img._bottom = img._top + ascent;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
img._fill = $._fill;
|
|
1601
|
+
img._stroke = $._stroke;
|
|
1602
|
+
img._strokeWeight = $._strokeWeight;
|
|
1603
|
+
img.modified = true;
|
|
1586
1604
|
|
|
1587
1605
|
ctx = img.ctx;
|
|
1588
1606
|
|
|
1589
1607
|
ctx.font = $.ctx.font;
|
|
1590
|
-
ctx.fillStyle = $.
|
|
1591
|
-
ctx.strokeStyle = $.
|
|
1608
|
+
ctx.fillStyle = $._fill;
|
|
1609
|
+
ctx.strokeStyle = $._stroke;
|
|
1592
1610
|
ctx.lineWidth = $.ctx.lineWidth;
|
|
1593
1611
|
}
|
|
1594
1612
|
|
|
@@ -1598,31 +1616,49 @@ Q5.renderers.q2d.text = ($, q) => {
|
|
|
1598
1616
|
ctx.fillStyle = 'black';
|
|
1599
1617
|
}
|
|
1600
1618
|
|
|
1601
|
-
for (let
|
|
1602
|
-
if ($._doStroke && $._strokeSet) ctx.strokeText(
|
|
1603
|
-
if ($._doFill) ctx.fillText(
|
|
1604
|
-
tY +=
|
|
1619
|
+
for (let line of lines) {
|
|
1620
|
+
if ($._doStroke && $._strokeSet) ctx.strokeText(line, tX, tY);
|
|
1621
|
+
if ($._doFill) ctx.fillText(line, tX, tY);
|
|
1622
|
+
tY += leading;
|
|
1605
1623
|
if (tY > h) break;
|
|
1606
1624
|
}
|
|
1625
|
+
lines.length = 0;
|
|
1607
1626
|
|
|
1608
1627
|
if (!$._fillSet) ctx.fillStyle = ogFill;
|
|
1609
1628
|
|
|
1610
|
-
if (useCache) {
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1629
|
+
if (useCache || genTextImage) {
|
|
1630
|
+
styleHashes.push(styleHash);
|
|
1631
|
+
(cache[str] ??= {})[styleHash] = img;
|
|
1632
|
+
|
|
1633
|
+
cacheSize++;
|
|
1634
|
+
if (cacheSize > cacheMax) {
|
|
1635
|
+
let half = Math.ceil(cacheSize / 2);
|
|
1636
|
+
let hashes = styleHashes.splice(0, half);
|
|
1637
|
+
for (let s in cache) {
|
|
1638
|
+
s = cache[s];
|
|
1639
|
+
for (let h of hashes) delete s[h];
|
|
1640
|
+
}
|
|
1641
|
+
cacheSize -= half;
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
if (genTextImage) return img;
|
|
1645
|
+
$.textImage(img, x, y);
|
|
1615
1646
|
}
|
|
1616
1647
|
};
|
|
1617
1648
|
$.textImage = (img, x, y) => {
|
|
1618
1649
|
let og = $._imageMode;
|
|
1619
1650
|
$._imageMode = 'corner';
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
if (
|
|
1623
|
-
if (
|
|
1624
|
-
|
|
1625
|
-
|
|
1651
|
+
|
|
1652
|
+
let ta = $._textAlign;
|
|
1653
|
+
if (ta == 'center') x -= img.canvas.hw;
|
|
1654
|
+
else if (ta == 'right') x -= img.width;
|
|
1655
|
+
|
|
1656
|
+
let bl = $._textBaseline;
|
|
1657
|
+
if (bl == 'alphabetic') y -= leading;
|
|
1658
|
+
else if (bl == 'middle') y -= img._middle;
|
|
1659
|
+
else if (bl == 'bottom') y -= img._bottom;
|
|
1660
|
+
else if (bl == 'top') y -= img._top;
|
|
1661
|
+
|
|
1626
1662
|
$.image(img, x, y);
|
|
1627
1663
|
$._imageMode = og;
|
|
1628
1664
|
};
|
|
@@ -3064,8 +3100,8 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3064
3100
|
$._createCanvas = (w, h, opt) => {
|
|
3065
3101
|
q.ctx = q.drawingContext = c.getContext('webgpu');
|
|
3066
3102
|
|
|
3067
|
-
opt.format
|
|
3068
|
-
opt.device
|
|
3103
|
+
opt.format ??= navigator.gpu.getPreferredCanvasFormat();
|
|
3104
|
+
opt.device ??= Q5.device;
|
|
3069
3105
|
|
|
3070
3106
|
$.ctx.configure(opt);
|
|
3071
3107
|
|
|
@@ -3928,20 +3964,30 @@ fn fragmentMain(@location(0) texCoord: vec2<f32>) -> @location(0) vec4<f32> {
|
|
|
3928
3964
|
minFilter: 'linear'
|
|
3929
3965
|
});
|
|
3930
3966
|
|
|
3967
|
+
let MAX_TEXTURES = 12000;
|
|
3968
|
+
|
|
3969
|
+
$._textures = [];
|
|
3970
|
+
let tIdx = 0;
|
|
3971
|
+
|
|
3931
3972
|
$._createTexture = (img) => {
|
|
3932
3973
|
if (img.canvas) img = img.canvas;
|
|
3933
3974
|
|
|
3934
3975
|
let textureSize = [img.width, img.height, 1];
|
|
3935
3976
|
|
|
3936
|
-
|
|
3977
|
+
let texture = Q5.device.createTexture({
|
|
3937
3978
|
size: textureSize,
|
|
3938
3979
|
format: 'bgra8unorm',
|
|
3939
3980
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
|
|
3940
3981
|
});
|
|
3941
3982
|
|
|
3942
|
-
Q5.device.queue.copyExternalImageToTexture(
|
|
3983
|
+
Q5.device.queue.copyExternalImageToTexture(
|
|
3984
|
+
{ source: img },
|
|
3985
|
+
{ texture, colorSpace: $.canvas.colorSpace },
|
|
3986
|
+
textureSize
|
|
3987
|
+
);
|
|
3943
3988
|
|
|
3944
|
-
|
|
3989
|
+
$._textures[tIdx] = texture;
|
|
3990
|
+
img.textureIndex = tIdx;
|
|
3945
3991
|
|
|
3946
3992
|
const textureBindGroup = Q5.device.createBindGroup({
|
|
3947
3993
|
layout: textureLayout,
|
|
@@ -3950,7 +3996,16 @@ fn fragmentMain(@location(0) texCoord: vec2<f32>) -> @location(0) vec4<f32> {
|
|
|
3950
3996
|
{ binding: 1, resource: texture.createView() }
|
|
3951
3997
|
]
|
|
3952
3998
|
});
|
|
3953
|
-
$._textureBindGroups
|
|
3999
|
+
$._textureBindGroups[tIdx] = textureBindGroup;
|
|
4000
|
+
|
|
4001
|
+
tIdx = (tIdx + 1) % MAX_TEXTURES;
|
|
4002
|
+
|
|
4003
|
+
// If the texture array is full, destroy the oldest texture
|
|
4004
|
+
if ($._textures[tIdx]) {
|
|
4005
|
+
$._textures[tIdx].destroy();
|
|
4006
|
+
delete $._textures[tIdx];
|
|
4007
|
+
delete $._textureBindGroups[tIdx];
|
|
4008
|
+
}
|
|
3954
4009
|
};
|
|
3955
4010
|
|
|
3956
4011
|
$.loadImage = $.loadTexture = (src) => {
|
|
@@ -4034,6 +4089,8 @@ Q5.renderers.webgpu.text = ($, q) => {
|
|
|
4034
4089
|
q._preloadCount--;
|
|
4035
4090
|
});
|
|
4036
4091
|
};
|
|
4092
|
+
|
|
4093
|
+
// directly add these text setting functions to the webgpu renderer
|
|
4037
4094
|
$.textFont = t.textFont;
|
|
4038
4095
|
$.textSize = t.textSize;
|
|
4039
4096
|
$.textLeading = t.textLeading;
|
|
@@ -4049,7 +4106,20 @@ Q5.renderers.webgpu.text = ($, q) => {
|
|
|
4049
4106
|
$.text = (str, x, y, w, h) => {
|
|
4050
4107
|
let img = t.createTextImage(str, w, h);
|
|
4051
4108
|
|
|
4052
|
-
if (img.canvas.textureIndex
|
|
4109
|
+
if (img.canvas.textureIndex === undefined) {
|
|
4110
|
+
$._createTexture(img);
|
|
4111
|
+
} else if (img.modified) {
|
|
4112
|
+
let cnv = img.canvas;
|
|
4113
|
+
let textureSize = [cnv.width, cnv.height, 1];
|
|
4114
|
+
let texture = $._textures[cnv.textureIndex];
|
|
4115
|
+
|
|
4116
|
+
Q5.device.queue.copyExternalImageToTexture(
|
|
4117
|
+
{ source: cnv },
|
|
4118
|
+
{ texture, colorSpace: $.canvas.colorSpace },
|
|
4119
|
+
textureSize
|
|
4120
|
+
);
|
|
4121
|
+
img.modified = false;
|
|
4122
|
+
}
|
|
4053
4123
|
|
|
4054
4124
|
$.textImage(img, x, y);
|
|
4055
4125
|
};
|
|
@@ -4057,12 +4127,20 @@ Q5.renderers.webgpu.text = ($, q) => {
|
|
|
4057
4127
|
$.createTextImage = t.createTextImage;
|
|
4058
4128
|
|
|
4059
4129
|
$.textImage = (img, x, y) => {
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
else if (
|
|
4130
|
+
let og = $._imageMode;
|
|
4131
|
+
$._imageMode = 'corner';
|
|
4132
|
+
|
|
4133
|
+
let ta = t._textAlign;
|
|
4134
|
+
if (ta == 'center') x -= img.canvas.hw;
|
|
4135
|
+
else if (ta == 'right') x -= img.width;
|
|
4136
|
+
|
|
4137
|
+
let bl = t._textBaseline;
|
|
4138
|
+
if (bl == 'alphabetic') y -= t._textLeading;
|
|
4139
|
+
else if (bl == 'middle') y -= img._middle;
|
|
4140
|
+
else if (bl == 'bottom') y -= img._bottom;
|
|
4141
|
+
else if (bl == 'top') y -= img._top;
|
|
4142
|
+
|
|
4066
4143
|
$.image(img, x, y);
|
|
4144
|
+
$._imageMode = og;
|
|
4067
4145
|
};
|
|
4068
4146
|
};
|