# Changelog

All notable changes to this project are documented in this file.

## 1.0.4 - 2026-09-29

### Changed

- Documentation only: the README's Documentation list links each page on the
  documentation site, so readers on GitHub and PyPI land there. The code is the same as 1.0.3.

## 1.0.3 - 2026-09-29

### Changed

- Documentation only: the README becomes a short entrance to the documentation
  site at https://offerrall.github.io/pygrbl-build/, and `docs/overview.md`
  holds the introduction: the algorithms, speed, lazy output and pairing with
  pygrbl-streamer. `docs/output.md` merges into the overview, without the
  hand-kept list of public names.
- New `docs/limitations.md` gathers what each algorithm does not do and the
  platforms with prebuilt wheels. The previous README said a C compiler was
  always required; it is needed only where no wheel exists.
- `RELEASING.md` moves to `docs/releasing.md`.
- Every example imports what it needs; the Bounds and framing example was
  missing `svg_gcode` and `SvgProfile`. The dead `pygrbl-server` link is gone.
- `pyproject.toml`: `[project.urls]` with the documentation site, repository,
  issues and changelog; a Python 3.14 classifier, matching the wheels; a
  shorter description.
- The code is the same as 1.0.2.

## 1.0.2 - 2026-09-29

### Changed

- Metadata only: the distribution name is spelled `pygrbl-build`, PyPI's
  canonical form, in `pyproject.toml` and the docs. `pip install pygrbl-build`
  and `import pygrbl_build` are unchanged. The code is the same as 1.0.1,
  apart from the version in the G-code header (`; pygrbl_build v1.0.2`).

## 1.0.1 - 2026-09-29

### Changed

- Documentation only: the README keeps an overview and a short example, the
  guides move to `docs/` (raster, vector, bounds and framing, output), and
  the release notes for maintainers move to `RELEASING.md`. The README title
  no longer carries the version. The code is the same as 1.0.0.

## 1.0.0 - 2026-09-22

### Added

- **Jarvis raster engraving** (`jarvis_gcode` + `JarvisProfile`): converts
  color or grayscale images to a 1-bit dot pattern using the
  Jarvis-Judice-Ninke error-diffusion kernel in C, then emits horizontal
  raster G-code through the existing native engine. Supports image paths,
  encoded bytes, bytearrays and Pillow images.
- Jarvis settings for resolution, feed, laser power, grayscale formula and
  channel weights, brightness, contrast, white clip, bidirectional scanning,
  overscan and `M3`/`M4` mode.
- Regression tests for Jarvis diffusion at image edges, binary power,
  transparency, input formats and profile validation.

### Changed

- Publishing a GitHub release now publishes the built distributions to PyPI
  after the wheel and source distribution jobs pass. The publish job checks
  that the release tag matches the package version. Pushes and manual runs
  continue to produce build artifacts only.

### Fixed

- Profiles and framing G-code reject `NaN` and infinite numeric values
  before those values can reach generated G-code.

Jarvis currently supports horizontal raster passes. Its diffusion kernel
follows LaserGRBL's behavior, while image resizing uses Pillow, so complete
byte-for-byte parity with LaserGRBL is not guaranteed.

## 0.4.1 - 2026-09-09

### Changed

- Line-to-Line raster output now uses GRBL's modal motion state: each scan row
  emits one `G1` after its `G0`, then omits redundant `G1` words from the
  remaining linear moves. Motion, power, coordinates, lazy iteration and
  constant-memory behaviour are unchanged while the serial payload is smaller.

## 0.4.0 - 2026-09-04

### Added

- All image APIs (`l2l_gcode`, `img2vector_gcode`, and `img2svg`) now accept
  encoded image `bytes`, `bytearray`, and loaded `PIL.Image.Image` instances in
  addition to file paths.
- `svg_gcode` now accepts SVG XML as `str`, `bytes`, or `bytearray` in addition
  to file paths.
- In-memory inputs receive the same traceability header as paths: encoded bytes
  are hashed directly, while Pillow images are hashed from their mode, size,
  and pixel content.

### Changed

- Exported `ImageSource` and `SvgSource` type aliases describing every accepted
  input.

## 0.3.0 - 2026-06-19

### Added

- **G-code bounds & framing** (`get_bounding_box` + `generate_framing_gcode`):
  the [gcode-bounds](https://github.com/offerrall/gcode-bounds) library
  folded in as a second C extension (`_gcode_parser`), same C parser as
  the original (`fast_atof` + line scan, 500MB+ files in seconds).
  `get_bounding_box` computes the `(min_x, max_x, min_y, max_y)` extent of
  some G-code; `generate_framing_gcode` traces that box (the framing pass)
  so the operator can confirm placement before engraving. Rapid moves to
  the origin (`G0` with `X0`/`Y0`) are skipped so the library's own home
  moves don't expand the box.
- `get_bounding_box` accepts the G-code as a file path (`str`/`Path`,
  opened and streamed in C) **or** as raw content already in memory
  (`bytes`/`bytearray`, or a multi-line `str`), so it no longer has to
  exist on disk. The Python wrapper decides which route to take; a new C
  entry point (`get_bounding_box_buffer`) parses the in-memory buffer with
  the same per-line logic as the file path.

## 0.2.0 - 2026-06-16

### Added

- **Image to SVG** algorithm (`img2svg` + `Img2SvgProfile`): traces a
  raster image to a standard vector SVG, reusing the same Potrace core
  and image preprocessing as `img2vector_gcode` but skipping the
  biarc/G-code stages. The contours are written as a single filled
  `<path>` with `fill-rule="evenodd"`, so inner contours become holes
  (the filled black silhouette potrace.exe produces). `viewBox` is in
  pixels while `width`/`height` carry the physical size in mm, and the
  bitmap is not Y-flipped, keeping the image's natural top-down
  orientation. `Img2SvgProfile` carries only the tracing and
  binarization knobs (no feed/power/laser-mode fields). Pure Python,
  Pillow only.

## 0.1.0 - 2026-06-16

### Added

- **Image vector** algorithm (`img2vector_gcode` + `Img2VectorProfile`):
  outline tracing from a raster image, a faithful Python port of
  LaserGRBL's "Vectorize!" mode. The image is reduced to black/white
  (resize, grayscale, white-clip, optional threshold), Potrace traces its
  outlines as closed contours, and each cubic Bezier is approximated by
  biarcs and emitted as `G2`/`G3` arcs (with a `G1` fallback). Pure
  Python, Pillow only. Outlines only — interior filling is not ported yet.
