pagyra-js 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ export declare class BinaryWriter {
2
+ private buffer;
3
+ private view;
4
+ private offset;
5
+ constructor(initialSize?: number);
6
+ ensureSize(size: number): void;
7
+ writeUint8(value: number): void;
8
+ writeInt8(value: number): void;
9
+ writeUint16(value: number): void;
10
+ writeInt16(value: number): void;
11
+ writeUint32(value: number): void;
12
+ writeInt32(value: number): void;
13
+ writeFixed(value: number): void;
14
+ writeString(value: string): void;
15
+ writeBytes(bytes: Uint8Array): void;
16
+ getData(): Uint8Array;
17
+ byteLength(): number;
18
+ }
@@ -0,0 +1,67 @@
1
+ export class BinaryWriter {
2
+ constructor(initialSize = 1024) {
3
+ this.buffer = new Uint8Array(initialSize);
4
+ this.view = new DataView(this.buffer.buffer);
5
+ this.offset = 0;
6
+ }
7
+ ensureSize(size) {
8
+ if (this.offset + size > this.buffer.length) {
9
+ const newSize = Math.max(this.buffer.length * 2, this.offset + size);
10
+ const newBuffer = new Uint8Array(newSize);
11
+ newBuffer.set(this.buffer);
12
+ this.buffer = newBuffer;
13
+ this.view = new DataView(this.buffer.buffer);
14
+ }
15
+ }
16
+ writeUint8(value) {
17
+ this.ensureSize(1);
18
+ this.view.setUint8(this.offset, value);
19
+ this.offset += 1;
20
+ }
21
+ writeInt8(value) {
22
+ this.ensureSize(1);
23
+ this.view.setInt8(this.offset, value);
24
+ this.offset += 1;
25
+ }
26
+ writeUint16(value) {
27
+ this.ensureSize(2);
28
+ this.view.setUint16(this.offset, value, false);
29
+ this.offset += 2;
30
+ }
31
+ writeInt16(value) {
32
+ this.ensureSize(2);
33
+ this.view.setInt16(this.offset, value, false);
34
+ this.offset += 2;
35
+ }
36
+ writeUint32(value) {
37
+ this.ensureSize(4);
38
+ this.view.setUint32(this.offset, value, false);
39
+ this.offset += 4;
40
+ }
41
+ writeInt32(value) {
42
+ this.ensureSize(4);
43
+ this.view.setInt32(this.offset, value, false);
44
+ this.offset += 4;
45
+ }
46
+ writeFixed(value) {
47
+ const integer = Math.floor(value);
48
+ const fraction = Math.floor((value - integer) * 65536);
49
+ this.writeInt16(integer);
50
+ this.writeUint16(fraction);
51
+ }
52
+ writeString(value) {
53
+ const encoded = new TextEncoder().encode(value);
54
+ this.writeBytes(encoded);
55
+ }
56
+ writeBytes(bytes) {
57
+ this.ensureSize(bytes.length);
58
+ this.buffer.set(bytes, this.offset);
59
+ this.offset += bytes.length;
60
+ }
61
+ getData() {
62
+ return this.buffer.slice(0, this.offset);
63
+ }
64
+ byteLength() {
65
+ return this.offset;
66
+ }
67
+ }
@@ -98,7 +98,7 @@ function computeBaseUrl() {
98
98
  return `${origin}assets/fonts/`;
99
99
  }
100
100
  try {
101
- return new URL("../../assets/fonts/", import.meta.url).toString();
101
+ return new URL(/* @vite-ignore */ "../../assets/fonts/", import.meta.url).toString();
102
102
  }
103
103
  catch {
104
104
  return "/assets/fonts/";
@@ -18,6 +18,7 @@ export declare class FontEmbedder {
18
18
  initialize(): Promise<void>;
19
19
  ensureFont(familyStack: string[], fontWeight?: number, fontStyle?: string): EmbeddedFont | null;
20
20
  private embedFont;
21
+ private realizeFont;
21
22
  private createToUnicodeCMap;
22
23
  /**
23
24
  * Return parsed TTF metrics for a loaded face by name or family, or null if not available.
@@ -87,6 +87,25 @@ export class FontEmbedder {
87
87
  const metrics = this.faceMetrics.get(face.name);
88
88
  if (!metrics)
89
89
  return null;
90
+ const fullFontData = new Uint8Array(face.data);
91
+ const resourceName = `F${this.embeddedFonts.size + 1}`;
92
+ let realizedRef;
93
+ const self = this;
94
+ const embedded = {
95
+ resourceName,
96
+ baseFont: face.name,
97
+ metrics,
98
+ subset: fullFontData,
99
+ get ref() {
100
+ if (!realizedRef) {
101
+ realizedRef = self.realizeFont(face, metrics, resourceName);
102
+ }
103
+ return realizedRef;
104
+ }
105
+ };
106
+ return embedded;
107
+ }
108
+ realizeFont(face, metrics, resourceName) {
90
109
  const unitsPerEm = metrics.metrics.unitsPerEm;
91
110
  const scaleTo1000 = (v) => Math.round((v / unitsPerEm) * 1000);
92
111
  let fontBBox;
@@ -95,16 +114,9 @@ export class FontEmbedder {
95
114
  fontBBox = [scaleTo1000(hb[0]), scaleTo1000(hb[1]), scaleTo1000(hb[2]), scaleTo1000(hb[3])];
96
115
  }
97
116
  else {
98
- // Fallback if headBBox is missing
99
117
  fontBBox = [-1000, -1000, 1000, 1000];
100
118
  }
101
- // Register the font file stream
102
- // We need the full font data here. In the initialize method we updated face.data
103
- // but here we need to access it.
104
- // Since we can't easily change the interface, we'll assume face.data is the source.
105
- // If it was converted to TTF in initialize, face.data (casted) holds the TTF buffer.
106
119
  const fullFontData = new Uint8Array(face.data);
107
- // FontFile2 streams require only /Length (PdfDocument adds it); avoid Type1-specific Length1 headers.
108
120
  const fontFileRef = this.doc.registerStream(fullFontData, {});
109
121
  const fontDescriptor = {
110
122
  Type: "/FontDescriptor",
@@ -120,10 +132,7 @@ export class FontEmbedder {
120
132
  FontFile2: fontFileRef
121
133
  };
122
134
  const fontDescriptorRef = this.doc.register(fontDescriptor);
123
- // Compute DW and compressed W
124
135
  const { DW, W } = computeWidths(metrics);
125
- // Create CID font dictionary (include DW)
126
- // CID fonts must declare string-valued CIDSystemInfo entries per PDF spec.
127
136
  const cidFontDict = {
128
137
  Type: "/Font",
129
138
  Subtype: "/CIDFontType2",
@@ -136,15 +145,10 @@ export class FontEmbedder {
136
145
  FontDescriptor: fontDescriptorRef,
137
146
  DW,
138
147
  W,
139
- // Rely on built-in Identity CIDToGID mapping to keep font dictionaries simple/compatible.
140
148
  CIDToGIDMap: "/Identity"
141
149
  };
142
150
  const cidFontRef = this.doc.register(cidFontDict);
143
- // Create Unicode mapping (ToUnicode CMap)
144
151
  const toUnicodeRef = this.createToUnicodeCMap(metrics);
145
- // Create Type0 font dictionary
146
- // Per PDF spec, Type0 BaseFont should include the CMap suffix (e.g. "-Identity-H")
147
- // to make the composite font name unambiguous for parsers/renderers.
148
152
  const type0Font = {
149
153
  Type: "/Font",
150
154
  Subtype: "/Type0",
@@ -153,14 +157,7 @@ export class FontEmbedder {
153
157
  DescendantFonts: [cidFontRef],
154
158
  ToUnicode: toUnicodeRef
155
159
  };
156
- const fontRef = this.doc.register(type0Font);
157
- return {
158
- resourceName: `F${this.embeddedFonts.size + 1}`,
159
- ref: fontRef,
160
- baseFont: face.name,
161
- metrics,
162
- subset: fullFontData
163
- };
160
+ return this.doc.register(type0Font);
164
161
  }
165
162
  createToUnicodeCMap(metrics, _uniqueUnicodes = []) {
166
163
  // Build inverse mapping gid -> unicode (pick first unicode when multiple map to same gid)
@@ -4,17 +4,6 @@ import { log } from "../../logging/debug.js";
4
4
  import { needsUnicode } from "../../text/text.js";
5
5
  import { fontWeightCacheKey, normalizeFontWeight } from "../../css/font-weight.js";
6
6
  import { parseFontFaces, parseFamilyList, isItalicStyle, normalizeToken, } from "../../css/font-face-parser.js";
7
- // import {
8
- // BASE_FONT_ALIASES,
9
- // GENERIC_FAMILIES,
10
- // BASE14_FALLBACKS,
11
- // BASE14_FAMILY_VARIANTS,
12
- // BASE14_VARIANT_LOOKUP,
13
- // detectBase14Family,
14
- // classifyBase14Variant,
15
- // type Base14Family,
16
- // type Base14Variant,
17
- // } from "./font-config.js";
18
7
  import { applyWeightToBaseFont } from "./resolvers/weight-style-applicator.js";
19
8
  import { buildAliasedFamilyStack } from "./resolvers/family-resolver.js";
20
9
  import { resolveBaseFont } from "./resolvers/base-font-mapper.js";
@@ -23,20 +12,17 @@ import { SubsetResourceManager } from "./managers/subset-resource-manager.js";
23
12
  export function getBase14(family) {
24
13
  return { isBase14: true, baseName: family, name: family };
25
14
  }
26
- // Note: getFontForText needs access to doc and config, so we'll modify the signature
27
15
  export function getFontForText(_requestedFamily, text, _doc, _config) {
28
16
  if (needsUnicode(text)) {
29
- // For now, use a simplified approach - we'll assume NotoSans-Regular is available
30
- // In a full implementation, you'd initialize the embedder properly
31
17
  const fontName = "NotoSans-Regular";
32
18
  log("font", "info", "font-path", { base14: false, family: fontName, encoding: "Identity-H" });
33
19
  return { isBase14: false, name: fontName };
34
20
  }
35
- const f = getBase14("Helvetica"); // fallback
21
+ const f = getBase14("Helvetica");
36
22
  log("font", "info", "font-path", { base14: true, family: f.baseName, encoding: "WinAnsi" });
37
23
  return f;
38
24
  }
39
- const DEFAULT_FONT = "Times New Roman"; // Use embedded TTF font instead of base14
25
+ const DEFAULT_FONT = "Times New Roman";
40
26
  export class FontRegistry {
41
27
  constructor(doc, stylesheets) {
42
28
  this.doc = doc;
@@ -62,7 +48,7 @@ export class FontRegistry {
62
48
  const resource = {
63
49
  baseFont: embedded.baseFont,
64
50
  resourceName: embedded.resourceName,
65
- ref: embedded.ref,
51
+ get ref() { return embedded.ref; },
66
52
  isBase14: false,
67
53
  metrics: embedded.metrics,
68
54
  embedded,
@@ -75,7 +61,6 @@ export class FontRegistry {
75
61
  this.fontResourceManager.setCached(familyKey, resolved);
76
62
  return resolved;
77
63
  }
78
- // New method to get embedder reference
79
64
  getEmbedder() {
80
65
  return this.embedder;
81
66
  }
@@ -94,14 +79,12 @@ export class FontRegistry {
94
79
  }
95
80
  if (this.embedder && this.fontConfig) {
96
81
  const familyStack = buildAliasedFamilyStack(family, this.fontConfig?.defaultStack);
97
- // Note: embedder.ensureFont is synchronous in its implementation (it uses pre-loaded data)
98
- // even though the interface might not explicitly say so, we know it returns EmbeddedFont | null immediately.
99
82
  const embedded = this.embedder.ensureFont(familyStack, normalizedWeight, style);
100
83
  if (embedded) {
101
84
  const resource = {
102
85
  baseFont: embedded.baseFont,
103
86
  resourceName: embedded.resourceName,
104
- ref: embedded.ref,
87
+ get ref() { return embedded.ref; },
105
88
  isBase14: false,
106
89
  metrics: embedded.metrics,
107
90
  embedded,
@@ -169,7 +152,6 @@ export function initFontSystem(doc, stylesheets) {
169
152
  }
170
153
  export async function ensureFontSubset(registry, run) {
171
154
  const font = await registry.ensureFontResource(run.fontFamily, run.fontWeight, run.fontStyle);
172
- // === diagnóstico cirúrgico: caminho de fonte ===
173
155
  log("font", "info", "font-path", {
174
156
  base14: font.isBase14 === true,
175
157
  family: font.baseFont,
@@ -179,7 +161,6 @@ export async function ensureFontSubset(registry, run) {
179
161
  }
180
162
  export function ensureFontSubsetSync(registry, run) {
181
163
  const font = registry.ensureFontResourceSync(run.fontFamily, run.fontWeight, run.fontStyle);
182
- // === diagnóstico cirúrgico: caminho de fonte ===
183
164
  log("font", "info", "font-path", {
184
165
  base14: font.isBase14 === true,
185
166
  family: font.baseFont,
@@ -188,8 +169,6 @@ export function ensureFontSubsetSync(registry, run) {
188
169
  return font;
189
170
  }
190
171
  export function finalizeFontSubsets(_registry) {
191
- // Actual font materialization happens during PdfDocument.finalize().
192
172
  }
193
173
  export function preflightFontsForPdfa(_registry) {
194
- // Placeholder for PDF/A validations.
195
174
  }
@@ -11,10 +11,13 @@ export interface PdfFontSubset {
11
11
  fontFile: Uint8Array;
12
12
  encodeGlyph(gid: number): number;
13
13
  /**
14
- * Ordered glyph IDs included in this subset. The position in this array matches
15
- * the width entries when using identity encoding.
14
+ * Ordered glyph IDs included in this subset.
16
15
  */
17
16
  glyphIds: number[];
17
+ /**
18
+ * Map from original GID to new subset GID.
19
+ */
20
+ gidMap: Map<number, number>;
18
21
  }
19
22
  /**
20
23
  * Options for creating a PDF font subset.
@@ -26,8 +29,8 @@ export interface PdfFontSubsetOptions {
26
29
  usedGlyphIds: Set<number>;
27
30
  /**
28
31
  * Controls how glyph IDs are mapped to PDF character codes.
29
- * - "identity" keeps CIDs = glyph IDs (suitable for CIDToGIDMap /Identity).
30
- * - "sequential" densely re-encodes glyphs starting at 0.
32
+ * - "identity" keeps CIDs = Original Glyph IDs (most stable for progressive rendering).
33
+ * - "sequential" densely re-encodes glyphs starting at 0 (most compact).
31
34
  */
32
35
  encoding?: "identity" | "sequential";
33
36
  }