File size: 2,388 Bytes
59022ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Synthetic screens for offline demos and tests.

No display required: this module draws a small fake desktop - a top bar with Files
and Terminal, plus a Save dialog with a file-name field and Save/Cancel buttons - so
the whole pipeline (pixels, OCR, index, menu, model, action) can be exercised on a
headless machine, in CI, or before you let an agent near your real desktop.
"""

from __future__ import annotations

import glob
from pathlib import Path
from typing import Any


def _font(size: int) -> Any:
    from PIL import ImageFont

    candidates = [
        "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
        "/System/Library/Fonts/Supplemental/Arial.ttf",
        "C:/Windows/Fonts/arial.ttf",
    ] + glob.glob("/usr/share/fonts/**/*Regular*.ttf", recursive=True)
    for path in candidates:
        try:
            return ImageFont.truetype(path, size)
        except Exception:
            continue
    return ImageFont.load_default()


def fake_desktop(width: int = 720, height: int = 460) -> Any:
    """Draw a screenshot-like image: a desktop with an unsaved Save dialog."""
    from PIL import Image, ImageDraw

    image = Image.new("RGB", (width, height), (245, 246, 248))
    draw = ImageDraw.Draw(image)
    draw.rectangle([0, 0, width, 28], fill=(38, 40, 48))
    draw.text((12, 7), "Files", fill="white", font=_font(15))
    draw.text((90, 7), "Terminal", fill="white", font=_font(15))
    draw.rectangle([180, 90, 540, 330], fill="white", outline=(120, 120, 130), width=2)
    draw.text((200, 108), "Untitled document - unsaved changes",
              fill=(30, 30, 30), font=_font(16))
    draw.text((200, 170), "File name", fill=(60, 60, 60), font=_font(15))
    draw.rectangle([200, 195, 520, 225], fill=(252, 252, 252),
                   outline=(120, 120, 130), width=2)
    draw.rectangle([200, 265, 380, 300], fill=(66, 111, 220),
                   outline=(40, 70, 160), width=2)
    draw.text((275, 274), "Save", fill="white", font=_font(16))
    draw.rectangle([400, 265, 520, 300], fill=(230, 230, 235),
                   outline=(120, 120, 130), width=2)
    draw.text((440, 274), "Cancel", fill=(30, 30, 30), font=_font(16))
    return image


def write_fake_desktop(path: str | Path) -> Path:
    """Save :func:`fake_desktop` to a PNG (handy for ``--image``)."""
    target = Path(path)
    fake_desktop().save(target)
    return target