q5 2.10.3 → 2.10.6

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.
@@ -1,53 +1,52 @@
1
1
  /* software implementation of image filters */
2
2
  Q5.renderers.q2d.soft_filters = ($) => {
3
- let tmpBuf = null;
3
+ let u = null; // uint8 temporary buffer
4
4
 
5
- function ensureTmpBuf() {
5
+ function ensureBuf() {
6
6
  let l = $.canvas.width * $.canvas.height * 4;
7
- if (!tmpBuf || tmpBuf.length != l) {
8
- tmpBuf = new Uint8ClampedArray(l);
9
- }
7
+ if (!u || u.length != l) u = new Uint8ClampedArray(l);
10
8
  }
11
9
 
12
10
  function initSoftFilters() {
13
11
  $._filters = [];
14
- $._filters[Q5.THRESHOLD] = (data, thresh) => {
12
+ $._filters[Q5.THRESHOLD] = (d, thresh) => {
15
13
  if (thresh === undefined) thresh = 127.5;
16
14
  else thresh *= 255;
17
- for (let i = 0; i < data.length; i += 4) {
18
- const gray = 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];
19
- data[i] = data[i + 1] = data[i + 2] = gray >= thresh ? 255 : 0;
15
+ for (let i = 0; i < d.length; i += 4) {
16
+ const gray = 0.2126 * d[i] + 0.7152 * d[i + 1] + 0.0722 * d[i + 2];
17
+ d[i] = d[i + 1] = d[i + 2] = gray >= thresh ? 255 : 0;
20
18
  }
21
19
  };
22
- $._filters[Q5.GRAY] = (data) => {
23
- for (let i = 0; i < data.length; i += 4) {
24
- const gray = 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];
25
- data[i] = data[i + 1] = data[i + 2] = gray;
20
+ $._filters[Q5.GRAY] = (d) => {
21
+ for (let i = 0; i < d.length; i += 4) {
22
+ const gray = 0.2126 * d[i] + 0.7152 * d[i + 1] + 0.0722 * d[i + 2];
23
+ d[i] = d[i + 1] = d[i + 2] = gray;
26
24
  }
27
25
  };
28
- $._filters[Q5.OPAQUE] = (data) => {
29
- for (let i = 0; i < data.length; i += 4) {
30
- data[i + 3] = 255;
26
+ $._filters[Q5.OPAQUE] = (d) => {
27
+ for (let i = 0; i < d.length; i += 4) {
28
+ d[i + 3] = 255;
31
29
  }
32
30
  };
33
- $._filters[Q5.INVERT] = (data) => {
34
- for (let i = 0; i < data.length; i += 4) {
35
- data[i] = 255 - data[i];
36
- data[i + 1] = 255 - data[i + 1];
37
- data[i + 2] = 255 - data[i + 2];
31
+ $._filters[Q5.INVERT] = (d) => {
32
+ for (let i = 0; i < d.length; i += 4) {
33
+ d[i] = 255 - d[i];
34
+ d[i + 1] = 255 - d[i + 1];
35
+ d[i + 2] = 255 - d[i + 2];
38
36
  }
39
37
  };
40
- $._filters[Q5.POSTERIZE] = (data, lvl = 4) => {
38
+ $._filters[Q5.POSTERIZE] = (d, lvl = 4) => {
41
39
  let lvl1 = lvl - 1;
42
- for (let i = 0; i < data.length; i += 4) {
43
- data[i] = (((data[i] * lvl) >> 8) * 255) / lvl1;
44
- data[i + 1] = (((data[i + 1] * lvl) >> 8) * 255) / lvl1;
45
- data[i + 2] = (((data[i + 2] * lvl) >> 8) * 255) / lvl1;
40
+ for (let i = 0; i < d.length; i += 4) {
41
+ d[i] = (((d[i] * lvl) >> 8) * 255) / lvl1;
42
+ d[i + 1] = (((d[i + 1] * lvl) >> 8) * 255) / lvl1;
43
+ d[i + 2] = (((d[i + 2] * lvl) >> 8) * 255) / lvl1;
46
44
  }
47
45
  };
48
- $._filters[Q5.DILATE] = (data) => {
49
- ensureTmpBuf();
50
- tmpBuf.set(data);
46
+ $._filters[Q5.DILATE] = (d, func) => {
47
+ func ??= Math.max;
48
+ ensureBuf();
49
+ u.set(d);
51
50
  let [w, h] = [$.canvas.width, $.canvas.height];
52
51
  for (let i = 0; i < h; i++) {
53
52
  for (let j = 0; j < w; j++) {
@@ -61,55 +60,25 @@ Q5.renderers.q2d.soft_filters = ($) => {
61
60
  let kt = k + t;
62
61
  let kb = k + b;
63
62
  let ko = k + oi;
64
- data[oi + oj + k] = Math.max(
65
- /*tmpBuf[kt+l],*/ tmpBuf[kt + oj] /*tmpBuf[kt+r],*/,
66
- tmpBuf[ko + l],
67
- tmpBuf[ko + oj],
68
- tmpBuf[ko + r],
69
- /*tmpBuf[kb+l],*/ tmpBuf[kb + oj] /*tmpBuf[kb+r],*/
70
- );
63
+ d[oi + oj + k] = func(u[kt + oj], u[ko + l], u[ko + oj], u[ko + r], u[kb + oj]);
71
64
  }
72
65
  }
73
66
  }
74
67
  };
75
- $._filters[Q5.ERODE] = (data) => {
76
- ensureTmpBuf();
77
- tmpBuf.set(data);
78
- let [w, h] = [$.canvas.width, $.canvas.height];
79
- for (let i = 0; i < h; i++) {
80
- for (let j = 0; j < w; j++) {
81
- let l = 4 * Math.max(j - 1, 0);
82
- let r = 4 * Math.min(j + 1, w - 1);
83
- let t = 4 * Math.max(i - 1, 0) * w;
84
- let b = 4 * Math.min(i + 1, h - 1) * w;
85
- let oi = 4 * i * w;
86
- let oj = 4 * j;
87
- for (let k = 0; k < 4; k++) {
88
- let kt = k + t;
89
- let kb = k + b;
90
- let ko = k + oi;
91
- data[oi + oj + k] = Math.min(
92
- /*tmpBuf[kt+l],*/ tmpBuf[kt + oj] /*tmpBuf[kt+r],*/,
93
- tmpBuf[ko + l],
94
- tmpBuf[ko + oj],
95
- tmpBuf[ko + r],
96
- /*tmpBuf[kb+l],*/ tmpBuf[kb + oj] /*tmpBuf[kb+r],*/
97
- );
98
- }
99
- }
100
- }
68
+ $._filters[Q5.ERODE] = (d) => {
69
+ $._filters[Q5.DILATE](d, Math.min);
101
70
  };
102
- $._filters[Q5.BLUR] = (data, rad) => {
103
- rad = rad || 1;
104
- rad = Math.floor(rad * $._pixelDensity);
105
- ensureTmpBuf();
106
- tmpBuf.set(data);
71
+ $._filters[Q5.BLUR] = (d, r) => {
72
+ r = r || 1;
73
+ r = Math.floor(r * $._pixelDensity);
74
+ ensureBuf();
75
+ u.set(d);
107
76
 
108
- let ksize = rad * 2 + 1;
77
+ let ksize = r * 2 + 1;
109
78
 
110
- function gauss1d(ksize) {
79
+ function gauss(ksize) {
111
80
  let im = new Float32Array(ksize);
112
- let sigma = 0.3 * rad + 0.8;
81
+ let sigma = 0.3 * r + 0.8;
113
82
  let ss2 = sigma * sigma * 2;
114
83
  for (let i = 0; i < ksize; i++) {
115
84
  let x = i - ksize / 2;
@@ -119,7 +88,7 @@ Q5.renderers.q2d.soft_filters = ($) => {
119
88
  return im;
120
89
  }
121
90
 
122
- let kern = gauss1d(ksize);
91
+ let kern = gauss(ksize);
123
92
  let [w, h] = [$.canvas.width, $.canvas.height];
124
93
  for (let i = 0; i < h; i++) {
125
94
  for (let j = 0; j < w; j++) {
@@ -128,21 +97,21 @@ Q5.renderers.q2d.soft_filters = ($) => {
128
97
  s2 = 0,
129
98
  s3 = 0;
130
99
  for (let k = 0; k < ksize; k++) {
131
- let jk = Math.min(Math.max(j - rad + k, 0), w - 1);
100
+ let jk = Math.min(Math.max(j - r + k, 0), w - 1);
132
101
  let idx = 4 * (i * w + jk);
133
- s0 += tmpBuf[idx] * kern[k];
134
- s1 += tmpBuf[idx + 1] * kern[k];
135
- s2 += tmpBuf[idx + 2] * kern[k];
136
- s3 += tmpBuf[idx + 3] * kern[k];
102
+ s0 += u[idx] * kern[k];
103
+ s1 += u[idx + 1] * kern[k];
104
+ s2 += u[idx + 2] * kern[k];
105
+ s3 += u[idx + 3] * kern[k];
137
106
  }
138
107
  let idx = 4 * (i * w + j);
139
- data[idx] = s0;
140
- data[idx + 1] = s1;
141
- data[idx + 2] = s2;
142
- data[idx + 3] = s3;
108
+ d[idx] = s0;
109
+ d[idx + 1] = s1;
110
+ d[idx + 2] = s2;
111
+ d[idx + 3] = s3;
143
112
  }
144
113
  }
145
- tmpBuf.set(data);
114
+ u.set(d);
146
115
  for (let i = 0; i < h; i++) {
147
116
  for (let j = 0; j < w; j++) {
148
117
  let s0 = 0,
@@ -150,18 +119,18 @@ Q5.renderers.q2d.soft_filters = ($) => {
150
119
  s2 = 0,
151
120
  s3 = 0;
152
121
  for (let k = 0; k < ksize; k++) {
153
- let ik = Math.min(Math.max(i - rad + k, 0), h - 1);
122
+ let ik = Math.min(Math.max(i - r + k, 0), h - 1);
154
123
  let idx = 4 * (ik * w + j);
155
- s0 += tmpBuf[idx] * kern[k];
156
- s1 += tmpBuf[idx + 1] * kern[k];
157
- s2 += tmpBuf[idx + 2] * kern[k];
158
- s3 += tmpBuf[idx + 3] * kern[k];
124
+ s0 += u[idx] * kern[k];
125
+ s1 += u[idx + 1] * kern[k];
126
+ s2 += u[idx + 2] * kern[k];
127
+ s3 += u[idx + 3] * kern[k];
159
128
  }
160
129
  let idx = 4 * (i * w + j);
161
- data[idx] = s0;
162
- data[idx + 1] = s1;
163
- data[idx + 2] = s2;
164
- data[idx + 3] = s3;
130
+ d[idx] = s0;
131
+ d[idx + 1] = s1;
132
+ d[idx + 2] = s2;
133
+ d[idx + 3] = s3;
165
134
  }
166
135
  }
167
136
  };
package/src/q5-canvas.js CHANGED
@@ -1,58 +1,4 @@
1
1
  Q5.modules.canvas = ($, q) => {
2
- $.CENTER = 'center';
3
- $.LEFT = 'left';
4
- $.RIGHT = 'right';
5
- $.TOP = 'top';
6
- $.BOTTOM = 'bottom';
7
-
8
- $.BASELINE = 'alphabetic';
9
-
10
- $.NORMAL = 'normal';
11
- $.ITALIC = 'italic';
12
- $.BOLD = 'bold';
13
- $.BOLDITALIC = 'italic bold';
14
-
15
- $.ROUND = 'round';
16
- $.SQUARE = 'butt';
17
- $.PROJECT = 'square';
18
- $.MITER = 'miter';
19
- $.BEVEL = 'bevel';
20
-
21
- $.CHORD_OPEN = 0;
22
- $.PIE_OPEN = 1;
23
- $.PIE = 2;
24
- $.CHORD = 3;
25
-
26
- $.RADIUS = 'radius';
27
- $.CORNER = 'corner';
28
- $.CORNERS = 'corners';
29
-
30
- $.OPEN = 0;
31
- $.CLOSE = 1;
32
-
33
- $.LANDSCAPE = 'landscape';
34
- $.PORTRAIT = 'portrait';
35
-
36
- $.BLEND = 'source-over';
37
- $.REMOVE = 'destination-out';
38
- $.ADD = 'lighter';
39
- $.DARKEST = 'darken';
40
- $.LIGHTEST = 'lighten';
41
- $.DIFFERENCE = 'difference';
42
- $.SUBTRACT = 'subtract';
43
- $.EXCLUSION = 'exclusion';
44
- $.MULTIPLY = 'multiply';
45
- $.SCREEN = 'screen';
46
- $.REPLACE = 'copy';
47
- $.OVERLAY = 'overlay';
48
- $.HARD_LIGHT = 'hard-light';
49
- $.SOFT_LIGHT = 'soft-light';
50
- $.DODGE = 'color-dodge';
51
- $.BURN = 'color-burn';
52
-
53
- $.P2D = '2d';
54
- $.WEBGL = 'webgl';
55
-
56
2
  $._OffscreenCanvas =
57
3
  window.OffscreenCanvas ||
58
4
  function () {
@@ -331,6 +277,74 @@ Q5.modules.canvas = ($, q) => {
331
277
  }
332
278
  };
333
279
 
280
+ Q5.CENTER = 'center';
281
+ Q5.LEFT = 'left';
282
+ Q5.RIGHT = 'right';
283
+ Q5.TOP = 'top';
284
+ Q5.BOTTOM = 'bottom';
285
+
286
+ Q5.BASELINE = 'alphabetic';
287
+
288
+ Q5.NORMAL = 'normal';
289
+ Q5.ITALIC = 'italic';
290
+ Q5.BOLD = 'bold';
291
+ Q5.BOLDITALIC = 'italic bold';
292
+
293
+ Q5.ROUND = 'round';
294
+ Q5.SQUARE = 'butt';
295
+ Q5.PROJECT = 'square';
296
+ Q5.MITER = 'miter';
297
+ Q5.BEVEL = 'bevel';
298
+
299
+ Q5.CHORD_OPEN = 0;
300
+ Q5.PIE_OPEN = 1;
301
+ Q5.PIE = 2;
302
+ Q5.CHORD = 3;
303
+
304
+ Q5.RADIUS = 'radius';
305
+ Q5.CORNER = 'corner';
306
+ Q5.CORNERS = 'corners';
307
+
308
+ Q5.OPEN = 0;
309
+ Q5.CLOSE = 1;
310
+
311
+ Q5.LANDSCAPE = 'landscape';
312
+ Q5.PORTRAIT = 'portrait';
313
+
314
+ Q5.BLEND = 'source-over';
315
+ Q5.REMOVE = 'destination-out';
316
+ Q5.ADD = 'lighter';
317
+ Q5.DARKEST = 'darken';
318
+ Q5.LIGHTEST = 'lighten';
319
+ Q5.DIFFERENCE = 'difference';
320
+ Q5.SUBTRACT = 'subtract';
321
+ Q5.EXCLUSION = 'exclusion';
322
+ Q5.MULTIPLY = 'multiply';
323
+ Q5.SCREEN = 'screen';
324
+ Q5.REPLACE = 'copy';
325
+ Q5.OVERLAY = 'overlay';
326
+ Q5.HARD_LIGHT = 'hard-light';
327
+ Q5.SOFT_LIGHT = 'soft-light';
328
+ Q5.DODGE = 'color-dodge';
329
+ Q5.BURN = 'color-burn';
330
+
331
+ Q5.THRESHOLD = 1;
332
+ Q5.GRAY = 2;
333
+ Q5.OPAQUE = 3;
334
+ Q5.INVERT = 4;
335
+ Q5.POSTERIZE = 5;
336
+ Q5.DILATE = 6;
337
+ Q5.ERODE = 7;
338
+ Q5.BLUR = 8;
339
+ Q5.SEPIA = 9;
340
+ Q5.BRIGHTNESS = 10;
341
+ Q5.SATURATION = 11;
342
+ Q5.CONTRAST = 12;
343
+ Q5.HUE_ROTATE = 13;
344
+
345
+ Q5.P2D = '2d';
346
+ Q5.WEBGL = 'webgl';
347
+
334
348
  Q5.canvasOptions = {
335
349
  alpha: false,
336
350
  colorSpace: 'display-p3'
package/src/q5-color.js CHANGED
@@ -1,5 +1,6 @@
1
1
  Q5.modules.color = ($, q) => {
2
2
  $.RGB = $.RGBA = $._colorMode = 'rgb';
3
+ $.SRGB = 'srgb';
3
4
  $.OKLCH = 'oklch';
4
5
 
5
6
  $.colorMode = (mode, format) => {
@@ -10,7 +11,6 @@ Q5.modules.color = ($, q) => {
10
11
  if (mode == 'oklch') {
11
12
  q.Color = Q5.ColorOKLCH;
12
13
  } else {
13
- let srgb = $.canvas.colorSpace == 'srgb';
14
14
  if ($._colorFormat == 255) {
15
15
  q.Color = srgb ? Q5.ColorRGBA_8 : Q5.ColorRGBA_P3_8;
16
16
  } else {
@@ -90,14 +90,19 @@ Q5.modules.color = ($, q) => {
90
90
  if (Array.isArray(c0)) [c0, c1, c2, c3] = c0;
91
91
  }
92
92
 
93
- if (c2 == undefined) return new C(c0, c0, c0, c1);
93
+ if (c2 == undefined) {
94
+ if ($._colorMode == Q5.OKLCH) return new C(c0, 0, 0, c1);
95
+ return new C(c0, c0, c0, c1);
96
+ }
94
97
  return new C(c0, c1, c2, c3);
95
98
  };
96
99
 
100
+ // deprecated
97
101
  $.red = (c) => c.r;
98
102
  $.green = (c) => c.g;
99
103
  $.blue = (c) => c.b;
100
104
  $.alpha = (c) => c.a;
105
+
101
106
  $.lightness = (c) => {
102
107
  if (c.l) return c.l;
103
108
  return ((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * 100) / 255;
@@ -155,9 +160,43 @@ Q5.ColorOKLCH = class extends Q5.Color {
155
160
  this.h = h;
156
161
  this.a = a ?? 1;
157
162
  }
163
+ get levels() {
164
+ return [this.l, this.c, this.h, this.a];
165
+ }
166
+ equals(c) {
167
+ return c && this.l == c.l && this.c == c.c && this.h == c.h && this.a == c.a;
168
+ }
169
+ isSameColor(c) {
170
+ return c && this.l == c.l && this.c == c.c && this.h == c.h;
171
+ }
158
172
  toString() {
159
173
  return `oklch(${this.l} ${this.c} ${this.h} / ${this.a})`;
160
174
  }
175
+
176
+ get lightness() {
177
+ return this.l;
178
+ }
179
+ set lightness(v) {
180
+ this.l = v;
181
+ }
182
+ get chroma() {
183
+ return this.c;
184
+ }
185
+ set chroma(v) {
186
+ this.c = v;
187
+ }
188
+ get hue() {
189
+ return this.h;
190
+ }
191
+ set hue(v) {
192
+ this.h = v;
193
+ }
194
+ get alpha() {
195
+ return this.a;
196
+ }
197
+ set alpha(v) {
198
+ this.a = v;
199
+ }
161
200
  };
162
201
 
163
202
  Q5.ColorRGBA = class extends Q5.Color {
@@ -171,9 +210,39 @@ Q5.ColorRGBA = class extends Q5.Color {
171
210
  get levels() {
172
211
  return [this.r, this.g, this.b, this.a];
173
212
  }
213
+ equals(c) {
214
+ return c && this.r == c.r && this.g == c.g && this.b == c.b && this.a == c.a;
215
+ }
216
+ isSameColor(c) {
217
+ return c && this.r == c.r && this.g == c.g && this.b == c.b;
218
+ }
174
219
  toString() {
175
220
  return `color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`;
176
221
  }
222
+ get red() {
223
+ return this.r;
224
+ }
225
+ set red(v) {
226
+ this.r = v;
227
+ }
228
+ get green() {
229
+ return this.g;
230
+ }
231
+ set green(v) {
232
+ this.g = v;
233
+ }
234
+ get blue() {
235
+ return this.b;
236
+ }
237
+ set blue(v) {
238
+ this.b = v;
239
+ }
240
+ get alpha() {
241
+ return this.a;
242
+ }
243
+ set alpha(v) {
244
+ this.a = v;
245
+ }
177
246
  };
178
247
 
179
248
  Q5.ColorRGBA_P3 = class extends Q5.ColorRGBA {
@@ -187,6 +256,7 @@ Q5.ColorRGBA_8 = class extends Q5.ColorRGBA {
187
256
  constructor(r, g, b, a) {
188
257
  super(r, g, b, a ?? 255);
189
258
  }
259
+ // deprecated set functions for backwards compatibility
190
260
  setRed(v) {
191
261
  this.r = v;
192
262
  }
@@ -199,9 +269,6 @@ Q5.ColorRGBA_8 = class extends Q5.ColorRGBA {
199
269
  setAlpha(v) {
200
270
  this.a = v;
201
271
  }
202
- get levels() {
203
- return [this.r, this.g, this.b, this.a];
204
- }
205
272
  toString() {
206
273
  return `rgb(${this.r} ${this.g} ${this.b} / ${this.a / 255})`;
207
274
  }
package/src/q5-core.js CHANGED
@@ -143,15 +143,16 @@ function Q5(scope, parent, renderer) {
143
143
  $.getTargetFrameRate = () => $._targetFrameRate || 60;
144
144
  $.getFPS = () => $._fps;
145
145
 
146
+ // shims for compatibility with p5.js libraries
146
147
  $.Element = function (a) {
147
148
  this.elt = a;
148
149
  };
149
150
  $._elements = [];
151
+ $.describe = () => {};
150
152
 
151
153
  $.TWO_PI = $.TAU = Math.PI * 2;
152
154
 
153
155
  $.log = $.print = console.log;
154
- $.describe = () => {};
155
156
 
156
157
  for (let m in Q5.modules) {
157
158
  Q5.modules[m]($, q);