From 9a5600ceeb7440d1c29e6030043d5cac356b66e5 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Fri, 6 Oct 2023 22:26:27 -0400 Subject: [PATCH] TextProperty type 8 --- ts/Gvas.ts | 8 +++++++- ts/exporter.ts | 9 ++++++++- ts/parser.ts | 17 +++++++++++++++-- ts/util.ts | 7 ++++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ts/Gvas.ts b/ts/Gvas.ts index ab35ad9..7aa472e 100644 --- a/ts/Gvas.ts +++ b/ts/Gvas.ts @@ -72,7 +72,7 @@ export interface CustomData { value: number; } -export type GvasText = null | RichText | GvasString[]; +export type GvasText = null | RichText | GvasString[] | GvasTextType8; export interface RichText { guid: GvasString; @@ -85,3 +85,9 @@ export interface RichTextFormat { contentType: number; values: GvasString[]; } + +export interface GvasTextType8 { + unknown: GvasString; + guid: GvasString; + value: GvasString; +} diff --git a/ts/exporter.ts b/ts/exporter.ts index 421337e..08344a7 100644 --- a/ts/exporter.ts +++ b/ts/exporter.ts @@ -1011,6 +1011,7 @@ function stringToBlob(str: GvasString): BlobPart { } function textToBlob(text: GvasText, largeWorldCoords: boolean): BlobPart { + const notSimple = !Array.isArray(text) && typeof text === 'object'; // text: // seq: // - id: component_type @@ -1034,7 +1035,7 @@ function textToBlob(text: GvasText, largeWorldCoords: boolean): BlobPart { new Uint8Array([255]), new Uint32Array([0]), ]); - } else if (!Array.isArray(text) && typeof text === 'object') { + } else if (notSimple && 'pattern' in text) { // text_rich: // seq: // - id: flags @@ -1059,6 +1060,12 @@ function textToBlob(text: GvasText, largeWorldCoords: boolean): BlobPart { new Uint32Array([text.textFormat.length]), new Blob(text.textFormat.map(rtfToBlob)), ]); + } else if (notSimple) { + return new Blob([ + new Uint32Array([8]), + new Uint8Array([0]), + new Blob([text.unknown, text.guid, text.value].map(stringToBlob)), + ]); } else { // text_simple: // seq: diff --git a/ts/parser.ts b/ts/parser.ts index d3ce370..63c1e01 100644 --- a/ts/parser.ts +++ b/ts/parser.ts @@ -5,6 +5,7 @@ import { GvasHeader, GvasString, GvasText, + GvasTextType8, GvasTypes, RichTextFormat, gvasToString, @@ -599,12 +600,15 @@ function parseTextArray(buffer: ArrayBuffer): [number, GvasText[]] { // - id: component_type // type: u4 const componentType = new Uint32Array(buffer.slice(pos, pos + 4))[0]; - if (componentType < 0 || componentType > 2) throw new Error(`Unexpected component type ${componentType}`); + if (![0, 1, 2, 8].includes(componentType)) throw new Error(`Unexpected component type ${componentType}`); pos += 4; // - id: indicator // type: u1 const indicator = new Uint8Array(buffer, pos, 1)[0]; - if (indicator !== [255, 3, 255][componentType]) throw new Error(`Unexpected component type ${componentType}`); + const expectedIndicator = componentType === 1 ? 3 : componentType === 8 ? 0 : 255; + if (indicator !== expectedIndicator) { + throw new Error(`Unexpected indicator ${indicator} for component type ${componentType}`); + } pos++; // - id: body // type: @@ -718,6 +722,15 @@ function parseTextArray(buffer: ArrayBuffer): [number, GvasText[]] { values.push(value); } array.push(values); + } else if (componentType === 8) { + let unknown; + let guid; + let value; + [pos, unknown] = parseString(buffer, pos); + [pos, guid] = parseString(buffer, pos); + [pos, value] = parseString(buffer, pos); + const values: GvasTextType8 = {unknown, guid, value}; + array.push(values); } else { throw new Error(`Unknown componentType: ${componentType}`); } diff --git a/ts/util.ts b/ts/util.ts index f580cf6..73bb3cc 100644 --- a/ts/util.ts +++ b/ts/util.ts @@ -43,12 +43,17 @@ export function stringToText(str: GvasString): GvasText { export function textToString(value: GvasText): GvasString { if (value === null) return null; - if (!Array.isArray(value) && typeof value === 'object') { + const notSimple = !Array.isArray(value) && typeof value === 'object'; + if (notSimple && 'pattern' in value) { // Rich text if (value.guid !== RRO_TEXT_GUID) throw new Error(`Unexpected GUID: ${value.guid}`); if (value.pattern === null) throw new Error('Null pattern'); return value.pattern.replace(/{(\d+)}/g, (m, i) => value.textFormat[Number(i)].values[0] ?? ''); + } else if (notSimple) { + // Type 8 + if (value.unknown !== '') throw new Error(`Unexpected unknown value: ${value.unknown}`); + return value.value; } else { // Simple text if (0 === value.length) {