# Nocker Pixel — Canvas / AI integration contract

Download: https://font.nocker.sh/fonts/nocker-pixel-16.json (16×16), https://font.nocker.sh/fonts/nocker-pixel-8.json (8×8)

This is bitmap data, not a browser font. Do not use fillText to render it.

- `cell`: `{ width, height }`, 16×16 or 8×8.
- `glyphs[character].rows[y]`: one hex string per row; the left pixel is the highest bit. A bit of 1 is filled, 0 empty.
- Origin: top left. Positive x is right; positive y is down.
- `glyphs[character].advance`: pen advance: half the cell width for Latin/ASCII, the full width for kana.
- The storage cell is the full cell, including ASCII; the unused right half is empty.
- Draw filled cells as equally sized squares at integer coordinates and integer scale.
- After drawing, move the pen by `advance + letterSpacing` logical pixels.
- Apply letterSpacing only BETWEEN glyphs when measuring a line.
- Line height: `cell.height + lineGap`; default lineGap is 4 (16×16) or 2 (8×8). Reset x on newline.
- Normalize input to NFC so decomposed voiced kana become supported precomposed glyphs.
- Missing glyph fallback: `?`. No kanji. Spaces have no ink but still advance.
- Ink bounds are the minimum bounding box of filled pixels. They are NOT the cell or advance.
- When scaling a bitmap canvas, disable image smoothing and use integer CSS scaling.
- Each font JSON embeds its license (16×16: SIL OFL 1.1 and upstream copyright; 8×8: the Misaki font license). Preserve them on redistribution.
- Conversion parameters and pinned upstream revision are recorded in the JSON.

Example glyph access in TypeScript:

```ts
const glyph = font.glyphs[character] ?? font.glyphs["?"]

const { width } = font.cell

glyph.rows.forEach((row, y) => {
  const bits = parseInt(row, 16)

  for (let x = 0; x < width; x++) {
    if ((bits >> (width - 1 - x)) & 1) {
      context.fillRect((penX + x) * scale, (penY + y) * scale, scale, scale)
    }
  }
})

penX += glyph.advance + letterSpacing
```

## Library

```sh
npm install @nocker/font
```

The package is published on the npm registry.

```ts
// Import the size you use; only that size's data is loaded.
import { renderText, layoutText, measureGlyph } from "@nocker/font/16x16"
// or: from '@nocker/font/8x8'

renderText(context, text, {
  x: 8,
  y: 8,
  scale: 3,
  letterSpacing: 1,
  maxWidth: 304,
})
```

`renderText` does not resize or clear the canvas and restores the context state. x/y/maxWidth are logical pixels, multiplied by scale when drawn. It uses the context's existing transform. `layoutText` reports logical width/height and glyph lines. Wrapping occurs at glyph boundaries.
