mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 10:23:41 +00:00
feature: Refactor PEN parser to decoder with coherent types
Renamed and restructured PEN parsing to match encoder pattern: Changes: - Renamed pen/parser.ts → pen/decoder.ts (consistent with encoder.ts) - Created pen/types.ts for PEN-specific type definitions - Moved types out of machine.ts (they're format-specific, not machine-specific) - Unified decoder with encoder test helpers (encoder.test.ts now uses decoder) New structure: - decodePenStitch() - decode single 4-byte stitch - decodeAllPenStitches() - decode all stitches from bytes - decodePenData() - full decode with color blocks and bounds - getStitchColor() - helper to get color for a stitch index Type definitions: - DecodedPenStitch - individual stitch with coordinates and flags - PenColorBlock - color block (stitch range for one thread) - DecodedPenData - complete decoded pattern data Backward compatibility: - Added compatibility aliases (isJump, flags, startStitch, endStitch) - Maintains API compatibility with existing UI code Also added dist-electron to eslint ignore list. All tests passing (27/27), build successful, lint clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
11b710eb17
commit
ba380723c0
6 changed files with 239 additions and 206 deletions
|
|
@ -6,7 +6,7 @@ import tseslint from 'typescript-eslint'
|
||||||
import { defineConfig, globalIgnores } from 'eslint/config'
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
export default defineConfig([
|
export default defineConfig([
|
||||||
globalIgnores(['dist', '.vite']),
|
globalIgnores(['dist', 'dist-electron', '.vite']),
|
||||||
{
|
{
|
||||||
files: ['**/*.{ts,tsx}'],
|
files: ['**/*.{ts,tsx}'],
|
||||||
extends: [
|
extends: [
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { WorkerMessage, WorkerResponse } from './worker';
|
import type { WorkerMessage, WorkerResponse } from './worker';
|
||||||
import PatternConverterWorker from './worker?worker';
|
import PatternConverterWorker from './worker?worker';
|
||||||
import { parsePenData } from '../pen/parser';
|
import { decodePenData } from '../pen/decoder';
|
||||||
import type { PenData } from '../../types/machine';
|
import type { DecodedPenData } from '../pen/types';
|
||||||
|
|
||||||
export type PyodideState = 'not_loaded' | 'loading' | 'ready' | 'error';
|
export type PyodideState = 'not_loaded' | 'loading' | 'ready' | 'error';
|
||||||
|
|
||||||
|
|
@ -24,8 +24,8 @@ export interface PesPatternData {
|
||||||
chart: string | null;
|
chart: string | null;
|
||||||
threadIndices: number[];
|
threadIndices: number[];
|
||||||
}>;
|
}>;
|
||||||
penData: Uint8Array; // Raw PEN bytes sent to machine
|
penData: Uint8Array; // Raw PEN bytes sent to machine
|
||||||
penStitches: PenData; // Parsed PEN stitches (for rendering)
|
penStitches: DecodedPenData; // Decoded PEN stitches (for rendering)
|
||||||
colorCount: number;
|
colorCount: number;
|
||||||
stitchCount: number;
|
stitchCount: number;
|
||||||
bounds: {
|
bounds: {
|
||||||
|
|
@ -180,9 +180,9 @@ class PatternConverterClient {
|
||||||
// Convert penData array back to Uint8Array
|
// Convert penData array back to Uint8Array
|
||||||
const penData = new Uint8Array(message.data.penData);
|
const penData = new Uint8Array(message.data.penData);
|
||||||
|
|
||||||
// Parse the PEN data to get stitches for rendering
|
// Decode the PEN data to get stitches for rendering
|
||||||
const penStitches = parsePenData(penData);
|
const penStitches = decodePenData(penData);
|
||||||
console.log('[PatternConverter] Parsed PEN data:', penStitches.totalStitches, 'stitches,', penStitches.colorCount, 'colors');
|
console.log('[PatternConverter] Decoded PEN data:', penStitches.stitches.length, 'stitches,', penStitches.colorBlocks.length, 'colors');
|
||||||
|
|
||||||
const result: PesPatternData = {
|
const result: PesPatternData = {
|
||||||
...message.data,
|
...message.data,
|
||||||
|
|
|
||||||
179
src/formats/pen/decoder.ts
Normal file
179
src/formats/pen/decoder.ts
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
/**
|
||||||
|
* PEN Format Decoder
|
||||||
|
*
|
||||||
|
* This module contains the logic for decoding Brother PP1 PEN format embroidery files.
|
||||||
|
* The PEN format uses absolute coordinates shifted left by 3 bits, with flags in the low 3 bits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { DecodedPenStitch, DecodedPenData, PenColorBlock } from './types';
|
||||||
|
|
||||||
|
// PEN format flags
|
||||||
|
const PEN_FEED_DATA = 0x01; // Bit 0: Jump stitch (move without stitching)
|
||||||
|
const PEN_CUT_DATA = 0x02; // Bit 1: Trim/cut thread command
|
||||||
|
const PEN_COLOR_END = 0x03; // Last stitch before color change
|
||||||
|
const PEN_DATA_END = 0x05; // Last stitch of entire pattern
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a single PEN stitch (4 bytes) into coordinates and flags
|
||||||
|
*
|
||||||
|
* @param bytes The byte array containing PEN data
|
||||||
|
* @param offset The offset in bytes to start reading from
|
||||||
|
* @returns Decoded stitch with coordinates and flag information
|
||||||
|
*/
|
||||||
|
export function decodePenStitch(
|
||||||
|
bytes: Uint8Array | number[],
|
||||||
|
offset: number
|
||||||
|
): DecodedPenStitch {
|
||||||
|
const xLow = bytes[offset];
|
||||||
|
const xHigh = bytes[offset + 1];
|
||||||
|
const yLow = bytes[offset + 2];
|
||||||
|
const yHigh = bytes[offset + 3];
|
||||||
|
|
||||||
|
const xRaw = xLow | (xHigh << 8);
|
||||||
|
const yRaw = yLow | (yHigh << 8);
|
||||||
|
|
||||||
|
// Extract flags from low 3 bits
|
||||||
|
const xFlags = xRaw & 0x07;
|
||||||
|
const yFlags = yRaw & 0x07;
|
||||||
|
|
||||||
|
// Clear flags and shift right to get actual coordinates
|
||||||
|
const xClean = xRaw & 0xFFF8;
|
||||||
|
const yClean = yRaw & 0xFFF8;
|
||||||
|
|
||||||
|
// Convert to signed 16-bit
|
||||||
|
let xSigned = xClean;
|
||||||
|
let ySigned = yClean;
|
||||||
|
if (xSigned > 0x7FFF) xSigned = xSigned - 0x10000;
|
||||||
|
if (ySigned > 0x7FFF) ySigned = ySigned - 0x10000;
|
||||||
|
|
||||||
|
// Shift right by 3 to get actual coordinates
|
||||||
|
const x = xSigned >> 3;
|
||||||
|
const y = ySigned >> 3;
|
||||||
|
|
||||||
|
const isFeed = (yFlags & PEN_FEED_DATA) !== 0;
|
||||||
|
const isCut = (yFlags & PEN_CUT_DATA) !== 0;
|
||||||
|
const isColorEnd = xFlags === PEN_COLOR_END;
|
||||||
|
const isDataEnd = xFlags === PEN_DATA_END;
|
||||||
|
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
xFlags,
|
||||||
|
yFlags,
|
||||||
|
isFeed,
|
||||||
|
isCut,
|
||||||
|
isColorEnd,
|
||||||
|
isDataEnd,
|
||||||
|
// Compatibility aliases
|
||||||
|
isJump: isFeed,
|
||||||
|
flags: (xFlags & 0x07) | (yFlags & 0x07),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode all stitches from PEN format bytes
|
||||||
|
*
|
||||||
|
* @param bytes PEN format byte array
|
||||||
|
* @returns Array of decoded stitches
|
||||||
|
*/
|
||||||
|
export function decodeAllPenStitches(bytes: Uint8Array | number[]): DecodedPenStitch[] {
|
||||||
|
if (bytes.length < 4 || bytes.length % 4 !== 0) {
|
||||||
|
throw new Error(`Invalid PEN data size: ${bytes.length} bytes (must be multiple of 4)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stitches: DecodedPenStitch[] = [];
|
||||||
|
for (let i = 0; i < bytes.length; i += 4) {
|
||||||
|
stitches.push(decodePenStitch(bytes, i));
|
||||||
|
}
|
||||||
|
return stitches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode PEN format data into a complete pattern structure
|
||||||
|
*
|
||||||
|
* This function parses PEN bytes and extracts:
|
||||||
|
* - Individual stitches with coordinates and flags
|
||||||
|
* - Color blocks (groups of stitches using the same thread color)
|
||||||
|
* - Pattern bounds
|
||||||
|
*
|
||||||
|
* @param data PEN format byte array
|
||||||
|
* @returns Complete decoded pattern data
|
||||||
|
*/
|
||||||
|
export function decodePenData(data: Uint8Array): DecodedPenData {
|
||||||
|
const stitches = decodeAllPenStitches(data);
|
||||||
|
const colorBlocks: PenColorBlock[] = [];
|
||||||
|
|
||||||
|
let minX = Infinity;
|
||||||
|
let maxX = -Infinity;
|
||||||
|
let minY = Infinity;
|
||||||
|
let maxY = -Infinity;
|
||||||
|
|
||||||
|
let currentColorStart = 0;
|
||||||
|
let currentColor = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < stitches.length; i++) {
|
||||||
|
const stitch = stitches[i];
|
||||||
|
|
||||||
|
// Track bounds (exclude jump stitches)
|
||||||
|
if (!stitch.isFeed) {
|
||||||
|
minX = Math.min(minX, stitch.x);
|
||||||
|
maxX = Math.max(maxX, stitch.x);
|
||||||
|
minY = Math.min(minY, stitch.y);
|
||||||
|
maxY = Math.max(maxY, stitch.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for color change or data end
|
||||||
|
if (stitch.isColorEnd) {
|
||||||
|
colorBlocks.push({
|
||||||
|
startStitchIndex: currentColorStart,
|
||||||
|
endStitchIndex: i,
|
||||||
|
colorIndex: currentColor,
|
||||||
|
// Compatibility aliases
|
||||||
|
startStitch: currentColorStart,
|
||||||
|
endStitch: i,
|
||||||
|
});
|
||||||
|
currentColor++;
|
||||||
|
currentColorStart = i + 1;
|
||||||
|
} else if (stitch.isDataEnd) {
|
||||||
|
// Final color block
|
||||||
|
if (currentColorStart <= i) {
|
||||||
|
colorBlocks.push({
|
||||||
|
startStitchIndex: currentColorStart,
|
||||||
|
endStitchIndex: i,
|
||||||
|
colorIndex: currentColor,
|
||||||
|
// Compatibility aliases
|
||||||
|
startStitch: currentColorStart,
|
||||||
|
endStitch: i,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
stitches,
|
||||||
|
colorBlocks,
|
||||||
|
bounds: {
|
||||||
|
minX: minX === Infinity ? 0 : minX,
|
||||||
|
maxX: maxX === -Infinity ? 0 : maxX,
|
||||||
|
minY: minY === Infinity ? 0 : minY,
|
||||||
|
maxY: maxY === -Infinity ? 0 : maxY,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the color index for a stitch at the given index
|
||||||
|
*
|
||||||
|
* @param penData Decoded PEN pattern data
|
||||||
|
* @param stitchIndex Index of the stitch
|
||||||
|
* @returns Color index, or -1 if not found
|
||||||
|
*/
|
||||||
|
export function getStitchColor(penData: DecodedPenData, stitchIndex: number): number {
|
||||||
|
for (const block of penData.colorBlocks) {
|
||||||
|
if (stitchIndex >= block.startStitchIndex && stitchIndex <= block.endStitchIndex) {
|
||||||
|
return block.colorIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
@ -5,74 +5,12 @@ import {
|
||||||
generateLockStitches,
|
generateLockStitches,
|
||||||
encodeStitchesToPen,
|
encodeStitchesToPen,
|
||||||
} from './encoder';
|
} from './encoder';
|
||||||
|
import { decodeAllPenStitches } from './decoder';
|
||||||
import { STITCH, MOVE, TRIM, END } from '../import/constants';
|
import { STITCH, MOVE, TRIM, END } from '../import/constants';
|
||||||
|
|
||||||
// PEN format flag constants for testing
|
// PEN format flag constants for testing
|
||||||
const PEN_FEED_DATA = 0x01;
|
const PEN_FEED_DATA = 0x01;
|
||||||
const PEN_CUT_DATA = 0x02;
|
const PEN_CUT_DATA = 0x02;
|
||||||
const PEN_COLOR_END = 0x03;
|
|
||||||
const PEN_DATA_END = 0x05;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to decode a single PEN stitch (4 bytes) into coordinates and flags
|
|
||||||
*/
|
|
||||||
function decodePenStitch(bytes: number[], offset: number): {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
xFlags: number;
|
|
||||||
yFlags: number;
|
|
||||||
isFeed: boolean;
|
|
||||||
isCut: boolean;
|
|
||||||
isColorEnd: boolean;
|
|
||||||
isDataEnd: boolean;
|
|
||||||
} {
|
|
||||||
const xLow = bytes[offset];
|
|
||||||
const xHigh = bytes[offset + 1];
|
|
||||||
const yLow = bytes[offset + 2];
|
|
||||||
const yHigh = bytes[offset + 3];
|
|
||||||
|
|
||||||
const xRaw = xLow | (xHigh << 8);
|
|
||||||
const yRaw = yLow | (yHigh << 8);
|
|
||||||
|
|
||||||
// Extract flags from low 3 bits
|
|
||||||
const xFlags = xRaw & 0x07;
|
|
||||||
const yFlags = yRaw & 0x07;
|
|
||||||
|
|
||||||
// Clear flags and shift right to get actual coordinates
|
|
||||||
const xClean = xRaw & 0xFFF8;
|
|
||||||
const yClean = yRaw & 0xFFF8;
|
|
||||||
|
|
||||||
// Convert to signed
|
|
||||||
let xSigned = xClean;
|
|
||||||
let ySigned = yClean;
|
|
||||||
if (xSigned > 0x7FFF) xSigned = xSigned - 0x10000;
|
|
||||||
if (ySigned > 0x7FFF) ySigned = ySigned - 0x10000;
|
|
||||||
|
|
||||||
const x = xSigned >> 3;
|
|
||||||
const y = ySigned >> 3;
|
|
||||||
|
|
||||||
return {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
xFlags,
|
|
||||||
yFlags,
|
|
||||||
isFeed: (yFlags & PEN_FEED_DATA) !== 0,
|
|
||||||
isCut: (yFlags & PEN_CUT_DATA) !== 0,
|
|
||||||
isColorEnd: xFlags === PEN_COLOR_END,
|
|
||||||
isDataEnd: xFlags === PEN_DATA_END,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to parse all stitches from PEN bytes
|
|
||||||
*/
|
|
||||||
function decodeAllPenStitches(bytes: number[]) {
|
|
||||||
const stitches = [];
|
|
||||||
for (let i = 0; i < bytes.length; i += 4) {
|
|
||||||
stitches.push(decodePenStitch(bytes, i));
|
|
||||||
}
|
|
||||||
return stitches;
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('encodeStitchPosition', () => {
|
describe('encodeStitchPosition', () => {
|
||||||
it('should encode position (0, 0) correctly', () => {
|
it('should encode position (0, 0) correctly', () => {
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
import type { PenData, PenStitch, PenColorBlock } from '../../types/machine';
|
|
||||||
|
|
||||||
// PEN format flags
|
|
||||||
const PEN_FEED_DATA = 0x01; // Y-coordinate low byte, bit 0
|
|
||||||
const PEN_COLOR_END = 0x03; // X-coordinate low byte, bits 0-2
|
|
||||||
const PEN_DATA_END = 0x05; // X-coordinate low byte, bits 0-2
|
|
||||||
|
|
||||||
export function parsePenData(data: Uint8Array): PenData {
|
|
||||||
if (data.length < 4 || data.length % 4 !== 0) {
|
|
||||||
throw new Error(`Invalid PEN data size: ${data.length} bytes`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const stitches: PenStitch[] = [];
|
|
||||||
const colorBlocks: PenColorBlock[] = [];
|
|
||||||
const stitchCount = data.length / 4;
|
|
||||||
|
|
||||||
let currentColorStart = 0;
|
|
||||||
let currentColor = 0;
|
|
||||||
let minX = Infinity, maxX = -Infinity;
|
|
||||||
let minY = Infinity, maxY = -Infinity;
|
|
||||||
|
|
||||||
console.log(`Parsing PEN data: ${data.length} bytes, ${stitchCount} stitches`);
|
|
||||||
|
|
||||||
for (let i = 0; i < stitchCount; i++) {
|
|
||||||
const offset = i * 4;
|
|
||||||
|
|
||||||
// Extract coordinates (shifted left by 3 bits in PEN format)
|
|
||||||
const xRaw = data[offset] | (data[offset + 1] << 8);
|
|
||||||
const yRaw = data[offset + 2] | (data[offset + 3] << 8);
|
|
||||||
|
|
||||||
// Extract flags from low 3 bits
|
|
||||||
const xFlags = data[offset] & 0x07;
|
|
||||||
const yFlags = data[offset + 2] & 0x07;
|
|
||||||
|
|
||||||
// Decode coordinates (shift right by 3 to get actual position)
|
|
||||||
// The coordinates are stored as signed 16-bit values, left-shifted by 3
|
|
||||||
// Step 1: Clear the flag bits (low 3 bits) from the raw values
|
|
||||||
const xRawClean = xRaw & 0xFFF8;
|
|
||||||
const yRawClean = yRaw & 0xFFF8;
|
|
||||||
|
|
||||||
// Step 2: Convert from unsigned 16-bit to signed 16-bit
|
|
||||||
let xSigned = xRawClean;
|
|
||||||
let ySigned = yRawClean;
|
|
||||||
if (xSigned > 0x7FFF) xSigned = xSigned - 0x10000;
|
|
||||||
if (ySigned > 0x7FFF) ySigned = ySigned - 0x10000;
|
|
||||||
|
|
||||||
// Step 3: Shift right by 3 (arithmetic shift, preserves sign)
|
|
||||||
const x = xSigned >> 3;
|
|
||||||
const y = ySigned >> 3;
|
|
||||||
|
|
||||||
const stitch: PenStitch = {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
flags: (xFlags & 0x07) | (yFlags & 0x07),
|
|
||||||
isJump: (yFlags & PEN_FEED_DATA) !== 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
stitches.push(stitch);
|
|
||||||
|
|
||||||
// Track bounds
|
|
||||||
if (!stitch.isJump) {
|
|
||||||
minX = Math.min(minX, x);
|
|
||||||
maxX = Math.max(maxX, x);
|
|
||||||
minY = Math.min(minY, y);
|
|
||||||
maxY = Math.max(maxY, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for color change or data end
|
|
||||||
if (xFlags === PEN_COLOR_END) {
|
|
||||||
const block: PenColorBlock = {
|
|
||||||
startStitch: currentColorStart,
|
|
||||||
endStitch: i,
|
|
||||||
colorIndex: currentColor,
|
|
||||||
};
|
|
||||||
colorBlocks.push(block);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Color ${currentColor}: stitches ${currentColorStart}-${i} (${
|
|
||||||
i - currentColorStart + 1
|
|
||||||
} stitches)`
|
|
||||||
);
|
|
||||||
|
|
||||||
currentColor++;
|
|
||||||
currentColorStart = i + 1;
|
|
||||||
} else if (xFlags === PEN_DATA_END) {
|
|
||||||
if (currentColorStart < i) {
|
|
||||||
const block: PenColorBlock = {
|
|
||||||
startStitch: currentColorStart,
|
|
||||||
endStitch: i,
|
|
||||||
colorIndex: currentColor,
|
|
||||||
};
|
|
||||||
colorBlocks.push(block);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Color ${currentColor} (final): stitches ${currentColorStart}-${i} (${
|
|
||||||
i - currentColorStart + 1
|
|
||||||
} stitches)`
|
|
||||||
);
|
|
||||||
|
|
||||||
currentColor++;
|
|
||||||
}
|
|
||||||
console.log(`Data end marker at stitch ${i}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: PenData = {
|
|
||||||
stitches,
|
|
||||||
colorBlocks,
|
|
||||||
totalStitches: stitches.length,
|
|
||||||
colorCount: colorBlocks.length,
|
|
||||||
bounds: {
|
|
||||||
minX: minX === Infinity ? 0 : minX,
|
|
||||||
maxX: maxX === -Infinity ? 0 : maxX,
|
|
||||||
minY: minY === Infinity ? 0 : minY,
|
|
||||||
maxY: maxY === -Infinity ? 0 : maxY,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Parsed: ${result.totalStitches} stitches, ${result.colorCount} colors`
|
|
||||||
);
|
|
||||||
console.log(`Bounds: (${result.bounds.minX}, ${result.bounds.minY}) to (${result.bounds.maxX}, ${result.bounds.maxY})`);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStitchColor(penData: PenData, stitchIndex: number): number {
|
|
||||||
for (const block of penData.colorBlocks) {
|
|
||||||
if (stitchIndex >= block.startStitch && stitchIndex <= block.endStitch) {
|
|
||||||
return block.colorIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
51
src/formats/pen/types.ts
Normal file
51
src/formats/pen/types.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* PEN Format Types
|
||||||
|
*
|
||||||
|
* Type definitions for decoded PEN format data.
|
||||||
|
* These types represent the parsed structure of Brother PP1 PEN embroidery files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single decoded PEN stitch with coordinates and flags
|
||||||
|
*/
|
||||||
|
export interface DecodedPenStitch {
|
||||||
|
x: number; // X coordinate (already shifted right by 3)
|
||||||
|
y: number; // Y coordinate (already shifted right by 3)
|
||||||
|
xFlags: number; // Flags from X coordinate low 3 bits
|
||||||
|
yFlags: number; // Flags from Y coordinate low 3 bits
|
||||||
|
isFeed: boolean; // Jump/move without stitching (Y-bit 0)
|
||||||
|
isCut: boolean; // Trim/cut thread (Y-bit 1)
|
||||||
|
isColorEnd: boolean; // Color change marker (X-bits 0-2 = 0x03)
|
||||||
|
isDataEnd: boolean; // Pattern end marker (X-bits 0-2 = 0x05)
|
||||||
|
|
||||||
|
// Compatibility aliases
|
||||||
|
isJump: boolean; // Alias for isFeed (backward compatibility)
|
||||||
|
flags: number; // Combined flags (backward compatibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A color block representing stitches of the same thread color
|
||||||
|
*/
|
||||||
|
export interface PenColorBlock {
|
||||||
|
startStitchIndex: number; // Index of first stitch in this color
|
||||||
|
endStitchIndex: number; // Index of last stitch in this color
|
||||||
|
colorIndex: number; // Color number (0-based)
|
||||||
|
|
||||||
|
// Compatibility aliases
|
||||||
|
startStitch: number; // Alias for startStitchIndex (backward compatibility)
|
||||||
|
endStitch: number; // Alias for endStitchIndex (backward compatibility)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete decoded PEN pattern data
|
||||||
|
*/
|
||||||
|
export interface DecodedPenData {
|
||||||
|
stitches: DecodedPenStitch[];
|
||||||
|
colorBlocks: PenColorBlock[];
|
||||||
|
bounds: {
|
||||||
|
minX: number;
|
||||||
|
maxX: number;
|
||||||
|
minY: number;
|
||||||
|
maxY: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue