Skip to content

Instantly share code, notes, and snippets.

@WhiteAbeLincoln
Last active August 4, 2020 20:44
Show Gist options
  • Save WhiteAbeLincoln/fa42cb698337bef14df99316c6cdffa8 to your computer and use it in GitHub Desktop.
Save WhiteAbeLincoln/fa42cb698337bef14df99316c6cdffa8 to your computer and use it in GitHub Desktop.
calculates the average character width in Open Sans 11px
function quickselect_median(arr) {
const L = arr.length, halfL = L/2;
if (L % 2 == 1)
return quickselect(arr, halfL);
else
return 0.5 * (quickselect(arr, halfL - 1) + quickselect(arr, halfL));
}
function quickselect(arr, k) {
// Select the kth element in arr
// arr: List of numerics
// k: Index
// return: The kth element (in numerical order) of arr
if (arr.length == 1)
return arr[0];
else {
const pivot = arr[0];
const lows = arr.filter((e)=>(e<pivot));
const highs = arr.filter((e)=>(e>pivot));
const pivots = arr.filter((e)=>(e==pivot));
if (k < lows.length) // the pivot is too high
return quickselect(lows, k);
else if (k < lows.length + pivots.length)// We got lucky and guessed the median
return pivot;
else // the pivot is too low
return quickselect(highs, k - lows.length - pivots.length);
}
}
function getTextWidth(text, font) {
// re-use canvas object for better performance
const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
const context = canvas.getContext("2d");
context.font = font;
const metrics = context.measureText(text);
return metrics.width;
}
// from https://fonts.google.com/specimen/Open+Sans#standard-styles
const glyphs = "ABCČĆDĐEFGHIJKLMNOPQRSŠTUVWXYZŽabcčćdđefghijklmnopqrsštuvwxyzžАБВГҐДЂЕЁЄЖЗЅИІЇЙЈКЛЉМНЊОПРСТЋУЎФХЦЧЏШЩЪЫЬЭЮЯабвгґдђеёєжзѕиіїйјклљмнњопрстћуўфхцчџшщъыьэюяΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωάΆέΈέΉίϊΐΊόΌύΰϋΎΫΏĂÂÊÔƠƯăâêôơư1234567890‘?’“!”(%)[#]{@}/&\<-+÷×=>®©$€£¥¢:;,.*"
const characterSizes = [...glyphs].map(c => getTextWidth(c, "11px Open Sans"))
console.log([...glyphs])
console.log(characterSizes)
const sum = (x, y) => x+y
const avg = characterSizes.reduce(sum, 0)/characterSizes.length
const max = Math.max(...characterSizes)
const min = Math.min(...characterSizes)
const median = quickselect_median(characterSizes)
console.log({avg,max,min,median})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment