Sample code for 30+ languages & platforms
Zig Requires Chilkat v11.7.0+

Why a PDF Text Replacement Is Refused: the Font Rule

See more PDF Text Replacement Examples

A PDF stores glyphs drawn with particular fonts, so new text can only be drawn when the original font can draw it. This example shows the two common refusals. A font embedded as a subset carries only the glyphs the document used: a value made of other characters is refused with the reason missingGlyph, and the report names the font and the characters it lacks. A font that is neither one of the standard 14 nor embedded (here Verdana) is refused with nonStandardUnembeddedFont, because Chilkat cannot know what a viewer will draw for it. A non-embedded Arial, Times New Roman or Courier New is treated as the standard font every viewer substitutes for it.

Chilkat Zig Downloads

Zig
const std = @import("std");
const chilkat = @import("chilkat");

pub fn main(init: std.process.Init) !void {
    const alloc = init.arena.allocator();

    var success: bool = false;

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    // The PDF used in this example is available at quote_subset_font.pdf
    // and letter_verdana.pdf

    // 1. An embedded subset font: only the glyphs the document uses are in the PDF.
    const pdf = try chilkat.Pdf.init();
    defer pdf.deinit();
    success = if (pdf.loadFile("qa_data/pdf/quote_subset_font.pdf")) true else |_| false;
    if (!success) {
        std.debug.print("{s}\n", .{try pdf.getLastErrorText(alloc)});
        return;
    }

    const json = try chilkat.JsonObject.init();
    defer json.deinit();
    const json_out = try chilkat.JsonObject.init();
    defer json_out.deinit();

    // The regular face's subset carries the characters of the quotation's text, among them the digits of
    // "58341".  A new number made of those digits can be drawn...
    json.updateString("labels[0].label", "Quote #:") catch {};
    json.updateString("labels[0].value", "58314") catch {};
    success = if (pdf.textReplace("check", json, json_out)) true else |_| false;
    if (!success) {
        std.debug.print("{s}\n", .{try pdf.getLastErrorText(alloc)});
        return;
    }

    std.debug.print("58314: ok = {}\n", .{json_out.boolOf("ok")});

    // ...but "Q" and "-" are not in the subset (nothing in the quotation's regular text uses them).
    json.updateString("labels[0].value", "Q-58341") catch {};
    success = if (pdf.textReplace("check", json, json_out)) true else |_| false;
    if (!success) {
        std.debug.print("{s}\n", .{try pdf.getLastErrorText(alloc)});
        return;
    }

    std.debug.print("Q-58341: ok = {}\n", .{json_out.boolOf("ok")});
    if (!json_out.boolOf("ok")) {
        // The problem names the font and the characters it cannot draw.
        std.debug.print("    reason: {s}\n", .{try json_out.stringOf(alloc, "problems[0].reason")});
        std.debug.print("    font: {s}\n", .{try json_out.stringOf(alloc, "problems[0].font")});
        std.debug.print("    missing: {s}\n", .{try json_out.stringOf(alloc, "problems[0].chars")});
    }

    // "apply" with a problem returns false and changes nothing.
    success = if (pdf.textReplace("apply", json, json_out)) true else |_| false;
    std.debug.print("apply returned {}, applied = {}\n", .{ success, json_out.boolOf("applied") });

    // 2. A font that is not embedded and not one of the standard 14.
    const pdf2 = try chilkat.Pdf.init();
    defer pdf2.deinit();
    pdf2.loadFile("qa_data/pdf/letter_verdana.pdf") catch {
        std.debug.print("{s}\n", .{try pdf2.getLastErrorText(alloc)});
        return;
    };

    const json2 = try chilkat.JsonObject.init();
    defer json2.deinit();
    json2.updateString("labels[0].label", "Account Number:") catch {};
    json2.updateString("labels[0].value", "0000099999") catch {};
    pdf2.textReplace("check", json2, json_out) catch {
        std.debug.print("{s}\n", .{try pdf2.getLastErrorText(alloc)});
        return;
    };

    std.debug.print("Verdana, not embedded: ok = {}, reason: {s}, font: {s}\n", .{ json_out.boolOf("ok"), try json_out.stringOf(alloc, "problems[0].reason"), try json_out.stringOf(alloc, "problems[0].font") });

    // Sample output:

    // 58314: ok = true
    // Q-58341: ok = false
    //     reason: missingGlyph
    //     font: AAAAAA+DejaVuSans
    //     missing: Q-
    // apply returned false, applied = false
    // Verdana, not embedded: ok = false, reason: nonStandardUnembeddedFont, font: Verdana
}