|
|
| (4 intermediate revisions by the same user not shown) |
| Line 1: |
Line 1: |
| local p = {} | | local p = {} |
| | local ustring = mw.ustring |
| | local textfit = require "Module:TextFit" |
|
| |
|
| local function charWidth(cp)
| | -- ============================================================================ |
| -- Fullwidth & Wide ranges (CJK, Hangul, etc.) → 2 units
| | -- Name box geometry, in em of .itembox's font-size (1em = 10px at size=1). |
| if
| | -- Mirrors Template:ItemBox/styles.css: |
| (cp >= 0x1100 and cp <= 0x115F) or -- Hangul Jamo
| | -- .itembox width: 8em |
| (cp >= 0x2E80 and cp <= 0x303E) or -- CJK radicals, Kangxi
| | -- .itembox-name-area height: 4.5em; padding: 0.5em 0.4em (border-box) |
| (cp >= 0x3041 and cp <= 0x33BF) or -- Hiragana, Katakana, CJK compat
| | -- .itembox-name line-height: 1.2; font-size: 1.5em (overridden inline) |
| (cp >= 0x33FF and cp <= 0xA4CF) or -- CJK unified
| | -- so the name's content box is 8 - 2*0.4 = 7.2em wide and 4.5 - 2*0.5 = 3.5em |
| (cp >= 0xA960 and cp <= 0xA97F) or -- Hangul Jamo Extended
| | -- tall. Only the ratio and the size limits are read from those figures: the |
| (cp >= 0xAC00 and cp <= 0xD7FF) or -- Hangul syllables
| | -- size is emitted in cqw against .itembox-name-area, so the browser supplies |
| (cp >= 0xF900 and cp <= 0xFAFF) or -- CJK compatibility ideographs
| | -- the actual width. Glyph widths live in [[Module:TextFit]]. |
| (cp >= 0xFE10 and cp <= 0xFE1F) or -- Vertical forms
| | -- ============================================================================ |
| (cp >= 0xFE30 and cp <= 0xFE6F) or -- CJK compatibility forms
| | local NAME_W = 7.2 |
| (cp >= 0xFF01 and cp <= 0xFF60) or -- Fullwidth Latin/punctuation
| | local NAME_H = 3.5 |
| (cp >= 0xFFE0 and cp <= 0xFFE6) or -- Fullwidth signs
| | local LINE_H = 1.2 |
| (cp >= 0x1B000 and cp <= 0x1B0FF) or -- Kana supplement
| | local MAX_EM = 1.5 |
| (cp >= 0x1F300 and cp <= 0x1F9FF) or -- Emoji block
| | local MIN_EM = 0.8 |
| (cp >= 0x20000 and cp <= 0x2FFFD) or -- CJK Extension B–F
| |
| (cp >= 0x30000 and cp <= 0x3FFFD) -- CJK Extension G+
| |
| then
| |
| return 2
| |
|
| |
|
| -- Narrow Latin specifics
| | -- Returns the name font size as a cqw string, measured against |
| elseif cp == 0x69 or cp == 0x6C or -- i, l
| | -- .itembox-name-area, which [[Template:ItemBox]] makes a query container. |
| cp == 0x49 or -- I
| | function p.getFontSize(frame) |
| cp == 0x31 or -- 1
| | local name = ustring.gsub(frame.args[1] or "", "^%s*(.-)%s*$", "%1") |
| cp == 0x21 or cp == 0x7C -- !, |
| | local max = MAX_EM / NAME_W * 100 -- 20.83cqw |
| then | | if name == "" then return string.format("%.2fcqw", max) end |
| return 0.5
| |
|
| |
|
| -- Wide Latin | | return string.format("%.2fcqw", textfit.fit(name, { |
| elseif cp == 0x6D or cp == 0x77 or -- m, w | | aspect = NAME_H / NAME_W, |
| cp == 0x4D or cp == 0x57 -- M, W
| | lineHeight = LINE_H, |
| then | | max = max, |
| return 1.5
| | min = MIN_EM / NAME_W * 100, -- 11.11cqw |
| | })) |
| | end |
|
| |
|
| -- Cyrillic and other "ambiguous" scripts — slightly wider than Latin
| | -- User for stable per-item texture variety |
| elseif cp >= 0x0400 and cp <= 0x04FF then
| | local function hash(s) |
| -- Wide Cyrillic (1.5)
| | local h = 5381 |
| local wide = {
| | for i = 1, #s do |
| [0x0416]=true, [0x0436]=true, -- Ж ж
| | h = (h * 33 + s:byte(i)) % 2147483647 |
| [0x041C]=true, [0x043C]=true, -- М м
| |
| [0x0424]=true, [0x0444]=true, -- Ф ф
| |
| [0x0428]=true, [0x0448]=true, -- Ш ш
| |
| [0x0429]=true, [0x0449]=true, -- Щ щ
| |
| [0x042E]=true, [0x044E]=true, -- Ю ю
| |
| [0x042B]=true, [0x044B]=true, -- Ы ы
| |
| }
| |
| -- Narrow Cyrillic (0.5)
| |
| local narrow = {
| |
| [0x0406]=true, [0x0456]=true, -- І і (Ukrainian I)
| |
| [0x0407]=true, [0x0457]=true, -- Ї ї
| |
| }
| |
| | |
| if wide[cp] then
| |
| return 1.5
| |
| elseif narrow[cp] then
| |
| return 0.5
| |
| else
| |
| return 1.1
| |
| end
| |
| | |
| -- Default for everything else (Arabic, Hebrew, Thai, etc.)
| |
| else
| |
| return 1
| |
| end | | end |
| | return h |
| end | | end |
|
| |
|
| local function wordWidth(word)
| | function p.variants(frame) |
| local width = 0
| | local h = hash(frame.args[1] or "") |
| for i = 1, mw.ustring.len(word) do
| | local icon = (h % 3) + 1 |
| local cp = mw.ustring.codepoint(word, i, i)
| | local wear = (math.floor(h / 3) % 4) + 1 |
| width = width + charWidth(cp)
| | local tex = (math.floor(h / 12) % 3) + 1 |
| end
| | return string.format("itembox-icon-v%d itembox-wear-v%d itembox-texture-v%d", |
| return math.ceil(width)
| | icon, wear, tex) |
| end
| |
| | |
| function p.getFontSize(frame) | |
| local name = frame.args[1] or "" | |
| local words = {} | |
| for word in name:gmatch("%S+") do
| |
| table.insert(words, word)
| |
| end
| |
|
| |
| local longestLine = 0 | |
| | |
| if #words == 1 then
| |
| longestLine = wordWidth(words[1])
| |
| | |
| elseif #words == 2 then
| |
| longestLine = math.max(wordWidth(words[1]), wordWidth(words[2]))
| |
| | |
| elseif #words == 3 then | |
| local first = wordWidth(words[1])
| |
| local mid = wordWidth(words[2])
| |
| local last = wordWidth(words[3])
| |
| | |
| local shorterOuter = math.min(first, last)
| |
| local longerOuter = math.max(first, last)
| |
| | |
| local combined = mid + 1 + shorterOuter
| |
| | |
| longestLine = math.max(combined, longerOuter)
| |
| else
| |
| -- 4+ words: take the max of all individual word widths
| |
| for _, word in ipairs(words) do
| |
| longestLine = math.max(longestLine, wordWidth(word))
| |
| end
| |
| end
| |
| | |
| local fullSize = 15
| |
| local fontSize
| |
| | |
| if longestLine <= 8 then
| |
| fontSize = fullSize
| |
| else
| |
| fontSize = fullSize - (longestLine - 8) * 1
| |
| end
| |
|
| |
| fontSize = math.max(6, fontSize)
| |
| | |
| return fontSize
| |
| end | | end |
|
| |
|
| return p | | return p |