Tingchenliang commited on
Commit
e48e154
·
verified ·
1 Parent(s): 778f8e1

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +738 -19
index.html CHANGED
@@ -1,19 +1,738 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Macintosh 128K Simulator with MacPaint</title>
7
+ <style>
8
+ :root {
9
+ --mac-beige: #f0f0f0;
10
+ --mac-dark-beige: #d0d0d0;
11
+ --mac-screen-bg: #3a3a3a;
12
+ --mac-desktop: #c0c0c0;
13
+ --mac-window: #ffffff;
14
+ --mac-border: #808080;
15
+ --mac-active-border: #000000;
16
+ --mac-text: #000000;
17
+ --mac-menu-bg: #ffffff;
18
+ --mac-menu-active: #000000;
19
+ --mac-menu-active-text: #ffffff;
20
+ --mac-icon-text: #000000;
21
+ --mac-button-face: #c0c0c0;
22
+ --mac-button-shadow: #808080;
23
+ --mac-button-highlight: #ffffff;
24
+ }
25
+
26
+ * {
27
+ margin: 0;
28
+ padding: 0;
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ body {
33
+ font-family: 'Chicago', 'Geneva', sans-serif;
34
+ background: linear-gradient(135deg, #e0e0e0 0%, #c0c0c0 100%);
35
+ min-height: 100vh;
36
+ display: flex;
37
+ justify-content: center;
38
+ align-items: center;
39
+ padding: 20px;
40
+ }
41
+
42
+ /* Macintosh 128K Computer */
43
+ .macintosh {
44
+ background: var(--mac-beige);
45
+ border-radius: 20px;
46
+ padding: 40px 30px 30px;
47
+ box-shadow:
48
+ 0 20px 40px rgba(0, 0, 0, 0.3),
49
+ inset 0 -2px 5px rgba(0, 0, 0, 0.1);
50
+ position: relative;
51
+ max-width: 800px;
52
+ width: 100%;
53
+ }
54
+
55
+ /* Screen Frame */
56
+ .screen-frame {
57
+ background: var(--mac-dark-beige);
58
+ border-radius: 10px;
59
+ padding: 20px;
60
+ box-shadow:
61
+ inset 0 2px 5px rgba(0, 0, 0, 0.2),
62
+ 0 2px 3px rgba(0, 0, 0, 0.1);
63
+ position: relative;
64
+ }
65
+
66
+ /* Screen */
67
+ .screen {
68
+ background: var(--mac-screen-bg);
69
+ border-radius: 5px;
70
+ aspect-ratio: 4/3;
71
+ position: relative;
72
+ overflow: hidden;
73
+ cursor: default;
74
+ }
75
+
76
+ /* Desktop */
77
+ .desktop {
78
+ background: var(--mac-desktop);
79
+ width: 100%;
80
+ height: 100%;
81
+ position: relative;
82
+ background-image:
83
+ repeating-linear-gradient(
84
+ 0deg,
85
+ transparent,
86
+ transparent 2px,
87
+ rgba(0, 0, 0, 0.03) 2px,
88
+ rgba(0, 0, 0, 0.03) 4px
89
+ ),
90
+ repeating-linear-gradient(
91
+ 90deg,
92
+ transparent,
93
+ transparent 2px,
94
+ rgba(0, 0, 0, 0.03) 2px,
95
+ rgba(0, 0, 0, 0.03) 4px
96
+ );
97
+ }
98
+
99
+ /* Menu Bar */
100
+ .menu-bar {
101
+ background: var(--mac-menu-bg);
102
+ border-bottom: 1px solid var(--mac-border);
103
+ padding: 3px 5px;
104
+ display: flex;
105
+ gap: 20px;
106
+ font-size: 11px;
107
+ position: absolute;
108
+ top: 0;
109
+ left: 0;
110
+ right: 0;
111
+ z-index: 1000;
112
+ }
113
+
114
+ .menu-item {
115
+ padding: 2px 8px;
116
+ cursor: pointer;
117
+ user-select: none;
118
+ }
119
+
120
+ .menu-item:hover {
121
+ background: var(--mac-menu-active);
122
+ color: var(--mac-menu-active-text);
123
+ }
124
+
125
+ /* MacPaint Window */
126
+ .window {
127
+ position: absolute;
128
+ background: var(--mac-window);
129
+ border: 2px solid var(--mac-border);
130
+ box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
131
+ top: 30px;
132
+ left: 20px;
133
+ right: 20px;
134
+ bottom: 20px;
135
+ display: flex;
136
+ flex-direction: column;
137
+ }
138
+
139
+ .window.active {
140
+ border-color: var(--mac-active-border);
141
+ }
142
+
143
+ /* Window Title Bar */
144
+ .title-bar {
145
+ background: linear-gradient(to bottom, #ffffff, #e0e0e0);
146
+ border-bottom: 1px solid var(--mac-border);
147
+ padding: 3px 5px;
148
+ display: flex;
149
+ justify-content: space-between;
150
+ align-items: center;
151
+ cursor: move;
152
+ }
153
+
154
+ .title-text {
155
+ font-size: 11px;
156
+ font-weight: bold;
157
+ }
158
+
159
+ .window-controls {
160
+ display: flex;
161
+ gap: 2px;
162
+ }
163
+
164
+ .window-control {
165
+ width: 16px;
166
+ height: 16px;
167
+ background: var(--mac-button-face);
168
+ border: 1px solid var(--mac-border);
169
+ cursor: pointer;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ font-size: 10px;
174
+ line-height: 1;
175
+ }
176
+
177
+ .window-control:active {
178
+ border-color: var(--mac-active-border);
179
+ }
180
+
181
+ /* MacPaint Content */
182
+ .macpaint-content {
183
+ flex: 1;
184
+ display: flex;
185
+ overflow: hidden;
186
+ }
187
+
188
+ /* Tool Palette */
189
+ .tool-palette {
190
+ width: 60px;
191
+ background: var(--mac-button-face);
192
+ border-right: 1px solid var(--mac-border);
193
+ padding: 5px;
194
+ display: flex;
195
+ flex-direction: column;
196
+ gap: 5px;
197
+ }
198
+
199
+ .tool-button {
200
+ width: 48px;
201
+ height: 48px;
202
+ background: var(--mac-window);
203
+ border: 2px solid var(--mac-border);
204
+ cursor: pointer;
205
+ display: flex;
206
+ align-items: center;
207
+ justify-content: center;
208
+ font-size: 20px;
209
+ transition: all 0.1s;
210
+ position: relative;
211
+ }
212
+
213
+ .tool-button:hover {
214
+ background: var(--mac-button-highlight);
215
+ }
216
+
217
+ .tool-button.active {
218
+ background: var(--mac-button-face);
219
+ border-color: var(--mac-active-border);
220
+ box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.2);
221
+ }
222
+
223
+ .tool-button::after {
224
+ content: attr(data-tooltip);
225
+ position: absolute;
226
+ left: 60px;
227
+ background: var(--mac-beige);
228
+ border: 1px solid var(--mac-border);
229
+ padding: 2px 5px;
230
+ font-size: 10px;
231
+ white-space: nowrap;
232
+ opacity: 0;
233
+ pointer-events: none;
234
+ transition: opacity 0.2s;
235
+ }
236
+
237
+ .tool-button:hover::after {
238
+ opacity: 1;
239
+ }
240
+
241
+ /* Canvas Area */
242
+ .canvas-area {
243
+ flex: 1;
244
+ display: flex;
245
+ flex-direction: column;
246
+ background: #808080;
247
+ padding: 10px;
248
+ }
249
+
250
+ .canvas-container {
251
+ flex: 1;
252
+ background: white;
253
+ position: relative;
254
+ overflow: hidden;
255
+ box-shadow: inset 2px 2px 5px rgba(0, 0, 0, 0.2);
256
+ }
257
+
258
+ #drawingCanvas {
259
+ position: absolute;
260
+ top: 0;
261
+ left: 0;
262
+ cursor: crosshair;
263
+ }
264
+
265
+ /* Info Bar */
266
+ .info-bar {
267
+ background: var(--mac-button-face);
268
+ border-top: 1px solid var(--mac-border);
269
+ padding: 3px 10px;
270
+ display: flex;
271
+ justify-content: space-between;
272
+ font-size: 11px;
273
+ }
274
+
275
+ /* Color Palette */
276
+ .color-palette {
277
+ display: flex;
278
+ gap: 3px;
279
+ align-items: center;
280
+ }
281
+
282
+ .color-swatch {
283
+ width: 20px;
284
+ height: 20px;
285
+ border: 2px solid var(--mac-border);
286
+ cursor: pointer;
287
+ transition: all 0.1s;
288
+ }
289
+
290
+ .color-swatch.active {
291
+ border-color: var(--mac-active-border);
292
+ box-shadow: 0 0 0 1px white;
293
+ }
294
+
295
+ /* Icons */
296
+ .desktop-icon {
297
+ position: absolute;
298
+ width: 64px;
299
+ text-align: center;
300
+ cursor: pointer;
301
+ user-select: none;
302
+ }
303
+
304
+ .icon-image {
305
+ width: 32px;
306
+ height: 32px;
307
+ margin: 0 auto;
308
+ background: var(--mac-icon-text);
309
+ mask-size: contain;
310
+ mask-repeat: no-repeat;
311
+ mask-position: center;
312
+ -webkit-mask-size: contain;
313
+ -webkit-mask-repeat: no-repeat;
314
+ -webkit-mask-position: center;
315
+ }
316
+
317
+ .icon-label {
318
+ font-size: 9px;
319
+ color: var(--mac-icon-text);
320
+ margin-top: 2px;
321
+ text-shadow: 0 0 1px white, 0 0 1px white, 0 0 1px white;
322
+ }
323
+
324
+ /* Responsive Design */
325
+ @media (max-width: 768px) {
326
+ .macintosh {
327
+ padding: 20px 15px 15px;
328
+ }
329
+
330
+ .tool-palette {
331
+ width: 50px;
332
+ }
333
+
334
+ .tool-button {
335
+ width: 40px;
336
+ height: 40px;
337
+ font-size: 16px;
338
+ }
339
+ }
340
+
341
+ @media (max-width: 480px) {
342
+ .menu-bar {
343
+ gap: 10px;
344
+ font-size: 10px;
345
+ }
346
+
347
+ .tool-palette {
348
+ width: 40px;
349
+ }
350
+
351
+ .tool-button {
352
+ width: 32px;
353
+ height: 32px;
354
+ font-size: 14px;
355
+ }
356
+ }
357
+ </style>
358
+ </head>
359
+ <body>
360
+ <div class="macintosh">
361
+ <div class="screen-frame">
362
+ <div class="screen">
363
+ <div class="desktop">
364
+ <div class="menu-bar">
365
+ <div class="menu-item">File</div>
366
+ <div class="menu-item">Edit</div>
367
+ <div class="menu-item">View</div>
368
+ <div class="menu-item">Special</div>
369
+ </div>
370
+
371
+ <!-- MacPaint Window -->
372
+ <div class="window active" id="macpaintWindow">
373
+ <div class="title-bar" id="titleBar">
374
+ <span class="title-text">MacPaint</span>
375
+ <div class="window-controls">
376
+ <div class="window-control" id="minimizeBtn">−</div>
377
+ <div class="window-control" id="maximizeBtn">□</div>
378
+ <div class="window-control" id="closeBtn">×</div>
379
+ </div>
380
+ </div>
381
+
382
+ <div class="macpaint-content">
383
+ <div class="tool-palette">
384
+ <div class="tool-button active" data-tool="pencil" data-tooltip="Pencil">✏️</div>
385
+ <div class="tool-button" data-tool="eraser" data-tooltip="Eraser">🧹</div>
386
+ <div class="tool-button" data-tool="line" data-tooltip="Line">📏</div>
387
+ <div class="tool-button" data-tool="rectangle" data-tooltip="Rectangle">⬜</div>
388
+ <div class="tool-button" data-tool="circle" data-tooltip="Circle">⭕</div>
389
+ <div class="tool-button" data-tool="fill" data-tooltip="Fill">🪣</div>
390
+ <div class="tool-button" data-tool="text" data-tooltip="Text">T</div>
391
+ <div class="tool-button" data-tool="spray" data-tooltip="Spray">💨</div>
392
+ </div>
393
+
394
+ <div class="canvas-area">
395
+ <div class="canvas-container">
396
+ <canvas id="drawingCanvas"></canvas>
397
+ </div>
398
+
399
+ <div class="info-bar">
400
+ <div class="color-palette">
401
+ <div class="color-swatch active" style="background: #000000" data-color="#000000"></div>
402
+ <div class="color-swatch" style="background: #ffffff" data-color="#ffffff"></div>
403
+ <div class="color-swatch" style="background: #ff0000" data-color="#ff0000"></div>
404
+ <div class="color-swatch" style="background: #00ff00" data-color="#00ff00"></div>
405
+ <div class="color-swatch" style="background: #0000ff" data-color="#0000ff"></div>
406
+ <div class="color-swatch" style="background: #ffff00" data-color="#ffff00"></div>
407
+ <div class="color-swatch" style="background: #ff00ff" data-color="#ff00ff"></div>
408
+ <div class="color-swatch" style="background: #00ffff" data-color="#00ffff"></div>
409
+ </div>
410
+ <div id="coordinates">0, 0</div>
411
+ </div>
412
+ </div>
413
+ </div>
414
+ </div>
415
+ </div>
416
+ </div>
417
+ </div>
418
+ </div>
419
+
420
+ <script>
421
+ // Canvas setup
422
+ const canvas = document.getElementById('drawingCanvas');
423
+ const ctx = canvas.getContext('2d');
424
+ const canvasContainer = document.querySelector('.canvas-container');
425
+
426
+ // Drawing state
427
+ let isDrawing = false;
428
+ let currentTool = 'pencil';
429
+ let currentColor = '#000000';
430
+ let startX, startY;
431
+ let snapshot;
432
+
433
+ // Resize canvas to fit container
434
+ function resizeCanvas() {
435
+ canvas.width = canvasContainer.clientWidth;
436
+ canvas.height = canvasContainer.clientHeight;
437
+ ctx.fillStyle = 'white';
438
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
439
+ }
440
+
441
+ resizeCanvas();
442
+ window.addEventListener('resize', resizeCanvas);
443
+
444
+ // Tool selection
445
+ document.querySelectorAll('.tool-button').forEach(button => {
446
+ button.addEventListener('click', function() {
447
+ document.querySelector('.tool-button.active').classList.remove('active');
448
+ this.classList.add('active');
449
+ currentTool = this.dataset.tool;
450
+ canvas.style.cursor = currentTool === 'text' ? 'text' : 'crosshair';
451
+ });
452
+ });
453
+
454
+ // Color selection
455
+ document.querySelectorAll('.color-swatch').forEach(swatch => {
456
+ swatch.addEventListener('click', function() {
457
+ document.querySelector('.color-swatch.active').classList.remove('active');
458
+ this.classList.add('active');
459
+ currentColor = this.dataset.color;
460
+ });
461
+ });
462
+
463
+ // Drawing functions
464
+ function startDrawing(e) {
465
+ isDrawing = true;
466
+ const rect = canvas.getBoundingClientRect();
467
+ startX = e.clientX - rect.left;
468
+ startY = e.clientY - rect.top;
469
+
470
+ // Save canvas state for shape tools
471
+ if (['line', 'rectangle', 'circle'].includes(currentTool)) {
472
+ snapshot = ctx.getImageData(0, 0, canvas.width, canvas.height);
473
+ }
474
+
475
+ if (currentTool === 'pencil' || currentTool === 'eraser') {
476
+ ctx.beginPath();
477
+ ctx.moveTo(startX, startY);
478
+ }
479
+ }
480
+
481
+ function draw(e) {
482
+ if (!isDrawing) return;
483
+
484
+ const rect = canvas.getBoundingClientRect();
485
+ const x = e.clientX - rect.left;
486
+ const y = e.clientY - rect.top;
487
+
488
+ // Update coordinates
489
+ document.getElementById('coordinates').textContent = `${Math.round(x)}, ${Math.round(y)}`;
490
+
491
+ ctx.lineWidth = 2;
492
+ ctx.lineCap = 'round';
493
+
494
+ switch(currentTool) {
495
+ case 'pencil':
496
+ ctx.globalCompositeOperation = 'source-over';
497
+ ctx.strokeStyle = currentColor;
498
+ ctx.lineTo(x, y);
499
+ ctx.stroke();
500
+ break;
501
+
502
+ case 'eraser':
503
+ ctx.globalCompositeOperation = 'destination-out';
504
+ ctx.lineTo(x, y);
505
+ ctx.stroke();
506
+ break;
507
+
508
+ case 'line':
509
+ ctx.putImageData(snapshot, 0, 0);
510
+ ctx.globalCompositeOperation = 'source-over';
511
+ ctx.strokeStyle = currentColor;
512
+ ctx.beginPath();
513
+ ctx.moveTo(startX, startY);
514
+ ctx.lineTo(x, y);
515
+ ctx.stroke();
516
+ break;
517
+
518
+ case 'rectangle':
519
+ ctx.putImageData(snapshot, 0, 0);
520
+ ctx.globalCompositeOperation = 'source-over';
521
+ ctx.strokeStyle = currentColor;
522
+ ctx.strokeRect(startX, startY, x - startX, y - startY);
523
+ break;
524
+
525
+ case 'circle':
526
+ ctx.putImageData(snapshot, 0, 0);
527
+ ctx.globalCompositeOperation = 'source-over';
528
+ ctx.strokeStyle = currentColor;
529
+ ctx.beginPath();
530
+ const radius = Math.sqrt(Math.pow(x - startX, 2) + Math.pow(y - startY, 2));
531
+ ctx.arc(startX, startY, radius, 0, 2 * Math.PI);
532
+ ctx.stroke();
533
+ break;
534
+
535
+ case 'spray':
536
+ ctx.globalCompositeOperation = 'source-over';
537
+ ctx.fillStyle = currentColor;
538
+ for (let i = 0; i < 20; i++) {
539
+ const offsetX = (Math.random() - 0.5) * 20;
540
+ const offsetY = (Math.random() - 0.5) * 20;
541
+ ctx.fillRect(x + offsetX, y + offsetY, 1, 1);
542
+ }
543
+ break;
544
+ }
545
+ }
546
+
547
+ function stopDrawing() {
548
+ isDrawing = false;
549
+ ctx.beginPath();
550
+ }
551
+
552
+ // Mouse events
553
+ canvas.addEventListener('mousedown', startDrawing);
554
+ canvas.addEventListener('mousemove', draw);
555
+ canvas.addEventListener('mouseup', stopDrawing);
556
+ canvas.addEventListener('mouseout', stopDrawing);
557
+
558
+ // Touch events for mobile
559
+ canvas.addEventListener('touchstart', (e) => {
560
+ e.preventDefault();
561
+ const touch = e.touches[0];
562
+ const mouseEvent = new MouseEvent('mousedown', {
563
+ clientX: touch.clientX,
564
+ clientY: touch.clientY
565
+ });
566
+ canvas.dispatchEvent(mouseEvent);
567
+ });
568
+
569
+ canvas.addEventListener('touchmove', (e) => {
570
+ e.preventDefault();
571
+ const touch = e.touches[0];
572
+ const mouseEvent = new MouseEvent('mousemove', {
573
+ clientX: touch.clientX,
574
+ clientY: touch.clientY
575
+ });
576
+ canvas.dispatchEvent(mouseEvent);
577
+ });
578
+
579
+ canvas.addEventListener('touchend', (e) => {
580
+ e.preventDefault();
581
+ const mouseEvent = new MouseEvent('mouseup', {});
582
+ canvas.dispatchEvent(mouseEvent);
583
+ });
584
+
585
+ // Fill tool
586
+ canvas.addEventListener('click', function(e) {
587
+ if (currentTool === 'fill') {
588
+ const rect = canvas.getBoundingClientRect();
589
+ const x = Math.floor(e.clientX - rect.left);
590
+ const y = Math.floor(e.clientY - rect.top);
591
+
592
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
593
+ const targetColor = getPixelColor(imageData, x, y);
594
+ const fillColor = hexToRgb(currentColor);
595
+
596
+ if (colorsMatch(targetColor, fillColor)) return;
597
+
598
+ floodFill(imageData, x, y, targetColor, fillColor);
599
+ ctx.putImageData(imageData, 0, 0);
600
+ }
601
+ });
602
+
603
+ function getPixelColor(imageData, x, y) {
604
+ const index = (y * imageData.width + x) * 4;
605
+ return {
606
+ r: imageData.data[index],
607
+ g: imageData.data[index + 1],
608
+ b: imageData.data[index + 2],
609
+ a: imageData.data[index + 3]
610
+ };
611
+ }
612
+
613
+ function setPixelColor(imageData, x, y, color) {
614
+ const index = (y * imageData.width + x) * 4;
615
+ imageData.data[index] = color.r;
616
+ imageData.data[index + 1] = color.g;
617
+ imageData.data[index + 2] = color.b;
618
+ imageData.data[index + 3] = 255;
619
+ }
620
+
621
+ function colorsMatch(color1, color2) {
622
+ return color1.r === color2.r && color1.g === color2.g &&
623
+ color1.b === color2.b && color1.a === color2.a;
624
+ }
625
+
626
+ function hexToRgb(hex) {
627
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
628
+ return result ? {
629
+ r: parseInt(result[1], 16),
630
+ g: parseInt(result[2], 16),
631
+ b: parseInt(result[3], 16),
632
+ a: 255
633
+ } : null;
634
+ }
635
+
636
+ function floodFill(imageData, x, y, targetColor, fillColor) {
637
+ const stack = [[x, y]];
638
+ const width = imageData.width;
639
+ const height = imageData.height;
640
+ const visited = new Set();
641
+
642
+ while (stack.length > 0) {
643
+ const [cx, cy] = stack.pop();
644
+ const key = `${cx},${cy}`;
645
+
646
+ if (visited.has(key)) continue;
647
+ if (cx < 0 || cx >= width || cy < 0 || cy >= height) continue;
648
+
649
+ const currentColor = getPixelColor(imageData, cx, cy);
650
+ if (!colorsMatch(currentColor, targetColor)) continue;
651
+
652
+ visited.add(key);
653
+ setPixelColor(imageData, cx, cy, fillColor);
654
+
655
+ stack.push([cx + 1, cy]);
656
+ stack.push([cx - 1, cy]);
657
+ stack.push([cx, cy + 1]);
658
+ stack.push([cx, cy - 1]);
659
+ }
660
+ }
661
+
662
+ // Text tool
663
+ canvas.addEventListener('click', function(e) {
664
+ if (currentTool === 'text') {
665
+ const rect = canvas.getBoundingClientRect();
666
+ const x = e.clientX - rect.left;
667
+ const y = e.clientY - rect.top;
668
+
669
+ const text = prompt('Enter text:');
670
+ if (text) {
671
+ ctx.globalCompositeOperation = 'source-over';
672
+ ctx.fillStyle = currentColor;
673
+ ctx.font = '16px Chicago, Geneva, sans-serif';
674
+ ctx.fillText(text, x, y);
675
+ }
676
+ }
677
+ });
678
+
679
+ // Window controls
680
+ document.getElementById('closeBtn').addEventListener('click', function() {
681
+ if (confirm('Are you sure you want to close MacPaint?')) {
682
+ document.getElementById('macpaintWindow').style.display = 'none';
683
+ }
684
+ });
685
+
686
+ document.getElementById('minimizeBtn').addEventListener('click', function() {
687
+ alert('Minimize not implemented in this demo');
688
+ });
689
+
690
+ document.getElementById('maximizeBtn').addEventListener('click', function() {
691
+ if (document.getElementById('macpaintWindow').classList.contains('maximized')) {
692
+ document.getElementById('macpaintWindow').classList.remove('maximized');
693
+ document.getElementById('macpaintWindow').style.cssText = '';
694
+ } else {
695
+ document.getElementById('macpaintWindow').classList.add('maximized');
696
+ document.getElementById('macpaintWindow').style.cssText = `
697
+ top: 30px !important;
698
+ left: 20px !important;
699
+ right: 20px !important;
700
+ bottom: 20px !important;
701
+ `;
702
+ }
703
+ });
704
+
705
+ // Window dragging
706
+ let isDragging = false;
707
+ let dragOffsetX, dragOffsetY;
708
+
709
+ document.getElementById('titleBar').addEventListener('mousedown', function(e) {
710
+ isDragging = true;
711
+ dragOffsetX = e.clientX - document.getElementById('macpaintWindow').offsetLeft;
712
+ dragOffsetY = e.clientY - document.getElementById('macpaintWindow').offsetTop;
713
+ });
714
+
715
+ document.addEventListener('mousemove', function(e) {
716
+ if (isDragging) {
717
+ const window = document.getElementById('macpaintWindow');
718
+ window.style.left = (e.clientX - dragOffsetX) + 'px';
719
+ window.style.top = (e.clientY - dragOffsetY) + 'px';
720
+ window.style.right = 'auto';
721
+ window.style.bottom = 'auto';
722
+ }
723
+ });
724
+
725
+ document.addEventListener('mouseup', function() {
726
+ isDragging = false;
727
+ });
728
+
729
+ // Clear canvas on double-click (Easter egg)
730
+ canvas.addEventListener('dblclick', function() {
731
+ if (confirm('Clear canvas?')) {
732
+ ctx.fillStyle = 'white';
733
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
734
+ }
735
+ });
736
+ </script>
737
+ </body>
738
+ </html>