|
|
|
|
@ -40,304 +40,39 @@ |
|
|
|
|
// FONT INDEX: 0..32767 = built-in; 0x8000+ = custom font in file (0x8000=first).
|
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Enums
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export enum SectionType { |
|
|
|
|
ElementsAlways = 1, |
|
|
|
|
ElementsTimespan = 2, |
|
|
|
|
CustomFont = 32, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export enum ElementType { |
|
|
|
|
Image2D = 1, |
|
|
|
|
Animation = 2, |
|
|
|
|
HorizontalScroll = 3, |
|
|
|
|
VerticalScroll = 4, |
|
|
|
|
Line = 5, |
|
|
|
|
ClippedText = 16, |
|
|
|
|
HScrollText = 17, |
|
|
|
|
// NOTE: spec shows CurrentTime as type 16 — likely a spec typo; treat as reserved until clarified
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Section flags (section types 1 and 2)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export interface SectionFlags { |
|
|
|
|
/** Bit 0: draw on the front side (default true for elements_always) */ |
|
|
|
|
drawFront?: boolean; |
|
|
|
|
/** Bit 1: draw on the back side */ |
|
|
|
|
drawBack?: boolean; |
|
|
|
|
/** Bit 2: clear the draw buffer(s) before drawing elements in this section */ |
|
|
|
|
clearBuffer?: boolean; |
|
|
|
|
// bits 3-15: reserved, must be 0 when writing
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Scroll flags (HorizontalScroll / VerticalScroll elements)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export interface ScrollElementFlags { |
|
|
|
|
endless?: boolean; // bit 0
|
|
|
|
|
invertDirection?: boolean; // bit 1
|
|
|
|
|
padStart?: boolean; // bit 2: padLeft (H) / padTop (V)
|
|
|
|
|
padEnd?: boolean; // bit 3: padRight (H) / padBottom (V)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// User-facing element descriptors (MonoDisplayFile input)
|
|
|
|
|
// Pixels are always 1 byte/pixel (0=off, 1=on) in the API; packed at write time.
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export interface Image2DElement { |
|
|
|
|
type: ElementType.Image2D; |
|
|
|
|
/** 1 byte per pixel (0=off 1=on), row-major. Packed to 1bpp in binary. */ |
|
|
|
|
pixels: Uint8Array; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
xOffset?: number; // default 0
|
|
|
|
|
yOffset?: number; // default 0
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface AnimationFrameDescriptor { |
|
|
|
|
/** 1 byte per pixel, same dimensions as parent AnimationElement */ |
|
|
|
|
pixels: Uint8Array; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface AnimationElement { |
|
|
|
|
type: ElementType.Animation; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
frames: AnimationFrameDescriptor[]; |
|
|
|
|
/** |
|
|
|
|
* Advance frame every (updateInterval+1) ticks. |
|
|
|
|
* 0 = every tick, 1 = every 2nd tick, etc. Default 0. |
|
|
|
|
*/ |
|
|
|
|
updateInterval?: number; |
|
|
|
|
xOffset?: number; |
|
|
|
|
yOffset?: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface HScrollElement { |
|
|
|
|
type: ElementType.HorizontalScroll; |
|
|
|
|
width: number; // viewport width
|
|
|
|
|
height: number; // viewport height
|
|
|
|
|
/** Pixel content to scroll horizontally; must be (contentWidth × height) pixels */ |
|
|
|
|
pixels: Uint8Array; // 1 byte/pixel
|
|
|
|
|
contentWidth: number; |
|
|
|
|
/** |
|
|
|
|
* Scroll speed byte SS; moves (SS+1)/16 pixels per tick. Default 0 (1/16 px/tick). |
|
|
|
|
* Range 0-255. |
|
|
|
|
*/ |
|
|
|
|
scrollSpeed?: number; |
|
|
|
|
flags?: ScrollElementFlags; |
|
|
|
|
xOffset?: number; |
|
|
|
|
yOffset?: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface VScrollElement { |
|
|
|
|
type: ElementType.VerticalScroll; |
|
|
|
|
width: number; |
|
|
|
|
height: number; // viewport height
|
|
|
|
|
pixels: Uint8Array; // 1 byte/pixel
|
|
|
|
|
contentHeight: number; |
|
|
|
|
scrollSpeed?: number; |
|
|
|
|
flags?: ScrollElementFlags; |
|
|
|
|
xOffset?: number; |
|
|
|
|
yOffset?: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface LineElement { |
|
|
|
|
type: ElementType.Line; |
|
|
|
|
xOrigin: number; |
|
|
|
|
yOrigin: number; |
|
|
|
|
xTarget: number; |
|
|
|
|
yTarget: number; |
|
|
|
|
lineStyle?: number; // reserved, default 0
|
|
|
|
|
invertPixels?: boolean; // flags bit 0
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface ClippedTextElement { |
|
|
|
|
type: ElementType.ClippedText; |
|
|
|
|
text: string; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
/** 0-32767 built-in font, 0x8000+ custom font in file. Default 0. */ |
|
|
|
|
fontIndex?: number; |
|
|
|
|
xOffset?: number; |
|
|
|
|
yOffset?: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface HScrollTextElement { |
|
|
|
|
type: ElementType.HScrollText; |
|
|
|
|
text: string; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
scrollSpeed?: number; // SS byte, default 0
|
|
|
|
|
fontIndex?: number; |
|
|
|
|
flags?: ScrollElementFlags; |
|
|
|
|
xOffset?: number; |
|
|
|
|
yOffset?: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export type DrawElement = |
|
|
|
|
| Image2DElement |
|
|
|
|
| AnimationElement |
|
|
|
|
| HScrollElement |
|
|
|
|
| VScrollElement |
|
|
|
|
| LineElement |
|
|
|
|
| ClippedTextElement |
|
|
|
|
| HScrollTextElement; |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// MonoDisplayFile descriptor
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export interface ElementsAlwaysDescriptor { |
|
|
|
|
flags?: SectionFlags; |
|
|
|
|
elements: DrawElement[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* JSON descriptor passed to MonoDisplayFile. |
|
|
|
|
* |
|
|
|
|
* elements_always — section type 1; drawn on every render tick. |
|
|
|
|
* Pass a DrawElement[] as shorthand (flags default to drawFront=true). |
|
|
|
|
* |
|
|
|
|
* PLAN: elements_timespan (section 2), custom_fonts (section 32) |
|
|
|
|
*/ |
|
|
|
|
export interface MonoDisplayFileDescriptor { |
|
|
|
|
elements_always?: DrawElement[] | ElementsAlwaysDescriptor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// MonoFormat types (parser output → renderer input)
|
|
|
|
|
// Pixels are always unpacked (1 byte/pixel) after parsing.
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
export interface MonoFormatPixelImage { |
|
|
|
|
/** Unpacked: 1 byte per pixel, 0=off 1=on, row-major */ |
|
|
|
|
pixels: Uint8Array; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatImage2D { |
|
|
|
|
type: ElementType.Image2D; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
image: MonoFormatPixelImage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatAnimation { |
|
|
|
|
type: ElementType.Animation; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
updateInterval: number; |
|
|
|
|
frames: MonoFormatPixelImage[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatHScroll { |
|
|
|
|
type: ElementType.HorizontalScroll; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
contentWidth: number; |
|
|
|
|
scrollSpeed: number; |
|
|
|
|
flags: { endless: boolean; invertDirection: boolean; padStart: boolean; padEnd: boolean }; |
|
|
|
|
content: MonoFormatPixelImage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatVScroll { |
|
|
|
|
type: ElementType.VerticalScroll; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
contentHeight: number; |
|
|
|
|
scrollSpeed: number; |
|
|
|
|
flags: { endless: boolean; invertDirection: boolean; padStart: boolean; padEnd: boolean }; |
|
|
|
|
content: MonoFormatPixelImage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatLine { |
|
|
|
|
type: ElementType.Line; |
|
|
|
|
xOrigin: number; |
|
|
|
|
yOrigin: number; |
|
|
|
|
xTarget: number; |
|
|
|
|
yTarget: number; |
|
|
|
|
lineStyle: number; |
|
|
|
|
invertPixels: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatClippedText { |
|
|
|
|
type: ElementType.ClippedText; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
fontIndex: number; |
|
|
|
|
text: string; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatHScrollText { |
|
|
|
|
type: ElementType.HScrollText; |
|
|
|
|
xOffset: number; |
|
|
|
|
yOffset: number; |
|
|
|
|
width: number; |
|
|
|
|
height: number; |
|
|
|
|
scrollSpeed: number; |
|
|
|
|
fontIndex: number; |
|
|
|
|
flags: { endless: boolean; invertDirection: boolean; padStart: boolean; padEnd: boolean }; |
|
|
|
|
text: string; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export type MonoFormatElement = |
|
|
|
|
| MonoFormatImage2D |
|
|
|
|
| MonoFormatAnimation |
|
|
|
|
| MonoFormatHScroll |
|
|
|
|
| MonoFormatVScroll |
|
|
|
|
| MonoFormatLine |
|
|
|
|
| MonoFormatClippedText |
|
|
|
|
| MonoFormatHScrollText; |
|
|
|
|
|
|
|
|
|
export interface MonoFormatSectionFlags { |
|
|
|
|
drawFront: boolean; |
|
|
|
|
drawBack: boolean; |
|
|
|
|
clearBuffer: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatElementsAlways { |
|
|
|
|
sectionType: SectionType.ElementsAlways; |
|
|
|
|
flags: MonoFormatSectionFlags; |
|
|
|
|
elements: MonoFormatElement[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatElementsTimespan { |
|
|
|
|
sectionType: SectionType.ElementsTimespan; |
|
|
|
|
flags: MonoFormatSectionFlags; |
|
|
|
|
startTimestamp: bigint; // POSIX seconds
|
|
|
|
|
endTimestamp: bigint; |
|
|
|
|
elements: MonoFormatElement[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export interface MonoFormatCustomFont { |
|
|
|
|
sectionType: SectionType.CustomFont; |
|
|
|
|
/** Raw U8G2 font data */ |
|
|
|
|
fontData: Uint8Array; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export type MonoFormatSection = MonoFormatElementsAlways | MonoFormatElementsTimespan | MonoFormatCustomFont; |
|
|
|
|
|
|
|
|
|
/** Top-level parser output */ |
|
|
|
|
export interface MonoFormatFile { |
|
|
|
|
sections: MonoFormatSection[]; |
|
|
|
|
} |
|
|
|
|
export * from "./types.js"; |
|
|
|
|
import { |
|
|
|
|
SectionType, |
|
|
|
|
ElementType, |
|
|
|
|
type SectionFlags, |
|
|
|
|
type ScrollElementFlags, |
|
|
|
|
type Image2DElement, |
|
|
|
|
type AnimationElement, |
|
|
|
|
type HScrollElement, |
|
|
|
|
type VScrollElement, |
|
|
|
|
type LineElement, |
|
|
|
|
type ClippedTextElement, |
|
|
|
|
type HScrollTextElement, |
|
|
|
|
type DrawElement, |
|
|
|
|
type ElementsAlwaysDescriptor, |
|
|
|
|
type MonoDisplayFileDescriptor, |
|
|
|
|
type MonoFormatPixelImage, |
|
|
|
|
type MonoFormatImage2D, |
|
|
|
|
type MonoFormatAnimation, |
|
|
|
|
type MonoFormatScrollFlags, |
|
|
|
|
type MonoFormatHScroll, |
|
|
|
|
type MonoFormatVScroll, |
|
|
|
|
type MonoFormatLine, |
|
|
|
|
type MonoFormatClippedText, |
|
|
|
|
type MonoFormatHScrollText, |
|
|
|
|
type MonoFormatElement, |
|
|
|
|
type MonoFormatSectionFlags, |
|
|
|
|
type MonoFormatElementsAlways, |
|
|
|
|
type MonoFormatElementsTimespan, |
|
|
|
|
type MonoFormatCustomFont, |
|
|
|
|
type MonoFormatSection, |
|
|
|
|
type MonoFormatFile, |
|
|
|
|
} from "./types.js"; |
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Pixel pack/unpack helpers
|
|
|
|
|
|