import * as grpc from "@grpc/grpc-js"; import {Buffer} from "buffer"; import {Access} from "../../access"; import {IronPdfServiceClient} from "../../generated_proto/ironpdfengineproto/IronPdfService"; import { PdfiumSetFormFontRequestStreamP } from "../../generated_proto/ironpdfengineproto/PdfiumSetFormFontRequestStreamP"; import { PdfiumSetFormFontResultP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumSetFormFontResultP"; import { PdfiumDisableFormFontFallbackResultP__Output } from "../../generated_proto/ironpdfengineproto/PdfiumDisableFormFontFallbackResultP"; import {chunkBuffer, handleRemoteException} from "../util"; import {validateFormFontData, validateFormFontName} from "./formFontValidator"; /** * Stream a font (or just a name reference) to the engine so subsequent * form-field fills with non-ASCII values use the supplied font instead of * triggering the automatic Tahoma/Arial fallback embed. */ export async function setFormFont( id: string, fontName: string, fontData: Buffer | undefined, forceEmbed: boolean ): Promise { validateFormFontName(fontName); // Distinguish between "name-only mode" (caller passed undefined/null) and // "caller passed bytes". An explicit Buffer — even an empty one — runs the // data validator, which rejects empty/oversize/non-sfnt payloads. Mirrors // .NET FormFontValidator behaviour where an empty byte[] is a caller error. if (fontData !== undefined && fontData !== null) { validateFormFontData(fontData); } const client: IronPdfServiceClient = await Access.ensureConnection(); return new Promise( (resolve: () => void, reject: (errorMsg: string) => void) => { let resolved = false; const stream: grpc.ClientWritableStream = client.Pdfium_Form_SetFormFont( ( err: grpc.ServiceError | null, value: PdfiumSetFormFontResultP__Output | undefined ) => { if (resolved) return; resolved = true; if (err) { reject(`${err.name}/n${err.message}`); return; } if (!value) { reject("No response from IronPdfEngine for setFormFont"); return; } if (value.exception) { handleRemoteException(value.exception, reject); return; } resolve(); } ); // Send Info first. stream.write({ info: { document: {documentId: id}, fontName: fontName, fontBytesSize: fontData ? fontData.length : 0, forceEmbed: forceEmbed, }, }); // Stream bytes (if any). if (fontData && fontData.length > 0) { for (const chunk of chunkBuffer(fontData)) { stream.write({fontBytesChunk: chunk}); } } stream.end(); } ); } /** * Suppress the engine's automatic Tahoma/Arial fallback embed for non-ASCII * form-field values without registering a replacement font. */ export async function disableFormFontFallback(id: string): Promise { const client: IronPdfServiceClient = await Access.ensureConnection(); return new Promise( (resolve: () => void, reject: (errorMsg: string) => void) => { client.Pdfium_Form_DisableFormFontFallback( {document: {documentId: id}}, ( err: grpc.ServiceError | null, value: PdfiumDisableFormFontFallbackResultP__Output | undefined ) => { if (err) { reject(`${err.name}/n${err.message}`); return; } if (!value) { reject("No response from IronPdfEngine for disableFormFontFallback"); return; } if (value.exception) { handleRemoteException(value.exception, reject); return; } resolve(); } ); } ); }