npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

opentype-layout-improved

v1.2.5

Published

word wraps and lays out Opentype.js glyphs. A fork from https://github.com/Jam3/opentype-layout

Downloads

187

Readme

opentype-layout

experimental

Experimental word-wrapping and layout for Opentype.js.

Install

Best used with npm and browserify. This should also work in Node.js and other environments.

npm install opentype-layout-improved --save

Demo

Live Demo

The demo shows Canvas2D vector text (red stroke) rendered on top of DOM/CSS (black fill). The demo reads the computed CSS style and converts units into the proper EM font units. Some lines also visualize some of the available metrics.

Example

See the demo folder for a complete example.

var opentype = require('opentype.js');
var computeLayout = require('opentype-layout-improved');

opentype.load('Font.ttf', function (err, font) {
  if (err) throw err;

  var fontSizePx = 72;
  var text = 'Hello\nWorld! This box should start word-wrapping!'
  var scale = 1 / font.unitsPerEm * fontSizePx;

  // Layout some text - notice everything is in em units!
  var result = computeLayout(font, text, {
    lineHeight: 2.5 * font.unitsPerEm, // '2.5em' in font units
    width: 500 / scale // '500px' in font units
  });

  // Array of characters after layout
  console.log(result.glyphs);

  // Computed height after word-wrap
  console.log(result.height);
});

Usage

layout = computeLayout(font, text, [opt])

Computes a new layout from the given Opentype.js Font interface and a text string.

All units should be in raw font units in the EM square, assuming a lower-left origin. For example, a lineHeight of '2em' should be passed as 2 * font.unitsPerEm. It is up to the user to scale the results to a pixel/point size after the fact.

Options:

  • width the width of the box in font units, will cause word-wrapping (default Infinity)
  • align string alignment of the text within its width (default 'left')
  • letterSpacing the additional letter spacing in font units (default 0)
  • lineHeight the line height in font units as per CSS spec, default 1.175 * font.unitsPerEm to match browsers
  • start the starting character index into text to layout, default 0
  • end the ending index into text to layout (exclusive), default text.length
  • mode can be 'pre' (maintain spacing), or 'nowrap' (collapse whitespace but only break on newline characters), otherwise defaults to normal word-wrap behaviour

See word-wrapper for details on how word wrapping is computed.

Metrics

The returned object has the following metrics.

layout.glyphs

This provides an array of characters after layout, useful for rendering. Each element in the array has the following properties:

{
  position: [ x, y ],
  data: { ... Opentype.js Glyph object ... },
  index: charIndex,
  row: lineIndex,
  column: columnInLineIndex
}

The position is in raw font units.

layout.baseline

This is the value from pen origin to the baseline of the last line of text in the layout.

layout.leading

This is the L value in the CSS line-height spec. Divide this by two for the "half-leading", which tells you how far above the first ascender and below the last descender the text box extends to.

layout.lines

This is an array of line objects with the following properties:

{
  start: startCharIndex, // inclusive
  end: endCharIndex, // exclusive
  width: lineWidth // in font units
}

layout.lineHeight

This is the computed lineHeight in font units. If no lineHeight is specified in options, it will be equivalent to 1.175 * font.unitsPerEm.

layout.left

This is the distance from the left of the text box to the widest line of text in the box. This is zero when align is left, but changes with other alignments.

layout.right

This is the distance from the right of the box to the widest line of text in the box. This is zero when align is right, but changes with other alignments.

layout.width

The width of the text box. If no opt.width is passed, this will equal layout.maxLineWidth (i.e. length of a single line of text). If opt.width is passed, this value should equal it.

layout.height

The height of the text box, including the half leadings above the first ascender and below the last descender.

layout.maxLineWidth

This is the maximum line width in all lines. This can be used to determine the "real" width of the text box after word wrap, instead of the layout.width which may be larger.

TODOs

This module is not yet finished — below are some areas that need improvement. PRs welcome.

  • 'center' and 'right' alignment do not match exactly with DOM/CSS
  • Tab characters are not yet handled
  • Undefined characters are not yet handled gracefully
  • Word wrap algorithm is naïve and does not always match DOM/CSS
  • Mainly suited for Latin left-to-right text, does not handle CTL

License

MIT, see LICENSE.md for details.