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/module.js CHANGED
@@ -2081,14 +2081,15 @@ function $9beb8f41637c29fd$export$909ab0580e273f19(style) {
2081
2081
  }
2082
2082
  }
2083
2083
  function $9beb8f41637c29fd$export$71b514a25c47df50(ctx, shape, x, y, config) {
2084
- const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation } = config;
2084
+ const { fillColor: fillColor, strokeColor: strokeColor, strokeWidth: strokeWidth, size: size, rotation: rotation, activeShapes: activeShapes } = config;
2085
2085
  ctx.save();
2086
2086
  ctx.translate(x, y);
2087
2087
  ctx.rotate(rotation * Math.PI / 180);
2088
2088
  ctx.fillStyle = fillColor;
2089
2089
  ctx.strokeStyle = strokeColor;
2090
2090
  ctx.lineWidth = strokeWidth;
2091
- const drawFunction = (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5)[shape];
2091
+ const registry = activeShapes ?? (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5);
2092
+ const drawFunction = registry[shape];
2092
2093
  if (drawFunction) {
2093
2094
  drawFunction(ctx, size);
2094
2095
  ctx.fill();
@@ -2598,7 +2599,8 @@ function $9beb8f41637c29fd$export$bb35a6995ddbf32d(ctx, shape, x, y, config) {
2598
2599
  } else ctx.fillStyle = fillColor;
2599
2600
  ctx.strokeStyle = strokeColor;
2600
2601
  ctx.lineWidth = strokeWidth;
2601
- const drawFunction = (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5)[shape];
2602
+ const registry = config.activeShapes ?? (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5);
2603
+ const drawFunction = registry[shape];
2602
2604
  if (drawFunction) {
2603
2605
  drawFunction(ctx, size, {
2604
2606
  rng: rng
@@ -3462,6 +3464,26 @@ const $24064302523652b1$export$4343b39fe47bd82c = {
3462
3464
  ]
3463
3465
  }
3464
3466
  };
3467
+ function $24064302523652b1$export$90912290d628650f(name, partial) {
3468
+ $24064302523652b1$export$4343b39fe47bd82c[name] = {
3469
+ tier: partial?.tier ?? 2,
3470
+ minSizeFraction: partial?.minSizeFraction ?? 0.05,
3471
+ maxSizeFraction: partial?.maxSizeFraction ?? 1.0,
3472
+ affinities: partial?.affinities ?? [
3473
+ "circle",
3474
+ "square"
3475
+ ],
3476
+ category: "procedural",
3477
+ heroCandidate: partial?.heroCandidate ?? false,
3478
+ bestStyles: partial?.bestStyles ?? [
3479
+ "fill-and-stroke",
3480
+ "watercolor"
3481
+ ]
3482
+ };
3483
+ }
3484
+ function $24064302523652b1$export$f4ca68bd046f15ae(name) {
3485
+ delete $24064302523652b1$export$4343b39fe47bd82c[name];
3486
+ }
3465
3487
  function $24064302523652b1$export$4a95df8944b5033b(rng, shapeNames, archetypeName) {
3466
3488
  const available = shapeNames.filter((s)=>$24064302523652b1$export$4343b39fe47bd82c[s]);
3467
3489
  // Pick a seed shape — tier 1 shapes that are hero candidates
@@ -3651,7 +3673,14 @@ function $24064302523652b1$export$ab873bb6fb56c1a8(shapeName, layerStyle, rng) {
3651
3673
 
3652
3674
 
3653
3675
  /**
3654
- * Configuration options for image generation.
3676
+ * Draw function signature for custom shapes.
3677
+ * The function should build a canvas path (moveTo/lineTo/arc/etc.)
3678
+ * centered at the origin. The pipeline handles translate, rotate,
3679
+ * fill, and stroke — your function just defines the geometry.
3680
+ *
3681
+ * @param ctx - Canvas 2D rendering context (already translated to shape center)
3682
+ * @param size - Bounding size in pixels
3683
+ * @param rng - Deterministic RNG seeded from the git hash — use this instead of Math.random()
3655
3684
  */ const $2bfb6a1ccb7a82ae$export$c2f8e0cc249a8d8f = {
3656
3685
  width: 2048,
3657
3686
  height: 2048,
@@ -4622,7 +4651,39 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
4622
4651
  // ── 0b. Color hierarchy — dominant/secondary/accent weighting ──
4623
4652
  const colorHierarchy = (0, $9d614e7d77fc2947$export$fabac4600b87056)(colors, rng);
4624
4653
  // ── 0c. Shape palette — curated shapes that work well together ──
4625
- const shapeNames = Object.keys((0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5));
4654
+ // Merge custom shapes into a combined registry
4655
+ const customShapeNames = [];
4656
+ let activeShapes;
4657
+ if (finalConfig.customShapes && Object.keys(finalConfig.customShapes).length > 0) {
4658
+ activeShapes = {
4659
+ ...(0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5)
4660
+ };
4661
+ for (const [name, def] of Object.entries(finalConfig.customShapes)){
4662
+ // Wrap CustomDrawFunction (ctx, size, rng) into DrawFunction (ctx, size, config?)
4663
+ const customDraw = def.draw;
4664
+ activeShapes[name] = (ctx, size, config)=>{
4665
+ customDraw(ctx, size, config?.rng ?? Math.random);
4666
+ };
4667
+ // Register profile for affinity system (inlined to avoid ESM interop issues)
4668
+ (0, $24064302523652b1$export$4343b39fe47bd82c)[name] = {
4669
+ tier: def.profile?.tier ?? 2,
4670
+ minSizeFraction: def.profile?.minSizeFraction ?? 0.05,
4671
+ maxSizeFraction: def.profile?.maxSizeFraction ?? 1.0,
4672
+ affinities: def.profile?.affinities ?? [
4673
+ "circle",
4674
+ "square"
4675
+ ],
4676
+ category: "procedural",
4677
+ heroCandidate: def.profile?.heroCandidate ?? false,
4678
+ bestStyles: def.profile?.bestStyles ?? [
4679
+ "fill-and-stroke",
4680
+ "watercolor"
4681
+ ]
4682
+ };
4683
+ customShapeNames.push(name);
4684
+ }
4685
+ }
4686
+ const shapeNames = Object.keys(activeShapes ?? (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5));
4626
4687
  const shapePalette = (0, $24064302523652b1$export$4a95df8944b5033b)(rng, shapeNames, archetype.name);
4627
4688
  // ── 0d. Color grading — unified tone for the whole image ───────
4628
4689
  const colorGrade = (0, $9d614e7d77fc2947$export$6d1620b367f86f7a)(rng);
@@ -4923,7 +4984,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
4923
4984
  renderStyle: heroStyle,
4924
4985
  rng: rng,
4925
4986
  lightAngle: lightAngle,
4926
- scaleFactor: scaleFactor
4987
+ scaleFactor: scaleFactor,
4988
+ activeShapes: activeShapes
4927
4989
  });
4928
4990
  heroCenter = {
4929
4991
  x: heroFocal.x,
@@ -5126,7 +5188,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5126
5188
  renderStyle: finalRenderStyle,
5127
5189
  rng: rng,
5128
5190
  lightAngle: lightAngle,
5129
- scaleFactor: scaleFactor
5191
+ scaleFactor: scaleFactor,
5192
+ activeShapes: activeShapes
5130
5193
  };
5131
5194
  if (shouldMirror) {
5132
5195
  (0, $9beb8f41637c29fd$export$8bd8bbd1a8e53689)(ctx, shape, finalX, finalY, {
@@ -5157,7 +5220,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5157
5220
  rotation: rotation,
5158
5221
  proportionType: "GOLDEN_RATIO",
5159
5222
  renderStyle: "fill-only",
5160
- rng: rng
5223
+ rng: rng,
5224
+ activeShapes: activeShapes
5161
5225
  });
5162
5226
  }
5163
5227
  extrasSpent += glazePasses;
@@ -5197,7 +5261,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5197
5261
  rotation: rotation + (e + 1) * 15,
5198
5262
  proportionType: "GOLDEN_RATIO",
5199
5263
  renderStyle: finalRenderStyle,
5200
- rng: rng
5264
+ rng: rng,
5265
+ activeShapes: activeShapes
5201
5266
  });
5202
5267
  shapePositions.push({
5203
5268
  x: echoX,
@@ -5244,7 +5309,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5244
5309
  rotation: innerRot,
5245
5310
  proportionType: "GOLDEN_RATIO",
5246
5311
  renderStyle: innerStyle,
5247
- rng: rng
5312
+ rng: rng,
5313
+ activeShapes: activeShapes
5248
5314
  });
5249
5315
  extrasSpent += $b623126c6e9cbb71$var$RENDER_STYLE_COST[innerStyle] ?? 1;
5250
5316
  }
@@ -5291,7 +5357,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5291
5357
  rotation: member.rotation + groupRotation * 180 / Math.PI,
5292
5358
  proportionType: "GOLDEN_RATIO",
5293
5359
  renderStyle: memberStyle,
5294
- rng: rng
5360
+ rng: rng,
5361
+ activeShapes: activeShapes
5295
5362
  });
5296
5363
  shapePositions.push({
5297
5364
  x: mx,
@@ -5345,7 +5412,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5345
5412
  rotation: rotation + (r + 1) * 12,
5346
5413
  proportionType: "GOLDEN_RATIO",
5347
5414
  renderStyle: finalRenderStyle,
5348
- rng: rng
5415
+ rng: rng,
5416
+ activeShapes: activeShapes
5349
5417
  });
5350
5418
  shapePositions.push({
5351
5419
  x: rx,
@@ -5377,64 +5445,7 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
5377
5445
  _dt.extraCount = extrasSpent;
5378
5446
  }
5379
5447
  _mark("5_shape_layers");
5380
- // ── 5g. Layered masking / cutout portals ───────────────────────
5381
- // ~18% of images get 1-3 portal windows that paint over foreground
5382
- // with a tinted background wash, creating a "peek through" effect.
5383
- if (rng() < 0.18 && shapePositions.length > 3) {
5384
- const portalCount = 1 + Math.floor(rng() * 2);
5385
- for(let p = 0; p < portalCount; p++){
5386
- // Pick a position biased toward placed shapes
5387
- const sourceShape = shapePositions[Math.floor(rng() * shapePositions.length)];
5388
- const portalX = sourceShape.x + (rng() - 0.5) * sourceShape.size * 0.5;
5389
- const portalY = sourceShape.y + (rng() - 0.5) * sourceShape.size * 0.5;
5390
- const portalSize = adjustedMaxSize * (0.15 + rng() * 0.25);
5391
- // Pick a portal shape from the palette
5392
- const portalShape = (0, $24064302523652b1$export$3c37d9a045754d0e)(shapePalette, rng, portalSize / adjustedMaxSize);
5393
- const portalRotation = rng() * 360;
5394
- const portalAlpha = 0.6 + rng() * 0.35;
5395
- ctx.save();
5396
- ctx.translate(portalX, portalY);
5397
- ctx.rotate(portalRotation * Math.PI / 180);
5398
- // Step 1: Clip to the portal shape and fill with background wash
5399
- ctx.beginPath();
5400
- (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5)[portalShape]?.(ctx, portalSize);
5401
- ctx.clip();
5402
- // Fill the clipped region with a radial gradient from background colors
5403
- const portalColor = (0, $9d614e7d77fc2947$export$18a34c25ea7e724b)(bgStart, rng, 15, 0.1);
5404
- const portalGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, portalSize);
5405
- portalGrad.addColorStop(0, portalColor);
5406
- portalGrad.addColorStop(1, bgEnd);
5407
- ctx.globalAlpha = portalAlpha;
5408
- ctx.fillStyle = portalGrad;
5409
- ctx.fillRect(-portalSize, -portalSize, portalSize * 2, portalSize * 2);
5410
- // Optional: subtle inner texture — a few tiny dots inside the portal
5411
- if (rng() < 0.5) {
5412
- const dotCount = 3 + Math.floor(rng() * 5);
5413
- ctx.globalAlpha = portalAlpha * 0.3;
5414
- ctx.fillStyle = (0, $9d614e7d77fc2947$export$f2121afcad3d553f)((0, $9d614e7d77fc2947$export$b49f62f0a99da0e8)(colorHierarchy, rng), 0.2);
5415
- for(let d = 0; d < dotCount; d++){
5416
- const dx = (rng() - 0.5) * portalSize * 1.4;
5417
- const dy = (rng() - 0.5) * portalSize * 1.4;
5418
- const dr = (1 + rng() * 3) * scaleFactor;
5419
- ctx.beginPath();
5420
- ctx.arc(dx, dy, dr, 0, Math.PI * 2);
5421
- ctx.fill();
5422
- }
5423
- }
5424
- ctx.restore();
5425
- // Step 2: Draw a border ring around the portal (outside the clip)
5426
- ctx.save();
5427
- ctx.translate(portalX, portalY);
5428
- ctx.rotate(portalRotation * Math.PI / 180);
5429
- ctx.globalAlpha = 0.15 + rng() * 0.2;
5430
- ctx.strokeStyle = (0, $9d614e7d77fc2947$export$f2121afcad3d553f)((0, $9d614e7d77fc2947$export$b49f62f0a99da0e8)(colorHierarchy, rng), 0.5);
5431
- ctx.lineWidth = (1.5 + rng() * 2.5) * scaleFactor;
5432
- ctx.beginPath();
5433
- (0, $701ba7c7229ef06d$export$4ff7fc6f1af248b5)[portalShape]?.(ctx, portalSize * 1.06);
5434
- ctx.stroke();
5435
- ctx.restore();
5436
- }
5437
- }
5448
+ // ── 5g. (Portal/cutout feature removed replaced by custom shapes API) ──
5438
5449
  _mark("5g_portals");
5439
5450
  // ── 6. Flow-line pass — variable color, branching, pressure ────
5440
5451
  // Optimized: collect all segments into width-quantized buckets, then
@@ -6032,6 +6043,8 @@ function $b623126c6e9cbb71$export$29a844702096332e(ctx, gitHash, config = {}) {
6032
6043
  }
6033
6044
  ctx.globalAlpha = 1;
6034
6045
  _mark("11_signature");
6046
+ // Clean up custom shape profiles to avoid leaking into subsequent renders
6047
+ for (const name of customShapeNames)delete (0, $24064302523652b1$export$4343b39fe47bd82c)[name];
6035
6048
  }
6036
6049
 
6037
6050