ImageGear for C and C++ on Windows v19.10 - Updated
Edit PDF Content and Fonts
User Guide > How to Work with... > Formats with Additional Functionality > PDF > How to... > Manage PDF Content > Edit PDF Content and Fonts

Before working with a PDF document, make sure to initialize the PDF component (see Getting Started with PDF).

The ImageGear API provides content editing functionality for creating, accessing, and editing PDF page content objects. With this API you can work with a page's content as a list of objects, such as images, text, forms. You can retain, modify, and save their data and properties.  

Document font support includes:

The code snippet below adds a text element to the content of a PDF. This example demonstrates creating a font, using the content in a PDF, and creating a text element.

C
Copy Code
#include <windows.h>

#include "gear.h"
#include "i_PDF.h"

// This function returns a new font to use for the text element.
HIG_PDE_FONT CreateNewFont( )
{
    // Declare variables.
    AT_PDE_FONTATTRS fontAttrs;
    HIG_PDE_FONT hFont = NULL;
    HIG_PDF_SYSFONT hSysFont = NULL;

    // Initialize font attributes.
    memset(&fontAttrs, 0, sizeof(fontAttrs));
    // Set font name attribute.
    IG_PDF_atom_from_string("Times-Roman", &(fontAttrs.name));
    // Set font type attribute.
    IG_PDF_atom_from_string("Type1", &(fontAttrs.type));

    // Create from sysfont.
    IG_PDF_sysfont_find(&fontAttrs, 0, &hSysFont);
    IG_PDE_font_create_from_sysfont(hSysFont, 0, IG_PDF_ATOM_NULL, NULL, &hFont);
    IG_PDF_sysfont_release(hSysFont);

    return hFont;
}

// This function will add a text element into the content of the PDF document.
void AddTextToFirstPDFPage( HMIGEAR document)
{
    // Declare variables.
    HIGEAR page = NULL;
    HIG_PDF_PAGE hPDFPage = NULL;
    HIG_PDE_CONTENT hContent = NULL;
    HIG_PDE_FONT hFont = NULL;
    HIG_PDF_ATOM hCSName = IG_PDF_ATOM_NULL;
    HIG_PDE_COLORSPACE hColorSpace = NULL;
    AT_PDE_GRAPHICSTATE graphicState;
    HIG_PDE_TEXT hText = NULL;
    AT_PDF_FIXEDMATRIX textMatrix;
    AT_PDF_FIXEDRECT cropBox;
    LPSTR textToAdd;
    int textLength = 0;
    LONG horizontalCenter, verticalCenter, textWidthEM, scaledTextWidth,
        textXPosition, textYPosition = 0;
    SHORT fontWidthScale, fontHeightScale = 0;

    // Get first page.
    IG_mpi_page_get(document, 0, &page);

    // Obtain PDF page.
    IG_vector_data_get(page, (LPVOID*)&hPDFPage);

    // Get page content.
    IG_PDF_page_get_content(hPDFPage, &hContent);

    // Create a font to use with the text element.
    hFont = CreateNewFont();

    // Set the color space to DeviceRGB.
    IG_PDF_atom_from_string("DeviceRGB", &hCSName);
    IG_PDE_colorspace_create(hCSName, NULL, &hColorSpace);

    // Set the attributes for the graphic state.
    memset(&graphicState, 0, sizeof(graphicState));
    graphicState.strokeColorSpec.space = graphicState.fillColorSpec.space = hColorSpace;

    // Create a blue text (for example).
    // Note: Color values are expressed as real numbers.
        // Set R componet.
    graphicState.fillColorSpec.value.color[0] = 0;
    // Set G componet.
    graphicState.fillColorSpec.value.color[1] = 0;
    // Set B componet.
    graphicState.fillColorSpec.value.color[2] = AM_PDF_DOUBLE_TO_FIXED(255./255);

    graphicState.miterLimit = IG_PDF_FIXED_TEN;
    graphicState.flatness = IG_PDF_FIXED_ONE;
    graphicState.lineWidth = IG_PDF_FIXED_ONE;

    // Create a string of text.
    textToAdd = "This is the string of text that will be added";

    // Set the length of the text.
    textLength = strlen(textToAdd);

    // Get page box.
    IG_PDF_page_get_crop_box(hPDFPage, &cropBox);

    // Calculate the center of the page.
    horizontalCenter = (cropBox.right - cropBox.left)/2;
    verticalCenter = (cropBox.top - cropBox.bottom)/2;

    // Get the width of the text in EM space.
    // Note: One EM in a 16-point typeface is 16 points.
    IG_PDE_font_sum_widths(hFont, (LPBYTE)textToAdd, textLength, &textWidthEM);
        
    fontWidthScale = 20;
    fontHeightScale = 20;

    // Get the width of the text considering font size.
    // Note: Convert from thousandths of a point to points and adjusts by the width scale factor.
    scaledTextWidth = (textWidthEM/1000) * fontWidthScale;

    // Set coordinates to center the text.
    textXPosition = horizontalCenter - AM_PDF_LONG_TO_FIXED(scaledTextWidth/ 2);
    textYPosition = verticalCenter;

    // Create a matrix to draw text with font size 20pt at the center of the page.
    // Note: The text matrix is a 3x3 affine transform matrix, depicted in its
    // abbreviated form: [ a b c d h v ]
    // * Set matrix values a and d to the font size in pt.
    // * Set matrix values h and v to move glyphs from user space origin to a place on the page.
    memset(&textMatrix, 0, sizeof(textMatrix));
    textMatrix.a = AM_PDF_SHORT_TO_FIXED(fontWidthScale);
    textMatrix.d = AM_PDF_SHORT_TO_FIXED(fontHeightScale);
    textMatrix.h = textXPosition;
    textMatrix.v = textYPosition;

    // Create new text run.
    IG_PDE_text_create(&hText);

    // Add the textToAdd into the element using the settings from above.
    IG_PDE_text_add(hText, IG_PDE_TEXT_RUN, 0, (LPBYTE)textToAdd, textLength, hFont,
            &graphicState, NULL, &textMatrix, NULL);
    // Add the text element into the content.
    IG_PDE_content_add_element(hContent, IG_PDE_AFTER_LAST, hText);

    // Set the page's PDE content back into the page object.
    IG_PDF_page_set_content(hPDFPage);

    // Release the objects created.
    IG_PDE_element_release(hText);
    IG_PDE_colorspace_release(hColorSpace);
    IG_PDF_page_release_content( hPDFPage );
}
C++
Copy Code
#include <string>
#include <windows.h>

#include "gear.h"
#include "i_PDF.h"

using namespace std;

// This function returns a new font to use for the text element.
HIG_PDE_FONT CreateNewFont( )
{
    AT_PDE_FONTATTRS fontAttrs;
    ZeroMemory(&fontAttrs, sizeof(fontAttrs));

    HIG_PDE_FONT hFont = NULL;

    // Set font name attribute.
    IG_PDF_atom_from_string("Times-Roman", &(fontAttrs.name));
    // Set font type attribute.
    IG_PDF_atom_from_string("Type1", &(fontAttrs.type));

    // Create from sysfont.
    HIG_PDF_SYSFONT hSysFont = NULL;
    IG_PDF_sysfont_find(&fontAttrs, 0, &hSysFont);
    IG_PDE_font_create_from_sysfont(hSysFont, 0, IG_PDF_ATOM_NULL, NULL, &hFont);
    IG_PDF_sysfont_release(hSysFont);

    return hFont;
}

// This function will add a text element into the content of the PDF document.
void AddTextToFirstPDFPage( HMIGEAR document)
{
    // Get first page.
    HIGEAR page = NULL;
    IG_mpi_page_get(document, 0, &page);

    // Obtain PDF page.
    HIG_PDF_PAGE hPDFPage = NULL;
    IG_vector_data_get(page, (LPVOID*)&hPDFPage);

    // Get page content.
    HIG_PDE_CONTENT hContent = NULL;
    IG_PDF_page_get_content(hPDFPage, &hContent);

    // Create a font to use with the text element.
    HIG_PDE_FONT hFont = CreateNewFont();

    // Set the color space to DeviceGray.
    HIG_PDF_ATOM hCSName = IG_PDF_ATOM_NULL;
    IG_PDF_atom_from_string("DeviceRGB", &hCSName);
    HIG_PDE_COLORSPACE hColorSpace = NULL;
    IG_PDE_colorspace_create(hCSName, NULL, &hColorSpace);

    // Set the attributes for the graphic state.
    AT_PDE_GRAPHICSTATE graphicState;
    ZeroMemory(&graphicState, sizeof(graphicState));
    graphicState.strokeColorSpec.space = graphicState.fillColorSpec.space = hColorSpace;
    graphicState.miterLimit = IG_PDF_FIXED_TEN;
    graphicState.flatness = IG_PDF_FIXED_ONE;
    graphicState.lineWidth = IG_PDF_FIXED_ONE;

    // Create a blue text (for example).
    // Note: Color values are expressed as real numbers.
        // Set R componet.
    graphicState.fillColorSpec.value.color[0] = 0;
    // Set G componet.
    graphicState.fillColorSpec.value.color[1] = 0;
    // Set B componet.
    graphicState.fillColorSpec.value.color[2] = AM_PDF_DOUBLE_TO_FIXED(255./255);

    // Create a string of text.
    string textToAdd = "This is the string of text that will be added";

    // Set the length of the text.
    int textLength = textToAdd.length();

    // Get page box.
    AT_PDF_FIXEDRECT cropBox;
    IG_PDF_page_get_crop_box(hPDFPage, &cropBox);

    // Calculate the center of the page.
    LONG horizontalCenter = (cropBox.right - cropBox.left)/2;
    LONG verticalCenter = (cropBox.top - cropBox.bottom)/2;

    // Get the width of the text in EM space.
    // Note: One EM in a 16-point typeface is 16 points.
    LONG textWidthEM;
    IG_PDE_font_sum_widths(hFont, (LPBYTE)textToAdd.c_str(), textLength, &textWidthEM);
        
    SHORT fontWidthScale = 20;
    SHORT fontHeightScale = 20;

    // Get the width of the text considering font size.
    // Note: Convert from thousandths of a point to points and adjusts by the width scale factor.
    LONG scaledTextWidth = (textWidthEM/1000) * fontWidthScale;

    // Set coordinates to center the text.
    LONG textXPosition = horizontalCenter - AM_PDF_LONG_TO_FIXED(scaledTextWidth/ 2);
    LONG textYPosition = verticalCenter;

    // Create a matrix to draw text with font size 20pt at the center of the page.
    // Note: The text matrix is a 3x3 affine transform matrix, depicted in its
    // abbreviated form: [ a b c d h v ]
    // * Set matrix values a and d to the font size in pt.
    // * Set matrix values h and v to move glyphs from user space origin to a place on the page.
    AT_PDF_FIXEDMATRIX textMatrix;
    memset(&textMatrix, 0, sizeof(textMatrix));
    textMatrix.a = AM_PDF_SHORT_TO_FIXED(fontWidthScale);
    textMatrix.d = AM_PDF_SHORT_TO_FIXED(fontHeightScale);
    textMatrix.h = textXPosition;
    textMatrix.v = textYPosition;

    // Create a new text element.
    HIG_PDE_TEXT hText = NULL;

    // Create new text run.
    IG_PDE_text_create(&hText);

    // Add the textToAdd into the element using the settings from above.
    IG_PDE_text_add(hText, IG_PDE_TEXT_RUN, 0, (LPBYTE)textToAdd.c_str(), textLength, hFont,
            &graphicState, NULL, &textMatrix, NULL);
    // Add the text element into the content.
    IG_PDE_content_add_element( hContent, IG_PDE_AFTER_LAST, hText );

    // Set the page's PDE content back into the page object.
    IG_PDF_page_set_content(hPDFPage);

    // Release the objects created.
    IG_PDE_element_release(hText);
    IG_PDE_colorspace_release(hColorSpace);
    IG_PDF_page_release_content( hPDFPage );
}