Fix logo generator: remove decorative fonts and fix missing char spacing
This commit is contained in:
1 parent
9a7b40eae6
commit
0272da09c1
3 files changed
+27
-56
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, useTransition } from
|
|||||||
import { ContentCard } from "@/components/public/ui";
|
import { ContentCard } from "@/components/public/ui";
|
||||||
import { saveLogo } from "@/actions/save-logo";
|
import { saveLogo } from "@/actions/save-logo";
|
||||||
import { HABBO_FONT_GROUPS } from "@/components/public/habbo-fonts";
|
import { HABBO_FONT_GROUPS } from "@/components/public/habbo-fonts";
|
||||||
import { getFontInfo, measureText, renderToCanvas } from "@/components/public/sprite-font";
|
import { getFontInfo, getMissingChars, renderToCanvas } from "@/components/public/sprite-font";
|
||||||
|
|
||||||
export default function LogoGenerator() {
|
export default function LogoGenerator() {
|
||||||
const [text, setText] = useState("Atom");
|
const [text, setText] = useState("Atom");
|
||||||
@@ -13,6 +13,7 @@ export default function LogoGenerator() {
|
|||||||
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "done" | "error">("idle");
|
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "done" | "error">("idle");
|
||||||
const [fontLoaded, setFontLoaded] = useState(false);
|
const [fontLoaded, setFontLoaded] = useState(false);
|
||||||
const [fontError, setFontError] = useState(false);
|
const [fontError, setFontError] = useState(false);
|
||||||
|
const [missingChars, setMissingChars] = useState<Set<string>>(new Set());
|
||||||
const [, startTransition] = useTransition();
|
const [, startTransition] = useTransition();
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ export default function LogoGenerator() {
|
|||||||
const ctx = canvasRef.current.getContext("2d");
|
const ctx = canvasRef.current.getContext("2d");
|
||||||
ctx?.drawImage(canvas, 0, 0);
|
ctx?.drawImage(canvas, 0, 0);
|
||||||
}
|
}
|
||||||
|
setMissingChars(getMissingChars(info.chars, safeText));
|
||||||
setFontLoaded(true);
|
setFontLoaded(true);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -224,7 +226,14 @@ export default function LogoGenerator() {
|
|||||||
{fontError ? (
|
{fontError ? (
|
||||||
<p className="muted">Failed to load font sprite.</p>
|
<p className="muted">Failed to load font sprite.</p>
|
||||||
) : fontLoaded ? (
|
) : fontLoaded ? (
|
||||||
|
<>
|
||||||
<canvas ref={canvasRef} style={{ maxWidth: "100%", height: "auto" }} />
|
<canvas ref={canvasRef} style={{ maxWidth: "100%", height: "auto" }} />
|
||||||
|
{missingChars.size > 0 && (
|
||||||
|
<p className="muted" style={{ marginTop: 8, fontSize: "0.8rem" }}>
|
||||||
|
Note: this font does not have characters: {[...missingChars].join(", ")}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<p className="muted">Loading font…</p>
|
<p className="muted">Loading font…</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -98,12 +98,23 @@ export function measureText(chars: CharInfo[], text: string, avgW: number): { to
|
|||||||
totalW += avgW;
|
totalW += avgW;
|
||||||
} else {
|
} else {
|
||||||
const info = map.get(ch);
|
const info = map.get(ch);
|
||||||
totalW += info?.w ?? avgW;
|
totalW += info?.w ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { totalW };
|
return { totalW };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMissingChars(chars: CharInfo[], text: string): Set<string> {
|
||||||
|
const available = new Set(chars.map((c) => c.char));
|
||||||
|
const missing = new Set<string>();
|
||||||
|
for (const ch of text.toLowerCase()) {
|
||||||
|
if (ch !== " " && !available.has(ch)) {
|
||||||
|
missing.add(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return missing;
|
||||||
|
}
|
||||||
|
|
||||||
export function renderToCanvas(
|
export function renderToCanvas(
|
||||||
chars: CharInfo[],
|
chars: CharInfo[],
|
||||||
h: number,
|
h: number,
|
||||||
@@ -118,7 +129,7 @@ export function renderToCanvas(
|
|||||||
|
|
||||||
let totalW = 0;
|
let totalW = 0;
|
||||||
for (const ch of safeText) {
|
for (const ch of safeText) {
|
||||||
totalW += ch === " " ? avgW : (map.get(ch)?.w ?? avgW);
|
totalW += ch === " " ? avgW : (map.get(ch)?.w ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalW === 0) return null;
|
if (totalW === 0) return null;
|
||||||
@@ -139,8 +150,6 @@ export function renderToCanvas(
|
|||||||
if (info) {
|
if (info) {
|
||||||
ctx.drawImage(sheet, info.x, top, info.w, h, x, 0, info.w, h);
|
ctx.drawImage(sheet, info.x, top, info.w, h, x, 0, info.w, h);
|
||||||
x += info.w;
|
x += info.w;
|
||||||
} else {
|
|
||||||
x += avgW;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user