Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ _Common/ — shared headers (extract_text.hpp)
Annotations/ — 5 samples
ContentCreation/ — 16 samples
ContentModification/ — 14 samples
DocumentConversion/ — 7 samples
DocumentConversion/ — 10 samples
DocumentOptimization/— 1 sample
Forms/ — 4 samples
Images/ — 14 samples
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<RootNamespace>CreateInvoiceFromStructuredData</RootNamespace>
<ProjectName>CreateInvoiceFromStructuredData</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="create_invoice_from_structured_data.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
32 changes: 32 additions & 0 deletions DocumentConversion/CreateInvoiceFromStructuredData/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
UNAME := $(shell uname)

CXX ?= $(if $(filter Darwin,$(UNAME)),clang++,g++)

TARGET = create_invoice_from_structured_data
SRC = create_invoice_from_structured_data.cpp

SDK_ROOT ?= ../../..

CXXFLAGS = -std=c++17 -I$(SDK_ROOT)/include
LDFLAGS = -L$(SDK_ROOT)/lib -ldatalogics_interface_api

SDK_LIB := $(abspath $(SDK_ROOT)/lib)

ifeq ($(UNAME),Darwin)
LDFLAGS += -Wl,-rpath,$(SDK_LIB)
else
LDFLAGS += -Wl,-rpath,$(SDK_LIB)
endif

all: $(TARGET)

$(TARGET): $(SRC)
$(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS)

clean:
rm -f $(TARGET)

run: $(TARGET)
./$(TARGET)

.PHONY: all clean run
63 changes: 63 additions & 0 deletions DocumentConversion/CreateInvoiceFromStructuredData/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# CreateInvoiceFromStructuredData

Builds a tagged PDF invoice from structured input files with the Datalogics
C++ APDFL API: JSON metadata (seller, customer, dates, tax rate), a CSV of
line items, a JSON style sheet (fonts, colors, page dimensions), and a local
PNG logo. Everything is drawn directly with APDFL — text positioned with real
font metrics, boxes and rules as vector paths, and the logo placed with
`Image` — while the logical structure tree is built alongside the content so
the invoice is accessible.

The generated invoice includes:

- A header with the scaled logo (tagged `Figure` with alt text), the invoice
number, and issue/due dates
- "From" and "Bill To" cards for the seller and customer
- A line-item table (`Table` → `TR` → `TH`/`TD`) whose header row repeats on
every continuation page, with right-aligned quantities and currency values
- A totals box with subtotal, tax, and grand total
- Payment terms and notes sections, and a decorative footer emitted as
artifact content outside the structure tree

When `applyRestrictionPassword` is enabled in the metadata (the default), the
document is secured with `Document::secure` using 256-bit AES: it opens,
prints, and remains accessible without a password, but editing requires the
owner password from the metadata file.

## Building and running

Run from this directory so the default `data/` paths resolve:

```sh
make # or open CreateInvoiceFromStructuredData.vcxproj in Visual Studio
./create_invoice_from_structured_data # uses the bundled data files
./create_invoice_from_structured_data --help # all options
./create_invoice_from_structured_data --self-test # validate inputs, no PDF written
```

Options: `--metadata <path>`, `--line-items <path>`, `--style <path>`,
`--output <path>`. The logo path in the metadata file is resolved relative to
the metadata file's directory.

Set `APDFL_LICENSE_KEY` to provide a Datalogics APDFL activation key before
the library initializes.

## Input files

- `data/metadata.json` — invoice number, dates, currency, tax rate, seller
and customer contact blocks, logo path, and the optional restriction
password. All data is fictional.
- `data/line-items.csv` — `itemCode,description,quantity,unitPrice` rows;
quoted fields may contain commas.
- `data/style.json` — fonts, font sizes, page size, margin, logo bounds, and
`#RRGGBB` colors.
- `images/northstar-logo.png` — the sample logo.

## Differences from the .NET sample

This is a rewrite of the `apdfl-csharp-dotnet-samples` sample of the same
name using the Modern C++ interface. The Modern C++ API assigns marked-content
IDs and maintains the structure parent tree automatically
(`StructElement::add_marked_content_ref`), so the tagging code is
substantially simpler than the .NET version. JSON and CSV parsing is done
with a small parser inside the sample, so APDFL remains the only dependency.
Loading