File size: 3,874 Bytes
213c234
 
 
 
 
 
 
 
 
 
 
 
f444918
 
 
 
 
213c234
c6f0353
 
f444918
213c234
f444918
c6f0353
f444918
 
 
c6f0353
 
213c234
c6f0353
f444918
 
213c234
 
c6f0353
213c234
 
f444918
213c234
f444918
 
 
 
213c234
f444918
 
 
 
213c234
 
 
f444918
 
 
 
 
 
 
 
 
213c234
c6f0353
213c234
f444918
c6f0353
f444918
213c234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type { PicletInstance } from '$lib/db/schema';
import { embedPicletMetadata } from './picletMetadata';

/**
 * Generates a shareable image of a piclet with embedded metadata
 */
export async function generateShareableImage(piclet: PicletInstance): Promise<Blob> {
  // Create canvas
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  if (!ctx) throw new Error('Could not create canvas context');
  
  // Set canvas size - narrower width to match content
  const canvasWidth = 700;
  const canvasHeight = 1536; // Taller to accommodate piclet at bottom
  canvas.width = canvasWidth;
  canvas.height = canvasHeight;
  
  // Fill background with solid sky blue
  ctx.fillStyle = '#87CEEB';
  ctx.fillRect(0, 0, canvasWidth, canvasHeight);
  
  // Load piclet image first
  const picletImg = await loadImage(piclet.imageData || piclet.imageUrl);
  const picletSize = 512;
  const picletX = (canvasWidth - picletSize) / 2;
  const picletY = canvasHeight - picletSize - 50; // Position near bottom with small margin
  
  // Load and draw grass platform positioned under the piclet
  const grassImg = await loadImage('/assets/grass.PNG');
  const platformSize = picletSize + 100; // Slightly larger than piclet
  const platformX = (canvasWidth - platformSize) / 2;
  const platformY = picletY + picletSize - 180; // Position so piclet sits on platform
  ctx.drawImage(grassImg, platformX, platformY, platformSize, platformSize);
  
  // Draw piclet on top of platform
  ctx.drawImage(picletImg, picletX, picletY, picletSize, picletSize);
  
  // Add piclet name with video game font
  ctx.fillStyle = 'white';
  ctx.strokeStyle = '#1e3a8a'; // Dark blue outline
  ctx.lineWidth = 8;
  // Try to use a more gaming-style font, fallback to Impact
  ctx.font = 'bold 72px "Press Start 2P", "Courier New", Impact, monospace';
  ctx.textAlign = 'center';
  ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
  ctx.shadowBlur = 10;
  ctx.shadowOffsetX = 4;
  ctx.shadowOffsetY = 4;
  
  const nameText = piclet.nickname || piclet.typeId;
  
  // Draw name with outline and shadow
  ctx.strokeText(nameText, canvasWidth / 2, 150);
  ctx.fillText(nameText, canvasWidth / 2, 150);
  
  // Reset shadow
  ctx.shadowColor = 'transparent';
  ctx.shadowBlur = 0;
  ctx.shadowOffsetX = 0;
  ctx.shadowOffsetY = 0;
  
  // Load and draw translucent watermark
  const logoImg = await loadImage('/assets/snap_logo.png');
  const logoSize = 120;
  ctx.globalAlpha = 0.3; // More translucent
  ctx.drawImage(logoImg, canvasWidth - logoSize - 20, canvasHeight - logoSize - 20, logoSize, logoSize);
  ctx.globalAlpha = 1.0;
  
  // Get the image as blob
  const blob = await canvasToBlob(canvas);
  
  // Embed metadata in the blob
  return embedPicletMetadata(blob, piclet);
}

/**
 * Downloads a piclet card image
 */
export async function downloadPicletCard(piclet: PicletInstance, filename?: string): Promise<void> {
  const blob = await generateShareableImage(piclet);
  const url = URL.createObjectURL(blob);
  
  const a = document.createElement('a');
  a.href = url;
  a.download = filename || `Piclet_${piclet.nickname || piclet.typeId}_Lv${piclet.level}.png`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  
  URL.revokeObjectURL(url);
}

/**
 * Helper to load an image
 */
function loadImage(src: string): Promise<HTMLImageElement> {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = () => resolve(img);
    img.onerror = reject;
    img.src = src;
  });
}

/**
 * Convert canvas to blob
 */
function canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {
  return new Promise((resolve, reject) => {
    canvas.toBlob((blob) => {
      if (blob) resolve(blob);
      else reject(new Error('Failed to create blob'));
    }, 'image/png');
  });
}