git-hash-art 0.13.0 → 0.14.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/dist/main.js CHANGED
@@ -2095,14 +2095,15 @@ function $c3de8257a8baa3b0$export$909ab0580e273f19(style) {
2095
2095
  }
2096
2096
  }
2097
2097
  function $c3de8257a8baa3b0$export$71b514a25c47df50(ctx, shape, x, y, config) {
2098
- const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation } = config;
2098
+ const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation, activeShapes: activeShapes } = config;
2099
2099
  ctx.save();
2100
2100
  ctx.translate(x, y);
2101
2101
  ctx.rotate(rotation * Math.PI / 180);
2102
2102
  ctx.fillStyle = fillColor;
2103
2103
  ctx.strokeStyle = strokeColor;
2104
2104
  ctx.lineWidth = strokeWidth;
2105
- const drawFunction = (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5)[shape];
2105
+ const registry = activeShapes ?? (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5);
2106
+ const drawFunction = registry[shape];
2106
2107
  if (drawFunction) {
2107
2108
  drawFunction(ctx, size);
2108
2109
  ctx.fill();
@@ -2612,7 +2613,8 @@ function $c3de8257a8baa3b0$export$bb35a6995ddbf32d(ctx, shape, x, y, config) {
2612
2613
  } else ctx.fillStyle = fillColor;
2613
2614
  ctx.strokeStyle = strokeColor;
2614
2615
  ctx.lineWidth = strokeWidth;
2615
- const drawFunction = (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5)[shape];
2616
+ const registry = config.activeShapes ?? (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5);
2617
+ const drawFunction = registry[shape];
2616
2618
  if (drawFunction) {
2617
2619
  drawFunction(ctx, size, {
2618
2620
  rng: rng
@@ -3476,6 +3478,26 @@ const $e73976f898150d4d$export$4343b39fe47bd82c = {
3476
3478
  ]
3477
3479
  }
3478
3480
  };
3481
+ function $e73976f898150d4d$export$90912290d628650f(name, partial) {
3482
+ $e73976f898150d4d$export$4343b39fe47bd82c[name] = {
3483
+ tier: partial?.tier ?? 2,
3484
+ minSizeFraction: partial?.minSizeFraction ?? 0.05,
3485
+ maxSizeFraction: partial?.maxSizeFraction ?? 1.0,
3486
+ affinities: partial?.affinities ?? [
3487
+ "circle",
3488
+ "square"
3489
+ ],
3490
+ category: "procedural",
3491
+ heroCandidate: partial?.heroCandidate ?? false,
3492
+ bestStyles: partial?.bestStyles ?? [
3493
+ "fill-and-stroke",
3494
+ "watercolor"
3495
+ ]
3496
+ };
3497
+ }
3498
+ function $e73976f898150d4d$export$f4ca68bd046f15ae(name) {
3499
+ delete $e73976f898150d4d$export$4343b39fe47bd82c[name];
3500
+ }
3479
3501
  function $e73976f898150d4d$export$4a95df8944b5033b(rng, shapeNames, archetypeName) {
3480
3502
  const available = shapeNames.filter((s)=>$e73976f898150d4d$export$4343b39fe47bd82c[s]);
3481
3503
  // Pick a seed shape — tier 1 shapes that are hero candidates
@@ -3665,7 +3687,14 @@ function $e73976f898150d4d$export$ab873bb6fb56c1a8(shapeName, layerStyle, rng) {
3665
3687
 
3666
3688
 
3667
3689
  /**
3668
- * Configuration options for image generation.
3690
+ * Draw function signature for custom shapes.
3691
+ * The function should build a canvas path (moveTo/lineTo/arc/etc.)
3692
+ * centered at the origin. The pipeline handles translate, rotate,
3693
+ * fill, and stroke — your function just defines the geometry.
3694
+ *
3695
+ * @param ctx - Canvas 2D rendering context (already translated to shape center)
3696
+ * @param size - Bounding size in pixels
3697
+ * @param rng - Deterministic RNG seeded from the git hash — use this instead of Math.random()
3669
3698
  */ const $93cf69256c93baa9$export$c2f8e0cc249a8d8f = {
3670
3699
  width: 2048,
3671
3700
  height: 2048,
@@ -4636,7 +4665,39 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
4636
4665
  // ── 0b. Color hierarchy — dominant/secondary/accent weighting ──
4637
4666
  const colorHierarchy = (0, $d016ad53434219a1$export$fabac4600b87056)(colors, rng);
4638
4667
  // ── 0c. Shape palette — curated shapes that work well together ──
4639
- const shapeNames = Object.keys((0, $9c828bde2acaae64$export$4ff7fc6f1af248b5));
4668
+ // Merge custom shapes into a combined registry
4669
+ const customShapeNames = [];
4670
+ let activeShapes;
4671
+ if (finalConfig.customShapes && Object.keys(finalConfig.customShapes).length > 0) {
4672
+ activeShapes = {
4673
+ ...(0, $9c828bde2acaae64$export$4ff7fc6f1af248b5)
4674
+ };
4675
+ for (const [name, def] of Object.entries(finalConfig.customShapes)){
4676
+ // Wrap CustomDrawFunction (ctx, size, rng) into DrawFunction (ctx, size, config?)
4677
+ const customDraw = def.draw;
4678
+ activeShapes[name] = (ctx, size, config)=>{
4679
+ customDraw(ctx, size, config?.rng ?? Math.random);
4680
+ };
4681
+ // Register profile for affinity system (inlined to avoid ESM interop issues)
4682
+ (0, $e73976f898150d4d$export$4343b39fe47bd82c)[name] = {
4683
+ tier: def.profile?.tier ?? 2,
4684
+ minSizeFraction: def.profile?.minSizeFraction ?? 0.05,
4685
+ maxSizeFraction: def.profile?.maxSizeFraction ?? 1.0,
4686
+ affinities: def.profile?.affinities ?? [
4687
+ "circle",
4688
+ "square"
4689
+ ],
4690
+ category: "procedural",
4691
+ heroCandidate: def.profile?.heroCandidate ?? false,
4692
+ bestStyles: def.profile?.bestStyles ?? [
4693
+ "fill-and-stroke",
4694
+ "watercolor"
4695
+ ]
4696
+ };
4697
+ customShapeNames.push(name);
4698
+ }
4699
+ }
4700
+ const shapeNames = Object.keys(activeShapes ?? (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5));
4640
4701
  const shapePalette = (0, $e73976f898150d4d$export$4a95df8944b5033b)(rng, shapeNames, archetype.name);
4641
4702
  // ── 0d. Color grading — unified tone for the whole image ───────
4642
4703
  const colorGrade = (0, $d016ad53434219a1$export$6d1620b367f86f7a)(rng);
@@ -4937,7 +4998,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
4937
4998
  renderStyle: heroStyle,
4938
4999
  rng: rng,
4939
5000
  lightAngle: lightAngle,
4940
- scaleFactor: scaleFactor
5001
+ scaleFactor: scaleFactor,
5002
+ activeShapes: activeShapes
4941
5003
  });
4942
5004
  heroCenter = {
4943
5005
  x: heroFocal.x,
@@ -5140,7 +5202,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5140
5202
  renderStyle: finalRenderStyle,
5141
5203
  rng: rng,
5142
5204
  lightAngle: lightAngle,
5143
- scaleFactor: scaleFactor
5205
+ scaleFactor: scaleFactor,
5206
+ activeShapes: activeShapes
5144
5207
  };
5145
5208
  if (shouldMirror) {
5146
5209
  (0, $c3de8257a8baa3b0$export$8bd8bbd1a8e53689)(ctx, shape, finalX, finalY, {
@@ -5171,7 +5234,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5171
5234
  rotation: rotation,
5172
5235
  proportionType: "GOLDEN_RATIO",
5173
5236
  renderStyle: "fill-only",
5174
- rng: rng
5237
+ rng: rng,
5238
+ activeShapes: activeShapes
5175
5239
  });
5176
5240
  }
5177
5241
  extrasSpent += glazePasses;
@@ -5211,7 +5275,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5211
5275
  rotation: rotation + (e + 1) * 15,
5212
5276
  proportionType: "GOLDEN_RATIO",
5213
5277
  renderStyle: finalRenderStyle,
5214
- rng: rng
5278
+ rng: rng,
5279
+ activeShapes: activeShapes
5215
5280
  });
5216
5281
  shapePositions.push({
5217
5282
  x: echoX,
@@ -5258,7 +5323,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5258
5323
  rotation: innerRot,
5259
5324
  proportionType: "GOLDEN_RATIO",
5260
5325
  renderStyle: innerStyle,
5261
- rng: rng
5326
+ rng: rng,
5327
+ activeShapes: activeShapes
5262
5328
  });
5263
5329
  extrasSpent += $4f72c5a314eddf25$var$RENDER_STYLE_COST[innerStyle] ?? 1;
5264
5330
  }
@@ -5305,7 +5371,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5305
5371
  rotation: member.rotation + groupRotation * 180 / Math.PI,
5306
5372
  proportionType: "GOLDEN_RATIO",
5307
5373
  renderStyle: memberStyle,
5308
- rng: rng
5374
+ rng: rng,
5375
+ activeShapes: activeShapes
5309
5376
  });
5310
5377
  shapePositions.push({
5311
5378
  x: mx,
@@ -5359,7 +5426,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5359
5426
  rotation: rotation + (r + 1) * 12,
5360
5427
  proportionType: "GOLDEN_RATIO",
5361
5428
  renderStyle: finalRenderStyle,
5362
- rng: rng
5429
+ rng: rng,
5430
+ activeShapes: activeShapes
5363
5431
  });
5364
5432
  shapePositions.push({
5365
5433
  x: rx,
@@ -5391,64 +5459,7 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
5391
5459
  _dt.extraCount = extrasSpent;
5392
5460
  }
5393
5461
  _mark("5_shape_layers");
5394
- // ── 5g. Layered masking / cutout portals ───────────────────────
5395
- // ~18% of images get 1-3 portal windows that paint over foreground
5396
- // with a tinted background wash, creating a "peek through" effect.
5397
- if (rng() < 0.18 && shapePositions.length > 3) {
5398
- const portalCount = 1 + Math.floor(rng() * 2);
5399
- for(let p = 0; p < portalCount; p++){
5400
- // Pick a position biased toward placed shapes
5401
- const sourceShape = shapePositions[Math.floor(rng() * shapePositions.length)];
5402
- const portalX = sourceShape.x + (rng() - 0.5) * sourceShape.size * 0.5;
5403
- const portalY = sourceShape.y + (rng() - 0.5) * sourceShape.size * 0.5;
5404
- const portalSize = adjustedMaxSize * (0.15 + rng() * 0.25);
5405
- // Pick a portal shape from the palette
5406
- const portalShape = (0, $e73976f898150d4d$export$3c37d9a045754d0e)(shapePalette, rng, portalSize / adjustedMaxSize);
5407
- const portalRotation = rng() * 360;
5408
- const portalAlpha = 0.6 + rng() * 0.35;
5409
- ctx.save();
5410
- ctx.translate(portalX, portalY);
5411
- ctx.rotate(portalRotation * Math.PI / 180);
5412
- // Step 1: Clip to the portal shape and fill with background wash
5413
- ctx.beginPath();
5414
- (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5)[portalShape]?.(ctx, portalSize);
5415
- ctx.clip();
5416
- // Fill the clipped region with a radial gradient from background colors
5417
- const portalColor = (0, $d016ad53434219a1$export$18a34c25ea7e724b)(bgStart, rng, 15, 0.1);
5418
- const portalGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, portalSize);
5419
- portalGrad.addColorStop(0, portalColor);
5420
- portalGrad.addColorStop(1, bgEnd);
5421
- ctx.globalAlpha = portalAlpha;
5422
- ctx.fillStyle = portalGrad;
5423
- ctx.fillRect(-portalSize, -portalSize, portalSize * 2, portalSize * 2);
5424
- // Optional: subtle inner texture — a few tiny dots inside the portal
5425
- if (rng() < 0.5) {
5426
- const dotCount = 3 + Math.floor(rng() * 5);
5427
- ctx.globalAlpha = portalAlpha * 0.3;
5428
- ctx.fillStyle = (0, $d016ad53434219a1$export$f2121afcad3d553f)((0, $d016ad53434219a1$export$b49f62f0a99da0e8)(colorHierarchy, rng), 0.2);
5429
- for(let d = 0; d < dotCount; d++){
5430
- const dx = (rng() - 0.5) * portalSize * 1.4;
5431
- const dy = (rng() - 0.5) * portalSize * 1.4;
5432
- const dr = (1 + rng() * 3) * scaleFactor;
5433
- ctx.beginPath();
5434
- ctx.arc(dx, dy, dr, 0, Math.PI * 2);
5435
- ctx.fill();
5436
- }
5437
- }
5438
- ctx.restore();
5439
- // Step 2: Draw a border ring around the portal (outside the clip)
5440
- ctx.save();
5441
- ctx.translate(portalX, portalY);
5442
- ctx.rotate(portalRotation * Math.PI / 180);
5443
- ctx.globalAlpha = 0.15 + rng() * 0.2;
5444
- ctx.strokeStyle = (0, $d016ad53434219a1$export$f2121afcad3d553f)((0, $d016ad53434219a1$export$b49f62f0a99da0e8)(colorHierarchy, rng), 0.5);
5445
- ctx.lineWidth = (1.5 + rng() * 2.5) * scaleFactor;
5446
- ctx.beginPath();
5447
- (0, $9c828bde2acaae64$export$4ff7fc6f1af248b5)[portalShape]?.(ctx, portalSize * 1.06);
5448
- ctx.stroke();
5449
- ctx.restore();
5450
- }
5451
- }
5462
+ // ── 5g. (Portal/cutout feature removed replaced by custom shapes API) ──
5452
5463
  _mark("5g_portals");
5453
5464
  // ── 6. Flow-line pass — variable color, branching, pressure ────
5454
5465
  // Optimized: collect all segments into width-quantized buckets, then
@@ -6046,6 +6057,8 @@ function $4f72c5a314eddf25$export$29a844702096332e(ctx, gitHash, config = {}) {
6046
6057
  }
6047
6058
  ctx.globalAlpha = 1;
6048
6059
  _mark("11_signature");
6060
+ // Clean up custom shape profiles to avoid leaking into subsequent renders
6061
+ for (const name of customShapeNames)delete (0, $e73976f898150d4d$export$4343b39fe47bd82c)[name];
6049
6062
  }
6050
6063
 
6051
6064