PDFium Documentation

repository·main·Indexed 19 days ago

https://github.com/chromium/pdfium

A high-performance PDF rendering engine used to embed PDF parsing, reading, and rasterization capabilities into applications. The documentation covers installation via Chromium build tooling, GN configuration arguments, Ninja build processes, and the use of the pdfium_test standalone program. It also details the internal architecture of the PWL and CFWL widget libraries, XFA form layout hierarchies (CXFA), and instructions for running pixel tests and generating Clang code coverage reports.

Tokens
7.5K
Snippets
17
Records
45
Agent score
68%

What's inside PDFium

  1. Understand the CFWL Widget Library architecture

    main

    The xfa/fwl library is a Widget Library for XFA Forms. It uses a class hierarchy where CFWL_Widget serves as the base class. Derived widget classes act as both controllers and renderers for their respective widgets.

    Key components of the architecture include:

    • Widgets: Derived from CFWL_Widget. Common widgets include CFWL_Form, CFWL_Edit, CFWL_PushButton, and CFWL_ListBox.
    • Messages: User input handled by widgets. Messages are identified by Message::Type and derived from CFWL_Message (e.g., CFWL_MessageMouse, CFWL_MessageSetFocus).
    • Events: Actions originated in widgets and handled by other CFWL_Widget or CXFA classes (e.g., CFWL_EventMouse, CFWL_EventSelectChanged).
    • Rendering: Widgets use IFWL_ThemeProvider for drawing, utilizing DrawBackground() and DrawText() with CFWL_ThemeBackground and CFWL_ThemeText options.

    Note that CFWL widgets are instantiated by and closely related to the CXFA classes found in the xfa/fxfa directory.

  2. CFWL Widget Hierarchy

    main

    The xfa/fwl library organizes widgets in a specific inheritance hierarchy. CFWL_Widget is the root base class.

    Hierarchy Tree:

    • CFWL_Widget
      • CFWL_Form
      • CFWL_Caret
      • CFWL_CheckBox
      • CFWL_ComboBox
      • CFWL_DateTimePicker
      • CFWL_Edit
        • CFWL_Barcode
        • CFWL_ComboEdit
        • CFWL_DateTimeEdit
      • CFWL_ListBox
        • CFWL_ComboList
      • CFWL_MonthCalendar
      • CFWL_PictureBox
      • CFWL_PushButton
      • CFWL_ScrollBar
      • CFWL_SpinButton
  3. Understand the PWL Widget Hierarchy

    main

    The fpdfsdk/pwl (Widget Library) provides controllers for AcroForms widgets. All widget classes extend the base class CPWL_Wnd. The library uses a controller-based model where derived classes manage specific widget types.

    Widget Hierarchy:

    • CPWL_Wnd (Base Class)
      • CPWL_Button
        • CPWL_CheckBox
        • CPWL_PushButton
        • CPWL_RadioButton
      • CPWL_Caret
      • CPWL_EditCtrl
        • CPWL_Edit
      • CPWL_ListBox
        • CPWL_CBListBox (Combo Box)
      • CPWL_ScrollBar
  4. Understand the FXFA layout item hierarchy

    main

    The xfa/fxfa directory provides a set of CXFA_LayoutItems used to model forms containing widgets. The hierarchy is organized into container items and content items:

    Container Hierarchy

    • CXFA_LayoutItem
      • CXFA_ContainerLayoutItem
        • CXFA_FFPageView

    Content Hierarchy

    • CXFA_LayoutItem
      • CXFA_ContentLayoutItem
        • CXFA_FFWidget
          • Basic shapes/elements: CXFA_FFArc, CXFA_FFImage, CXFA_FFLine, CXFA_FFRectangle, CXFA_FFText, CXFA_FFExclGroup
          • Form Fields: CXFA_FFField (and its specialized subclasses)

    Fields (CXFA_FFField) are the base class for all interactive widgets.

  5. How to use build overrides in GN

    main

    The build_overrides/ directory allows different products to customize settings for shared or DEPS'ed repositories. By creating a .gni file within this directory (e.g., build_overrides/v8.gni), a project can define variables that change the build behavior of a dependency without modifying the dependency's own source code.

    To implement an override:

    1. Define a set of variables in a .gni file inside build_overrides/.
    2. The dependency's top-level BUILD.gn file must import this file (e.g., import("//build_overrides/v8.gni")) to make the variables available.
    3. Different products can then provide their own build_overrides/*.gni files with different values for the same variables to suit their specific build configurations (e.g., enabling or disabling a standalone executable like d8 in V8).
  6. Embed PDFium in your own projects

    main

    To embed PDFium, use the header files located in the public/ directory. These represent the stable API surface intended for consumers.

    Warning: Do not call routines located outside of the public/ directory, as those are internal and subject to change without notice.

  7. Map CXFA_FFField widgets to CFWL instances

    main

    Every CXFA_FFField widget owns a lower-level CFWL widget instance from xfa/fwl. When working with form widgets, use this mapping to understand the underlying implementation:

    CXFA_FFField SubclassCorresponding CFWL Widget
    CXFA_FFCheckButtonCFWL_CheckBox
    CXFA_FFComboBoxCFWL_ComboBox
    CXFA_FFImageEditCFWL_PictureBox
    CXFA_FFListBoxCFWL_ListBox
    CXFA_FFPushButtonCFWL_PushButton
    CXFA_FFSignaturenone
    CXFA_FFTextEditCFWL_Edit
    CXFA_FFBarcodeCFWL_Barcode
    CXFA_FFDateTimeEditCFWL_DateTimePicker
    CXFA_FFNumericEditCFWL_Edit
    CXFA_FFPasswordEditCFWL_Edit
  8. How XFA widget rendering and themes work together

    main

    XFA widget rendering is managed through a hierarchy of Theme Parts (TP) and a central Theme Provider.

    1. Theme Parts (TP): These classes handle the actual drawing logic. CFWL_WidgetTP serves as the base class containing common code for multiple widgets. Specific widget classes (e.g., CFWL_CheckboxTP, CFWL_EditTP) derive from CFWL_WidgetTP to implement drawing logic unique to that widget type.

    2. Theme Provider: The CXFA_FWLTheme class implements the IFWL_ThemeProvider interface. It acts as the central orchestrator. When a CFWL widget needs to be drawn, it calls DrawBackground() on the CXFA_FWLTheme instance. The theme provider then routes that call to the specific Theme Part (TP) corresponding to that widget type.

    Inheritance Hierarchy for Theme Parts:

    • CFWL_WidgetTP (Base)
      • CFWL_BarcodeTP
      • CFWL_CaretTP
      • CFWL_CheckboxTP
      • CFWL_ComboBowTP
      • CFWL_DateTimePickerTP
      • CFWL_EditTP
      • CFWL_ListBoxTP
      • CFWL_MonthCalendarTP
      • CFWL_PictureBoxTP
      • CFWL_PushButtonTP
      • CFWL_ScrollBarTP
  9. Initialize and destroy the PDFium library

    main

    To use PDFium, you must first initialize the library using FPDF_InitLibraryWithConfig() and provide an FPDF_LIBRARY_CONFIG structure. When your application is finished using the library, you must call FPDF_DestroyLibrary() to clean up resources.

    Configuration Details:

    • config.version: Must be set to 2 for current usage.
    • config.m_pUserFontPaths: A NULL terminated list of const char* paths to override the font paths searched by PDFium.
    • config.m_pIsolate: Used to configure the V8 JavaScript engine. Provide an existing isolate or NULL to let PDFium allocate a new one.
    • config.m_v8EmbedderSlot: The embedder data slot to use in the v8::Isolate. Typically set to 0.

    Note: If you are using the examples in this guide, you must compile PDFium without V8 and XFA support (e.g., set pdf_enable_v8 = false in GN args).

    #include <fpdfview.h>
    
    int main() {
      FPDF_LIBRARY_CONFIG config;
      config.version = 2;
      config.m_pUserFontPaths = NULL;
      config.m_pIsolate = NULL;
      config.m_v8EmbedderSlot = 0;
    
      FPDF_InitLibraryWithConfig(&config);
    
      FPDF_DestroyLibrary();
      return 0;
    }
  10. Work with PDF template (.in) files

    main

    .in files are PDF templates that use keywords to replace byte offsets, making them easier to maintain and reduce to essential test cases.

    To convert a .in template into a valid .pdf file, use the fixup_pdf_template.py tool.

    ./testing/tools/fixup_pdf_template.py your_file.in
  11. Enable Clang coverage in build configuration

    main

    To generate code coverage, you must first configure your build directory with coverage enabled. This requires setting the use_clang_coverage flag to true in your args.gn file.

    Note: If you are upgrading from a previous version, replace use_coverage = true with use_clang_coverage = true.

    # If creating a new build directory
    gn args out/Coverage
    # (Set use_clang_coverage = true in the editor that opens)
    
    # OR append to an existing build directory
    echo "use_clang_coverage = true" >> out/Coverage/args.gn