You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
4.0 KiB
JavaScript
107 lines
4.0 KiB
JavaScript
// @flow
|
|
|
|
/**
|
|
* This file does conversion between units. In particular, it provides
|
|
* calculateSize to convert other units into ems.
|
|
*/
|
|
|
|
import ParseError from "./ParseError";
|
|
import Options from "./Options";
|
|
|
|
// This table gives the number of TeX pts in one of each *absolute* TeX unit.
|
|
// Thus, multiplying a length by this number converts the length from units
|
|
// into pts. Dividing the result by ptPerEm gives the number of ems
|
|
// *assuming* a font size of ptPerEm (normal size, normal style).
|
|
const ptPerUnit = {
|
|
// https://en.wikibooks.org/wiki/LaTeX/Lengths and
|
|
// https://tex.stackexchange.com/a/8263
|
|
"pt": 1, // TeX point
|
|
"mm": 7227 / 2540, // millimeter
|
|
"cm": 7227 / 254, // centimeter
|
|
"in": 72.27, // inch
|
|
"bp": 803 / 800, // big (PostScript) points
|
|
"pc": 12, // pica
|
|
"dd": 1238 / 1157, // didot
|
|
"cc": 14856 / 1157, // cicero (12 didot)
|
|
"nd": 685 / 642, // new didot
|
|
"nc": 1370 / 107, // new cicero (12 new didot)
|
|
"sp": 1 / 65536, // scaled point (TeX's internal smallest unit)
|
|
// https://tex.stackexchange.com/a/41371
|
|
"px": 803 / 800, // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
|
|
};
|
|
|
|
// Dictionary of relative units, for fast validity testing.
|
|
const relativeUnit = {
|
|
"ex": true,
|
|
"em": true,
|
|
"mu": true,
|
|
};
|
|
|
|
export type Measurement = {| number: number, unit: string |};
|
|
|
|
/**
|
|
* Determine whether the specified unit (either a string defining the unit
|
|
* or a "size" parse node containing a unit field) is valid.
|
|
*/
|
|
export const validUnit = function(unit: string | Measurement): boolean {
|
|
if (typeof unit !== "string") {
|
|
unit = unit.unit;
|
|
}
|
|
return (unit in ptPerUnit || unit in relativeUnit || unit === "ex");
|
|
};
|
|
|
|
/*
|
|
* Convert a "size" parse node (with numeric "number" and string "unit" fields,
|
|
* as parsed by functions.js argType "size") into a CSS em value for the
|
|
* current style/scale. `options` gives the current options.
|
|
*/
|
|
export const calculateSize = function(
|
|
sizeValue: Measurement, options: Options): number {
|
|
let scale;
|
|
if (sizeValue.unit in ptPerUnit) {
|
|
// Absolute units
|
|
scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
|
|
/ options.fontMetrics().ptPerEm // Convert pt to CSS em
|
|
/ options.sizeMultiplier; // Unscale to make absolute units
|
|
} else if (sizeValue.unit === "mu") {
|
|
// `mu` units scale with scriptstyle/scriptscriptstyle.
|
|
scale = options.fontMetrics().cssEmPerMu;
|
|
} else {
|
|
// Other relative units always refer to the *textstyle* font
|
|
// in the current size.
|
|
let unitOptions;
|
|
if (options.style.isTight()) {
|
|
// isTight() means current style is script/scriptscript.
|
|
unitOptions = options.havingStyle(options.style.text());
|
|
} else {
|
|
unitOptions = options;
|
|
}
|
|
// TODO: In TeX these units are relative to the quad of the current
|
|
// *text* font, e.g. cmr10. KaTeX instead uses values from the
|
|
// comparably-sized *Computer Modern symbol* font. At 10pt, these
|
|
// match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
|
|
// cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
|
|
// TeX \showlists shows a kern of 1.13889 * fontsize;
|
|
// KaTeX shows a kern of 1.171 * fontsize.
|
|
if (sizeValue.unit === "ex") {
|
|
scale = unitOptions.fontMetrics().xHeight;
|
|
} else if (sizeValue.unit === "em") {
|
|
scale = unitOptions.fontMetrics().quad;
|
|
} else {
|
|
throw new ParseError("Invalid unit: '" + sizeValue.unit + "'");
|
|
}
|
|
if (unitOptions !== options) {
|
|
scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
|
|
}
|
|
}
|
|
return Math.min(sizeValue.number * scale, options.maxSize);
|
|
};
|
|
|
|
/**
|
|
* Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See
|
|
* https://github.com/KaTeX/KaTeX/pull/2460.
|
|
*/
|
|
export const makeEm = function(n: number): string {
|
|
return +n.toFixed(4) + "em";
|
|
};
|