@carto/api-client 0.5.32-alpha.723d642.132 → 0.5.32-alpha.72cdcfe.130

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 CHANGED
@@ -8,7 +8,7 @@
8
8
  "homepage": "https://github.com/CartoDB/carto-api-client#readme",
9
9
  "author": "Don McCurdy <donmccurdy@carto.com>",
10
10
  "packageManager": "yarn@4.3.1",
11
- "version": "0.5.32-alpha.723d642.132",
11
+ "version": "0.5.32-alpha.72cdcfe.130",
12
12
  "license": "MIT",
13
13
  "publishConfig": {
14
14
  "access": "public"
@@ -1,14 +1,12 @@
1
1
  // Fill-pattern atlas — internal to carto-api-client.
2
2
  //
3
- // The patterns live as individual, developer-editable tiles (src/fetch-map/patterns/):
4
- // Design's original 64px raster masks (*.png) plus vector twins (*.svg), both inlined
5
- // by tsup's `dataurl` loader, with procedural canvas painters as a third, asset-free
6
- // source selectable via a debug knob while the final asset strategy is evaluated.
7
- // Tiles are composited into a sprite sheet on a canvas the first time a pattern is
8
- // needed. Each atlas cell is filled with side-by-side copies of its tile (raster art
9
- // never resampled), and is surrounded by a gutter holding the tile's own wrapped
10
- // content — so linear sampling stays seamless at repeat boundaries and never bleeds a
11
- // neighboring cell.
3
+ // The patterns live as individual, developer-editable tiles (src/fetch-map/patterns/
4
+ // *.png any resolution; ideally anti-aliased exports from the Design vector master),
5
+ // inlined by tsup's `dataurl` loader and composited into a sprite sheet on a canvas the
6
+ // first time a pattern is needed. Each cell is surrounded by a gutter filled with the
7
+ // tile's own wrapped content, so linear sampling stays seamless at repeat boundaries
8
+ // and never bleeds a neighboring cell. High-res sources are smoothly downscaled;
9
+ // lower-res (pixel-art) sources are upscaled nearest-neighbor.
12
10
  //
13
11
  // parse-map sets `result.fillPatternAtlas = getPatternAtlas()`. deck.gl's
14
12
  // `fillPatternAtlas` prop is async — but the Promise must resolve to a decoded image,
@@ -20,10 +18,6 @@
20
18
  // globalThis.__CARTO_PATTERN_TEXTURE_PARAMS__ = {magFilter: 'nearest', ...}
21
19
  // // merged into the atlas texture's sampler via deck's `textureParameters`;
22
20
  // // unset -> deck defaults (linear).
23
- // globalThis.__CARTO_PATTERN_ASSET_SOURCE__ = 'png' | 'svg' | 'procedural'
24
- // // 'png' (default): Design's original 64px raster masks, tiled at native
25
- // // resolution. 'svg': in-repo vector tiles rasterized at atlas-build time
26
- // // (2x texel density per repeat). 'procedural': canvas painters, no assets.
27
21
 
28
22
  import hlinesLarge from './patterns/hlines-large.png';
29
23
  import hlinesMedium from './patterns/hlines-medium.png';
@@ -48,43 +42,13 @@ import checkerMedium from './patterns/checker-medium.png';
48
42
  import checkerSmall from './patterns/checker-small.png';
49
43
  import solid from './patterns/solid.png';
50
44
 
51
- import hlinesLargeSvg from './patterns/hlines-large.svg';
52
- import hlinesMediumSvg from './patterns/hlines-medium.svg';
53
- import hlinesSmallSvg from './patterns/hlines-small.svg';
54
- import vlinesLargeSvg from './patterns/vlines-large.svg';
55
- import vlinesMediumSvg from './patterns/vlines-medium.svg';
56
- import vlinesSmallSvg from './patterns/vlines-small.svg';
57
- import diagLeftLargeSvg from './patterns/diag-left-large.svg';
58
- import diagLeftMediumSvg from './patterns/diag-left-medium.svg';
59
- import diagLeftSmallSvg from './patterns/diag-left-small.svg';
60
- import diagRightLargeSvg from './patterns/diag-right-large.svg';
61
- import diagRightMediumSvg from './patterns/diag-right-medium.svg';
62
- import diagRightSmallSvg from './patterns/diag-right-small.svg';
63
- import crossHatchLargeSvg from './patterns/cross-hatch-large.svg';
64
- import crossHatchMediumSvg from './patterns/cross-hatch-medium.svg';
65
- import crossHatchSmallSvg from './patterns/cross-hatch-small.svg';
66
- import dotsLargeSvg from './patterns/dots-large.svg';
67
- import dotsMediumSvg from './patterns/dots-medium.svg';
68
- import dotsSmallSvg from './patterns/dots-small.svg';
69
- import checkerLargeSvg from './patterns/checker-large.svg';
70
- import checkerMediumSvg from './patterns/checker-medium.svg';
71
- import checkerSmallSvg from './patterns/checker-small.svg';
72
- import solidSvg from './patterns/solid.svg';
73
-
74
45
  const DEFAULT_CELL_SIZE = 128;
75
- // px of the original raster masks; also the design grid the on-screen size is
76
- // defined against — one tile spans 64 design units whatever the asset source.
46
+ // px of the authored pattern art; also the reference for on-screen pattern size.
77
47
  const SOURCE_TILE_SIZE = 64;
78
- // Vector sources (svg/procedural) rasterize each repeat at up to this many px,
79
- // doubling texel density per repeat vs the 64px masks.
80
- const VECTOR_RENDER_SIZE = 128;
81
-
82
- export type PatternAssetSource = 'png' | 'svg' | 'procedural';
83
48
 
84
49
  type PatternDebugGlobals = {
85
50
  __CARTO_PATTERN_CELL_SIZE__?: number;
86
51
  __CARTO_PATTERN_TEXTURE_PARAMS__?: Record<string, unknown>;
87
- __CARTO_PATTERN_ASSET_SOURCE__?: PatternAssetSource;
88
52
  };
89
53
 
90
54
  export type PatternAtlasFrame = {
@@ -134,32 +98,6 @@ const CELL_URLS: Record<string, string> = {
134
98
  solid,
135
99
  };
136
100
 
137
- // atlas key -> inlined data URL of its vector source tile
138
- const CELL_SVG_URLS: Record<string, string> = {
139
- 'hlines-large': hlinesLargeSvg,
140
- 'hlines-medium': hlinesMediumSvg,
141
- 'hlines-small': hlinesSmallSvg,
142
- 'vlines-large': vlinesLargeSvg,
143
- 'vlines-medium': vlinesMediumSvg,
144
- 'vlines-small': vlinesSmallSvg,
145
- 'diag-left-large': diagLeftLargeSvg,
146
- 'diag-left-medium': diagLeftMediumSvg,
147
- 'diag-left-small': diagLeftSmallSvg,
148
- 'diag-right-large': diagRightLargeSvg,
149
- 'diag-right-medium': diagRightMediumSvg,
150
- 'diag-right-small': diagRightSmallSvg,
151
- 'cross-hatch-large': crossHatchLargeSvg,
152
- 'cross-hatch-medium': crossHatchMediumSvg,
153
- 'cross-hatch-small': crossHatchSmallSvg,
154
- 'dots-large': dotsLargeSvg,
155
- 'dots-medium': dotsMediumSvg,
156
- 'dots-small': dotsSmallSvg,
157
- 'checker-large': checkerLargeSvg,
158
- 'checker-medium': checkerMediumSvg,
159
- 'checker-small': checkerSmallSvg,
160
- solid: solidSvg,
161
- };
162
-
163
101
  function debugGlobals(): PatternDebugGlobals {
164
102
  return globalThis as PatternDebugGlobals;
165
103
  }
@@ -169,11 +107,6 @@ export function getPatternCellSize(): number {
169
107
  return typeof cell === 'number' && cell > 0 ? cell : DEFAULT_CELL_SIZE;
170
108
  }
171
109
 
172
- export function getPatternAssetSource(): PatternAssetSource {
173
- const source = debugGlobals().__CARTO_PATTERN_ASSET_SOURCE__;
174
- return source === 'svg' || source === 'procedural' ? source : 'png';
175
- }
176
-
177
110
  /** Sampler overrides for the atlas texture; undefined keeps deck's defaults (linear). */
178
111
  export function getPatternTextureParameters():
179
112
  | Record<string, unknown>
@@ -182,27 +115,14 @@ export function getPatternTextureParameters():
182
115
  return params && typeof params === 'object' ? params : undefined;
183
116
  }
184
117
 
185
- // Copies of the source tile laid side by side inside one atlas cell, per axis. Raster
186
- // tiles draw at native resolution (no resampling); vector sources rasterize each
187
- // repeat at up to VECTOR_RENDER_SIZE px. The UV wrap — where sampling seams live —
188
- // happens 1/reps as often.
189
- function getPatternRepeats(
190
- cell: number,
191
- source: PatternAssetSource = getPatternAssetSource()
192
- ): number {
193
- const repeatSize = source === 'png' ? SOURCE_TILE_SIZE : VECTOR_RENDER_SIZE;
194
- return Math.max(1, Math.floor(cell / repeatSize));
195
- }
196
-
197
118
  // deck's fill-pattern shader sizes the on-screen repeat proportionally to the mapping
198
- // frame's texel size (scale = FILL_UV_SCALE * getFillPatternScale * frame.wh). This
199
- // factor compensates for the cell size and the repeats inside it, normalized to the
200
- // 64px design grid, so the pattern keeps a constant on-screen size across cell sizes
201
- // and asset sources.
119
+ // frame's texel size (scale = FILL_UV_SCALE * getFillPatternScale * frame.wh), so a
120
+ // bigger cell magnifies the art instead of sharpening it. This factor compensates:
121
+ // getFillPatternScale must be multiplied by it so cell size only changes resolution.
202
122
  export function getPatternScaleAdjustment(
203
123
  cell: number = getPatternCellSize()
204
124
  ): number {
205
- return (SOURCE_TILE_SIZE * getPatternRepeats(cell)) / cell;
125
+ return SOURCE_TILE_SIZE / cell;
206
126
  }
207
127
 
208
128
  // Gutter width around each cell; sized so a few mip levels stay bleed-free.
@@ -268,108 +188,27 @@ async function loadImage(dataUrl: string): Promise<CanvasImageSource> {
268
188
  });
269
189
  }
270
190
 
271
- // SVG images always go through an Image element: createImageBitmap on SVG blobs is
272
- // inconsistent across engines, and drawImage from an SVG image rasterizes from the
273
- // vector at the destination size in modern browsers.
274
- function loadSvgImage(dataUrl: string): Promise<CanvasImageSource> {
275
- return new Promise((resolve, reject) => {
276
- const img = new Image();
277
- img.onload = () => resolve(img);
278
- img.onerror = reject;
279
- img.src = dataUrl;
280
- });
281
- }
191
+ const atlasPromises = new Map<number, Promise<AssembledAtlas>>();
282
192
 
283
- // Procedural painters the same measured design-grid geometry as the assets, drawn
284
- // in 64-unit design coordinates onto a pre-scaled context (canvas AA does the rest).
285
- const DENSITY_STEP: Record<string, number> = {small: 1, medium: 2, large: 4};
286
-
287
- function paintDesignTile(
288
- ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D,
289
- key: string
290
- ): void {
291
- const [, name, density] =
292
- key.match(/^(.*?)(?:-(small|medium|large))?$/) ?? [];
293
- const step = DENSITY_STEP[density ?? ''] ?? 1;
294
- const linePeriod = 4 * step;
295
- const diagPeriod = 16 * step;
296
- const square = 2 * step;
297
- ctx.fillStyle = '#000';
298
- ctx.strokeStyle = '#000';
299
- const diag = (dir: 1 | -1) => {
300
- // dir 1: "\" lines (x - y = k*p); dir -1: "/" lines (x + y = k*p)
301
- ctx.lineWidth = Math.SQRT2; // 2px horizontal width at 45 degrees
302
- ctx.beginPath();
303
- for (
304
- let k = -Math.ceil(64 / diagPeriod);
305
- k <= 2 * Math.ceil(64 / diagPeriod);
306
- k++
307
- ) {
308
- ctx.moveTo(k * diagPeriod - 8 * dir, -8);
309
- ctx.lineTo(k * diagPeriod + 72 * dir, 72);
310
- }
311
- ctx.stroke();
312
- };
313
- switch (name) {
314
- case 'solid':
315
- ctx.fillRect(0, 0, 64, 64);
316
- break;
317
- case 'hlines':
318
- for (let y = 0; y < 64; y += linePeriod) ctx.fillRect(0, y, 64, 2);
319
- break;
320
- case 'vlines':
321
- for (let x = 0; x < 64; x += linePeriod) ctx.fillRect(x, 0, 2, 64);
322
- break;
323
- case 'dots':
324
- for (let y = 0; y < 64; y += linePeriod)
325
- for (let x = 0; x < 64; x += linePeriod) ctx.fillRect(x, y, 2, 2);
326
- break;
327
- case 'checker':
328
- for (let j = 0; j * square < 64; j++)
329
- for (let i = 0; i * square < 64; i++)
330
- if ((i + j) % 2 === 0)
331
- ctx.fillRect(i * square, j * square, square, square);
332
- break;
333
- case 'diag-left':
334
- diag(1);
335
- break;
336
- case 'diag-right':
337
- diag(-1);
338
- break;
339
- case 'cross-hatch':
340
- diag(1);
341
- diag(-1);
342
- break;
193
+ /** Assemble the sprite sheet from the individual editable pattern tiles. Memoized. */
194
+ export function getPatternAtlas(
195
+ cell: number = getPatternCellSize()
196
+ ): Promise<AssembledAtlas> {
197
+ let promise = atlasPromises.get(cell);
198
+ if (!promise) {
199
+ promise = build(cell);
200
+ // Keep a rejection observed even if no consumer attaches a handler (e.g. Node,
201
+ // where there is no canvas) — the returned promise still rejects for real callers.
202
+ promise.catch(() => {});
203
+ atlasPromises.set(cell, promise);
343
204
  }
205
+ return promise;
344
206
  }
345
207
 
346
- function paintTileCanvas(key: string, size: number): CanvasImageSource {
347
- const canvas = createCanvas(size, size);
348
- const ctx = canvas.getContext('2d');
349
- if (!ctx)
350
- throw new Error(
351
- 'carto-api-client: 2D context unavailable for pattern tile'
352
- );
353
- ctx.scale(size / 64, size / 64);
354
- paintDesignTile(ctx, key);
355
- return canvas;
356
- }
357
-
358
- type TileImages = Record<string, CanvasImageSource>;
359
-
360
- // Shared compositor: lay out the per-key tile images on the atlas grid. `none` is
361
- // left transparent (no tile). Every other cell is filled with reps x reps copies of
362
- // its tile, with one extra ring clipped into the gutter, so the padding holds the
363
- // tile's own wrapped content.
364
- async function composeAtlas(
365
- cell: number,
366
- reps: number,
367
- images: TileImages
368
- ): Promise<AssembledAtlas> {
208
+ async function build(cell: number): Promise<AssembledAtlas> {
369
209
  const mapping = getPatternAtlasMapping(cell);
370
210
  const pad = getPatternCellPadding(cell);
371
211
  const pitch = cell + 2 * pad;
372
- const step = cell / reps;
373
212
  const canvas = createCanvas(pitch * 3, pitch * (PATTERN_ROWS.length + 1));
374
213
  const ctx = canvas.getContext('2d');
375
214
  if (!ctx)
@@ -377,16 +216,30 @@ async function composeAtlas(
377
216
  'carto-api-client: 2D context unavailable for pattern atlas'
378
217
  );
379
218
 
219
+ const images: Record<string, CanvasImageSource> = {};
220
+ await Promise.all(
221
+ Object.entries(CELL_URLS).map(async ([key, url]) => {
222
+ images[key] = await loadImage(url);
223
+ })
224
+ );
225
+
226
+ // `none` is left transparent (no tile). Every other tile is drawn 3x3 clipped to its
227
+ // padded rect, so the gutter holds the tile's own wrapped content.
380
228
  for (const [key, frame] of Object.entries(mapping)) {
381
229
  const img = images[key];
382
230
  if (!img) continue;
231
+ // Two art classes: diagonal tiles rely on baked anti-aliasing, which nearest
232
+ // scaling turns into hard blocks — scale them smoothly. Axis-aligned tiles have
233
+ // exact hard edges on texel boundaries — nearest is lossless, smoothing blurs.
234
+ ctx.imageSmoothingEnabled = /^(diag-|cross-hatch)/.test(key);
235
+ if ('imageSmoothingQuality' in ctx) ctx.imageSmoothingQuality = 'high';
383
236
  ctx.save();
384
237
  ctx.beginPath();
385
238
  ctx.rect(frame.x - pad, frame.y - pad, cell + 2 * pad, cell + 2 * pad);
386
239
  ctx.clip();
387
- for (let i = -1; i <= reps; i++) {
388
- for (let j = -1; j <= reps; j++) {
389
- ctx.drawImage(img, frame.x + i * step, frame.y + j * step, step, step);
240
+ for (const dx of [-cell, 0, cell]) {
241
+ for (const dy of [-cell, 0, cell]) {
242
+ ctx.drawImage(img, frame.x + dx, frame.y + dy, cell, cell);
390
243
  }
391
244
  }
392
245
  ctx.restore();
@@ -396,66 +249,3 @@ async function composeAtlas(
396
249
  return createImageBitmap(canvas);
397
250
  return canvas as HTMLCanvasElement;
398
251
  }
399
-
400
- // One builder per asset source, all funneling into composeAtlas.
401
-
402
- // Design's original 64px raster masks, tiled at native resolution (never resampled).
403
- async function buildPngAtlas(cell: number): Promise<AssembledAtlas> {
404
- const images: TileImages = {};
405
- await Promise.all(
406
- Object.entries(CELL_URLS).map(async ([key, url]) => {
407
- images[key] = await loadImage(url);
408
- })
409
- );
410
- return composeAtlas(cell, getPatternRepeats(cell, 'png'), images);
411
- }
412
-
413
- // In-repo vector tiles, rasterized from the vector at the repeat size.
414
- async function buildSvgAtlas(cell: number): Promise<AssembledAtlas> {
415
- const images: TileImages = {};
416
- await Promise.all(
417
- Object.entries(CELL_SVG_URLS).map(async ([key, url]) => {
418
- images[key] = await loadSvgImage(url);
419
- })
420
- );
421
- return composeAtlas(cell, getPatternRepeats(cell, 'svg'), images);
422
- }
423
-
424
- // Asset-free canvas painters drawing the measured design-grid geometry.
425
- async function buildProceduralAtlas(cell: number): Promise<AssembledAtlas> {
426
- const reps = getPatternRepeats(cell, 'procedural');
427
- const step = cell / reps;
428
- const images: TileImages = {};
429
- for (const key of Object.keys(CELL_URLS)) {
430
- images[key] = paintTileCanvas(key, step);
431
- }
432
- return composeAtlas(cell, reps, images);
433
- }
434
-
435
- const ATLAS_BUILDERS: Record<
436
- PatternAssetSource,
437
- (cell: number) => Promise<AssembledAtlas>
438
- > = {
439
- png: buildPngAtlas,
440
- svg: buildSvgAtlas,
441
- procedural: buildProceduralAtlas,
442
- };
443
-
444
- const atlasPromises = new Map<string, Promise<AssembledAtlas>>();
445
-
446
- /** Assemble the sprite sheet for the active asset source and cell size. Memoized. */
447
- export function getPatternAtlas(
448
- cell: number = getPatternCellSize()
449
- ): Promise<AssembledAtlas> {
450
- const source = getPatternAssetSource();
451
- const memoKey = `${source}:${cell}`;
452
- let promise = atlasPromises.get(memoKey);
453
- if (!promise) {
454
- promise = ATLAS_BUILDERS[source](cell);
455
- // Keep a rejection observed even if no consumer attaches a handler (e.g. Node,
456
- // where there is no canvas) — the returned promise still rejects for real callers.
457
- promise.catch(() => {});
458
- atlasPromises.set(memoKey, promise);
459
- }
460
- return promise;
461
- }
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="16" height="16" patternUnits="userSpaceOnUse"><rect width="8" height="8"/><rect x="8" y="8" width="8" height="8"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="8" height="8" patternUnits="userSpaceOnUse"><rect width="4" height="4"/><rect x="4" y="4" width="4" height="4"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="4" height="4" patternUnits="userSpaceOnUse"><rect width="2" height="2"/><rect x="2" y="2" width="2" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="a" width="45.2548" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern><pattern id="b" width="45.2548" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#a)"/><rect width="64" height="64" fill="url(#b)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="a" width="22.6274" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern><pattern id="b" width="22.6274" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#a)"/><rect width="64" height="64" fill="url(#b)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="a" width="11.3137" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern><pattern id="b" width="11.3137" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#a)"/><rect width="64" height="64" fill="url(#b)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="45.2548" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="22.6274" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="11.3137" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(-45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="45.2548" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="22.6274" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="11.3137" height="64" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><rect width="1.4142" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="16" height="16" patternUnits="userSpaceOnUse"><rect width="2" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="8" height="8" patternUnits="userSpaceOnUse"><rect width="2" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="4" height="4" patternUnits="userSpaceOnUse"><rect width="2" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="64" height="16" patternUnits="userSpaceOnUse"><rect width="64" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="64" height="8" patternUnits="userSpaceOnUse"><rect width="64" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="64" height="4" patternUnits="userSpaceOnUse"><rect width="64" height="2"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs></defs><rect width="64" height="64"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="16" height="64" patternUnits="userSpaceOnUse"><rect width="2" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="8" height="64" patternUnits="userSpaceOnUse"><rect width="2" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><pattern id="p" width="4" height="64" patternUnits="userSpaceOnUse"><rect width="2" height="64"/></pattern></defs><rect width="64" height="64" fill="url(#p)"/></svg>