diff --git a/src/display/optional_content_config.js b/src/display/optional_content_config.js index 27c59340f..75b437353 100644 --- a/src/display/optional_content_config.js +++ b/src/display/optional_content_config.js @@ -72,6 +72,13 @@ class OptionalContentGroup { this.#userSet = userSet; this.#visible = visible; } + + get serializable() { + return { + userSet: this.#userSet, + visible: this.#visible, + }; + } } class OptionalContentConfig { @@ -83,11 +90,19 @@ class OptionalContentConfig { #order = null; - constructor(data, renderingIntent = RenderingIntentFlag.DISPLAY) { - this.renderingIntent = renderingIntent; + #rawData; - this.name = null; - this.creator = null; + creator = null; + + name = null; + + constructor( + data, + renderingIntent = RenderingIntentFlag.DISPLAY, + groupState = null // Should *only* be used with `fromSerializable`. + ) { + this.#rawData = data; + this.renderingIntent = renderingIntent; if (data === null) { return; @@ -102,18 +117,29 @@ class OptionalContentConfig { ); } - if (data.baseState === "OFF") { - for (const group of this.#groups.values()) { - group._setVisible(INTERNAL, false); + if (groupState) { + if (groupState.size !== this.#groups.size) { + unreachable("Incorrect serialized groupState."); + } + for (const [id, group] of groupState) { + this.#groups + .get(id) + ._setVisible(INTERNAL, group.visible, group.userSet); + } + } else { + if (data.baseState === "OFF") { + for (const group of this.#groups.values()) { + group._setVisible(INTERNAL, false); + } } - } - for (const on of data.on) { - this.#groups.get(on)._setVisible(INTERNAL, true); - } + for (const on of data.on) { + this.#groups.get(on)._setVisible(INTERNAL, true); + } - for (const off of data.off) { - this.#groups.get(off)._setVisible(INTERNAL, false); + for (const off of data.off) { + this.#groups.get(off)._setVisible(INTERNAL, false); + } } // The following code must always run *last* in the constructor. @@ -230,6 +256,9 @@ class OptionalContentConfig { } setVisibility(id, visible = true, preserveRB = true) { + if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("WORKER_THREAD")) { + throw new Error("Not implemented: setVisibility"); + } const group = this.#groups.get(id); if (!group) { warn(`Optional content group not found: ${id}`); @@ -255,6 +284,9 @@ class OptionalContentConfig { } setOCGState({ state, preserveRB }) { + if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("WORKER_THREAD")) { + throw new Error("Not implemented: setOCGState"); + } let operator; for (const elem of state) { @@ -319,6 +351,23 @@ class OptionalContentConfig { [Symbol.iterator]() { return this.#groups.entries(); } + + get serializable() { + const groupState = new Map(); + for (const [id, group] of this.#groups) { + groupState.set(id, group.serializable); + } + + return { + data: this.#rawData, + renderingIntent: this.renderingIntent, + groupState, + }; + } + + static fromSerializable({ data, renderingIntent, groupState }) { + return new OptionalContentConfig(data, renderingIntent, groupState); + } } export { OptionalContentConfig };