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

tiny-atlas

v1.2.1

Published

Index glyphs of a label into a single SDF texture for rendering.

Downloads

7

Readme

tiny-atlas

Utility to produce data for drawing labels using signed distance fields in a webgl context. Internally uses tiny-sdf and potpack to create label props that glyphs index into a single texture. Made to be paired with regl.

See example/atlas.cjs for a complete example with regl based rendering. example/atlas-instances.cjs is the same example but done with instancing, properties are all attached to a single object.

API Interface Example

const { Atlas } = require('tiny-atlas')

// The arguments object is sent directly to `tiny-sdf`
const atlas = new Atlas({
  fontSize: 48,
  buffer: 3,
  radius: 8,
  cutoff: 0.25,
  fontFamily: 'Arial',
})

// Make as many labels as you want. `text` is string that is processed
// any other keys are passed to the final object in the `glyphs`
const labels = [{ text: 'coquí' }]

// `texture` is passed into `regl.texture` to produce a `sampler2D`
// compatible object.
// `glyphs` are in the shape described below, they hold all the properties
// to render with a reference to the `texture`.
const { texture, glyphs } = atlas.prepare({ labels })
const glyphsTexture = regl.texture(texture)

API

Atlas is the exported class. Its constructor takes an object passed along to tiny-sdf. This class is used to manage label's, which are in turn made up of glyphs.

atlas.prepare({ labels: [{ text }] }) method accepts an array of labels. The objects in this array only required a string value at the text key, any other keys will be spread across the glyphs object that corresponds to that particular label. The texture return value can be passed directly into regl.texture. The baselineOffsets key is a two element array with the first value being the max top distance from the baseline across all labels, and the second value being the max bottom distance from the baseline.

If drawing labels using instancing is desired, a truthy value at the instances key of the options object of atlas.prepare can be used. Additional label props can be spread in the return value by setting the instances value to an object with the shape { create, onGlyph}. create & onGlyph are expected to be functions. create gets passed an object with keys { props, size } where props is the return value that we are spreading across, and size is the total number of glyphs that are being accounted for with the output props. This allows for determining the type and length of array that will be returned. onGlyph is a function that is called with keys { props, labelIndex, charIndex, glyphIndex }. Again, props is the return value. labelIndex is the index of the current label that is being processed from the labels array. charIndex is the character index within that label. glyphIndex is the position in the array with the same length as the size that was used in the create function.

Instanced and object preperation will return a labels key that is the original label data that includes a glyphIndicies array. For instanced preperation the indicies will map into the individual arrays available on the glyphs arrays. For example, getting the labelDim for a label would look like:

const prepared = atlas.prepare({ labels, instances: true })
for (let i = 0; i < prepared.labels.length; i++) {
  const label = prepare.labels[i]
  const { glyphIndicies } = label
  const gi = glyphIndicies[0]
  const labelDim = [
    prepared.glyphs.labelDim[gi * 2 + 0],
    prepared.glyphs.labelDim[gi * 2 + 1],
  ]
}

Where as object preperation (non-instanced) data will be accessible indexing into glyphs, as follows:

const prepared = atlas.prepare({ labels })
for (let i = 0; i < prepared.labels.length; i++) {
  const label = prepare.labels[i]
  const { glyphIndicies } = label
  const gi = glyphIndicies[0]
  const { labelDim } = prepared.glyphs[gi]
}

If requesting instanced props, there will be an additional label key on the return value whose value will be an array of the original input labels, with the additional glyphIndicies array. glyphIndicies carries the integer index values that can be used to pull data from the various props arrays for the any input label.

atlas.prepare({
    labels : [{ text, ... }],
  }) => {
    texture: {
      data,
      width,
      height,
      format,
      type,
      mag,
      min,
    },
    glyphs: [{
      // 0-1 value of the position of the glyph in the label
      glyphInLabelStringIndex: Float, 
      // accumulated glyph widths preceding this glyph in the label
      glyphInLabelStringOffset: vec2<Float>,
      // glyph offset in the texture
      glyphTexOffset: vec2<Float>,
      // glyph dimensions in the texture
      glyphTexDim: vec2<Float>,
      // glyph's dimensions in SDF space
      // (tinySDFResult.{glyphWidth,glyphHeight})
      glyphRasterDim: vec2<Float>,
      // glyphs rasterized max distance from the baseline in SDF space
      glyphRasterTop: Float,
      // dimensions of the label in SDF space
      labelDim: vec2<Float>,
    }],
    // offsets from the baseline, describing the max distance above
    // and below the baseline: [top, bottom]
    baselineOffset: vec2<Float>,
    labels: {
      // includes all original label props
      ...label,
      // glyphIndicies are the indicies of glyphs of this label
      glyphIndicies: [Integer]
    }
  }
atlas.prepare({
    labels : [{ text, ... }],
    instances? : {
      init?: ({ props, size }) => void,
      onGlyph?: ({ props, labelIndex, charIndex, glyphIndex }) => void,
    },
  }) => {
    texture: {
      data,
      width,
      height,
      format,
      type,
      mag,
      min,
    },
    glyphs: {
      // 0-1 value of the position of the glyph in the label
      // length = size * 1
      glyphInLabelStringIndex: Float32Array, 
      // accumulated glyph widths preceding this glyph in the label
      // length = size * 2
      glyphInLabelStringOffset: Float32Array,
      // glyph offset in the texture
      // length = size * 2
      glyphTexOffset: Float32Array,
      // glyph dimensions in the texture
      // length = size * 2
      glyphTexDim: Float32Array,
      // glyph's dimensions in SDF space
      // (tinySDFResult.{glyphWidth,glyphHeight})
      // length = size * 2
      glyphRasterDim: Float32Array,
      // glyphs rasterized max distance from the baseline in SDF space
      // length = size * 1
      glyphRasterTop: Float32Array,
      // dimensions of the label in SDF space
      // length = size * 2
      labelDim: Float32Array,
    },
    // offsets from the baseline, describing the max distance above
    // and below the baseline: [top, bottom]
    baselineOffset: vec2<Float>,
    labels: {
      // includes all original label props
      ...label,
      // glyphIndicies are the indicies of glyphs of this label
      glyphIndicies: [Integer]
    }
  }

atlas.clear({ cache: boolean }) method accepts an object that can include a cache key with a boolean value. If this is set to true, the tiny-sdf results that are stored internally will be cleared. If cache is falsy, only the label level data will be removed, but glyph level data will be maintained.