As a footnote, here is a basic JXA example of obtaining the width, in points, of a particular string:
(() => {
'use strict';
// WIDTH OF A GIVEN STRING IN HELVETICA 12 --------------------------------
// helvetica12Width :: String -> Num
function helvetica12Width(str) {
return $.NSAttributedString.alloc.init.initWithString(
str
)
.size.width;
}
// helvetica12MaxWidth :: Int -> Num
function helvetica12MaxWidth(intChars) {
return $.NSAttributedString.alloc.init.initWithString(
replicateS(intChars, 'M')
)
.size.width;
}
// GENERIC FUNCTIONS ------------------------------------------------------
// concat :: [[a]] -> [a] | [String] -> String
const concat = xs => {
if (xs.length > 0) {
const unit = typeof xs[0] === 'string' ? '' : [];
return unit.concat.apply(unit, xs);
} else return [];
};
// replicate :: Int -> a -> [a]
const replicate = (n, a) => {
let v = [a],
o = [];
if (n < 1) return o;
while (n > 1) {
if (n & 1) o = o.concat(v);
n >>= 1;
v = v.concat(v);
}
return o.concat(v);
};
// replicateS :: Int -> String -> String
const replicateS = (n, s) => concat(replicate(n, s));
// show :: a -> String
const show = x => JSON.stringify(x, null, 2);
// TEST -------------------------------------------------------------------
return show(
[
["Substantiation", "MMMMMMMMMMMMMM"]
.map(helvetica12Width),
helvetica12MaxWidth(14)
]
);
})();
Returns:
[
[
76.0546875,
139.9453125
],
139.9453125
]