初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,179 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
from fastapi.testclient import TestClient
from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen
from PIL import Image
from app.fonts.store import MAX_FONT_UPLOAD_BYTES, FontCatalog
from app.main import create_app
def build_test_font(family: str = "Codex Test Sans", style: str = "Regular") -> bytes:
builder = FontBuilder(1000, isTTF=True)
glyph_order = [".notdef", "space", "A", "B"]
builder.setupGlyphOrder(glyph_order)
glyphs = {}
empty = TTGlyphPen(None)
glyphs[".notdef"] = empty.glyph()
glyphs["space"] = TTGlyphPen(None).glyph()
for name, inset in (("A", 100), ("B", 180)):
pen = TTGlyphPen(None)
pen.moveTo((inset, 0))
pen.lineTo((800 - inset, 0))
pen.lineTo((800 - inset, 800))
pen.lineTo((inset, 800))
pen.closePath()
glyphs[name] = pen.glyph()
builder.setupGlyf(glyphs)
builder.setupHorizontalMetrics({name: (900, 0) for name in glyph_order})
builder.setupHorizontalHeader(ascent=800, descent=-200)
builder.setupCharacterMap({32: "space", 65: "A", 66: "B"})
builder.setupNameTable({
"familyName": family,
"styleName": style,
"uniqueFontIdentifier": f"{family}-{style}",
"fullName": f"{family} {style}",
"psName": f"{family.replace(' ', '')}-{style.replace(' ', '')}",
})
builder.setupOS2(
sTypoAscender=800,
sTypoDescender=-200,
usWinAscent=800,
usWinDescent=200,
)
builder.setupPost()
builder.setupMaxp()
output = BytesIO()
builder.save(output)
return output.getvalue()
def test_font_catalog_import_duplicate_restart_and_render(tmp_path: Path) -> None:
font_bytes = build_test_font()
app = create_app(project_root=tmp_path, driver_kind="mock")
client = TestClient(app)
initial = client.get("/api/fonts")
assert initial.status_code == 200
document = initial.json()
assert document["items"][0] == {
"id": "default",
"label": "自动多语言字体",
"family": "自动多语言字体",
"style": "自动回退",
"source": "automatic",
}
assert document["accepted_extensions"] == [".ttf", ".otf", ".ttc", ".otc"]
assert document["max_upload_bytes"] == MAX_FONT_UPLOAD_BYTES
assert str(tmp_path) not in initial.text
created = client.post(
"/api/fonts/import?filename=Codex%20Test.ttf",
content=font_bytes,
headers={"Content-Type": "application/octet-stream"},
)
assert created.status_code == 201
payload = created.json()
assert payload["created"] is True
assert len(payload["fonts"]) == 1
imported = payload["fonts"][0]
assert imported["id"].startswith("user:")
assert imported["family"] == "Codex Test Sans"
assert imported["source"] == "imported"
assert str(tmp_path) not in created.text
stored = list((tmp_path / "data" / "fonts").glob("*.font"))
assert len(stored) == 1
assert stored[0].stem in imported["id"]
duplicate = client.post(
"/api/fonts/import?filename=renamed.otf",
content=font_bytes,
headers={"Content-Type": "application/octet-stream"},
)
assert duplicate.status_code == 200
assert duplicate.json() == {"created": False, "fonts": [imported]}
assert len(list((tmp_path / "data" / "fonts").glob("*.font"))) == 1
preview = client.post("/api/preview/text-layer", json={
"text": "AB",
"font": imported["id"],
"size": 18,
"x": 0,
"y": 0,
"align": "left",
"color": "#FFFFFF",
})
assert preview.status_code == 200
assert Image.open(BytesIO(preview.content)).getchannel("A").getbbox() is not None
restarted = TestClient(create_app(project_root=tmp_path, driver_kind="mock"))
items = restarted.get("/api/fonts").json()["items"]
assert imported in items
restarted_preview = restarted.post("/api/preview/text-layer", json={
"text": "A",
"font": imported["id"],
"size": 18,
"x": 0,
"y": 0,
"align": "left",
"color": "#FFFFFF",
})
assert restarted_preview.status_code == 200
def test_font_import_rejects_type_content_and_size_without_residue(tmp_path: Path) -> None:
client = TestClient(create_app(project_root=tmp_path, driver_kind="mock"))
root = tmp_path / "data" / "fonts"
wrong_content_type = client.post(
"/api/fonts/import?filename=test.ttf",
content=b"not-a-font",
headers={"Content-Type": "text/plain"},
)
assert wrong_content_type.status_code == 415
wrong_extension = client.post(
"/api/fonts/import?filename=test.woff2",
content=b"not-a-font",
headers={"Content-Type": "application/octet-stream"},
)
assert wrong_extension.status_code == 415
damaged = client.post(
"/api/fonts/import?filename=test.ttf",
content=b"not-a-font",
headers={"Content-Type": "application/octet-stream"},
)
assert damaged.status_code == 422
oversized = client.post(
"/api/fonts/import?filename=test.ttf",
content=b"x",
headers={
"Content-Type": "application/octet-stream",
"Content-Length": str(MAX_FONT_UPLOAD_BYTES + 1),
},
)
assert oversized.status_code == 413
assert not list(root.glob(".upload-*.tmp"))
assert not list(root.glob("*.font"))
def test_invalid_persisted_font_is_preserved_and_reported(tmp_path: Path) -> None:
root = tmp_path / "data" / "fonts"
root.mkdir(parents=True)
damaged = root / f"{'a' * 64}.font"
damaged.write_bytes(b"damaged")
catalog = FontCatalog(tmp_path / "data")
document = catalog.document()
assert damaged.read_bytes() == b"damaged"
assert document["warnings"] == [f"已保留但忽略损坏字体:{damaged.name}"]
assert all(item["source"] != "imported" for item in document["items"])