User:What7what8/NoMoreMissingGlyphs.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
const { ceil, floor, max, min } = Math;
function getCssValue(element, property) {
return window.getComputedStyle(element, null).getPropertyValue(property)
}
function getCssValues(element, properties) {
const styles = window.getComputedStyle(element, null)
return properties.map(p => styles.getPropertyValue(p))
}
const fontStretches = {
"50%": "ultra-condensed",
"62.5%": "extra-condensed",
"75%": "condensed",
"87.5%": "semi-condensed",
"100%": "normal",
"112.5%": "semi-expanded",
"125%": "expanded",
"150%": "extra-expanded",
"200%": "ultra-expanded"
}
function getFont(element) {
const style = window.getComputedStyle(element, null)
let font = style.getPropertyValue("font")
if (!font) {
const fontStyle = style.getPropertyValue("font-style")
const fontVariant = style.getPropertyValue("font-variant")
const fontWeight = style.getPropertyValue("font-weight")
const fontStretch =
fontStretches[style.getPropertyValue("font-stretch")] || ""
const fontSize = style.getPropertyValue("font-size")
const lineHeight = style.getPropertyValue("line-height")
const fontFamily = style.getPropertyValue("font-family")
font = (
fontStyle +
" " +
fontVariant +
" " +
fontWeight +
" " +
fontStretch +
" " +
fontSize +
(lineHeight ? " / " + lineHeight : "") +
" " +
fontFamily
)
.replace(/ +/g, " ")
.trim()
}
return font
}
const cachedMetrics = {}
function getFontMetrics(elementOrFont, specificChar) {
let font
if (typeof elementOrFont === "string") font = elementOrFont
else font = getFont(elementOrFont)
let metrics = !specificChar && cachedMetrics[font]
if (metrics) return metrics
let testFont = font
let fontSize = 12
let testFontSize = 12
const fontParts = /(.?\b)((?:\d|\.)+)(px\b.)/.exec(font)
// Double the font size so there's more pixel detail to scan, then scale down the result afterward.
if (fontParts) {
fontSize = parseFloat(fontParts[2])
testFontSize = fontSize * 2
testFont = fontParts[1] + testFontSize + fontParts[3]
}
const sampleText1 = "Eg"
const sampleText2 = "ÅÊ"
let lineHeight = fontSize * 1.2
const padding = min(50, lineHeight * 1.5)
const heightDiv = document.createElement("div")
heightDiv.style.position = "absolute"
heightDiv.style.opacity = "0"
heightDiv.style.font = font
heightDiv.innerHTML = sampleText1 + "<br>" + sampleText1
document.body.appendChild(heightDiv)
const heightDivHeight = parseFloat(
getCssValue(heightDiv, "height").replace("px", "")
)
if (heightDivHeight >= fontSize * 2) lineHeight = heightDivHeight / 2
document.body.removeChild(heightDiv)
const canvas =
getFontMetrics.canvas ||
(getFontMetrics.canvas = document.createElement("canvas"))
canvas.width = testFontSize * 2 + padding
canvas.height = testFontSize * 3
canvas.style.opacity = "1"
const context = canvas.getContext("2d",{ willReadFrequently: true })
const w = canvas.width,
w4 = w * 4,
h = canvas.height,
baseline = h / 2
context.fillStyle = "white"
context.fillRect(-1, -1, w + 2, h + 2)
context.fillStyle = "black"
context.font = testFont
context.fillText(sampleText1, padding / 2, baseline)
let pixels = context.getImageData(0, 0, w, h).data
let i = 0
const len = pixels.length
// Finding the ascent uses a normal, forward scanline
while (++i < len && pixels[i] > 192) {}
let ascent = baseline - floor(i / w4)
// Finding the descent uses a reverse scanline
i = len - 1
while (--i > 0 && pixels[i] > 192) {}
let descent = floor(i / w4) - baseline
context.fillStyle = "white"
context.fillRect(-1, -1, w + 2, h + 2)
context.fillStyle = "black"
context.fillText(sampleText2, padding / 2, baseline)
pixels = context.getImageData(0, 0, w, h).data
// Find full ascent, including diacriticals.
i = 0
while (++i < len && pixels[i] > 192) {}
let fullAscent = baseline - floor(i / w4)
let extraAscent = fullAscent
let extraDescent = descent
if (specificChar) {
context.fillStyle = "white"
context.fillRect(-1, -1, w + 2, h + 2)
context.fillStyle = "black"
context.fillText(specificChar, padding / 2, baseline)
pixels = context.getImageData(0, 0, w, h).data
// Find ascent of specificChar.
i = 0
while (++i < len && pixels[i] > 192) {}
extraAscent = max(floor(i / w4) - baseline, fullAscent)
// Find descent of specificChar.
i = len - 1
while (--i > 0 && pixels[i] > 192) {}
extraDescent = max(floor(i / w4) - baseline, descent)
}
if (testFontSize > fontSize) {
ascent = ceil(ascent / 2)
fullAscent = ceil(fullAscent / 2)
descent = ceil(descent / 2)
extraAscent = ceil(extraAscent / 2)
extraDescent = ceil(extraDescent / 2)
}
const leading = lineHeight - fullAscent - descent
metrics = { font, lineHeight, ascent, fullAscent, descent, leading }
if (!specificChar) cachedMetrics[font] = metrics
else {
metrics.extraAscent = extraAscent
metrics.extraDescent = extraDescent
metrics.extraLineHeight = max(extraAscent + extraDescent, lineHeight)
}
return metrics
}
function doesCharacterGlyphExist(elementOrFont, charOrCodePoint) {
if (typeof charOrCodePoint === "number")
charOrCodePoint = String.fromCodePoint(charOrCodePoint)
const metrics = getFontMetrics(elementOrFont)
const PADDING = 8
const size = metrics.lineHeight + PADDING
const canvas0 =
doesCharacterGlyphExist.canvas0 ||
(doesCharacterGlyphExist.canvas0 = document.createElement("canvas"))
const canvas1 =
doesCharacterGlyphExist.canvas1 ||
(doesCharacterGlyphExist.canvas1 = document.createElement("canvas"))
const canvases = [canvas0, canvas1]
const pixmaps = []
for (let i = 0; i < 2; ++i) {
const canvas = canvases[i]
canvas.width = size
canvas.height = size
canvas.style.opacity = "1"
const context = canvas.getContext("2d",{ willReadFrequently: true })
context.fillStyle = "white"
context.fillRect(-1, -1, size + 2, size + 2)
context.fillStyle = "black"
context.font = metrics.font
// Compare pixels for test character to pixels for known character without a glyph
context.fillText(i === 0 ? charOrCodePoint : "\uFFFE", 0, metrics.ascent)
pixmaps[i] = context.getImageData(0, 0, size, size).data
}
for (let i = 0; i < pixmaps[0].length; ++i) {
if (pixmaps[0][i] !== pixmaps[1][i]) return true
}
return false
}
//----------------------------A simple line----------------------------
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
function string2unicode(str){
var ret ="";
for(var i=0; i<str.length; i++){
ret += "\\u" + str.charCodeAt(i).toString(16);
}
return ret;
}
//mw.loader.load("https://github.com/Fitzgerald-Porthmouth-Koenigsegg/Plangothic-Project/raw/main/PlangothicP2-Regular.ttf")
//mw.loader.load("https://github.com/Fitzgerald-Porthmouth-Koenigsegg/Plangothic-Project/raw/main/PlangothicP1-Regular%20(allideo).ttf")
$(function() {
$('head').append(
`<style>
@font-face {
font-family: P1;
src: url("//github.com/Fitzgerald-Porthmouth-Koenigsegg/Plangothic-Project/raw/main/PlangothicP1-Regular%20(allideo).ttf") format("truetype");
}
@font-face {
font-family: P2;
src: url("//github.com/Fitzgerald-Porthmouth-Koenigsegg/Plangothic-Project/raw/main/PlangothicP2-Regular.ttf") format("truetype");
}
</style>`
)
$('head').append(`<span id="P1test" style="font-family=P1"></span><span id="P2test" style="font-family=P2"></span>`)
$('#content').each(function(i,obj) {
if (obj.innerText != null && obj.innerText !== ''){
let needcheck = unique(obj.innerText)
for (let checkchar of needcheck) {
if(!doesCharacterGlyphExist(obj,checkchar)){
console.log(checkchar+" Uni:"+string2unicode(checkchar))
}
}
}
/*
for (var key in obj.innerText) {
| trash code
v
console.log(obj.innerText[key]+":"+doesCharacterGlyphExist(obj,obj.innerText[key]))
}
*/
});
})