Socket
Book a DemoInstallSign in
Socket

font-measure

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

font-measure - npm Package Compare versions

Comparing version

to
1.1.0

194

index.js

@@ -5,22 +5,46 @@ 'use strict'

var canvas = measure.canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
var chars = {
upper: 'H',
lower: 'x',
descent: 'p',
ascent: 'h',
tittle: 'i',
overshoot: 'O'
}
measure.canvas = document.createElement('canvas')
measure.cache = {}
var l = canvas.height = 100
canvas.width = l * .5
var fs = 64
function measure (font, o) {
if (!o) o = {}
if (typeof font === 'string' || Array.isArray(font)) {
o.family = font
}
function measure (family) {
family = Array.isArray(family) ? family.join(', ') : family
ctx.font = fs + 'px ' + family
var family = Array.isArray(o.family) ? o.family.join(', ') : o.family
if (!family) throw Error('`family` must be defined')
var fs = o.size || o.fontSize || o.em || 48
var font = fs + 'px ' + family
var origin = o.origin || 'top'
if (measure.cache[family]) {
// return more precise values if cache has them
if (fs <= measure.cache[family].em) {
return origin === 'top' ? measure.cache[family] : applyOrigin(measure.cache[family], origin)
}
}
var canvas = o.canvas || measure.canvas
var ctx = canvas.getContext('2d')
var chars = {
upper: o.upper !== undefined ? o.upper : 'H',
lower: o.lower !== undefined ? o.lower : 'x',
descent: o.descent !== undefined ? o.descent : 'p',
ascent: o.ascent !== undefined ? o.ascent : 'h',
tittle: o.tittle !== undefined ? o.tittle : 'i',
overshoot: o.overshoot !== undefined ? o.overshoot : 'O'
}
var l = Math.ceil(fs * 1.5)
canvas.height = l
canvas.width = l * .5
ctx.font = font
var char = 'H'
var result = {
top: 0
}
// measure line-height

@@ -30,9 +54,10 @@ ctx.clearRect(0, 0, l, l)

ctx.fillStyle = 'black'
ctx.fillText(chars.upper, 0, 0)
ctx.fillText(char, 0, 0)
var topPx = firstTop(ctx.getImageData(0, 0, l, l))
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'bottom'
ctx.fillText(chars.upper, 0, l)
ctx.fillText(char, 0, l)
var bottomPx = firstTop(ctx.getImageData(0, 0, l, l))
var lineHeight = l - bottomPx + topPx
result.lineHeight =
result.bottom = l - bottomPx + topPx

@@ -42,5 +67,7 @@ // measure baseline

ctx.textBaseline = 'alphabetic'
ctx.fillText(chars.upper, 0, l)
ctx.fillText(char, 0, l)
var baselinePx = firstTop(ctx.getImageData(0, 0, l, l))
var baseline = l - baselinePx + topPx
var baseline = l - baselinePx - 1 + topPx
result.baseline =
result.alphabetic = baseline

@@ -50,5 +77,6 @@ // measure median

ctx.textBaseline = 'middle'
ctx.fillText(chars.upper, 0, l * .5)
ctx.fillText(char, 0, l * .5)
var medianPx = firstTop(ctx.getImageData(0, 0, l, l))
var median = l - medianPx + topPx - l * .5
result.median =
result.middle = l - medianPx - 1 + topPx - l * .5

@@ -58,5 +86,5 @@ // measure hanging

ctx.textBaseline = 'hanging'
ctx.fillText(chars.upper, 0, l * .5)
ctx.fillText(char, 0, l * .5)
var hangingPx = firstTop(ctx.getImageData(0, 0, l, l))
var hanging = l - hangingPx + topPx - l * .5
result.hanging = l - hangingPx - 1 + topPx - l * .5

@@ -66,82 +94,82 @@ // measure ideographic

ctx.textBaseline = 'ideographic'
ctx.fillText(chars.upper, 0, l)
var ideographicH = firstTop(ctx.getImageData(0, 0, l, l))
var ideographic = l - hangingPx + topPx
ctx.fillText(char, 0, l)
var ideographicPx = firstTop(ctx.getImageData(0, 0, l, l))
result.ideographic = l - ideographicPx - 1 + topPx
// measure cap
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.upper, 0, 0)
var upper = firstTop(ctx.getImageData(0, 0, l, l))
if (chars.upper) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.upper, 0, 0)
result.upper = firstTop(ctx.getImageData(0, 0, l, l))
result.capHeight = (result.baseline - result.upper)
}
// measure x
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.lower, 0, 0)
var lower = firstTop(ctx.getImageData(0, 0, l, l))
if (chars.lower) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.lower, 0, 0)
result.lower = firstTop(ctx.getImageData(0, 0, l, l))
result.xHeight = (result.baseline - result.lower)
}
// measure tittle
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.tittle, 0, 0)
var tittle = firstTop(ctx.getImageData(0, 0, l, l))
if (chars.tittle) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.tittle, 0, 0)
result.tittle = firstTop(ctx.getImageData(0, 0, l, l))
}
// measure ascent
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.ascent, 0, 0)
var ascent = firstTop(ctx.getImageData(0, 0, l, l))
if (chars.ascent) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.ascent, 0, 0)
result.ascent = firstTop(ctx.getImageData(0, 0, l, l))
}
// measure descent
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.descent, 0, 0)
var descent = l - firstBottom(ctx.getImageData(0, 0, l, l))
if (chars.descent) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.descent, 0, 0)
result.descent = firstBottom(ctx.getImageData(0, 0, l, l))
}
// measure overshoot
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.overshoot, 0, 0)
var overshootPx = firstBottom(ctx.getImageData(0, 0, l, l))
var overshoot = overshootPx - baseline
var result = {
top: 0,
bottom: lineHeight,
lineHeight: lineHeight,
baseline: baseline,
alphabetic: baseline,
xHeight: (baseline - lower),
capHeight: (baseline - upper),
lower: lower,
upper: upper,
ascent: ascent,
descent: descent,
tittle: tittle,
overshoot: overshoot,
ideographic: ideographic,
hanging: hanging,
median: median,
middle: median
if (chars.overshoot) {
ctx.clearRect(0, 0, l, l)
ctx.textBaseline = 'top'
ctx.fillText(chars.overshoot, 0, 0)
var overshootPx = firstBottom(ctx.getImageData(0, 0, l, l))
result.overshoot = overshootPx - baseline
}
var origin = 'top'
var originValue = result[origin]
// normalize result
for (var name in result) {
result[name] = result[name] - originValue
result[name] /= fs
}
return result
result.em = fs
measure.cache[family] = result
return applyOrigin(result, origin)
}
function applyOrigin(obj, origin) {
var res = {}
if (typeof origin === 'string') origin = obj[origin]
for (var name in obj) {
if (name === 'em') continue
res[name] = obj[name] - origin
}
return res
}
function firstTop(iData) {
var l = iData.height
var data = iData.data
for (var i = 3; i < data.length; i+=4) {
var px = data[i]
if (data[i] !== 0) {

@@ -154,5 +182,5 @@ return Math.floor((i - 3) *.25 / l)

function firstBottom(iData) {
var l = iData.height
var data = iData.data
for (var i = data.length - 1; i > 0; i -= 4) {
var px = data[i]
if (data[i] !== 0) {

@@ -159,0 +187,0 @@ return Math.floor((i - 3) *.25 / l)

{
"name": "font-measure",
"version": "1.0.0",
"version": "1.1.0",
"description": "Calculate metrics of a font",

@@ -38,4 +38,4 @@ "main": "index.js",

"dependencies": {
"css-font": "^1.0.0"
"object-assign": "^4.1.1"
}
}

@@ -15,18 +15,18 @@ # font-measure [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges)

top: 0,
median: 0.640625,
middle: 0.640625,
bottom: 1.3125,
alphabetic: 1.03125,
baseline: 1.03125,
upper: 0.328125,
lower: 0.515625,
upper: 0.328125,
xHeight: 0.53125,
alphabetic: 1.046875,
baseline: 1.046875,
capHeight: 0.71875,
median: 0.65625,
middle: 0.65625,
capHeight: 0.703125,
xHeight: 0.515625
ascent: 0.28125,
descent: 0.328125,
hanging: 0.21875,
ideographic: 1,
descent: 1.234375,
hanging: 0.203125,
ideographic: 1.296875,
lineHeight: 1.3125,
overshoot: 0.015625,
tittle: 0.28125,
overshoot: 0
}

@@ -39,9 +39,9 @@ */

### `metrics = measure(font|options)`
### `let metrics = measure(font, options?)`
Get metrics data for a font or custom options.
Get metrics data for a font, possibly with custom options. Font can be a string or an array with fonts.
#### `metrics`:
<img src="./sphinx.svg" width="720"/>
<img src="https://github.com/dy/font-measure/raw/master/sphinx.svg?sanitize=true" width="720"/>

@@ -53,12 +53,11 @@

---|---|---
`family` | `null` | Font-family to detect metrics. Can be a string or an array (fontstack).
`origin` | `top` | Origin for metrics. Can be changed to `baseline` or any other metric.
`size` | `64` | Font-size to use for calculations. Larger size gives higher precision with slower performance.
`canvas` | `measure.canvas` | Canvas to use for measurements.
`tittle` | `i` | Character to detect tittle. Null value ignores calculation.
`descent` | `p` | Character to detect descent line. Null value ignores calculation.
`ascent` | `h` | Character to detect ascent line. Null value ignores calculation.
`overshoot` | `O` | Character to detect overshoot. Null value ignores calculation.
`upper` | `H` | Character to detect upper line / cap-height. Null value ignores calculation.
`lower` | `x` | Character to detect lower line / x-height. Null value ignores calculation.
`tittle` | `i` | Character to detect tittle. `null` disables calculation.
`descent` | `p` | Character to detect descent line. `null` disables calculation.
`ascent` | `h` | Character to detect ascent line. `null` disables calculation.
`overshoot` | `O` | Character to detect overshoot. `null` disables calculation.
`upper` | `H` | Character to detect upper line / cap-height. `null` disables calculation.
`lower` | `x` | Character to detect lower line / x-height. `null` disables calculation.

@@ -65,0 +64,0 @@

@@ -6,20 +6,23 @@ 'use strict'

a.deepEqual(m('Roboto'), {
top: 0,
let fix = {
alphabetic: 1.03125,
ascent: 0.28125,
baseline: 1.03125,
bottom: 1.3125,
capHeight: 0.703125,
descent: 1.234375,
hanging: 0.203125,
ideographic: 1.296875,
lineHeight: 1.3125,
lower: 0.515625,
median: 0.640625,
middle: 0.640625,
overshoot: 0.015625,
tittle: 0.28125,
top: 0,
upper: 0.328125,
xHeight: 0.53125,
alphabetic: 1.046875,
baseline: 1.046875,
capHeight: 0.71875,
median: 0.65625,
middle: 0.65625,
ascent: 0.28125,
descent: 0.328125,
hanging: 0.21875,
ideographic: 1,
lineHeight: 1.3125,
tittle: 0.28125,
overshoot: 0
})
xHeight: 0.515625
}
a.deepEqual(m('Roboto', {fontSize: 64}), fix)
a.equal(m('Roboto', {fontSize: 64, origin: 'baseline'}).baseline, 0)
SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.