q5 2.7.6 → 2.9.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/q5.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * q5.js
3
- * @version 2.7
3
+ * @version 2.9
4
4
  * @author quinton-ashley, Tezumie, and LingDong-
5
5
  * @license LGPL-3.0
6
6
  * @class Q5
@@ -290,6 +290,13 @@ if (Q5._nodejs) global.p5 ??= global.Q5 = Q5;
290
290
  else if (typeof window == 'object') window.p5 ??= window.Q5 = Q5;
291
291
  else global.window = 0;
292
292
 
293
+ function createCanvas(w, h, opt) {
294
+ if (!Q5._hasGlobal) {
295
+ let q = new Q5();
296
+ q.createCanvas(w, h, opt);
297
+ }
298
+ }
299
+
293
300
  if (typeof document == 'object') {
294
301
  document.addEventListener('DOMContentLoaded', () => {
295
302
  if (!Q5._hasGlobal) new Q5('auto');
@@ -486,6 +493,8 @@ Q5.modules.canvas = ($, q) => {
486
493
  c.h = h = Math.ceil(h);
487
494
  c.hw = w / 2;
488
495
  c.hh = h / 2;
496
+
497
+ // changes the actual size of the canvas
489
498
  c.width = Math.ceil(w * $._pixelDensity);
490
499
  c.height = Math.ceil(h * $._pixelDensity);
491
500
 
@@ -498,6 +507,17 @@ Q5.modules.canvas = ($, q) => {
498
507
  else $._adjustDisplay();
499
508
  };
500
509
 
510
+ $._setImageSize = (w, h) => {
511
+ q.width = c.w = w;
512
+ q.height = c.h = h;
513
+ c.hw = w / 2;
514
+ c.hh = h / 2;
515
+
516
+ // changes the actual size of the canvas
517
+ c.width = Math.ceil(w * $._pixelDensity);
518
+ c.height = Math.ceil(h * $._pixelDensity);
519
+ };
520
+
501
521
  if ($._scope == 'image') return;
502
522
 
503
523
  if (c && $._scope != 'graphics') {
@@ -552,6 +572,12 @@ Q5.modules.canvas = ($, q) => {
552
572
  return v;
553
573
  };
554
574
 
575
+ $.defaultImageScale = (scale) => {
576
+ if (!scale) return $._defaultImageScale;
577
+ return ($._defaultImageScale = scale);
578
+ };
579
+ $.defaultImageScale(0.5);
580
+
555
581
  $.flexibleCanvas = (unit = 400) => {
556
582
  if (unit) {
557
583
  $._da = c.width / (unit * $._pixelDensity);
@@ -705,6 +731,10 @@ Q5.renderers.q2d.canvas = ($, q) => {
705
731
  $.ctx.rotate(r);
706
732
  };
707
733
  $.scale = (x, y) => {
734
+ if (x.x) {
735
+ y = x.y;
736
+ x = x.x;
737
+ }
708
738
  y ??= x;
709
739
  $.ctx.scale(x, y);
710
740
  };
@@ -712,8 +742,10 @@ Q5.renderers.q2d.canvas = ($, q) => {
712
742
  $.shearX = (ang) => $.ctx.transform(1, 0, $.tan(ang), 1, 0, 0);
713
743
  $.shearY = (ang) => $.ctx.transform(1, $.tan(ang), 0, 1, 0, 0);
714
744
  $.resetMatrix = () => {
715
- $.ctx.resetTransform();
716
- $.scale($._pixelDensity);
745
+ if ($.ctx) {
746
+ $.ctx.resetTransform();
747
+ $.scale($._pixelDensity);
748
+ }
717
749
  };
718
750
 
719
751
  $.pushMatrix = () => $.ctx.save();
@@ -776,6 +808,7 @@ Q5.renderers.q2d.drawing = ($) => {
776
808
  $.background = function (c) {
777
809
  $.ctx.save();
778
810
  $.ctx.resetTransform();
811
+ $.ctx.globalAlpha = 1;
779
812
  if (c.canvas) $.image(c, 0, 0, $.canvas.width, $.canvas.height);
780
813
  else {
781
814
  if (Q5.Color && !c._q5Color) {
@@ -888,20 +921,20 @@ Q5.renderers.q2d.drawing = ($) => {
888
921
  } else $.ellipse(x, y, d, d);
889
922
  };
890
923
  $.point = (x, y) => {
891
- if (x.x) {
892
- y = x.y;
893
- x = x.x;
894
- }
895
- if ($._da) {
896
- x *= $._da;
897
- y *= $._da;
924
+ if ($._doStroke) {
925
+ if (x.x) {
926
+ y = x.y;
927
+ x = x.x;
928
+ }
929
+ if ($._da) {
930
+ x *= $._da;
931
+ y *= $._da;
932
+ }
933
+ $.ctx.beginPath();
934
+ $.ctx.moveTo(x, y);
935
+ $.ctx.lineTo(x, y);
936
+ $.ctx.stroke();
898
937
  }
899
- $.ctx.save();
900
- $.ctx.beginPath();
901
- $.ctx.arc(x, y, $.ctx.lineWidth / 2, 0, $.TAU);
902
- $.ctx.fillStyle = $.ctx.strokeStyle;
903
- $.ctx.fill();
904
- $.ctx.restore();
905
938
  };
906
939
  function rect(x, y, w, h) {
907
940
  if ($._da) {
@@ -1218,9 +1251,15 @@ Q5.renderers.q2d.image = ($, q) => {
1218
1251
  opt = typeof last == 'object' ? last : null;
1219
1252
 
1220
1253
  let g = $.createImage(1, 1, opt);
1254
+ let pd = (g._pixelDensity = opt?.pixelDensity || 1);
1221
1255
 
1222
1256
  function loaded(img) {
1223
- g.resize(img.naturalWidth || img.width, img.naturalHeight || img.height);
1257
+ g.canvas.defaultWidth = img.width * $._defaultImageScale;
1258
+ g.canvas.defaultHeight = img.height * $._defaultImageScale;
1259
+ g.naturalWidth = img.naturalWidth;
1260
+ g.naturalHeight = img.naturalHeight;
1261
+ g._setImageSize(Math.ceil(g.naturalWidth / pd), Math.ceil(g.naturalHeight / pd));
1262
+
1224
1263
  g.ctx.drawImage(img, 0, 0);
1225
1264
  q._preloadCount--;
1226
1265
  if (cb) cb(g);
@@ -1237,7 +1276,7 @@ Q5.renderers.q2d.image = ($, q) => {
1237
1276
  let img = new window.Image();
1238
1277
  img.src = url;
1239
1278
  img.crossOrigin = 'Anonymous';
1240
- img._pixelDensity = 1;
1279
+ img._pixelDensity = pd;
1241
1280
  img.onload = () => loaded(img);
1242
1281
  img.onerror = (e) => {
1243
1282
  q._preloadCount--;
@@ -1254,8 +1293,9 @@ Q5.renderers.q2d.image = ($, q) => {
1254
1293
  if (Q5._createNodeJSCanvas) {
1255
1294
  drawable = drawable.context.canvas;
1256
1295
  }
1257
- dw ??= img.width || img.videoWidth;
1258
- dh ??= img.height || img.videoHeight;
1296
+
1297
+ dw ??= drawable.defaultWidth || drawable.width || img.videoWidth;
1298
+ dh ??= drawable.defaultHeight || drawable.height || img.videoHeight;
1259
1299
  if ($._imageMode == 'center') {
1260
1300
  dx -= dw * 0.5;
1261
1301
  dy -= dh * 0.5;
@@ -1316,15 +1356,16 @@ Q5.renderers.q2d.image = ($, q) => {
1316
1356
 
1317
1357
  if ($._scope == 'image') {
1318
1358
  $.resize = (w, h) => {
1319
- let o = new $._OffscreenCanvas($.canvas.width, $.canvas.height);
1359
+ let c = $.canvas;
1360
+ let o = new $._OffscreenCanvas(c.width, c.height);
1320
1361
  let tmpCtx = o.getContext('2d', {
1321
- colorSpace: $.canvas.colorSpace
1362
+ colorSpace: c.colorSpace
1322
1363
  });
1323
- tmpCtx.drawImage($.canvas, 0, 0);
1324
- $._setCanvasSize(w, h);
1364
+ tmpCtx.drawImage(c, 0, 0);
1365
+ $._setImageSize(w, h);
1325
1366
 
1326
- $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
1327
- $.ctx.drawImage(o, 0, 0, $.canvas.width, $.canvas.height);
1367
+ $.ctx.clearRect(0, 0, c.width, c.height);
1368
+ $.ctx.drawImage(o, 0, 0, c.width, c.height);
1328
1369
  };
1329
1370
  }
1330
1371
 
@@ -1721,8 +1762,9 @@ Q5.modules.ai = ($) => {
1721
1762
  }
1722
1763
  while (stackLines[idx].indexOf('q5') >= 0) idx++;
1723
1764
 
1724
- let parts = stackLines[idx].split(sep).at(-1);
1725
- parts = parts.split(':');
1765
+ let errFile = stackLines[idx].split(sep).at(-1);
1766
+ if (errFile.startsWith('blob:')) errFile = errFile.slice(5);
1767
+ let parts = errFile.split(':');
1726
1768
  let lineNum = parseInt(parts.at(-2));
1727
1769
  if (askAI) lineNum++;
1728
1770
  parts[3] = parts[3].split(')')[0];
@@ -2085,7 +2127,7 @@ main {
2085
2127
  if ($.noSmooth) $.noSmooth();
2086
2128
  if ($.textFont) $.textFont('monospace');
2087
2129
  }
2088
- if (c.displayMode == 'normal') {
2130
+ if (c.displayMode == 'default' || c.displayMode == 'normal') {
2089
2131
  p.classList.remove('q5-centered', 'q5-maxed', 'q5-fullscreen');
2090
2132
  s.width = c.w * c.displayScale + 'px';
2091
2133
  s.height = c.h * c.displayScale + 'px';
@@ -2110,7 +2152,7 @@ main {
2110
2152
  }
2111
2153
  };
2112
2154
 
2113
- $.displayMode = (displayMode = 'normal', renderQuality = 'default', displayScale = 1) => {
2155
+ $.displayMode = (displayMode = 'normal', renderQuality = 'smooth', displayScale = 1) => {
2114
2156
  if (typeof displayScale == 'string') {
2115
2157
  displayScale = parseFloat(displayScale.slice(1));
2116
2158
  }
@@ -2313,7 +2355,7 @@ Q5.modules.math = ($, q) => {
2313
2355
  $.abs = Math.abs;
2314
2356
  $.ceil = Math.ceil;
2315
2357
  $.exp = Math.exp;
2316
- $.floor = Math.floor;
2358
+ $.floor = $.int = Math.floor;
2317
2359
  $.loge = Math.log;
2318
2360
  $.mag = Math.hypot;
2319
2361
  $.max = Math.max;
@@ -3590,8 +3632,8 @@ Q5.renderers.webgpu.canvas = ($, q) => {
3590
3632
  // v is the texture index
3591
3633
  pass.setBindGroup(2, $._textureBindGroups[v]);
3592
3634
  }
3593
- pass.draw(6, 1, imageVertOffset);
3594
- imageVertOffset += 6;
3635
+ pass.draw(4, 1, imageVertOffset);
3636
+ imageVertOffset += 4;
3595
3637
  } else if (curPipelineIndex == 2) {
3596
3638
  let o = drawStack[i + 2];
3597
3639
  pass.setBindGroup(2, $._fonts[o].bindGroup);
@@ -3746,29 +3788,6 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
3746
3788
  vertIndex = i;
3747
3789
  };
3748
3790
 
3749
- const addTri = (x1, y1, x2, y2, x3, y3, ci, ti) => {
3750
- let v = vertexStack,
3751
- i = vertIndex;
3752
-
3753
- v[i++] = x1;
3754
- v[i++] = y1;
3755
- v[i++] = ci;
3756
- v[i++] = ti;
3757
-
3758
- v[i++] = x2;
3759
- v[i++] = y2;
3760
- v[i++] = ci;
3761
- v[i++] = ti;
3762
-
3763
- v[i++] = x3;
3764
- v[i++] = y3;
3765
- v[i++] = ci;
3766
- v[i++] = ti;
3767
-
3768
- vertIndex = i;
3769
- drawStack.push(0, 3);
3770
- };
3771
-
3772
3791
  const addRect = (x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) => {
3773
3792
  let v = vertexStack,
3774
3793
  i = vertIndex;
@@ -3852,21 +3871,40 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
3852
3871
  if ($._doStroke) {
3853
3872
  ci = $._strokeIndex;
3854
3873
 
3855
- // outer rectangle coordinates
3874
+ // stroke weight adjustment
3856
3875
  let sw = $._strokeWeight / 2;
3857
- let to = t + sw,
3858
- bo = b - sw,
3859
- lo = l - sw,
3860
- ro = r + sw;
3861
-
3862
- // stroke is simply a bigger rectangle drawn first
3863
- addRect(lo, to, ro, to, ro, bo, lo, bo, ci, ti);
3864
3876
 
3865
- // inner rectangle coordinates
3866
- t -= sw;
3867
- b += sw;
3868
- l += sw;
3869
- r -= sw;
3877
+ if ($._doFill) {
3878
+ // existing behavior: draw stroke as one big rectangle
3879
+ let to = t + sw,
3880
+ bo = b - sw,
3881
+ lo = l - sw,
3882
+ ro = r + sw;
3883
+
3884
+ // draw stroke rectangle
3885
+ addRect(lo, to, ro, to, ro, bo, lo, bo, ci, ti);
3886
+
3887
+ // adjust inner rectangle coordinates
3888
+ t -= sw;
3889
+ b += sw;
3890
+ l += sw;
3891
+ r -= sw;
3892
+ } else {
3893
+ // new behavior: draw stroke as four rectangles (sides)
3894
+ let lsw = l - sw,
3895
+ rsw = r + sw,
3896
+ tsw = t + sw,
3897
+ bsw = b - sw,
3898
+ lpsw = l + sw,
3899
+ rpsw = r - sw,
3900
+ tpsw = t - sw,
3901
+ bpsw = b + sw;
3902
+
3903
+ addRect(lsw, tpsw, rsw, tpsw, rsw, tsw, lsw, tsw, ci, ti); // top
3904
+ addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // bottom
3905
+ addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // left
3906
+ addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // right
3907
+ }
3870
3908
  }
3871
3909
 
3872
3910
  if ($._doFill) {
@@ -4041,11 +4079,16 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
4041
4079
  $.vertex(x1, y1);
4042
4080
  $.vertex(x2, y2);
4043
4081
  $.vertex(x3, y3);
4044
- $.endShape();
4082
+ $.endShape(true);
4045
4083
  };
4046
4084
 
4047
4085
  $.quad = (x1, y1, x2, y2, x3, y3, x4, y4) => {
4048
- addRect(x1, y1, x2, y2, x3, y3, x4, y4, $._fillIndex, $._transformIndex);
4086
+ $.beginShape();
4087
+ $.vertex(x1, y1);
4088
+ $.vertex(x2, y2);
4089
+ $.vertex(x3, y3);
4090
+ $.vertex(x4, y4);
4091
+ $.endShape(true);
4049
4092
  };
4050
4093
 
4051
4094
  $.background = (r, g, b, a) => {
@@ -4178,7 +4221,7 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
4178
4221
  entryPoint: 'fragmentMain',
4179
4222
  targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
4180
4223
  },
4181
- primitive: { topology: 'triangle-list' },
4224
+ primitive: { topology: 'triangle-strip', stripIndexFormat: 'uint32' },
4182
4225
  multisample: { count: 4 }
4183
4226
  };
4184
4227
 
@@ -4210,7 +4253,6 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
4210
4253
  {
4211
4254
  texture,
4212
4255
  colorSpace: $.canvas.colorSpace
4213
- // premultipliedAlpha: true
4214
4256
  },
4215
4257
  textureSize
4216
4258
  );
@@ -4242,6 +4284,11 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
4242
4284
  const img = new Image();
4243
4285
  img.crossOrigin = 'Anonymous';
4244
4286
  img.onload = () => {
4287
+ // calculate the default width and height that the image
4288
+ // should be drawn at if the user doesn't specify a display size
4289
+ img.defaultWidth = img.width * $._defaultImageScale;
4290
+ img.defaultHeight = img.height * $._defaultImageScale;
4291
+
4245
4292
  $._createTexture(img);
4246
4293
  q._preloadCount--;
4247
4294
  };
@@ -4258,8 +4305,8 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
4258
4305
  if ($._matrixDirty) $._saveMatrix();
4259
4306
  let ti = $._transformIndex;
4260
4307
 
4261
- w ??= img.width / $._pixelDensity;
4262
- h ??= img.height / $._pixelDensity;
4308
+ w ??= img.defaultWidth;
4309
+ h ??= img.defaultHeight;
4263
4310
 
4264
4311
  let [l, r, t, b] = $._calcBox(x, y, w, h, $._imageMode);
4265
4312
 
@@ -4268,8 +4315,6 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {
4268
4315
  l, t, 0, 0, ti,
4269
4316
  r, t, 1, 0, ti,
4270
4317
  l, b, 0, 1, ti,
4271
- r, t, 1, 0, ti,
4272
- l, b, 0, 1, ti,
4273
4318
  r, b, 1, 1, ti
4274
4319
  );
4275
4320