Fix logo generator: remove decorative fonts and fix missing char spacing
This commit is contained in:
1 parent
9a7b40eae6
commit
0272da09c1
3 files changed
+28
-57
No files matched your search
@@ -25,7 +25,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Habjoy light", styleName: "habjoy_light" },
|
||||
{ name: "Paradise", styleName: "paradise" },
|
||||
{ name: "Paradise 2", styleName: "paradise_rounded" },
|
||||
{ name: "Habbnew", styleName: "habbnew" },
|
||||
{ name: "Habbo Clicker", styleName: "habbo_clicker" },
|
||||
{ name: "Reception", styleName: "reception" },
|
||||
],
|
||||
@@ -35,7 +34,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
fonts: [
|
||||
{ name: "Accessoires", styleName: "accessoires" },
|
||||
{ name: "Africa", styleName: "africa" },
|
||||
{ name: "Alhambra", styleName: "alhambra" },
|
||||
{ name: "Arctic", styleName: "arctic", hasNumbers: true },
|
||||
{ name: "Asian", styleName: "asian" },
|
||||
{ name: "Asian small", styleName: "asian_small" },
|
||||
@@ -44,11 +42,9 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Bathroom", styleName: "bathroom", hasNumbers: true },
|
||||
{ name: "Battle Banzai", styleName: "battlebanzai" },
|
||||
{ name: "Bensalem", styleName: "bensalem", hasNumbers: true },
|
||||
{ name: "Bensalem sea", styleName: "bensalem_sea" },
|
||||
{ name: "Bling", styleName: "bling", hasNumbers: true },
|
||||
{ name: "Bling Gold", styleName: "bling_gold" },
|
||||
{ name: "Bones", styleName: "bones" },
|
||||
{ name: "Books", styleName: "books", hasNumbers: true },
|
||||
{ name: "Bots", styleName: "bots" },
|
||||
{ name: "Bubble", styleName: "bubble" },
|
||||
{ name: "Bubble blue", styleName: "bubble_blue" },
|
||||
@@ -58,14 +54,11 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Buttons", styleName: "buttons" },
|
||||
{ name: "Candy", styleName: "candy" },
|
||||
{ name: "Collectibles", styleName: "collectibles" },
|
||||
{ name: "Crystal", styleName: "crystal" },
|
||||
{ name: "Cubie", styleName: "cubie" },
|
||||
{ name: "Disco", styleName: "disco" },
|
||||
{ name: "Dreams", styleName: "dreams" },
|
||||
{ name: "Dreams flat", styleName: "dreams_flat" },
|
||||
{ name: "Duckets", styleName: "duckets" },
|
||||
{ name: "Emo", styleName: "emo" },
|
||||
{ name: "Exchange", styleName: "exchange" },
|
||||
{ name: "Executive", styleName: "executive" },
|
||||
{ name: "Explore", styleName: "explore" },
|
||||
{ name: "Explore big", styleName: "explore_big" },
|
||||
@@ -74,12 +67,11 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "F.BOMB", styleName: "fbomb" },
|
||||
{ name: "Festival", styleName: "festival" },
|
||||
{ name: "Flags", styleName: "flags" },
|
||||
{ name: "FX", styleName: "fx" },
|
||||
{ name: "Freehand", styleName: "freehand" },
|
||||
{ name: "Gaming", styleName: "gaming" },
|
||||
{ name: "Gallery", styleName: "gallery" },
|
||||
{ name: "Golden temple", styleName: "goldentemple" },
|
||||
{ name: "Gravity", styleName: "gravity" },
|
||||
|
||||
{ name: "HMA", styleName: "hma" },
|
||||
{ name: "Habbo gold", styleName: "gold_big" },
|
||||
{ name: "Habbo news", styleName: "habbo_news" },
|
||||
@@ -99,8 +91,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Love", styleName: "love" },
|
||||
{ name: "Marketplace red", styleName: "marketplace_red" },
|
||||
{ name: "Monkey", styleName: "monkey" },
|
||||
{ name: "Mushroom", styleName: "mushroom" },
|
||||
{ name: "Mushroom green", styleName: "mushroom_green" },
|
||||
{ name: "Neon blue", styleName: "neon_blue", hasNumbers: true },
|
||||
{ name: "Neon green", styleName: "neon_green", hasNumbers: true },
|
||||
{ name: "Neon pink", styleName: "neon_pink", hasNumbers: true },
|
||||
@@ -127,8 +117,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Spaces", styleName: "spaces" },
|
||||
{ name: "Special offers", styleName: "special_offers" },
|
||||
{ name: "StrayPixels", styleName: "straypixels" },
|
||||
{ name: "Steampunk", styleName: "steampunk" },
|
||||
{ name: "SCI-FI", styleName: "scifi" },
|
||||
{ name: "Summer", styleName: "summer" },
|
||||
{ name: "Teleport", styleName: "teleport", hasNumbers: true },
|
||||
{ name: "Theater lights", styleName: "theater_lights" },
|
||||
@@ -136,7 +124,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "Trophies", styleName: "trophies" },
|
||||
{ name: "USVA", styleName: "usva" },
|
||||
{ name: "Unknown blue", styleName: "unknown_blue" },
|
||||
{ name: "Unknown blue 2", styleName: "unknown_blue_2" },
|
||||
{ name: "Unknown metal", styleName: "unknown_metal" },
|
||||
{ name: "Unknown white", styleName: "unknown_white" },
|
||||
{ name: "Unknown pillow", styleName: "unknown_pillow_1" },
|
||||
@@ -164,8 +151,6 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{
|
||||
groupName: "Group fonts",
|
||||
fonts: [
|
||||
{ name: "Bling", styleName: "bling" },
|
||||
{ name: "Plastic", styleName: "plastic" },
|
||||
{ name: "Plastic playful", styleName: "plastic_playful" },
|
||||
{ name: "Dinner blue", styleName: "dinner_blue", hasNumbers: true },
|
||||
{ name: "Dinner green", styleName: "dinner_green", hasNumbers: true },
|
||||
@@ -176,10 +161,7 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
groupName: "Games",
|
||||
fonts: [
|
||||
{ name: "Battleball", styleName: "battleball" },
|
||||
{ name: "Battle Banzai", styleName: "battlebanzai" },
|
||||
{ name: "Lido", styleName: "lido", hasNumbers: true },
|
||||
{ name: "Soccer", styleName: "soccer" },
|
||||
{ name: "Soccer big", styleName: "soccer_big" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -191,9 +173,7 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{ name: "HC Compact", styleName: "hc_compact", hasNumbers: true },
|
||||
{ name: "HC gold", styleName: "hc_gold" },
|
||||
{ name: "Habbo Club 2", styleName: "habboclub", hasNumbers: true },
|
||||
{ name: "Habbo Club 2", styleName: "habboclub_banner", hasNumbers: true },
|
||||
{ name: "VIP", styleName: "habbovip", hasNumbers: true },
|
||||
{ name: "VIP", styleName: "habbovip_banner", hasNumbers: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -212,15 +192,12 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
groupName: "Windows",
|
||||
fonts: [
|
||||
{ name: "Windows", styleName: "windows" },
|
||||
{ name: "Lowercase", styleName: "windows_lowercase" },
|
||||
{ name: "Jungle", styleName: "windows_jungle" },
|
||||
|
||||
{ name: "Blue", styleName: "windows_blue", hasNumbers: true },
|
||||
{ name: "Green", styleName: "windows_green", hasNumbers: true },
|
||||
{ name: "Pink", styleName: "windows_pink", hasNumbers: true },
|
||||
{ name: "Red", styleName: "windows_red", hasNumbers: true },
|
||||
{ name: "Dark red", styleName: "windows_red_dark", hasNumbers: true },
|
||||
{ name: "Yellow", styleName: "windows_yellow" },
|
||||
{ name: "Purple", styleName: "windows_purple" },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -235,37 +212,13 @@ export const HABBO_FONT_GROUPS: HabboFontGroup[] = [
|
||||
{
|
||||
groupName: "Special fonts",
|
||||
fonts: [
|
||||
{ name: "Duckets", styleName: "duckets" },
|
||||
{ name: "Habbo club", styleName: "habboclub_complete" },
|
||||
{ name: "FX", styleName: "fx" },
|
||||
{ name: "Gift", styleName: "gift" },
|
||||
{ name: "HC silver", styleName: "habboclub_silver" },
|
||||
{ name: "Love full", styleName: "love_full" },
|
||||
{ name: "Marketplace", styleName: "marketplace_full" },
|
||||
{ name: "RELAX", styleName: "relax" },
|
||||
{ name: "Ribbon", styleName: "habbo_ribbon" },
|
||||
{ name: "Scifi", styleName: "scifi" },
|
||||
{ name: "Steampunk", styleName: "steampunk" },
|
||||
{ name: "USVA", styleName: "usva" },
|
||||
{ name: "Valentine", styleName: "valentine" },
|
||||
],
|
||||
},
|
||||
{
|
||||
groupName: "Unknown fonts",
|
||||
fonts: [
|
||||
{ name: "Unknown blue", styleName: "unknown_blue" },
|
||||
{ name: "Unknown blue 2", styleName: "unknown_blue_2" },
|
||||
{ name: "Unknown metal", styleName: "unknown_metal" },
|
||||
{ name: "Unknown white", styleName: "unknown_white" },
|
||||
{ name: "Unknown pillow", styleName: "unknown_pillow_1" },
|
||||
{ name: "Unknown pillow", styleName: "unknown_pillow_2" },
|
||||
{ name: "Relax", styleName: "relax" },
|
||||
],
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export function buildFontUrl(styleName: string, text: string): string {
|
||||
const t = text.toLowerCase().replace(/\s/g, "+");
|
||||
return `/api/font/${styleName}/${t}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, useTransition } from
|
||||
import { ContentCard } from "@/components/public/ui";
|
||||
import { saveLogo } from "@/actions/save-logo";
|
||||
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() {
|
||||
const [text, setText] = useState("Atom");
|
||||
@@ -13,6 +13,7 @@ export default function LogoGenerator() {
|
||||
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "done" | "error">("idle");
|
||||
const [fontLoaded, setFontLoaded] = useState(false);
|
||||
const [fontError, setFontError] = useState(false);
|
||||
const [missingChars, setMissingChars] = useState<Set<string>>(new Set());
|
||||
const [, startTransition] = useTransition();
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
@@ -54,6 +55,7 @@ export default function LogoGenerator() {
|
||||
const ctx = canvasRef.current.getContext("2d");
|
||||
ctx?.drawImage(canvas, 0, 0);
|
||||
}
|
||||
setMissingChars(getMissingChars(info.chars, safeText));
|
||||
setFontLoaded(true);
|
||||
})
|
||||
.catch(() => {
|
||||
@@ -224,7 +226,14 @@ export default function LogoGenerator() {
|
||||
{fontError ? (
|
||||
<p className="muted">Failed to load font sprite.</p>
|
||||
) : 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>
|
||||
)}
|
||||
|
||||
@@ -98,12 +98,23 @@ export function measureText(chars: CharInfo[], text: string, avgW: number): { to
|
||||
totalW += avgW;
|
||||
} else {
|
||||
const info = map.get(ch);
|
||||
totalW += info?.w ?? avgW;
|
||||
totalW += info?.w ?? 0;
|
||||
}
|
||||
}
|
||||
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(
|
||||
chars: CharInfo[],
|
||||
h: number,
|
||||
@@ -118,7 +129,7 @@ export function renderToCanvas(
|
||||
|
||||
let totalW = 0;
|
||||
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;
|
||||
@@ -139,8 +150,6 @@ export function renderToCanvas(
|
||||
if (info) {
|
||||
ctx.drawImage(sheet, info.x, top, info.w, h, x, 0, info.w, h);
|
||||
x += info.w;
|
||||
} else {
|
||||
x += avgW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user