Module:ItemBox: Difference between revisionsGive feedback
Jump to navigation
Jump to search
Rewrite getFontSize: measured Retail Demo advance-width table + fit logic, output em so name scales with the card (with help from vergir-bot LLM) |
Add variants() for stable per-item texture variety (replaces nth-child); add font-table regen recipe to header (with help from vergir-bot LLM) |
||
| Line 4: | Line 4: | ||
-- ============================================================================ | -- ============================================================================ | ||
-- Retail Demo (bold) glyph advance widths, in em of the font size. | -- Retail Demo (bold) glyph advance widths, in em of the font size. | ||
-- unitsPerEm = 1000. Measured | -- unitsPerEm = 1000. Measured from File:Retaildemo-bold.woff2 | ||
-- ( /images/d/d5/Retaildemo-bold.woff2 ), the bold face used by .itembox-name. | |||
-- | -- | ||
-- THIS TABLE IS FONT-SPECIFIC. If that file is re-uploaded with different | -- THIS TABLE IS FONT-SPECIFIC. If that file is re-uploaded with different | ||
-- metrics, name fitting | -- metrics, name fitting drifts. Regenerate the table with: | ||
-- | -- | ||
-- curl -o rd.woff2 https://deadlock.wiki/images/d/d5/Retaildemo-bold.woff2 | |||
-- fontforge -lang=py -c 'import fontforge;f=fontforge.open("rd.woff2");f.generate("rd.ttf")' | |||
-- python3 - << 'PY' | |||
-- from fontTools.ttLib import TTFont; import string | |||
-- f=TTFont("rd.ttf"); upm=f["head"].unitsPerEm; hm=f["hmtx"]; uni={} | |||
-- for t in f["cmap"].tables: | |||
-- if t.isUnicode(): | |||
-- for cp,gn in t.cmap.items(): uni.setdefault(cp,gn) | |||
-- for c in string.ascii_uppercase+string.ascii_lowercase+string.digits+" ": | |||
-- gn=uni.get(ord(c)) | |||
-- if gn: print(f' ["{c}"]={hm[gn][0]/upm:.3f},') | |||
-- PY | |||
-- ============================================================================ | -- ============================================================================ | ||
local WIDTH = { | local WIDTH = { | ||
| Line 31: | Line 42: | ||
-- Card geometry in px at the reference scale where 1em = 10px. The card is | -- Card geometry in px at the reference scale where 1em = 10px. The card is | ||
-- scaled through font-size on . | -- scaled through font-size on .itembox (the |size= parameter) and the value | ||
-- | -- returned here is em, so it scales together with everything else. | ||
local USABLE_W = 72 -- 80px card minus 4px padding on each side | local USABLE_W = 72 -- 80px card minus 4px padding on each side | ||
local NAME_H = 42 -- vertical room the wrapped name may occupy | local NAME_H = 42 -- vertical room the wrapped name may occupy | ||
local LINE_H = 1.2 -- must match . | local LINE_H = 1.2 -- must match .itembox-name line-height | ||
local MAX_PX = 15 -- full size (1.50em) | local MAX_PX = 15 -- full size (1.50em) | ||
local MIN_PX = 8 -- hard floor (0.80em) | local MIN_PX = 8 -- hard floor (0.80em) | ||
| Line 107: | Line 118: | ||
return string.format("%.2f", snapped / 10) | return string.format("%.2f", snapped / 10) | ||
end | |||
-- Stable per-item texture variety, replacing position-dependent :nth-child. | |||
-- A djb2 hash of the (language-independent) code name picks one of each of the | |||
-- icon-mask / wear / paper-texture variants. Same item -> same look everywhere. | |||
local function hash(s) | |||
local h = 5381 | |||
for i = 1, #s do | |||
h = (h * 33 + s:byte(i)) % 2147483647 | |||
end | |||
return h | |||
end | |||
function p.variants(frame) | |||
local h = hash(frame.args[1] or "") | |||
local icon = (h % 3) + 1 | |||
local wear = (math.floor(h / 3) % 4) + 1 | |||
local tex = (math.floor(h / 12) % 3) + 1 | |||
return string.format("itembox-icon-v%d itembox-wear-v%d itembox-texture-v%d", | |||
icon, wear, tex) | |||
end | end | ||
return p | return p | ||