Add ChrFont, a reader for Gravograph .CHR engraving fonts, plus UI to
convert placed text into engraved geometry in the CAD converter.
The .CHR files are obfuscated with a single-byte XOR. Different
GravoStyle releases use different keys (0x2F in older versions, 0xCF in
the 7000 series, and others across the font library), so the key is
auto-detected from byte 1 of the file: the font name is ASCII stored as
UTF-16LE, so the high byte of its first character is 0x00 in plaintext
and the raw byte equals the key. This reads every font in a GravoStyle
install regardless of version, not just one hardcoded key.
UI: right-clicking a text item in EntityView raises TextConvertRequested;
CadConverterForm renders it via ChrFont with H/V alignment and adds the
result on an ENGRAVE layer.
Tests use Xunit.SkippableFact and a gitignored test-config.json so the
suite points at a local .CHR file without committing proprietary assets.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop CadImportResult.Document: no caller reads it after the
migrations (BendDetectorRegistry runs inside CadImporter.Import
itself, and downstream callers only consume the entity/bend data).
- Drop dead CadConverterForm.GetNextColor() helper: zero callers
since GetDrawings stopped needing it.
- Drop stale 'using OpenNest.Properties;' and unused 'newItems'
local in OnSplitClicked.
- Add Import_WhenNamedDetectorDoesNotExist_ReturnsEmptyBends to
cover the previously untested named-detector branch in
CadImporter.Import.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidated two stateless classes into one unified API: Dxf.Import(),
Dxf.GetGeometry(), Dxf.ExportPlate(), Dxf.ExportProgram(). Export
state moved into a private ExportContext. Removed bool+out pattern
from GetGeometry in favor of returning empty list on failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Emit variable definitions before G-code in program text entries and use
\$varName syntax for coordinate fields that have VariableRefs, so programs
round-trip through NestWriter → NestReader without losing variable information.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ProgramReader now supports G-code user variables with a two-pass
approach: first pass collects variable definitions (name = expression
[inline] [global]) and evaluates them via topological sort and
ExpressionEvaluator; second pass parses G-code lines with $name
substitution and VariableRef tracking on motion and feedrate objects.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move 43 root-level test files into feature-specific subdirectories
mirroring the main codebase structure: Geometry, Fill, BestFit, CutOffs,
CuttingStrategy, Engine, IO. Update namespaces to match folder paths.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>