[READ-ONLY] Mirror of https://github.com/tynanpurdy/real-font-size. Tiny calculator that tells you the real dimensions of text, not its bounding box
tynanpurdy.github.io/real-font-size/
5.9 kB
195 lines
1const fontInput = document.getElementById("fontInput");
2const fontWeightInput = document.getElementById("fontWeightInput");
3const typeSizeInput = document.getElementById("typeSizeInput");
4const typeUnitsInput = document.getElementById("typeUnitsInput");
5const previewText = document.getElementById("previewText");
6const diagram = document.getElementById("diagram");
7const testStringInput = document.getElementById("testStringInput");
8
9class Font {
10 constructor(name = "Arial", weight = 400, size = 12, units = "pt") {
11 (this.name = name),
12 (this.weight = weight),
13 (this.size = size),
14 (this.units = units);
15 }
16
17 get style() {
18 return `${this.weight} ${this.size}${this.units} ${this.name}`;
19 }
20}
21
22previewText.style.font = new Font().style;
23
24// INITIALIZE
25updateFont();
26
27// FUNCTIONS
28function unitsCorrectedSize(size, units) {
29 if (units === "pt") {
30 return size * (72.0 / 96.0);
31 }
32 return size;
33}
34
35function getRealFontHeightPx(textMetrics) {
36 return (
37 textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent
38 );
39}
40
41function getFontBoundingHeightPx(textMetrics) {
42 return textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent;
43}
44
45function clearCanvas(canvas) {
46 const ctx = canvas.getContext("2d");
47 ctx.clearRect(0, 0, canvas.width, canvas.height);
48 return ctx;
49}
50
51function updateFont() {
52 const newFont = getChosenFont();
53 const testString = getTestString();
54 console.log("measure updated");
55 console.log(newFont);
56 console.log(testString);
57 drawDiagram(newFont, testString);
58 previewText.style.font = newFont.style;
59}
60
61function getChosenFont() {
62 return new Font(
63 fontInput.value,
64 fontWeightInput.value,
65 typeSizeInput.value,
66 typeUnitsInput.value
67 );
68}
69
70function getTestString() {
71 const testString = testStringInput.value;
72 return testString != "" ? testString : "Apd";
73}
74
75function drawDiagram(font = new Font(), testString = "Apd", canvas = diagram) {
76 const ctx = clearCanvas(canvas);
77
78 // measure the chosen font
79 ctx.font = font.style;
80 const sampleText = testString;
81 const textMetrics = ctx.measureText(sampleText);
82
83 // display the real height
84 const realHeightPx = getRealFontHeightPx(textMetrics);
85 document.getElementById("realHeight").textContent = `${unitsCorrectedSize(
86 realHeightPx,
87 font.units
88 )} ${font.units}`;
89 console.log(textMetrics);
90
91 // create a fixed-size matching diagram font
92 const diagramFont = new Font(font.name, font.weight, 18, "rem");
93 ctx.font = diagramFont.style;
94 const diagramTextMetrics = ctx.measureText(sampleText);
95
96 // resize canvas to fit diagram text
97 const sampleTextX = 0;
98 const sampleTextY = diagramTextMetrics.fontBoundingBoxAscent;
99 canvas.width = diagramTextMetrics.width;
100 canvas.height = getFontBoundingHeightPx(diagramTextMetrics);
101
102 // draw bounding-box background
103 ctx.beginPath();
104 ctx.fillStyle = "#282828";
105 ctx.fillRect(
106 sampleTextX,
107 0,
108 diagramTextMetrics.width,
109 diagramTextMetrics.fontBoundingBoxAscent +
110 diagramTextMetrics.fontBoundingBoxDescent
111 );
112 ctx.stroke();
113
114 // draw diagram text
115 ctx.font = diagramFont.style;
116 ctx.fillStyle = "white";
117 ctx.fillText(sampleText, sampleTextX, sampleTextY);
118
119 const baselinesAboveAlphabetic = ["actualBoundingBoxAscent"];
120 const baselinesBelowAlphabetic = ["actualBoundingBoxDescent"];
121 const baselines = [...baselinesAboveAlphabetic, ...baselinesBelowAlphabetic];
122 ctx.strokeStyle = "red";
123
124 baselines.forEach((baseline) => {
125 const y = sampleTextY;
126 ctx.beginPath();
127
128 const baselineMetricValue = diagramTextMetrics[baseline];
129 if (baselineMetricValue === undefined) {
130 return;
131 }
132
133 const lineY = baselinesBelowAlphabetic.includes(baseline)
134 ? y + Math.abs(baselineMetricValue)
135 : y - Math.abs(baselineMetricValue);
136 ctx.moveTo(sampleTextX, lineY);
137 ctx.lineTo(sampleTextX + diagramTextMetrics.width, lineY);
138 ctx.stroke();
139 });
140}
141
142// EVENT HANDLERS
143typeInputs.addEventListener("change", updateFont);
144
145testStringInput.addEventListener("input", updateFont);
146
147document
148 .getElementById("copyButton")
149 .addEventListener("click", async function () {
150 try {
151 const realHeight = document.getElementById("realHeight").textContent;
152
153 // Use the Clipboard API to copy the text
154 await navigator.clipboard.writeText(realHeight);
155
156 // signify value has been copied via button content
157 let originalText = this.textContent;
158 this.textContent = "✅";
159 setTimeout(
160 function () {
161 this.textContent = originalText;
162 }.bind(this),
163 1500
164 );
165 } catch (err) {
166 console.error("Failed to copy: ", err);
167 }
168 });
169
170document.getElementById("launchFonts").addEventListener("click", () => {
171 if (navigator.userAgent.toUpperCase().indexOf("MAC") >= 0) {
172 window.open("fontbook://");
173 } else if (navigator.userAgent.toUpperCase().indexOf("WIN") >= 0) {
174 window.open("ms-settings:fonts");
175 } else if (navigator.userAgent.includes("Linux")) {
176 alert(
177 "I'm a novice programmer, ok? You chose linux and you knew the consequences when you did so. I have no clue how to open your font manager, if you even bothered to install one. Your fonts are in a folder somewhere, or three, I have no idea. Have fun searching, I believe in you."
178 );
179 } else if (navigator.userAgent.includes("Android")) {
180 alert(
181 "Font management is not available on Android. I don't make the rules. You can yell at Sundar Pichai if you want."
182 );
183 } else if (
184 navigator.userAgent.includes("iPhone") ||
185 navigator.userAgent.includes("iPad")
186 ) {
187 alert(
188 "Font management is not available on iOS. I don't make the rules. You can yell at Tim Apple if you want."
189 );
190 } else {
191 alert(
192 "Whatever OS you're running is not easily identified by my simple if statements. Good on you. As for your fonts, I have no clue where they are."
193 );
194 }
195});